summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS8
-rw-r--r--CONTRIBUTORS11
-rw-r--r--api/next.txt597
-rw-r--r--doc/contribute.html7
-rw-r--r--doc/effective_go.html748
-rw-r--r--doc/go1.1.html722
-rw-r--r--doc/go_faq.html85
-rw-r--r--doc/go_spec.html444
-rw-r--r--doc/progs/eff_unused1.go18
-rw-r--r--doc/progs/eff_unused2.go22
-rwxr-xr-xdoc/progs/run1
-rw-r--r--doc/progs/unused1.go12
-rw-r--r--doc/progs/unused2.go16
-rw-r--r--include/libc.h6
-rw-r--r--lib/codereview/codereview.py4
-rw-r--r--lib/godoc/package.html30
-rw-r--r--lib/godoc/package.txt15
-rw-r--r--lib/time/README2
-rw-r--r--[-rwxr-xr-x]misc/bbedit/Go.plist0
-rw-r--r--misc/cgo/test/cthread.go1
-rw-r--r--misc/cgo/test/issue4029.go9
-rw-r--r--misc/dashboard/README4
-rw-r--r--misc/dashboard/app/build/init.go3
-rw-r--r--misc/dashboard/codereview/dashboard/cl.go18
-rw-r--r--misc/dashboard/codereview/dashboard/people.go19
-rw-r--r--misc/dist/bindist.go13
-rw-r--r--misc/emacs/go-mode.el421
-rw-r--r--[-rwxr-xr-x]misc/notepadplus/README0
-rw-r--r--[-rwxr-xr-x]misc/notepadplus/go.xml0
-rw-r--r--[-rwxr-xr-x]misc/notepadplus/userDefineLang.xml0
-rwxr-xr-xmisc/pprof35
-rw-r--r--misc/swig/stdio/Makefile17
-rw-r--r--src/cmd/5g/gsubr.c20
-rw-r--r--src/cmd/5l/asm.c57
-rw-r--r--src/cmd/5l/l.h8
-rw-r--r--src/cmd/5l/obj.c11
-rw-r--r--src/cmd/6a/lex.c3
-rw-r--r--src/cmd/6c/swt.c2
-rw-r--r--src/cmd/6g/gsubr.c16
-rw-r--r--src/cmd/6l/6.out.h3
-rw-r--r--src/cmd/6l/asm.c165
-rw-r--r--src/cmd/6l/l.h16
-rw-r--r--src/cmd/6l/obj.c28
-rw-r--r--src/cmd/6l/optab.c20
-rw-r--r--src/cmd/6l/span.c10
-rw-r--r--src/cmd/8a/a.y15
-rw-r--r--src/cmd/8a/lex.c6
-rw-r--r--src/cmd/8a/y.tab.c1572
-rw-r--r--src/cmd/8a/y.tab.h98
-rw-r--r--src/cmd/8c/swt.c2
-rw-r--r--src/cmd/8g/cgen.c2
-rw-r--r--src/cmd/8g/gsubr.c16
-rw-r--r--src/cmd/8l/8.out.h10
-rw-r--r--src/cmd/8l/asm.c185
-rw-r--r--src/cmd/8l/l.h13
-rw-r--r--src/cmd/8l/obj.c29
-rw-r--r--src/cmd/8l/optab.c31
-rw-r--r--src/cmd/8l/span.c19
-rw-r--r--src/cmd/addr2line/main.c19
-rw-r--r--src/cmd/api/goapi.go5
-rw-r--r--src/cmd/cc/dpchk.c22
-rw-r--r--src/cmd/cgo/doc.go16
-rw-r--r--src/cmd/cgo/gcc.go6
-rw-r--r--src/cmd/cgo/main.go4
-rw-r--r--src/cmd/cgo/out.go11
-rw-r--r--src/cmd/dist/build.c53
-rw-r--r--src/cmd/dist/windows.c2
-rw-r--r--src/cmd/fix/netipv6zone.go11
-rw-r--r--src/cmd/fix/netipv6zone_test.go28
-rw-r--r--src/cmd/gc/builtin.c6
-rw-r--r--src/cmd/gc/closure.c179
-rw-r--r--src/cmd/gc/const.c35
-rw-r--r--src/cmd/gc/cplx.c8
-rw-r--r--src/cmd/gc/dcl.c48
-rw-r--r--src/cmd/gc/esc.c13
-rw-r--r--src/cmd/gc/fmt.c6
-rw-r--r--src/cmd/gc/gen.c5
-rw-r--r--src/cmd/gc/go.h11
-rw-r--r--src/cmd/gc/go.y5
-rw-r--r--src/cmd/gc/inl.c31
-rw-r--r--src/cmd/gc/lex.c1
-rw-r--r--src/cmd/gc/obj.c14
-rw-r--r--src/cmd/gc/racewalk.c66
-rw-r--r--src/cmd/gc/range.c4
-rw-r--r--src/cmd/gc/reflect.c31
-rw-r--r--src/cmd/gc/subr.c15
-rw-r--r--src/cmd/gc/swt.c4
-rw-r--r--src/cmd/gc/typecheck.c201
-rw-r--r--src/cmd/gc/walk.c136
-rw-r--r--src/cmd/gc/y.tab.c505
-rw-r--r--src/cmd/go/build.go44
-rw-r--r--src/cmd/go/discovery.go1
-rw-r--r--src/cmd/go/doc.go43
-rw-r--r--src/cmd/go/go11.go10
-rw-r--r--src/cmd/go/main.go11
-rw-r--r--src/cmd/go/pkg.go7
-rwxr-xr-xsrc/cmd/go/test.bash39
-rw-r--r--src/cmd/go/test.go9
-rw-r--r--src/cmd/go/testdata/errmsg/x.go3
-rw-r--r--src/cmd/go/testdata/errmsg/x1_test.go3
-rw-r--r--src/cmd/go/testdata/errmsg/x_test.go3
-rw-r--r--src/cmd/go/vet.go2
-rw-r--r--src/cmd/godoc/doc.go3
-rw-r--r--src/cmd/godoc/godoc.go33
-rw-r--r--src/cmd/ld/data.c334
-rw-r--r--src/cmd/ld/dwarf.c294
-rw-r--r--src/cmd/ld/dwarf_defs.h1
-rw-r--r--src/cmd/ld/elf.c54
-rw-r--r--src/cmd/ld/elf.h2
-rw-r--r--src/cmd/ld/go.c107
-rw-r--r--src/cmd/ld/ldelf.c4
-rw-r--r--src/cmd/ld/ldmacho.c4
-rw-r--r--src/cmd/ld/ldpe.c10
-rw-r--r--src/cmd/ld/lib.c334
-rw-r--r--src/cmd/ld/lib.h47
-rw-r--r--src/cmd/ld/macho.c592
-rw-r--r--src/cmd/ld/macho.h13
-rw-r--r--src/cmd/ld/pe.c14
-rw-r--r--src/cmd/ld/symtab.c20
-rw-r--r--src/cmd/vet/Makefile8
-rw-r--r--src/cmd/vet/asmdecl.go532
-rw-r--r--src/cmd/vet/assign.go44
-rw-r--r--src/cmd/vet/buildtag.go2
-rw-r--r--src/cmd/vet/deadcode.go280
-rw-r--r--src/cmd/vet/doc.go6
-rw-r--r--src/cmd/vet/main.go118
-rw-r--r--src/cmd/vet/method.go2
-rw-r--r--src/cmd/vet/print.go117
-rw-r--r--src/cmd/vet/structtag.go4
-rw-r--r--src/cmd/vet/taglit.go54
-rw-r--r--src/cmd/vet/test_asm.go24
-rw-r--r--src/cmd/vet/test_asm1.s249
-rw-r--r--src/cmd/vet/test_asm2.s253
-rw-r--r--src/cmd/vet/test_asm3.s168
-rw-r--r--src/cmd/vet/test_assign.go20
-rw-r--r--src/cmd/vet/test_deadcode.go2121
-rw-r--r--src/cmd/vet/test_taglit.go34
-rw-r--r--src/cmd/vet/types.go179
-rw-r--r--src/cmd/vet/typestub.go45
-rw-r--r--src/cmd/yacc/yacc.go1
-rw-r--r--src/lib9/run_plan9.c38
-rw-r--r--src/lib9/run_unix.c43
-rw-r--r--src/lib9/run_windows.c83
-rw-r--r--src/lib9/tempdir_plan9.c54
-rw-r--r--src/lib9/tempdir_unix.c52
-rw-r--r--src/lib9/tempdir_windows.c110
-rw-r--r--src/lib9/win.h8
-rw-r--r--src/libmach/executable.c142
-rw-r--r--src/pkg/bufio/bufio.go1
-rw-r--r--src/pkg/bufio/bufio_test.go47
-rw-r--r--src/pkg/bufio/example_test.go4
-rw-r--r--src/pkg/bufio/scan.go3
-rw-r--r--src/pkg/bytes/asm_386.s12
-rw-r--r--src/pkg/bytes/asm_amd64.s16
-rw-r--r--src/pkg/bytes/asm_arm.s14
-rw-r--r--src/pkg/bytes/bytes.go4
-rw-r--r--src/pkg/compress/bzip2/huffman.go2
-rw-r--r--src/pkg/compress/flate/deflate_test.go1
-rw-r--r--src/pkg/compress/flate/inflate.go3
-rw-r--r--src/pkg/compress/flate/token.go1
-rw-r--r--src/pkg/compress/gzip/gunzip.go1
-rw-r--r--src/pkg/compress/lzw/reader.go2
-rw-r--r--src/pkg/crypto/cipher/example_test.go4
-rw-r--r--src/pkg/crypto/dsa/dsa.go2
-rw-r--r--src/pkg/crypto/dsa/dsa_test.go5
-rw-r--r--src/pkg/crypto/md5/gen.go19
-rw-r--r--src/pkg/crypto/md5/md5block.go5
-rw-r--r--src/pkg/crypto/md5/md5block_386.s180
-rw-r--r--src/pkg/crypto/md5/md5block_amd64.s177
-rw-r--r--src/pkg/crypto/md5/md5block_decl.go9
-rw-r--r--src/pkg/crypto/rand/util.go4
-rw-r--r--src/pkg/crypto/rc4/rc4.go6
-rw-r--r--src/pkg/crypto/rc4/rc4_386.s51
-rw-r--r--src/pkg/crypto/rc4/rc4_amd64.s202
-rw-r--r--src/pkg/crypto/rc4/rc4_arm.s10
-rw-r--r--src/pkg/crypto/rc4/rc4_asm.go4
-rw-r--r--src/pkg/crypto/rc4/rc4_ref.go2
-rw-r--r--src/pkg/crypto/rc4/rc4_test.go69
-rw-r--r--src/pkg/crypto/sha1/sha1block.go2
-rw-r--r--src/pkg/crypto/sha1/sha1block_386.s233
-rw-r--r--src/pkg/crypto/sha1/sha1block_amd64.s216
-rw-r--r--src/pkg/crypto/sha1/sha1block_decl.go9
-rw-r--r--src/pkg/crypto/tls/common.go19
-rw-r--r--src/pkg/crypto/tls/handshake_server.go17
-rw-r--r--src/pkg/crypto/x509/pkcs8.go2
-rw-r--r--src/pkg/crypto/x509/x509.go1
-rw-r--r--src/pkg/database/sql/convert.go42
-rw-r--r--src/pkg/database/sql/convert_test.go30
-rw-r--r--src/pkg/database/sql/sql.go414
-rw-r--r--src/pkg/database/sql/sql_test.go92
-rw-r--r--src/pkg/debug/dwarf/buf.go48
-rw-r--r--src/pkg/debug/dwarf/entry.go26
-rw-r--r--src/pkg/debug/dwarf/type.go4
-rw-r--r--src/pkg/debug/dwarf/unit.go51
-rw-r--r--src/pkg/debug/elf/file.go18
-rw-r--r--src/pkg/debug/macho/file.go2
-rw-r--r--src/pkg/encoding/ascii85/ascii85.go1
-rw-r--r--src/pkg/encoding/asn1/marshal.go1
-rw-r--r--src/pkg/encoding/base32/base32.go87
-rw-r--r--src/pkg/encoding/base32/base32_test.go106
-rw-r--r--src/pkg/encoding/base64/base64.go63
-rw-r--r--src/pkg/encoding/base64/base64_test.go71
-rw-r--r--src/pkg/encoding/binary/varint.go1
-rw-r--r--src/pkg/encoding/csv/reader.go3
-rw-r--r--src/pkg/encoding/gob/codec_test.go6
-rw-r--r--src/pkg/encoding/gob/decode.go1
-rw-r--r--src/pkg/encoding/gob/timing_test.go9
-rw-r--r--src/pkg/encoding/gob/type.go1
-rw-r--r--src/pkg/encoding/json/decode.go13
-rw-r--r--src/pkg/encoding/json/decode_test.go13
-rw-r--r--src/pkg/encoding/xml/marshal.go75
-rw-r--r--src/pkg/encoding/xml/marshal_test.go38
-rw-r--r--src/pkg/encoding/xml/read.go6
-rw-r--r--src/pkg/encoding/xml/read_test.go222
-rw-r--r--src/pkg/encoding/xml/typeinfo.go41
-rw-r--r--src/pkg/encoding/xml/xml.go28
-rw-r--r--src/pkg/encoding/xml/xml_test.go31
-rw-r--r--src/pkg/exp/norm/Makefile30
-rw-r--r--src/pkg/exp/norm/composition.go382
-rw-r--r--src/pkg/exp/norm/composition_test.go143
-rw-r--r--src/pkg/exp/norm/example_iter_test.go81
-rw-r--r--src/pkg/exp/norm/forminfo.go229
-rw-r--r--src/pkg/exp/norm/input.go105
-rw-r--r--src/pkg/exp/norm/iter.go401
-rw-r--r--src/pkg/exp/norm/iter_test.go188
-rw-r--r--src/pkg/exp/norm/maketables.go923
-rw-r--r--src/pkg/exp/norm/maketesttables.go45
-rw-r--r--src/pkg/exp/norm/norm_test.go14
-rw-r--r--src/pkg/exp/norm/normalize.go478
-rw-r--r--src/pkg/exp/norm/normalize_test.go750
-rw-r--r--src/pkg/exp/norm/normregtest.go304
-rw-r--r--src/pkg/exp/norm/readwriter.go126
-rw-r--r--src/pkg/exp/norm/readwriter_test.go68
-rw-r--r--src/pkg/exp/norm/tables.go6779
-rw-r--r--src/pkg/exp/norm/trie.go232
-rw-r--r--src/pkg/exp/norm/trie_test.go152
-rw-r--r--src/pkg/exp/norm/triedata_test.go85
-rw-r--r--src/pkg/exp/norm/triegen.go317
-rw-r--r--src/pkg/fmt/fmt_test.go4
-rw-r--r--src/pkg/go/build/build.go73
-rw-r--r--src/pkg/go/doc/doc.go20
-rw-r--r--src/pkg/go/doc/filter.go2
-rw-r--r--src/pkg/go/doc/reader.go87
-rw-r--r--src/pkg/go/doc/testdata/a.0.golden22
-rw-r--r--src/pkg/go/doc/testdata/a.1.golden22
-rw-r--r--src/pkg/go/doc/testdata/a.2.golden22
-rw-r--r--src/pkg/go/doc/testdata/a0.go23
-rw-r--r--src/pkg/go/doc/testdata/template.txt2
-rw-r--r--src/pkg/go/format/format.go9
-rw-r--r--src/pkg/go/parser/error_test.go2
-rw-r--r--src/pkg/go/parser/parser.go55
-rw-r--r--src/pkg/go/parser/short_test.go3
-rw-r--r--src/pkg/go/printer/nodes.go4
-rw-r--r--src/pkg/go/printer/testdata/declarations.golden25
-rw-r--r--src/pkg/go/printer/testdata/declarations.input25
-rw-r--r--src/pkg/go/types/api.go105
-rw-r--r--src/pkg/go/types/builtins.go455
-rw-r--r--src/pkg/go/types/check.go507
-rw-r--r--src/pkg/go/types/check_test.go259
-rw-r--r--src/pkg/go/types/const.go718
-rw-r--r--src/pkg/go/types/conversions.go129
-rw-r--r--src/pkg/go/types/errors.go335
-rw-r--r--src/pkg/go/types/exportdata.go111
-rw-r--r--src/pkg/go/types/expr.go1520
-rw-r--r--src/pkg/go/types/gcimporter.go950
-rw-r--r--src/pkg/go/types/gcimporter_test.go180
-rw-r--r--src/pkg/go/types/objects.go186
-rw-r--r--src/pkg/go/types/operand.go411
-rw-r--r--src/pkg/go/types/predicates.go303
-rw-r--r--src/pkg/go/types/resolve.go197
-rw-r--r--src/pkg/go/types/resolver_test.go167
-rw-r--r--src/pkg/go/types/scope.go78
-rw-r--r--src/pkg/go/types/sizes.go162
-rw-r--r--src/pkg/go/types/stmt.go743
-rw-r--r--src/pkg/go/types/testdata/builtins.src401
-rw-r--r--src/pkg/go/types/testdata/const0.src215
-rw-r--r--src/pkg/go/types/testdata/conversions.src18
-rw-r--r--src/pkg/go/types/testdata/decls0.src187
-rw-r--r--src/pkg/go/types/testdata/decls1.src132
-rw-r--r--src/pkg/go/types/testdata/decls2a.src67
-rw-r--r--src/pkg/go/types/testdata/decls2b.src28
-rw-r--r--src/pkg/go/types/testdata/decls3.src253
-rw-r--r--src/pkg/go/types/testdata/exports.go89
-rw-r--r--src/pkg/go/types/testdata/expr0.src161
-rw-r--r--src/pkg/go/types/testdata/expr1.src7
-rw-r--r--src/pkg/go/types/testdata/expr2.src23
-rw-r--r--src/pkg/go/types/testdata/expr3.src463
-rw-r--r--src/pkg/go/types/testdata/stmt0.src288
-rw-r--r--src/pkg/go/types/types.go236
-rw-r--r--src/pkg/go/types/types_test.go171
-rw-r--r--src/pkg/go/types/universe.go146
-rw-r--r--src/pkg/hash/crc32/crc32_amd64.s6
-rw-r--r--src/pkg/html/template/template.go22
-rw-r--r--src/pkg/html/template/transition.go3
-rw-r--r--src/pkg/image/gif/reader.go103
-rw-r--r--src/pkg/image/gif/reader_test.go135
-rw-r--r--src/pkg/image/jpeg/reader.go32
-rw-r--r--src/pkg/image/jpeg/reader_test.go63
-rw-r--r--src/pkg/image/jpeg/scan.go8
-rw-r--r--src/pkg/image/jpeg/writer_test.go39
-rw-r--r--src/pkg/io/ioutil/ioutil.go1
-rw-r--r--src/pkg/math/abs_386.s2
-rw-r--r--src/pkg/math/abs_amd64.s2
-rw-r--r--src/pkg/math/abs_arm.s8
-rw-r--r--src/pkg/math/asin_386.s4
-rw-r--r--src/pkg/math/atan2_386.s2
-rw-r--r--src/pkg/math/atan_386.s2
-rw-r--r--src/pkg/math/big/arith_386.s18
-rw-r--r--src/pkg/math/big/arith_amd64.s18
-rw-r--r--src/pkg/math/big/arith_arm.s16
-rw-r--r--src/pkg/math/big/int.go4
-rw-r--r--src/pkg/math/big/nat.go2
-rw-r--r--src/pkg/math/dim_amd64.s24
-rw-r--r--src/pkg/math/exp2_386.s16
-rw-r--r--src/pkg/math/exp_386.s14
-rw-r--r--src/pkg/math/exp_amd64.s6
-rw-r--r--src/pkg/math/expm1_386.s16
-rw-r--r--src/pkg/math/floor_386.s6
-rw-r--r--src/pkg/math/floor_amd64.s12
-rw-r--r--src/pkg/math/hypot_386.s24
-rw-r--r--src/pkg/math/hypot_amd64.s8
-rw-r--r--src/pkg/math/ldexp_386.s2
-rw-r--r--src/pkg/math/log10_386.s4
-rw-r--r--src/pkg/math/log1p_386.s4
-rw-r--r--src/pkg/math/log_386.s2
-rw-r--r--src/pkg/math/log_amd64.s8
-rw-r--r--src/pkg/math/mod_386.s2
-rw-r--r--src/pkg/math/rand/exp.go1
-rw-r--r--src/pkg/math/rand/normal.go1
-rw-r--r--src/pkg/math/remainder_386.s2
-rw-r--r--src/pkg/math/sin_386.s8
-rw-r--r--src/pkg/math/sqrt.go11
-rw-r--r--src/pkg/math/sqrt_386.s2
-rw-r--r--src/pkg/math/sqrt_amd64.s2
-rw-r--r--src/pkg/math/sqrt_arm.s2
-rw-r--r--src/pkg/math/tan_386.s4
-rw-r--r--src/pkg/mime/multipart/multipart.go3
-rw-r--r--src/pkg/net/conn_test.go13
-rw-r--r--src/pkg/net/dial.go118
-rw-r--r--src/pkg/net/dial_test.go8
-rw-r--r--src/pkg/net/empty.c8
-rw-r--r--src/pkg/net/fd_darwin.go126
-rw-r--r--src/pkg/net/fd_linux.go192
-rw-r--r--src/pkg/net/fd_poll_runtime.go119
-rw-r--r--src/pkg/net/fd_poll_unix.go360
-rw-r--r--src/pkg/net/fd_unix.go363
-rw-r--r--src/pkg/net/http/client.go12
-rw-r--r--src/pkg/net/http/client_test.go35
-rw-r--r--src/pkg/net/http/example_test.go5
-rw-r--r--src/pkg/net/http/export_test.go2
-rw-r--r--src/pkg/net/http/fcgi/child.go41
-rw-r--r--src/pkg/net/http/fs_test.go28
-rw-r--r--src/pkg/net/http/header.go47
-rw-r--r--src/pkg/net/http/header_test.go12
-rw-r--r--src/pkg/net/http/httputil/dump_test.go4
-rw-r--r--src/pkg/net/http/httputil/reverseproxy.go37
-rw-r--r--src/pkg/net/http/httputil/reverseproxy_test.go4
-rw-r--r--src/pkg/net/http/request.go2
-rw-r--r--src/pkg/net/http/request_test.go34
-rw-r--r--src/pkg/net/http/requestwrite_test.go60
-rw-r--r--src/pkg/net/http/response.go3
-rw-r--r--src/pkg/net/http/response_test.go2
-rw-r--r--src/pkg/net/http/serve_test.go75
-rw-r--r--src/pkg/net/http/server.go122
-rw-r--r--src/pkg/net/http/sniff_test.go11
-rw-r--r--src/pkg/net/http/status.go12
-rw-r--r--src/pkg/net/http/transport.go175
-rw-r--r--src/pkg/net/http/transport_test.go183
-rw-r--r--src/pkg/net/http/z_last_test.go55
-rw-r--r--src/pkg/net/interface_bsd.go1
-rw-r--r--src/pkg/net/interface_darwin.go3
-rw-r--r--src/pkg/net/interface_freebsd.go3
-rw-r--r--src/pkg/net/interface_linux.go6
-rw-r--r--src/pkg/net/interface_test.go34
-rw-r--r--src/pkg/net/ip.go95
-rw-r--r--src/pkg/net/ip_test.go129
-rw-r--r--src/pkg/net/ipraw_test.go39
-rw-r--r--src/pkg/net/iprawsock.go9
-rw-r--r--src/pkg/net/iprawsock_plan9.go2
-rw-r--r--src/pkg/net/iprawsock_posix.go2
-rw-r--r--src/pkg/net/ipsock.go61
-rw-r--r--src/pkg/net/lookup_plan9.go22
-rw-r--r--src/pkg/net/multicast_posix_test.go180
-rw-r--r--src/pkg/net/multicast_test.go184
-rw-r--r--src/pkg/net/newpollserver_unix.go46
-rw-r--r--src/pkg/net/packetconn_test.go30
-rw-r--r--src/pkg/net/protoconn_test.go10
-rw-r--r--src/pkg/net/rpc/jsonrpc/all_test.go17
-rw-r--r--src/pkg/net/rpc/jsonrpc/client.go2
-rw-r--r--src/pkg/net/rpc/server_test.go8
-rw-r--r--src/pkg/net/sendfile_freebsd.go2
-rw-r--r--src/pkg/net/sendfile_linux.go2
-rw-r--r--src/pkg/net/server_test.go19
-rw-r--r--src/pkg/net/sock_bsd.go6
-rw-r--r--src/pkg/net/sock_cloexec.go4
-rw-r--r--src/pkg/net/sock_linux.go6
-rw-r--r--src/pkg/net/sock_posix.go11
-rw-r--r--src/pkg/net/sock_windows.go1
-rw-r--r--src/pkg/net/sockopt_posix.go19
-rw-r--r--src/pkg/net/sockopt_windows.go19
-rw-r--r--src/pkg/net/tcp_test.go100
-rw-r--r--src/pkg/net/tcpsock.go14
-rw-r--r--src/pkg/net/textproto/reader.go1
-rw-r--r--src/pkg/net/timeout_test.go60
-rw-r--r--src/pkg/net/udp_test.go99
-rw-r--r--src/pkg/net/udpsock.go14
-rw-r--r--src/pkg/net/udpsock_plan9.go2
-rw-r--r--src/pkg/net/udpsock_posix.go2
-rw-r--r--src/pkg/net/unixsock.go9
-rw-r--r--src/pkg/net/unixsock_posix.go1
-rw-r--r--src/pkg/net/url/url.go102
-rw-r--r--src/pkg/net/url/url_test.go190
-rw-r--r--src/pkg/os/exec/exec.go2
-rw-r--r--src/pkg/os/exec/exec_test.go27
-rw-r--r--src/pkg/os/file_posix.go2
-rw-r--r--src/pkg/os/file_unix.go1
-rw-r--r--src/pkg/os/file_windows.go2
-rw-r--r--src/pkg/os/getwd.go2
-rw-r--r--src/pkg/os/signal/sig.s5
-rw-r--r--src/pkg/os/signal/signal.go93
-rw-r--r--src/pkg/os/signal/signal_stub.go8
-rw-r--r--src/pkg/os/signal/signal_test.go117
-rw-r--r--src/pkg/os/signal/signal_unix.go25
-rw-r--r--src/pkg/path/filepath/path_test.go5
-rw-r--r--src/pkg/path/path_test.go6
-rw-r--r--src/pkg/reflect/all_test.go306
-rw-r--r--src/pkg/reflect/asm_386.s14
-rw-r--r--src/pkg/reflect/asm_amd64.s14
-rw-r--r--src/pkg/reflect/asm_arm.s14
-rw-r--r--src/pkg/reflect/deepequal.go2
-rw-r--r--src/pkg/reflect/makefunc.go57
-rw-r--r--src/pkg/reflect/tostring_test.go1
-rw-r--r--src/pkg/reflect/type.go2
-rw-r--r--src/pkg/reflect/value.go232
-rw-r--r--src/pkg/regexp/regexp.go12
-rw-r--r--src/pkg/regexp/syntax/doc.go6
-rw-r--r--src/pkg/runtime/alg.c42
-rw-r--r--src/pkg/runtime/arch_386.h4
-rw-r--r--src/pkg/runtime/arch_amd64.h4
-rw-r--r--src/pkg/runtime/arch_arm.h4
-rw-r--r--src/pkg/runtime/asm_386.s275
-rw-r--r--src/pkg/runtime/asm_amd64.s182
-rw-r--r--src/pkg/runtime/asm_arm.s15
-rw-r--r--src/pkg/runtime/atomic_386.c13
-rw-r--r--src/pkg/runtime/atomic_arm.c13
-rw-r--r--src/pkg/runtime/cgo/callbacks.c6
-rw-r--r--src/pkg/runtime/cgo/gcc_freebsd_arm.c14
-rw-r--r--src/pkg/runtime/cgo/gcc_openbsd_386.c6
-rw-r--r--src/pkg/runtime/cgo/gcc_openbsd_amd64.c6
-rw-r--r--src/pkg/runtime/cgocall.c26
-rw-r--r--src/pkg/runtime/crash_test.go26
-rw-r--r--src/pkg/runtime/defs2_linux.go26
-rw-r--r--src/pkg/runtime/defs_darwin.go20
-rw-r--r--src/pkg/runtime/defs_darwin_386.h30
-rw-r--r--src/pkg/runtime/defs_darwin_amd64.h30
-rw-r--r--src/pkg/runtime/defs_linux.go21
-rw-r--r--src/pkg/runtime/defs_linux_386.h22
-rw-r--r--src/pkg/runtime/defs_linux_amd64.h24
-rw-r--r--src/pkg/runtime/defs_linux_arm.h26
-rw-r--r--src/pkg/runtime/defs_netbsd.go1
-rw-r--r--src/pkg/runtime/defs_netbsd_386.go1
-rw-r--r--src/pkg/runtime/defs_netbsd_amd64.go1
-rw-r--r--src/pkg/runtime/defs_netbsd_arm.go39
-rw-r--r--src/pkg/runtime/defs_netbsd_arm.h26
-rw-r--r--src/pkg/runtime/env_plan9.c2
-rw-r--r--src/pkg/runtime/export_futex_test.go13
-rw-r--r--src/pkg/runtime/extern.go52
-rw-r--r--src/pkg/runtime/futex_test.go31
-rw-r--r--src/pkg/runtime/gc_test.go15
-rw-r--r--src/pkg/runtime/hashmap.c1663
-rw-r--r--src/pkg/runtime/hashmap.h180
-rw-r--r--src/pkg/runtime/hashmap_fast.c149
-rw-r--r--src/pkg/runtime/malloc.goc6
-rw-r--r--src/pkg/runtime/map_test.go282
-rw-r--r--src/pkg/runtime/mapspeed_test.go150
-rw-r--r--src/pkg/runtime/mcentral.c1
-rw-r--r--src/pkg/runtime/mem_darwin.c9
-rw-r--r--src/pkg/runtime/mem_freebsd.c21
-rw-r--r--src/pkg/runtime/mem_linux.c2
-rw-r--r--src/pkg/runtime/mem_netbsd.c9
-rw-r--r--src/pkg/runtime/mem_openbsd.c9
-rw-r--r--src/pkg/runtime/memmove_amd64.s5
-rw-r--r--src/pkg/runtime/memmove_linux_amd64_test.go61
-rw-r--r--src/pkg/runtime/mfixalloc.c5
-rw-r--r--src/pkg/runtime/mgc0.c234
-rw-r--r--src/pkg/runtime/mgc0.h1
-rw-r--r--src/pkg/runtime/mheap.c3
-rw-r--r--src/pkg/runtime/netpoll.goc351
-rw-r--r--src/pkg/runtime/netpoll_epoll.c92
-rw-r--r--src/pkg/runtime/netpoll_kqueue.c105
-rw-r--r--src/pkg/runtime/netpoll_stub.c18
-rw-r--r--src/pkg/runtime/os_darwin.c (renamed from src/pkg/runtime/thread_darwin.c)62
-rw-r--r--src/pkg/runtime/os_darwin.h6
-rw-r--r--src/pkg/runtime/os_freebsd.c (renamed from src/pkg/runtime/thread_freebsd.c)84
-rw-r--r--src/pkg/runtime/os_freebsd.h10
-rw-r--r--src/pkg/runtime/os_freebsd_arm.c23
-rw-r--r--src/pkg/runtime/os_linux.c (renamed from src/pkg/runtime/thread_linux.c)103
-rw-r--r--src/pkg/runtime/os_linux.h6
-rw-r--r--src/pkg/runtime/os_linux_386.c37
-rw-r--r--src/pkg/runtime/os_linux_arm.c82
-rw-r--r--src/pkg/runtime/os_netbsd.c (renamed from src/pkg/runtime/thread_netbsd.c)77
-rw-r--r--src/pkg/runtime/os_netbsd.h7
-rw-r--r--src/pkg/runtime/os_netbsd_386.c17
-rw-r--r--src/pkg/runtime/os_netbsd_amd64.c18
-rw-r--r--src/pkg/runtime/os_netbsd_arm.c33
-rw-r--r--src/pkg/runtime/os_openbsd.c (renamed from src/pkg/runtime/thread_openbsd.c)81
-rw-r--r--src/pkg/runtime/os_openbsd.h6
-rw-r--r--src/pkg/runtime/os_plan9.c (renamed from src/pkg/runtime/thread_plan9.c)24
-rw-r--r--src/pkg/runtime/os_plan9.h4
-rw-r--r--src/pkg/runtime/os_plan9_386.c (renamed from src/pkg/runtime/signal_plan9_386.c)13
-rw-r--r--src/pkg/runtime/os_plan9_amd64.c (renamed from src/pkg/runtime/signal_plan9_amd64.c)13
-rw-r--r--src/pkg/runtime/os_windows.c (renamed from src/pkg/runtime/thread_windows.c)56
-rw-r--r--src/pkg/runtime/os_windows_386.c (renamed from src/pkg/runtime/signal_windows_386.c)13
-rw-r--r--src/pkg/runtime/os_windows_amd64.c (renamed from src/pkg/runtime/signal_windows_amd64.c)12
-rw-r--r--src/pkg/runtime/panic.c12
-rw-r--r--src/pkg/runtime/parfor.c6
-rw-r--r--src/pkg/runtime/proc.c110
-rw-r--r--src/pkg/runtime/race/testdata/map_test.go6
-rw-r--r--src/pkg/runtime/race/testdata/mop_test.go96
-rw-r--r--src/pkg/runtime/race/testdata/regression_test.go12
-rw-r--r--src/pkg/runtime/race/testdata/slice_test.go21
-rw-r--r--src/pkg/runtime/rt0_darwin_386.s10
-rw-r--r--src/pkg/runtime/rt0_darwin_amd64.s9
-rw-r--r--src/pkg/runtime/rt0_freebsd_386.s11
-rw-r--r--src/pkg/runtime/rt0_freebsd_amd64.s12
-rw-r--r--src/pkg/runtime/rt0_linux_386.s14
-rw-r--r--src/pkg/runtime/rt0_linux_amd64.s9
-rw-r--r--src/pkg/runtime/rt0_netbsd_386.s12
-rw-r--r--src/pkg/runtime/rt0_netbsd_amd64.s11
-rw-r--r--src/pkg/runtime/rt0_openbsd_386.s12
-rw-r--r--src/pkg/runtime/rt0_openbsd_amd64.s11
-rw-r--r--src/pkg/runtime/rt0_plan9_386.s7
-rw-r--r--src/pkg/runtime/rt0_plan9_amd64.s5
-rw-r--r--src/pkg/runtime/rt0_windows_386.s11
-rw-r--r--src/pkg/runtime/rt0_windows_amd64.s9
-rw-r--r--src/pkg/runtime/runtime.c28
-rw-r--r--src/pkg/runtime/runtime.h47
-rw-r--r--src/pkg/runtime/signal_386.c123
-rw-r--r--src/pkg/runtime/signal_amd64.c133
-rw-r--r--src/pkg/runtime/signal_arm.c124
-rw-r--r--src/pkg/runtime/signal_darwin_386.c155
-rw-r--r--src/pkg/runtime/signal_darwin_386.h23
-rw-r--r--src/pkg/runtime/signal_darwin_amd64.c165
-rw-r--r--src/pkg/runtime/signal_darwin_amd64.h31
-rw-r--r--src/pkg/runtime/signal_freebsd_386.c154
-rw-r--r--src/pkg/runtime/signal_freebsd_386.h23
-rw-r--r--src/pkg/runtime/signal_freebsd_amd64.c162
-rw-r--r--src/pkg/runtime/signal_freebsd_amd64.h31
-rw-r--r--src/pkg/runtime/signal_freebsd_arm.c193
-rw-r--r--src/pkg/runtime/signal_freebsd_arm.h28
-rw-r--r--src/pkg/runtime/signal_linux_386.c175
-rw-r--r--src/pkg/runtime/signal_linux_386.h24
-rw-r--r--src/pkg/runtime/signal_linux_amd64.c162
-rw-r--r--src/pkg/runtime/signal_linux_amd64.h32
-rw-r--r--src/pkg/runtime/signal_linux_arm.c241
-rw-r--r--src/pkg/runtime/signal_linux_arm.h28
-rw-r--r--src/pkg/runtime/signal_netbsd_386.c164
-rw-r--r--src/pkg/runtime/signal_netbsd_386.h23
-rw-r--r--src/pkg/runtime/signal_netbsd_amd64.c172
-rw-r--r--src/pkg/runtime/signal_netbsd_amd64.h31
-rw-r--r--src/pkg/runtime/signal_netbsd_arm.c208
-rw-r--r--src/pkg/runtime/signal_netbsd_arm.h30
-rw-r--r--src/pkg/runtime/signal_openbsd_386.c147
-rw-r--r--src/pkg/runtime/signal_openbsd_386.h23
-rw-r--r--src/pkg/runtime/signal_openbsd_amd64.c156
-rw-r--r--src/pkg/runtime/signal_openbsd_amd64.h31
-rw-r--r--src/pkg/runtime/signal_unix.c72
-rw-r--r--src/pkg/runtime/signal_unix.h14
-rw-r--r--src/pkg/runtime/signals_plan9.h4
-rw-r--r--src/pkg/runtime/sigqueue.goc18
-rw-r--r--src/pkg/runtime/stack_test.go13
-rw-r--r--src/pkg/runtime/string_test.go4
-rw-r--r--src/pkg/runtime/symtab.c2
-rw-r--r--src/pkg/runtime/sys_darwin_386.s59
-rw-r--r--src/pkg/runtime/sys_darwin_amd64.s75
-rw-r--r--src/pkg/runtime/sys_freebsd_386.s24
-rw-r--r--src/pkg/runtime/sys_freebsd_amd64.s28
-rw-r--r--src/pkg/runtime/sys_freebsd_arm.s23
-rw-r--r--src/pkg/runtime/sys_linux_386.s49
-rw-r--r--src/pkg/runtime/sys_linux_amd64.s47
-rw-r--r--src/pkg/runtime/sys_linux_arm.s53
-rw-r--r--src/pkg/runtime/sys_netbsd_386.s22
-rw-r--r--src/pkg/runtime/sys_netbsd_amd64.s32
-rw-r--r--src/pkg/runtime/sys_netbsd_arm.s23
-rw-r--r--src/pkg/runtime/sys_openbsd_386.s22
-rw-r--r--src/pkg/runtime/sys_openbsd_amd64.s32
-rw-r--r--src/pkg/runtime/sys_plan9_386.s27
-rw-r--r--src/pkg/runtime/sys_plan9_amd64.s28
-rw-r--r--src/pkg/runtime/sys_windows_386.s43
-rw-r--r--src/pkg/runtime/sys_windows_amd64.s32
-rw-r--r--src/pkg/runtime/time.goc19
-rw-r--r--src/pkg/runtime/time_plan9_386.c2
-rw-r--r--src/pkg/runtime/vdso_linux_amd64.c10
-rw-r--r--src/pkg/sort/search_test.go4
-rw-r--r--src/pkg/strconv/extfloat.go1
-rw-r--r--src/pkg/strconv/strconv_test.go4
-rw-r--r--src/pkg/strings/strings.go10
-rw-r--r--src/pkg/strings/strings_test.go18
-rw-r--r--src/pkg/sync/atomic/asm_386.s28
-rw-r--r--src/pkg/sync/atomic/atomic_test.go26
-rw-r--r--src/pkg/syscall/asm_plan9_386.s4
-rw-r--r--src/pkg/syscall/asm_plan9_amd64.s4
-rw-r--r--src/pkg/syscall/exec_bsd.go5
-rwxr-xr-xsrc/pkg/syscall/mkerrors.sh1
-rw-r--r--src/pkg/syscall/passfd_test.go4
-rw-r--r--src/pkg/syscall/syscall_bsd.go5
-rw-r--r--src/pkg/syscall/zerrors_freebsd_386.go204
-rw-r--r--src/pkg/syscall/zerrors_freebsd_amd64.go204
-rw-r--r--src/pkg/syscall/zerrors_freebsd_arm.go44
-rw-r--r--src/pkg/syscall/zsysnum_freebsd_386.go4
-rw-r--r--src/pkg/syscall/zsysnum_freebsd_amd64.go4
-rw-r--r--src/pkg/syscall/zsysnum_freebsd_arm.go11
-rw-r--r--src/pkg/testing/quick/quick.go2
-rw-r--r--src/pkg/text/template/exec.go18
-rw-r--r--src/pkg/text/template/exec_test.go37
-rw-r--r--src/pkg/text/template/parse/parse.go2
-rw-r--r--src/pkg/time/time_test.go4
-rw-r--r--src/pkg/unicode/letter.go2
-rw-r--r--src/pkg/unicode/maketables.go2
-rw-r--r--src/pkg/unicode/tables.go2
-rw-r--r--src/pkg/unicode/utf8/utf8_test.go6
-rwxr-xr-xsrc/run.bash11
-rw-r--r--src/run.bat2
-rw-r--r--test/bench/garbage/parser.go1
-rw-r--r--test/bench/go1/fmt_test.go68
-rw-r--r--test/bench/go1/http_test.go45
-rw-r--r--test/bench/go1/json_test.go4
-rw-r--r--test/bench/go1/jsondata_test.go3607
-rw-r--r--test/bench/go1/parser_test.go2
-rw-r--r--test/bench/go1/regexp_test.go59
-rw-r--r--test/bench/go1/time_test.go25
-rw-r--r--test/cmplx.go26
-rwxr-xr-xtest/errchk2
-rw-r--r--test/escape2.go29
-rw-r--r--test/fixedbugs/bug040.go2
-rw-r--r--test/fixedbugs/bug086.go4
-rw-r--r--test/fixedbugs/bug342.go6
-rw-r--r--test/fixedbugs/bug412.go4
-rw-r--r--test/fixedbugs/bug469.go13
-rw-r--r--test/fixedbugs/bug474.go29
-rw-r--r--test/fixedbugs/issue4663.go1
-rw-r--r--test/fixedbugs/issue4813.go52
-rw-r--r--test/fixedbugs/issue4964.dir/a.go27
-rw-r--r--test/fixedbugs/issue4964.dir/b.go34
-rw-r--r--test/fixedbugs/issue4964.go10
-rw-r--r--test/fixedbugs/issue5002.go16
-rw-r--r--test/fixedbugs/issue5056.go34
-rw-r--r--test/fixedbugs/issue5089.go15
-rw-r--r--test/func1.go2
-rw-r--r--test/funcdup.go27
-rw-r--r--test/funcdup2.go17
-rw-r--r--test/index.go69
-rw-r--r--test/method5.go297
-rw-r--r--test/return.go2889
-rw-r--r--test/shift1.go195
-rw-r--r--test/switch.go9
-rw-r--r--test/switch4.go36
657 files changed, 29308 insertions, 33407 deletions
diff --git a/AUTHORS b/AUTHORS
index de75396d0..78d149f02 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,6 +9,7 @@
# Please keep the list sorted.
Abhinav Gupta <abhinav.g90@gmail.com>
+Adrian Nos <nos.adrian@gmail.com>
Adrian O'Grady <elpollouk@gmail.com>
Akshat Kumar <seed@mail.nanosouffle.net>
Albert Strasheim <fullung@gmail.com>
@@ -54,6 +55,7 @@ Casey Marshall <casey.marshall@gmail.com>
Charles L. Dorian <cldorian@gmail.com>
Chris Dollin <ehog.hedge@gmail.com>
Chris Farmiloe <chrisfarms@gmail.com>
+Chris Howey <howeyc@gmail.com>
Chris Jones <chris@cjones.org>
Chris Lennert <calennert@gmail.com>
Christian Himpel <chressie@googlemail.com>
@@ -98,6 +100,7 @@ Eric Roshan-Eisner <eric.d.eisner@gmail.com>
Erik St. Martin <alakriti@gmail.com>
Esko Luontola <esko.luontola@gmail.com>
Evan Shaw <chickencha@gmail.com>
+Ewan Chou <coocood@gmail.com>
Fan Hongjian <fan.howard@gmail.com>
Fazlul Shahriar <fshahriar@gmail.com>
Firmansyah Adiputra <frm.adiputra@gmail.com>
@@ -117,6 +120,7 @@ Gustavo Niemeyer <gustavo@niemeyer.net>
Gwenael Treguier <gwenn.kahz@gmail.com>
Harley Laue <losinggeneration@gmail.com>
Hector Chu <hectorchu@gmail.com>
+Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
Icarus Sparry <golang@icarus.freeuk.com>
Ingo Oeser <nightlyone@googlemail.com>
@@ -148,6 +152,7 @@ John Asmuth <jasmuth@gmail.com>
John Graham-Cumming <jgc@jgc.org> <jgrahamc@gmail.com>
Jonathan Gold <jgold.bg@gmail.com>
Jonathan Mark <jhmark@xenops.com>
+Jonathan Rudenberg <jonathan@titanous.com>
Jonathan Wills <runningwild@gmail.com>
Jongmin Kim <atomaths@gmail.com>
Jose Luis Vázquez González <josvazg@gmail.com>
@@ -223,6 +228,7 @@ Peter Mundy <go.peter.90@gmail.com>
Péter Surányi <speter.go1@gmail.com>
Peter Waller <peter.waller@gmail.com>
Peter Williams <pwil3058@gmail.com>
+Philip K. Warren <pkwarren@gmail.com>
Pieter Droogendijk <pieter@binky.org.uk>
Quan Yong Zhai <qyzhai@gmail.com>
Raif S. Naffah <go@naffah-raif.name>
@@ -235,6 +241,7 @@ Robert Dinu <r@oktett.se>
Robert Figueiredo <robfig@gmail.com>
Robert Hencke <robert.hencke@gmail.com>
Robin Eklind <r.eklind.87@gmail.com>
+Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>
Roger Pau Monné <royger@gmail.com>
Roger Peppe <rogpeppe@gmail.com>
@@ -258,6 +265,7 @@ Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
Stéphane Travostino <stephane.travostino@gmail.com>
Stephen McQuay <stephen@mcquay.me>
Stephen Weinberg <stephen@q5comm.com>
+Steve McCoy <mccoyst@gmail.com>
Steven Elliot Harris <seharris@gmail.com>
Sven Almgren <sven@tras.se>
Szabolcs Nagy <nsz@port70.net>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 01f412872..6afe1f0d1 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -34,6 +34,7 @@
Aaron Kemp <kemp.aaron@gmail.com>
Abhinav Gupta <abhinav.g90@gmail.com>
Adam Langley <agl@golang.org>
+Adrian Nos <nos.adrian@gmail.com>
Adrian O'Grady <elpollouk@gmail.com>
Akshat Kumar <seed@mail.nanosouffle.net>
Alan Donovan <adonovan@google.com>
@@ -98,6 +99,7 @@ Casey Marshall <casey.marshall@gmail.com>
Charles L. Dorian <cldorian@gmail.com>
Chris Dollin <ehog.hedge@gmail.com>
Chris Farmiloe <chrisfarms@gmail.com>
+Chris Howey <howeyc@gmail.com>
Chris Hundt <hundt@google.com>
Chris Jones <chris@cjones.org> <chris.jones.yar@gmail.com>
Chris Lennert <calennert@gmail.com>
@@ -155,6 +157,7 @@ Erik St. Martin <alakriti@gmail.com>
Esko Luontola <esko.luontola@gmail.com>
Evan Martin <evan.martin@gmail.com>
Evan Shaw <chickencha@gmail.com>
+Ewan Chou <coocood@gmail.com>
Fan Hongjian <fan.howard@gmail.com>
Fazlul Shahriar <fshahriar@gmail.com>
Firmansyah Adiputra <frm.adiputra@gmail.com>
@@ -178,6 +181,7 @@ Gwenael Treguier <gwenn.kahz@gmail.com>
Han-Wen Nienhuys <hanwen@google.com>
Harley Laue <losinggeneration@gmail.com>
Hector Chu <hectorchu@gmail.com>
+Herbert Georg Fischer <herbert.fischer@gmail.com>
Hong Ruiqi <hongruiqi@gmail.com>
Hossein Sheikh Attar <hattar@google.com>
Ian Lance Taylor <iant@golang.org>
@@ -224,11 +228,14 @@ Jonathan Feinberg <feinberg@google.com>
Jonathan Gold <jgold.bg@gmail.com>
Jonathan Hseu <jhseu@google.com>
Jonathan Mark <jhmark@xenops.com> <jhmark000@gmail.com>
+Jonathan Nieder <jrn@google.com>
Jonathan Pittman <jmpittman@google.com> <jonathan.mark.pittman@gmail.com>
+Jonathan Rudenberg <jonathan@titanous.com>
Jonathan Wills <runningwild@gmail.com>
Jongmin Kim <atomaths@gmail.com>
Jos Visser <josv@google.com>
Jose Luis Vázquez González <josvazg@gmail.com>
+Joseph Bonneau <jcb@google.com>
Josh Goebel <dreamer3@gmail.com>
Josh Holland <jrh@joshh.co.uk>
Jukka-Pekka Kekkonen <karatepekka@gmail.com>
@@ -237,6 +244,7 @@ Julien Schmidt <google@julienschmidt.com>
Kai Backman <kaib@golang.org>
Kamil Kisiel <kamil@kamilkisiel.net> <kamil.kisiel@gmail.com>
Kei Son <hey.calmdown@gmail.com>
+Keith Randall <khr@golang.org>
Keith Rarick <kr@xph.us>
Ken Friedenbach <kenliz@cruzio.com>
Ken Rockot <ken@oz.gs> <ken.rockot@gmail.com>
@@ -326,6 +334,7 @@ Peter Waller <peter.waller@gmail.com>
Peter Weinberger <pjw@golang.org>
Peter Williams <pwil3058@gmail.com>
Phil Pennock <pdp@golang.org>
+Philip K. Warren <pkwarren@gmail.com>
Pieter Droogendijk <pieter@binky.org.uk>
Quan Yong Zhai <qyzhai@gmail.com>
Raif S. Naffah <go@naffah-raif.name>
@@ -341,6 +350,7 @@ Robert Figueiredo <robfig@gmail.com>
Robert Griesemer <gri@golang.org>
Robert Hencke <robert.hencke@gmail.com>
Robin Eklind <r.eklind.87@gmail.com>
+Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>
Roger Pau Monné <royger@gmail.com>
Roger Peppe <rogpeppe@gmail.com>
@@ -371,6 +381,7 @@ Stéphane Travostino <stephane.travostino@gmail.com>
Stephen Ma <stephenm@golang.org>
Stephen McQuay <stephen@mcquay.me>
Stephen Weinberg <stephen@q5comm.com>
+Steve McCoy <mccoyst@gmail.com>
Steven Elliot Harris <seharris@gmail.com>
Sugu Sougoumarane <ssougou@gmail.com>
Sven Almgren <sven@tras.se>
diff --git a/api/next.txt b/api/next.txt
index b049cc3ce..b45c22526 100644
--- a/api/next.txt
+++ b/api/next.txt
@@ -109,194 +109,6 @@ pkg go/format, func Node(io.Writer, *token.FileSet, interface{}) error
pkg go/format, func Source([]uint8) ([]uint8, error)
pkg go/parser, const AllErrors Mode
pkg go/printer, type Config struct, Indent int
-pkg go/types, const Bool BasicKind
-pkg go/types, const Byte BasicKind
-pkg go/types, const Complex128 BasicKind
-pkg go/types, const Complex64 BasicKind
-pkg go/types, const DefaultMaxAlign ideal-int
-pkg go/types, const DefaultPtrSize ideal-int
-pkg go/types, const Float32 BasicKind
-pkg go/types, const Float64 BasicKind
-pkg go/types, const Int BasicKind
-pkg go/types, const Int16 BasicKind
-pkg go/types, const Int32 BasicKind
-pkg go/types, const Int64 BasicKind
-pkg go/types, const Int8 BasicKind
-pkg go/types, const Invalid BasicKind
-pkg go/types, const IsBoolean BasicInfo
-pkg go/types, const IsComplex BasicInfo
-pkg go/types, const IsConstType BasicInfo
-pkg go/types, const IsFloat BasicInfo
-pkg go/types, const IsInteger BasicInfo
-pkg go/types, const IsNumeric BasicInfo
-pkg go/types, const IsOrdered BasicInfo
-pkg go/types, const IsString BasicInfo
-pkg go/types, const IsUnsigned BasicInfo
-pkg go/types, const IsUntyped BasicInfo
-pkg go/types, const Rune BasicKind
-pkg go/types, const String BasicKind
-pkg go/types, const Uint BasicKind
-pkg go/types, const Uint16 BasicKind
-pkg go/types, const Uint32 BasicKind
-pkg go/types, const Uint64 BasicKind
-pkg go/types, const Uint8 BasicKind
-pkg go/types, const Uintptr BasicKind
-pkg go/types, const UnsafePointer BasicKind
-pkg go/types, const UntypedBool BasicKind
-pkg go/types, const UntypedComplex BasicKind
-pkg go/types, const UntypedFloat BasicKind
-pkg go/types, const UntypedInt BasicKind
-pkg go/types, const UntypedNil BasicKind
-pkg go/types, const UntypedRune BasicKind
-pkg go/types, const UntypedString BasicKind
-pkg go/types, func Check(*token.FileSet, []*ast.File) (*Package, error)
-pkg go/types, func DefaultAlignof(Type) int64
-pkg go/types, func DefaultOffsetsof([]*Field) []int64
-pkg go/types, func DefaultSizeof(Type) int64
-pkg go/types, func FindGcExportData(*bufio.Reader) error
-pkg go/types, func FindPkg(string, string) (string, string)
-pkg go/types, func GcImport(map[string]*Package, string) (*Package, error)
-pkg go/types, func GcImportData(map[string]*Package, string, string, *bufio.Reader) (*Package, error)
-pkg go/types, func IsIdentical(Type, Type) bool
-pkg go/types, method (*Array) String() string
-pkg go/types, method (*Basic) String() string
-pkg go/types, method (*Chan) String() string
-pkg go/types, method (*Const) GetName() string
-pkg go/types, method (*Const) GetPkg() *Package
-pkg go/types, method (*Const) GetPos() token.Pos
-pkg go/types, method (*Const) GetType() Type
-pkg go/types, method (*Context) Check(*token.FileSet, []*ast.File) (*Package, error)
-pkg go/types, method (*Func) GetName() string
-pkg go/types, method (*Func) GetPkg() *Package
-pkg go/types, method (*Func) GetPos() token.Pos
-pkg go/types, method (*Func) GetType() Type
-pkg go/types, method (*Interface) String() string
-pkg go/types, method (*Map) String() string
-pkg go/types, method (*NamedType) String() string
-pkg go/types, method (*Package) GetName() string
-pkg go/types, method (*Package) GetPkg() *Package
-pkg go/types, method (*Package) GetPos() token.Pos
-pkg go/types, method (*Package) GetType() Type
-pkg go/types, method (*Pointer) String() string
-pkg go/types, method (*Result) String() string
-pkg go/types, method (*Scope) Insert(Object) Object
-pkg go/types, method (*Scope) Lookup(string) Object
-pkg go/types, method (*Scope) String() string
-pkg go/types, method (*Signature) String() string
-pkg go/types, method (*Slice) String() string
-pkg go/types, method (*Struct) String() string
-pkg go/types, method (*TypeName) GetName() string
-pkg go/types, method (*TypeName) GetPkg() *Package
-pkg go/types, method (*TypeName) GetPos() token.Pos
-pkg go/types, method (*TypeName) GetType() Type
-pkg go/types, method (*Var) GetName() string
-pkg go/types, method (*Var) GetPkg() *Package
-pkg go/types, method (*Var) GetPos() token.Pos
-pkg go/types, method (*Var) GetType() Type
-pkg go/types, method (Complex) String() string
-pkg go/types, method (Field) IsSame(QualifiedName) bool
-pkg go/types, method (Method) IsSame(QualifiedName) bool
-pkg go/types, method (NilType) String() string
-pkg go/types, method (QualifiedName) IsSame(QualifiedName) bool
-pkg go/types, type Array struct
-pkg go/types, type Array struct, Elt Type
-pkg go/types, type Array struct, Len int64
-pkg go/types, type Basic struct
-pkg go/types, type Basic struct, Info BasicInfo
-pkg go/types, type Basic struct, Kind BasicKind
-pkg go/types, type Basic struct, Name string
-pkg go/types, type Basic struct, Size int64
-pkg go/types, type BasicInfo int
-pkg go/types, type BasicKind int
-pkg go/types, type Chan struct
-pkg go/types, type Chan struct, Dir ast.ChanDir
-pkg go/types, type Chan struct, Elt Type
-pkg go/types, type Complex struct
-pkg go/types, type Complex struct, Im *big.Rat
-pkg go/types, type Complex struct, Re *big.Rat
-pkg go/types, type Const struct
-pkg go/types, type Const struct, Name string
-pkg go/types, type Const struct, Pkg *Package
-pkg go/types, type Const struct, Type Type
-pkg go/types, type Const struct, Val interface{}
-pkg go/types, type Context struct
-pkg go/types, type Context struct, Alignof func(Type) int64
-pkg go/types, type Context struct, Error func(error)
-pkg go/types, type Context struct, Expr func(ast.Expr, Type, interface{})
-pkg go/types, type Context struct, Ident func(*ast.Ident, Object)
-pkg go/types, type Context struct, Import Importer
-pkg go/types, type Context struct, IntSize int64
-pkg go/types, type Context struct, Offsetsof func([]*Field) []int64
-pkg go/types, type Context struct, PtrSize int64
-pkg go/types, type Context struct, Sizeof func(Type) int64
-pkg go/types, type Field struct
-pkg go/types, type Field struct, IsAnonymous bool
-pkg go/types, type Field struct, Tag string
-pkg go/types, type Field struct, Type Type
-pkg go/types, type Field struct, embedded QualifiedName
-pkg go/types, type Func struct
-pkg go/types, type Func struct, Name string
-pkg go/types, type Func struct, Pkg *Package
-pkg go/types, type Func struct, Type Type
-pkg go/types, type Importer func(imports map[string]*Package, path string) (pkg *Package, err error)
-pkg go/types, type Importer func(map[string]*Package, string) (*Package, error)
-pkg go/types, type Interface struct
-pkg go/types, type Interface struct, Methods []*Method
-pkg go/types, type Map struct
-pkg go/types, type Map struct, Elt Type
-pkg go/types, type Map struct, Key Type
-pkg go/types, type Method struct
-pkg go/types, type Method struct, Type *Signature
-pkg go/types, type Method struct, embedded QualifiedName
-pkg go/types, type NamedType struct
-pkg go/types, type NamedType struct, Methods []*Method
-pkg go/types, type NamedType struct, Obj *TypeName
-pkg go/types, type NamedType struct, Underlying Type
-pkg go/types, type NilType struct
-pkg go/types, type Object interface, GetName() string
-pkg go/types, type Object interface, GetPkg() *Package
-pkg go/types, type Object interface, GetPos() token.Pos
-pkg go/types, type Object interface, GetType() Type
-pkg go/types, type Object interface, unexported methods
-pkg go/types, type Package struct
-pkg go/types, type Package struct, Complete bool
-pkg go/types, type Package struct, Imports map[string]*Package
-pkg go/types, type Package struct, Name string
-pkg go/types, type Package struct, Path string
-pkg go/types, type Package struct, Scope *Scope
-pkg go/types, type Pointer struct
-pkg go/types, type Pointer struct, Base Type
-pkg go/types, type QualifiedName struct
-pkg go/types, type QualifiedName struct, Name string
-pkg go/types, type QualifiedName struct, Pkg *Package
-pkg go/types, type Result struct
-pkg go/types, type Result struct, Values []*Var
-pkg go/types, type Scope struct
-pkg go/types, type Scope struct, Entries []Object
-pkg go/types, type Scope struct, Outer *Scope
-pkg go/types, type Signature struct
-pkg go/types, type Signature struct, IsVariadic bool
-pkg go/types, type Signature struct, Params []*Var
-pkg go/types, type Signature struct, Recv *Var
-pkg go/types, type Signature struct, Results []*Var
-pkg go/types, type Slice struct
-pkg go/types, type Slice struct, Elt Type
-pkg go/types, type Struct struct
-pkg go/types, type Struct struct, Fields []*Field
-pkg go/types, type Type interface, String() string
-pkg go/types, type Type interface, unexported methods
-pkg go/types, type TypeName struct
-pkg go/types, type TypeName struct, Name string
-pkg go/types, type TypeName struct, Pkg *Package
-pkg go/types, type TypeName struct, Type Type
-pkg go/types, type Var struct
-pkg go/types, type Var struct, Name string
-pkg go/types, type Var struct, Pkg *Package
-pkg go/types, type Var struct, Type Type
-pkg go/types, var Default Context
-pkg go/types, var Typ [...]*Basic
-pkg go/types, var Universe *Scope
-pkg go/types, var Unsafe *Package
pkg image, const YCbCrSubsampleRatio440 YCbCrSubsampleRatio
pkg io, type ByteWriter interface { WriteByte }
pkg io, type ByteWriter interface, WriteByte(uint8) error
@@ -552,11 +364,21 @@ pkg net, var UDP DialOption
pkg net/http, func ParseTime(string) (time.Time, error)
pkg net/http, method (*Request) PostFormValue(string) string
pkg net/http, method (*ServeMux) Handler(*Request) (Handler, string)
+pkg net/http, method (*Transport) CancelRequest(*Request)
pkg net/http, type CloseNotifier interface { CloseNotify }
pkg net/http, type CloseNotifier interface, CloseNotify() <-chan bool
pkg net/http, type Request struct, PostForm url.Values
pkg net/http, type Server struct, TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
pkg net/http, type Transport struct, ResponseHeaderTimeout time.Duration
+pkg net/http/cookiejar, func New(*Options) (*Jar, error)
+pkg net/http/cookiejar, method (*Jar) Cookies(*url.URL) []*http.Cookie
+pkg net/http/cookiejar, method (*Jar) SetCookies(*url.URL, []*http.Cookie)
+pkg net/http/cookiejar, type Jar struct
+pkg net/http/cookiejar, type Options struct
+pkg net/http/cookiejar, type Options struct, PublicSuffixList PublicSuffixList
+pkg net/http/cookiejar, type PublicSuffixList interface { PublicSuffix, String }
+pkg net/http/cookiejar, type PublicSuffixList interface, PublicSuffix(string) string
+pkg net/http/cookiejar, type PublicSuffixList interface, String() string
pkg net/mail, func ParseAddress(string) (*Address, error)
pkg net/mail, func ParseAddressList(string) ([]*Address, error)
pkg net/smtp, method (*Client) Hello(string) error
@@ -1031,9 +853,206 @@ pkg syscall (darwin-amd64-cgo), type Termios struct, Lflag uint64
pkg syscall (darwin-amd64-cgo), type Termios struct, Oflag uint64
pkg syscall (darwin-amd64-cgo), type Termios struct, Ospeed uint64
pkg syscall (darwin-amd64-cgo), type Termios struct, Pad_cgo_0 [4]uint8
+pkg syscall (freebsd-386), const B0 ideal-int
+pkg syscall (freebsd-386), const B110 ideal-int
+pkg syscall (freebsd-386), const B115200 ideal-int
+pkg syscall (freebsd-386), const B1200 ideal-int
+pkg syscall (freebsd-386), const B134 ideal-int
+pkg syscall (freebsd-386), const B14400 ideal-int
+pkg syscall (freebsd-386), const B150 ideal-int
+pkg syscall (freebsd-386), const B1800 ideal-int
+pkg syscall (freebsd-386), const B19200 ideal-int
+pkg syscall (freebsd-386), const B200 ideal-int
+pkg syscall (freebsd-386), const B230400 ideal-int
+pkg syscall (freebsd-386), const B2400 ideal-int
+pkg syscall (freebsd-386), const B28800 ideal-int
+pkg syscall (freebsd-386), const B300 ideal-int
+pkg syscall (freebsd-386), const B38400 ideal-int
+pkg syscall (freebsd-386), const B460800 ideal-int
+pkg syscall (freebsd-386), const B4800 ideal-int
+pkg syscall (freebsd-386), const B50 ideal-int
+pkg syscall (freebsd-386), const B57600 ideal-int
+pkg syscall (freebsd-386), const B600 ideal-int
+pkg syscall (freebsd-386), const B7200 ideal-int
+pkg syscall (freebsd-386), const B75 ideal-int
+pkg syscall (freebsd-386), const B76800 ideal-int
+pkg syscall (freebsd-386), const B921600 ideal-int
+pkg syscall (freebsd-386), const B9600 ideal-int
+pkg syscall (freebsd-386), const BIOCGTSTAMP ideal-int
+pkg syscall (freebsd-386), const BIOCSTSTAMP ideal-int
+pkg syscall (freebsd-386), const BPF_T_BINTIME ideal-int
+pkg syscall (freebsd-386), const BPF_T_BINTIME_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_BINTIME_MONOTONIC ideal-int
+pkg syscall (freebsd-386), const BPF_T_BINTIME_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_FLAG_MASK ideal-int
+pkg syscall (freebsd-386), const BPF_T_FORMAT_MASK ideal-int
+pkg syscall (freebsd-386), const BPF_T_MICROTIME ideal-int
+pkg syscall (freebsd-386), const BPF_T_MICROTIME_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_MICROTIME_MONOTONIC ideal-int
+pkg syscall (freebsd-386), const BPF_T_MICROTIME_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_MONOTONIC ideal-int
+pkg syscall (freebsd-386), const BPF_T_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_NANOTIME ideal-int
+pkg syscall (freebsd-386), const BPF_T_NANOTIME_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_NANOTIME_MONOTONIC ideal-int
+pkg syscall (freebsd-386), const BPF_T_NANOTIME_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-386), const BPF_T_NONE ideal-int
+pkg syscall (freebsd-386), const BPF_T_NORMAL ideal-int
+pkg syscall (freebsd-386), const BRKINT ideal-int
+pkg syscall (freebsd-386), const CFLUSH ideal-int
+pkg syscall (freebsd-386), const CLOCAL ideal-int
+pkg syscall (freebsd-386), const CREAD ideal-int
+pkg syscall (freebsd-386), const CS5 ideal-int
+pkg syscall (freebsd-386), const CS6 ideal-int
+pkg syscall (freebsd-386), const CS7 ideal-int
+pkg syscall (freebsd-386), const CS8 ideal-int
+pkg syscall (freebsd-386), const CSIZE ideal-int
+pkg syscall (freebsd-386), const CSTART ideal-int
+pkg syscall (freebsd-386), const CSTATUS ideal-int
+pkg syscall (freebsd-386), const CSTOP ideal-int
+pkg syscall (freebsd-386), const CSTOPB ideal-int
+pkg syscall (freebsd-386), const CSUSP ideal-int
+pkg syscall (freebsd-386), const DLT_AOS ideal-int
+pkg syscall (freebsd-386), const DLT_CAN_SOCKETCAN ideal-int
+pkg syscall (freebsd-386), const DLT_DBUS ideal-int
+pkg syscall (freebsd-386), const DLT_DECT ideal-int
+pkg syscall (freebsd-386), const DLT_DVB_CI ideal-int
+pkg syscall (freebsd-386), const DLT_FC_2 ideal-int
+pkg syscall (freebsd-386), const DLT_FC_2_WITH_FRAME_DELIMS ideal-int
+pkg syscall (freebsd-386), const DLT_GSMTAP_ABIS ideal-int
+pkg syscall (freebsd-386), const DLT_GSMTAP_UM ideal-int
+pkg syscall (freebsd-386), const DLT_IEEE802_15_4_NOFCS ideal-int
+pkg syscall (freebsd-386), const DLT_IPNET ideal-int
+pkg syscall (freebsd-386), const DLT_IPOIB ideal-int
+pkg syscall (freebsd-386), const DLT_IPV4 ideal-int
+pkg syscall (freebsd-386), const DLT_IPV6 ideal-int
+pkg syscall (freebsd-386), const DLT_JUNIPER_ATM_CEMIC ideal-int
+pkg syscall (freebsd-386), const DLT_JUNIPER_FIBRECHANNEL ideal-int
+pkg syscall (freebsd-386), const DLT_JUNIPER_SRX_E2E ideal-int
+pkg syscall (freebsd-386), const DLT_JUNIPER_VS ideal-int
+pkg syscall (freebsd-386), const DLT_LINUX_EVDEV ideal-int
+pkg syscall (freebsd-386), const DLT_MATCHING_MAX ideal-int
+pkg syscall (freebsd-386), const DLT_MATCHING_MIN ideal-int
+pkg syscall (freebsd-386), const DLT_MPLS ideal-int
+pkg syscall (freebsd-386), const DLT_MUX27010 ideal-int
+pkg syscall (freebsd-386), const DLT_NETANALYZER ideal-int
+pkg syscall (freebsd-386), const DLT_NETANALYZER_TRANSPARENT ideal-int
+pkg syscall (freebsd-386), const DLT_NFLOG ideal-int
+pkg syscall (freebsd-386), const DLT_STANAG_5066_D_PDU ideal-int
+pkg syscall (freebsd-386), const DLT_USB_LINUX_MMAPPED ideal-int
+pkg syscall (freebsd-386), const DLT_WIHART ideal-int
+pkg syscall (freebsd-386), const ECAPMODE Errno
+pkg syscall (freebsd-386), const FLUSHO ideal-int
+pkg syscall (freebsd-386), const HUPCL ideal-int
+pkg syscall (freebsd-386), const ICANON ideal-int
+pkg syscall (freebsd-386), const ICRNL ideal-int
+pkg syscall (freebsd-386), const IEXTEN ideal-int
pkg syscall (freebsd-386), const IFAN_ARRIVAL ideal-int
pkg syscall (freebsd-386), const IFAN_DEPARTURE ideal-int
+pkg syscall (freebsd-386), const IFF_CANTCONFIG ideal-int
+pkg syscall (freebsd-386), const IFT_INFINIBAND ideal-int
+pkg syscall (freebsd-386), const IGNBRK ideal-int
+pkg syscall (freebsd-386), const IGNCR ideal-int
+pkg syscall (freebsd-386), const IGNPAR ideal-int
+pkg syscall (freebsd-386), const IMAXBEL ideal-int
+pkg syscall (freebsd-386), const INLCR ideal-int
+pkg syscall (freebsd-386), const INPCK ideal-int
+pkg syscall (freebsd-386), const IN_RFC3021_MASK ideal-int
+pkg syscall (freebsd-386), const IPPROTO_MH ideal-int
+pkg syscall (freebsd-386), const IPPROTO_SEND ideal-int
+pkg syscall (freebsd-386), const IP_RECVTOS ideal-int
+pkg syscall (freebsd-386), const ISIG ideal-int
+pkg syscall (freebsd-386), const ISTRIP ideal-int
+pkg syscall (freebsd-386), const IXANY ideal-int
+pkg syscall (freebsd-386), const IXOFF ideal-int
+pkg syscall (freebsd-386), const IXON ideal-int
+pkg syscall (freebsd-386), const MADV_AUTOSYNC ideal-int
+pkg syscall (freebsd-386), const MADV_CORE ideal-int
+pkg syscall (freebsd-386), const MADV_DONTNEED ideal-int
+pkg syscall (freebsd-386), const MADV_FREE ideal-int
+pkg syscall (freebsd-386), const MADV_NOCORE ideal-int
+pkg syscall (freebsd-386), const MADV_NORMAL ideal-int
+pkg syscall (freebsd-386), const MADV_NOSYNC ideal-int
+pkg syscall (freebsd-386), const MADV_PROTECT ideal-int
+pkg syscall (freebsd-386), const MADV_RANDOM ideal-int
+pkg syscall (freebsd-386), const MADV_SEQUENTIAL ideal-int
+pkg syscall (freebsd-386), const MADV_WILLNEED ideal-int
+pkg syscall (freebsd-386), const MAP_ANON ideal-int
+pkg syscall (freebsd-386), const MAP_ANONYMOUS ideal-int
+pkg syscall (freebsd-386), const MAP_COPY ideal-int
+pkg syscall (freebsd-386), const MAP_FILE ideal-int
+pkg syscall (freebsd-386), const MAP_FIXED ideal-int
+pkg syscall (freebsd-386), const MAP_HASSEMAPHORE ideal-int
+pkg syscall (freebsd-386), const MAP_NOCORE ideal-int
+pkg syscall (freebsd-386), const MAP_NORESERVE ideal-int
+pkg syscall (freebsd-386), const MAP_NOSYNC ideal-int
+pkg syscall (freebsd-386), const MAP_PREFAULT_READ ideal-int
+pkg syscall (freebsd-386), const MAP_PRIVATE ideal-int
+pkg syscall (freebsd-386), const MAP_RENAME ideal-int
+pkg syscall (freebsd-386), const MAP_RESERVED0080 ideal-int
+pkg syscall (freebsd-386), const MAP_RESERVED0100 ideal-int
+pkg syscall (freebsd-386), const MAP_SHARED ideal-int
+pkg syscall (freebsd-386), const MAP_STACK ideal-int
+pkg syscall (freebsd-386), const MCL_CURRENT ideal-int
+pkg syscall (freebsd-386), const MCL_FUTURE ideal-int
+pkg syscall (freebsd-386), const MS_ASYNC ideal-int
+pkg syscall (freebsd-386), const MS_INVALIDATE ideal-int
+pkg syscall (freebsd-386), const MS_SYNC ideal-int
+pkg syscall (freebsd-386), const NET_RT_IFLISTL ideal-int
+pkg syscall (freebsd-386), const NOFLSH ideal-int
+pkg syscall (freebsd-386), const OCRNL ideal-int
+pkg syscall (freebsd-386), const ONLCR ideal-int
+pkg syscall (freebsd-386), const ONLRET ideal-int
+pkg syscall (freebsd-386), const ONOCR ideal-int
+pkg syscall (freebsd-386), const ONOEOT ideal-int
+pkg syscall (freebsd-386), const OPOST ideal-int
+pkg syscall (freebsd-386), const PARENB ideal-int
+pkg syscall (freebsd-386), const PARMRK ideal-int
+pkg syscall (freebsd-386), const PARODD ideal-int
+pkg syscall (freebsd-386), const PENDIN ideal-int
+pkg syscall (freebsd-386), const PROT_EXEC ideal-int
+pkg syscall (freebsd-386), const PROT_NONE ideal-int
+pkg syscall (freebsd-386), const PROT_READ ideal-int
+pkg syscall (freebsd-386), const PROT_WRITE ideal-int
+pkg syscall (freebsd-386), const RT_CACHING_CONTEXT ideal-int
+pkg syscall (freebsd-386), const RT_DEFAULT_FIB ideal-int
+pkg syscall (freebsd-386), const SIOCGIFFIB ideal-int
+pkg syscall (freebsd-386), const SIOCSIFFIB ideal-int
+pkg syscall (freebsd-386), const SO_PROTOCOL ideal-int
+pkg syscall (freebsd-386), const SO_PROTOTYPE ideal-int
+pkg syscall (freebsd-386), const SO_USER_COOKIE ideal-int
+pkg syscall (freebsd-386), const SYS_CLOCK_GETCPUCLOCKID2 ideal-int
+pkg syscall (freebsd-386), const SYS_WAIT6 ideal-int
pkg syscall (freebsd-386), const SizeofIfAnnounceMsghdr ideal-int
+pkg syscall (freebsd-386), const TCIFLUSH ideal-int
+pkg syscall (freebsd-386), const TCIOFLUSH ideal-int
+pkg syscall (freebsd-386), const TCOFLUSH ideal-int
+pkg syscall (freebsd-386), const TCP_KEEPCNT ideal-int
+pkg syscall (freebsd-386), const TCP_KEEPIDLE ideal-int
+pkg syscall (freebsd-386), const TCP_KEEPINIT ideal-int
+pkg syscall (freebsd-386), const TCP_KEEPINTVL ideal-int
+pkg syscall (freebsd-386), const TCSAFLUSH ideal-int
+pkg syscall (freebsd-386), const TOSTOP ideal-int
+pkg syscall (freebsd-386), const VDISCARD ideal-int
+pkg syscall (freebsd-386), const VDSUSP ideal-int
+pkg syscall (freebsd-386), const VEOF ideal-int
+pkg syscall (freebsd-386), const VEOL ideal-int
+pkg syscall (freebsd-386), const VEOL2 ideal-int
+pkg syscall (freebsd-386), const VERASE ideal-int
+pkg syscall (freebsd-386), const VERASE2 ideal-int
+pkg syscall (freebsd-386), const VINTR ideal-int
+pkg syscall (freebsd-386), const VKILL ideal-int
+pkg syscall (freebsd-386), const VLNEXT ideal-int
+pkg syscall (freebsd-386), const VMIN ideal-int
+pkg syscall (freebsd-386), const VQUIT ideal-int
+pkg syscall (freebsd-386), const VREPRINT ideal-int
+pkg syscall (freebsd-386), const VSTART ideal-int
+pkg syscall (freebsd-386), const VSTATUS ideal-int
+pkg syscall (freebsd-386), const VSTOP ideal-int
+pkg syscall (freebsd-386), const VSUSP ideal-int
+pkg syscall (freebsd-386), const VTIME ideal-int
+pkg syscall (freebsd-386), const VWERASE ideal-int
pkg syscall (freebsd-386), func SlicePtrFromStrings([]string) ([]*uint8, error)
pkg syscall (freebsd-386), type IfAnnounceMsghdr struct
pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, Index uint16
@@ -1044,9 +1063,206 @@ pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, Version uint8
pkg syscall (freebsd-386), type IfAnnounceMsghdr struct, What uint16
pkg syscall (freebsd-386), type InterfaceAnnounceMessage struct
pkg syscall (freebsd-386), type InterfaceAnnounceMessage struct, Header IfAnnounceMsghdr
+pkg syscall (freebsd-amd64), const B0 ideal-int
+pkg syscall (freebsd-amd64), const B110 ideal-int
+pkg syscall (freebsd-amd64), const B115200 ideal-int
+pkg syscall (freebsd-amd64), const B1200 ideal-int
+pkg syscall (freebsd-amd64), const B134 ideal-int
+pkg syscall (freebsd-amd64), const B14400 ideal-int
+pkg syscall (freebsd-amd64), const B150 ideal-int
+pkg syscall (freebsd-amd64), const B1800 ideal-int
+pkg syscall (freebsd-amd64), const B19200 ideal-int
+pkg syscall (freebsd-amd64), const B200 ideal-int
+pkg syscall (freebsd-amd64), const B230400 ideal-int
+pkg syscall (freebsd-amd64), const B2400 ideal-int
+pkg syscall (freebsd-amd64), const B28800 ideal-int
+pkg syscall (freebsd-amd64), const B300 ideal-int
+pkg syscall (freebsd-amd64), const B38400 ideal-int
+pkg syscall (freebsd-amd64), const B460800 ideal-int
+pkg syscall (freebsd-amd64), const B4800 ideal-int
+pkg syscall (freebsd-amd64), const B50 ideal-int
+pkg syscall (freebsd-amd64), const B57600 ideal-int
+pkg syscall (freebsd-amd64), const B600 ideal-int
+pkg syscall (freebsd-amd64), const B7200 ideal-int
+pkg syscall (freebsd-amd64), const B75 ideal-int
+pkg syscall (freebsd-amd64), const B76800 ideal-int
+pkg syscall (freebsd-amd64), const B921600 ideal-int
+pkg syscall (freebsd-amd64), const B9600 ideal-int
+pkg syscall (freebsd-amd64), const BIOCGTSTAMP ideal-int
+pkg syscall (freebsd-amd64), const BIOCSTSTAMP ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_BINTIME ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_BINTIME_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_BINTIME_MONOTONIC ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_BINTIME_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_FLAG_MASK ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_FORMAT_MASK ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_MICROTIME ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_MICROTIME_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_MICROTIME_MONOTONIC ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_MICROTIME_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_MONOTONIC ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_NANOTIME ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_NANOTIME_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_NANOTIME_MONOTONIC ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_NANOTIME_MONOTONIC_FAST ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_NONE ideal-int
+pkg syscall (freebsd-amd64), const BPF_T_NORMAL ideal-int
+pkg syscall (freebsd-amd64), const BRKINT ideal-int
+pkg syscall (freebsd-amd64), const CFLUSH ideal-int
+pkg syscall (freebsd-amd64), const CLOCAL ideal-int
+pkg syscall (freebsd-amd64), const CREAD ideal-int
+pkg syscall (freebsd-amd64), const CS5 ideal-int
+pkg syscall (freebsd-amd64), const CS6 ideal-int
+pkg syscall (freebsd-amd64), const CS7 ideal-int
+pkg syscall (freebsd-amd64), const CS8 ideal-int
+pkg syscall (freebsd-amd64), const CSIZE ideal-int
+pkg syscall (freebsd-amd64), const CSTART ideal-int
+pkg syscall (freebsd-amd64), const CSTATUS ideal-int
+pkg syscall (freebsd-amd64), const CSTOP ideal-int
+pkg syscall (freebsd-amd64), const CSTOPB ideal-int
+pkg syscall (freebsd-amd64), const CSUSP ideal-int
+pkg syscall (freebsd-amd64), const DLT_AOS ideal-int
+pkg syscall (freebsd-amd64), const DLT_CAN_SOCKETCAN ideal-int
+pkg syscall (freebsd-amd64), const DLT_DBUS ideal-int
+pkg syscall (freebsd-amd64), const DLT_DECT ideal-int
+pkg syscall (freebsd-amd64), const DLT_DVB_CI ideal-int
+pkg syscall (freebsd-amd64), const DLT_FC_2 ideal-int
+pkg syscall (freebsd-amd64), const DLT_FC_2_WITH_FRAME_DELIMS ideal-int
+pkg syscall (freebsd-amd64), const DLT_GSMTAP_ABIS ideal-int
+pkg syscall (freebsd-amd64), const DLT_GSMTAP_UM ideal-int
+pkg syscall (freebsd-amd64), const DLT_IEEE802_15_4_NOFCS ideal-int
+pkg syscall (freebsd-amd64), const DLT_IPNET ideal-int
+pkg syscall (freebsd-amd64), const DLT_IPOIB ideal-int
+pkg syscall (freebsd-amd64), const DLT_IPV4 ideal-int
+pkg syscall (freebsd-amd64), const DLT_IPV6 ideal-int
+pkg syscall (freebsd-amd64), const DLT_JUNIPER_ATM_CEMIC ideal-int
+pkg syscall (freebsd-amd64), const DLT_JUNIPER_FIBRECHANNEL ideal-int
+pkg syscall (freebsd-amd64), const DLT_JUNIPER_SRX_E2E ideal-int
+pkg syscall (freebsd-amd64), const DLT_JUNIPER_VS ideal-int
+pkg syscall (freebsd-amd64), const DLT_LINUX_EVDEV ideal-int
+pkg syscall (freebsd-amd64), const DLT_MATCHING_MAX ideal-int
+pkg syscall (freebsd-amd64), const DLT_MATCHING_MIN ideal-int
+pkg syscall (freebsd-amd64), const DLT_MPLS ideal-int
+pkg syscall (freebsd-amd64), const DLT_MUX27010 ideal-int
+pkg syscall (freebsd-amd64), const DLT_NETANALYZER ideal-int
+pkg syscall (freebsd-amd64), const DLT_NETANALYZER_TRANSPARENT ideal-int
+pkg syscall (freebsd-amd64), const DLT_NFLOG ideal-int
+pkg syscall (freebsd-amd64), const DLT_STANAG_5066_D_PDU ideal-int
+pkg syscall (freebsd-amd64), const DLT_USB_LINUX_MMAPPED ideal-int
+pkg syscall (freebsd-amd64), const DLT_WIHART ideal-int
+pkg syscall (freebsd-amd64), const ECAPMODE Errno
+pkg syscall (freebsd-amd64), const FLUSHO ideal-int
+pkg syscall (freebsd-amd64), const HUPCL ideal-int
+pkg syscall (freebsd-amd64), const ICANON ideal-int
+pkg syscall (freebsd-amd64), const ICRNL ideal-int
+pkg syscall (freebsd-amd64), const IEXTEN ideal-int
pkg syscall (freebsd-amd64), const IFAN_ARRIVAL ideal-int
pkg syscall (freebsd-amd64), const IFAN_DEPARTURE ideal-int
+pkg syscall (freebsd-amd64), const IFF_CANTCONFIG ideal-int
+pkg syscall (freebsd-amd64), const IFT_INFINIBAND ideal-int
+pkg syscall (freebsd-amd64), const IGNBRK ideal-int
+pkg syscall (freebsd-amd64), const IGNCR ideal-int
+pkg syscall (freebsd-amd64), const IGNPAR ideal-int
+pkg syscall (freebsd-amd64), const IMAXBEL ideal-int
+pkg syscall (freebsd-amd64), const INLCR ideal-int
+pkg syscall (freebsd-amd64), const INPCK ideal-int
+pkg syscall (freebsd-amd64), const IN_RFC3021_MASK ideal-int
+pkg syscall (freebsd-amd64), const IPPROTO_MH ideal-int
+pkg syscall (freebsd-amd64), const IPPROTO_SEND ideal-int
+pkg syscall (freebsd-amd64), const IP_RECVTOS ideal-int
+pkg syscall (freebsd-amd64), const ISIG ideal-int
+pkg syscall (freebsd-amd64), const ISTRIP ideal-int
+pkg syscall (freebsd-amd64), const IXANY ideal-int
+pkg syscall (freebsd-amd64), const IXOFF ideal-int
+pkg syscall (freebsd-amd64), const IXON ideal-int
+pkg syscall (freebsd-amd64), const MADV_AUTOSYNC ideal-int
+pkg syscall (freebsd-amd64), const MADV_CORE ideal-int
+pkg syscall (freebsd-amd64), const MADV_DONTNEED ideal-int
+pkg syscall (freebsd-amd64), const MADV_FREE ideal-int
+pkg syscall (freebsd-amd64), const MADV_NOCORE ideal-int
+pkg syscall (freebsd-amd64), const MADV_NORMAL ideal-int
+pkg syscall (freebsd-amd64), const MADV_NOSYNC ideal-int
+pkg syscall (freebsd-amd64), const MADV_PROTECT ideal-int
+pkg syscall (freebsd-amd64), const MADV_RANDOM ideal-int
+pkg syscall (freebsd-amd64), const MADV_SEQUENTIAL ideal-int
+pkg syscall (freebsd-amd64), const MADV_WILLNEED ideal-int
+pkg syscall (freebsd-amd64), const MAP_ANON ideal-int
+pkg syscall (freebsd-amd64), const MAP_ANONYMOUS ideal-int
+pkg syscall (freebsd-amd64), const MAP_COPY ideal-int
+pkg syscall (freebsd-amd64), const MAP_FILE ideal-int
+pkg syscall (freebsd-amd64), const MAP_FIXED ideal-int
+pkg syscall (freebsd-amd64), const MAP_HASSEMAPHORE ideal-int
+pkg syscall (freebsd-amd64), const MAP_NOCORE ideal-int
+pkg syscall (freebsd-amd64), const MAP_NORESERVE ideal-int
+pkg syscall (freebsd-amd64), const MAP_NOSYNC ideal-int
+pkg syscall (freebsd-amd64), const MAP_PREFAULT_READ ideal-int
+pkg syscall (freebsd-amd64), const MAP_PRIVATE ideal-int
+pkg syscall (freebsd-amd64), const MAP_RENAME ideal-int
+pkg syscall (freebsd-amd64), const MAP_RESERVED0080 ideal-int
+pkg syscall (freebsd-amd64), const MAP_RESERVED0100 ideal-int
+pkg syscall (freebsd-amd64), const MAP_SHARED ideal-int
+pkg syscall (freebsd-amd64), const MAP_STACK ideal-int
+pkg syscall (freebsd-amd64), const MCL_CURRENT ideal-int
+pkg syscall (freebsd-amd64), const MCL_FUTURE ideal-int
+pkg syscall (freebsd-amd64), const MS_ASYNC ideal-int
+pkg syscall (freebsd-amd64), const MS_INVALIDATE ideal-int
+pkg syscall (freebsd-amd64), const MS_SYNC ideal-int
+pkg syscall (freebsd-amd64), const NET_RT_IFLISTL ideal-int
+pkg syscall (freebsd-amd64), const NOFLSH ideal-int
+pkg syscall (freebsd-amd64), const OCRNL ideal-int
+pkg syscall (freebsd-amd64), const ONLCR ideal-int
+pkg syscall (freebsd-amd64), const ONLRET ideal-int
+pkg syscall (freebsd-amd64), const ONOCR ideal-int
+pkg syscall (freebsd-amd64), const ONOEOT ideal-int
+pkg syscall (freebsd-amd64), const OPOST ideal-int
+pkg syscall (freebsd-amd64), const PARENB ideal-int
+pkg syscall (freebsd-amd64), const PARMRK ideal-int
+pkg syscall (freebsd-amd64), const PARODD ideal-int
+pkg syscall (freebsd-amd64), const PENDIN ideal-int
+pkg syscall (freebsd-amd64), const PROT_EXEC ideal-int
+pkg syscall (freebsd-amd64), const PROT_NONE ideal-int
+pkg syscall (freebsd-amd64), const PROT_READ ideal-int
+pkg syscall (freebsd-amd64), const PROT_WRITE ideal-int
+pkg syscall (freebsd-amd64), const RT_CACHING_CONTEXT ideal-int
+pkg syscall (freebsd-amd64), const RT_DEFAULT_FIB ideal-int
+pkg syscall (freebsd-amd64), const SIOCGIFFIB ideal-int
+pkg syscall (freebsd-amd64), const SIOCSIFFIB ideal-int
+pkg syscall (freebsd-amd64), const SO_PROTOCOL ideal-int
+pkg syscall (freebsd-amd64), const SO_PROTOTYPE ideal-int
+pkg syscall (freebsd-amd64), const SO_USER_COOKIE ideal-int
+pkg syscall (freebsd-amd64), const SYS_CLOCK_GETCPUCLOCKID2 ideal-int
+pkg syscall (freebsd-amd64), const SYS_WAIT6 ideal-int
pkg syscall (freebsd-amd64), const SizeofIfAnnounceMsghdr ideal-int
+pkg syscall (freebsd-amd64), const TCIFLUSH ideal-int
+pkg syscall (freebsd-amd64), const TCIOFLUSH ideal-int
+pkg syscall (freebsd-amd64), const TCOFLUSH ideal-int
+pkg syscall (freebsd-amd64), const TCP_KEEPCNT ideal-int
+pkg syscall (freebsd-amd64), const TCP_KEEPIDLE ideal-int
+pkg syscall (freebsd-amd64), const TCP_KEEPINIT ideal-int
+pkg syscall (freebsd-amd64), const TCP_KEEPINTVL ideal-int
+pkg syscall (freebsd-amd64), const TCSAFLUSH ideal-int
+pkg syscall (freebsd-amd64), const TOSTOP ideal-int
+pkg syscall (freebsd-amd64), const VDISCARD ideal-int
+pkg syscall (freebsd-amd64), const VDSUSP ideal-int
+pkg syscall (freebsd-amd64), const VEOF ideal-int
+pkg syscall (freebsd-amd64), const VEOL ideal-int
+pkg syscall (freebsd-amd64), const VEOL2 ideal-int
+pkg syscall (freebsd-amd64), const VERASE ideal-int
+pkg syscall (freebsd-amd64), const VERASE2 ideal-int
+pkg syscall (freebsd-amd64), const VINTR ideal-int
+pkg syscall (freebsd-amd64), const VKILL ideal-int
+pkg syscall (freebsd-amd64), const VLNEXT ideal-int
+pkg syscall (freebsd-amd64), const VMIN ideal-int
+pkg syscall (freebsd-amd64), const VQUIT ideal-int
+pkg syscall (freebsd-amd64), const VREPRINT ideal-int
+pkg syscall (freebsd-amd64), const VSTART ideal-int
+pkg syscall (freebsd-amd64), const VSTATUS ideal-int
+pkg syscall (freebsd-amd64), const VSTOP ideal-int
+pkg syscall (freebsd-amd64), const VSUSP ideal-int
+pkg syscall (freebsd-amd64), const VTIME ideal-int
+pkg syscall (freebsd-amd64), const VWERASE ideal-int
pkg syscall (freebsd-amd64), func SlicePtrFromStrings([]string) ([]*uint8, error)
pkg syscall (freebsd-amd64), func Syscall9(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct
@@ -1058,6 +1274,7 @@ pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, Version uint8
pkg syscall (freebsd-amd64), type IfAnnounceMsghdr struct, What uint16
pkg syscall (freebsd-amd64), type InterfaceAnnounceMessage struct
pkg syscall (freebsd-amd64), type InterfaceAnnounceMessage struct, Header IfAnnounceMsghdr
+pkg syscall (linux-386), const MSG_FASTOPEN ideal-int
pkg syscall (linux-386), const RTNLGRP_IPV4_IFADDR ideal-int
pkg syscall (linux-386), const RTNLGRP_IPV4_MROUTE ideal-int
pkg syscall (linux-386), const RTNLGRP_IPV4_ROUTE ideal-int
@@ -1117,6 +1334,7 @@ pkg syscall (linux-386), type TCPInfo struct, Snd_ssthresh uint32
pkg syscall (linux-386), type TCPInfo struct, State uint8
pkg syscall (linux-386), type TCPInfo struct, Total_retrans uint32
pkg syscall (linux-386), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-386-cgo), const MSG_FASTOPEN ideal-int
pkg syscall (linux-386-cgo), const RTNLGRP_IPV4_IFADDR ideal-int
pkg syscall (linux-386-cgo), const RTNLGRP_IPV4_MROUTE ideal-int
pkg syscall (linux-386-cgo), const RTNLGRP_IPV4_ROUTE ideal-int
@@ -1176,6 +1394,7 @@ pkg syscall (linux-386-cgo), type TCPInfo struct, Snd_ssthresh uint32
pkg syscall (linux-386-cgo), type TCPInfo struct, State uint8
pkg syscall (linux-386-cgo), type TCPInfo struct, Total_retrans uint32
pkg syscall (linux-386-cgo), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-amd64), const MSG_FASTOPEN ideal-int
pkg syscall (linux-amd64), const RTNLGRP_IPV4_IFADDR ideal-int
pkg syscall (linux-amd64), const RTNLGRP_IPV4_MROUTE ideal-int
pkg syscall (linux-amd64), const RTNLGRP_IPV4_ROUTE ideal-int
@@ -1235,6 +1454,7 @@ pkg syscall (linux-amd64), type TCPInfo struct, Snd_ssthresh uint32
pkg syscall (linux-amd64), type TCPInfo struct, State uint8
pkg syscall (linux-amd64), type TCPInfo struct, Total_retrans uint32
pkg syscall (linux-amd64), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-amd64-cgo), const MSG_FASTOPEN ideal-int
pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV4_IFADDR ideal-int
pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV4_MROUTE ideal-int
pkg syscall (linux-amd64-cgo), const RTNLGRP_IPV4_ROUTE ideal-int
@@ -1294,6 +1514,7 @@ pkg syscall (linux-amd64-cgo), type TCPInfo struct, Snd_ssthresh uint32
pkg syscall (linux-amd64-cgo), type TCPInfo struct, State uint8
pkg syscall (linux-amd64-cgo), type TCPInfo struct, Total_retrans uint32
pkg syscall (linux-amd64-cgo), type TCPInfo struct, Unacked uint32
+pkg syscall (linux-arm), const MSG_FASTOPEN ideal-int
pkg syscall (linux-arm), const RTNLGRP_IPV4_IFADDR ideal-int
pkg syscall (linux-arm), const RTNLGRP_IPV4_MROUTE ideal-int
pkg syscall (linux-arm), const RTNLGRP_IPV4_ROUTE ideal-int
diff --git a/doc/contribute.html b/doc/contribute.html
index 72c936472..c659de617 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -117,6 +117,13 @@ enabled for your checkout in <code>$GOROOT</code>, the remainder of this
document assumes you are inside <code>$GOROOT</code> when issuing commands.
</p>
+<p>
+Windows users may need to perform extra steps to get the code review
+extension working. See the
+<a href="https://code.google.com/p/go-wiki/wiki/CodeReview">CodeReview page</a>
+on the <a href="http://code.google.com/p/go-wiki/wiki">Go Wiki</a> for details.
+</p>
+
<h3>Log in to the code review site.</h3>
<p>
diff --git a/doc/effective_go.html b/doc/effective_go.html
index e02694add..decca34b5 100644
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -696,10 +696,18 @@ for _, value := range array {
</pre>
<p>
+The blank identifier has many uses, as described in <a href="#blank">a later section</a>.
+
+<p>
For strings, the <code>range</code> does more work for you, breaking out individual
Unicode code points by parsing the UTF-8.
Erroneous encodings consume one byte and produce the
-replacement rune U+FFFD. The loop
+replacement rune U+FFFD.
+(The name (with associated builtin type) <code>rune</code> is Go terminology for a
+single Unicode code point.
+See <a href="http://golang.org/ref/spec#Rune_literals">the language specification</a>
+for details.)
+The loop
</p>
<pre>
for pos, char := range "日本\x80語" { // \x80 is an illegal UTF-8 encoding
@@ -797,6 +805,8 @@ func Compare(a, b []byte) int {
}
</pre>
+<h2 id="type_switch">Type switch</h2>
+
<p>
A switch can also be used to discover the dynamic type of an interface
variable. Such a <em>type switch</em> uses the syntax of a type
@@ -831,8 +841,8 @@ case *int:
One of Go's unusual features is that functions and methods
can return multiple values. This form can be used to
improve on a couple of clumsy idioms in C programs: in-band
-error returns (such as <code>-1</code> for <code>EOF</code>)
-and modifying an argument.
+error returns such as <code>-1</code> for <code>EOF</code>
+and modifying an argument passed by address.
</p>
<p>
@@ -841,7 +851,8 @@ error code secreted away in a volatile location.
In Go, <code>Write</code>
can return a count <i>and</i> an error: &ldquo;Yes, you wrote some
bytes but not all of them because you filled the device&rdquo;.
-The signature of <code>File.Write</code> in package <code>os</code> is:
+The signature of the <code>Write</code> method on files from
+package <code>os</code> is:
</p>
<pre>
@@ -1208,7 +1219,7 @@ It creates slices, maps, and channels only, and it returns an <em>initialized</e
(not <em>zeroed</em>)
value of type <code>T</code> (not <code>*T</code>).
The reason for the distinction
-is that these three types are, under the covers, references to data structures that
+is that these three types represent, under the covers, references to data structures that
must be initialized before use.
A slice, for example, is a three-item descriptor
containing a pointer to the data (inside an array), the length, and the
@@ -1253,7 +1264,8 @@ v := make([]int, 100)
<p>
Remember that <code>make</code> applies only to maps, slices and channels
and does not return a pointer.
-To obtain an explicit pointer allocate with <code>new</code>.
+To obtain an explicit pointer allocate with <code>new</code> or take the address
+of a variable explicitly.
</p>
<h3 id="arrays">Arrays</h3>
@@ -1300,7 +1312,8 @@ x := Sum(&amp;array) // Note the explicit address-of operator
</pre>
<p>
-But even this style isn't idiomatic Go. Slices are.
+But even this style isn't idiomatic Go.
+Use slices instead.
</p>
<h3 id="slices">Slices</h3>
@@ -1312,9 +1325,9 @@ dimension such as transformation matrices, most array programming in
Go is done with slices rather than simple arrays.
</p>
<p>
-Slices are <i>reference types</i>, which means that if you assign one
-slice to another, both refer to the same underlying array. For
-instance, if a function takes a slice argument, changes it makes to
+Slices hold references to an underlying array, and if you assign one
+slice to another, both refer to the same array.
+If a function takes a slice argument, changes it makes to
the elements of the slice will be visible to the caller, analogous to
passing a pointer to the underlying array. A <code>Read</code>
function can therefore accept a slice argument rather than a pointer
@@ -1391,19 +1404,87 @@ design, though, we need a little more information, so we'll return
to it later.
</p>
+<h3 id="two_dimensional_slices">Two-dimensional slices</h3>
+
+<p>
+Go's arrays and slices are one-dimensional.
+To create the equivalent of a 2D array or slice, it is necessary to define an array-of-arrays
+or slice-of-slices, like this:
+</p>
+
+<pre>
+type Transform [3][3]float64 // A 3x3 array, really an array of arrays.
+type LinesOfText [][]byte // A slice of byte slices.
+</pre>
+
+<p>
+Because slices are variable-length, it is possible to have each inner
+slice be a different length.
+That can be a common situation, as in our <code>LinesOfText</code>
+example: each line has an independent length.
+</p>
+
+<pre>
+text := LinesOfText{
+ []byte("Now is the time"),
+ []byte("for all good gophers"),
+ []byte("to bring some fun to the party."),
+}
+</pre>
+
+<p>
+Sometimes it's necessary to allocate a 2D slice, a situation that can arise when
+processing scan lines of pixels, for instance.
+There are two ways to achieve this.
+One is to allocate each slice independently; the other
+is to allocate a single array and point the individual slices into it.
+Which to use depends on your application.
+If the slices might grow or shrink, they should be allocated independently
+to avoid overwriting the next line; if not, it can be more efficient to construct
+the object with a single allocation.
+For reference, here are sketches of the two methods.
+First, a line a time:
+</p>
+
+<pre>
+// Allocate the top-level slice.
+picture := make([][]uint8, YSize) // One row per unit of y.
+// Loop over the rows, allocating the slice for each row.
+for i := range picture {
+ picture[i] = make([]uint8, XSize)
+}
+</pre>
+
+<p>
+And now as one allocation, sliced into lines:
+</p>
+
+<pre>
+// Allocate the top-level slice, the same as before.
+picture := make([][]uint8, YSize) // One row per unit of y.
+// Allocate one large slice to hold all the pixels.
+pixels := make([]uint8, XSize*YSize) // Has type []uint8 even though picture is [][]uint8.
+// Loop over the rows, slicing each row from the front of the remaining pixels slice.
+for i := range picture {
+ picture[i], pixels = pixels[:XSize], pixels[XSize:]
+}
+</pre>
<h3 id="maps">Maps</h3>
<p>
-Maps are a convenient and powerful built-in data structure to associate
-values of different types.
+Maps are a convenient and powerful built-in data structure that associate
+values of one type (the <em>key</em>) with values of another type
+(the <em>element</em> or <em>value</em>)
The key can be of any type for which the equality operator is defined,
such as integers,
floating point and complex numbers,
strings, pointers, interfaces (as long as the dynamic type
-supports equality), structs and arrays. Slices cannot be used as map keys,
+supports equality), structs and arrays.
+Slices cannot be used as map keys,
because equality is not defined on them.
-Like slices, maps are a reference type. If you pass a map to a function
+Like slices, maps hold references to an underlying data structure.
+If you pass a map to a function
that changes the contents of the map, the changes will be visible
in the caller.
</p>
@@ -1453,7 +1534,7 @@ if attended[person] { // will be false if person is not in the map
<p>
Sometimes you need to distinguish a missing entry from
a zero value. Is there an entry for <code>"UTC"</code>
-or is that zero value because it's not in the map at all?
+or is that the empty string because it's not in the map at all?
You can discriminate with a form of multiple assignment.
</p>
<pre>
@@ -1480,10 +1561,8 @@ func offset(tz string) int {
</pre>
<p>
To test for presence in the map without worrying about the actual value,
-you can use the blank identifier (<code>_</code>).
-The blank identifier can be assigned or declared with any value of any type, with the
-value discarded harmlessly. For testing just presence in a map, use the blank
-identifier in place of the usual variable for the value.
+you can use the <a href="#blank">blank identifier</a> (<code>_</code>)
+in place of the usual variable for the value.
</p>
<pre>
_, present := timeZone[tz]
@@ -1524,8 +1603,7 @@ fmt.Println("Hello", 23)
fmt.Println(fmt.Sprint("Hello ", 23))
</pre>
<p>
-As mentioned in
-the <a href="http://tour.golang.org">Tour</a>, <code>fmt.Fprint</code>
+The formatted print functions <code>fmt.Fprint</code>
and friends take as a first argument any object
that implements the <code>io.Writer</code> interface; the variables <code>os.Stdout</code>
and <code>os.Stderr</code> are familiar instances.
@@ -1591,8 +1669,10 @@ map[string] int{"CST":-21600, "PST":-28800, "EST":-18000, "UTC":0, "MST":-25200}
<p>
(Note the ampersands.)
That quoted string format is also available through <code>%q</code> when
-applied to a value of type <code>string</code> or <code>[]byte</code>;
-the alternate format <code>%#q</code> will use backquotes instead if possible.
+applied to a value of type <code>string</code> or <code>[]byte</code>.
+The alternate format <code>%#q</code> will use backquotes instead if possible.
+(The <code>%q</code> format also applies to integers and runes, producing a
+single-quoted rune constant.)
Also, <code>%x</code> works on strings, byte arrays and byte slices as well as
on integers, generating a long hexadecimal string, and with
a space in the format (<code>%&nbsp;x</code>) it puts spaces between the bytes.
@@ -1632,10 +1712,45 @@ the receiver for <code>String</code> must be of value type; this example used a
that's more efficient and idiomatic for struct types.
See the section below on <a href="#pointers_vs_values">pointers vs. value receivers</a> for more information.)
</p>
+
<p>
Our <code>String</code> method is able to call <code>Sprintf</code> because the
-print routines are fully reentrant and can be used recursively.
-We can even go one step further and pass a print routine's arguments directly to another such routine.
+print routines are fully reentrant and can be wrapped this way.
+There is one important detail to understand about this approach,
+however: don't construct a <code>String</code> method by calling
+<code>Sprintf</code> in a way that will recur into your <code>String</code>
+method indefinitely. This can happen if the <code>Sprintf</code>
+call attempts to print the receiver directly as a string, which in
+turn will invoke the method again. It's a common and easy mistake
+to make, as this example shows.
+</p>
+
+<pre>
+type MyString string
+
+func (m MyString) String() string {
+ return fmt.Sprintf("MyString=%s", m) // Error: will recur forever.
+}
+</pre>
+
+<p>
+It's also easy to fix: convert the argument to the basic string type, which does not have the
+method.
+</p>
+
+<pre>
+type MyString string
+func (m MyString) String() string {
+ return fmt.Sprintf("MyString=%s", string(m)) // OK: note conversion.
+}
+</pre>
+
+<p>
+In the <a href="#initialization">initialization section</a> we'll see another technique that avoids this recursion.
+</p>
+
+<p>
+Another printing technique is to pass a print routine's arguments directly to another such routine.
The signature of <code>Printf</code> uses the type <code>...interface{}</code>
for its final argument to specify that an arbitrary number of parameters (of arbitrary type)
can appear after the format.
@@ -1690,7 +1805,7 @@ is different from our custom <code>Append</code> function above.
Schematically, it's like this:
</p>
<pre>
-func append(slice []<i>T</i>, elements...T) []<i>T</i>
+func append(slice []<i>T</i>, elements...<i>T</i>) []<i>T</i>
</pre>
<p>
where <i>T</i> is a placeholder for any given type. You can't
@@ -1738,7 +1853,7 @@ would be wrong; <code>y</code> is not of type <code>int</code>.
Although it doesn't look superficially very different from
initialization in C or C++, initialization in Go is more powerful.
Complex structures can be built during initialization and the ordering
-issues between initialized objects in different packages are handled
+issues among initialized objects, even among different packages, are handled
correctly.
</p>
@@ -1748,7 +1863,7 @@ correctly.
Constants in Go are just that&mdash;constant.
They are created at compile time, even when defined as
locals in functions,
-and can only be numbers, strings or booleans.
+and can only be numbers, characters (runes), strings or booleans.
Because of the compile-time restriction, the expressions
that define them must be constant expressions,
evaluatable by the compiler. For instance,
@@ -1766,9 +1881,11 @@ sets of values.
</p>
{{code "/doc/progs/eff_bytesize.go" `/^type ByteSize/` `/^\)/`}}
<p>
-The ability to attach a method such as <code>String</code> to a
-type makes it possible for such values to format themselves
-automatically for printing, even as part of a general type.
+The ability to attach a method such as <code>String</code> to any
+user-defined type makes it possible for arbitrary values to format themselves
+automatically for printing.
+Although you'll see it most often applied to structs, this technique is also useful for
+scalar types such as floating-point types like <code>ByteSize</code>.
</p>
{{code "/doc/progs/eff_bytesize.go" `/^func.*ByteSize.*String/` `/^}/`}}
<p>
@@ -1777,13 +1894,13 @@ while <code>ByteSize(1e13)</code> prints as <code>9.09TB</code>.
</p>
<p>
-Note that it's fine to call <code>Sprintf</code> and friends in the
-implementation of <code>String</code> methods, but beware of
-recurring into the <code>String</code> method through the nested
-<code>Sprintf</code> call using a string format
-(<code>%s</code>, <code>%q</code>, <code>%v</code>, <code>%x</code> or <code>%X</code>).
-The <code>ByteSize</code> implementation of <code>String</code> is safe
-because it calls <code>Sprintf</code> with <code>%f</code>.
+The use here of <code>Sprintf</code>
+to implement <code>ByteSize</code>'s <code>String</code> method is safe
+(avoids recurring indefinitely) not because of a conversion but
+because it calls <code>Sprintf</code> with <code>%f</code>,
+which is not a string format: <code>Sprintf</code> will only call
+the <code>String</code> method when it wants a string, and <code>%f</code>
+wants a floating-point value.
</p>
<h3 id="variables">Variables</h3>
@@ -1837,7 +1954,8 @@ func init() {
<h3 id="pointers_vs_values">Pointers vs. Values</h3>
<p>
-Methods can be defined for any named type that is not a pointer or an interface;
+As we saw with <code>ByteSize</code>,
+methods can be defined for any named type (except a pointer or an interface);
the receiver does not have to be a struct.
</p>
<p>
@@ -1898,7 +2016,7 @@ modifications to be discarded.
</p>
<p>
By the way, the idea of using <code>Write</code> on a slice of bytes
-is implemented by <code>bytes.Buffer</code>.
+is central to the implementation of <code>bytes.Buffer</code>.
</p>
<h2 id="interfaces_and_types">Interfaces and other types</h2>
@@ -1941,10 +2059,8 @@ func (s Sequence) String() string {
}
</pre>
<p>
-The conversion causes <code>s</code> to be treated as an ordinary slice
-and therefore receive the default formatting.
-Without the conversion, <code>Sprint</code> would find the
-<code>String</code> method of <code>Sequence</code> and recur indefinitely.
+This method is another example of the conversion technique for calling
+<code>Sprintf</code> safely from a <code>String</code> method.
Because the two types (<code>Sequence</code> and <code>[]int</code>)
are the same if we ignore the type name, it's legal to convert between them.
The conversion doesn't create a new value, it just temporarily acts
@@ -1976,6 +2092,91 @@ and <code>[]int</code>), each of which does some part of the job.
That's more unusual in practice but can be effective.
</p>
+<h3 id="interface_conversions">Interface conversions and type assertions</h3>
+
+<p>
+<a href="#type_switch">Type switches</a> are a form of conversion: they take an interface and, for
+each case in the switch, in a sense convert it to the type of that case.
+Here's a simplified version of how the code under <code>fmt.Printf</code> turns a value into
+a string using a type switch.
+If it's already a string, we want the actual string value held by the interface, while if it has a
+<code>String</code> method we want the result of calling the method.
+</p>
+
+<pre>
+type Stringer interface {
+ String() string
+}
+
+var value interface{} // Value provided by caller.
+switch str := value.(type) {
+case string:
+ return str
+case Stringer:
+ return str.String()
+}
+</pre>
+
+<p>
+The first case finds a concrete value; the second converts the interface into another interface.
+It's perfectly fine to mix types this way.
+</p>
+
+<p>
+What if there's only one type we care about? If we know the value holds a <code>string</code>
+and we just want to extract it?
+A one-case type switch would do, but so would a <em>type assertion</em>.
+A type assertion takes an interface value and extracts from it a value of the specified explicit type.
+The syntax borrows from the clause opening a type switch, but with an explicit
+type rather than the <code>type</code> keyword:
+
+<pre>
+value.(typeName)
+</pre>
+
+<p>
+and the result is a new value with the static type <code>typeName</code>.
+That type must either be the concrete type held by the interface, or a second interface
+type that the value can be converted to.
+To extract the string we know is in the value, we could write:
+</p>
+
+<pre>
+str := value.(string)
+</pre>
+
+<p>
+But if it turns out that the value does not contain a string, the program will crash with a run-time error.
+To guard against that, use the "comma, ok" idiom to test, safely, whether the value is a string:
+</p>
+
+<pre>
+str, ok := value.(string)
+if ok {
+ fmt.Printf("string value is: %q\n", str)
+} else {
+ fmt.Printf("value is not a string\n")
+}
+</pre>
+
+<p>
+If the type assertion fails, <code>str</code> will still exist and be of type string, but it will have
+the zero value, an empty string.
+</p>
+
+<p>
+As an illustration of the capability, here's an <code>if</code>-<code>else</code>
+statement that's equivalent to the type switch that opened this section.
+</p>
+
+<pre>
+if str, ok := value.(string); ok {
+ return str
+} else if str, ok := value.(Stringer); ok {
+ return str.String()
+}
+</pre>
+
<h3 id="generality">Generality</h3>
<p>
If a type exists only to implement an interface
@@ -2133,9 +2334,7 @@ It's easy to write a function to print the arguments.
</p>
<pre>
func ArgServer() {
- for _, s := range os.Args {
- fmt.Println(s)
- }
+ fmt.Println(os.Args)
}
</pre>
<p>
@@ -2171,9 +2370,7 @@ to have the right signature.
<pre>
// Argument server.
func ArgServer(w http.ResponseWriter, req *http.Request) {
- for _, s := range os.Args {
- fmt.Fprintln(w, s)
- }
+ fmt.Fprintln(w, os.Args)
}
</pre>
<p>
@@ -2202,6 +2399,196 @@ a channel, and a function, all because interfaces are just sets of
methods, which can be defined for (almost) any type.
</p>
+<h2 id="blank">The blank identifier</h2>
+
+<p>
+We've mentioned the blank identifier a couple of times now, in the context of
+<a href="#for"><code>for</code> <code>range</code> loops</a>
+and <a href="#maps">maps</a>.
+The blank identifier can be assigned or declared with any value of any type, with the
+value discarded harmlessly.
+It's a bit like writing to the Unix <code>/dev/null</code> file:
+it represents a write-only value
+to be used as a place-holder
+where a variable is needed but the actual value is irrelevant.
+It has uses beyond those we've seen already.
+</p>
+
+<h3 id="blank_assign">The blank identifier in multiple assignment</h3>
+
+<p>
+The use of a blank identifier in a <code>for</code> <code>range</code> loop is a
+special case of a general situation: multiple assignment.
+<p>
+If an assignment requires multiple values on the left side,
+but one of the values will not be used by the program,
+a blank identifier on the left-hand-side of
+the assignment avoids the need
+to create a dummy variable and makes it clear that the
+value is to be discarded.
+For instance, when calling a function that returns
+a value and an error, but only the error is important,
+use the blank identifier to discard the irrelevant value.
+</p>
+
+<pre>
+if _, err := os.Stat(path); os.IsNotExist(err) {
+ fmt.Printf("%s does not exist\n", path)
+}
+</pre>
+
+<p>
+Occasionally you'll see code that discards the error value in order
+to ignore the error; this is terrible practice. Always check error returns;
+they're provided for a reason.
+</p>
+
+<pre>
+// Bad! This code will crash if path does not exist.
+fi, _ := os.Stat(path)
+if fi.IsDir() {
+ fmt.Printf("%s is a directory\n", path)
+}
+</pre>
+
+<h3 id="blank_unused">Unused imports and variables</h3>
+
+<p>
+It is an error to import a package or to declare a variable without using it.
+Unused imports bloat the program and slow compilation,
+while a variable that is initialized but not used is at least
+a wasted computation and perhaps indicative of a
+larger bug.
+When a program is under active development, however,
+unused imports and variables often arise and it can
+be annoying to delete them just to have the compilation proceed,
+only to have them be needed again later.
+The blank identifier provides a workaround.
+</p>
+<p>
+This half-written program is has two unused imports
+(<code>fmt</code> and <code>io</code>)
+and an unused variable (<code>fd</code>),
+so it will not compile, but it would be nice to see if the
+code so far is correct.
+</p>
+{{code "/doc/progs/eff_unused1.go" `/package/` `$`}}
+<p>
+To silence complaints about the unused imports, use a
+blank identifier to refer to a symbol from the imported package.
+Similarly, assigning the unused variable <code>fd</code>
+to the blank identifier will silence the unused variable error.
+This version of the program does compile.
+</p>
+{{code "/doc/progs/eff_unused2.go" `/package/` `$`}}
+
+<p>
+By convention, the global declarations to silence import errors
+should come right after the imports and be commented,
+both to make them easy to find and as a reminder to clean things up later.
+</p>
+
+<h3 id="blank_import">Import for side effect</h3>
+
+<p>
+An unused import like <code>fmt</code> or <code>io</code> in the
+previous example should eventually be used or removed:
+blank assignments identify code as a work in progress.
+But sometimes it is useful to import a package only for its
+side effects, without any explicit use.
+For example, during its <code>init</code> function,
+the <code><a href="/pkg/net/http/pprof/">net/http/pprof</a></code>
+package registers HTTP handlers that provide
+debugging information. It has an exported API, but
+most clients need only the handler registration and
+access the data through a web page.
+To import the package only for its side effects, rename the package
+to the blank identifier:
+</p>
+<pre>
+import _ "net/http/pprof"
+</pre>
+<p>
+This form of import makes clear that the package is being
+imported for its side effects, because there is no other possible
+use of the package: in this file, it doesn't have a name.
+(If it did, and we didn't use that name, the compiler would reject the program.)
+</p>
+
+<h3 id="blank_implements">Interface checks</h3>
+
+<p>
+As we saw in the discussion of <a href="#interfaces_and_types">interfaces</a> above,
+a type need not declare explicitly that it implements an interface.
+Instead, a type implements the interface just by implementing the interface's methods.
+In practice, most interface conversions are static and therefore checked at compile time.
+For example, passing an <code>*os.File</code> to a function
+expecting an <code>io.Reader</code> will not compile unless
+<code>*os.File</code> implements the <code>io.Reader</code> interface.
+</p>
+
+<p>
+Some interface checks do happen at run-time, though.
+One instance is in the <code><a href="/pkg/encoding/json/">encoding/json</a></code>
+package, which defines a <code><a href="/pkg/encoding/json/#Marshaler">Marshaler</a></code>
+interface. When the JSON encoder receives a value that implements that interface,
+the encoder invokes the value's marshaling method to convert it to JSON
+instead of doing the standard conversion.
+The encoder checks this property at run time with a <a href="interface_conversions">type assertion</a> like:
+</p>
+
+<pre>
+m, ok := val.(json.Marshaler)
+</pre>
+
+<p>
+If it's necessary only to ask whether a type implements an interface, without
+actually using the interface itself, perhaps as part of an error check, use the blank
+identifier to ignore the type-asserted value:
+</p>
+
+<pre>
+if _, ok := val.(json.Marshaler); ok {
+ fmt.Printf("value %v of type %T implements json.Marshaler\n", val, val)
+}
+</pre>
+
+<p>
+One place this situation arises is when it is necessary to guarantee within the package implementing the type that
+it it actually satisfies the interface.
+If a type—for example,
+<code><a href="/pkg/encoding/json/#RawMessage">json.RawMessage</a></code>—needs
+a custom its JSON representation, it should implement
+<code>json.Marshaler</code>, but there are no static conversions that would
+cause the compiler to verify this automatically.
+If the type inadvertently fails to satisfy the interface, the JSON encoder will still work,
+but will not use the custom implementation.
+To guarantee that the implementation is correct,
+a global declaration using the blank identifier can be used in the package:
+</p>
+<pre>
+var _ json.Marshaler = (*RawMessage)(nil)
+</pre>
+<p>
+In this declaration, the assignment involving a conversion of a
+<code>*RawMessage</code> to a <code>Marshaler</code>
+requires that <code>*RawMessage</code> implements <code>Marshaler</code>,
+and that property will be checked at compile time.
+Should the <code>json.Marshaler</code> interface change, this package
+will no longer compile and we will be on notice that it needs to be updated.
+</p>
+
+<p>
+The appearance of the blank identifier in this construct indicates that
+the declaration exists only for the type checking,
+not to create a variable.
+Don't do this for every type that satisfies an interface, though.
+By convention, such declarations are only used
+when there are no static conversions already present in the code,
+which is a rare event.
+</p>
+
+
<h2 id="embedding">Embedding</h2>
<p>
@@ -2328,8 +2715,8 @@ log to the <code>Job</code>:
job.Log("starting now...")
</pre>
<p>
-The <code>Logger</code> is a regular field of the struct and we can initialize
-it in the usual way with a constructor,
+The <code>Logger</code> is a regular field of the <code>Job</code> struct,
+so we can initialize it in the usual way inside the constructor for <code>Job</code>, like this,
</p>
<pre>
func NewJob(command string, logger *log.Logger) *Job {
@@ -2344,10 +2731,12 @@ job := &amp;Job{command, log.New(os.Stderr, "Job: ", log.Ldate)}
</pre>
<p>
If we need to refer to an embedded field directly, the type name of the field,
-ignoring the package qualifier, serves as a field name. If we needed to access the
+ignoring the package qualifier, serves as a field name, as it did
+in the <code>Read</code> method of our <code>ReaderWriter</code> struct.
+Here, if we needed to access the
<code>*log.Logger</code> of a <code>Job</code> variable <code>job</code>,
-we would write <code>job.Logger</code>.
-This would be useful if we wanted to refine the methods of <code>Logger</code>.
+we would write <code>job.Logger</code>,
+which would be useful if we wanted to refine the methods of <code>Logger</code>.
</p>
<pre>
func (job *Job) Logf(format string, args ...interface{}) {
@@ -2463,7 +2852,8 @@ completion. For that, we need channels.
<h3 id="channels">Channels</h3>
<p>
-Like maps, channels are a reference type and are allocated with <code>make</code>.
+Like maps, channels are allocated with <code>make</code>, and
+the resulting value acts as a reference to an underlying data structure.
If an optional integer parameter is provided, it sets the buffer size for the channel.
The default is zero, for an unbuffered or synchronous channel.
</p>
@@ -2473,7 +2863,7 @@ cj := make(chan int, 0) // unbuffered channel of integers
cs := make(chan *os.File, 100) // buffered channel of pointers to Files
</pre>
<p>
-Channels combine communication&mdash;the exchange of a value&mdash;with
+Unbuffered channels combine communication&mdash;the exchange of a value&mdash;with
synchronization&mdash;guaranteeing that two calculations (goroutines) are in
a known state.
</p>
@@ -2503,18 +2893,26 @@ means waiting until some receiver has retrieved a value.
<p>
A buffered channel can be used like a semaphore, for instance to
limit throughput. In this example, incoming requests are passed
-to <code>handle</code>, which sends a value into the channel, processes
-the request, and then receives a value from the channel.
+to <code>handle</code>, which receives a value from the channel, processes
+the request, and then sends a value back to the channel
+to ready the "semaphore" for the next consumer.
The capacity of the channel buffer limits the number of
-simultaneous calls to <code>process</code>.
+simultaneous calls to <code>process</code>,
+so during initialization we prime the channel by filling it to capacity.
</p>
<pre>
var sem = make(chan int, MaxOutstanding)
func handle(r *Request) {
- sem &lt;- 1 // Wait for active queue to drain.
- process(r) // May take a long time.
- &lt;-sem // Done; enable next request to run.
+ &lt;-sem // Wait for active queue to drain.
+ process(r) // May take a long time.
+ sem &lt;- 1 // Done; enable next request to run.
+}
+
+func init() {
+ for i := 0; i < MaxOutstanding; i++ {
+ sem &lt;- 1
+ }
}
func Serve(queue chan *Request) {
@@ -2524,8 +2922,37 @@ func Serve(queue chan *Request) {
}
}
</pre>
+
+<p>
+Because data synchronization occurs on a receive from a channel
+(that is, the send "happens before" the receive; see
+<a href="/ref/mem">The Go Memory Model</a>),
+acquisition of the semaphore must be on a channel receive, not a send.
+</p>
+
+<p>
+This design has a problem, though: <code>Serve</code>
+creates a new goroutine for
+every incoming request, even though only <code>MaxOutstanding</code>
+of them can run at any moment.
+As a result, the program can consume unlimited resources if the requests come in too fast.
+We can address that deficiency by changing <code>Serve</code> to
+gate the creation of the goroutines.
+</p>
+
+<pre>
+func Serve(queue chan *Request) {
+ for req := range queue {
+ &lt;-sem
+ go func() {
+ process(req)
+ sem &lt;- 1
+ }
+ }
+}</pre>
+
<p>
-Here's the same idea implemented by starting a fixed
+Another solution that manages resources well is to start a fixed
number of <code>handle</code> goroutines all reading from the request
channel.
The number of goroutines limits the number of simultaneous
@@ -2534,6 +2961,7 @@ This <code>Serve</code> function also accepts a channel on which
it will be told to exit; after launching the goroutines it blocks
receiving from that channel.
</p>
+
<pre>
func handle(queue chan *Request) {
for r := range queue {
@@ -2669,6 +3097,17 @@ of logical CPUs on the local machine.
Again, this requirement is expected to be retired as the scheduling and run-time improve.
</p>
+<p>
+Be sure not to confuse the ideas of concurrency—structuring a program
+as independently executing components—and parallelism—executing
+calculations in parallel for efficiency on multiple CPUs.
+Although the concurrency features of Go can make some problems easy
+to structure as parallel computations, Go is a concurrent language,
+not a parallel one, and not all parallelization problems fit Go's model.
+For a discussion of the distinction, see the talk cited in
+<a href="http://blog.golang.org/2013/01/concurrency-is-not-parallelism.html">this
+blog post</a>.
+
<h3 id="leaky_buffer">A leaky buffer</h3>
<p>
@@ -2785,7 +3224,7 @@ it is much more informative than the plain
<p>
When feasible, error strings should identify their origin, such as by having
-a prefix naming the package that generated the error. For example, in package
+a prefix naming the operation or package that generated the error. For example, in package
<code>image</code>, the string representation for a decoding error due to an
unknown format is "image: unknown format".
</p>
@@ -2813,11 +3252,8 @@ for try := 0; try &lt; 2; try++ {
</pre>
<p>
-The second <code>if</code> statement here is idiomatic Go.
-The type assertion <code>err.(*os.PathError)</code> is
-checked with the "comma ok" idiom (mentioned <a href="#maps">earlier</a>
-in the context of examining maps).
-If the type assertion fails, <code>ok</code> will be false, and <code>e</code>
+The second <code>if</code> statement here is another <a href="#interface_conversion">type assertion</a>.
+If it fails, <code>ok</code> will be false, and <code>e</code>
will be <code>nil</code>.
If it succeeds, <code>ok</code> will be true, which means the
error was of type <code>*os.PathError</code>, and then so is <code>e</code>,
@@ -2840,9 +3276,7 @@ that in effect creates a run-time error that will stop the program
(but see the next section). The function takes a single argument
of arbitrary type&mdash;often a string&mdash;to be printed as the
program dies. It's also a way to indicate that something impossible has
-happened, such as exiting an infinite loop. In fact, the compiler
-recognizes a <code>panic</code> at the end of a function and
-suppresses the usual check for a <code>return</code> statement.
+happened, such as exiting an infinite loop.
</p>
@@ -2944,7 +3378,7 @@ With our recovery pattern in place, the <code>do</code>
function (and anything it calls) can get out of any bad situation
cleanly by calling <code>panic</code>. We can use that idea to
simplify error handling in complex software. Let's look at an
-idealized excerpt from the <code>regexp</code> package, which reports
+idealized version of a <code>regexp</code> package, which reports
parsing errors by calling <code>panic</code> with a local
error type. Here's the definition of <code>Error</code>,
an <code>error</code> method, and the <code>Compile</code> function.
@@ -2985,18 +3419,27 @@ to <code>err</code>, that the problem was a parse error by asserting
that it has the local type <code>Error</code>.
If it does not, the type assertion will fail, causing a run-time error
that continues the stack unwinding as though nothing had interrupted
-it. This check means that if something unexpected happens, such
+it.
+This check means that if something unexpected happens, such
as an index out of bounds, the code will fail even though we
are using <code>panic</code> and <code>recover</code> to handle
-user-triggered errors.
+parse errors.
</p>
<p>
-With error handling in place, the <code>error</code> method
+With error handling in place, the <code>error</code> method (because it's a
+method bound to a type, it's fine, even natural, for it to have the same name
+as the builtin <code>error</code> type)
makes it easy to report parse errors without worrying about unwinding
-the parse stack by hand.
+the parse stack by hand:
</p>
+<pre>
+if pos==0 {
+ re.error("'*' illegal at start of expression")
+}
+</pre>
+
<p>
Useful though this pattern is, it should be used only within a package.
<code>Parse</code> turns its internal <code>panic</code> calls into
@@ -3015,155 +3458,6 @@ filter unexpected problems and re-panic with the original error.
That's left as an exercise for the reader.
</p>
-<h2 id="blank">Blank identifier</h2>
-
-<p>
-Go defines a special identifier <code>_</code>, called the <i>blank identifier</i>.
-The blank identifier can be used in a declaration to avoid
-declaring a name, and it can be used in an assignment to discard a value.
-This definition makes it useful in a variety of contexts.
-</p>
-
-<h3 id="blank_assign">Multiple assignment</h3>
-
-<p>
-If an assignment requires multiple values on the left side,
-but one of the values will not be used by the program,
-using the blank identifier in the assignment avoids the need
-to create a dummy variable.
-We saw one example of this in the discussion of
-<a href="#for">for loops</a> above.
-</p>
-<pre>
-sum := 0
-for _, value := range array {
- sum += value
-}
-</pre>
-
-<p>
-Another common use is when calling a function that returns
-a value and an error, but only the error is important.
-</p>
-<pre>
-if _, err := os.Stat(path); os.IsNotExist(err) {
- fmt.Printf("%s does not exist\n", path)
-}
-</pre>
-
-<p>
-A final use that is more common than it should be is to
-discard the error from a function that is not expected to fail.
-This is usually a mistake: when the function does fail, the code
-will continue on and probably panic dereferencing a nil pointer.
-</p>
-<pre>
-// Always check errors: this program crashes if path does not exist.
-fi, _ := os.Stat(path)
-fmt.Printf("%s is %d bytes\n", path, fi.Size())
-</pre>
-
-<h3 id="blank_unused">Unused imports and variables</h3>
-
-<p>
-Go defines that it is an error to import a package without using it,
-or to declare a variable without using its value.
-Unused imports bloat a program and lengthen compiles unnecessarily;
-a variable that is initialized but not used is at least
-a wasted computation and perhaps indicative of a
-larger bug.
-Of course, both of these situations also arise in programs
-that are under active development, as you test and refine
-your code.
-</p>
-<p>
-For example, in this program, there are two unused imports
-(<code>fmt</code> and <code>io</code>)
-and an unused variable (<code>greeting</code>).
-</p>
-{{code "/doc/progs/unused1.go" `/package/` `$`}}
-<p>
-Top-level blank declarations referring to the packages
-will silence the unused import errors.
-By convention, these declarations should come immediately after
-the imports, as a reminder to clean things up later.
-Similarly, assigning <code>greeting</code> to a blank identifier
-will silence the unused variable error.
-</p>
-{{code "/doc/progs/unused2.go" `/package/` `$`}}
-
-<h3 id="blank_import">Import for side effect</h3>
-
-<p>
-An unused import like <code>fmt</code> or <code>io</code> in the last section
-should eventually be used or removed:
-blank assignments identify code as a work in progress.
-But sometimes it is useful to import a package only for its
-side effects, without any explicit use.
-For example, during its <code>init</code> function,
-the <code><a href="/pkg/net/http/pprof/">net/http/pprof</a></code>
-package registers HTTP handlers that provide useful
-debugging information. It has an exported API too, but
-most clients need only the handler registration.
-In this situation, it is conventional to rename the package
-to the blank identifier:
-</p>
-<pre>
-import _ "net/http/pprof"
-</pre>
-<p>
-This form of import makes clear that the package is being
-imported for its side effects, because there is no other possible
-use of the package: in this file, it doesn't have a name.
-</p>
-
-<h3 id="blank_implements">Interface checks</h3>
-
-<p>
-As we saw in the discussion of <a href="#interfaces_and_types">interfaces</a> above,
-Go does not require a type to declare explicitly that it implements an interface.
-It implements the interface by simply implementing the required methods.
-This makes Go programs more lightweight and flexible, and it can avoid
-unnecessary dependencies between packages.
-Most interface conversions are static, visible to the compiler,
-and therefore checked at compile time.
-For example, passing an <code>*os.File</code> to a function
-expecting an <code>io.Reader</code> will not compile unless
-<code>*os.File</code> implements the <code>io.Reader</code> interface.
-</p>
-<p>
-However, some types that are used only to satisfy dynamic interface checks.
-For example, the <code><a href="/pkg/encoding/json/">encoding/json</a></code>
-package defines a <code><a href="/pkg/encoding/json/#Marshaler">Marshaler</a></code>
-interface. If the JSON encoder encounters a type implementing that interface,
-the encoder will let the type convert itself to JSON instead of using the standard
-conversion.
-This check is done only at runtime, with code like:
-</p>
-<pre>
-m, ok := val.(json.Marshaler)
-</pre>
-<p>
-If a type—for example,
-<code><a href="/pkg/encoding/json/#RawMessage">json.RawMessage</a></code>—intends
-to customize its JSON representation, it should implement
-<code>json.Marshaler</code>, but there are no static conversions that would
-cause the compiler to verify this automatically.
-A declaration can be used to add such a check:
-</p>
-<pre>
-var _ json.Marshaler = (*RawMessage)(nil)
-</pre>
-<p>
-As part of type-checking this static assignment of a
-<code>*RawMessage</code> to a <code>Marshaler</code>,
-the Go compiler will require that <code>*RawMessage</code> implements <code>Marshaler</code>.
-Using the blank identifier here indicates that
-the declaration exists only for the type checking,
-not to create a variable.
-Conventionally, such declarations are used only when there are
-no static conversions already present in the code.
-</p>
<h2 id="web_server">A web server</h2>
diff --git a/doc/go1.1.html b/doc/go1.1.html
index ae0a09939..f1d490f41 100644
--- a/doc/go1.1.html
+++ b/doc/go1.1.html
@@ -12,12 +12,19 @@ TODO
<h2 id="language">Changes to the language</h2>
-TODO
+<p>
+<a href="/doc/go1compat.html">The Go compatibility document</a> promises
+that programs written to the Go 1 language specification will continue to operate,
+and those promises are maintained.
+In the interest of firming up the specification, though, there are
+details about some error cases that have been clarified.
+There are also some new language features.
+</p>
<h3 id="divzero">Integer division by zero</h3>
<p>
-In Go 1, integer division by a constant zero produced a runtime panic:
+In Go 1, integer division by a constant zero produced a run-time panic:
</p>
<pre>
@@ -30,15 +37,93 @@ func f(x int) int {
In Go 1.1, an integer division by constant zero is not a legal program, so it is a compile-time error.
</p>
+<h3 id="unicode_literals">Surrogates in Unicode literals</h3>
-<h2 id="impl">Changes to the implementations and tools</h2>
+<p>
+The definition of string and rune literals has been refined to exclude surrogate halves from the
+set of valid Unicode code points.
+See the <a href="#unicode">Unicode</a> section for more information.
+</p>
-TODO: more
+<h3 id="method_values">Method values</h3>
-<h3 id="gc-flag">Command-line flag parsing</h3>
+<p>
+Go 1.1 now implements
+<a href="/ref/spec#Method_values">method values</a>,
+which are functions that have been bound to a specific receiver value.
+For instance, given a
+<a href="/pkg/bufio/#Writer"><code>Writer</code></a>
+value <code>w</code>,
+the expression
+<code>w.Write</code>,
+a method value, is a function that will always write to <code>w</code>; it is equivalent to
+a function literal closing over <code>w</code>:
+</p>
+
+<pre>
+func (p []byte) (n int, err error) {
+ return w.Write(n, err)
+}
+</pre>
<p>
-In the gc toolchain, the compilers and linkers now use the
+Method values are distinct from method expressions, which generate functions
+from methods of a given type; the method expression <code>(*bufio.Writer).Write</code>
+is equivalent to a function with an extra first argument, a receiver of type
+<code>(*bufio.Writer)</code>:
+</p>
+
+<pre>
+func (w *bufio.Writer, p []byte) (n int, err error) {
+ return w.Write(n, err)
+}
+</pre>
+
+<p>
+<em>Updating</em>: No existing code is affected; the change is strictly backward-compatible.
+</p>
+
+<h3 id="return">Return requirements</h3>
+
+<p>
+Before Go 1.1, a function that returned a value needed an explicit "return"
+or call to <code>panic</code> at
+the end of the function; this was a simple way to make the programmer
+be explicit about the meaning of the function. But there are many cases
+where a final "return" is clearly unnecessary, such as a function with
+only an infinite "for" loop.
+</p>
+
+<p>
+In Go 1.1, the rule about final "return" statements is more permissive.
+It introduces the concept of a
+<a href="/ref/spec/#Terminating_statements"><em>terminating statement</em></a>,
+a statement that is guaranteed to be the last one a function executes.
+Examples include
+"for" loops with no condition and "if-else"
+statements in which each half ends in a "return".
+If the final statement of a function can be shown <em>syntactically</em> to
+be a terminating statement, no final "return" statement is needed.
+</p>
+
+<p>
+Note that the rule is purely syntactic: it pays no attention to the values in the
+code and therefore requires no complex analysis.
+</p>
+
+<p>
+<em>Updating</em>: The change is backward-compatible, but existing code
+with superfluous "return" statements and calls to <code>panic</code> may
+be simplified manually.
+Such code can be identified by <code>go vet</code>.
+</p>
+
+<h2 id="impl">Changes to the implementations and tools</h2>
+
+<h3 id="gc_flag">Command-line flag parsing</h3>
+
+<p>
+In the gc tool chain, the compilers and linkers now use the
same command-line flag parsing rules as the Go flag package, a departure
from the traditional Unix flag parsing. This may affect scripts that invoke
the tool directly.
@@ -50,7 +135,11 @@ For example,
<h3 id="int">Size of int on 64-bit platforms</h3>
<p>
-The language allows the implementation to choose whether the <code>int</code> type and <code>uint</code> types are 32 or 64 bits. Previous Go implementations made <code>int</code> and <code>uint</code> 32 bits on all systems. Both the gc and gccgo implementations (TODO: check that gccgo does) <a href="http://golang.org/issue/2188">now make <code>int</code> and <code>uint</code> 64 bits on 64-bit platforms such as AMD64/x86-64</a>.
+The language allows the implementation to choose whether the <code>int</code> type and
+<code>uint</code> types are 32 or 64 bits. Previous Go implementations made <code>int</code>
+and <code>uint</code> 32 bits on all systems. Both the gc and gccgo implementations
+now make
+<code>int</code> and <code>uint</code> 64 bits on 64-bit platforms such as AMD64/x86-64.
Among other things, this enables the allocation of slices with
more than 2 billion elements on 64-bit platforms.
</p>
@@ -59,7 +148,7 @@ more than 2 billion elements on 64-bit platforms.
<em>Updating</em>:
Most programs will be unaffected by this change.
Because Go does not allow implicit conversions between distinct
-<a href="/ref/spec#Numeric_types">numeric types</a>,
+<a href="/ref/spec/#Numeric_types">numeric types</a>,
no programs will stop compiling due to this change.
However, programs that contain implicit assumptions
that <code>int</code> is only 32 bits may change behavior.
@@ -72,7 +161,7 @@ i := int(x) // i is -1 on 32-bit systems, 0xffffffff on 64-bit
fmt.Println(i)
</pre>
-<p>Portable code intending 32-bit sign extension (yielding -1 on all systems)
+<p>Portable code intending 32-bit sign extension (yielding <code>-1</code> on all systems)
would instead say:
</p>
@@ -80,31 +169,100 @@ would instead say:
i := int(int32(x))
</pre>
-<h3 id="asm">Assembler</h3>
+<h3 id="unicode">Unicode</h3>
+
+<p>
+To make it possible to represent code points greater than 65535 in UTF-16,
+Unicode defines <em>surrogate halves</em>,
+a range of code points to be used only in the assembly of large values, and only in UTF-16.
+The code points in that surrogate range are illegal for any other purpose.
+In Go 1.1, this constraint is honored by the compiler, libraries, and run-time:
+a surrogate half is illegal as a rune value, when encoded as UTF-8, or when
+encoded in isolation as UTF-16.
+When encountered, for example in converting from a rune to UTF-8, it is
+treated as an encoding error and will yield the replacement rune,
+<a href="/pkg/unicode/utf8/#RuneError"><code>utf8.RuneError</code></a>,
+U+FFFD.
+</p>
+
+<p>
+This program,
+</p>
+
+<pre>
+import "fmt"
+
+func main() {
+ fmt.Printf("%+q\n", string(0xD800))
+}
+</pre>
+
+<p>
+printed <code>"\ud800"</code> in Go 1.0, but prints <code>"\ufffd"</code> in Go 1.1.
+</p>
+
+<p>
+Surrogate-half Unicode values are now illegal in rune and string constants, so constants such as
+<code>'\ud800'</code> and <code>"\ud800"</code> are now rejected by the compilers.
+When written explicitly as UTF-8 encoded bytes,
+such strings can still be created, as in <code>"\xed\xa0\x80"</code>.
+However, when such a string is decoded as a sequence of runes, as in a range loop, it will yield only <code>utf8.RuneError</code>
+values.
+</p>
+
+<p>
+The Unicode byte order marks U+FFFE and U+FEFF, encoded in UTF-8, are now permitted as the first
+character of a Go source file.
+Even though their appearance in the byte-order-free UTF-8 encoding is clearly unnecessary,
+some editors add them as a kind of "magic number" identifying a UTF-8 encoded file.
+</p>
+
+<p>
+<em>Updating</em>:
+Most programs will be unaffected by the surrogate change.
+Programs that depend on the old behavior should be modified to avoid the issue.
+The byte-order-mark change is strictly backward-compatible.
+</p>
+
+<h3 id="gc_asm">The gc assemblers</h3>
<p>
-Due to the <a href="#int">int</a> and TODO: OTHER changes,
-the placement of function arguments on the stack has changed.
+Due to the change of the <a href="#int"><code>int</code></a> to 64 bits and some other changes,
+the arrangement of function arguments on the stack has changed in the gc tool chain.
Functions written in assembly will need to be revised at least
to adjust frame pointer offsets.
</p>
-<h3 id="gotool">Changes to the go tool</h3>
+<p>
+<em>Updating</em>:
+The <code>go vet</code> command now checks that functions implemented in assembly
+match the Go function prototypes they implement.
+</p>
+
+<h3 id="gocmd">Changes to the go command</h3>
-<p>The <code>go</code> tool has acquired several improvements which are intended to improve the experience for new Go users.</p>
+<p>
+The <a href="/cmd/go/"><code>go</code></a> command has acquired several
+changes intended to improve the experience for new Go users.
+</p>
-<p>Firstly, when compiling, testing, or running Go code, the <code>go</code> tool will now give more detailed errors messages, including a list of paths searched, when a package cannot be located.
+<p>
+First, when compiling, testing, or running Go code, the <code>go</code> command will now give more detailed error messages,
+including a list of paths searched, when a package cannot be located.
</p>
<pre>
$ go build foo/quxx
can't load package: package foo/quxx: cannot find package "foo/quxx" in any of:
- /home/User/go/src/pkg/foo/quxx (from $GOROOT)
- /home/User/src/foo/quxx (from $GOPATH)
+ /home/you/go/src/pkg/foo/quxx (from $GOROOT)
+ /home/you/src/foo/quxx (from $GOPATH)
</pre>
<p>
-Secondly, the <code>go get</code> command no longer allows <code>$GOROOT</code> as the default destination when downloading package source. To use <code>go get</code> command, a valid <code>$GOPATH</code> is now required.
+Second, the <code>go get</code> command no longer allows <code>$GOROOT</code>
+as the default destination when downloading package source.
+To use the <code>go get</code>
+command, a valid <code>$GOPATH</code> is now required.
</p>
<pre>
@@ -112,7 +270,9 @@ $ GOPATH= go get code.google.com/p/foo/quxx
package code.google.com/p/foo/quxx: cannot download, $GOPATH not set. For more details see: go help gopath
</pre>
-<p>Finally, as a result of the previous change, the <code>go get</code> command will also fail when <code>$GOPATH</code> and <code>$GOROOT</code> are set to the same value.
+<p>
+Finally, as a result of the previous change, the <code>go get</code> command will also fail
+when <code>$GOPATH</code> and <code>$GOROOT</code> are set to the same value.
</p>
<pre>
@@ -121,68 +281,226 @@ warning: GOPATH set to GOROOT (/home/User/go) has no effect
package code.google.com/p/foo/quxx: cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath
</pre>
-<h3 id="gofix">Changes to go fix</h3>
+<h3 id="gotest">Changes to the go test command</h3>
<p>
-The <code>go fix</code> command no longer applies fixes to update code from
-before Go 1 to use Go 1 APIs. To update pre-Go 1 code to Go 1.1, use a Go 1.0 toolchain
+The <code>go test</code> command no longer deletes the binary when run with profiling enabled,
+to make it easier to analyze the profile.
+The implementation sets the <code>-c</code> flag automatically, so after running,
+</p>
+
+<pre>
+$ go test -cpuprofile cpuprof.out mypackage
+</pre>
+
+<p>
+the file <code>mypackage.test</code> will be left in the directory where <code>go test</code> was run.
+</p>
+
+<p>
+The <code>go test</code> command can now generate profiling information
+that reports where goroutines are blocked, that is,
+where they tend to stall waiting for an event such as a channel communication.
+The information is presented as a
+<em>blocking profile</em>
+enabled with the
+<code>-blockprofile</code>
+option of
+<code>go test</code>.
+Run <code>go help test</code> for more information.
+</p>
+
+<h3 id="gofix">Changes to the go fix command</h3>
+
+<p>
+The <a href="/cmd/fix/"><code>fix</code></a> command, usually run as
+<code>go fix</code>, no longer applies fixes to update code from
+before Go 1 to use Go 1 APIs.
+To update pre-Go 1 code to Go 1.1, use a Go 1.0 tool chain
to convert the code to Go 1.0 first.
</p>
+<h2 id="performance">Performance</h2>
+
+<p>
+TODO introduction
+</p>
+
+<ul>
+<li>TODO better code generation (inlining, ...?)</li>
+<li>TODO parallel gc</li>
+<li>TODO more precise gc</li>
+<li>TODO networking is more efficient (known to runtime)</li>
+</ul>
+
<h2 id="library">Changes to the standard library</h2>
-<h3 id="debug_elf">debug/elf</h3>
+<h3 id="bufio_scanner">bufio.Scanner</h3>
+
<p>
-Previous versions of the debug/elf package intentionally skipped over the first
-symbol in the ELF symbol table, since it is always an empty symbol. This symbol
-is no longer skipped since indexes into the symbol table returned by debug/elf,
-will be different to indexes into the original ELF symbol table. Any code that
-calls the debug/elf functions Symbols or ImportedSymbols may need to be
-adjusted to account for the additional symbol and the change in symbol offsets.
+The various routines to scan textual input in the
+<a href="/pkg/bufio/"><code>bufio</code></a>
+package,
+<a href="/pkg/bufio/#Reader.ReadBytes"><code>ReadBytes</code></a>,
+<a href="/pkg/bufio/#Reader.ReadString"><code>ReadString</code></a>
+and particularly
+<a href="/pkg/bufio/#Reader.ReadLine"><code>ReadLine</code></a>,
+are needlessly complex to use for simple purposes.
+In Go 1.1, a new type,
+<a href="/pkg/bufio/#Scanner"><code>Scanner</code></a>,
+has been added to make it easier to do simple tasks such as
+read the input as a sequence of lines or space-delimited words.
+It simplifies the problem by terminating the scan on problematic
+input such as pathologically long lines, and having a simple
+default: line-oriented input, with each line stripped of its terminator.
+Here is code to reproduce the input a line at a time:
</p>
-<h3 id="html_template">html/template</h3>
+<pre>
+scanner := bufio.NewScanner(os.Stdin)
+for scanner.Scan() {
+ fmt.Println(scanner.Text()) // Println will add back the final '\n'
+}
+if err := scanner.Err(); err != nil {
+ fmt.Fprintln(os.Stderr, "reading standard input:", err)
+}
+</pre>
<p>
-Templates using the undocumented and only partially implemented
-"noescape" feature will break: that feature was removed.
+Scanning behavior can be adjusted through a function to control subdividing the input
+(see the documentation for <a href="/pkg/bufio/#SplitFunc"><code>SplitFunc</code></a>),
+but for tough problems or the need to continue past errors, the older interface
+may still be required.
</p>
<h3 id="net">net</h3>
<p>
-The protocol-specific resolvers were formerly
-lax about the network name passed in. For example, although the documentation was clear
-that the only valid networks for <code>ResolveTCPAddr</code> are <code>"tcp"</code>,
-<code>"tcp4"</code>, and <code>"tcp6"</code>, the Go 1.0 implementation silently accepted
-any string. The Go 1.1 implementation returns an error if the network is not one of those strings.
-The same is true of the other protocol-specific resolvers <code>ResolveIPAddr</code>, <code>ResolveUDPAddr</code>, and
-<code>ResolveUnixAddr</code>.
+The protocol-specific resolvers in the <a href="/pkg/net/"><code>net</code></a> package were formerly
+lax about the network name passed in.
+Although the documentation was clear
+that the only valid networks for
+<a href="/pkg/net/#ResolveTCPAddr"><code>ResolveTCPAddr</code></a>
+are <code>"tcp"</code>,
+<code>"tcp4"</code>, and <code>"tcp6"</code>, the Go 1.0 implementation silently accepted any string.
+The Go 1.1 implementation returns an error if the network is not one of those strings.
+The same is true of the other protocol-specific resolvers <a href="/pkg/net/#ResolveIPAddr"><code>ResolveIPAddr</code></a>,
+<a href="/pkg/net/#ResolveUDPAddr"><code>ResolveUDPAddr</code></a>, and
+<a href="/pkg/net/#ResolveUnixAddr"><code>ResolveUnixAddr</code></a>.
</p>
<p>
-The previous <code>ListenUnixgram</code> returned <code>UDPConn</code> as
-arepresentation of the connection endpoint. The Go 1.1 implementation
-returns <code>UnixConn</code> to allow reading and writing
-with <code>ReadFrom</code> and <code>WriteTo</code> methods on
-the <code>UnixConn</code>.
+The previous implementation of
+<a href="/pkg/net/#ListenUnixgram"><code>ListenUnixgram</code></a>
+returned a
+<a href="/pkg/net/#UDPConn"><code>UDPConn</code></a> as
+a representation of the connection endpoint.
+The Go 1.1 implementation instead returns a
+<a href="/pkg/net/#UnixConn"><code>UnixConn</code></a>
+to allow reading and writing
+with its
+<a href="/pkg/net/#UnixConn.ReadFrom"><code>ReadFrom</code></a>
+and
+<a href="/pkg/net/#UnixConn.WriteTo"><code>WriteTo</code></a>
+methods.
+</p>
+
+<h3 id="reflect">reflect</h3>
+
+<p>
+The <a href="/pkg/reflect/"><code>reflect</code></a> package has several significant additions.
</p>
+<p>
+It is now possible to run a "select" statement using
+the <code>reflect</code> package; see the description of
+<a href="/pkg/reflect/#Select"><code>Select</code></a>
+and
+<a href="/pkg/reflect/#SelectCase"><code>SelectCase</code></a>
+for details.
+</p>
+
+<p>
+The new method
+<a href="/pkg/reflect/#Value.Convert"><code>Value.Convert</code></a>
+(or
+<a href="/pkg/reflect/#Type"><code>Type.ConvertibleTo</code></a>)
+provides functionality to execute a Go conversion or type assertion operation
+on a
+<a href="/pkg/reflect/#Value"><code>Value</code></a>
+(or test for its possibility).
+</p>
+
+<p>
+The new function
+<a href="/pkg/reflect/#MakeFunc"><code>MakeFunc</code></a>
+creates a wrapper function to make it easier to call a function with existing
+<a href="/pkg/reflect/#Value"><code>Values</code></a>,
+doing the standard Go conversions among the arguments, for instance
+to pass an actual <code>int</code> to a formal <code>interface{}</code>.
+</p>
+
+<p>
+Finally, the new functions
+<a href="/pkg/reflect/#ChanOf"><code>ChanOf</code></a>,
+<a href="/pkg/reflect/#MapOf"><code>MapOf</code></a>
+and
+<a href="/pkg/reflect/#SliceOf"><code>SliceOf</code></a>
+construct new
+<a href="/pkg/reflect/#Type"><code>Types</code></a>
+from existing types, for example to construct a the type <code>[]T</code> given
+only <code>T</code>.
+</p>
+
+
<h3 id="time">time</h3>
<p>
-On FreeBSD, Linux, NetBSD, OS X and OpenBSD, previous versions of the time package
-returned times with microsecond precision. The Go 1.1 implementation of time on these
-systems now returns times with nanosecond precision. Code may exist that expects to be
-able to store such a time in an external format with only microsecond precision,
-read it back, and recover exactly the same time instant.
-In Go 1.1 the same time will not be recovered, since the external storage
-will have discarded nanoseconds.
-To address this case, there are two new methods of time.Time, Round and Truncate,
+On FreeBSD, Linux, NetBSD, OS X and OpenBSD, previous versions of the
+<a href="/pkg/time/"><code>time</code></a> package
+returned times with microsecond precision.
+The Go 1.1 implementation on these
+systems now returns times with nanosecond precision.
+Programs that write to an external format with microsecond precision
+and read it back, expecting to recover the original value, will be affected
+by the loss of precision.
+There are two new methods of <a href="/pkg/time/#Time"><code>Time</code></a>,
+<a href="/pkg/time/#Time.Round"><code>Round</code></a>
+and
+<a href="/pkg/time/#Time.Truncate"><code>Truncate</code></a>,
that can be used to remove precision from a time before passing it to
external storage.
</p>
-<h3 id="exp_old">Exp and old subtrees moved to go.exp subrepo</h3>
+<p>
+The new method
+<a href="/pkg/time/#Time.YearDay"><code>YearDay</code></a>
+returns the one-indexed integral day number of the year specified by the time value.
+</p>
+
+<p>
+The
+<a href="/pkg/time/#Timer"><code>Timer</code></a>
+type has a new method
+<a href="/pkg/time/#Timer.Reset"><code>Reset</code></a>
+that modifies the timer to expire after a specified duration.
+</p>
+
+<p>
+Finally, the new function
+<a href="/pkg/time/#ParseInLocation"><code>ParseInLocation</code></a>
+is like the existing
+<a href="/pkg/time/#Parse"><code>Parse</code></a>
+but parses the time in the context of a location (time zone), ignoring
+time zone information in the parsed string.
+This function addresses a common source of confusion in the time API.
+</p>
+
+<p>
+<em>Updating</em>:
+Code that needs to read and write times using an external format with
+lower precision should be modified to use the new methods.
+
+<h3 id="exp_old">Exp and old subtrees moved to go.exp and go.text subrepositories</h3>
<p>
To make it easier for binary distributions to access them if desired, the <code>exp</code>
@@ -204,4 +522,300 @@ and then in Go source,
import "code.google.com/p/go.exp/ssa"
</pre>
-<h3 id="TODO">TODO</h3>
+<p>
+The old package <code>exp/norm</code> has also been moved, but to a new repository
+<code>go.text</code>, where the Unicode APIs and other text-related packages will
+be developed.
+</p>
+
+<h3 id="minor_library_changes">Minor changes to the library</h3>
+
+<p>
+The following list summarizes a number of minor changes to the library, mostly additions.
+See the relevant package documentation for more information about each change.
+</p>
+
+<ul>
+<li>
+The <a href="/pkg/bytes/"><code>bytes</code></a> package has two new functions,
+<a href="/pkg/bytes/#TrimPrefix"><code>TrimPrefix</code></a>
+and
+<a href="/pkg/bytes/#TrimSuffix"><code>TrimSuffix</code></a>,
+with self-evident properties.
+Also, the <a href="/pkg/bytes/#Buffer"><code>Buffer</code></a> type
+has a new method
+<a href="/pkg/bytes/#Buffer.Grow"><code>Grow</code></a> that
+provides some control over memory allocation inside the buffer.
+Finally, the
+<a href="/pkg/bytes/#Reader"><code>Reader</code></a> type now has a
+<a href="/pkg/strings/#Reader.WriteTo"><code>WriteTo</code></a> method
+so it implements the
+<a href="/pkg/io/#WriterTo"><code>io.WriterTo</code></a> interface.
+</li>
+
+<li>
+The <a href="/pkg/crypto/hmac/"><code>crypto/hmac</code></a> package has a new function,
+<a href="/pkg/crypto/hmac/#Equal"><code>Equal</code></a>, to compare two MACs.
+</li>
+
+<li>
+The <a href="/pkg/crypto/x509/"><code>crypto/x509</code></a> package
+now supports PEM blocks (see
+<a href="/pkg/crypto/x509/#DecryptPEMBlock"><code>DecryptPEMBlock</code></a> for instance),
+and a new function
+<a href="/pkg/crypto/x509/#ParseECPrivateKey"><code>ParseECPrivateKey</code></a> to parse elliptic curve private keys.
+</li>
+
+<li>
+The <a href="/pkg/database/sql/"><code>database/sql/</code></a> package
+has a new
+<a href="/pkg/database/sql/#DB.Ping"><code>Ping</code></a>
+method for its
+<a href="/pkg/database/sql/#DB"><code>DB</code></a>
+type that tests the health of the connection.
+</li>
+
+<li>
+The <a href="/pkg/database/sql/driver/"><code>database/sql/driver</code></a> package
+has a new
+<a href="/pkg/database/sql/driver/#Queryer"><code>Queryer</code></a>
+interface that a
+<a href="/pkg/database/sql/driver/#Conn"><code>Conn</code></a>
+may implement to improve performance.
+</li>
+
+<li>
+The <a href="/pkg/encoding/json/"><code>encoding/json</code></a> package's
+<a href="/pkg/encoding/json/#Decoder"><code>Decoder</code></a>
+has a new method
+<a href="/pkg/encoding/json/#Decoder.Reader"><code>Reader</code></a>
+to provide access to the remaining data in its buffer,
+as well as a new method
+<a href="/pkg/encoding/json/#Decoder.UseNumber"><code>UseNumber</code></a>
+to unmarshal a value into the new type
+<a href="/pkg/encoding/json/#Number"><code>Number</code></a>,
+a string, rather than a float64.
+</li>
+
+<li>
+The <a href="/pkg/encoding/xml/"><code>endoding/xml</code></a> package
+has a new function,
+<a href="/pkg/encoding/xml/#EscapeText"><code>EscapeText</code></a>,
+which writes escaped XML output,
+and a method on
+<a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a>,
+<a href="/pkg/encoding/xml/#Encoder.Indent"><code>Indent</code></a>,
+to specify indented output.
+</li>
+
+<li>
+In the <a href="/pkg/go/ast/"><code>go/ast</code></a> package, a
+new type <a href="/pkg/go/ast/#CommentMap"><code>CommentMap</code></a>
+and associated methods makes it easier to extract and process comments in Go programs.
+</li>
+
+<li>
+In the <a href="/pkg/go/doc/"><code>go/doc</code></a> package,
+the parser now keeps better track of stylized annotations such as <code>TODO(joe)</code>
+throughout the code,
+information that the <a href="/cmd/godoc/"><code>godoc</code></a>
+command can filter or present according to the value of the <code>-notes</code> flag.
+</li>
+
+<li>
+A new package, <a href="/pkg/go/format/"><code>go/format</code></a>, provides
+a convenient way for a program to access the formatting capabilities of <code>gofmt</code>.
+It has two functions,
+<a href="/pkg/go/format/#Node"><code>Node</code></a> to format a Go parser
+<a href="/pkg/go/ast/#Node"><code>Node</code></a>,
+and
+<a href="/pkg/go/format/#Source"><code>Source</code></a>
+to format arbitrary Go source code.
+</li>
+
+<li>
+The undocumented and only partially implemented "noescape" feature of the
+<a href="/pkg/html/template/">html/template</a>
+package has been removed; programs that depend on it will break.
+</li>
+
+<li>
+The <a href="/pkg/io/">io</a> package now exports the
+<a href="/pkg/io/#ByteWriter"><code>io.ByteWriter</code></a> interface to capture the common
+functionality of writing a byte at a time.
+</li>
+
+<li>
+The <a href="/pkg/log/syslog/"><code>log/syslog</code></a> package now provides better support
+for OS-specific logging features.
+</li>
+
+<li>
+The <a href="/pkg/math/big/"><code>math/big</code></a> package's
+<a href="/pkg/math/big/#Int"><code>Int</code></a> type now has
+now has methods
+<a href="/pkg/math/big/#Int.MarshalJSON"><code>MarshalJSON</code></a>
+and
+<a href="/pkg/math/big/#Int.UnmarshalJSON"><code>UnmarshalJSON</code></a>
+to convert to and from a JSON representation.
+Also,
+<a href="/pkg/math/big/#Int"><code>Int</code></a>
+can now convert directly to and from a <code>uint64</code> using
+<a href="/pkg/math/big/#Int.Uint64"><code>Uint64</code></a>
+and
+<a href="/pkg/math/big/#Int.SetUint64"><code>SetUint64</code></a>,
+while
+<a href="/pkg/math/big/#Rat"><code>Rat</code></a>
+can do the same with <code>float64</code> using
+<a href="/pkg/math/big/#Rat.Float64"><code>Float64</code></a>
+and
+<a href="/pkg/math/big/#Rat.SetFloat64"><code>SetFloat64</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/mime/multipart/"><code>mime/multipart</code></a> package
+has a new method for its
+<a href="/pkg/mime/multipart/#Writer"><code>Writer</code></a>,
+<a href="/pkg/mime/multipart/#Writer.SetBoundary"><code>SetBoundary</code></a>,
+to define the boundary separator used to package the output.
+</li>
+
+<li>
+The
+<a href="/pkg/net/"><code>net</code></a> package's
+<a href="/pkg/net/#ListenUnixgram"><code>net/ListenUnixgram</code></a>
+function has changed return types: it now returns a
+<a href="/pkg/net/#UnixConn"><code>net/UnixConn</code></a>
+rather than a
+<a href="/pkg/net/#UDPConn"><code>net/UDPConn</code></a>, which was
+clearly a mistake in Go 1.0.
+Since this API change fixes a bug, it is permitted by the Go 1 compatibility rules.
+</li>
+
+<li>
+The new <a href="/pkg/net/http/cookiejar/">net/http/cookiejar</a> package provides the basics for managing HTTP cookies.
+</li>
+
+<li> TODO:
+<code>net/http</code>: ParseTime, CloseNotifier, Request.PostFormValue, ServeMux.Handler, Transport.CancelRequest
+</li>
+
+<li> TODO:
+<code>net/mail</code>: ParseAddress, ParseAddressList
+</li>
+
+<li> TODO:
+<code>net/smtp</code>: Client.Hello
+</li>
+
+<li>
+The <a href="/pkg/net/textproto/"><code>net/textproto</code></a> package
+has two new functions,
+<a href="/pkg/net/textproto/#TrimBytes"><code>TrimBytes</code></a> and
+<a href="/pkg/net/textproto/#TrimString"><code>TrimString</code></a>,
+which do ASCII-only trimming of leading and trailing spaces.
+</li>
+
+<li> TODO:
+<code>net</code>: DialOption, DialOpt, ListenUnixgram, LookupNS, IPConn.ReadMsgIP, IPConn.WriteMsgIP, UDPConn.ReadMsgUDP, UDPConn.WriteMsgUDP, UnixConn.CloseRead, UnixConn.CloseWrite
+</li>
+
+<li>
+The new method <a href="/pkg/os/#FileMode.IsRegular"><code>os.FileMode.IsRegular</code> </a> makes it easy to ask if a file is a plain file.
+</li>
+
+<li>
+The <a href="/pkg/image/jpeg/"><code>image/jpeg</code></a> package now
+reads progressive JPEG files and handles a few more subsampling configurations.
+</li>
+
+<li>
+The <a href="/pkg/regexp/"><code>regexp</code></a> package
+now supports Unix-original leftmost-longest matches through the
+<a href="/pkg/regexp/#Regexp.Longest"><code>Regexp.Longest</code></a>
+method, while
+<a href="/pkg/regexp/#Regexp.Split"><code>Regexp.Split</code></a> slices
+strings into pieces based on separators defined by the regular expression.
+</li>
+
+<li>
+The <a href="/pkg/runtime/debug/"><code>runtime/debug</code></a> package
+has three new functions regarding memory usage.
+The <a href="/pkg/runtime/debug/#FreeOSMemory"><code>FreeOSMemory</code></a>
+function triggers a run of the garbage collector and then attempts to return unused
+memory to the operating system;
+the <a href="/pkg/runtime/debug/#ReadGCStats"><code>ReadGCStats</code></a>
+function retrieves statistics about the collector; and
+<a href="/pkg/runtime/debug/#SetGCPercent"><code>SetGCPercent</code></a>
+provides a programmatic way to control how often the collector runs,
+including disabling it altogether.
+</li>
+
+<li>
+The <a href="/pkg/sort/"><code>sort</code></a> package has a new function,
+<a href="/pkg/sort/#Reverse"><code>Reverse</code></a>.
+Wrapping the argument of a call to
+<a href="/pkg/sort/#Sort"><code>sort.Sort</code></a>
+with a call to <code>Reverse</code> causes the sort order to be reversed.
+</li>
+
+<li>
+The <a href="/pkg/strings/"><code>strings</code></a> package has two new functions,
+<a href="/pkg/strings/#TrimPrefix"><code>TrimPrefix</code></a>
+and
+<a href="/pkg/strings/#TrimSuffix"><code>TrimSuffix</code></a>
+with self-evident properties, and the the new method
+<a href="/pkg/strings/#Reader.WriteTo"><code>Reader.WriteTo</code></a> so the
+<a href="/pkg/strings/#Reader"><code>Reader</code></a>
+type now implements the
+<a href="/pkg/io/#WriterTo"><code>io.WriterTo</code></a> interface.
+</li>
+
+<li>
+The <a href="/pkg/syscall/"><code>syscall</code></a> package has received many updates to make it more inclusive of constants and system calls for each supported operating system.
+</li>
+
+<li>
+The <a href="/pkg/testing/"><code>testing</code></a> package now automates the generation of allocation
+statistics in benchmarks using the new
+<a href="/pkg/testing/#AllocsPerRun"><code>AllocsPerRun</code></a> function and the
+<a href="/pkg/testing/#BenchmarkResult.AllocsPerOp"><code>AllocsPerOp</code></a> method of
+<a href="/pkg/testing/#BenchmarkResult"><code>BenchmarkResult</code></a>.
+There is also a new
+<a href="/pkg/testing/#Verbose"><code>Verbose</code></a> function to test the state of the <code>-v</code>
+command-line flag,
+and a new
+<a href="/pkg/testing/#B.Skip"><code>Skip</code></a> method of
+<a href="/pkg/testing/#B"><code>testing.B</code></a> and
+<a href="/pkg/testing/#T"><code>testing.T</code></a>
+to simplify skipping an inappropriate test.
+</li>
+
+<li>
+In the <a href="/pkg/text/template/"><code>text/template</code></a>
+and
+<a href="/pkg/html/template/"><code>html/template</code></a> packages,
+templates can now use parentheses to group the elements of pipelines, simplifying the construction of complex pipelines.
+TODO: Link to example.
+Also, as part of the new parser, the
+<a href="/pkg/text/template/parse/#Node"><code>Node</code></a> interface got two new methods to provide
+better error reporting.
+Although this violates the Go 1 compatibility rules,
+no existing code should be affected because this interface is explicitly intended only to be used
+by the
+<a href="/pkg/text/template/"><code>text/template</code></a>
+and
+<a href="/pkg/html/template/"><code>html/template</code></a>
+packages and there are safeguards to guarantee that.
+</li>
+
+<li>
+In the <a href="/pkg/unicode/utf8/"><code>unicode/utf8</code></a> package,
+the new function <a href="/pkg/unicode/utf8/#ValidRune"><code>ValidRune</code></a> reports whether the rune is a valid Unicode code point.
+To be valid, a rune must be in range and not be a surrogate half.
+</li>
+
+<li>
+The implementation of the <a href="/pkg/unicode/"><code>unicode</code></a> package has been updated to Unicode version 6.2.0.
+</li>
+</ul>
diff --git a/doc/go_faq.html b/doc/go_faq.html
index 5c68aa7e5..3e742d9f7 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -949,6 +949,38 @@ combined with the Go project's mostly linear, non-branching use of
version control, a switch to git doesn't seem worthwhile.
</p>
+<h3 id="git_https">
+Why does "go get" use HTTPS when cloning a repository?</h3>
+
+<p>
+Companies often permit outgoing traffic only on the standard TCP ports 80 (HTTP)
+and 443 (HTTPS), blocking outgoing traffic on other ports, including TCP port 9418
+(git) and TCP port 22 (SSH).
+When using HTTPS instead of HTTP, <code>git</code> enforces certificate validation by
+default, providing protection against man-in-the-middle, eavesdropping and tampering attacks.
+The <code>go get</code> command therefore uses HTTPS for safety.
+</p>
+
+<p>
+If you use <code>git</code> and prefer to push changes through SSH using your existing key
+it's easy to work around this. For GitHub, try one of these solutions:
+</p>
+<ul>
+<li>Manually clone the repository in the expected package directory:
+<pre>
+$ cd $GOPATH/src/github.com/username
+$ git clone git@github.com:username/package.git
+</pre>
+</li>
+<li>Force <code>git push</code> to use the <code>SSH</code> protocol by appending
+these two lines to <code>~/.gitconfig</code>:
+<pre>
+[url "git@github.com:"]
+ pushInsteadOf = https://github.com/
+</pre>
+</li>
+</ul>
+
<h2 id="Pointers">Pointers and Allocation</h2>
<h3 id="pass_by_value">
@@ -974,6 +1006,57 @@ struct. If the interface value holds a pointer, copying the interface value
makes a copy of the pointer, but again not the data it points to.
</p>
+<h3 id="pointer_to_interface">
+When should I use a pointer to an interface?</h3>
+
+<p>
+Almost never. Pointers to interface values arise only in rare, tricky situations involving
+disguising an interface value's type for delayed evaluation.
+</p>
+
+<p>
+It is however a common mistake to pass a pointer to an interface value
+to a function expecting an interface. The compiler will complain about this
+error but the situation can still be confusing, because sometimes a
+<a href="#different_method_sets">pointer
+is necessary to satisfy an interface</a>.
+The insight is that although a pointer to a concrete type can satisfy
+an interface, with one exception <em>a pointer to an interface can never satisfy a interface</em>.
+</p>
+
+<p>
+Consider the variable declaration,
+</p>
+
+<pre>
+var w io.Writer
+</pre>
+
+<p>
+The printing function <code>fmt.Fprintf</code> takes as its first argument
+a value that satisfies <code>io.Writer</code>—something that implements
+the canonical <code>Write</code> method. Thus we can write
+</p>
+
+<pre>
+fmt.Fprintf(w, "hello, world\n")
+</pre>
+
+<p>
+If however we pass the address of <code>w</code>, the program will not compile.
+</p>
+
+<pre>
+fmt.Fprintf(&amp;w, "hello, world\n") // Compile-time error.
+</pre>
+
+<p>
+The one exception is that any value, even a pointer to an interface, can be assigned to
+a variable of empty interface type (<code>interface{}</code>).
+Even so, it's almost certainly a mistake if the value is a pointer to an interface;
+the result can be confusing.
+</p>
+
<h3 id="methods_on_values_or_pointers">
Should I define methods on values or pointers?</h3>
@@ -1407,7 +1490,7 @@ test cases. The standard Go library is full of illustrative examples, such as in
What compiler technology is used to build the compilers?</h3>
<p>
-<code>Gccgo</code> has a C++ front-end with a recursive descent parser coupled to the
+<code>Gccgo</code> has a front end written in C++, with a recursive descent parser coupled to the
standard GCC back end. <code>Gc</code> is written in C using
<code>yacc</code>/<code>bison</code> for the parser.
Although it's a new program, it fits in the Plan 9 C compiler suite
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 0cb9f54b1..881d16656 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of March 1, 2013",
+ "Subtitle": "Version of March 22, 2013",
"Path": "/ref/spec"
}-->
@@ -639,8 +639,8 @@ expressions</a>.
<p>
A type determines the set of values and operations specific to values of that
type. A type may be specified by a
-(possibly <a href="#Qualified_identifiers">qualified</a>) <i>type name</i>
-(§<a href="#Type_declarations">Type declarations</a>) or a <i>type literal</i>,
+(possibly <a href="#Qualified_identifiers">qualified</a>)
+<a href="#Type_declarations"><i>type name</i></a> or a <i>type literal</i>,
which composes a new type from previously declared types.
</p>
@@ -866,8 +866,8 @@ distinct arrays always represent distinct storage.
The array underlying a slice may extend past the end of the slice.
The <i>capacity</i> is a measure of that extent: it is the sum of
the length of the slice and the length of the array beyond the slice;
-a slice of length up to that capacity can be created by `slicing' a new
-one from the original slice (§<a href="#Slices">Slices</a>).
+a slice of length up to that capacity can be created by
+<a href="#Slices"><i>slicing</i></a> a new one from the original slice.
The capacity of a slice <code>a</code> can be discovered using the
built-in function <a href="#Length_and_capacity"><code>cap(a)</code></a>.
</p>
@@ -1236,8 +1236,8 @@ KeyType = Type .
</pre>
<p>
-The comparison operators <code>==</code> and <code>!=</code>
-(§<a href="#Comparison_operators">Comparison operators</a>) must be fully defined
+The <a href="#Comparison_operators">comparison operators</a>
+<code>==</code> and <code>!=</code> must be fully defined
for operands of the key type; thus the key type must not be a function, map, or
slice.
If the key type is an interface type, these
@@ -1469,12 +1469,13 @@ Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a
<h2 id="Blocks">Blocks</h2>
<p>
-A <i>block</i> is a sequence of declarations and statements within matching
-brace brackets.
+A <i>block</i> is a possibly empty sequence of declarations and statements
+within matching brace brackets.
</p>
<pre class="ebnf">
-Block = "{" { Statement ";" } "}" .
+Block = "{" StatementList "}" .
+StatementList = { Statement ";" } .
</pre>
<p>
@@ -1490,10 +1491,13 @@ In addition to explicit blocks in the source code, there are implicit blocks:
<li>Each file has a <i>file block</i> containing all Go source text
in that file.</li>
- <li>Each <code>if</code>, <code>for</code>, and <code>switch</code>
+ <li>Each <a href="#If_statements">"if"</a>,
+ <a href="#For_statements">"for"</a>, and
+ <a href="#Switch_statements">"switch"</a>
statement is considered to be in its own implicit block.</li>
- <li>Each clause in a <code>switch</code> or <code>select</code> statement
+ <li>Each clause in a <a href="#Switch_statements">"switch"</a>
+ or <a href="#Select_statements">"select"</a> statement
acts as an implicit block.</li>
</ol>
@@ -1567,8 +1571,9 @@ declarations.
<p>
Labels are declared by <a href="#Labeled_statements">labeled statements</a> and are
-used in the <code>break</code>, <code>continue</code>, and <code>goto</code>
-statements (§<a href="#Break_statements">Break statements</a>, §<a href="#Continue_statements">Continue statements</a>, §<a href="#Goto_statements">Goto statements</a>).
+used in the <a href="#Break_statements">"break"</a>,
+<a href="#Continue_statements">"continue"</a>, and
+<a href="#Goto_statements">"goto"</a> statements.
It is illegal to define a label that is never used.
In contrast to other identifiers, labels are not block scoped and do
not conflict with identifiers that are not labels. The scope of a label
@@ -1868,7 +1873,7 @@ var _, found = entries[name] // map lookup; only interested in "found"
<p>
If a list of expressions is given, the variables are initialized
-by assigning the expressions to the variables (§<a href="#Assignments">Assignments</a>)
+by <a href="#Assignments">assigning</a> the expressions to the variables
in order; all expressions must be consumed and all variables initialized from them.
Otherwise, each variable is initialized to its <a href="#The_zero_value">zero value</a>.
</p>
@@ -1935,9 +1940,11 @@ a, a := 1, 2 // illegal: double declaration of a or
<p>
Short variable declarations may appear only inside functions.
-In some contexts such as the initializers for <code>if</code>,
-<code>for</code>, or <code>switch</code> statements,
-they can be used to declare local temporary variables (§<a href="#Statements">Statements</a>).
+In some contexts such as the initializers for
+<a href="#If_statements">"if"</a>,
+<a href="#For_statements">"for"</a>, or
+<a href="#Switch_statements">"switch"</a> statements,
+they can be used to declare local temporary variables.
</p>
<h3 id="Function_declarations">Function declarations</h3>
@@ -1948,9 +1955,27 @@ to a function.
</p>
<pre class="ebnf">
-FunctionDecl = "func" FunctionName Signature [ Body ] .
+FunctionDecl = "func" FunctionName ( Function | Signature ) .
FunctionName = identifier .
-Body = Block .
+Function = Signature FunctionBody .
+FunctionBody = Block .
+</pre>
+
+<p>
+If the function's <a href="#Function_types">signature</a> declares
+result parameters, the function body's statement list must end in
+a <a href="#Terminating_statements">terminating statement</a>.
+</p>
+
+<pre>
+func findMarker(c <-chan int) int {
+ for i := range c {
+ if x := <-c; isMarker(x) {
+ return x
+ }
+ }
+ // invalid: missing return statement.
+}
</pre>
<p>
@@ -1972,13 +1997,13 @@ func flushICache(begin, end uintptr) // implemented externally
<h3 id="Method_declarations">Method declarations</h3>
<p>
-A method is a function with a <i>receiver</i>.
-A method declaration binds an identifier, the <i>method name</i>, to a method.
-It also associates the method with the receiver's <i>base type</i>.
+A method is a <a href="#Function_declarations">function</a> with a <i>receiver</i>.
+A method declaration binds an identifier, the <i>method name</i>, to a method,
+and associates the method with the receiver's <i>base type</i>.
</p>
<pre class="ebnf">
-MethodDecl = "func" Receiver MethodName Signature [ Body ] .
+MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" .
BaseTypeName = identifier .
</pre>
@@ -2185,7 +2210,7 @@ For array and slice literals the following rules apply:
</ul>
<p>
-Taking the address of a composite literal (§<a href="#Address_operators">Address operators</a>)
+<a href="#Address_operators">Taking the address</a> of a composite literal
generates a pointer to a unique instance of the literal's value.
</p>
<pre>
@@ -2284,12 +2309,11 @@ noteFrequency := map[string]float32{
<h3 id="Function_literals">Function literals</h3>
<p>
-A function literal represents an anonymous function.
-It consists of a specification of the function type and a function body.
+A function literal represents an anonymous <a href="#Function_declarations">function</a>.
</p>
<pre class="ebnf">
-FunctionLit = FunctionType Body .
+FunctionLit = "func" Function .
</pre>
<pre>
@@ -2414,8 +2438,15 @@ expression is illegal.
In all other cases, <code>x.f</code> is illegal.
</li>
<li>
-If <code>x</code> is of pointer or interface type and has the value
-<code>nil</code>, assigning to, evaluating, or calling <code>x.f</code>
+If <code>x</code> is of pointer type and has the value
+<code>nil</code> and <code>x.f</code> denotes a struct field,
+assigning to or evaluating <code>x.f</code>
+causes a <a href="#Run_time_panics">run-time panic</a>.
+</li>
+<li>
+If <code>x</code> is of interface type and has the value
+<code>nil</code>, <a href="#Calls">calling</a> or
+<a href="#Method_values">evaluating</a> the method <code>x.f</code>
causes a <a href="#Run_time_panics">run-time panic</a>.
</li>
</ol>
@@ -2503,7 +2534,8 @@ rules apply:
If <code>a</code> is not a map:
</p>
<ul>
- <li>the index <code>x</code> must be an integer value; it is <i>in range</i> if <code>0 &lt;= x &lt; len(a)</code>,
+ <li>the index <code>x</code> must be of integer type or untyped;
+ it is <i>in range</i> if <code>0 &lt;= x &lt; len(a)</code>,
otherwise it is <i>out of range</i></li>
<li>a <a href="#Constants">constant</a> index must be non-negative
and representable by a value of type <code>int</code>
@@ -2894,9 +2926,7 @@ 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 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 <code>int</code> if it cannot
-be determined from the context (for instance, if the shift expression is an
-operand in a comparison against an untyped constant).
+replaced by its left operand alone.
</p>
<pre>
@@ -2905,10 +2935,12 @@ var i = 1&lt;&lt;s // 1 has type int
var j int32 = 1&lt;&lt;s // 1 has type int32; j == 0
var k = uint64(1&lt;&lt;s) // 1 has type uint64; k == 1&lt;&lt;33
var m int = 1.0&lt;&lt;s // 1.0 has type int
-var n = 1.0&lt;&lt;s != 0 // 1.0 has type int; n == false if ints are 32bits in size
+var n = 1.0&lt;&lt;s != i // 1.0 has type int; n == false if ints are 32bits in size
var o = 1&lt;&lt;s == 2&lt;&lt;s // 1 and 2 have type int; o == true if ints are 32bits in size
var p = 1&lt;&lt;s == 1&lt;&lt;33 // illegal if ints are 32bits in size: 1 has type int, but 1&lt;&lt;33 overflows int
var u = 1.0&lt;&lt;s // illegal: 1.0 has type float64, cannot shift
+var u1 = 1.0&lt;&lt;s != 0 // illegal: 1.0 has type float64, cannot shift
+var u2 = 1&lt;&lt;s != 1.0 // illegal: 1 has type float64, cannot shift
var v float32 = 1&lt;&lt;s // illegal: 1 has type float32, cannot shift
var w int64 = 1.0&lt;&lt;33 // 1.0&lt;&lt;33 is a constant shift expression
</pre>
@@ -3080,8 +3112,8 @@ occurs is implementation-specific.
For unsigned integer values, the operations <code>+</code>,
<code>-</code>, <code>*</code>, and <code>&lt;&lt;</code> are
computed modulo 2<sup><i>n</i></sup>, where <i>n</i> is the bit width of
-the unsigned integer's type
-(§<a href="#Numeric_types">Numeric types</a>). Loosely speaking, these unsigned integer operations
+the <a href="#Numeric_types">unsigned integer</a>'s type.
+Loosely speaking, these unsigned integer operations
discard high bits upon overflow, and programs may rely on ``wrap around''.
</p>
<p>
@@ -3098,7 +3130,7 @@ not occur. For instance, it may not assume that <code>x &lt; x + 1</code> is alw
<h3 id="Comparison_operators">Comparison operators</h3>
<p>
-Comparison operators compare two operands and yield a boolean value.
+Comparison operators compare two operands and yield an untyped boolean value.
</p>
<pre class="grammar">
@@ -3158,8 +3190,8 @@ These terms and the result of the comparisons are defined as follows:
<li>
Channel values are comparable.
- Two channel values are equal if they were created by the same call to <code>make</code>
- (§<a href="#Making_slices_maps_and_channels">Making slices, maps, and channels</a>)
+ Two channel values are equal if they were created by the same call to
+ <a href="#Making_slices_maps_and_channels"><code>make</code></a>
or if both have value <code>nil</code>.
</li>
@@ -3206,20 +3238,17 @@ Comparison of pointer, channel, and interface values to <code>nil</code>
is also allowed and follows from the general rules above.
</p>
-<p>
-The result of a comparison can be assigned to any boolean type.
-If the context does not demand a specific boolean type,
-the result has type <code>bool</code>.
-</p>
-
<pre>
-type MyBool bool
+const c = 3 < 4 // c is the untyped bool constant true
+type MyBool bool
var x, y int
var (
- b1 MyBool = x == y // result of comparison has type MyBool
- b2 bool = x == y // result of comparison has type bool
- b3 = x == y // result of comparison has type bool
+ // The result of a comparison is an untyped bool.
+ // The usual assignment rules apply.
+ b3 = x == y // b3 has type bool
+ b4 bool = x == y // b4 has type bool
+ b5 MyBool = x == y // b5 has type MyBool
)
</pre>
@@ -3341,6 +3370,7 @@ type T struct {
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
+
var t T
</pre>
@@ -3426,7 +3456,8 @@ the receiver is provided as the first argument to the call.
That is, given <code>f := T.Mv</code>, <code>f</code> is invoked
as <code>f(t, 7)</code> not <code>t.f(7)</code>.
To construct a function that binds the receiver, use a
-<a href="#Function_literals">closure</a>.
+<a href="#Function_literals">function literal</a> or
+<a href="#Method_values">method value</a>.
</p>
<p>
@@ -3434,6 +3465,111 @@ It is legal to derive a function value from a method of an interface type.
The resulting function takes an explicit receiver of that interface type.
</p>
+<h3 id="Method_values">Method values</h3>
+
+<p>
+If the expression <code>x</code> has static type <code>T</code> and
+<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
+<code>x.M</code> is called a <i>method value</i>.
+The method value <code>x.M</code> is a function value that is callable
+with the same arguments as a method call of <code>x.M</code>.
+The expression <code>x</code> is evaluated and saved during the evaluation of the
+method value; the saved copy is then used as the receiver in any calls,
+which may be executed later.
+</p>
+
+<p>
+The type <code>T</code> may be an interface or non-interface type.
+</p>
+
+<p>
+As in the discussion of <a href="#Method_expressions">method expressions</a> above,
+consider a struct type <code>T</code> with two methods,
+<code>Mv</code>, whose receiver is of type <code>T</code>, and
+<code>Mp</code>, whose receiver is of type <code>*T</code>.
+</p>
+
+<pre>
+type T struct {
+ a int
+}
+func (tv T) Mv(a int) int { return 0 } // value receiver
+func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
+
+var t T
+var pt *T
+func makeT() T
+</pre>
+
+<p>
+The expression
+</p>
+
+<pre>
+t.Mv
+</pre>
+
+<p>
+yields a function value of type
+</p>
+
+<pre>
+func(int) int
+</pre>
+
+<p>
+These two invocations are equivalent:
+</p>
+
+<pre>
+t.Mv(7)
+f := t.Mv; f(7)
+</pre>
+
+<p>
+Similarly, the expression
+</p>
+
+<pre>
+pt.Mp
+</pre>
+
+<p>
+yields a function value of type
+</p>
+
+<pre>
+func(float32) float32
+</pre>
+
+<p>
+As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
+using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
+</p>
+
+<p>
+As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
+using an addressable value will automatically take the address of that value: <code>t.Mv</code> is equivalent to <code>(&amp;t).Mv</code>.
+</p>
+
+<pre>
+f := t.Mv; f(7) // like t.Mv(7)
+f := pt.Mp; f(7) // like pt.Mp(7)
+f := pt.Mv; f(7) // like (*pt).Mv(7)
+f := t.Mp; f(7) // like (&amp;t).Mp(7)
+f := makeT().Mp // invalid: result of makeT() is not addressable
+</pre>
+
+<p>
+Although the examples above use non-interface types, it is also legal to create a method value
+from a value of interface type.
+</p>
+
+<pre>
+var i interface { M(int) } = myVal
+f := i.M; f(7) // like i.M(7)
+</pre>
+
<h3 id="Conversions">Conversions</h3>
<p>
@@ -3484,8 +3620,8 @@ type <code>T</code> in any of these cases:
<li>
<code>x</code> is an integer constant and <code>T</code> is a
<a href="#String_types">string type</a>.
- The same rule as for non-constant <code>x</code> applies in this case
- (§<a href="#Conversions_to_and_from_a_string_type">Conversions to and from a string type</a>).
+ The <a href="#Conversions_to_and_from_a_string_type">same rule</a>
+ as for non-constant <code>x</code> applies in this case.
</li>
</ul>
@@ -3683,8 +3819,8 @@ A constant <a href="#Comparison_operators">comparison</a> always yields
an untyped boolean constant. If the left operand of a constant
<a href="#Operators">shift expression</a> is an untyped constant, the
result is an integer constant; otherwise it is a constant of the same
-type as the left operand, which must be of integer type
-(§<a href="#Arithmetic_operators">Arithmetic operators</a>).
+type as the left operand, which must be of
+<a href="#Numeric_types">integer type</a>.
Applying all other operators to untyped constants results in an untyped
constant of the same kind (that is, a boolean, integer, floating-point,
complex, or string constant).
@@ -3843,6 +3979,84 @@ Statement =
SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
</pre>
+<h3 id="Terminating_statements">Terminating statements</h3>
+
+<p>
+A terminating statement is one of the following:
+</p>
+
+<ol>
+<li>
+ A <a href="#Return_statements">"return"</a> or
+ <a href="#Goto_statements">"goto"</a> statement.
+ <!-- ul below only for regular layout -->
+ <ul> </ul>
+</li>
+
+<li>
+ A call to the built-in function
+ <a href="#Handling_panics"><code>panic</code></a>.
+ <!-- ul below only for regular layout -->
+ <ul> </ul>
+</li>
+
+<li>
+ A <a href="#Blocks">block</a> in which the statement list ends in a terminating statement.
+ <!-- ul below only for regular layout -->
+ <ul> </ul>
+</li>
+
+<li>
+ An <a href="#If_statements">"if" statement</a> in which:
+ <ul>
+ <li>the "else" branch is present, and</li>
+ <li>both branches are terminating statements.</li>
+ </ul>
+</li>
+
+<li>
+ A <a href="#For_statements">"for" statement</a> in which:
+ <ul>
+ <li>there are no "break" statements referring to the "for" statement, and</li>
+ <li>the loop condition is absent.</li>
+ </ul>
+</li>
+
+<li>
+ A <a href="#Switch_statements">"switch" statement</a> in which:
+ <ul>
+ <li>there are no "break" statements referring to the "switch" statement,</li>
+ <li>there is a default case, and</li>
+ <li>the statement lists in each case, including the default, end in a terminating
+ statement, or a possibly labeled <a href="#Fallthrough_statements">"fallthrough"
+ statement</a>.</li>
+ </ul>
+</li>
+
+<li>
+ A <a href="#Select_statements">"select" statement</a> in which:
+ <ul>
+ <li>there are no "break" statements referring to the "select" statement, and</li>
+ <li>the statement lists in each case, including the default if present,
+ end in a terminating statement.</li>
+ </ul>
+</li>
+
+<li>
+ A <a href="#Labeled_statements">labeled statement</a> labeling
+ a terminating statement.
+</li>
+</ol>
+
+<p>
+All other statements are not terminating.
+</p>
+
+<p>
+A <a href="#Blocks">statement list</a> ends in a terminating statement if the list
+is not empty and its final statement is terminating.
+</p>
+
<h3 id="Empty_statements">Empty statements</h3>
@@ -4149,7 +4363,7 @@ the expression <code>true</code>.
<pre class="ebnf">
ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
-ExprCaseClause = ExprSwitchCase ":" { Statement ";" } .
+ExprCaseClause = ExprSwitchCase ":" StatementList .
ExprSwitchCase = "case" ExpressionList | "default" .
</pre>
@@ -4213,7 +4427,7 @@ expression <code>x</code>. As with type assertions, <code>x</code> must be of
<pre class="ebnf">
TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
-TypeCaseClause = TypeSwitchCase ":" { Statement ";" } .
+TypeCaseClause = TypeSwitchCase ":" StatementList .
TypeSwitchCase = "case" TypeList | "default" .
TypeList = Type { "," Type } .
</pre>
@@ -4229,8 +4443,7 @@ in the TypeSwitchGuard.
</p>
<p>
-The type in a case may be <code>nil</code>
-(§<a href="#Predeclared_identifiers">Predeclared identifiers</a>);
+The type in a case may be <a href="#Predeclared_identifiers"><code>nil</code></a>;
that case is used when the expression in the TypeSwitchGuard
is a <code>nil</code> interface value.
</p>
@@ -4382,8 +4595,8 @@ the range clause is equivalent to the same clause with only the first variable p
The range expression is evaluated once before beginning the loop,
with one exception. If the range expression is an array or a pointer to an array
and only the first iteration value is present, only the range expression's
-length is evaluated; if that length is constant by definition
-(see §<a href="#Length_and_capacity">Length and capacity</a>),
+length is evaluated; if that length is constant
+<a href="#Length_and_capacity">by definition</a>,
the range expression itself will not be evaluated.
</p>
@@ -4536,7 +4749,7 @@ cases all referring to communication operations.
<pre class="ebnf">
SelectStmt = "select" "{" { CommClause } "}" .
-CommClause = CommCase ":" { Statement ";" } .
+CommClause = CommCase ":" StatementList .
CommCase = "case" ( SendStmt | RecvStmt ) | "default" .
RecvStmt = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr .
RecvExpr = Expression .
@@ -4661,7 +4874,7 @@ func complexF2() (re float64, im float64) {
</pre>
</li>
<li>The expression list may be empty if the function's result
- type specifies names for its result parameters (§<a href="#Function_types">Function types</a>).
+ type specifies names for its <a href="#Function_types">result parameters</a>.
The result parameters act as ordinary local variables
and the function may assign values to them as necessary.
The "return" statement returns the values of these variables.
@@ -4681,8 +4894,8 @@ func (devnull) Write(p []byte) (n int, _ error) {
</ol>
<p>
-Regardless of how they are declared, all the result values are initialized to the zero
-values for their type (§<a href="#The_zero_value">The zero value</a>) upon entry to the
+Regardless of how they are declared, all the result values are initialized to
+the <a href="#The_zero_value">zero values</a> for their type upon entry to the
function. A "return" statement that specifies results sets the result parameters before
any deferred functions are executed.
</p>
@@ -4699,7 +4912,9 @@ TODO: Define when return is required.<br />
<p>
A "break" statement terminates execution of the innermost
-"for", "switch" or "select" statement.
+<a href="#For_statements">"for"</a>,
+<a href="#Switch_statements">"switch"</a>, or
+<a href="#Select_statements">"select"</a> statement.
</p>
<pre class="ebnf">
@@ -4708,10 +4923,8 @@ BreakStmt = "break" [ Label ] .
<p>
If there is a label, it must be that of an enclosing
-"for", "switch" or "select" statement, and that is the one whose execution
-terminates
-(§<a href="#For_statements">For statements</a>, §<a href="#Switch_statements">Switch statements</a>,
-§<a href="#Select_statements">Select statements</a>).
+"for", "switch", or "select" statement,
+and that is the one whose execution terminates.
</p>
<pre>
@@ -4728,7 +4941,7 @@ L:
<p>
A "continue" statement begins the next iteration of the
-innermost "for" loop at its post statement (§<a href="#For_statements">For statements</a>).
+innermost <a href="#For_statements">"for" loop</a> at its post statement.
</p>
<pre class="ebnf">
@@ -4738,8 +4951,7 @@ ContinueStmt = "continue" [ Label ] .
<p>
If there is a label, it must be that of an enclosing
"for" statement, and that is the one whose execution
-advances
-(§<a href="#For_statements">For statements</a>).
+advances.
</p>
<h3 id="Goto_statements">Goto statements</h3>
@@ -4958,8 +5170,8 @@ constant and <code>s</code> is evaluated.
<p>
The built-in function <code>new</code> takes a type <code>T</code> and
returns a value of type <code>*T</code>.
-The memory is initialized as described in the section on initial values
-(§<a href="#The_zero_value">The zero value</a>).
+The memory is initialized as described in the section on
+<a href="#The_zero_value">initial values</a>.
</p>
<pre class="grammar">
@@ -4991,8 +5203,8 @@ The built-in function <code>make</code> takes a type <code>T</code>,
which must be a slice, map or channel type,
optionally followed by a type-specific list of expressions.
It returns a value of type <code>T</code> (not <code>*T</code>).
-The memory is initialized as described in the section on initial values
-(§<a href="#The_zero_value">The zero value</a>).
+The memory is initialized as described in the section on
+<a href="#The_zero_value">initial values</a>.
</p>
<pre class="grammar">
@@ -5010,7 +5222,7 @@ make(T, n) channel asynchronous channel of type T, buffer size n
<p>
-The size arguments <code>n</code> and <code>m</code> must be integer values.
+The size arguments <code>n</code> and <code>m</code> must be of integer type or untyped.
A <a href="#Constants">constant</a> size argument must be non-negative and
representable by a value of type <code>int</code>.
If both <code>n</code> and <code>m</code> are provided and are constant, then
@@ -5184,14 +5396,14 @@ func recover() interface{}
</pre>
<p>
-A <code>panic</code> call in a function <code>F</code> terminates the execution
-of <code>F</code>.
+While executing a function <code>F</code>,
+an explicit call to <code>panic</code> or a <a href="#Run_time_panics">run-time panic</a>
+terminates the execution of <code>F</code>.
Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
-are executed before <code>F</code> returns to its caller. To the caller,
-the call of <code>F</code> then behaves itself like a call to <code>panic</code>,
-terminating its own execution and running deferred functions in the same manner.
-This continues until all functions in the goroutine have ceased execution,
-in reverse order. At that point, the program is terminated and the error
+are then executed as usual.
+Next, any deferred functions run by <code>F's</code> caller are run,
+and so on up to any deferred by the top-level function in the executing goroutine.
+At that point, the program is terminated and the error
condition is reported, including the value of the argument to <code>panic</code>.
This termination sequence is called <i>panicking</i>.
</p>
@@ -5204,17 +5416,36 @@ panic(Error("cannot parse"))
<p>
The <code>recover</code> function allows a program to manage behavior
-of a panicking goroutine. Executing a <code>recover</code> call
-<i>inside</i> a deferred function (but not any function called by it) stops
-the panicking sequence by restoring normal execution, and retrieves
-the error value passed to the call of <code>panic</code>. If
-<code>recover</code> is called outside the deferred function it will
-not stop a panicking sequence. In this case, or when the goroutine
-is not panicking, or if the argument supplied to <code>panic</code>
-was <code>nil</code>, <code>recover</code> returns <code>nil</code>.
+of a panicking goroutine.
+Suppose a function <code>G</code> defers a function <code>D</code> that calls
+<code>recover</code> and a panic occurs in a function on the same goroutine in which <code>G</code>
+is executing.
+When the running of deferred functions reaches <code>D</code>,
+the return value of <code>D</code>'s call to <code>recover</code> will be the value passed to the call of <code>panic</code>.
+If <code>D</code> returns normally, without starting a new
+<code>panic</code>, the panicking sequence stops. In that case,
+the state of functions called between <code>G</code> and the call to <code>panic</code>
+is discarded, and normal execution resumes.
+Any functions deferred by <code>G</code> before <code>D</code> are then run and <code>G</code>'s
+execution terminates by returning to its caller.
</p>
<p>
+The return value of <code>recover</code> is <code>nil</code> if any of the following conditions holds:
+</p>
+<ul>
+<li>
+<code>panic</code>'s argument was <code>nil</code>;
+</li>
+<li>
+the goroutine is not panicking;
+</li>
+<li>
+<code>recover</code> was not called directly by a deferred function.
+</li>
+</ul>
+
+<p>
The <code>protect</code> function in the example below invokes
the function argument <code>g</code> and protects callers from
run-time panics raised by <code>g</code>.
@@ -5367,7 +5598,8 @@ import . "lib/math" Sin
<p>
An import declaration declares a dependency relation between
the importing and imported package.
-It is illegal for a package to import itself or to import a package without
+It is illegal for a package to import itself, directly or indirectly,
+or to directly import a package without
referring to any of its exported identifiers. To import a package solely for
its side-effects (initialization), use the <a href="#Blank_identifier">blank</a>
identifier as explicit package name:
@@ -5495,19 +5727,23 @@ in unspecified order.
</p>
<p>
Within a package, package-level variables are initialized,
-and constant values are determined, in
-data-dependent order: if the initializer of <code>A</code>
-depends on the value of <code>B</code>, <code>A</code>
+and constant values are determined, according to
+order of reference: if the initializer of <code>A</code>
+depends on <code>B</code>, <code>A</code>
will be set after <code>B</code>.
-It is an error if such dependencies form a cycle.
-Dependency analysis is done lexically: <code>A</code>
+Dependency analysis does not depend on the actual values
+of the items being initialized, only on their appearance
+in the source.
+<code>A</code>
depends on <code>B</code> if the value of <code>A</code>
contains a mention of <code>B</code>, contains a value
whose initializer
mentions <code>B</code>, or mentions a function that
mentions <code>B</code>, recursively.
+It is an error if such dependencies form a cycle.
If two items are not interdependent, they will be initialized
-in the order they appear in the source.
+in the order they appear in the source, possibly in multiple files,
+as presented to the compiler.
Since the dependency analysis is done per package, it can produce
unspecified results if <code>A</code>'s initializer calls a function defined
in another package that refers to <code>B</code>.
@@ -5645,8 +5881,10 @@ as if <code>v</code> was declared via <code>var v = x</code>.
</p>
<p>
The function <code>Offsetof</code> takes a (possibly parenthesized) <a href="#Selectors">selector</a>
-denoting a struct field of any type and returns the field offset in bytes relative to the
-struct's address.
+<code>s.f</code>, denoting a field <code>f</code> of the struct denoted by <code>s</code>
+or <code>*s</code>, and returns the field offset in bytes relative to the struct's address.
+If <code>f</code> is an <a href="#Struct_types">embedded field</a>, it must be reachable
+without pointer indirections through fields of the struct.
For a struct <code>s</code> with field <code>f</code>:
</p>
@@ -5675,7 +5913,7 @@ Calls to <code>Alignof</code>, <code>Offsetof</code>, and
<h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
<p>
-For the numeric types (§<a href="#Numeric_types">Numeric types</a>), the following sizes are guaranteed:
+For the <a href="#Numeric_types">numeric types</a>, the following sizes are guaranteed:
</p>
<pre class="grammar">
diff --git a/doc/progs/eff_unused1.go b/doc/progs/eff_unused1.go
new file mode 100644
index 000000000..f990a19f7
--- /dev/null
+++ b/doc/progs/eff_unused1.go
@@ -0,0 +1,18 @@
+// skip
+
+package main
+
+import (
+ "fmt"
+ "io"
+ "log"
+ "os"
+)
+
+func main() {
+ fd, err := os.Open("test.go")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // TODO: use fd.
+}
diff --git a/doc/progs/eff_unused2.go b/doc/progs/eff_unused2.go
new file mode 100644
index 000000000..3e6e041c7
--- /dev/null
+++ b/doc/progs/eff_unused2.go
@@ -0,0 +1,22 @@
+// compile
+
+package main
+
+import (
+ "fmt"
+ "io"
+ "log"
+ "os"
+)
+
+var _ = fmt.Printf // For debugging; delete when done.
+var _ io.Reader // For debugging; delete when done.
+
+func main() {
+ fd, err := os.Open("test.go")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // TODO: use fd.
+ _ = fd
+}
diff --git a/doc/progs/run b/doc/progs/run
index da777f329..71759c565 100755
--- a/doc/progs/run
+++ b/doc/progs/run
@@ -16,6 +16,7 @@ effective_go="
eff_bytesize
eff_qr
eff_sequence
+ eff_unused2
"
error_handling="
diff --git a/doc/progs/unused1.go b/doc/progs/unused1.go
deleted file mode 100644
index 96a6d98a3..000000000
--- a/doc/progs/unused1.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// skip
-
-package main
-
-import (
- "fmt"
- "io"
-)
-
-func main() {
- greeting := "hello, world"
-}
diff --git a/doc/progs/unused2.go b/doc/progs/unused2.go
deleted file mode 100644
index 5c5f9d74f..000000000
--- a/doc/progs/unused2.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// compile
-
-package main
-
-import (
- "fmt"
- "io"
-)
-
-var _ = fmt.Printf
-var _ io.Reader
-
-func main() {
- greeting := "hello, world"
- _ = greeting
-}
diff --git a/include/libc.h b/include/libc.h
index 1440209e3..fab1532f2 100644
--- a/include/libc.h
+++ b/include/libc.h
@@ -292,6 +292,10 @@ extern char* getgoversion(void);
extern char* getgoarm(void);
extern char* getgo386(void);
+extern char* mktempdir(void);
+extern void removeall(char*);
+extern int runcmd(char**);
+
extern void flagcount(char*, char*, int*);
extern void flagint32(char*, char*, int32*);
extern void flagint64(char*, char*, int64*);
@@ -304,7 +308,7 @@ extern void flagprint(int);
#ifdef _WIN32
-#ifndef _WIN64
+#if !defined(_WIN64) && !defined(__MINGW64_VERSION_MAJOR)
struct timespec {
int tv_sec;
long tv_nsec;
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py
index 4b6014505..11766fcb2 100644
--- a/lib/codereview/codereview.py
+++ b/lib/codereview/codereview.py
@@ -155,7 +155,8 @@ default_to_utf8()
global_status = None
def set_status(s):
- # print >>sys.stderr, "\t", time.asctime(), s
+ if verbosity > 0:
+ print >>sys.stderr, time.asctime(), s
global global_status
global_status = s
@@ -2213,6 +2214,7 @@ def reposetup(ui, repo):
if codereview_init:
return
codereview_init = True
+ start_status_thread()
# Read repository-specific options from lib/codereview/codereview.cfg or codereview.cfg.
root = ''
diff --git a/lib/godoc/package.html b/lib/godoc/package.html
index 1df1f9151..33c2c2791 100644
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -10,7 +10,11 @@
correspond to Go identifiers).
-->
{{with .PDoc}}
- {{if not $.IsMain}}
+ {{if $.IsMain}}
+ {{/* command documentation */}}
+ {{comment_html .Doc}}
+ {{else}}
+ {{/* package documentation */}}
<div id="short-nav">
<dl>
<dd><code>import "{{html .ImportPath}}"</code></dd>
@@ -71,9 +75,9 @@
{{end}}
{{end}}
{{if $.Notes}}
- {{range $marker, $item := $.Notes}}
+ {{range $marker, $item := $.Notes}}
<dd><a href="#pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</a></dd>
- {{end}}
+ {{end}}
{{end}}
</dl>
</div><!-- #manual-nav -->
@@ -88,7 +92,7 @@
</dl>
</div>
{{end}}
-
+
{{with .Filenames}}
<h4>Package files</h4>
<p>
@@ -101,7 +105,7 @@
{{end}}
</div><!-- .expanded -->
</div><!-- #pkg-index -->
-
+
{{with .Consts}}
<h2 id="pkg-constants">Constants</h2>
{{range .}}
@@ -160,16 +164,16 @@
{{example_html $name $.Examples $.FSet}}
{{end}}
{{end}}
- {{else}} {{/* not a package; is a command */}}
- {{comment_html .Doc}}
{{end}}
{{with $.Notes}}
- {{range $marker, $content := .}}
- <h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
- {{range .}}
- {{comment_html .}}
- {{end}}
+ {{range $marker, $content := .}}
+ <h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
+ <ul>
+ {{range .}}
+ <li>{{html .Body}}</li>
+ {{end}}
+ </ul>
{{end}}
{{end}}
{{end}}
@@ -250,7 +254,7 @@ $(document).ready(function() {
var resize = function() {
code.height(0);
var h = code[0].scrollHeight;
- code.height(h+20); // minimize bouncing
+ code.height(h+20); // minimize bouncing.
code.closest('.input').height(h);
};
code.on('keydown', resize);
diff --git a/lib/godoc/package.txt b/lib/godoc/package.txt
index 94239ca1a..bc11fc3c5 100644
--- a/lib/godoc/package.txt
+++ b/lib/godoc/package.txt
@@ -2,14 +2,15 @@
---------------------------------------
-*/}}{{with .PDoc}}{{if not $.IsMain}}PACKAGE
+*/}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
+
+{{comment_text .Doc " " "\t"}}
+{{else}}PACKAGE DOCUMENTATION
package {{.Name}}
import "{{.ImportPath}}"
-{{else}}COMMAND DOCUMENTATION
-
-{{end}}{{comment_text .Doc " " "\t"}}
+{{comment_text .Doc " " "\t"}}
{{example_text "" $.Examples $.FSet " "}}{{/*
---------------------------------------
@@ -58,15 +59,15 @@ TYPES
{{end}}{{range .Methods}}{{node .Decl $.FSet}}
{{comment_text .Doc " " "\t"}}
{{$name := printf "%s_%s" $tname .Name}}{{example_text $name $.Examples $.FSet " "}}
-{{end}}{{end}}{{end}}{{/*
+{{end}}{{end}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with $.Notes}}
{{range $marker, $content := .}}
-{{noteTitle $marker}}s
+{{$marker}}S
-{{range $content}}{{comment_text . " " "\t"}}
+{{range $content}}{{comment_text .Body " " "\t"}}
{{end}}{{end}}{{end}}{{end}}{{/*
---------------------------------------
diff --git a/lib/time/README b/lib/time/README
index d83e0addf..ffce9b0e0 100644
--- a/lib/time/README
+++ b/lib/time/README
@@ -5,6 +5,6 @@ The IANA asserts that the database is in the public domain.
For more information, see
http://www.iana.org/time-zones
ftp://ftp.iana.org/tz/code/tz-link.htm
-http://tools.ietf.org/html/draft-lear-iana-timezone-database-05
+http://tools.ietf.org/html/rfc6557
To rebuild the archive, read and run update.bash.
diff --git a/misc/bbedit/Go.plist b/misc/bbedit/Go.plist
index 791f93d16..791f93d16 100755..100644
--- a/misc/bbedit/Go.plist
+++ b/misc/bbedit/Go.plist
diff --git a/misc/cgo/test/cthread.go b/misc/cgo/test/cthread.go
index d918d033f..bdfd1103d 100644
--- a/misc/cgo/test/cthread.go
+++ b/misc/cgo/test/cthread.go
@@ -35,6 +35,7 @@ func testCthread(t *testing.T) {
t.Skip("testCthread disabled on arm")
}
+ sum.i = 0
C.doAdd(10, 6)
want := 10 * (10 - 1) / 2 * 6
diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go
index 7495d38fe..b0385eb85 100644
--- a/misc/cgo/test/issue4029.go
+++ b/misc/cgo/test/issue4029.go
@@ -47,14 +47,15 @@ func test4029(t *testing.T) {
func loadThySelf(t *testing.T, symbol string) {
this_process := C.dlopen(nil, C.RTLD_NOW)
if this_process == nil {
- t.Fatal("dlopen:", C.GoString(C.dlerror()))
+ t.Error("dlopen:", C.GoString(C.dlerror()))
+ return
}
defer C.dlclose(this_process)
symbol_address := C.dlsym(this_process, C.CString(symbol))
if symbol_address == nil {
- t.Fatal("dlsym:", C.GoString(C.dlerror()))
- } else {
- t.Log(symbol, symbol_address)
+ t.Error("dlsym:", C.GoString(C.dlerror()))
+ return
}
+ t.Log(symbol, symbol_address)
}
diff --git a/misc/dashboard/README b/misc/dashboard/README
index c00311ef7..d599f3d06 100644
--- a/misc/dashboard/README
+++ b/misc/dashboard/README
@@ -4,8 +4,8 @@
The files in this directory constitute the continuous builder:
-godashboard/: an AppEngine server
-builder/: gobuilder, a Go continuous build client
+app/: an AppEngine server
+builder/: gobuilder, a Go continuous build client
If you wish to run a Go builder, please email golang-dev@googlegroups.com
diff --git a/misc/dashboard/app/build/init.go b/misc/dashboard/app/build/init.go
index 85a766b9d..505f96fc4 100644
--- a/misc/dashboard/app/build/init.go
+++ b/misc/dashboard/app/build/init.go
@@ -20,12 +20,13 @@ var defaultPackages = []*Package{
// subRepos specifies the Go project sub-repositories.
var subRepos = []string{
+ "blog",
"codereview",
"crypto",
+ "exp",
"image",
"net",
"talks",
- "exp",
}
// Put subRepos into defaultPackages.
diff --git a/misc/dashboard/codereview/dashboard/cl.go b/misc/dashboard/codereview/dashboard/cl.go
index e150ea123..0ef3303e9 100644
--- a/misc/dashboard/codereview/dashboard/cl.go
+++ b/misc/dashboard/codereview/dashboard/cl.go
@@ -178,8 +178,14 @@ func handleAssign(w http.ResponseWriter, r *http.Request) {
return
}
defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ c.Errorf("Failed reading body: %v", err)
+ http.Error(w, err.Error(), 500)
+ return
+ }
if resp.StatusCode != 200 {
- c.Errorf("Retrieving CL reviewer list failed: got HTTP response %d", resp.StatusCode)
+ c.Errorf("Retrieving CL reviewer list failed: got HTTP response %d\nBody: %s", resp.StatusCode, body)
http.Error(w, "Failed contacting Rietveld", 500)
return
}
@@ -187,7 +193,7 @@ func handleAssign(w http.ResponseWriter, r *http.Request) {
var apiResp struct {
Reviewers []string `json:"reviewers"`
}
- if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
+ if err := json.Unmarshal(body, &apiResp); err != nil {
// probably can't be retried
msg := fmt.Sprintf("Malformed JSON from %v: %v", url, err)
c.Errorf("%s", msg)
@@ -212,8 +218,14 @@ func handleAssign(w http.ResponseWriter, r *http.Request) {
return
}
defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ c.Errorf("Failed reading Gobot body: %v", err)
+ http.Error(w, err.Error(), 500)
+ return
+ }
if resp.StatusCode != 200 {
- c.Errorf("Gobot GET failed: got HTTP response %d", resp.StatusCode)
+ c.Errorf("Gobot GET failed: got HTTP response %d\nBody: %s", resp.StatusCode, body)
http.Error(w, "Failed contacting Gobot", 500)
return
}
diff --git a/misc/dashboard/codereview/dashboard/people.go b/misc/dashboard/codereview/dashboard/people.go
index facda7baf..45de03b1e 100644
--- a/misc/dashboard/codereview/dashboard/people.go
+++ b/misc/dashboard/codereview/dashboard/people.go
@@ -21,6 +21,7 @@ func init() {
// and prefer to use their golang.org address for code review.
gophers := [...]string{
"adg",
+ "agl",
"bradfitz",
"campoy",
"dsymonds",
@@ -37,6 +38,24 @@ func init() {
emailToPerson[p+"@google.com"] = p
preferredEmail[p] = p + "@golang.org"
}
+ // Other people.
+ others := map[string]string{
+ "adonovan": "adonovan@google.com",
+ "brainman": "alex.brainman@gmail.com",
+ "ality": "ality@pbrane.org",
+ "dfc": "dave@cheney.net",
+ "dvyukov": "dvyukov@google.com",
+ "gustavo": "gustavo@niemeyer.net",
+ "jsing": "jsing@google.com",
+ "mikioh": "mikioh.mikioh@gmail.com",
+ "minux": "minux.ma@gmail.com",
+ "rminnich": "rminnich@gmail.com",
+ }
+ for p, e := range others {
+ personList = append(personList, p)
+ emailToPerson[e] = p
+ preferredEmail[p] = e
+ }
sort.Strings(personList)
}
diff --git a/misc/dist/bindist.go b/misc/dist/bindist.go
index 29454c73c..2d633bef9 100644
--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -386,9 +386,13 @@ func (b *Build) tour() error {
}
// Copy gotour binary to tool directory as "tour"; invoked as "go tool tour".
+ gotour := "gotour"
+ if runtime.GOOS == "windows" {
+ gotour = "gotour.exe"
+ }
return cp(
filepath.Join(b.root, "pkg", "tool", b.OS+"_"+b.Arch, "tour"),
- filepath.Join(b.gopath, "bin", "gotour"),
+ filepath.Join(b.gopath, "bin", gotour),
)
}
@@ -620,8 +624,11 @@ func cp(dst, src string) error {
return err
}
defer df.Close()
- if err := df.Chmod(fi.Mode()); err != nil {
- return err
+ // Windows doesn't currently implement Fchmod
+ if runtime.GOOS != "windows" {
+ if err := df.Chmod(fi.Mode()); err != nil {
+ return err
+ }
}
_, err = io.Copy(df, sf)
return err
diff --git a/misc/emacs/go-mode.el b/misc/emacs/go-mode.el
index 8a16d8a4f..9b6ea74f3 100644
--- a/misc/emacs/go-mode.el
+++ b/misc/emacs/go-mode.el
@@ -5,18 +5,71 @@
;; license that can be found in the LICENSE file.
(require 'cl)
-(require 'diff-mode)
(require 'ffap)
-(require 'find-lisp)
(require 'url)
+;; XEmacs compatibility guidelines
+;; - Minimum required version of XEmacs: 21.5.32
+;; - Feature that cannot be backported: POSIX character classes in
+;; regular expressions
+;; - Functions that could be backported but won't because 21.5.32
+;; covers them: plenty.
+;; - Features that are still partly broken:
+;; - godef will not work correctly if multibyte characters are
+;; being used
+;; - Fontification will not handle unicode correctly
+;;
+;; - Do not use \_< and \_> regexp delimiters directly; use
+;; go--regexp-enclose-in-symbol
+;;
+;; - The character `_` must not be a symbol constituent but a
+;; character constituent
+;;
+;; - Do not use process-lines
+;;
+;; - Use go--old-completion-list-style when using a plain list as the
+;; collection for completing-read
+;;
+;; - Use go--kill-whole-line instead of kill-whole-line (called
+;; kill-entire-line in XEmacs)
+;;
+;; - Use go--position-bytes instead of position-bytes
+(defmacro go--xemacs-p ()
+ `(featurep 'xemacs))
+
+(defalias 'go--kill-whole-line
+ (if (fboundp 'kill-whole-line)
+ 'kill-whole-line
+ 'kill-entire-line))
+
+;; XEmacs unfortunately does not offer position-bytes. We can fall
+;; back to just using (point), but it will be incorrect as soon as
+;; multibyte characters are being used.
+(if (fboundp 'position-bytes)
+ (defalias 'go--position-bytes 'position-bytes)
+ (defun go--position-bytes (point) point))
+
+(defun go--old-completion-list-style (list)
+ (mapcar (lambda (x) (cons x nil)) list))
+
+
+(defun go--regexp-enclose-in-symbol (s)
+ ;; XEmacs does not support \_<, GNU Emacs does. In GNU Emacs we make
+ ;; extensive use of \_< to support unicode in identifiers. Until we
+ ;; come up with a better solution for XEmacs, this solution will
+ ;; break fontification in XEmacs for identifiers such as "typeµ".
+ ;; XEmacs will consider "type" a keyword, GNU Emacs won't.
+
+ (if (go--xemacs-p)
+ (concat "\\<" s "\\>")
+ (concat "\\_<" s "\\_>")))
+
(defconst go-dangling-operators-regexp "[^-]-\\|[^+]\\+\\|[/*&><.=|^]")
-(defconst gofmt-stdin-tag "<standard input>")
-(defconst go-identifier-regexp "[[:word:][:multibyte:]_]+")
+(defconst go-identifier-regexp "[[:word:][:multibyte:]]+")
(defconst go-label-regexp go-identifier-regexp)
-(defconst go-type-regexp "[[:word:][:multibyte:]_*]+")
-(defconst go-func-regexp (concat "\\<func\\>\\s *\\(" go-identifier-regexp "\\)"))
-(defconst go-func-meth-regexp (concat "\\<func\\>\\s *\\(?:(\\s *" go-identifier-regexp "\\s +" go-type-regexp "\\s *)\\s *\\)?\\(" go-identifier-regexp "\\)("))
+(defconst go-type-regexp "[[:word:][:multibyte:]*]+")
+(defconst go-func-regexp (concat (go--regexp-enclose-in-symbol "func") "\\s *\\(" go-identifier-regexp "\\)"))
+(defconst go-func-meth-regexp (concat (go--regexp-enclose-in-symbol "func") "\\s *\\(?:(\\s *" go-identifier-regexp "\\s +" go-type-regexp "\\s *)\\s *\\)?\\(" go-identifier-regexp "\\)("))
(defconst go-builtins
'("append" "cap" "close" "complex" "copy"
"delete" "imag" "len" "make" "new"
@@ -35,6 +88,7 @@
(defconst go-type-name-regexp (concat "\\(?:[*(]\\)*\\(?:" go-identifier-regexp "\\.\\)?\\(" go-identifier-regexp "\\)"))
(defvar go-dangling-cache)
+(defvar go-godoc-history nil)
(defgroup go nil
"Major mode for editing Go code"
@@ -57,23 +111,27 @@
(modify-syntax-entry ?= "." st)
(modify-syntax-entry ?< "." st)
(modify-syntax-entry ?> "." st)
- (modify-syntax-entry ?/ ". 124b" st)
+ (modify-syntax-entry ?/ (if (go--xemacs-p) ". 1456" ". 124b") st)
(modify-syntax-entry ?* ". 23" st)
(modify-syntax-entry ?\n "> b" st)
(modify-syntax-entry ?\" "\"" st)
(modify-syntax-entry ?\' "\"" st)
(modify-syntax-entry ?` "\"" st)
(modify-syntax-entry ?\\ "\\" st)
- (modify-syntax-entry ?_ "_" st)
+ ;; It would be nicer to have _ as a symbol constituent, but that
+ ;; would trip up XEmacs, which does not support the \_< anchor
+ (modify-syntax-entry ?_ "w" st)
st)
"Syntax table for Go mode.")
(defun go--build-font-lock-keywords ()
+ ;; we cannot use 'symbols in regexp-opt because emacs <24 doesn't
+ ;; understand that
(append
- `((,(regexp-opt go-mode-keywords 'symbols) . font-lock-keyword-face)
- (,(regexp-opt go-builtins 'symbols) . font-lock-builtin-face)
- (,(regexp-opt go-constants 'symbols) . font-lock-constant-face)
+ `((,(go--regexp-enclose-in-symbol (regexp-opt go-mode-keywords t)) . font-lock-keyword-face)
+ (,(go--regexp-enclose-in-symbol (regexp-opt go-builtins t)) . font-lock-builtin-face)
+ (,(go--regexp-enclose-in-symbol (regexp-opt go-constants t)) . font-lock-constant-face)
(,go-func-regexp 1 font-lock-function-name-face)) ;; function (not method) name
(if go-fontify-function-calls
@@ -82,22 +140,22 @@
`((,go-func-meth-regexp 1 font-lock-function-name-face))) ;; method name
`(
- ("\\<type\\>[[:space:]]*\\([^[:space:]]+\\)" 1 font-lock-type-face) ;; types
- (,(concat "\\<type\\>[[:space:]]*" go-identifier-regexp "[[:space:]]*" go-type-name-regexp) 1 font-lock-type-face) ;; types
- (,(concat "\\(?:[[:space:]]+\\|\\]\\)\\[\\([[:digit:]]+\\|\\.\\.\\.\\)?\\]" go-type-name-regexp) 2 font-lock-type-face) ;; Arrays/slices
- (,(concat "map\\[[^]]+\\]" go-type-name-regexp) 1 font-lock-type-face) ;; map value type
+ (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]*\\([^[:space:]]+\\)") 1 font-lock-type-face) ;; types
+ (,(concat (go--regexp-enclose-in-symbol "type") "[[:space:]]*" go-identifier-regexp "[[:space:]]*" go-type-name-regexp) 1 font-lock-type-face) ;; types
+ (,(concat "[^[:word:][:multibyte:]]\\[\\([[:digit:]]+\\|\\.\\.\\.\\)?\\]" go-type-name-regexp) 2 font-lock-type-face) ;; Arrays/slices
(,(concat "\\(" go-identifier-regexp "\\)" "{") 1 font-lock-type-face)
- (,(concat "\\<map\\[" go-type-name-regexp) 1 font-lock-type-face) ;; map key type
- (,(concat "\\<chan\\>[[:space:]]*\\(?:<-\\)?" go-type-name-regexp) 1 font-lock-type-face) ;; channel type
- (,(concat "\\<\\(?:new\\|make\\)\\>\\(?:[[:space:]]\\|)\\)*(" go-type-name-regexp) 1 font-lock-type-face) ;; new/make type
+ (,(concat (go--regexp-enclose-in-symbol "map") "\\[[^]]+\\]" go-type-name-regexp) 1 font-lock-type-face) ;; map value type
+ (,(concat (go--regexp-enclose-in-symbol "map") "\\[" go-type-name-regexp) 1 font-lock-type-face) ;; map key type
+ (,(concat (go--regexp-enclose-in-symbol "chan") "[[:space:]]*\\(?:<-\\)?" go-type-name-regexp) 1 font-lock-type-face) ;; channel type
+ (,(concat (go--regexp-enclose-in-symbol "\\(?:new\\|make\\)") "\\(?:[[:space:]]\\|)\\)*(" go-type-name-regexp) 1 font-lock-type-face) ;; new/make type
;; TODO do we actually need this one or isn't it just a function call?
(,(concat "\\.\\s *(" go-type-name-regexp) 1 font-lock-type-face) ;; Type conversion
- (,(concat "\\<func\\>[[:space:]]+(" go-identifier-regexp "[[:space:]]+" go-type-name-regexp ")") 1 font-lock-type-face) ;; Method receiver
+ (,(concat (go--regexp-enclose-in-symbol "func") "[[:space:]]+(" go-identifier-regexp "[[:space:]]+" go-type-name-regexp ")") 1 font-lock-type-face) ;; Method receiver
;; Like the original go-mode this also marks compound literal
;; fields. There, it was marked as to fix, but I grew quite
;; accustomed to it, so it'll stay for now.
(,(concat "^[[:space:]]*\\(" go-label-regexp "\\)[[:space:]]*:\\(\\S.\\|$\\)") 1 font-lock-constant-face) ;; Labels and compound literal fields
- (,(concat "\\<\\(goto\\|break\\|continue\\)\\>[[:space:]]*\\(" go-label-regexp "\\)") 2 font-lock-constant-face)))) ;; labels in goto/break/continue
+ (,(concat (go--regexp-enclose-in-symbol "\\(goto\\|break\\|continue\\)") "[[:space:]]*\\(" go-label-regexp "\\)") 2 font-lock-constant-face)))) ;; labels in goto/break/continue
(defvar go-mode-map
(let ((m (make-sparse-keymap)))
@@ -107,6 +165,8 @@
(define-key m ":" 'go-mode-insert-and-indent)
(define-key m "=" 'go-mode-insert-and-indent)
(define-key m (kbd "C-c C-a") 'go-import-add)
+ (define-key m (kbd "C-c C-j") 'godef-jump)
+ (define-key m (kbd "C-c C-d") 'godef-describe)
m)
"Keymap used by Go mode to implement electric keys.")
@@ -140,7 +200,7 @@ It skips over whitespace, comments, cases and labels and, if
STOP-AT-STRING is not true, over strings."
(let (pos (start-pos (point)))
- (skip-chars-backward "\n[:blank:]")
+ (skip-chars-backward "\n\s\t")
(if (and (save-excursion (beginning-of-line) (go-in-string-p)) (looking-back "`") (not stop-at-string))
(backward-char))
(if (and (go-in-string-p) (not stop-at-string))
@@ -177,6 +237,28 @@ STOP-AT-STRING is not true, over strings."
(puthash cur-line val go-dangling-cache))))
val))
+(defun go--at-function-definition ()
+ "Return non-nil if point is on the opening curly brace of a
+function definition.
+
+We do this by first calling (beginning-of-defun), which will take
+us to the start of *some* function. We then look for the opening
+curly brace of that function and compare its position against the
+curly brace we are checking. If they match, we return non-nil."
+ (if (= (char-after) ?\{)
+ (save-excursion
+ (let ((old-point (point))
+ start-nesting)
+ (beginning-of-defun)
+ (when (looking-at "func ")
+ (setq start-nesting (go-paren-level))
+ (skip-chars-forward "^{")
+ (while (> (go-paren-level) start-nesting)
+ (forward-char)
+ (skip-chars-forward "^{") 0)
+ (if (and (= (go-paren-level) start-nesting) (= old-point (point)))
+ t))))))
+
(defun go-goto-opening-parenthesis (&optional char)
(let ((start-nesting (go-paren-level)))
(while (and (not (bobp))
@@ -189,6 +271,20 @@ STOP-AT-STRING is not true, over strings."
(go-goto-beginning-of-string-or-comment)
(backward-char))))))
+(defun go--indentation-for-opening-parenthesis ()
+ "Return the semantic indentation for the current opening parenthesis.
+
+If point is on an opening curly brace and said curly brace
+belongs to a function declaration, the indentation of the func
+keyword will be returned. Otherwise the indentation of the
+current line will be returned."
+ (save-excursion
+ (if (go--at-function-definition)
+ (progn
+ (beginning-of-defun)
+ (current-indentation))
+ (current-indentation))))
+
(defun go-indentation-at-point ()
(save-excursion
(let (start-nesting (outindent 0))
@@ -202,7 +298,7 @@ STOP-AT-STRING is not true, over strings."
(go-goto-opening-parenthesis (char-after))
(if (go-previous-line-has-dangling-op-p)
(- (current-indentation) tab-width)
- (current-indentation)))
+ (go--indentation-for-opening-parenthesis)))
((progn (go--backward-irrelevant t) (looking-back go-dangling-operators-regexp))
;; only one nesting for all dangling operators in one operation
(if (go-previous-line-has-dangling-op-p)
@@ -213,7 +309,7 @@ STOP-AT-STRING is not true, over strings."
((progn (go-goto-opening-parenthesis) (< (go-paren-level) start-nesting))
(if (go-previous-line-has-dangling-op-p)
(current-indentation)
- (+ (current-indentation) tab-width)))
+ (+ (go--indentation-for-opening-parenthesis) tab-width)))
(t
(current-indentation))))))
@@ -299,12 +395,26 @@ The following extra functions are defined:
- `go-goto-imports'
- `go-play-buffer' and `go-play-region'
- `go-download-play'
+- `godef-describe' and `godef-jump'
If you want to automatically run `gofmt' before saving a file,
add the following hook to your emacs configuration:
\(add-hook 'before-save-hook 'gofmt-before-save)
+If you want to use `godef-jump' instead of etags (or similar),
+consider binding godef-jump to `M-.', which is the default key
+for `find-tag':
+
+\(add-hook 'go-mode-hook (lambda ()
+ (local-set-key (kbd \"M-.\") 'godef-jump)))
+
+Please note that godef is an external dependency. You can install
+it with
+
+go get code.google.com/p/rog-go/exp/cmd/godef
+
+
If you're looking for even more integration with Go, namely
on-the-fly syntax checking, auto-completion and snippets, it is
recommended that you look at goflymake
@@ -360,99 +470,93 @@ recommended that you look at goflymake
;;;###autoload
(add-to-list 'auto-mode-alist (cons "\\.go\\'" 'go-mode))
+(defun go--apply-rcs-patch (patch-buffer)
+ "Apply an RCS-formatted diff from PATCH-BUFFER to the current
+buffer."
+ (let ((target-buffer (current-buffer))
+ ;; Relative offset between buffer line numbers and line numbers
+ ;; in patch.
+ ;;
+ ;; Line numbers in the patch are based on the source file, so
+ ;; we have to keep an offset when making changes to the
+ ;; buffer.
+ ;;
+ ;; Appending lines decrements the offset (possibly making it
+ ;; negative), deleting lines increments it. This order
+ ;; simplifies the forward-line invocations.
+ (line-offset 0))
+ (save-excursion
+ (with-current-buffer patch-buffer
+ (goto-char (point-min))
+ (while (not (eobp))
+ (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)")
+ (error "invalid rcs patch or internal error in go--apply-rcs-patch"))
+ (forward-line)
+ (let ((action (match-string 1))
+ (from (string-to-number (match-string 2)))
+ (len (string-to-number (match-string 3))))
+ (cond
+ ((equal action "a")
+ (let ((start (point)))
+ (forward-line len)
+ (let ((text (buffer-substring start (point))))
+ (with-current-buffer target-buffer
+ (decf line-offset len)
+ (goto-char (point-min))
+ (forward-line (- from len line-offset))
+ (insert text)))))
+ ((equal action "d")
+ (with-current-buffer target-buffer
+ (goto-char (point-min))
+ (forward-line (- from line-offset 1))
+ (incf line-offset len)
+ (go--kill-whole-line len)))
+ (t
+ (error "invalid rcs patch or internal error in go--apply-rcs-patch")))))))))
+
(defun gofmt ()
- "Pipe the current buffer through the external tool `gofmt`.
-Replace the current buffer on success; display errors on failure."
+ "Formats the current buffer according to the gofmt tool."
(interactive)
- (let ((currconf (current-window-configuration)))
- (let ((srcbuf (current-buffer))
- (filename buffer-file-name)
- (patchbuf (get-buffer-create "*Gofmt patch*")))
- (with-current-buffer patchbuf
- (let ((errbuf (get-buffer-create "*Gofmt Errors*"))
- ;; use utf-8 with subprocesses
- (coding-system-for-read 'utf-8)
- (coding-system-for-write 'utf-8))
- (with-current-buffer errbuf
- (setq buffer-read-only nil)
- (erase-buffer))
- (with-current-buffer srcbuf
- (save-restriction
- (let (deactivate-mark)
- (widen)
- ;; If this is a new file, diff-mode can't apply a
- ;; patch to a non-exisiting file, so replace the buffer
- ;; completely with the output of 'gofmt'.
- ;; If the file exists, patch it to keep the 'undo' list happy.
- (let* ((newfile (not (file-exists-p filename)))
- (flag (if newfile "" " -d")))
-
- ;; diff-mode doesn't work too well with missing
- ;; end-of-file newline, so add one
- (if (/= (char-after (1- (point-max))) ?\n)
- (save-excursion
- (goto-char (point-max))
- (insert ?\n)))
-
- (if (zerop (shell-command-on-region (point-min) (point-max)
- (concat "gofmt" flag)
- patchbuf nil errbuf))
- ;; gofmt succeeded: replace buffer or apply patch hunks.
- (let ((old-point (point))
- (old-mark (mark t)))
- (kill-buffer errbuf)
- (if newfile
- ;; New file, replace it (diff-mode won't work)
- (gofmt--replace-buffer srcbuf patchbuf)
- ;; Existing file, patch it
- (gofmt--apply-patch filename srcbuf patchbuf))
- (goto-char (min old-point (point-max)))
- ;; Restore the mark and point
- (if old-mark (push-mark (min old-mark (point-max)) t))
- (set-window-configuration currconf))
-
- ;; gofmt failed: display the errors
- (message "Could not apply gofmt. Check errors for details")
- (gofmt--process-errors filename errbuf))))))
-
- ;; Collapse any window opened on outbuf if shell-command-on-region
- ;; displayed it.
- (delete-windows-on patchbuf)))
- (kill-buffer patchbuf))))
-
-(defun gofmt--replace-buffer (srcbuf patchbuf)
- (with-current-buffer srcbuf
- (erase-buffer)
- (insert-buffer-substring patchbuf))
- (message "Applied gofmt"))
-
-(defun gofmt--apply-patch (filename srcbuf patchbuf)
- ;; apply all the patch hunks
- (let (changed)
+ (let ((tmpfile (make-temp-file "gofmt" nil ".go"))
+ (patchbuf (get-buffer-create "*Gofmt patch*"))
+ (errbuf (get-buffer-create "*Gofmt Errors*"))
+ (coding-system-for-read 'utf-8)
+ (coding-system-for-write 'utf-8))
+
+ (with-current-buffer errbuf
+ (setq buffer-read-only nil)
+ (erase-buffer))
(with-current-buffer patchbuf
- (goto-char (point-min))
- ;; The .* is for TMPDIR, but to avoid dealing with TMPDIR
- ;; having a trailing / or not, it's easier to just search for .*
- ;; especially as we're only replacing the first instance.
- (if (re-search-forward "^--- \\(.*/gofmt[0-9]*\\)" nil t)
- (replace-match filename nil nil nil 1))
- (condition-case nil
- (while t
- (diff-hunk-next)
- (diff-apply-hunk)
- (setq changed t))
- ;; When there's no more hunks, diff-hunk-next signals an error, ignore it
- (error nil)))
- (if changed (message "Applied gofmt") (message "Buffer was already gofmted"))))
-
-(defun gofmt--process-errors (filename errbuf)
+ (erase-buffer))
+
+ (write-region nil nil tmpfile)
+
+ ;; We're using errbuf for the mixed stdout and stderr output. This
+ ;; is not an issue because gofmt -w does not produce any stdout
+ ;; output in case of success.
+ (if (zerop (call-process "gofmt" nil errbuf nil "-w" tmpfile))
+ (if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile))
+ (progn
+ (kill-buffer errbuf)
+ (message "Buffer is already gofmted"))
+ (go--apply-rcs-patch patchbuf)
+ (kill-buffer errbuf)
+ (message "Applied gofmt"))
+ (message "Could not apply gofmt. Check errors for details")
+ (gofmt--process-errors (buffer-file-name) tmpfile errbuf))
+
+ (kill-buffer patchbuf)
+ (delete-file tmpfile)))
+
+
+(defun gofmt--process-errors (filename tmpfile errbuf)
;; Convert the gofmt stderr to something understood by the compilation mode.
(with-current-buffer errbuf
(goto-char (point-min))
(insert "gofmt errors:\n")
- (if (search-forward gofmt-stdin-tag nil t)
- (replace-match (file-name-nondirectory filename) nil t))
+ (while (search-forward-regexp (concat "^\\(" (regexp-quote tmpfile) "\\):") nil t)
+ (replace-match (file-name-nondirectory filename) t t nil 1))
(display-buffer errbuf)
(compilation-mode)))
@@ -476,10 +580,10 @@ you save any file, kind of defeating the point of autoloading."
(symbol (if bounds
(buffer-substring-no-properties (car bounds)
(cdr bounds)))))
- (read-string (if symbol
- (format "godoc (default %s): " symbol)
- "godoc: ")
- nil nil symbol)))
+ (completing-read (if symbol
+ (format "godoc (default %s): " symbol)
+ "godoc: ")
+ (go--old-completion-list-style (go-packages)) nil nil nil 'go-godoc-history symbol)))
(defun godoc--get-buffer (query)
"Get an empty buffer for a godoc query."
@@ -628,7 +732,7 @@ uncommented, otherwise a new import will be added."
(interactive
(list
current-prefix-arg
- (replace-regexp-in-string "^[\"']\\|[\"']$" "" (completing-read "Package: " (go-packages)))))
+ (replace-regexp-in-string "^[\"']\\|[\"']$" "" (completing-read "Package: " (go--old-completion-list-style (go-packages))))))
(save-excursion
(let (as line import-start)
(if arg
@@ -653,11 +757,34 @@ uncommented, otherwise a new import will be added."
('none (insert "\nimport (\n\t" line "\n)\n")))))))
(defun go-root-and-paths ()
- (let* ((output (process-lines "go" "env" "GOROOT" "GOPATH"))
+ (let* ((output (split-string (shell-command-to-string "go env GOROOT GOPATH") "\n"))
(root (car output))
- (paths (split-string (car (cdr output)) ":")))
+ (paths (split-string (cadr output) ":")))
(append (list root) paths)))
+(defun go--string-prefix-p (s1 s2 &optional ignore-case)
+ "Return non-nil if S1 is a prefix of S2.
+If IGNORE-CASE is non-nil, the comparison is case-insensitive."
+ (eq t (compare-strings s1 nil nil
+ s2 0 (length s1) ignore-case)))
+
+(defun go--directory-dirs (dir)
+ "Recursively return all subdirectories in DIR."
+ (if (file-directory-p dir)
+ (let ((dir (directory-file-name dir))
+ (dirs '())
+ (files (directory-files dir nil nil t)))
+ (dolist (file files)
+ (unless (member file '("." ".."))
+ (let ((file (concat dir "/" file)))
+ (if (file-directory-p file)
+ (setq dirs (append (cons file
+ (go--directory-dirs file))
+ dirs))))))
+ dirs)
+ '()))
+
+
(defun go-packages ()
(sort
(delete-dups
@@ -667,12 +794,12 @@ uncommented, otherwise a new import will be added."
(mapcan (lambda (dir)
(mapcar (lambda (file)
(let ((sub (substring file (length pkgdir) -2)))
- (unless (or (string-prefix-p "obj/" sub) (string-prefix-p "tool/" sub))
+ (unless (or (go--string-prefix-p "obj/" sub) (go--string-prefix-p "tool/" sub))
(mapconcat 'identity (cdr (split-string sub "/")) "/"))))
(if (file-directory-p dir)
(directory-files dir t "\\.a$"))))
(if (file-directory-p pkgdir)
- (find-lisp-find-files-internal pkgdir 'find-lisp-file-predicate-is-directory 'find-lisp-default-directory-predicate)))))
+ (go--directory-dirs pkgdir)))))
(go-root-and-paths)))
'string<))
@@ -712,9 +839,63 @@ will be commented, otherwise they will be removed completely."
(beginning-of-line)
(if arg
(comment-region (line-beginning-position) (line-end-position))
- (let ((kill-whole-line t))
- (kill-line))))
+ (go--kill-whole-line)))
(message "Removed %d imports" (length lines)))
(if flymake-state (flymake-mode-on)))))
+(defun godef--find-file-line-column (specifier)
+ "Given a file name in the format of `filename:line:column',
+visit FILENAME and go to line LINE and column COLUMN."
+ (let* ((components (split-string specifier ":"))
+ (line (string-to-number (nth 1 components)))
+ (column (string-to-number (nth 2 components))))
+ (with-current-buffer (find-file (car components))
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (beginning-of-line)
+ (forward-char (1- column))
+ (if (buffer-modified-p)
+ (message "Buffer is modified, file position might not have been correct")))))
+
+(defun godef--call (point)
+ "Call godef, acquiring definition position and expression
+description at POINT."
+ (if (go--xemacs-p)
+ (message "godef does not reliably work in XEmacs, expect bad results"))
+ (if (not buffer-file-name)
+ (message "Cannot use godef on a buffer without a file name")
+ (let ((outbuf (get-buffer-create "*godef*")))
+ (with-current-buffer outbuf
+ (erase-buffer))
+ (call-process-region (point-min) (point-max) "godef" nil outbuf nil "-i" "-t" "-f" (file-truename buffer-file-name) "-o" (number-to-string (go--position-bytes (point))))
+ (with-current-buffer outbuf
+ (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n")))))
+
+(defun godef-describe (point)
+ "Describe the expression at POINT."
+ (interactive "d")
+ (condition-case nil
+ (let ((description (nth 1 (godef--call point))))
+ (if (string= "" description)
+ (message "No description found for expression at point")
+ (message "%s" description)))
+ (file-error (message "Could not run godef binary"))))
+
+(defun godef-jump (point)
+ "Jump to the definition of the expression at POINT."
+ (interactive "d")
+ (condition-case nil
+ (let ((file (car (godef--call point))))
+ (cond
+ ((string= "-" file)
+ (message "godef: expression is not defined anywhere"))
+ ((string= "godef: no identifier found" file)
+ (message "%s" file))
+ ((go--string-prefix-p "godef: no declaration found for " file)
+ (message "%s" file))
+ (t
+ (push-mark)
+ (godef--find-file-line-column file))))
+ (file-error (message "Could not run godef binary"))))
+
(provide 'go-mode)
diff --git a/misc/notepadplus/README b/misc/notepadplus/README
index 000d31746..000d31746 100755..100644
--- a/misc/notepadplus/README
+++ b/misc/notepadplus/README
diff --git a/misc/notepadplus/go.xml b/misc/notepadplus/go.xml
index 237ef6b4b..237ef6b4b 100755..100644
--- a/misc/notepadplus/go.xml
+++ b/misc/notepadplus/go.xml
diff --git a/misc/notepadplus/userDefineLang.xml b/misc/notepadplus/userDefineLang.xml
index 2954aad48..2954aad48 100755..100644
--- a/misc/notepadplus/userDefineLang.xml
+++ b/misc/notepadplus/userDefineLang.xml
diff --git a/misc/pprof b/misc/pprof
index 7c379acbe..f471c7395 100755
--- a/misc/pprof
+++ b/misc/pprof
@@ -81,6 +81,11 @@ use Getopt::Long;
my $PPROF_VERSION = "1.5";
+# NOTE: All mentions of c++filt have been expunged from this script
+# because (1) we don't use C++, and (2) the copy of c++filt that ships
+# on OS X is from 2007 and destroys nm output by "demangling" the
+# first two columns (address and symbol type).
+
# These are the object tools we use which can come from a
# user-specified location using --tools, from the PPROF_TOOLS
# environment variable, or from the environment.
@@ -88,7 +93,6 @@ my %obj_tool_map = (
"objdump" => "objdump",
"nm" => "nm",
"addr2line" => "addr2line",
- "c++filt" => "c++filt",
## ConfigureObjTools may add architecture-specific entries:
#"nm_pdb" => "nm-pdb", # for reading windows (PDB-format) executables
#"addr2line_pdb" => "addr2line-pdb", # ditto
@@ -3093,9 +3097,7 @@ sub FetchSymbols {
my $url = SymbolPageURL();
$url = ResolveRedirectionForCurl($url);
my $command_line = "$CURL -sd '\@$main::tmpfile_sym' '$url'";
- # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.
- my $cppfilt = $obj_tool_map{"c++filt"};
- open(SYMBOL, "$command_line | $cppfilt |") or error($command_line);
+ open(SYMBOL, "$command_line |") or error($command_line);
ReadSymbols(*SYMBOL{IO}, $symbol_map);
close(SYMBOL);
}
@@ -4415,11 +4417,9 @@ sub MapToSymbols {
$cmd = "$addr2line --demangle -f -C -e $image";
}
- if (system("$addr2line --help >/dev/null 2>&1") != 0) {
- # addr2line must not exist. Fall back to go tool addr2line.
- $addr2line = "go tool addr2line";
- $cmd = "$addr2line $image";
- }
+ # Use the go version because we know it works on all platforms
+ $addr2line = "go tool addr2line";
+ $cmd = "$addr2line $image";
# If "addr2line" isn't installed on the system at all, just use
# nm to get what info we can (function names, but not line numbers).
@@ -4790,7 +4790,6 @@ sub GetProcedureBoundaries {
}
my $nm = $obj_tool_map{"nm"};
- my $cppfilt = $obj_tool_map{"c++filt"};
# nm can fail for two reasons: 1) $image isn't a debug library; 2) nm
# binary doesn't support --demangle. In addition, for OS X we need
@@ -4799,27 +4798,21 @@ sub GetProcedureBoundaries {
# in an incompatible way. So first we test whether our nm supports
# --demangle and -f.
my $demangle_flag = "";
- my $cppfilt_flag = "";
if (system("$nm --demangle $image >/dev/null 2>&1") == 0) {
# In this mode, we do "nm --demangle <foo>"
$demangle_flag = "--demangle";
- $cppfilt_flag = "";
- } elsif (system("$cppfilt $image >/dev/null 2>&1") == 0) {
- # In this mode, we do "nm <foo> | c++filt"
- $cppfilt_flag = " | $cppfilt";
- };
+ }
my $flatten_flag = "";
if (system("$nm -f $image >/dev/null 2>&1") == 0) {
$flatten_flag = "-f";
}
- # Finally, in the case $imagie isn't a debug library, we try again with
- # -D to at least get *exported* symbols. If we can't use --demangle,
- # we use c++filt instead, if it exists on this system.
+ # Finally, in the case $image isn't a debug library, we try again with
+ # -D to at least get *exported* symbols. If we can't use --demangle, too bad.
my @nm_commands = ("$nm -n $flatten_flag $demangle_flag" .
- " $image 2>/dev/null $cppfilt_flag",
+ " $image 2>/dev/null",
"$nm -D -n $flatten_flag $demangle_flag" .
- " $image 2>/dev/null $cppfilt_flag",
+ " $image 2>/dev/null",
# go tool nm is for Go binaries
"go tool nm $image 2>/dev/null | sort");
diff --git a/misc/swig/stdio/Makefile b/misc/swig/stdio/Makefile
deleted file mode 100644
index 0f23345e4..000000000
--- a/misc/swig/stdio/Makefile
+++ /dev/null
@@ -1,17 +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.
-
-include ../../../src/Make.inc
-
-TARG=swig/file
-SWIGFILES=\
- file.swig
-
-CLEANFILES+=hello
-
-include ../../../src/Make.pkg
-
-%: install %.go
- $(GC) $(GCFLAGS) $(GCIMPORTS) $*.go
- $(LD) $(SWIG_RPATH) -o $@ $*.$O
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index 191c755b8..d049ebe05 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -543,6 +543,7 @@ ismem(Node *n)
case OINDREG:
case ONAME:
case OPARAM:
+ case OCLOSUREVAR:
return 1;
}
return 0;
@@ -1163,11 +1164,11 @@ gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
// Generate an instruction referencing *n
// to force segv on nil pointer dereference.
void
-checkref(Node *n)
+checkref(Node *n, int force)
{
Node m1, m2;
- if(n->type->type->width < unmappedzero)
+ if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero)
return;
regalloc(&m1, types[TUINTPTR], n);
@@ -1209,8 +1210,6 @@ checkoffset(Addr *a, int canemitcode)
void
naddr(Node *n, Addr *a, int canemitcode)
{
- Prog *p;
-
a->type = D_NONE;
a->name = D_NONE;
a->reg = NREG;
@@ -1283,16 +1282,9 @@ naddr(Node *n, Addr *a, int canemitcode)
break;
case OCLOSUREVAR:
- if(!canemitcode)
- fatal("naddr OCLOSUREVAR cannot emit code");
- p = gins(AMOVW, N, N);
- p->from.type = D_OREG;
- p->from.reg = 7;
- p->from.offset = n->xoffset;
- p->to.type = D_REG;
- p->to.reg = 1;
- a->type = D_REG;
- a->reg = 1;
+ a->type = D_OREG;
+ a->reg = 7;
+ a->offset = n->xoffset;
a->sym = S;
break;
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 04f2a9c6c..a1220a38e 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -125,7 +125,7 @@ adddynrel(Sym *s, Reloc *r)
// Handle relocations found in ELF object files.
case 256 + R_ARM_PLT32:
r->type = D_CALL;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
@@ -138,7 +138,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_ARM_GOT32: // R_ARM_GOT_BREL
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
addgotsyminternal(targ);
} else {
addgotsym(targ);
@@ -149,7 +149,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_ARM_GOT_PREL: // GOT(S) + A - P
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
addgotsyminternal(targ);
} else {
addgotsym(targ);
@@ -171,7 +171,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_ARM_CALL:
r->type = D_CALL;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
@@ -184,7 +184,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_ARM_ABS32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ->name);
r->type = D_ADDR;
return;
@@ -201,7 +201,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_ARM_PC24:
case 256 + R_ARM_JUMP24:
r->type = D_CALL;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = braddoff(r->add, targ->plt / 4);
@@ -210,7 +210,7 @@ adddynrel(Sym *s, Reloc *r)
}
// Handle references to ELF symbols from our own object files.
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
return;
switch(r->type) {
@@ -240,12 +240,13 @@ adddynrel(Sym *s, Reloc *r)
}
int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
{
- USED(add); // written to obj file by ../ld/data.c's reloc
-
- LPUT(off);
+ int32 elfsym;
+
+ LPUT(sectoff);
+ elfsym = r->xsym->elfsym;
switch(r->type) {
default:
return -1;
@@ -295,6 +296,16 @@ elfsetupplt(void)
}
int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+ USED(r);
+ USED(sectoff);
+
+ return -1;
+}
+
+
+int
archreloc(Reloc *r, Sym *s, vlong *val)
{
switch(r->type) {
@@ -324,15 +335,16 @@ archreloc(Reloc *r, Sym *s, vlong *val)
*val = braddoff((0xff000000U & (uint32)r->add),
(0xffffff & (uint32)
((symaddr(r->sym) + ((uint32)r->add) * 4 - (s->value + r->off)) / 4)));
- return 0;
-}
-return -1;
+ return 0;
+ }
+ return -1;
}
static Reloc *
addpltreloc(Sym *plt, Sym *got, Sym *sym, int typ)
{
-Reloc *r;
+ Reloc *r;
+
r = addrel(plt);
r->sym = got;
r->off = plt->size;
@@ -437,20 +449,13 @@ adddynsym(Sym *s)
if(s->dynid >= 0)
return;
- if(s->dynimpname == nil) {
- s->dynimpname = s->name;
- //diag("adddynsym: no dynamic name for %s", s->name);
- }
-
if(iself) {
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
/* name */
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
+ name = s->extname;
adduint32(d, addstring(lookup(".dynstr", 0), name));
/* value */
@@ -464,7 +469,7 @@ adddynsym(Sym *s)
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && (s->type&SMASK) == STEXT)
+ if((s->cgoexport & CgoExportDynamic) && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -472,7 +477,7 @@ adddynsym(Sym *s)
adduint8(d, 0);
/* shndx */
- if(!s->dynexport && s->dynimpname != nil)
+ if(s->type == SDYNIMPORT)
adduint16(d, SHN_UNDEF);
else {
switch(s->type) {
@@ -600,7 +605,7 @@ asmb(void)
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
- if(isobj)
+ if(linkmode == LinkExternal)
elfemitreloc();
}
break;
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 62dd8947f..83c8b755c 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -38,6 +38,7 @@ enum
thechar = '5',
PtrSize = 4,
IntSize = 4,
+ MaxAlign = 8, // max data alignment
FuncAlign = 4 // single-instruction alignment
};
@@ -95,9 +96,12 @@ struct Reloc
{
int32 off;
uchar siz;
+ uchar done;
int16 type;
int32 add;
+ int32 xadd;
Sym* sym;
+ Sym* xsym;
};
struct Prog
@@ -133,11 +137,12 @@ struct Prog
struct Sym
{
char* name;
+ char* extname; // name used in external object files
short type;
short version;
uchar dupok;
uchar reachable;
- uchar dynexport;
+ uchar cgoexport;
uchar leaf;
int32 dynid;
int32 plt;
@@ -162,7 +167,6 @@ struct Sym
Sym* reachparent;
Sym* queue;
char* file;
- char* dynimpname;
char* dynimplib;
char* dynimpvers;
struct Section* sect;
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 6aa7fdd69..1bcf436c4 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -82,6 +82,7 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
LIBINITENTRY = 0;
+ linkmode = LinkInternal; // TODO: LinkAuto once everything works.
nuxiinit();
p = getgoarm();
@@ -116,22 +117,30 @@ main(int argc, char *argv[])
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
flagstr("k", "sym: set field tracking symbol", &tracksym);
+ flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagcount("n", "dump symbol table", &debug['n']);
flagstr("o", "outfile: set output file", &outfile);
flagcount("p", "insert profiling code", &debug['p']);
flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
+ flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
flagcount("shared", "generate shared object", &flag_shared);
+ // TODO: link mode flag
flagparse(&argc, &argv, usage);
if(argc != 1)
usage();
+ if(linkmode != LinkInternal) {
+ diag("only -linkmode=internal is supported");
+ errorexit();
+ }
+
libinit();
if(HEADTYPE == -1)
@@ -268,6 +277,7 @@ main(int argc, char *argv[])
reloc();
asmb();
undef();
+ hostlink();
if(debug['c'])
print("ARM size = %d\n", armsize);
@@ -424,6 +434,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
ntext = 0;
eof = Boffset(f) + len;
src[0] = 0;
+ pn = estrdup(pn); // we keep it in Sym* references
newloop:
memset(h, 0, sizeof(h));
diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c
index d65802a20..c969e98e5 100644
--- a/src/cmd/6a/lex.c
+++ b/src/cmd/6a/lex.c
@@ -932,6 +932,8 @@ struct
"PCMPGTW", LTYPE3, APCMPGTW,
"PEXTRW", LTYPEX, APEXTRW,
"PINSRW", LTYPEX, APINSRW,
+ "PINSRD", LTYPEX, APINSRD,
+ "PINSRQ", LTYPEX, APINSRQ,
"PMADDWL", LTYPE3, APMADDWL,
"PMAXSW", LTYPE3, APMAXSW,
"PMAXUB", LTYPE3, APMAXUB,
@@ -949,6 +951,7 @@ struct
"PSHUFL", LTYPEX, APSHUFL,
"PSHUFLW", LTYPEX, APSHUFLW,
"PSHUFW", LTYPEX, APSHUFW,
+ "PSHUFB", LTYPEM, APSHUFB,
"PSLLO", LTYPE3, APSLLO,
"PSLLDQ", LTYPE3, APSLLO, /* syn */
"PSLLL", LTYPE3, APSLLL,
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
index 58d6d5129..541c7beaa 100644
--- a/src/cmd/6c/swt.c
+++ b/src/cmd/6c/swt.c
@@ -320,7 +320,7 @@ outcode(void)
zaddr(&b, &p->from, sf);
zaddr(&b, &p->to, st);
}
- Bflush(&b);
+ Bterm(&b);
close(f);
firstp = P;
lastp = P;
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index fc5407a1f..739983246 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -555,6 +555,7 @@ ismem(Node *n)
case OINDREG:
case ONAME:
case OPARAM:
+ case OCLOSUREVAR:
return 1;
case OADDR:
if(flag_largemodel)
@@ -1057,11 +1058,11 @@ gins(int as, Node *f, Node *t)
// Generate an instruction referencing *n
// to force segv on nil pointer dereference.
void
-checkref(Node *n)
+checkref(Node *n, int force)
{
Node m;
- if(n->type->type->width < unmappedzero)
+ if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero)
return;
regalloc(&m, types[TUINTPTR], n);
@@ -1098,8 +1099,6 @@ checkoffset(Addr *a, int canemitcode)
void
naddr(Node *n, Addr *a, int canemitcode)
{
- Prog *p;
-
a->scale = 0;
a->index = D_NONE;
a->type = D_NONE;
@@ -1163,14 +1162,9 @@ naddr(Node *n, Addr *a, int canemitcode)
break;
case OCLOSUREVAR:
- if(!canemitcode)
- fatal("naddr OCLOSUREVAR cannot emit code");
- p = gins(AMOVQ, N, N);
- p->from.type = D_DX+D_INDIR;
- p->from.offset = n->xoffset;
- p->to.type = D_BX;
- a->type = D_BX;
+ a->type = D_DX+D_INDIR;
a->sym = S;
+ a->offset = n->xoffset;
break;
case OCFUNC:
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h
index 805b3fc6f..28de74944 100644
--- a/src/cmd/6l/6.out.h
+++ b/src/cmd/6l/6.out.h
@@ -654,6 +654,8 @@ enum as
APFSUB,
APFSUBR,
APINSRW,
+ APINSRD,
+ APINSRQ,
APMADDWL,
APMAXSW,
APMAXUB,
@@ -671,6 +673,7 @@ enum as
APSHUFL,
APSHUFLW,
APSHUFW,
+ APSHUFB,
APSLLO,
APSLLL,
APSLLQ,
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 5fb75ba4d..07ba59ad9 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -131,7 +131,7 @@ adddynrel(Sym *s, Reloc *r)
// Handle relocations found in ELF object files.
case 256 + R_X86_64_PC32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name);
if(targ->type == 0 || targ->type == SXREF)
diag("unknown symbol %s in pcrel", targ->name);
@@ -142,7 +142,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_X86_64_PLT32:
r->type = D_PCREL;
r->add += 4;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add += targ->plt;
@@ -150,7 +150,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_X86_64_GOTPCREL:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
// turn MOVQ of GOT entry into LEAQ of symbol itself
@@ -161,7 +161,6 @@ adddynrel(Sym *s, Reloc *r)
}
// fall back to using GOT and hope for the best (CMOV*)
// TODO: just needs relocation, no need to put in .dynsym
- targ->dynimpname = targ->name;
}
addgotsym(targ);
r->type = D_PCREL;
@@ -171,7 +170,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_X86_64_64:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name);
r->type = D_ADDR;
return;
@@ -182,12 +181,12 @@ adddynrel(Sym *s, Reloc *r)
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0:
// TODO: What is the difference between all these?
r->type = D_ADDR;
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected reloc for dynamic symbol %s", targ->name);
return;
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1:
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = targ->plt;
@@ -201,12 +200,12 @@ adddynrel(Sym *s, Reloc *r)
case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1:
case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
r->type = D_PCREL;
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name);
return;
case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
// turn MOVQ of GOT entry into LEAQ of symbol itself
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
@@ -219,7 +218,7 @@ adddynrel(Sym *s, Reloc *r)
}
// fall through
case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
addgotsym(targ);
r->type = D_PCREL;
@@ -229,7 +228,7 @@ adddynrel(Sym *s, Reloc *r)
}
// Handle references to ELF symbols from our own object files.
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
return;
switch(r->type) {
@@ -285,10 +284,13 @@ adddynrel(Sym *s, Reloc *r)
}
int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
{
- VPUT(off);
+ int32 elfsym;
+ VPUT(sectoff);
+
+ elfsym = r->xsym->elfsym;
switch(r->type) {
default:
return -1;
@@ -307,11 +309,67 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
else
return -1;
- add -= r->siz;
break;
}
- VPUT(add);
+ VPUT(r->xadd);
+ return 0;
+}
+
+int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+ uint32 v;
+ Sym *rs;
+
+ rs = r->xsym;
+
+ if(rs->type == SHOSTOBJ) {
+ if(rs->dynid < 0) {
+ diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
+ return -1;
+ }
+ v = rs->dynid;
+ v |= 1<<27; // external relocation
+ } else {
+ v = rs->sect->extnum;
+ if(v == 0) {
+ diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type);
+ return -1;
+ }
+ }
+
+ switch(r->type) {
+ default:
+ return -1;
+ case D_ADDR:
+ v |= MACHO_X86_64_RELOC_UNSIGNED<<28;
+ break;
+ case D_PCREL:
+ v |= 1<<24; // pc-relative bit
+ v |= MACHO_X86_64_RELOC_BRANCH<<28;
+ break;
+ }
+
+ switch(r->siz) {
+ default:
+ return -1;
+ case 1:
+ v |= 0<<25;
+ break;
+ case 2:
+ v |= 1<<25;
+ break;
+ case 4:
+ v |= 2<<25;
+ break;
+ case 8:
+ v |= 3<<25;
+ break;
+ }
+
+ LPUT(sectoff);
+ LPUT(v);
return 0;
}
@@ -448,29 +506,23 @@ addgotsym(Sym *s)
void
adddynsym(Sym *s)
{
- Sym *d, *str;
+ Sym *d;
int t;
char *name;
- vlong off;
if(s->dynid >= 0)
return;
- if(s->dynimpname == nil)
- diag("adddynsym: no dynamic name for %s", s->name);
-
if(iself) {
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
+ name = s->extname;
adduint32(d, addstring(lookup(".dynstr", 0), name));
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && (s->type&SMASK) == STEXT)
+ if(s->cgoexport && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -480,7 +532,7 @@ adddynsym(Sym *s)
adduint8(d, 0);
/* section where symbol is defined */
- if(!s->dynexport && s->dynimpname != nil)
+ if(s->type == SDYNIMPORT)
adduint16(d, SHN_UNDEF);
else {
switch(s->type) {
@@ -510,62 +562,15 @@ adddynsym(Sym *s)
/* size of object */
adduint64(d, s->size);
- if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
+ if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) {
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
addstring(lookup(".dynstr", 0), s->dynimplib));
}
} else if(HEADTYPE == Hdarwin) {
- // Mach-o symbol nlist64
- d = lookup(".dynsym", 0);
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
- if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
- symgrow(d, ndynexp*16);
- }
- if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
- s->dynid = -s->dynid-100;
- off = s->dynid*16;
- } else {
- off = d->size;
- s->dynid = off/16;
- }
- // darwin still puts _ prefixes on all C symbols
- str = lookup(".dynstr", 0);
- setuint32(d, off, str->size);
- off += 4;
- adduint8(str, '_');
- addstring(str, name);
- if(s->type == SDYNIMPORT) {
- setuint8(d, off, 0x01); // type - N_EXT - external symbol
- off++;
- setuint8(d, off, 0); // section
- off++;
- } else {
- setuint8(d, off, 0x0f);
- off++;
- switch(s->type) {
- default:
- case STEXT:
- setuint8(d, off, 1);
- break;
- case SDATA:
- setuint8(d, off, 2);
- break;
- case SBSS:
- setuint8(d, off, 4);
- break;
- }
- off++;
- }
- setuint16(d, off, 0); // desc
- off += 2;
- if(s->type == SDYNIMPORT)
- setuint64(d, off, 0); // value
- else
- setaddr(d, off, s);
- off += 8;
- } else if(HEADTYPE != Hwindows) {
+ diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
+ } else if(HEADTYPE == Hwindows) {
+ // already taken care of
+ } else {
diag("adddynsym: unsupported binary format");
}
}
@@ -706,7 +711,7 @@ asmb(void)
dwarfemitdebugsections();
- if(isobj)
+ if(linkmode == LinkExternal)
elfemitreloc();
}
break;
@@ -729,6 +734,10 @@ asmb(void)
dwarfemitdebugsections();
break;
+ case Hdarwin:
+ if(linkmode == LinkExternal)
+ machoemitreloc();
+ break;
}
}
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index ffb8a4552..1d6e55c97 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -42,6 +42,7 @@ enum
thechar = '6',
PtrSize = 8,
IntSize = 8,
+ MaxAlign = 32, // max data alignment
// Loop alignment constants:
// want to align loop entry to LoopAlign-byte boundary,
@@ -100,9 +101,12 @@ struct Reloc
{
int32 off;
uchar siz;
+ uchar done;
int32 type;
int64 add;
+ int64 xadd;
Sym* sym;
+ Sym* xsym;
};
struct Prog
@@ -140,11 +144,12 @@ struct Auto
struct Sym
{
char* name;
+ char* extname; // name used in external object files
short type;
short version;
uchar dupok;
uchar reachable;
- uchar dynexport;
+ uchar cgoexport;
uchar special;
uchar stkcheck;
uchar hide;
@@ -167,7 +172,6 @@ struct Sym
vlong size;
Sym* gotype;
char* file;
- char* dynimpname;
char* dynimplib;
char* dynimpvers;
struct Section* sect;
@@ -263,6 +267,7 @@ enum
Zo_iw,
Zm_o,
Zm_r,
+ Zm2_r,
Zm_r_xm,
Zm_r_i_xm,
Zm_r_3d,
@@ -292,10 +297,11 @@ enum
P32 = 0x32, /* 32-bit only */
Pe = 0x66, /* operand escape */
Pm = 0x0f, /* 2byte opcode escape */
- Pq = 0xff, /* both escape */
+ Pq = 0xff, /* both escapes: 66 0f */
Pb = 0xfe, /* byte operands */
- Pf2 = 0xf2, /* xmm escape 1 */
- Pf3 = 0xf3, /* xmm escape 2 */
+ Pf2 = 0xf2, /* xmm escape 1: f2 0f */
+ Pf3 = 0xf3, /* xmm escape 2: f3 0f */
+ Pq3 = 0x67, /* xmm escape 3: 66 48 0f */
Pw = 0x48, /* Rex.w */
Py = 0x80, /* defaults to 64-bit mode */
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 10e4a9860..3775df9de 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -83,6 +83,7 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
LIBINITENTRY = 0;
+ linkmode = LinkInternal; // TODO: LinkAuto once everything works.
nuxiinit();
flagcount("1", "use alternate profiling code", &debug['1']);
@@ -108,7 +109,7 @@ main(int argc, char *argv[])
flagcount("d", "disable dynamic executable", &debug['d']);
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
- flagcount("hostobj", "generate host object file", &isobj);
+ flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagstr("k", "sym: set field tracking symbol", &tracksym);
flagcount("n", "dump symbol table", &debug['n']);
flagstr("o", "outfile: set output file", &outfile);
@@ -116,10 +117,11 @@ main(int argc, char *argv[])
flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
+ flagcount("shared", "generate shared object", &flag_shared);
+ flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
- flagcount("shared", "generate shared object", &flag_shared);
flagparse(&argc, &argv, usage);
@@ -131,13 +133,19 @@ main(int argc, char *argv[])
if(HEADTYPE == -1)
HEADTYPE = headtype(goos);
- if(isobj) {
- switch(HEADTYPE) {
- default:
- sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE));
- case Hlinux:
- break;
- }
+ switch(HEADTYPE) {
+ default:
+ if(linkmode == LinkAuto)
+ linkmode = LinkInternal;
+ if(linkmode == LinkExternal)
+ sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
+ break;
+ case Hdarwin:
+ case Hfreebsd:
+ case Hlinux:
+ case Hnetbsd:
+ case Hopenbsd:
+ break;
}
if(outfile == nil) {
@@ -282,6 +290,7 @@ main(int argc, char *argv[])
reloc();
asmb();
undef();
+ hostlink();
if(debug['v']) {
Bprint(&bso, "%5.2f cpu time\n", cputime());
Bprint(&bso, "%d symbols\n", nsymbol);
@@ -412,6 +421,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
ntext = 0;
eof = Boffset(f) + len;
src[0] = 0;
+ pn = estrdup(pn); // we keep it in Sym* references
newloop:
memset(h, 0, sizeof(h));
diff --git a/src/cmd/6l/optab.c b/src/cmd/6l/optab.c
index a163e6faa..b0d5ca788 100644
--- a/src/cmd/6l/optab.c
+++ b/src/cmd/6l/optab.c
@@ -522,6 +522,11 @@ uchar ymshuf[] =
Ymm, Ymr, Zibm_r, 2,
0
};
+uchar ymshufb[] =
+{
+ Yxm, Yxr, Zm2_r, 2,
+ 0
+};
uchar yxshuf[] =
{
Yxm, Yxr, Zibm_r, 2,
@@ -532,6 +537,16 @@ uchar yextrw[] =
Yxr, Yrl, Zibm_r, 2,
0
};
+uchar yinsrw[] =
+{
+ Yml, Yxr, Zibm_r, 2,
+ 0
+};
+uchar yinsr[] =
+{
+ Ymm, Yxr, Zibm_r, 3,
+ 0
+};
uchar ypsdq[] =
{
Yi8, Yxr, Zibo_m, 2,
@@ -982,7 +997,9 @@ Optab optab[] =
{ APFRSQRT, ymfp, Px, 0x97 },
{ APFSUB, ymfp, Px, 0x9a },
{ APFSUBR, ymfp, Px, 0xaa },
- { APINSRW, yextrw, Pq, 0xc4,(00) },
+ { APINSRW, yinsrw, Pq, 0xc4,(00) },
+ { APINSRD, yinsr, Pq, 0x3a, 0x22, (00) },
+ { APINSRQ, yinsr, Pq3, 0x3a, 0x22, (00) },
{ APMADDWL, ymm, Py, 0xf5,Pe,0xf5 },
{ APMAXSW, yxm, Pe, 0xee },
{ APMAXUB, yxm, Pe, 0xde },
@@ -1008,6 +1025,7 @@ Optab optab[] =
{ APSHUFL, yxshuf, Pq, 0x70,(00) },
{ APSHUFLW, yxshuf, Pf2, 0x70,(00) },
{ APSHUFW, ymshuf, Pm, 0x70,(00) },
+ { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
{ APSLLO, ypsdq, Pq, 0x73,(07) },
{ APSLLL, yps, Py, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) },
{ APSLLQ, yps, Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index 283a0e349..fa94d8cf9 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -1161,6 +1161,11 @@ found:
*andptr++ = Pe;
*andptr++ = Pm;
break;
+ case Pq3: /* 16 bit escape, Rex.w, and opcode escape */
+ *andptr++ = Pe;
+ *andptr++ = Pw;
+ *andptr++ = Pm;
+ break;
case Pf2: /* xmm opcode escape */
case Pf3:
@@ -1229,6 +1234,11 @@ found:
*andptr++ = op;
asmand(&p->from, &p->to);
break;
+ case Zm2_r:
+ *andptr++ = op;
+ *andptr++ = o->op[z+1];
+ asmand(&p->from, &p->to);
+ break;
case Zm_r_xm:
mediaop(o, op, t[3], z);
diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y
index 60707d1c9..516e5fbe7 100644
--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -54,7 +54,7 @@
%left '*' '/' '%'
%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
-%token <lval> LCONST LFP LPC LSB
+%token <lval> LTYPEX LCONST LFP LPC LSB
%token <lval> LBREG LLREG LSREG LFREG LXREG
%token <dval> LFCONST
%token <sval> LSCONST LSP
@@ -63,7 +63,7 @@
%type <con2> con2
%type <gen> mem imm imm2 reg nam rel rem rim rom omem nmem
%type <gen2> nonnon nonrel nonrem rimnon rimrem remrim
-%type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
+%type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10
%%
prog:
| prog
@@ -117,6 +117,7 @@ inst:
| LTYPEI spec7 { outcode($1, &$2); }
| LTYPEG spec8 { outcode($1, &$2); }
| LTYPEXC spec9 { outcode($1, &$2); }
+| LTYPEX spec10 { outcode($1, &$2); }
nonnon:
{
@@ -296,6 +297,16 @@ spec9: /* CMPPS/CMPPD */
$$.to.offset = $5;
}
+spec10: /* PINSRD */
+ imm ',' rem ',' reg
+ {
+ $$.from = $3;
+ $$.to = $5;
+ if($1.type != D_CONST)
+ yyerror("illegal constant");
+ $$.to.offset = $1.offset;
+ }
+
rem:
reg
| mem
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
index 770ca5a88..b8fc2c03e 100644
--- a/src/cmd/8a/lex.c
+++ b/src/cmd/8a/lex.c
@@ -306,6 +306,7 @@ struct
"CMPXCHGB", LTYPE3, ACMPXCHGB,
"CMPXCHGL", LTYPE3, ACMPXCHGL,
"CMPXCHGW", LTYPE3, ACMPXCHGW,
+ "CPUID", LTYPE0, ACPUID,
"DAA", LTYPE0, ADAA,
"DAS", LTYPE0, ADAS,
"DATA", LTYPED, ADATA,
@@ -408,6 +409,7 @@ struct
"MOVB", LTYPE3, AMOVB,
"MOVL", LTYPEM, AMOVL,
"MOVW", LTYPEM, AMOVW,
+ "MOVQ", LTYPEM, AMOVQ,
"MOVBLSX", LTYPE3, AMOVBLSX,
"MOVBLZX", LTYPE3, AMOVBLZX,
"MOVBWSX", LTYPE3, AMOVBWSX,
@@ -437,6 +439,7 @@ struct
"OUTSL", LTYPE0, AOUTSL,
"OUTSW", LTYPE0, AOUTSW,
"PAUSE", LTYPEN, APAUSE,
+ "PINSRD", LTYPEX, APINSRD,
"POPAL", LTYPE0, APOPAL,
"POPAW", LTYPE0, APOPAW,
"POPFL", LTYPE0, APOPFL,
@@ -687,6 +690,7 @@ struct
"ADDPS", LTYPE3, AADDPS,
"ADDSD", LTYPE3, AADDSD,
"ADDSS", LTYPE3, AADDSS,
+ "AESENC", LTYPE3, AAESENC,
"ANDNPD", LTYPE3, AANDNPD,
"ANDNPS", LTYPE3, AANDNPS,
"ANDPD", LTYPE3, AANDPD,
@@ -755,11 +759,13 @@ struct
"ORPD", LTYPE3, AORPD,
"ORPS", LTYPE3, AORPS,
"PADDQ", LTYPE3, APADDQ,
+ "PAND", LTYPE3, APAND,
"PMAXSW", LTYPE3, APMAXSW,
"PMAXUB", LTYPE3, APMAXUB,
"PMINSW", LTYPE3, APMINSW,
"PMINUB", LTYPE3, APMINUB,
"PSADBW", LTYPE3, APSADBW,
+ "PSHUFB", LTYPE3, APSHUFB,
"PSUBB", LTYPE3, APSUBB,
"PSUBL", LTYPE3, APSUBL,
"PSUBQ", LTYPE3, APSUBQ,
diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c
index 38f2de52d..7eaff0bb0 100644
--- a/src/cmd/8a/y.tab.c
+++ b/src/cmd/8a/y.tab.c
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 2.6.5. */
+/* A Bison parser, made by GNU Bison 2.5. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.6.5"
+#define YYBISON_VERSION "2.5"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -58,11 +58,14 @@
/* Pull parsers. */
#define YYPULL 1
+/* Using locations. */
+#define YYLSP_NEEDED 0
/* Copy the first part of user declarations. */
-/* Line 360 of yacc.c */
+
+/* Line 268 of yacc.c */
#line 31 "a.y"
#include <u.h>
@@ -70,16 +73,14 @@
#include <libc.h>
#include "a.h"
-/* Line 360 of yacc.c */
-#line 75 "y.tab.c"
-# ifndef YY_NULL
-# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULL nullptr
-# else
-# define YY_NULL 0
-# endif
-# endif
+/* Line 268 of yacc.c */
+#line 79 "y.tab.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
@@ -89,18 +90,12 @@
# define YYERROR_VERBOSE 0
#endif
-/* In a future release of Bison, this section will be replaced
- by #include "y.tab.h". */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
#endif
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -122,21 +117,22 @@ extern int yydebug;
LTYPEI = 270,
LTYPEG = 271,
LTYPEXC = 272,
- LCONST = 273,
- LFP = 274,
- LPC = 275,
- LSB = 276,
- LBREG = 277,
- LLREG = 278,
- LSREG = 279,
- LFREG = 280,
- LXREG = 281,
- LFCONST = 282,
- LSCONST = 283,
- LSP = 284,
- LNAME = 285,
- LLAB = 286,
- LVAR = 287
+ LTYPEX = 273,
+ LCONST = 274,
+ LFP = 275,
+ LPC = 276,
+ LSB = 277,
+ LBREG = 278,
+ LLREG = 279,
+ LSREG = 280,
+ LFREG = 281,
+ LXREG = 282,
+ LFCONST = 283,
+ LSCONST = 284,
+ LSP = 285,
+ LNAME = 286,
+ LLAB = 287,
+ LVAR = 288
};
#endif
/* Tokens. */
@@ -155,28 +151,31 @@ extern int yydebug;
#define LTYPEI 270
#define LTYPEG 271
#define LTYPEXC 272
-#define LCONST 273
-#define LFP 274
-#define LPC 275
-#define LSB 276
-#define LBREG 277
-#define LLREG 278
-#define LSREG 279
-#define LFREG 280
-#define LXREG 281
-#define LFCONST 282
-#define LSCONST 283
-#define LSP 284
-#define LNAME 285
-#define LLAB 286
-#define LVAR 287
+#define LTYPEX 273
+#define LCONST 274
+#define LFP 275
+#define LPC 276
+#define LSB 277
+#define LBREG 278
+#define LLREG 279
+#define LSREG 280
+#define LFREG 281
+#define LXREG 282
+#define LFCONST 283
+#define LSCONST 284
+#define LSP 285
+#define LNAME 286
+#define LLAB 287
+#define LVAR 288
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
-/* Line 376 of yacc.c */
+
+/* Line 293 of yacc.c */
#line 37 "a.y"
Sym *sym;
@@ -191,7 +190,8 @@ typedef union YYSTYPE
Gen2 gen2;
-/* Line 376 of yacc.c */
+
+/* Line 293 of yacc.c */
#line 196 "y.tab.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
@@ -199,28 +199,12 @@ typedef union YYSTYPE
# define YYSTYPE_IS_DECLARED 1
#endif
-extern YYSTYPE yylval;
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_Y_TAB_H_INCLUDED */
/* Copy the second part of user declarations. */
-/* Line 379 of yacc.c */
-#line 224 "y.tab.c"
+
+/* Line 343 of yacc.c */
+#line 208 "y.tab.c"
#ifdef short
# undef short
@@ -273,24 +257,24 @@ typedef short int yytype_int16;
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
# endif
# endif
# ifndef YY_
-# define YY_(Msgid) Msgid
+# define YY_(msgid) msgid
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
+# define YYUSE(e) ((void) (e))
#else
-# define YYUSE(E) /* empty */
+# define YYUSE(e) /* empty */
#endif
/* Identity function, used to suppress warnings about constant conditions. */
#ifndef lint
-# define YYID(N) (N)
+# define YYID(n) (n)
#else
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
@@ -326,7 +310,6 @@ YYID (yyi)
# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
- /* Use EXIT_SUCCESS as a witness for stdlib.h. */
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# endif
@@ -418,20 +401,20 @@ union yyalloc
#endif
#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST. The source and destination do
+/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(Dst, Src, Count) \
- __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
-# define YYCOPY(Dst, Src, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (Dst)[yyi] = (Src)[yyi]; \
- } \
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
while (YYID (0))
# endif
# endif
@@ -440,20 +423,20 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 544
+#define YYLAST 553
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 51
+#define YYNTOKENS 52
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 38
+#define YYNNTS 39
/* YYNRULES -- Number of rules. */
-#define YYNRULES 128
+#define YYNRULES 130
/* YYNRULES -- Number of states. */
-#define YYNSTATES 255
+#define YYNSTATES 262
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 287
+#define YYMAXUTOK 288
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -464,16 +447,16 @@ static const yytype_uint8 yytranslate[] =
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 49, 12, 5, 2,
- 47, 48, 10, 8, 46, 9, 2, 11, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 43, 44,
- 6, 45, 7, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 50, 12, 5, 2,
+ 48, 49, 10, 8, 47, 9, 2, 11, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 44, 45,
+ 6, 46, 7, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 4, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 3, 2, 50, 2, 2, 2,
+ 2, 2, 2, 2, 3, 2, 51, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -489,7 +472,7 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 1, 2, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42
+ 35, 36, 37, 38, 39, 40, 41, 42, 43
};
#if YYDEBUG
@@ -500,65 +483,67 @@ static const yytype_uint16 yyprhs[] =
0, 0, 3, 4, 5, 9, 10, 15, 16, 21,
23, 26, 29, 33, 37, 40, 43, 46, 49, 52,
55, 58, 61, 64, 67, 70, 73, 76, 79, 82,
- 83, 85, 89, 93, 96, 98, 101, 103, 106, 108,
- 112, 118, 122, 128, 131, 133, 136, 138, 140, 144,
- 150, 154, 160, 163, 165, 169, 173, 179, 185, 187,
- 189, 191, 193, 196, 199, 201, 203, 205, 207, 209,
- 214, 217, 220, 222, 224, 226, 228, 230, 232, 235,
- 238, 241, 244, 249, 255, 259, 262, 264, 267, 271,
- 276, 278, 280, 282, 287, 292, 299, 309, 313, 317,
- 322, 328, 337, 339, 346, 352, 360, 361, 364, 367,
- 369, 371, 373, 375, 377, 380, 383, 386, 390, 392,
- 396, 400, 404, 408, 412, 417, 422, 426, 430
+ 85, 86, 88, 92, 96, 99, 101, 104, 106, 109,
+ 111, 115, 121, 125, 131, 134, 136, 139, 141, 143,
+ 147, 153, 157, 163, 166, 168, 172, 176, 182, 188,
+ 194, 196, 198, 200, 202, 205, 208, 210, 212, 214,
+ 216, 218, 223, 226, 229, 231, 233, 235, 237, 239,
+ 241, 244, 247, 250, 253, 258, 264, 268, 271, 273,
+ 276, 280, 285, 287, 289, 291, 296, 301, 308, 318,
+ 322, 326, 331, 337, 346, 348, 355, 361, 369, 370,
+ 373, 376, 378, 380, 382, 384, 386, 389, 392, 395,
+ 399, 401, 405, 409, 413, 417, 421, 426, 431, 435,
+ 439
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 52, 0, -1, -1, -1, 52, 53, 54, -1, -1,
- 41, 43, 55, 54, -1, -1, 40, 43, 56, 54,
- -1, 44, -1, 57, 44, -1, 1, 44, -1, 40,
- 45, 88, -1, 42, 45, 88, -1, 13, 58, -1,
- 14, 62, -1, 15, 61, -1, 16, 59, -1, 17,
- 60, -1, 21, 63, -1, 19, 64, -1, 22, 65,
- -1, 18, 66, -1, 20, 67, -1, 23, 68, -1,
- 24, 69, -1, 25, 70, -1, 26, 71, -1, 27,
- 72, -1, -1, 46, -1, 75, 46, 73, -1, 73,
- 46, 75, -1, 75, 46, -1, 75, -1, 46, 73,
- -1, 73, -1, 46, 76, -1, 76, -1, 78, 46,
- 76, -1, 84, 11, 87, 46, 78, -1, 81, 46,
- 79, -1, 81, 46, 87, 46, 79, -1, 46, 74,
- -1, 74, -1, 10, 84, -1, 58, -1, 62, -1,
- 75, 46, 73, -1, 75, 46, 73, 43, 33, -1,
- 75, 46, 73, -1, 75, 46, 73, 43, 34, -1,
- 75, 46, -1, 75, -1, 75, 46, 73, -1, 81,
- 46, 78, -1, 81, 46, 87, 46, 78, -1, 77,
- 46, 73, 46, 87, -1, 77, -1, 81, -1, 76,
- -1, 83, -1, 10, 77, -1, 10, 82, -1, 77,
- -1, 82, -1, 78, -1, 73, -1, 78, -1, 87,
- 47, 30, 48, -1, 40, 85, -1, 41, 85, -1,
- 32, -1, 35, -1, 33, -1, 36, -1, 39, -1,
- 34, -1, 49, 87, -1, 49, 84, -1, 49, 38,
- -1, 49, 37, -1, 49, 47, 37, 48, -1, 49,
- 47, 9, 37, 48, -1, 49, 9, 37, -1, 49,
- 80, -1, 28, -1, 9, 28, -1, 28, 9, 28,
- -1, 9, 28, 9, 28, -1, 82, -1, 83, -1,
- 87, -1, 87, 47, 33, 48, -1, 87, 47, 39,
- 48, -1, 87, 47, 33, 10, 87, 48, -1, 87,
- 47, 33, 48, 47, 33, 10, 87, 48, -1, 47,
- 33, 48, -1, 47, 39, 48, -1, 87, 47, 34,
- 48, -1, 47, 33, 10, 87, 48, -1, 47, 33,
- 48, 47, 33, 10, 87, 48, -1, 84, -1, 84,
- 47, 33, 10, 87, 48, -1, 40, 85, 47, 86,
- 48, -1, 40, 6, 7, 85, 47, 31, 48, -1,
- -1, 8, 87, -1, 9, 87, -1, 31, -1, 39,
- -1, 29, -1, 28, -1, 42, -1, 9, 87, -1,
- 8, 87, -1, 50, 87, -1, 47, 88, 48, -1,
- 87, -1, 88, 8, 88, -1, 88, 9, 88, -1,
- 88, 10, 88, -1, 88, 11, 88, -1, 88, 12,
- 88, -1, 88, 6, 6, 88, -1, 88, 7, 7,
- 88, -1, 88, 5, 88, -1, 88, 4, 88, -1,
- 88, 3, 88, -1
+ 53, 0, -1, -1, -1, 53, 54, 55, -1, -1,
+ 42, 44, 56, 55, -1, -1, 41, 44, 57, 55,
+ -1, 45, -1, 58, 45, -1, 1, 45, -1, 41,
+ 46, 90, -1, 43, 46, 90, -1, 13, 59, -1,
+ 14, 63, -1, 15, 62, -1, 16, 60, -1, 17,
+ 61, -1, 21, 64, -1, 19, 65, -1, 22, 66,
+ -1, 18, 67, -1, 20, 68, -1, 23, 69, -1,
+ 24, 70, -1, 25, 71, -1, 26, 72, -1, 27,
+ 73, -1, 28, 74, -1, -1, 47, -1, 77, 47,
+ 75, -1, 75, 47, 77, -1, 77, 47, -1, 77,
+ -1, 47, 75, -1, 75, -1, 47, 78, -1, 78,
+ -1, 80, 47, 78, -1, 86, 11, 89, 47, 80,
+ -1, 83, 47, 81, -1, 83, 47, 89, 47, 81,
+ -1, 47, 76, -1, 76, -1, 10, 86, -1, 59,
+ -1, 63, -1, 77, 47, 75, -1, 77, 47, 75,
+ 44, 34, -1, 77, 47, 75, -1, 77, 47, 75,
+ 44, 35, -1, 77, 47, -1, 77, -1, 77, 47,
+ 75, -1, 83, 47, 80, -1, 83, 47, 89, 47,
+ 80, -1, 79, 47, 75, 47, 89, -1, 80, 47,
+ 75, 47, 79, -1, 79, -1, 83, -1, 78, -1,
+ 85, -1, 10, 79, -1, 10, 84, -1, 79, -1,
+ 84, -1, 80, -1, 75, -1, 80, -1, 89, 48,
+ 31, 49, -1, 41, 87, -1, 42, 87, -1, 33,
+ -1, 36, -1, 34, -1, 37, -1, 40, -1, 35,
+ -1, 50, 89, -1, 50, 86, -1, 50, 39, -1,
+ 50, 38, -1, 50, 48, 38, 49, -1, 50, 48,
+ 9, 38, 49, -1, 50, 9, 38, -1, 50, 82,
+ -1, 29, -1, 9, 29, -1, 29, 9, 29, -1,
+ 9, 29, 9, 29, -1, 84, -1, 85, -1, 89,
+ -1, 89, 48, 34, 49, -1, 89, 48, 40, 49,
+ -1, 89, 48, 34, 10, 89, 49, -1, 89, 48,
+ 34, 49, 48, 34, 10, 89, 49, -1, 48, 34,
+ 49, -1, 48, 40, 49, -1, 89, 48, 35, 49,
+ -1, 48, 34, 10, 89, 49, -1, 48, 34, 49,
+ 48, 34, 10, 89, 49, -1, 86, -1, 86, 48,
+ 34, 10, 89, 49, -1, 41, 87, 48, 88, 49,
+ -1, 41, 6, 7, 87, 48, 32, 49, -1, -1,
+ 8, 89, -1, 9, 89, -1, 32, -1, 40, -1,
+ 30, -1, 29, -1, 43, -1, 9, 89, -1, 8,
+ 89, -1, 51, 89, -1, 48, 90, 49, -1, 89,
+ -1, 90, 8, 90, -1, 90, 9, 90, -1, 90,
+ 10, 90, -1, 90, 11, 90, -1, 90, 12, 90,
+ -1, 90, 6, 6, 90, -1, 90, 7, 7, 90,
+ -1, 90, 5, 90, -1, 90, 4, 90, -1, 90,
+ 3, 90, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
@@ -566,21 +551,22 @@ static const yytype_uint16 yyrline[] =
{
0, 68, 68, 70, 69, 77, 76, 84, 83, 89,
90, 91, 94, 99, 105, 106, 107, 108, 109, 110,
- 111, 112, 113, 114, 115, 116, 117, 118, 119, 122,
- 126, 133, 140, 147, 152, 159, 164, 171, 176, 181,
- 188, 196, 201, 209, 214, 219, 228, 229, 232, 237,
- 247, 252, 262, 267, 272, 279, 284, 292, 300, 301,
- 304, 305, 306, 310, 314, 315, 316, 319, 320, 323,
- 329, 338, 347, 352, 357, 362, 367, 372, 379, 385,
- 396, 402, 408, 414, 420, 428, 437, 442, 447, 452,
- 459, 460, 463, 469, 475, 481, 490, 499, 504, 509,
- 515, 523, 533, 537, 546, 553, 562, 565, 569, 575,
- 576, 580, 583, 584, 588, 592, 596, 600, 606, 607,
- 611, 615, 619, 623, 627, 631, 635, 639, 643
+ 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
+ 123, 127, 134, 141, 148, 153, 160, 165, 172, 177,
+ 182, 189, 197, 202, 210, 215, 220, 229, 230, 233,
+ 238, 248, 253, 263, 268, 273, 280, 285, 293, 301,
+ 311, 312, 315, 316, 317, 321, 325, 326, 327, 330,
+ 331, 334, 340, 349, 358, 363, 368, 373, 378, 383,
+ 390, 396, 407, 413, 419, 425, 431, 439, 448, 453,
+ 458, 463, 470, 471, 474, 480, 486, 492, 501, 510,
+ 515, 520, 526, 534, 544, 548, 557, 564, 573, 576,
+ 580, 586, 587, 591, 594, 595, 599, 603, 607, 611,
+ 617, 618, 622, 626, 630, 634, 638, 642, 646, 650,
+ 654
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || 0
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -588,14 +574,15 @@ static const char *const yytname[] =
"$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
"'-'", "'*'", "'/'", "'%'", "LTYPE0", "LTYPE1", "LTYPE2", "LTYPE3",
"LTYPE4", "LTYPEC", "LTYPED", "LTYPEN", "LTYPER", "LTYPET", "LTYPES",
- "LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LCONST", "LFP", "LPC", "LSB",
- "LBREG", "LLREG", "LSREG", "LFREG", "LXREG", "LFCONST", "LSCONST", "LSP",
- "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','", "'('", "')'", "'$'",
- "'~'", "$accept", "prog", "$@1", "line", "$@2", "$@3", "inst", "nonnon",
- "rimrem", "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2",
- "spec3", "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "rem",
- "rom", "rim", "rel", "reg", "imm", "imm2", "con2", "mem", "omem", "nmem",
- "nam", "offset", "pointer", "con", "expr", YY_NULL
+ "LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LTYPEX", "LCONST", "LFP",
+ "LPC", "LSB", "LBREG", "LLREG", "LSREG", "LFREG", "LXREG", "LFCONST",
+ "LSCONST", "LSP", "LNAME", "LLAB", "LVAR", "':'", "';'", "'='", "','",
+ "'('", "')'", "'$'", "'~'", "$accept", "prog", "$@1", "line", "$@2",
+ "$@3", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem",
+ "nonrel", "spec1", "spec2", "spec3", "spec4", "spec5", "spec6", "spec7",
+ "spec8", "spec9", "spec10", "rem", "rom", "rim", "rel", "reg", "imm",
+ "imm2", "con2", "mem", "omem", "nmem", "nam", "offset", "pointer", "con",
+ "expr", 0
};
#endif
@@ -608,27 +595,28 @@ static const yytype_uint16 yytoknum[] =
42, 47, 37, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286, 287, 58, 59, 61, 44, 40, 41, 36,
- 126
+ 285, 286, 287, 288, 58, 59, 61, 44, 40, 41,
+ 36, 126
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 51, 52, 53, 52, 55, 54, 56, 54, 54,
- 54, 54, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 58,
- 58, 59, 60, 61, 61, 62, 62, 63, 63, 63,
- 64, 65, 65, 66, 66, 66, 67, 67, 68, 68,
- 69, 69, 70, 70, 70, 71, 71, 72, 73, 73,
- 74, 74, 74, 74, 74, 74, 74, 75, 75, 76,
- 76, 76, 77, 77, 77, 77, 77, 77, 78, 78,
- 78, 78, 78, 78, 78, 79, 80, 80, 80, 80,
- 81, 81, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 83, 83, 84, 84, 85, 85, 85, 86,
- 86, 86, 87, 87, 87, 87, 87, 87, 88, 88,
- 88, 88, 88, 88, 88, 88, 88, 88, 88
+ 0, 52, 53, 54, 53, 56, 55, 57, 55, 55,
+ 55, 55, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 59, 59, 60, 61, 62, 62, 63, 63, 64, 64,
+ 64, 65, 66, 66, 67, 67, 67, 68, 68, 69,
+ 69, 70, 70, 71, 71, 71, 72, 72, 73, 74,
+ 75, 75, 76, 76, 76, 76, 76, 76, 76, 77,
+ 77, 78, 78, 78, 79, 79, 79, 79, 79, 79,
+ 80, 80, 80, 80, 80, 80, 80, 81, 82, 82,
+ 82, 82, 83, 83, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 85, 85, 86, 86, 87, 87,
+ 87, 88, 88, 88, 89, 89, 89, 89, 89, 89,
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
+ 90
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -636,17 +624,18 @@ static const yytype_uint8 yyr2[] =
{
0, 2, 0, 0, 3, 0, 4, 0, 4, 1,
2, 2, 3, 3, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
- 1, 3, 3, 2, 1, 2, 1, 2, 1, 3,
- 5, 3, 5, 2, 1, 2, 1, 1, 3, 5,
- 3, 5, 2, 1, 3, 3, 5, 5, 1, 1,
- 1, 1, 2, 2, 1, 1, 1, 1, 1, 4,
- 2, 2, 1, 1, 1, 1, 1, 1, 2, 2,
- 2, 2, 4, 5, 3, 2, 1, 2, 3, 4,
- 1, 1, 1, 4, 4, 6, 9, 3, 3, 4,
- 5, 8, 1, 6, 5, 7, 0, 2, 2, 1,
- 1, 1, 1, 1, 2, 2, 2, 3, 1, 3,
- 3, 3, 3, 3, 4, 4, 3, 3, 3
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 1, 3, 3, 2, 1, 2, 1, 2, 1,
+ 3, 5, 3, 5, 2, 1, 2, 1, 1, 3,
+ 5, 3, 5, 2, 1, 3, 3, 5, 5, 5,
+ 1, 1, 1, 1, 2, 2, 1, 1, 1, 1,
+ 1, 4, 2, 2, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 4, 5, 3, 2, 1, 2,
+ 3, 4, 1, 1, 1, 4, 4, 6, 9, 3,
+ 3, 4, 5, 8, 1, 6, 5, 7, 0, 2,
+ 2, 1, 1, 1, 1, 1, 2, 2, 2, 3,
+ 1, 3, 3, 3, 3, 3, 4, 4, 3, 3,
+ 3
};
/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -654,243 +643,248 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 2, 3, 1, 0, 0, 29, 0, 0, 0, 0,
- 0, 0, 29, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 9, 4, 0, 11, 30, 14, 0,
- 0, 112, 72, 74, 77, 73, 75, 76, 106, 113,
- 0, 0, 0, 15, 36, 58, 59, 90, 91, 102,
- 92, 0, 16, 67, 34, 68, 17, 0, 18, 0,
- 0, 106, 106, 0, 22, 44, 60, 64, 66, 65,
- 61, 92, 20, 0, 30, 46, 47, 23, 106, 0,
- 0, 19, 38, 0, 0, 21, 0, 24, 0, 25,
- 0, 26, 53, 27, 0, 28, 0, 7, 0, 5,
- 0, 10, 115, 114, 0, 0, 0, 0, 35, 0,
- 0, 118, 0, 116, 0, 0, 0, 81, 80, 0,
- 79, 78, 33, 0, 0, 62, 63, 45, 70, 71,
- 0, 43, 0, 0, 70, 37, 0, 0, 0, 0,
- 0, 52, 0, 0, 0, 12, 0, 13, 106, 107,
- 108, 0, 0, 97, 98, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 117, 0, 0, 0, 0,
- 84, 0, 0, 31, 32, 0, 0, 39, 0, 41,
- 0, 48, 50, 54, 55, 0, 0, 8, 6, 0,
- 111, 109, 110, 0, 0, 0, 128, 127, 126, 0,
- 0, 119, 120, 121, 122, 123, 0, 0, 93, 99,
- 94, 0, 82, 69, 0, 0, 86, 85, 0, 0,
- 0, 0, 0, 0, 104, 100, 0, 124, 125, 0,
- 0, 0, 83, 40, 87, 0, 42, 49, 51, 56,
- 57, 0, 0, 103, 95, 0, 0, 88, 105, 0,
- 0, 89, 101, 0, 96
+ 2, 3, 1, 0, 0, 30, 0, 0, 0, 0,
+ 0, 0, 30, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 4, 0, 11, 31, 14,
+ 0, 0, 114, 74, 76, 79, 75, 77, 78, 108,
+ 115, 0, 0, 0, 15, 37, 60, 61, 92, 93,
+ 104, 94, 0, 16, 69, 35, 70, 17, 0, 18,
+ 0, 0, 108, 108, 0, 22, 45, 62, 66, 68,
+ 67, 63, 94, 20, 0, 31, 47, 48, 23, 108,
+ 0, 0, 19, 39, 0, 0, 21, 0, 24, 0,
+ 25, 0, 26, 54, 27, 0, 28, 0, 29, 0,
+ 7, 0, 5, 0, 10, 117, 116, 0, 0, 0,
+ 0, 36, 0, 0, 120, 0, 118, 0, 0, 0,
+ 83, 82, 0, 81, 80, 34, 0, 0, 64, 65,
+ 46, 72, 73, 0, 44, 0, 0, 72, 38, 0,
+ 0, 0, 0, 0, 53, 0, 0, 0, 0, 12,
+ 0, 13, 108, 109, 110, 0, 0, 99, 100, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 119,
+ 0, 0, 0, 0, 86, 0, 0, 32, 33, 0,
+ 0, 40, 0, 42, 0, 49, 51, 55, 56, 0,
+ 0, 0, 8, 6, 0, 113, 111, 112, 0, 0,
+ 0, 130, 129, 128, 0, 0, 121, 122, 123, 124,
+ 125, 0, 0, 95, 101, 96, 0, 84, 71, 0,
+ 0, 88, 87, 0, 0, 0, 0, 0, 0, 0,
+ 106, 102, 0, 126, 127, 0, 0, 0, 85, 41,
+ 89, 0, 43, 50, 52, 57, 58, 59, 0, 0,
+ 105, 97, 0, 0, 90, 107, 0, 0, 91, 103,
+ 0, 98
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 1, 3, 24, 146, 144, 25, 28, 56, 58,
- 52, 43, 81, 72, 85, 64, 77, 87, 89, 91,
- 93, 95, 53, 65, 54, 66, 45, 55, 179, 217,
- 46, 47, 48, 49, 107, 193, 50, 112
+ -1, 1, 3, 25, 150, 148, 26, 29, 57, 59,
+ 53, 44, 82, 73, 86, 65, 78, 88, 90, 92,
+ 94, 96, 98, 54, 66, 55, 67, 46, 56, 183,
+ 222, 47, 48, 49, 50, 110, 198, 51, 115
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -96
+#define YYPACT_NINF -100
static const yytype_int16 yypact[] =
{
- -96, 34, -96, 158, -38, -30, 267, 288, 288, 338,
- 195, 20, 317, 210, 428, 288, 288, 288, 428, 68,
- -6, 2, 42, -96, -96, 45, -96, -96, -96, 449,
- 449, -96, -96, -96, -96, -96, -96, -96, 127, -96,
- 338, 388, 449, -96, -96, -96, -96, -96, -96, 46,
- 47, 382, -96, -96, 52, -96, -96, 59, -96, 62,
- 338, 127, 19, 238, -96, -96, -96, -96, -96, -96,
- -96, 63, -96, 103, 338, -96, -96, -96, 19, 403,
- 449, -96, -96, 69, 78, -96, 81, -96, 94, -96,
- 97, -96, 98, -96, 102, -96, 111, -96, 449, -96,
- 449, -96, -96, -96, 142, 449, 449, 113, -96, 23,
- 110, -96, 74, -96, 137, 58, 432, -96, -96, 439,
- -96, -96, -96, 338, 288, -96, -96, -96, 113, -96,
- 367, -96, 13, 449, -96, -96, 403, 156, 16, 338,
- 338, 338, 443, 338, 158, 523, 158, 523, 19, -96,
- -96, 11, 449, 140, -96, 449, 449, 449, 182, 194,
- 449, 449, 449, 449, 449, -96, 197, 25, 160, 161,
- -96, 475, 162, -96, -96, 163, 168, -96, 8, -96,
- 169, 173, 174, -96, -96, 175, 176, -96, -96, 177,
- -96, -96, -96, 172, 178, 192, 532, 157, 498, 449,
- 449, 64, 64, -96, -96, -96, 449, 449, 186, -96,
- -96, 191, -96, -96, 200, 215, 244, -96, 205, 222,
- 224, 200, 449, 230, -96, -96, 252, 183, 183, 216,
- 217, 234, -96, -96, 254, 240, -96, -96, -96, -96,
- -96, 221, 449, -96, -96, 271, 255, -96, -96, 236,
- 449, -96, -96, 241, -96
+ -100, 22, -100, 165, -32, -22, 263, 286, 286, 332,
+ 195, -1, 309, 212, 414, 286, 286, 286, 414, 81,
+ 7, -16, 24, -12, -100, -100, -4, -100, -100, -100,
+ 485, 485, -100, -100, -100, -100, -100, -100, -100, 39,
+ -100, 332, 385, 485, -100, -100, -100, -100, -100, -100,
+ 46, 65, 370, -100, -100, 72, -100, -100, 75, -100,
+ 76, 332, 39, 102, 240, -100, -100, -100, -100, -100,
+ -100, -100, 77, -100, 117, 332, -100, -100, -100, 102,
+ 408, 485, -100, -100, 83, 85, -100, 89, -100, 91,
+ -100, 92, -100, 97, -100, 98, -100, 100, -100, 101,
+ -100, 485, -100, 485, -100, -100, -100, 135, 485, 485,
+ 104, -100, -6, 113, -100, 71, -100, 119, 32, 423,
+ -100, -100, 438, -100, -100, -100, 332, 286, -100, -100,
+ -100, 104, -100, 355, -100, 29, 485, -100, -100, 408,
+ 146, 455, 332, 332, 332, 461, 332, 332, 165, 164,
+ 165, 164, 102, -100, -100, 6, 485, 161, -100, 485,
+ 485, 485, 206, 207, 485, 485, 485, 485, 485, -100,
+ 203, 4, 166, 167, -100, 470, 173, -100, -100, 174,
+ 178, -100, 15, -100, 179, 183, 189, -100, -100, 187,
+ 193, 197, -100, -100, 204, -100, -100, -100, 202, 208,
+ 222, 533, 541, 78, 485, 485, 95, 95, -100, -100,
+ -100, 485, 485, 210, -100, -100, 215, -100, -100, 7,
+ 232, 256, -100, 216, 233, 235, 7, 485, 81, 236,
+ -100, -100, 268, 188, 188, 230, 237, 250, -100, -100,
+ 276, 258, -100, -100, -100, -100, -100, -100, 244, 485,
+ -100, -100, 279, 272, -100, -100, 253, 485, -100, -100,
+ 259, -100
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -96, -96, -96, -95, -96, -96, -96, 270, -96, -96,
- -96, 274, -96, -96, -96, -96, -96, -96, -96, -96,
- -96, -96, -2, 227, 6, -12, -1, -8, 73, -96,
- 12, 1, 5, -3, -49, -96, -10, -44
+ -100, -100, -100, -99, -100, -100, -100, 293, -100, -100,
+ -100, 295, -100, -100, -100, -100, -100, -100, -100, -100,
+ -100, -100, -100, 17, 245, 0, -7, -9, -8, 90,
+ -100, 13, 1, -3, -2, -44, -100, -10, -64
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
+static const yytype_uint16 yytable[] =
{
- 71, 82, 68, 84, 44, 83, 26, 59, 73, 67,
- 44, 69, 128, 129, 57, 70, 27, 215, 96, 102,
- 103, 88, 90, 92, 29, 30, 86, 105, 106, 134,
- 94, 111, 113, 152, 2, 207, 216, 97, 108, 98,
- 190, 121, 191, 175, 31, 99, 167, 168, 120, 187,
- 192, 188, 169, 71, 145, 68, 147, 127, 39, 125,
- 38, 126, 67, 80, 69, 178, 42, 135, 70, 84,
- 111, 153, 108, 208, 162, 163, 164, 155, 156, 157,
- 158, 159, 160, 161, 162, 163, 164, 100, 111, 101,
- 111, 167, 168, 114, 115, 149, 150, 169, 122, 189,
- 32, 33, 34, 35, 36, 123, 103, 37, 124, 111,
- 132, 196, 197, 198, 133, 136, 201, 202, 203, 204,
- 205, 173, 165, 176, 177, 137, 84, 138, 180, 125,
- 174, 126, 185, 104, 184, 105, 106, 181, 182, 183,
- 139, 186, 194, 140, 141, 111, 111, 111, 142, 148,
- 111, 111, 111, 111, 111, 227, 228, 143, 154, 4,
- 151, 103, 157, 158, 159, 160, 161, 162, 163, 164,
- 166, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 175, 195, 199, 111,
- 111, 160, 161, 162, 163, 164, 229, 230, 20, 21,
- 22, 200, 23, 29, 30, 60, 233, 206, 209, 210,
- 212, 213, 240, 239, 214, 218, 219, 220, 29, 30,
- 224, 221, 222, 31, 223, 226, 225, 32, 33, 34,
- 35, 36, 249, 231, 37, 61, 62, 39, 31, 232,
- 253, 63, 41, 234, 51, 42, 29, 30, 130, 51,
- 78, 62, 39, 235, 178, 237, 79, 80, 238, 51,
- 42, 241, 242, 246, 243, 244, 31, 245, 247, 248,
- 32, 33, 34, 35, 36, 29, 30, 37, 61, 62,
- 39, 250, 75, 251, 252, 41, 76, 51, 42, 254,
- 131, 236, 0, 0, 0, 31, 29, 30, 0, 32,
- 33, 34, 35, 36, 0, 0, 37, 38, 0, 39,
- 0, 0, 0, 40, 41, 0, 31, 42, 0, 0,
- 32, 33, 34, 35, 36, 29, 30, 37, 38, 0,
- 39, 0, 0, 0, 0, 41, 0, 51, 42, 0,
- 0, 0, 0, 0, 0, 31, 29, 30, 0, 32,
- 33, 34, 35, 36, 0, 0, 37, 38, 0, 39,
- 0, 0, 0, 74, 41, 0, 31, 42, 0, 0,
- 32, 33, 34, 35, 36, 29, 30, 37, 38, 0,
- 39, 0, 0, 0, 0, 41, 0, 0, 42, 0,
- 29, 116, 0, 0, 0, 31, 29, 30, 0, 32,
- 33, 34, 35, 36, 0, 0, 37, 0, 0, 39,
- 31, 29, 30, 0, 41, 0, 31, 42, 0, 117,
- 118, 109, 38, 0, 39, 0, 0, 110, 0, 119,
- 39, 31, 42, 0, 0, 80, 29, 30, 42, 0,
- 29, 30, 0, 78, 62, 39, 0, 29, 171, 0,
- 80, 29, 30, 42, 0, 0, 31, 29, 30, 0,
- 31, 0, 0, 0, 0, 0, 0, 31, 38, 170,
- 39, 31, 0, 0, 39, 41, 172, 31, 42, 80,
- 0, 39, 42, 29, 30, 39, 80, 0, 0, 42,
- 80, 39, 51, 42, 0, 0, 80, 0, 0, 42,
- 0, 0, 0, 31, 158, 159, 160, 161, 162, 163,
- 164, 0, 211, 0, 0, 0, 0, 39, 0, 0,
- 0, 0, 80, 0, 0, 42, 155, 156, 157, 158,
- 159, 160, 161, 162, 163, 164, 156, 157, 158, 159,
- 160, 161, 162, 163, 164
+ 72, 68, 69, 85, 156, 84, 83, 71, 58, 74,
+ 97, 70, 99, 27, 212, 89, 91, 93, 131, 132,
+ 105, 106, 2, 45, 220, 28, 60, 87, 100, 45,
+ 101, 95, 114, 116, 103, 137, 195, 149, 196, 151,
+ 39, 104, 124, 157, 221, 107, 197, 108, 109, 192,
+ 123, 193, 128, 213, 72, 68, 69, 52, 111, 130,
+ 179, 71, 129, 171, 172, 70, 171, 172, 102, 173,
+ 85, 114, 173, 138, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 162, 163, 164, 165, 166, 167,
+ 168, 114, 111, 114, 117, 201, 202, 203, 153, 154,
+ 206, 207, 208, 209, 210, 166, 167, 168, 194, 106,
+ 108, 109, 114, 118, 33, 34, 35, 36, 37, 125,
+ 169, 38, 126, 127, 128, 135, 180, 178, 136, 85,
+ 139, 184, 181, 140, 129, 189, 141, 188, 142, 143,
+ 233, 234, 152, 177, 144, 145, 199, 146, 147, 114,
+ 114, 114, 155, 170, 114, 114, 114, 114, 114, 185,
+ 186, 187, 158, 190, 191, 106, 4, 159, 160, 161,
+ 162, 163, 164, 165, 166, 167, 168, 179, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 114, 114, 164, 165, 166, 167,
+ 168, 235, 236, 30, 31, 61, 21, 22, 23, 200,
+ 24, 239, 204, 211, 205, 214, 215, 246, 245, 247,
+ 30, 31, 217, 218, 32, 219, 223, 224, 33, 34,
+ 35, 36, 37, 225, 226, 38, 62, 63, 40, 256,
+ 227, 32, 64, 42, 228, 52, 43, 260, 30, 31,
+ 133, 230, 229, 79, 63, 40, 232, 231, 237, 80,
+ 81, 240, 52, 43, 238, 241, 182, 243, 248, 32,
+ 244, 30, 31, 33, 34, 35, 36, 37, 249, 250,
+ 38, 62, 63, 40, 252, 253, 251, 254, 42, 257,
+ 52, 43, 32, 255, 30, 31, 33, 34, 35, 36,
+ 37, 258, 259, 38, 39, 76, 40, 77, 261, 134,
+ 41, 42, 0, 242, 43, 32, 0, 30, 31, 33,
+ 34, 35, 36, 37, 0, 0, 38, 39, 0, 40,
+ 0, 0, 0, 0, 42, 0, 52, 43, 32, 0,
+ 30, 31, 33, 34, 35, 36, 37, 0, 0, 38,
+ 39, 0, 40, 0, 0, 0, 75, 42, 0, 0,
+ 43, 32, 0, 30, 31, 33, 34, 35, 36, 37,
+ 0, 0, 38, 39, 0, 40, 0, 0, 30, 119,
+ 42, 0, 0, 43, 32, 0, 0, 0, 33, 34,
+ 35, 36, 37, 30, 31, 38, 0, 0, 40, 32,
+ 0, 0, 0, 42, 0, 0, 43, 0, 120, 121,
+ 0, 39, 0, 40, 32, 0, 30, 31, 122, 112,
+ 0, 43, 30, 31, 0, 113, 0, 0, 40, 0,
+ 0, 30, 31, 81, 0, 0, 43, 32, 0, 0,
+ 0, 0, 0, 32, 0, 0, 30, 175, 0, 79,
+ 63, 40, 32, 0, 0, 39, 81, 40, 0, 43,
+ 0, 174, 42, 30, 31, 43, 40, 32, 0, 30,
+ 31, 81, 0, 0, 43, 0, 176, 0, 30, 31,
+ 0, 40, 0, 0, 32, 0, 81, 0, 0, 43,
+ 32, 0, 0, 30, 31, 0, 0, 0, 40, 32,
+ 0, 0, 0, 81, 40, 182, 43, 0, 216, 81,
+ 0, 52, 43, 40, 32, 0, 0, 0, 81, 0,
+ 0, 43, 0, 0, 0, 0, 0, 0, 40, 0,
+ 0, 0, 0, 81, 0, 0, 43, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 161, 162, 163, 164,
+ 165, 166, 167, 168
};
-#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-96)))
+#define yypact_value_is_default(yystate) \
+ ((yystate) == (-100))
-#define yytable_value_is_error(Yytable_value) \
+#define yytable_value_is_error(yytable_value) \
YYID (0)
static const yytype_int16 yycheck[] =
{
- 10, 13, 10, 13, 6, 13, 44, 9, 11, 10,
- 12, 10, 61, 62, 8, 10, 46, 9, 19, 29,
- 30, 15, 16, 17, 8, 9, 14, 8, 9, 78,
- 18, 41, 42, 10, 0, 10, 28, 43, 40, 45,
- 29, 51, 31, 30, 28, 43, 33, 34, 51, 144,
- 39, 146, 39, 63, 98, 63, 100, 60, 42, 60,
- 40, 60, 63, 47, 63, 49, 50, 79, 63, 79,
- 80, 48, 74, 48, 10, 11, 12, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 45, 98, 44,
- 100, 33, 34, 47, 47, 105, 106, 39, 46, 148,
- 32, 33, 34, 35, 36, 46, 116, 39, 46, 119,
- 47, 155, 156, 157, 11, 46, 160, 161, 162, 163,
- 164, 123, 48, 133, 136, 47, 136, 46, 138, 130,
- 124, 130, 142, 6, 142, 8, 9, 139, 140, 141,
- 46, 143, 152, 46, 46, 155, 156, 157, 46, 7,
- 160, 161, 162, 163, 164, 199, 200, 46, 48, 1,
- 47, 171, 5, 6, 7, 8, 9, 10, 11, 12,
- 33, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 30, 47, 6, 199,
- 200, 8, 9, 10, 11, 12, 206, 207, 40, 41,
- 42, 7, 44, 8, 9, 10, 214, 10, 48, 48,
- 48, 48, 222, 221, 46, 46, 43, 43, 8, 9,
- 48, 46, 46, 28, 47, 33, 48, 32, 33, 34,
- 35, 36, 242, 47, 39, 40, 41, 42, 28, 48,
- 250, 46, 47, 28, 49, 50, 8, 9, 10, 49,
- 40, 41, 42, 9, 49, 33, 46, 47, 34, 49,
- 50, 31, 10, 9, 48, 48, 28, 33, 28, 48,
- 32, 33, 34, 35, 36, 8, 9, 39, 40, 41,
- 42, 10, 12, 28, 48, 47, 12, 49, 50, 48,
- 63, 218, -1, -1, -1, 28, 8, 9, -1, 32,
- 33, 34, 35, 36, -1, -1, 39, 40, -1, 42,
- -1, -1, -1, 46, 47, -1, 28, 50, -1, -1,
- 32, 33, 34, 35, 36, 8, 9, 39, 40, -1,
- 42, -1, -1, -1, -1, 47, -1, 49, 50, -1,
- -1, -1, -1, -1, -1, 28, 8, 9, -1, 32,
- 33, 34, 35, 36, -1, -1, 39, 40, -1, 42,
- -1, -1, -1, 46, 47, -1, 28, 50, -1, -1,
- 32, 33, 34, 35, 36, 8, 9, 39, 40, -1,
- 42, -1, -1, -1, -1, 47, -1, -1, 50, -1,
- 8, 9, -1, -1, -1, 28, 8, 9, -1, 32,
- 33, 34, 35, 36, -1, -1, 39, -1, -1, 42,
- 28, 8, 9, -1, 47, -1, 28, 50, -1, 37,
- 38, 33, 40, -1, 42, -1, -1, 39, -1, 47,
- 42, 28, 50, -1, -1, 47, 8, 9, 50, -1,
- 8, 9, -1, 40, 41, 42, -1, 8, 9, -1,
- 47, 8, 9, 50, -1, -1, 28, 8, 9, -1,
- 28, -1, -1, -1, -1, -1, -1, 28, 40, 37,
- 42, 28, -1, -1, 42, 47, 37, 28, 50, 47,
- -1, 42, 50, 8, 9, 42, 47, -1, -1, 50,
- 47, 42, 49, 50, -1, -1, 47, -1, -1, 50,
- -1, -1, -1, 28, 6, 7, 8, 9, 10, 11,
- 12, -1, 37, -1, -1, -1, -1, 42, -1, -1,
- -1, -1, 47, -1, -1, 50, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 4, 5, 6, 7,
- 8, 9, 10, 11, 12
+ 10, 10, 10, 13, 10, 13, 13, 10, 8, 11,
+ 19, 10, 20, 45, 10, 15, 16, 17, 62, 63,
+ 30, 31, 0, 6, 9, 47, 9, 14, 44, 12,
+ 46, 18, 42, 43, 46, 79, 30, 101, 32, 103,
+ 41, 45, 52, 49, 29, 6, 40, 8, 9, 148,
+ 52, 150, 61, 49, 64, 64, 64, 50, 41, 61,
+ 31, 64, 61, 34, 35, 64, 34, 35, 44, 40,
+ 80, 81, 40, 80, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 6, 7, 8, 9, 10, 11,
+ 12, 101, 75, 103, 48, 159, 160, 161, 108, 109,
+ 164, 165, 166, 167, 168, 10, 11, 12, 152, 119,
+ 8, 9, 122, 48, 33, 34, 35, 36, 37, 47,
+ 49, 40, 47, 47, 133, 48, 136, 127, 11, 139,
+ 47, 141, 139, 48, 133, 145, 47, 145, 47, 47,
+ 204, 205, 7, 126, 47, 47, 156, 47, 47, 159,
+ 160, 161, 48, 34, 164, 165, 166, 167, 168, 142,
+ 143, 144, 49, 146, 147, 175, 1, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 31, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 204, 205, 8, 9, 10, 11,
+ 12, 211, 212, 8, 9, 10, 41, 42, 43, 48,
+ 45, 219, 6, 10, 7, 49, 49, 227, 226, 228,
+ 8, 9, 49, 49, 29, 47, 47, 44, 33, 34,
+ 35, 36, 37, 44, 47, 40, 41, 42, 43, 249,
+ 47, 29, 47, 48, 47, 50, 51, 257, 8, 9,
+ 10, 49, 48, 41, 42, 43, 34, 49, 48, 47,
+ 48, 29, 50, 51, 49, 9, 50, 34, 32, 29,
+ 35, 8, 9, 33, 34, 35, 36, 37, 10, 49,
+ 40, 41, 42, 43, 34, 9, 49, 29, 48, 10,
+ 50, 51, 29, 49, 8, 9, 33, 34, 35, 36,
+ 37, 29, 49, 40, 41, 12, 43, 12, 49, 64,
+ 47, 48, -1, 223, 51, 29, -1, 8, 9, 33,
+ 34, 35, 36, 37, -1, -1, 40, 41, -1, 43,
+ -1, -1, -1, -1, 48, -1, 50, 51, 29, -1,
+ 8, 9, 33, 34, 35, 36, 37, -1, -1, 40,
+ 41, -1, 43, -1, -1, -1, 47, 48, -1, -1,
+ 51, 29, -1, 8, 9, 33, 34, 35, 36, 37,
+ -1, -1, 40, 41, -1, 43, -1, -1, 8, 9,
+ 48, -1, -1, 51, 29, -1, -1, -1, 33, 34,
+ 35, 36, 37, 8, 9, 40, -1, -1, 43, 29,
+ -1, -1, -1, 48, -1, -1, 51, -1, 38, 39,
+ -1, 41, -1, 43, 29, -1, 8, 9, 48, 34,
+ -1, 51, 8, 9, -1, 40, -1, -1, 43, -1,
+ -1, 8, 9, 48, -1, -1, 51, 29, -1, -1,
+ -1, -1, -1, 29, -1, -1, 8, 9, -1, 41,
+ 42, 43, 29, -1, -1, 41, 48, 43, -1, 51,
+ -1, 38, 48, 8, 9, 51, 43, 29, -1, 8,
+ 9, 48, -1, -1, 51, -1, 38, -1, 8, 9,
+ -1, 43, -1, -1, 29, -1, 48, -1, -1, 51,
+ 29, -1, -1, 8, 9, -1, -1, -1, 43, 29,
+ -1, -1, -1, 48, 43, 50, 51, -1, 38, 48,
+ -1, 50, 51, 43, 29, -1, -1, -1, 48, -1,
+ -1, 51, -1, -1, -1, -1, -1, -1, 43, -1,
+ -1, -1, -1, 48, -1, -1, 51, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 5, 6, 7, 8,
+ 9, 10, 11, 12
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 52, 0, 53, 1, 13, 14, 15, 16, 17,
+ 0, 53, 0, 54, 1, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
- 40, 41, 42, 44, 54, 57, 44, 46, 58, 8,
- 9, 28, 32, 33, 34, 35, 36, 39, 40, 42,
- 46, 47, 50, 62, 73, 77, 81, 82, 83, 84,
- 87, 49, 61, 73, 75, 78, 59, 75, 60, 73,
- 10, 40, 41, 46, 66, 74, 76, 77, 78, 82,
- 83, 87, 64, 84, 46, 58, 62, 67, 40, 46,
- 47, 63, 76, 78, 87, 65, 81, 68, 75, 69,
- 75, 70, 75, 71, 81, 72, 77, 43, 45, 43,
- 45, 44, 87, 87, 6, 8, 9, 85, 73, 33,
- 39, 87, 88, 87, 47, 47, 9, 37, 38, 47,
- 84, 87, 46, 46, 46, 77, 82, 84, 85, 85,
- 10, 74, 47, 11, 85, 76, 46, 47, 46, 46,
- 46, 46, 46, 46, 56, 88, 55, 88, 7, 87,
- 87, 47, 10, 48, 48, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 48, 33, 33, 34, 39,
- 37, 9, 37, 73, 75, 30, 87, 76, 49, 79,
- 87, 73, 73, 73, 78, 87, 73, 54, 54, 85,
- 29, 31, 39, 86, 87, 47, 88, 88, 88, 6,
- 7, 88, 88, 88, 88, 88, 10, 10, 48, 48,
- 48, 37, 48, 48, 46, 9, 28, 80, 46, 43,
- 43, 46, 46, 47, 48, 48, 33, 88, 88, 87,
- 87, 47, 48, 78, 28, 9, 79, 33, 34, 78,
- 87, 31, 10, 48, 48, 33, 9, 28, 48, 87,
- 10, 28, 48, 87, 48
+ 28, 41, 42, 43, 45, 55, 58, 45, 47, 59,
+ 8, 9, 29, 33, 34, 35, 36, 37, 40, 41,
+ 43, 47, 48, 51, 63, 75, 79, 83, 84, 85,
+ 86, 89, 50, 62, 75, 77, 80, 60, 77, 61,
+ 75, 10, 41, 42, 47, 67, 76, 78, 79, 80,
+ 84, 85, 89, 65, 86, 47, 59, 63, 68, 41,
+ 47, 48, 64, 78, 80, 89, 66, 83, 69, 77,
+ 70, 77, 71, 77, 72, 83, 73, 79, 74, 80,
+ 44, 46, 44, 46, 45, 89, 89, 6, 8, 9,
+ 87, 75, 34, 40, 89, 90, 89, 48, 48, 9,
+ 38, 39, 48, 86, 89, 47, 47, 47, 79, 84,
+ 86, 87, 87, 10, 76, 48, 11, 87, 78, 47,
+ 48, 47, 47, 47, 47, 47, 47, 47, 57, 90,
+ 56, 90, 7, 89, 89, 48, 10, 49, 49, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 49,
+ 34, 34, 35, 40, 38, 9, 38, 75, 77, 31,
+ 89, 78, 50, 81, 89, 75, 75, 75, 80, 89,
+ 75, 75, 55, 55, 87, 30, 32, 40, 88, 89,
+ 48, 90, 90, 90, 6, 7, 90, 90, 90, 90,
+ 90, 10, 10, 49, 49, 49, 38, 49, 49, 47,
+ 9, 29, 82, 47, 44, 44, 47, 47, 47, 48,
+ 49, 49, 34, 90, 90, 89, 89, 48, 49, 80,
+ 29, 9, 81, 34, 35, 80, 89, 79, 32, 10,
+ 49, 49, 34, 9, 29, 49, 89, 10, 29, 49,
+ 89, 49
};
#define yyerrok (yyerrstatus = 0)
@@ -920,35 +914,62 @@ static const yytype_uint8 yystos[] =
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (yylen); \
- yystate = *yyssp; \
- goto yybackup; \
- } \
- else \
- { \
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
while (YYID (0))
-/* Error token number */
+
#define YYTERROR 1
#define YYERRCODE 256
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
/* This macro is provided for backward compatibility. */
+
#ifndef YY_LOCATION_PRINT
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
#endif
/* YYLEX -- calling `yylex' with the right arguments. */
+
#ifdef YYLEX_PARAM
# define YYLEX yylex (YYLEX_PARAM)
#else
@@ -998,8 +1019,6 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
YYSTYPE const * const yyvaluep;
#endif
{
- FILE *yyo = yyoutput;
- YYUSE (yyo);
if (!yyvaluep)
return;
# ifdef YYPRINT
@@ -1251,12 +1270,12 @@ static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yytype_int16 *yyssp, int yytoken)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
YYSIZE_T yysize1;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
- const char *yyformat = YY_NULL;
+ const char *yyformat = 0;
/* Arguments of yyformat. */
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
/* Number of reported tokens (one for the "unexpected", one per
@@ -1316,7 +1335,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
break;
}
yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
if (! (yysize <= yysize1
&& yysize1 <= YYSTACK_ALLOC_MAXIMUM))
return 2;
@@ -1408,22 +1427,27 @@ yydestruct (yymsg, yytype, yyvaluep)
}
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
/* The lookahead symbol. */
int yychar;
-
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+YYSTYPE yylval;
/* Number of syntax errors so far. */
int yynerrs;
@@ -1463,7 +1487,7 @@ yyparse ()
`yyss': related to states.
`yyvs': related to semantic values.
- Refer to the stacks through separate pointers, to allow yyoverflow
+ Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
/* The state stack. */
@@ -1481,7 +1505,7 @@ yyparse ()
int yyn;
int yyresult;
/* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
+ int yytoken;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
@@ -1499,8 +1523,9 @@ yyparse ()
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yyssp = yyss = yyssa;
- yyvsp = yyvs = yyvsa;
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
yystacksize = YYINITDEPTH;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1509,6 +1534,14 @@ yyparse ()
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
goto yysetstate;
/*------------------------------------------------------------.
@@ -1649,9 +1682,7 @@ yybackup:
yychar = YYEMPTY;
yystate = yyn;
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
goto yynewstate;
@@ -1688,7 +1719,8 @@ yyreduce:
switch (yyn)
{
case 3:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 70 "a.y"
{
stmtline = lineno;
@@ -1696,7 +1728,8 @@ yyreduce:
break;
case 5:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 77 "a.y"
{
if((yyvsp[(1) - (2)].sym)->value != pc)
@@ -1706,7 +1739,8 @@ yyreduce:
break;
case 7:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 84 "a.y"
{
(yyvsp[(1) - (2)].sym)->type = LLAB;
@@ -1715,7 +1749,8 @@ yyreduce:
break;
case 12:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 95 "a.y"
{
(yyvsp[(1) - (3)].sym)->type = LVAR;
@@ -1724,7 +1759,8 @@ yyreduce:
break;
case 13:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 100 "a.y"
{
if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
@@ -1734,197 +1770,231 @@ yyreduce:
break;
case 14:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 105 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 15:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 106 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 16:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 107 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 17:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 108 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 18:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 109 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 19:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 110 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 20:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 111 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 21:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 112 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 22:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 113 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 23:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 114 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 24:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 115 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 25:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 116 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 26:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 117 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 27:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 118 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 28:
-/* Line 1778 of yacc.c */
+
+/* Line 1806 of yacc.c */
#line 119 "a.y"
{ outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
break;
case 29:
-/* Line 1778 of yacc.c */
-#line 122 "a.y"
+
+/* Line 1806 of yacc.c */
+#line 120 "a.y"
+ { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].gen2)); }
+ break;
+
+ case 30:
+
+/* Line 1806 of yacc.c */
+#line 123 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = nullgen;
}
break;
- case 30:
-/* Line 1778 of yacc.c */
-#line 127 "a.y"
+ case 31:
+
+/* Line 1806 of yacc.c */
+#line 128 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = nullgen;
}
break;
- case 31:
-/* Line 1778 of yacc.c */
-#line 134 "a.y"
+ case 32:
+
+/* Line 1806 of yacc.c */
+#line 135 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 32:
-/* Line 1778 of yacc.c */
-#line 141 "a.y"
+ case 33:
+
+/* Line 1806 of yacc.c */
+#line 142 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 33:
-/* Line 1778 of yacc.c */
-#line 148 "a.y"
+ case 34:
+
+/* Line 1806 of yacc.c */
+#line 149 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 34:
-/* Line 1778 of yacc.c */
-#line 153 "a.y"
+ case 35:
+
+/* Line 1806 of yacc.c */
+#line 154 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 35:
-/* Line 1778 of yacc.c */
-#line 160 "a.y"
+ case 36:
+
+/* Line 1806 of yacc.c */
+#line 161 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
}
break;
- case 36:
-/* Line 1778 of yacc.c */
-#line 165 "a.y"
+ case 37:
+
+/* Line 1806 of yacc.c */
+#line 166 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
}
break;
- case 37:
-/* Line 1778 of yacc.c */
-#line 172 "a.y"
+ case 38:
+
+/* Line 1806 of yacc.c */
+#line 173 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
}
break;
- case 38:
-/* Line 1778 of yacc.c */
-#line 177 "a.y"
+ case 39:
+
+/* Line 1806 of yacc.c */
+#line 178 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
}
break;
- case 39:
-/* Line 1778 of yacc.c */
-#line 182 "a.y"
+ case 40:
+
+/* Line 1806 of yacc.c */
+#line 183 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 40:
-/* Line 1778 of yacc.c */
-#line 189 "a.y"
+ case 41:
+
+/* Line 1806 of yacc.c */
+#line 190 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1932,18 +2002,20 @@ yyreduce:
}
break;
- case 41:
-/* Line 1778 of yacc.c */
-#line 197 "a.y"
+ case 42:
+
+/* Line 1806 of yacc.c */
+#line 198 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 42:
-/* Line 1778 of yacc.c */
-#line 202 "a.y"
+ case 43:
+
+/* Line 1806 of yacc.c */
+#line 203 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -1951,27 +2023,30 @@ yyreduce:
}
break;
- case 43:
-/* Line 1778 of yacc.c */
-#line 210 "a.y"
+ case 44:
+
+/* Line 1806 of yacc.c */
+#line 211 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
}
break;
- case 44:
-/* Line 1778 of yacc.c */
-#line 215 "a.y"
+ case 45:
+
+/* Line 1806 of yacc.c */
+#line 216 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(1) - (1)].gen);
}
break;
- case 45:
-/* Line 1778 of yacc.c */
-#line 220 "a.y"
+ case 46:
+
+/* Line 1806 of yacc.c */
+#line 221 "a.y"
{
(yyval.gen2).from = nullgen;
(yyval.gen2).to = (yyvsp[(2) - (2)].gen);
@@ -1980,18 +2055,20 @@ yyreduce:
}
break;
- case 48:
-/* Line 1778 of yacc.c */
-#line 233 "a.y"
+ case 49:
+
+/* Line 1806 of yacc.c */
+#line 234 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 49:
-/* Line 1778 of yacc.c */
-#line 238 "a.y"
+ case 50:
+
+/* Line 1806 of yacc.c */
+#line 239 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -2001,18 +2078,20 @@ yyreduce:
}
break;
- case 50:
-/* Line 1778 of yacc.c */
-#line 248 "a.y"
+ case 51:
+
+/* Line 1806 of yacc.c */
+#line 249 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 51:
-/* Line 1778 of yacc.c */
-#line 253 "a.y"
+ case 52:
+
+/* Line 1806 of yacc.c */
+#line 254 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -2022,45 +2101,50 @@ yyreduce:
}
break;
- case 52:
-/* Line 1778 of yacc.c */
-#line 263 "a.y"
+ case 53:
+
+/* Line 1806 of yacc.c */
+#line 264 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (2)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 53:
-/* Line 1778 of yacc.c */
-#line 268 "a.y"
+ case 54:
+
+/* Line 1806 of yacc.c */
+#line 269 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (1)].gen);
(yyval.gen2).to = nullgen;
}
break;
- case 54:
-/* Line 1778 of yacc.c */
-#line 273 "a.y"
+ case 55:
+
+/* Line 1806 of yacc.c */
+#line 274 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 55:
-/* Line 1778 of yacc.c */
-#line 280 "a.y"
+ case 56:
+
+/* Line 1806 of yacc.c */
+#line 281 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (3)].gen);
(yyval.gen2).to = (yyvsp[(3) - (3)].gen);
}
break;
- case 56:
-/* Line 1778 of yacc.c */
-#line 285 "a.y"
+ case 57:
+
+/* Line 1806 of yacc.c */
+#line 286 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).from.scale = (yyvsp[(3) - (5)].lval);
@@ -2068,9 +2152,10 @@ yyreduce:
}
break;
- case 57:
-/* Line 1778 of yacc.c */
-#line 293 "a.y"
+ case 58:
+
+/* Line 1806 of yacc.c */
+#line 294 "a.y"
{
(yyval.gen2).from = (yyvsp[(1) - (5)].gen);
(yyval.gen2).to = (yyvsp[(3) - (5)].gen);
@@ -2078,25 +2163,41 @@ yyreduce:
}
break;
- case 62:
-/* Line 1778 of yacc.c */
-#line 307 "a.y"
+ case 59:
+
+/* Line 1806 of yacc.c */
+#line 302 "a.y"
+ {
+ (yyval.gen2).from = (yyvsp[(3) - (5)].gen);
+ (yyval.gen2).to = (yyvsp[(5) - (5)].gen);
+ if((yyvsp[(1) - (5)].gen).type != D_CONST)
+ yyerror("illegal constant");
+ (yyval.gen2).to.offset = (yyvsp[(1) - (5)].gen).offset;
+ }
+ break;
+
+ case 64:
+
+/* Line 1806 of yacc.c */
+#line 318 "a.y"
{
(yyval.gen) = (yyvsp[(2) - (2)].gen);
}
break;
- case 63:
-/* Line 1778 of yacc.c */
-#line 311 "a.y"
+ case 65:
+
+/* Line 1806 of yacc.c */
+#line 322 "a.y"
{
(yyval.gen) = (yyvsp[(2) - (2)].gen);
}
break;
- case 69:
-/* Line 1778 of yacc.c */
-#line 324 "a.y"
+ case 71:
+
+/* Line 1806 of yacc.c */
+#line 335 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_BRANCH;
@@ -2104,9 +2205,10 @@ yyreduce:
}
break;
- case 70:
-/* Line 1778 of yacc.c */
-#line 330 "a.y"
+ case 72:
+
+/* Line 1806 of yacc.c */
+#line 341 "a.y"
{
(yyval.gen) = nullgen;
if(pass == 2)
@@ -2117,9 +2219,10 @@ yyreduce:
}
break;
- case 71:
-/* Line 1778 of yacc.c */
-#line 339 "a.y"
+ case 73:
+
+/* Line 1806 of yacc.c */
+#line 350 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_BRANCH;
@@ -2128,63 +2231,70 @@ yyreduce:
}
break;
- case 72:
-/* Line 1778 of yacc.c */
-#line 348 "a.y"
+ case 74:
+
+/* Line 1806 of yacc.c */
+#line 359 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 73:
-/* Line 1778 of yacc.c */
-#line 353 "a.y"
+ case 75:
+
+/* Line 1806 of yacc.c */
+#line 364 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 74:
-/* Line 1778 of yacc.c */
-#line 358 "a.y"
+ case 76:
+
+/* Line 1806 of yacc.c */
+#line 369 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 75:
-/* Line 1778 of yacc.c */
-#line 363 "a.y"
+ case 77:
+
+/* Line 1806 of yacc.c */
+#line 374 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 76:
-/* Line 1778 of yacc.c */
-#line 368 "a.y"
+ case 78:
+
+/* Line 1806 of yacc.c */
+#line 379 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_SP;
}
break;
- case 77:
-/* Line 1778 of yacc.c */
-#line 373 "a.y"
+ case 79:
+
+/* Line 1806 of yacc.c */
+#line 384 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(1) - (1)].lval);
}
break;
- case 78:
-/* Line 1778 of yacc.c */
-#line 380 "a.y"
+ case 80:
+
+/* Line 1806 of yacc.c */
+#line 391 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_CONST;
@@ -2192,9 +2302,10 @@ yyreduce:
}
break;
- case 79:
-/* Line 1778 of yacc.c */
-#line 386 "a.y"
+ case 81:
+
+/* Line 1806 of yacc.c */
+#line 397 "a.y"
{
(yyval.gen) = (yyvsp[(2) - (2)].gen);
(yyval.gen).index = (yyvsp[(2) - (2)].gen).type;
@@ -2207,9 +2318,10 @@ yyreduce:
}
break;
- case 80:
-/* Line 1778 of yacc.c */
-#line 397 "a.y"
+ case 82:
+
+/* Line 1806 of yacc.c */
+#line 408 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_SCONST;
@@ -2217,9 +2329,10 @@ yyreduce:
}
break;
- case 81:
-/* Line 1778 of yacc.c */
-#line 403 "a.y"
+ case 83:
+
+/* Line 1806 of yacc.c */
+#line 414 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2227,9 +2340,10 @@ yyreduce:
}
break;
- case 82:
-/* Line 1778 of yacc.c */
-#line 409 "a.y"
+ case 84:
+
+/* Line 1806 of yacc.c */
+#line 420 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2237,9 +2351,10 @@ yyreduce:
}
break;
- case 83:
-/* Line 1778 of yacc.c */
-#line 415 "a.y"
+ case 85:
+
+/* Line 1806 of yacc.c */
+#line 426 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2247,9 +2362,10 @@ yyreduce:
}
break;
- case 84:
-/* Line 1778 of yacc.c */
-#line 421 "a.y"
+ case 86:
+
+/* Line 1806 of yacc.c */
+#line 432 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_FCONST;
@@ -2257,9 +2373,10 @@ yyreduce:
}
break;
- case 85:
-/* Line 1778 of yacc.c */
-#line 429 "a.y"
+ case 87:
+
+/* Line 1806 of yacc.c */
+#line 440 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_CONST2;
@@ -2268,45 +2385,50 @@ yyreduce:
}
break;
- case 86:
-/* Line 1778 of yacc.c */
-#line 438 "a.y"
+ case 88:
+
+/* Line 1806 of yacc.c */
+#line 449 "a.y"
{
(yyval.con2).v1 = (yyvsp[(1) - (1)].lval);
(yyval.con2).v2 = 0;
}
break;
- case 87:
-/* Line 1778 of yacc.c */
-#line 443 "a.y"
+ case 89:
+
+/* Line 1806 of yacc.c */
+#line 454 "a.y"
{
(yyval.con2).v1 = -(yyvsp[(2) - (2)].lval);
(yyval.con2).v2 = 0;
}
break;
- case 88:
-/* Line 1778 of yacc.c */
-#line 448 "a.y"
+ case 90:
+
+/* Line 1806 of yacc.c */
+#line 459 "a.y"
{
(yyval.con2).v1 = (yyvsp[(1) - (3)].lval);
(yyval.con2).v2 = (yyvsp[(3) - (3)].lval);
}
break;
- case 89:
-/* Line 1778 of yacc.c */
-#line 453 "a.y"
+ case 91:
+
+/* Line 1806 of yacc.c */
+#line 464 "a.y"
{
(yyval.con2).v1 = -(yyvsp[(2) - (4)].lval);
(yyval.con2).v2 = (yyvsp[(4) - (4)].lval);
}
break;
- case 92:
-/* Line 1778 of yacc.c */
-#line 464 "a.y"
+ case 94:
+
+/* Line 1806 of yacc.c */
+#line 475 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_NONE;
@@ -2314,9 +2436,10 @@ yyreduce:
}
break;
- case 93:
-/* Line 1778 of yacc.c */
-#line 470 "a.y"
+ case 95:
+
+/* Line 1806 of yacc.c */
+#line 481 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2324,9 +2447,10 @@ yyreduce:
}
break;
- case 94:
-/* Line 1778 of yacc.c */
-#line 476 "a.y"
+ case 96:
+
+/* Line 1806 of yacc.c */
+#line 487 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_SP;
@@ -2334,9 +2458,10 @@ yyreduce:
}
break;
- case 95:
-/* Line 1778 of yacc.c */
-#line 482 "a.y"
+ case 97:
+
+/* Line 1806 of yacc.c */
+#line 493 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_NONE;
@@ -2347,9 +2472,10 @@ yyreduce:
}
break;
- case 96:
-/* Line 1778 of yacc.c */
-#line 491 "a.y"
+ case 98:
+
+/* Line 1806 of yacc.c */
+#line 502 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(3) - (9)].lval);
@@ -2360,27 +2486,30 @@ yyreduce:
}
break;
- case 97:
-/* Line 1778 of yacc.c */
-#line 500 "a.y"
+ case 99:
+
+/* Line 1806 of yacc.c */
+#line 511 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(2) - (3)].lval);
}
break;
- case 98:
-/* Line 1778 of yacc.c */
-#line 505 "a.y"
+ case 100:
+
+/* Line 1806 of yacc.c */
+#line 516 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_SP;
}
break;
- case 99:
-/* Line 1778 of yacc.c */
-#line 510 "a.y"
+ case 101:
+
+/* Line 1806 of yacc.c */
+#line 521 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(3) - (4)].lval);
@@ -2388,9 +2517,10 @@ yyreduce:
}
break;
- case 100:
-/* Line 1778 of yacc.c */
-#line 516 "a.y"
+ case 102:
+
+/* Line 1806 of yacc.c */
+#line 527 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+D_NONE;
@@ -2400,9 +2530,10 @@ yyreduce:
}
break;
- case 101:
-/* Line 1778 of yacc.c */
-#line 524 "a.y"
+ case 103:
+
+/* Line 1806 of yacc.c */
+#line 535 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_INDIR+(yyvsp[(2) - (8)].lval);
@@ -2412,17 +2543,19 @@ yyreduce:
}
break;
- case 102:
-/* Line 1778 of yacc.c */
-#line 534 "a.y"
+ case 104:
+
+/* Line 1806 of yacc.c */
+#line 545 "a.y"
{
(yyval.gen) = (yyvsp[(1) - (1)].gen);
}
break;
- case 103:
-/* Line 1778 of yacc.c */
-#line 538 "a.y"
+ case 105:
+
+/* Line 1806 of yacc.c */
+#line 549 "a.y"
{
(yyval.gen) = (yyvsp[(1) - (6)].gen);
(yyval.gen).index = (yyvsp[(3) - (6)].lval);
@@ -2431,9 +2564,10 @@ yyreduce:
}
break;
- case 104:
-/* Line 1778 of yacc.c */
-#line 547 "a.y"
+ case 106:
+
+/* Line 1806 of yacc.c */
+#line 558 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = (yyvsp[(4) - (5)].lval);
@@ -2442,9 +2576,10 @@ yyreduce:
}
break;
- case 105:
-/* Line 1778 of yacc.c */
-#line 554 "a.y"
+ case 107:
+
+/* Line 1806 of yacc.c */
+#line 565 "a.y"
{
(yyval.gen) = nullgen;
(yyval.gen).type = D_STATIC;
@@ -2453,161 +2588,181 @@ yyreduce:
}
break;
- case 106:
-/* Line 1778 of yacc.c */
-#line 562 "a.y"
+ case 108:
+
+/* Line 1806 of yacc.c */
+#line 573 "a.y"
{
(yyval.lval) = 0;
}
break;
- case 107:
-/* Line 1778 of yacc.c */
-#line 566 "a.y"
+ case 109:
+
+/* Line 1806 of yacc.c */
+#line 577 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 108:
-/* Line 1778 of yacc.c */
-#line 570 "a.y"
+ case 110:
+
+/* Line 1806 of yacc.c */
+#line 581 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 110:
-/* Line 1778 of yacc.c */
-#line 577 "a.y"
+ case 112:
+
+/* Line 1806 of yacc.c */
+#line 588 "a.y"
{
(yyval.lval) = D_AUTO;
}
break;
- case 113:
-/* Line 1778 of yacc.c */
-#line 585 "a.y"
+ case 115:
+
+/* Line 1806 of yacc.c */
+#line 596 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
}
break;
- case 114:
-/* Line 1778 of yacc.c */
-#line 589 "a.y"
+ case 116:
+
+/* Line 1806 of yacc.c */
+#line 600 "a.y"
{
(yyval.lval) = -(yyvsp[(2) - (2)].lval);
}
break;
- case 115:
-/* Line 1778 of yacc.c */
-#line 593 "a.y"
+ case 117:
+
+/* Line 1806 of yacc.c */
+#line 604 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (2)].lval);
}
break;
- case 116:
-/* Line 1778 of yacc.c */
-#line 597 "a.y"
+ case 118:
+
+/* Line 1806 of yacc.c */
+#line 608 "a.y"
{
(yyval.lval) = ~(yyvsp[(2) - (2)].lval);
}
break;
- case 117:
-/* Line 1778 of yacc.c */
-#line 601 "a.y"
+ case 119:
+
+/* Line 1806 of yacc.c */
+#line 612 "a.y"
{
(yyval.lval) = (yyvsp[(2) - (3)].lval);
}
break;
- case 119:
-/* Line 1778 of yacc.c */
-#line 608 "a.y"
+ case 121:
+
+/* Line 1806 of yacc.c */
+#line 619 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
}
break;
- case 120:
-/* Line 1778 of yacc.c */
-#line 612 "a.y"
+ case 122:
+
+/* Line 1806 of yacc.c */
+#line 623 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
}
break;
- case 121:
-/* Line 1778 of yacc.c */
-#line 616 "a.y"
+ case 123:
+
+/* Line 1806 of yacc.c */
+#line 627 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
}
break;
- case 122:
-/* Line 1778 of yacc.c */
-#line 620 "a.y"
+ case 124:
+
+/* Line 1806 of yacc.c */
+#line 631 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
}
break;
- case 123:
-/* Line 1778 of yacc.c */
-#line 624 "a.y"
+ case 125:
+
+/* Line 1806 of yacc.c */
+#line 635 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
}
break;
- case 124:
-/* Line 1778 of yacc.c */
-#line 628 "a.y"
+ case 126:
+
+/* Line 1806 of yacc.c */
+#line 639 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
}
break;
- case 125:
-/* Line 1778 of yacc.c */
-#line 632 "a.y"
+ case 127:
+
+/* Line 1806 of yacc.c */
+#line 643 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
}
break;
- case 126:
-/* Line 1778 of yacc.c */
-#line 636 "a.y"
+ case 128:
+
+/* Line 1806 of yacc.c */
+#line 647 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
}
break;
- case 127:
-/* Line 1778 of yacc.c */
-#line 640 "a.y"
+ case 129:
+
+/* Line 1806 of yacc.c */
+#line 651 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
}
break;
- case 128:
-/* Line 1778 of yacc.c */
-#line 644 "a.y"
+ case 130:
+
+/* Line 1806 of yacc.c */
+#line 655 "a.y"
{
(yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
}
break;
-/* Line 1778 of yacc.c */
-#line 2611 "y.tab.c"
+
+/* Line 1806 of yacc.c */
+#line 2766 "y.tab.c"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -2770,9 +2925,7 @@ yyerrlab1:
YY_STACK_PRINT (yyss, yyssp);
}
- YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
- YY_IGNORE_MAYBE_UNINITIALIZED_END
/* Shift the error token. */
@@ -2796,7 +2949,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#if !defined yyoverflow || YYERROR_VERBOSE
+#if !defined(yyoverflow) || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -2838,3 +2991,4 @@ yyreturn:
}
+
diff --git a/src/cmd/8a/y.tab.h b/src/cmd/8a/y.tab.h
index 621aba79f..4d7bbe80d 100644
--- a/src/cmd/8a/y.tab.h
+++ b/src/cmd/8a/y.tab.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 2.6.5. */
+/* A Bison parser, made by GNU Bison 2.5. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,15 +30,6 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
/* Tokens. */
#ifndef YYTOKENTYPE
@@ -61,21 +52,22 @@ extern int yydebug;
LTYPEI = 270,
LTYPEG = 271,
LTYPEXC = 272,
- LCONST = 273,
- LFP = 274,
- LPC = 275,
- LSB = 276,
- LBREG = 277,
- LLREG = 278,
- LSREG = 279,
- LFREG = 280,
- LXREG = 281,
- LFCONST = 282,
- LSCONST = 283,
- LSP = 284,
- LNAME = 285,
- LLAB = 286,
- LVAR = 287
+ LTYPEX = 273,
+ LCONST = 274,
+ LFP = 275,
+ LPC = 276,
+ LSB = 277,
+ LBREG = 278,
+ LLREG = 279,
+ LSREG = 280,
+ LFREG = 281,
+ LXREG = 282,
+ LFCONST = 283,
+ LSCONST = 284,
+ LSP = 285,
+ LNAME = 286,
+ LLAB = 287,
+ LVAR = 288
};
#endif
/* Tokens. */
@@ -94,28 +86,31 @@ extern int yydebug;
#define LTYPEI 270
#define LTYPEG 271
#define LTYPEXC 272
-#define LCONST 273
-#define LFP 274
-#define LPC 275
-#define LSB 276
-#define LBREG 277
-#define LLREG 278
-#define LSREG 279
-#define LFREG 280
-#define LXREG 281
-#define LFCONST 282
-#define LSCONST 283
-#define LSP 284
-#define LNAME 285
-#define LLAB 286
-#define LVAR 287
+#define LTYPEX 273
+#define LCONST 274
+#define LFP 275
+#define LPC 276
+#define LSB 277
+#define LBREG 278
+#define LLREG 279
+#define LSREG 280
+#define LFREG 281
+#define LXREG 282
+#define LFCONST 283
+#define LSCONST 284
+#define LSP 285
+#define LNAME 286
+#define LLAB 287
+#define LVAR 288
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
-/* Line 2042 of yacc.c */
+
+/* Line 2068 of yacc.c */
#line 37 "a.y"
Sym *sym;
@@ -130,8 +125,9 @@ typedef union YYSTYPE
Gen2 gen2;
-/* Line 2042 of yacc.c */
-#line 135 "y.tab.h"
+
+/* Line 2068 of yacc.c */
+#line 131 "y.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -140,18 +136,4 @@ typedef union YYSTYPE
extern YYSTYPE yylval;
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-#endif /* !YY_YY_Y_TAB_H_INCLUDED */
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
index d331eee1a..1b8ceb0c6 100644
--- a/src/cmd/8c/swt.c
+++ b/src/cmd/8c/swt.c
@@ -324,7 +324,7 @@ outcode(void)
zaddr(&b, &p->from, sf);
zaddr(&b, &p->to, st);
}
- Bflush(&b);
+ Bterm(&b);
close(f);
firstp = P;
lastp = P;
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 0b2f2b76e..f93be57e5 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -1055,7 +1055,7 @@ bgen(Node *n, int true, int likely, Prog *to)
}
if(is64(nr->type)) {
- if(!nl->addable) {
+ if(!nl->addable || isconst(nl, CTINT)) {
tempname(&n1, nl->type);
cgen(nl, &n1);
nl = &n1;
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index c4c184bb9..79348a42d 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -1150,6 +1150,7 @@ ismem(Node *n)
case OINDREG:
case ONAME:
case OPARAM:
+ case OCLOSUREVAR:
return 1;
}
return 0;
@@ -2160,11 +2161,11 @@ gins(int as, Node *f, Node *t)
// Generate an instruction referencing *n
// to force segv on nil pointer dereference.
void
-checkref(Node *n)
+checkref(Node *n, int force)
{
Node m;
- if(n->type->type->width < unmappedzero)
+ if(!force && isptr[n->type->etype] && n->type->type->width < unmappedzero)
return;
regalloc(&m, types[TUINTPTR], n);
@@ -2201,8 +2202,6 @@ checkoffset(Addr *a, int canemitcode)
void
naddr(Node *n, Addr *a, int canemitcode)
{
- Prog *p;
-
a->scale = 0;
a->index = D_NONE;
a->type = D_NONE;
@@ -2239,13 +2238,8 @@ naddr(Node *n, Addr *a, int canemitcode)
break;
case OCLOSUREVAR:
- if(!canemitcode)
- fatal("naddr OCLOSUREVAR cannot emit code");
- p = gins(AMOVL, N, N);
- p->from.type = D_DX+D_INDIR;
- p->from.offset = n->xoffset;
- p->to.type = D_BX;
- a->type = D_BX;
+ a->type = D_DX+D_INDIR;
+ a->offset = n->xoffset;
a->sym = S;
break;
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 386889956..93d44eb51 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -153,6 +153,7 @@ enum as
AMOVB,
AMOVL,
AMOVW,
+ AMOVQ,
AMOVBLSX,
AMOVBLZX,
AMOVBWSX,
@@ -397,6 +398,7 @@ enum as
ACMPXCHGW,
ACMPXCHG8B,
+ ACPUID,
ARDTSC,
AXADDB,
@@ -531,6 +533,7 @@ enum as
AORPD,
AORPS,
APADDQ,
+ APAND,
APMAXSW,
APMAXUB,
APMINSW,
@@ -566,7 +569,12 @@ enum as
AUNPCKLPS,
AXORPD,
AXORPS,
-
+
+ /* SSE 3+ */
+ AAESENC,
+ APINSRD,
+ APSHUFB,
+
AUSEFIELD,
ALOCALS,
ATYPE,
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index a00174c36..bfeb13839 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -128,7 +128,7 @@ adddynrel(Sym *s, Reloc *r)
// Handle relocations found in ELF object files.
case 256 + R_386_PC32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name);
if(targ->type == 0 || targ->type == SXREF)
diag("unknown symbol %s in pcrel", targ->name);
@@ -139,7 +139,7 @@ adddynrel(Sym *s, Reloc *r)
case 256 + R_386_PLT32:
r->type = D_PCREL;
r->add += 4;
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add += targ->plt;
@@ -147,7 +147,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_386_GOT32:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
// turn MOVL of GOT entry into LEAL of symbol itself
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
@@ -175,19 +175,19 @@ adddynrel(Sym *s, Reloc *r)
return;
case 256 + R_386_32:
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name);
r->type = D_ADDR;
return;
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0:
r->type = D_ADDR;
- if(targ->dynimpname != nil && !targ->dynexport)
+ if(targ->type == SDYNIMPORT)
diag("unexpected reloc for dynamic symbol %s", targ->name);
return;
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
- if(targ->dynimpname != nil && !targ->dynexport) {
+ if(targ->type == SDYNIMPORT) {
addpltsym(targ);
r->sym = lookup(".plt", 0);
r->add = targ->plt;
@@ -198,7 +198,7 @@ adddynrel(Sym *s, Reloc *r)
return;
case 512 + MACHO_FAKE_GOTPCREL:
- if(targ->dynimpname == nil || targ->dynexport) {
+ if(targ->type != SDYNIMPORT) {
// have symbol
// turn MOVL of GOT entry into LEAL of symbol itself
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
@@ -217,7 +217,7 @@ adddynrel(Sym *s, Reloc *r)
}
// Handle references to ELF symbols from our own object files.
- if(targ->dynimpname == nil || targ->dynexport)
+ if(targ->type != SDYNIMPORT)
return;
switch(r->type) {
@@ -270,12 +270,13 @@ adddynrel(Sym *s, Reloc *r)
}
int
-elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+elfreloc1(Reloc *r, vlong sectoff)
{
- USED(add); // written to obj file by ../ld/data.c's reloc
+ int32 elfsym;
- LPUT(off);
+ LPUT(sectoff);
+ elfsym = r->xsym->elfsym;
switch(r->type) {
default:
return -1;
@@ -298,6 +299,78 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
return 0;
}
+int
+machoreloc1(Reloc *r, vlong sectoff)
+{
+ uint32 v;
+ Sym *rs;
+
+ rs = r->xsym;
+
+ if(rs->type == SHOSTOBJ) {
+ if(rs->dynid < 0) {
+ diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
+ return -1;
+ }
+ v = rs->dynid;
+ v |= 1<<27; // external relocation
+ } else {
+ v = rs->sect->extnum;
+ if(v == 0) {
+ diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type);
+ return -1;
+ }
+ }
+
+ switch(r->type) {
+ default:
+ return -1;
+ case D_ADDR:
+ v |= MACHO_GENERIC_RELOC_VANILLA<<28;
+ break;
+ case D_PCREL:
+ v |= 1<<24; // pc-relative bit
+ v |= MACHO_GENERIC_RELOC_VANILLA<<28;
+ break;
+ }
+
+ switch(r->siz) {
+ default:
+ return -1;
+ case 1:
+ v |= 0<<25;
+ break;
+ case 2:
+ v |= 1<<25;
+ break;
+ case 4:
+ v |= 2<<25;
+ break;
+ case 8:
+ v |= 3<<25;
+ break;
+ }
+
+ LPUT(sectoff);
+ LPUT(v);
+ return 0;
+}
+
+int
+archreloc(Reloc *r, Sym *s, vlong *val)
+{
+ USED(s);
+ switch(r->type) {
+ case D_CONST:
+ *val = r->add;
+ return 0;
+ case D_GOTOFF:
+ *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
+ return 0;
+ }
+ return -1;
+}
+
void
elfsetupplt(void)
{
@@ -326,21 +399,6 @@ elfsetupplt(void)
}
}
-int
-archreloc(Reloc *r, Sym *s, vlong *val)
-{
- USED(s);
- switch(r->type) {
- case D_CONST:
- *val = r->add;
- return 0;
- case D_GOTOFF:
- *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
- return 0;
- }
- return -1;
-}
-
static void
addpltsym(Sym *s)
{
@@ -428,26 +486,20 @@ addgotsym(Sym *s)
void
adddynsym(Sym *s)
{
- Sym *d, *str;
+ Sym *d;
int t;
char *name;
- vlong off;
if(s->dynid >= 0)
return;
- if(s->dynimpname == nil)
- diag("adddynsym: no dynamic name for %s", s->name);
-
if(iself) {
s->dynid = nelfsym++;
d = lookup(".dynsym", 0);
/* name */
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
+ name = s->extname;
adduint32(d, addstring(lookup(".dynstr", 0), name));
/* value */
@@ -461,7 +513,7 @@ adddynsym(Sym *s)
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && (s->type&SMASK) == STEXT)
+ if(s->cgoexport && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -469,7 +521,7 @@ adddynsym(Sym *s)
adduint8(d, 0);
/* shndx */
- if(!s->dynexport && s->dynimpname != nil)
+ if(s->type == SDYNIMPORT)
adduint16(d, SHN_UNDEF);
else {
switch(s->type) {
@@ -490,57 +542,10 @@ adddynsym(Sym *s)
adduint16(d, t);
}
} else if(HEADTYPE == Hdarwin) {
- // Mach-O symbol nlist32
- d = lookup(".dynsym", 0);
- name = s->dynimpname;
- if(name == nil)
- name = s->name;
- if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
- symgrow(d, ndynexp*12);
- }
- if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
- s->dynid = -s->dynid-100;
- off = s->dynid*12;
- } else {
- off = d->size;
- s->dynid = off/12;
- }
- // darwin still puts _ prefixes on all C symbols
- str = lookup(".dynstr", 0);
- setuint32(d, off, str->size);
- off += 4;
- adduint8(str, '_');
- addstring(str, name);
- if(s->type == SDYNIMPORT) {
- setuint8(d, off, 0x01); // type - N_EXT - external symbol
- off++;
- setuint8(d, off, 0); // section
- off++;
- } else {
- setuint8(d, off, 0x0f);
- off++;
- switch(s->type) {
- default:
- case STEXT:
- setuint8(d, off, 1);
- break;
- case SDATA:
- setuint8(d, off, 2);
- break;
- case SBSS:
- setuint8(d, off, 4);
- break;
- }
- off++;
- }
- setuint16(d, off, 0); // desc
- off += 2;
- if(s->type == SDYNIMPORT)
- setuint32(d, off, 0); // value
- else
- setaddr(d, off, s);
- off += 4;
- } else if(HEADTYPE != Hwindows) {
+ diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
+ } else if(HEADTYPE == Hwindows) {
+ // already taken care of
+ } else {
diag("adddynsym: unsupported binary format");
}
}
@@ -666,7 +671,7 @@ asmb(void)
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
- if(isobj)
+ if(linkmode == LinkExternal)
elfemitreloc();
}
break;
@@ -688,6 +693,10 @@ asmb(void)
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
break;
+ case Hdarwin:
+ if(linkmode == LinkExternal)
+ machoemitreloc();
+ break;
}
}
if(debug['v'])
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index f88f058e3..980a7f830 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -42,6 +42,7 @@ enum
thechar = '8',
PtrSize = 4,
IntSize = 4,
+ MaxAlign = 32, // max data alignment
FuncAlign = 16
};
@@ -83,9 +84,12 @@ struct Reloc
{
int32 off;
uchar siz;
+ uchar done;
int32 type;
int32 add;
+ int32 xadd;
Sym* sym;
+ Sym* xsym;
};
struct Prog
@@ -122,11 +126,12 @@ struct Auto
struct Sym
{
char* name;
+ char* extname; // name used in external object files
short type;
short version;
uchar dupok;
uchar reachable;
- uchar dynexport;
+ uchar cgoexport;
uchar special;
uchar stkcheck;
uchar hide;
@@ -149,7 +154,6 @@ struct Sym
Sym* reachparent;
Sym* queue;
char* file;
- char* dynimpname;
char* dynimplib;
char* dynimpvers;
struct Section* sect;
@@ -172,7 +176,7 @@ struct Optab
short as;
uchar* ytab;
uchar prefix;
- uchar op[10];
+ uchar op[12];
};
enum
@@ -217,6 +221,7 @@ enum
Zxxx = 0,
Zlit,
+ Zlitm_r,
Z_rp,
Zbr,
Zcall,
@@ -233,6 +238,7 @@ enum
Zloop,
Zm_o,
Zm_r,
+ Zm2_r,
Zm_r_xm,
Zm_r_i_xm,
Zaut_r,
@@ -249,6 +255,7 @@ enum
Zib_rr,
Zil_rr,
Zclr,
+ Zibm_r, /* mmx1,mmx2/mem64,imm8 */
Zbyte,
Zmov,
Zmax,
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index dcb8390b9..306e288a3 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -90,6 +90,7 @@ main(int argc, char *argv[])
INITRND = -1;
INITENTRY = 0;
LIBINITENTRY = 0;
+ linkmode = LinkInternal; // TODO: LinkAuto once everything works.
nuxiinit();
flagcount("1", "use alternate profiling code", &debug['1']);
@@ -114,7 +115,7 @@ main(int argc, char *argv[])
flagcount("d", "disable dynamic executable", &debug['d']);
flagcount("f", "ignore version mismatch", &debug['f']);
flagcount("g", "disable go package data checks", &debug['g']);
- flagcount("hostobj", "generate host object file", &isobj);
+ flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode);
flagstr("k", "sym: set field tracking symbol", &tracksym);
flagstr("o", "outfile: set output file", &outfile);
flagcount("p", "insert profiling code", &debug['p']);
@@ -122,9 +123,11 @@ main(int argc, char *argv[])
flagcount("race", "enable race detector", &flag_race);
flagcount("s", "disable symbol table", &debug['s']);
flagcount("n", "dump symbol table", &debug['n']);
+ flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
flagcount("u", "reject unsafe packages", &debug['u']);
flagcount("v", "print link trace", &debug['v']);
flagcount("w", "disable DWARF generation", &debug['w']);
+ // TODO: link mode flag
flagparse(&argc, &argv, usage);
@@ -136,13 +139,19 @@ main(int argc, char *argv[])
if(HEADTYPE == -1)
HEADTYPE = headtype(goos);
- if(isobj) {
- switch(HEADTYPE) {
- default:
- sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE));
- case Hlinux:
- break;
- }
+ switch(HEADTYPE) {
+ default:
+ if(linkmode == LinkAuto)
+ linkmode = LinkInternal;
+ if(linkmode == LinkExternal)
+ sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
+ break;
+ case Hdarwin:
+ case Hfreebsd:
+ case Hlinux:
+ case Hnetbsd:
+ case Hopenbsd:
+ break;
}
if(outfile == nil) {
@@ -308,6 +317,8 @@ main(int argc, char *argv[])
reloc();
asmb();
undef();
+ hostlink();
+
if(debug['v']) {
Bprint(&bso, "%5.2f cpu time\n", cputime());
Bprint(&bso, "%d symbols\n", nsymbol);
@@ -431,7 +442,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
ntext = 0;
eof = Boffset(f) + len;
src[0] = 0;
-
+ pn = estrdup(pn); // we keep it in Sym* references
newloop:
memset(h, 0, sizeof(h));
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
index 79d7b39f0..a6ebf063e 100644
--- a/src/cmd/8l/optab.c
+++ b/src/cmd/8l/optab.c
@@ -150,9 +150,16 @@ uchar ymovl[] =
// Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
Yi32, Yrl, Zil_rp, 1,
Yi32, Yml, Zilo_m, 2,
+ Yml, Yxr, Zm_r_xm, 2, // XMM MOVD (32 bit)
+ Yxr, Yml, Zr_m_xm, 2, // XMM MOVD (32 bit)
Yiauto, Yrl, Zaut_r, 2,
0
};
+uchar ymovq[] =
+{
+ Yml, Yxr, Zm_r_xm, 2,
+ 0
+};
uchar ym_rl[] =
{
Ym, Yrl, Zm_r, 1,
@@ -435,6 +442,21 @@ uchar yprefetch[] =
Ym, Ynone, Zm_o, 2,
0,
};
+uchar yaes[] =
+{
+ Yxm, Yxr, Zlitm_r, 2,
+ 0
+};
+uchar yinsrd[] =
+{
+ Yml, Yxr, Zibm_r, 2,
+ 0
+};
+uchar ymshufb[] =
+{
+ Yxm, Yxr, Zm2_r, 2,
+ 0
+};
Optab optab[] =
/* as, ytab, andproto, opcode */
@@ -552,8 +574,9 @@ Optab optab[] =
{ ALSLL, yml_rl, Pm, 0x03 },
{ ALSLW, yml_rl, Pq, 0x03 },
{ AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) },
- { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00) },
+ { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e },
{ AMOVW, ymovl, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00) },
+ { AMOVQ, ymovq, Pf3, 0x7e },
{ AMOVBLSX, ymb_rl, Pm, 0xbe },
{ AMOVBLZX, ymb_rl, Pm, 0xb6 },
{ AMOVBWSX, ymb_rl, Pq, 0xbe },
@@ -793,6 +816,7 @@ Optab optab[] =
{ ACMPXCHGW, yrl_ml, Pm, 0xb1 },
{ ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
+ { ACPUID, ynone, Pm, 0xa2 },
{ ARDTSC, ynone, Pm, 0x31 },
{ AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
@@ -925,6 +949,7 @@ Optab optab[] =
{ AORPD, yxm, Pq, 0x56 },
{ AORPS, yxm, Pm, 0x56 },
{ APADDQ, yxm, Pe, 0xd4 },
+ { APAND, yxm, Pe, 0xdb },
{ APMAXSW, yxm, Pe, 0xee },
{ APMAXUB, yxm, Pe, 0xde },
{ APMINSW, yxm, Pe, 0xea },
@@ -961,6 +986,10 @@ Optab optab[] =
{ AXORPD, yxm, Pe, 0x57 },
{ AXORPS, yxm, Pm, 0x57 },
+ { AAESENC, yaes, Pq, 0x38,0xdc,(0) },
+ { APINSRD, yinsrd, Pq, 0x3a, 0x22, (00) },
+ { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
+
{ AUSEFIELD, ynop, Px, 0,0 },
{ ALOCALS },
{ ATYPE },
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index b828d8645..0678fa8f2 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -1003,11 +1003,23 @@ found:
*andptr++ = op;
break;
+ case Zlitm_r:
+ for(; op = o->op[z]; z++)
+ *andptr++ = op;
+ asmand(&p->from, reg[p->to.type]);
+ break;
+
case Zm_r:
*andptr++ = op;
asmand(&p->from, reg[p->to.type]);
break;
+ case Zm2_r:
+ *andptr++ = op;
+ *andptr++ = o->op[z+1];
+ asmand(&p->from, reg[p->to.type]);
+ break;
+
case Zm_r_xm:
mediaop(o, op, t[3], z);
asmand(&p->from, reg[p->to.type]);
@@ -1019,6 +1031,13 @@ found:
*andptr++ = p->to.offset;
break;
+ case Zibm_r:
+ while ((op = o->op[z++]) != 0)
+ *andptr++ = op;
+ asmand(&p->from, reg[p->to.type]);
+ *andptr++ = p->to.offset;
+ break;
+
case Zaut_r:
*andptr++ = 0x8d; /* leal */
if(p->from.type != D_ADDR)
diff --git a/src/cmd/addr2line/main.c b/src/cmd/addr2line/main.c
index 6b2fe5dfe..9faadc27b 100644
--- a/src/cmd/addr2line/main.c
+++ b/src/cmd/addr2line/main.c
@@ -12,12 +12,18 @@
#include <mach.h>
void
+printusage(int fd)
+{
+ fprint(fd, "usage: addr2line binary\n");
+ fprint(fd, "reads addresses from standard input and writes two lines for each:\n");
+ fprint(fd, "\tfunction name\n");
+ fprint(fd, "\tfile:line\n");
+}
+
+void
usage(void)
{
- fprint(2, "usage: addr2line binary\n");
- fprint(2, "reads addresses from standard input and writes two lines for each:\n");
- fprint(2, "\tfunction name\n");
- fprint(2, "\tfile:line\n");
+ printusage(2);
exits("usage");
}
@@ -32,6 +38,11 @@ main(int argc, char **argv)
Biobuf bin, bout;
char file[1024];
+ if(argc > 1 && strcmp(argv[1], "--help") == 0) {
+ printusage(1);
+ exits(0);
+ }
+
ARGBEGIN{
default:
usage();
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 0d76b0cdb..d5e66428b 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -138,9 +138,7 @@ func main() {
}
for _, pkg := range pkgs {
- if strings.HasPrefix(pkg, "cmd/") ||
- strings.HasPrefix(pkg, "exp/") ||
- strings.HasPrefix(pkg, "old/") {
+ if strings.HasPrefix(pkg, "cmd/") {
continue
}
if fi, err := os.Stat(filepath.Join(w.root, pkg)); err != nil || !fi.IsDir() {
@@ -725,7 +723,6 @@ func (w *Walker) varValueType(vi interface{}) (string, error) {
default:
return "", fmt.Errorf("unknown const value type %T", vi)
}
- panic("unreachable")
}
// resolveName finds a top-level node named name and returns the node
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
index 2f038f520..34163ff92 100644
--- a/src/cmd/cc/dpchk.c
+++ b/src/cmd/cc/dpchk.c
@@ -692,22 +692,24 @@ pragcgo(char *verb)
goto out;
}
- if(strcmp(verb, "cgo_export") == 0 || strcmp(verb, "dynexport") == 0) {
+ if(strcmp(verb, "dynexport") == 0)
+ verb = "cgo_export_dynamic";
+ if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
local = getimpsym();
if(local == nil)
goto err2;
if(!more()) {
- fmtprint(&pragcgobuf, "cgo_export %q\n", local->name);
+ fmtprint(&pragcgobuf, "%s %q\n", verb, local->name);
goto out;
}
remote = getimpsym();
if(remote == nil)
goto err2;
- fmtprint(&pragcgobuf, "cgo_export %q %q\n", local->name, remote->name);
+ fmtprint(&pragcgobuf, "%s %q %q\n", verb, local->name, remote->name);
goto out;
err2:
- yyerror("usage: #pragma cgo_export local [remote]");
+ yyerror("usage: #pragma %s local [remote]", verb);
goto out;
}
@@ -749,6 +751,18 @@ pragcgo(char *verb)
goto out;
}
+ if(strcmp(verb, "cgo_ldflag") == 0) {
+ p = getquoted();
+ if(p == nil)
+ goto err5;
+ fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
+ goto out;
+
+ err5:
+ yyerror("usage: #pragma cgo_ldflag \"arg\"");
+ goto out;
+ }
+
out:
while(getnsc() != '\n')
;
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 955b7c495..efbeae958 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -70,7 +70,7 @@ assignment context to retrieve both the return value (if any) and the
C errno variable as an error (use _ to skip the result value if the
function returns void). For example:
- n, err := C.atoi("abc")
+ n, err := C.sqrt(-1)
_, err := C.voidFunc()
In C, a function argument written as a fixed size array
@@ -484,16 +484,16 @@ The directives are:
Example:
#pragma cgo_dynamic_linker "/lib/ld-linux.so.2"
-#pragma cgo_export <local> <remote>
+#pragma cgo_export_dynamic <local> <remote>
- In both internal and external linking modes, put the Go symbol
+ In internal linking mode, put the Go symbol
named <local> into the program's exported symbol table as
<remote>, so that C code can refer to it by that name. This
mechanism makes it possible for C code to call back into Go or
to share Go's data.
For compatibility with current versions of SWIG,
- #pragma dynexport is an alias for #pragma cgo_export.
+ #pragma dynexport is an alias for #pragma cgo_export_dynamic.
#pragma cgo_import_static <local>
@@ -505,6 +505,14 @@ The directives are:
Example:
#pragma cgo_import_static puts_wrapper
+#pragma cgo_export_static <local> <remote>
+
+ In external linking mode, put the Go symbol
+ named <local> into the program's exported symbol table as
+ <remote>, so that C code can refer to it by that name. This
+ mechanism makes it possible for C code to call back into Go or
+ to share Go's data.
+
#pragma cgo_ldflag "<arg>"
In external linking mode, invoke the host linker (usually gcc)
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 4b0a521a8..585f01477 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -139,11 +139,7 @@ NextLine:
// addToFlag appends args to flag. All flags are later written out onto the
// _cgo_flags file for the build system to use.
func (p *Package) addToFlag(flag string, args []string) {
- if oldv, ok := p.CgoFlags[flag]; ok {
- p.CgoFlags[flag] = oldv + " " + strings.Join(args, " ")
- } else {
- p.CgoFlags[flag] = strings.Join(args, " ")
- }
+ p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
if flag == "CFLAGS" {
// We'll also need these when preprocessing for dwarf information.
p.GccOptions = append(p.GccOptions, args...)
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 7adc795de..ca370ef3f 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -33,7 +33,7 @@ type Package struct {
PtrSize int64
IntSize int64
GccOptions []string
- CgoFlags map[string]string // #cgo flags (CFLAGS, LDFLAGS)
+ CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS)
Written map[string]bool
Name map[string]*Name // accumulated Name from Files
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
@@ -312,7 +312,7 @@ func newPackage(args []string) *Package {
PtrSize: ptrSize,
IntSize: intSize,
GccOptions: gccOptions,
- CgoFlags: make(map[string]string),
+ CgoFlags: make(map[string][]string),
Written: make(map[string]bool),
}
return p
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index a126cf17f..ee1d89142 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -31,7 +31,12 @@ func (p *Package) writeDefs() {
fflg := creat(*objDir + "_cgo_flags")
for k, v := range p.CgoFlags {
- fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v)
+ fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
+ if k == "LDFLAGS" {
+ for _, arg := range v {
+ fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
+ }
+ }
}
fflg.Close()
@@ -100,6 +105,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
+ fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
cVars[n.C] = true
@@ -651,8 +657,9 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
if fn.Recv != nil {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
- fmt.Fprintf(fc, "#pragma cgo_export %s\n", goname)
+ fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
+ fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
fmt.Fprintf(fc, "void\n")
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index dda45ca62..fd6a329c4 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -313,7 +313,6 @@ static char *unreleased[] = {
"src/cmd/cov",
"src/cmd/prof",
"src/pkg/old",
- "src/pkg/exp",
};
// setup sets up the tree for the initial build.
@@ -795,6 +794,9 @@ install(char *dir)
bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
+ p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
+ if(isfile(p))
+ copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
copy(bpathf(&b, "%s/os_GOOS.h", workdir),
bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
@@ -940,6 +942,8 @@ install(char *dir)
}
vadd(&compile, "-I");
vadd(&compile, workdir);
+ vadd(&compile, "-I");
+ vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
vadd(&compile, "-D");
vadd(&compile, bprintf(&b, "GOOS_%s", goos));
vadd(&compile, "-D");
@@ -1045,7 +1049,16 @@ out:
static bool
matchfield(char *f)
{
- return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap");
+ char *p;
+ bool res;
+
+ p = xstrrchr(f, ',');
+ if(p == nil)
+ return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1");
+ *p = 0;
+ res = matchfield(f) && matchfield(p+1);
+ *p = ',';
+ return res;
}
// shouldbuild reports whether we should build this file.
@@ -1071,7 +1084,8 @@ shouldbuild(char *file, char *dir)
name = lastelem(file);
if(streq(name, "goos.c") || streq(name, "flag.c"))
return 1;
- return 0;
+ if(!contains(name, "plan9"))
+ return 0;
}
if(streq(dir, "libbio"))
return 0;
@@ -1574,7 +1588,7 @@ cmdclean(int argc, char **argv)
void
cmdbanner(int argc, char **argv)
{
- char *pathsep;
+ char *pathsep, *pid, *ns;
Buf b, b1, search, path;
ARGBEGIN{
@@ -1598,15 +1612,28 @@ cmdbanner(int argc, char **argv)
xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot);
xprintf("Installed commands in %s\n", gobin);
- // Check that gobin appears in $PATH.
- xgetenv(&b, "PATH");
- pathsep = ":";
- if(streq(gohostos, "windows"))
- pathsep = ";";
- bprintf(&b1, "%s%s%s", pathsep, bstr(&b), pathsep);
- bprintf(&search, "%s%s%s", pathsep, gobin, pathsep);
- if(xstrstr(bstr(&b1), bstr(&search)) == nil)
- xprintf("*** You need to add %s to your PATH.\n", gobin);
+ if(streq(gohostos, "plan9")) {
+ // Check that gobin is bound before /bin.
+ readfile(&b, "#c/pid");
+ bsubst(&b, " ", "");
+ pid = btake(&b);
+ bprintf(&b, "/proc/%s/ns", pid);
+ ns = btake(&b);
+ readfile(&b, ns);
+ bprintf(&search, "bind -b %s /bin\n", gobin);
+ if(xstrstr(bstr(&b), bstr(&search)) == nil)
+ xprintf("*** You need to bind %s before /bin.\n", gobin);
+ } else {
+ // Check that gobin appears in $PATH.
+ xgetenv(&b, "PATH");
+ pathsep = ":";
+ if(streq(gohostos, "windows"))
+ pathsep = ";";
+ bprintf(&b1, "%s%s%s", pathsep, bstr(&b), pathsep);
+ bprintf(&search, "%s%s%s", pathsep, gobin, pathsep);
+ if(xstrstr(bstr(&b1), bstr(&search)) == nil)
+ xprintf("*** You need to add %s to your PATH.\n", gobin);
+ }
if(streq(gohostos, "darwin")) {
if(isfile(bpathf(&path, "%s/cov", tooldir)))
diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c
index 7bcda4508..ba23a7ae8 100644
--- a/src/cmd/dist/windows.c
+++ b/src/cmd/dist/windows.c
@@ -271,6 +271,8 @@ static void bgwait1(void);
static void
genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
{
+ // Another copy of this logic is in ../../lib9/run_windows.c.
+ // If there's a bug here, fix the logic there too.
int i, j, nslash;
Buf cmd;
char *q;
diff --git a/src/cmd/fix/netipv6zone.go b/src/cmd/fix/netipv6zone.go
index 587b9ffec..fe973a211 100644
--- a/src/cmd/fix/netipv6zone.go
+++ b/src/cmd/fix/netipv6zone.go
@@ -14,7 +14,7 @@ var netipv6zoneFix = fix{
"netipv6zone",
"2012-11-26",
netipv6zone,
- `Adapt element key to IPNet, IPAddr, UDPAddr or TCPAddr composite literals.
+ `Adapt element key to IPAddr, UDPAddr or TCPAddr composite literals.
https://codereview.appspot.com/6849045/
`,
@@ -39,7 +39,7 @@ func netipv6zone(f *ast.File) bool {
return
}
switch ss := se.Sel.String(); ss {
- case "IPNet", "IPAddr", "UDPAddr", "TCPAddr":
+ case "IPAddr", "UDPAddr", "TCPAddr":
for i, e := range cl.Elts {
if _, ok := e.(*ast.KeyValueExpr); ok {
break
@@ -51,11 +51,8 @@ func netipv6zone(f *ast.File) bool {
Value: e,
}
case 1:
- if ss == "IPNet" {
- cl.Elts[i] = &ast.KeyValueExpr{
- Key: ast.NewIdent("Mask"),
- Value: e,
- }
+ if e.(*ast.BasicLit).Value == "0" {
+ cl.Elts = append(cl.Elts[:i], cl.Elts[i+1:]...)
} else {
cl.Elts[i] = &ast.KeyValueExpr{
Key: ast.NewIdent("Port"),
diff --git a/src/cmd/fix/netipv6zone_test.go b/src/cmd/fix/netipv6zone_test.go
index 229daa386..0fab00531 100644
--- a/src/cmd/fix/netipv6zone_test.go
+++ b/src/cmd/fix/netipv6zone_test.go
@@ -15,36 +15,24 @@ var netipv6zoneTests = []testCase{
import "net"
-var a = []struct {
- *net.IPNet
-}{
- &net.IPNet{net.ParseIP("2001:DB8::"), net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
-}
-
func f() net.Addr {
- b := net.IPNet{net.IPv4(127, 0, 0, 1), net.IPv4Mask(255, 0, 0, 0)}
- c := &net.IPAddr{ip1}
+ a := &net.IPAddr{ip1}
sub(&net.UDPAddr{ip2, 12345})
- d := &net.TCPAddr{IP: ip3, Port: 54321}
- return &net.TCPAddr{ip4}, nil
+ c := &net.TCPAddr{IP: ip3, Port: 54321}
+ d := &net.TCPAddr{ip4, 0}
+ return &net.TCPAddr{ip5}, nil
}
`,
Out: `package main
import "net"
-var a = []struct {
- *net.IPNet
-}{
- &net.IPNet{IP: net.ParseIP("2001:DB8::"), Mask: net.IPMask(net.ParseIP("ffff:ffff:ffff::"))},
-}
-
func f() net.Addr {
- b := net.IPNet{IP: net.IPv4(127, 0, 0, 1), Mask: net.IPv4Mask(255, 0, 0, 0)}
- c := &net.IPAddr{IP: ip1}
+ a := &net.IPAddr{IP: ip1}
sub(&net.UDPAddr{IP: ip2, Port: 12345})
- d := &net.TCPAddr{IP: ip3, Port: 54321}
- return &net.TCPAddr{IP: ip4}, nil
+ c := &net.TCPAddr{IP: ip3, Port: 54321}
+ d := &net.TCPAddr{IP: ip4}
+ return &net.TCPAddr{IP: ip5}, nil
}
`,
},
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index 7de448d1e..f1d0931d4 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -63,7 +63,13 @@ char *runtimeimport =
"func @\"\".equal (@\"\".typ·2 *byte, @\"\".x1·3 any, @\"\".x2·4 any) (@\"\".ret·1 bool)\n"
"func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64) (@\"\".hmap·1 map[any]any)\n"
"func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 any)\n"
+ "func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
+ "func @\"\".mapaccess1_fast64 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
+ "func @\"\".mapaccess1_faststr (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
"func @\"\".mapaccess2 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_fast32 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_fast64 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_faststr (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
"func @\"\".mapassign1 (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any, @\"\".val·4 any)\n"
"func @\"\".mapiterinit (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".hiter·3 *any)\n"
"func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any)\n"
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index 4e029ef83..aca30dc1c 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -60,6 +60,7 @@ closurebody(NodeList *body)
func = curfn;
func->nbody = body;
+ func->endlineno = lineno;
funcbody(func);
// closure-specific variables are hanging off the
@@ -154,6 +155,7 @@ makeclosure(Node *func, int nowrap)
declare(xfunc->nname, PFUNC);
xfunc->nname->funcdepth = func->funcdepth;
xfunc->funcdepth = func->funcdepth;
+ xfunc->endlineno = func->endlineno;
// declare variables holding addresses taken from closure
// and initialize in entry prologue.
@@ -255,26 +257,167 @@ walkclosure(Node *func, NodeList **init)
return clos;
}
-// Special case for closures that get called in place.
-// Optimize runtime.closure(X, __func__xxxx_, .... ) away
-// to __func__xxxx_(Y ....).
-// On entry, expect n->op == OCALL, n->left->op == OCLOSURE.
+static Node *makepartialcall(Node*, Type*, Node*);
+
void
-walkcallclosure(Node *n, NodeList **init)
+typecheckpartialcall(Node *fn, Node *sym)
+{
+ switch(fn->op) {
+ case ODOTINTER:
+ case ODOTMETH:
+ break;
+ default:
+ fatal("invalid typecheckpartialcall");
+ }
+
+ // Create top-level function.
+ fn->nname = makepartialcall(fn, fn->type, sym);
+ fn->right = sym;
+ fn->op = OCALLPART;
+ fn->type = fn->nname->type;
+}
+
+static Node*
+makepartialcall(Node *fn, Type *t0, Node *meth)
{
- USED(init);
- if (n->op != OCALLFUNC || n->left->op != OCLOSURE) {
- dump("walkcallclosure", n);
- fatal("abuse of walkcallclosure");
+ Node *ptr, *n, *call, *xtype, *xfunc, *cv;
+ Type *rcvrtype, *basetype, *t;
+ NodeList *body, *l, *callargs, *retargs;
+ char *p;
+ Sym *sym;
+ int i;
+
+ // TODO: names are not right
+ rcvrtype = fn->left->type;
+ if(exportname(meth->sym->name))
+ p = smprint("%-hT.%s·fm", rcvrtype, meth->sym->name);
+ else
+ p = smprint("%-hT.(%-S)·fm", rcvrtype, meth->sym);
+ basetype = rcvrtype;
+ if(isptr[rcvrtype->etype])
+ basetype = basetype->type;
+ if(basetype->sym == S)
+ fatal("missing base type for %T", rcvrtype);
+
+ sym = pkglookup(p, basetype->sym->pkg);
+ free(p);
+ if(sym->flags & SymUniq)
+ return sym->def;
+ sym->flags |= SymUniq;
+
+ xtype = nod(OTFUNC, N, N);
+ i = 0;
+ l = nil;
+ callargs = nil;
+ xfunc = nod(ODCLFUNC, N, N);
+ for(t = getinargx(t0)->type; t; t = t->down) {
+ snprint(namebuf, sizeof namebuf, "a%d", i++);
+ n = newname(lookup(namebuf));
+ n->class = PPARAM;
+ xfunc->dcl = list(xfunc->dcl, n);
+ callargs = list(callargs, n);
+ l = list(l, nod(ODCLFIELD, n, typenod(t->type)));
}
+ xtype->list = l;
+ i = 0;
+ l = nil;
+ retargs = nil;
+ for(t = getoutargx(t0)->type; t; t = t->down) {
+ snprint(namebuf, sizeof namebuf, "r%d", i++);
+ n = newname(lookup(namebuf));
+ n->class = PPARAMOUT;
+ xfunc->dcl = list(xfunc->dcl, n);
+ retargs = list(retargs, n);
+ l = list(l, nod(ODCLFIELD, n, typenod(t->type)));
+ }
+ xtype->rlist = l;
- // New arg list for n. First the closure-args
- // and then the original parameter list.
- n->list = concat(n->left->enter, n->list);
- n->left = n->left->closure->nname;
- dowidth(n->left->type);
- n->type = getoutargx(n->left->type);
- // for a single valued function, pull the field type out of the struct
- if (n->type && n->type->type && !n->type->type->down)
- n->type = n->type->type->type;
+ xfunc->dupok = 1;
+ xfunc->nname = newname(sym);
+ xfunc->nname->sym->flags |= SymExported; // disable export
+ xfunc->nname->ntype = xtype;
+ xfunc->nname->defn = xfunc;
+ declare(xfunc->nname, PFUNC);
+
+ // Declare and initialize variable holding receiver.
+ body = nil;
+ cv = nod(OCLOSUREVAR, N, N);
+ cv->xoffset = widthptr;
+ cv->type = rcvrtype;
+ ptr = nod(ONAME, N, N);
+ ptr->sym = lookup("rcvr");
+ ptr->class = PAUTO;
+ ptr->addable = 1;
+ ptr->ullman = 1;
+ ptr->used = 1;
+ ptr->curfn = xfunc;
+ xfunc->dcl = list(xfunc->dcl, ptr);
+ if(isptr[rcvrtype->etype] || isinter(rcvrtype)) {
+ ptr->ntype = typenod(rcvrtype);
+ body = list(body, nod(OAS, ptr, cv));
+ } else {
+ ptr->ntype = typenod(ptrto(rcvrtype));
+ body = list(body, nod(OAS, ptr, nod(OADDR, cv, N)));
+ }
+
+ call = nod(OCALL, nod(OXDOT, ptr, meth), N);
+ call->list = callargs;
+ if(t0->outtuple == 0) {
+ body = list(body, call);
+ } else {
+ n = nod(OAS2, N, N);
+ n->list = retargs;
+ n->rlist = list1(call);
+ body = list(body, n);
+ n = nod(ORETURN, N, N);
+ body = list(body, n);
+ }
+
+ xfunc->nbody = body;
+
+ typecheck(&xfunc, Etop);
+ sym->def = xfunc;
+ xtop = list(xtop, xfunc);
+
+ return xfunc;
+}
+
+Node*
+walkpartialcall(Node *n, NodeList **init)
+{
+ Node *clos, *typ;
+
+ // Create closure in the form of a composite literal.
+ // For x.M with receiver (x) type T, the generated code looks like:
+ //
+ // clos = &struct{F uintptr; R T}{M.T·f, x}
+ //
+ // Like walkclosure above.
+
+ if(isinter(n->left->type)) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
+
+ typ = nod(OTSTRUCT, N, N);
+ typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR])));
+ typ->list = list(typ->list, nod(ODCLFIELD, newname(lookup("R")), typenod(n->left->type)));
+
+ clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
+ clos->esc = n->esc;
+ clos->right->implicit = 1;
+ clos->list = list1(nod(OCFUNC, n->nname->nname, N));
+ clos->list = list(clos->list, n->left);
+
+ // Force type conversion from *struct to the func type.
+ clos = nod(OCONVNOP, clos, N);
+ clos->type = n->type;
+
+ typecheck(&clos, Erv);
+ // typecheck will insert a PTRLIT node under CONVNOP,
+ // tag it with escape analysis result.
+ clos->left->esc = n->esc;
+ walkexpr(&clos, init);
+
+ return clos;
}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 4f1ff6778..add438daf 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -119,6 +119,27 @@ convlit1(Node **np, Type *t, int explicit)
}
n->type = t;
return;
+ case OCOMPLEX:
+ if(n->type->etype == TIDEAL) {
+ switch(t->etype) {
+ default:
+ // If trying to convert to non-complex type,
+ // leave as complex128 and let typechecker complain.
+ t = types[TCOMPLEX128];
+ //fallthrough
+ case TCOMPLEX128:
+ n->type = t;
+ convlit(&n->left, types[TFLOAT64]);
+ convlit(&n->right, types[TFLOAT64]);
+ break;
+ case TCOMPLEX64:
+ n->type = t;
+ convlit(&n->left, types[TFLOAT32]);
+ convlit(&n->right, types[TFLOAT32]);
+ break;
+ }
+ }
+ return;
}
// avoided repeated calculations, errors
@@ -1068,6 +1089,11 @@ idealkind(Node *n)
return k1;
else
return k2;
+ case OREAL:
+ case OIMAG:
+ return CTFLT;
+ case OCOMPLEX:
+ return CTCPLX;
case OADDSTR:
return CTSTR;
case OANDAND:
@@ -1185,6 +1211,7 @@ void
defaultlit2(Node **lp, Node **rp, int force)
{
Node *l, *r;
+ int lkind, rkind;
l = *lp;
r = *rp;
@@ -1204,18 +1231,20 @@ defaultlit2(Node **lp, Node **rp, int force)
convlit(lp, types[TBOOL]);
convlit(rp, types[TBOOL]);
}
- if(isconst(l, CTCPLX) || isconst(r, CTCPLX)) {
+ lkind = idealkind(l);
+ rkind = idealkind(r);
+ if(lkind == CTCPLX || rkind == CTCPLX) {
convlit(lp, types[TCOMPLEX128]);
convlit(rp, types[TCOMPLEX128]);
return;
}
- if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
+ if(lkind == CTFLT || rkind == CTFLT) {
convlit(lp, types[TFLOAT64]);
convlit(rp, types[TFLOAT64]);
return;
}
- if(isconst(l, CTRUNE) || isconst(r, CTRUNE)) {
+ if(lkind == CTRUNE || rkind == CTRUNE) {
convlit(lp, runetype);
convlit(rp, runetype);
return;
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
index e0127fc59..c9bab7a76 100644
--- a/src/cmd/gc/cplx.c
+++ b/src/cmd/gc/cplx.c
@@ -36,7 +36,7 @@ void
complexmove(Node *f, Node *t)
{
int ft, tt;
- Node n1, n2, n3, n4;
+ Node n1, n2, n3, n4, tmp;
if(debug['g']) {
dump("\ncomplexmove-f", f);
@@ -62,9 +62,9 @@ complexmove(Node *f, Node *t)
// make f addable.
// also use temporary if possible stack overlap.
if(!f->addable || overlap(f, t)) {
- tempname(&n1, f->type);
- complexmove(f, &n1);
- f = &n1;
+ tempname(&tmp, f->type);
+ complexmove(f, &tmp);
+ f = &tmp;
}
subnode(&n1, &n2, f);
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index aa2489d9a..429f212e7 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -225,8 +225,12 @@ declare(Node *n, int ctxt)
if(ctxt == PAUTO)
n->xoffset = 0;
- if(s->block == block)
- redeclare(s, "in this block");
+ if(s->block == block) {
+ // functype will print errors about duplicate function arguments.
+ // Don't repeat the error here.
+ if(ctxt != PPARAM && ctxt != PPARAMOUT)
+ redeclare(s, "in this block");
+ }
s->block = block;
s->lastlineno = parserline();
@@ -824,22 +828,24 @@ structfield(Node *n)
return f;
}
+static uint32 uniqgen;
+
static void
checkdupfields(Type *t, char* what)
{
- Type* t1;
int lno;
lno = lineno;
- for( ; t; t=t->down)
- if(t->sym && t->nname && !isblank(t->nname))
- for(t1=t->down; t1; t1=t1->down)
- if(t1->sym == t->sym) {
- lineno = t->nname->lineno;
- yyerror("duplicate %s %s", what, t->sym->name);
- break;
- }
+ for( ; t; t=t->down) {
+ if(t->sym && t->nname && !isblank(t->nname)) {
+ if(t->sym->uniqgen == uniqgen) {
+ lineno = t->nname->lineno;
+ yyerror("duplicate %s %s", what, t->sym->name);
+ } else
+ t->sym->uniqgen = uniqgen;
+ }
+ }
lineno = lno;
}
@@ -865,6 +871,7 @@ tostruct(NodeList *l)
if(f->broke)
t->broke = 1;
+ uniqgen++;
checkdupfields(t->type, "field");
if (!t->broke)
@@ -897,7 +904,6 @@ tofunargs(NodeList *l)
if(f->broke)
t->broke = 1;
- checkdupfields(t->type, "argument");
return t;
}
@@ -1004,6 +1010,7 @@ tointerface(NodeList *l)
if(f->broke)
t->broke = 1;
+ uniqgen++;
checkdupfields(t->type, "method");
t = sortinter(t);
checkwidth(t);
@@ -1187,6 +1194,11 @@ functype(Node *this, NodeList *in, NodeList *out)
t->type->down = tofunargs(out);
t->type->down->down = tofunargs(in);
+ uniqgen++;
+ checkdupfields(t->type->type, "argument");
+ checkdupfields(t->type->down->type, "argument");
+ checkdupfields(t->type->down->down->type, "argument");
+
if (t->type->broke || t->type->down->broke || t->type->down->down->broke)
t->broke = 1;
@@ -1368,6 +1380,12 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
}
}
+ if(local && !pa->local) {
+ // defining method on non-local type.
+ yyerror("cannot define new methods on non-local type %T", pa);
+ return;
+ }
+
n = nod(ODCLFIELD, newname(sf), N);
n->type = t;
@@ -1383,12 +1401,6 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
return;
}
- if(local && !pa->local) {
- // defining method on non-local type.
- yyerror("cannot define new methods on non-local type %T", pa);
- return;
- }
-
f = structfield(n);
f->nointerface = nointerface;
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 46c06d10e..df273e392 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -596,6 +596,14 @@ esc(EscState *e, Node *n)
// Contents make it to memory, lose track.
escassign(e, &e->theSink, n->left);
break;
+
+ case OCALLPART:
+ n->esc = EscNone; // until proven otherwise
+ e->noesc = list(e->noesc, n);
+ n->escloopdepth = e->loopdepth;
+ // Contents make it to memory, lose track.
+ escassign(e, &e->theSink, n->left);
+ break;
case OMAPLIT:
n->esc = EscNone; // until proven otherwise
@@ -667,6 +675,7 @@ escassign(EscState *e, Node *dst, Node *src)
case OCONVNOP:
case OMAPLIT:
case OSTRUCTLIT:
+ case OCALLPART:
break;
case ONAME:
@@ -713,6 +722,7 @@ escassign(EscState *e, Node *dst, Node *src)
case OMAKESLICE:
case ONEW:
case OCLOSURE:
+ case OCALLPART:
escflows(e, dst, src);
break;
@@ -1033,7 +1043,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
switch(src->op) {
case ONAME:
- if(src->class == PPARAM && leaks && src->esc != EscHeap) {
+ if(src->class == PPARAM && (leaks || dst->escloopdepth < 0) && src->esc != EscHeap) {
src->esc = EscScope;
if(debug['m'])
warnl(src->lineno, "leaking param: %hN", src);
@@ -1073,6 +1083,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
case OMAPLIT:
case ONEW:
case OCLOSURE:
+ case OCALLPART:
if(leaks) {
src->esc = EscHeap;
if(debug['m'])
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
index ab81e6c88..ee5b9e939 100644
--- a/src/cmd/gc/fmt.c
+++ b/src/cmd/gc/fmt.c
@@ -168,7 +168,7 @@ Lconv(Fmt *fp)
lno = a[i].incl->line - 1; // now print out start of this file
}
if(n == 0)
- fmtprint(fp, "<epoch>");
+ fmtprint(fp, "<unknown line number>");
return 0;
}
@@ -1022,6 +1022,7 @@ static int opprec[] = {
[ODOTTYPE] = 8,
[ODOT] = 8,
[OXDOT] = 8,
+ [OCALLPART] = 8,
[OPLUS] = 7,
[ONOT] = 7,
@@ -1269,9 +1270,10 @@ exprfmt(Fmt *f, Node *n, int prec)
case ODOTPTR:
case ODOTINTER:
case ODOTMETH:
+ case OCALLPART:
exprfmt(f, n->left, nprec);
if(n->right == N || n->right->sym == S)
- fmtstrcpy(f, ".<nil>");
+ return fmtstrcpy(f, ".<nil>");
return fmtprint(f, ".%hhS", n->right->sym);
case ODOTTYPE:
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 5f03d9476..b47a04bf0 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -491,6 +491,9 @@ gen(Node *n)
case ORETURN:
cgen_ret(n);
break;
+
+ case OCHECKNOTNIL:
+ checkref(n->left, 1);
}
ret:
@@ -807,7 +810,7 @@ cgen_slice(Node *n, Node *res)
if(n->op == OSLICEARR) {
if(!isptr[n->left->type->etype])
fatal("slicearr is supposed to work on pointer: %+N\n", n);
- checkref(n->left);
+ checkref(n->left, 0);
}
if(isnil(n->left)) {
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index f86c152f2..6be0ec8c9 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -268,6 +268,7 @@ struct Node
uchar addrtaken; // address taken, even if not moved to heap
uchar dupok; // duplicate definitions ok (for func)
schar likely; // likeliness of if statement
+ uchar hasbreak; // has break statement
// most nodes
Type* type;
@@ -368,6 +369,7 @@ struct Sym
uchar sym; // huffman encoding in object file
Sym* link;
int32 npkg; // number of imported packages with this name
+ uint32 uniqgen;
// saved and restored by dcopy
Pkg* pkg;
@@ -450,6 +452,7 @@ enum
OCALLFUNC, // f()
OCALLMETH, // t.Method()
OCALLINTER, // err.Error()
+ OCALLPART, // t.Method (without ())
OCAP, // cap
OCLOSE, // close
OCLOSURE, // f = func() { etc }
@@ -562,6 +565,7 @@ enum
OITAB, // itable word of an interface value.
OCLOSUREVAR, // variable reference at beginning of closure function
OCFUNC, // reference to c function pointer (not go func value)
+ OCHECKNOTNIL, // emit code to ensure pointer/interface not nil
// arch-specific registers
OREGISTER, // a register, such as AX.
@@ -987,7 +991,8 @@ Node* closurebody(NodeList *body);
void closurehdr(Node *ntype);
void typecheckclosure(Node *func, int top);
Node* walkclosure(Node *func, NodeList **init);
-void walkcallclosure(Node *n, NodeList **init);
+void typecheckpartialcall(Node*, Node*);
+Node* walkpartialcall(Node*, NodeList**);
/*
* const.c
@@ -1363,6 +1368,7 @@ Node* typecheck(Node **np, int top);
void typechecklist(NodeList *l, int top);
Node* typecheckdef(Node *n);
void copytype(Node *n, Type *t);
+void checkreturn(Node*);
void queuemethod(Node *n);
/*
@@ -1416,7 +1422,8 @@ EXTERN Node* nodfp;
int anyregalloc(void);
void betypeinit(void);
void bgen(Node *n, int true, int likely, Prog *to);
-void checkref(Node*);
+void checkref(Node *n, int force);
+void checknotnil(Node*, NodeList**);
void cgen(Node*, Node*);
void cgen_asop(Node *n);
void cgen_call(Node *n, int proc);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 794961e8e..a12da5671 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -536,7 +536,10 @@ compound_stmt:
}
stmt_list '}'
{
- $$ = liststmt($3);
+ if($3 == nil)
+ $$ = nod(OEMPTY, N, N);
+ else
+ $$ = liststmt($3);
popdcl();
}
diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c
index 1cc13a304..850bb36ec 100644
--- a/src/cmd/gc/inl.c
+++ b/src/cmd/gc/inl.c
@@ -357,7 +357,7 @@ inlnode(Node **np)
}
case OCLOSURE:
- // TODO do them here (or earlier) instead of in walkcallclosure,
+ // TODO do them here (or earlier),
// so escape analysis can avoid more heapmoves.
return;
}
@@ -565,24 +565,31 @@ mkinlcall1(Node **np, Node *fn, int isddd)
inlretvars = nil;
i = 0;
// Make temp names to use instead of the originals
- for(ll = dcl; ll; ll=ll->next)
+ for(ll = dcl; ll; ll=ll->next) {
+ if(ll->n->class == PPARAMOUT) // return values handled below.
+ continue;
if(ll->n->op == ONAME) {
ll->n->inlvar = inlvar(ll->n);
// Typecheck because inlvar is not necessarily a function parameter.
typecheck(&ll->n->inlvar, Erv);
if ((ll->n->class&~PHEAP) != PAUTO)
ninit = list(ninit, nod(ODCL, ll->n->inlvar, N)); // otherwise gen won't emit the allocations for heapallocs
- if (ll->n->class == PPARAMOUT) // we rely on the order being correct here
- inlretvars = list(inlretvars, ll->n->inlvar);
}
+ }
- // anonymous return values, synthesize names for use in assignment that replaces return
- if(inlretvars == nil && fn->type->outtuple > 0)
- for(t = getoutargx(fn->type)->type; t; t = t->down) {
+ // temporaries for return values.
+ for(t = getoutargx(fn->type)->type; t; t = t->down) {
+ if(t != T && t->nname != N && !isblank(t->nname)) {
+ m = inlvar(t->nname);
+ typecheck(&m, Erv);
+ t->nname->inlvar = m;
+ } else {
+ // anonymous return values, synthesize names for use in assignment that replaces return
m = retvar(t, i++);
- ninit = list(ninit, nod(ODCL, m, N));
- inlretvars = list(inlretvars, m);
}
+ ninit = list(ninit, nod(ODCL, m, N));
+ inlretvars = list(inlretvars, m);
+ }
// assign receiver.
if(fn->type->thistuple && n->left->op == ODOTMETH) {
@@ -790,6 +797,12 @@ inlvar(Node *var)
n->class = PAUTO;
n->used = 1;
n->curfn = curfn; // the calling function, not the called one
+
+ // esc pass wont run if we're inlining into a iface wrapper
+ // luckily, we can steal the results from the target func
+ if(var->esc == EscHeap)
+ addrescapes(n);
+
curfn->dcl = list(curfn->dcl, n);
return n;
}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 68ae6864d..118a0d7a0 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -376,6 +376,7 @@ main(int argc, char *argv[])
curfn = l->n;
saveerrors();
typechecklist(l->n->nbody, Etop);
+ checkreturn(l->n);
if(nerrors != 0)
l->n->nbody = nil; // type errors; do not compile
}
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index b87d35b7b..e4bcd1170 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -16,6 +16,8 @@ static void dumpglobls(void);
void
dumpobj(void)
{
+ NodeList *externs, *tmp;
+
bout = Bopen(outfile, OWRITE);
if(bout == nil) {
flusherrors();
@@ -31,8 +33,20 @@ dumpobj(void)
outhist(bout);
+ externs = nil;
+ if(externdcl != nil)
+ externs = externdcl->end;
+
dumpglobls();
dumptypestructs();
+
+ // Dump extra globals.
+ tmp = externdcl;
+ if(externs != nil)
+ externdcl = externs->next;
+ dumpglobls();
+ externdcl = tmp;
+
dumpdata();
dumpfuncs();
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
index bae98ec1b..3e5e592ca 100644
--- a/src/cmd/gc/racewalk.c
+++ b/src/cmd/gc/racewalk.c
@@ -196,6 +196,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OPLUS:
case OREAL:
case OIMAG:
+ case OCOM:
racewalknode(&n->left, init, wr, 0);
goto ret;
@@ -222,23 +223,17 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OCAP:
racewalknode(&n->left, init, 0, 0);
if(istype(n->left->type, TMAP)) {
- // crashes on len(m[0]) or len(f())
- SET(n1);
- USED(n1);
- /*
- n1 = nod(OADDR, n->left, N);
- n1 = conv(n1, types[TUNSAFEPTR]);
- n1 = conv(n1, ptrto(ptrto(types[TINT8])));
- n1 = nod(OIND, n1, N);
+ n1 = nod(OCONVNOP, n->left, N);
+ n1->type = ptrto(types[TUINT8]);
n1 = nod(OIND, n1, N);
typecheck(&n1, Erv);
callinstr(&n1, init, 0, skip);
- */
}
goto ret;
case OLSH:
case ORSH:
+ case OLROT:
case OAND:
case OANDNOT:
case OOR:
@@ -279,7 +274,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case ODIV:
case OMOD:
- // TODO(dvyukov): add a test for this
racewalknode(&n->left, init, wr, 0);
racewalknode(&n->right, init, wr, 0);
goto ret;
@@ -324,9 +318,30 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OPANIC:
case ORECOVER:
case OCONVIFACE:
+ case OMAKECHAN:
+ case OMAKEMAP:
+ case OMAKESLICE:
+ case OCALL:
+ case OCOPY:
+ case ORUNESTR:
+ case OARRAYBYTESTR:
+ case OARRAYRUNESTR:
+ case OSTRARRAYBYTE:
+ case OSTRARRAYRUNE:
+ case OINDEXMAP: // lowered to call
+ case OCMPSTR:
+ case OADDSTR:
+ case ODOTTYPE:
+ case ODOTTYPE2:
yyerror("racewalk: %O must be lowered by now", n->op);
goto ret;
+ // impossible nodes: only appear in backend.
+ case ORROTC:
+ case OEXTEND:
+ yyerror("racewalk: %O cannot exist now", n->op);
+ goto ret;
+
// just do generic traversal
case OFOR:
case OIF:
@@ -334,43 +349,28 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case ORETURN:
case OSELECT:
case OEMPTY:
+ case OBREAK:
+ case OCONTINUE:
+ case OFALL:
+ case OGOTO:
+ case OLABEL:
goto ret;
// does not require instrumentation
- case OINDEXMAP: // implemented in runtime
case OPRINT: // don't bother instrumenting it
case OPRINTN: // don't bother instrumenting it
case OPARAM: // it appears only in fn->exit to copy heap params back
goto ret;
// unimplemented
- case OCMPSTR:
- case OADDSTR:
case OSLICESTR:
case OAPPEND:
- case OCOPY:
- case OMAKECHAN:
- case OMAKEMAP:
- case OMAKESLICE:
- case ORUNESTR:
- case OARRAYBYTESTR:
- case OARRAYRUNESTR:
- case OSTRARRAYBYTE:
- case OSTRARRAYRUNE:
case OCMPIFACE:
case OARRAYLIT:
case OMAPLIT:
case OSTRUCTLIT:
case OCLOSURE:
- case ODOTTYPE:
- case ODOTTYPE2:
- case OCALL:
- case OBREAK:
case ODCL:
- case OCONTINUE:
- case OFALL:
- case OGOTO:
- case OLABEL:
case ODCLCONST:
case ODCLTYPE:
case OLITERAL:
@@ -378,13 +378,11 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OTYPE:
case ONONAME:
case OINDREG:
- case OCOM:
case ODOTMETH:
case OITAB:
- case OEXTEND:
case OHMUL:
- case OLROT:
- case ORROTC:
+ case OCHECKNOTNIL:
+ case OCLOSUREVAR:
goto ret;
}
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index 50c4617c0..e80a8c723 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -182,8 +182,8 @@ walkrange(Node *n)
th = typ(TARRAY);
th->type = ptrto(types[TUINT8]);
// see ../../pkg/runtime/hashmap.h:/hash_iter
- // Size in words.
- th->bound = 5 + 4*3 + 4*4/widthptr;
+ // Size of hash_iter in # of pointers.
+ th->bound = 10;
hit = temp(th);
fn = syslook("mapiterinit", 1);
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b8eb79938..8b546e235 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -1026,10 +1026,23 @@ dalgsym(Type *t)
}
static int
+gcinline(Type *t) {
+ switch(t->etype) {
+ case TARRAY:
+ if(t->bound == 1)
+ return 1;
+ if(t->width <= 4*widthptr)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+static int
dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
{
Type *t1;
- vlong o, off2, fieldoffset;
+ vlong o, off2, fieldoffset, i;
if(t->align > 0 && (*off % t->align) != 0)
fatal("dgcsym1: invalid initial alignment, %T", t);
@@ -1069,7 +1082,6 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
*off += t->width;
break;
- case TCHAN:
case TUNSAFEPTR:
case TFUNC:
if(*off % widthptr != 0)
@@ -1079,6 +1091,16 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
*off += t->width;
break;
+ // struct Hchan*
+ case TCHAN:
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ ot = duintptr(s, ot, GC_CHAN_PTR);
+ ot = duintptr(s, ot, *off);
+ ot = dsymptr(s, ot, dtypesym(t), 0);
+ *off += t->width;
+ break;
+
// struct Hmap*
case TMAP:
if(*off % widthptr != 0)
@@ -1132,8 +1154,9 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
} else {
if(t->bound < 1 || !haspointers(t->type)) {
*off += t->width;
- } else if(t->bound == 1) {
- ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1
+ } else if(gcinline(t)) {
+ for(i=0; i<t->bound; i++)
+ ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1
} else {
if(stack_size < GC_STACK_CAPACITY) {
ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index c53eaf285..796851f1a 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -2565,6 +2565,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn->dupok = 1;
typecheck(&fn, Etop);
typechecklist(fn->nbody, Etop);
+ inlcalls(fn);
curfn = nil;
funccompile(fn, 0);
}
@@ -3722,3 +3723,17 @@ isbadimport(Strlit *path)
}
return 0;
}
+
+void
+checknotnil(Node *x, NodeList **init)
+{
+ Node *n;
+
+ if(isinter(x->type)) {
+ x = nod(OITAB, x, N);
+ typecheck(&x, Erv);
+ }
+ n = nod(OCHECKNOTNIL, x, N);
+ n->typecheck = 1;
+ *init = list(*init, n);
+}
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index a497b8622..5fba73140 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -322,6 +322,10 @@ casebody(Node *sw, Node *typeswvar)
setlineno(last);
yyerror("cannot fallthrough in type switch");
}
+ if(l->next == nil) {
+ setlineno(last);
+ yyerror("cannot fallthrough final case in switch");
+ }
last->op = OFALL;
} else
stat = list(stat, br);
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index fbab85d03..938716e21 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -276,6 +276,29 @@ callrecvlist(NodeList *l)
return 0;
}
+// indexlit implements typechecking of untyped values as
+// array/slice indexes. It is equivalent to defaultlit
+// except for constants of numerical kind, which are acceptable
+// whenever they can be represented by a value of type int.
+static void
+indexlit(Node **np)
+{
+ Node *n;
+
+ n = *np;
+ if(n == N || !isideal(n->type))
+ return;
+ switch(consttype(n)) {
+ case CTINT:
+ case CTRUNE:
+ case CTFLT:
+ case CTCPLX:
+ defaultlit(np, types[TINT]);
+ break;
+ }
+ defaultlit(np, T);
+}
+
static void
typecheck1(Node **np, int top)
{
@@ -732,6 +755,7 @@ reswitch:
yyerror("rhs of . must be a name"); // impossible
goto error;
}
+ r = n->right;
if(n->left->op == OTYPE) {
if(!looktypedot(n, t, 0)) {
@@ -775,7 +799,12 @@ reswitch:
switch(n->op) {
case ODOTINTER:
case ODOTMETH:
- ok |= Ecall;
+ if(top&Ecall)
+ ok |= Ecall;
+ else {
+ typecheckpartialcall(n, r);
+ ok |= Erv;
+ }
break;
default:
ok |= Erv;
@@ -839,7 +868,7 @@ reswitch:
case TSTRING:
case TARRAY:
- defaultlit(&n->right, T);
+ indexlit(&n->right);
if(t->etype == TSTRING)
n->type = types[TUINT8];
else
@@ -855,8 +884,8 @@ reswitch:
yyerror("non-integer %s index %N", why, n->right);
break;
}
- if(n->right->op == OLITERAL) {
- if(mpgetfix(n->right->val.u.xval) < 0)
+ if(isconst(n->right, CTINT)) {
+ if(mpgetfix(n->right->val.u.xval) < 0)
yyerror("invalid %s index %N (index must be non-negative)", why, n->right);
else if(isfixedarray(t) && t->bound > 0 && mpgetfix(n->right->val.u.xval) >= t->bound)
yyerror("invalid array index %N (out of bounds for %d-element array)", n->right, t->bound);
@@ -932,8 +961,8 @@ reswitch:
typecheck(&n->right->left, Erv);
typecheck(&n->right->right, Erv);
defaultlit(&n->left, T);
- defaultlit(&n->right->left, T);
- defaultlit(&n->right->right, T);
+ indexlit(&n->right->left);
+ indexlit(&n->right->right);
l = n->left;
if(isfixedarray(l->type)) {
if(!islvalue(n->left)) {
@@ -1180,16 +1209,18 @@ reswitch:
if(l->type == T || r->type == T)
goto error;
defaultlit2(&l, &r, 0);
+ if(l->type == T || r->type == T)
+ goto error;
n->left = l;
n->right = r;
- if(l->type->etype != r->type->etype) {
- badcmplx:
- yyerror("invalid operation: %N (complex of types %T, %T)", n, l->type, r->type);
+ if(!eqtype(l->type, r->type)) {
+ yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
goto error;
}
switch(l->type->etype) {
default:
- goto badcmplx;
+ yyerror("invalid operation: %N (arguments have type %T, expected floating-point)", n, l->type, r->type);
+ goto error;
case TIDEAL:
t = types[TIDEAL];
break;
@@ -1692,10 +1723,6 @@ ret:
yyerror("%N is not a type", n);
goto error;
}
- if((ok & Ecall) && !(top & Ecall)) {
- yyerror("method %N is not an expression, must be called", n);
- goto error;
- }
// TODO(rsc): simplify
if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) {
yyerror("%N used as value", n);
@@ -2558,6 +2585,7 @@ islvalue(Node *n)
// fall through
case OIND:
case ODOTPTR:
+ case OCLOSUREVAR:
return 1;
case ODOT:
return islvalue(n->left);
@@ -3144,3 +3172,148 @@ checkmake(Type *t, char *arg, Node *n)
}
return 0;
}
+
+static void markbreaklist(NodeList*, Node*);
+
+static void
+markbreak(Node *n, Node *implicit)
+{
+ Label *lab;
+
+ if(n == N)
+ return;
+
+ switch(n->op) {
+ case OBREAK:
+ if(n->left == N) {
+ if(implicit)
+ implicit->hasbreak = 1;
+ } else {
+ lab = n->left->sym->label;
+ if(lab != L)
+ lab->def->hasbreak = 1;
+ }
+ break;
+
+ case OFOR:
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ case ORANGE:
+ implicit = n;
+ // fall through
+
+ default:
+ markbreak(n->left, implicit);
+ markbreak(n->right, implicit);
+ markbreak(n->ntest, implicit);
+ markbreak(n->nincr, implicit);
+ markbreaklist(n->ninit, implicit);
+ markbreaklist(n->nbody, implicit);
+ markbreaklist(n->nelse, implicit);
+ markbreaklist(n->list, implicit);
+ markbreaklist(n->rlist, implicit);
+ break;
+ }
+}
+
+static void
+markbreaklist(NodeList *l, Node *implicit)
+{
+ Node *n;
+ Label *lab;
+
+ for(; l; l=l->next) {
+ n = l->n;
+ if(n->op == OLABEL && l->next && n->defn == l->next->n) {
+ switch(n->defn->op) {
+ case OFOR:
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ case ORANGE:
+ lab = mal(sizeof *lab);
+ lab->def = n->defn;
+ n->left->sym->label = lab;
+ markbreak(n->defn, n->defn);
+ n->left->sym->label = L;
+ l = l->next;
+ continue;
+ }
+ }
+ markbreak(n, implicit);
+ }
+}
+
+static int
+isterminating(NodeList *l, int top)
+{
+ int def;
+ Node *n;
+
+ if(l == nil)
+ return 0;
+ if(top) {
+ while(l->next && l->n->op != OLABEL)
+ l = l->next;
+ markbreaklist(l, nil);
+ }
+ while(l->next)
+ l = l->next;
+ n = l->n;
+
+ if(n == N)
+ return 0;
+
+ switch(n->op) {
+ // NOTE: OLABEL is treated as a separate statement,
+ // not a separate prefix, so skipping to the last statement
+ // in the block handles the labeled statement case by
+ // skipping over the label. No case OLABEL here.
+
+ case OBLOCK:
+ return isterminating(n->list, 0);
+
+ case OGOTO:
+ case ORETURN:
+ case OPANIC:
+ case OXFALL:
+ return 1;
+
+ case OFOR:
+ if(n->ntest != N)
+ return 0;
+ if(n->hasbreak)
+ return 0;
+ return 1;
+
+ case OIF:
+ return isterminating(n->nbody, 0) && isterminating(n->nelse, 0);
+
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ if(n->hasbreak)
+ return 0;
+ def = 0;
+ for(l=n->list; l; l=l->next) {
+ if(!isterminating(l->n->nbody, 0))
+ return 0;
+ if(l->n->list == nil) // default
+ def = 1;
+ }
+ if(n->op != OSELECT && !def)
+ return 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+checkreturn(Node *fn)
+{
+ if(fn->type->outtuple && fn->nbody != nil)
+ if(!isterminating(fn->nbody, 1))
+ yyerrorl(fn->endlineno, "missing return at end of function");
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index de2105ed3..50e05fc3c 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -29,40 +29,6 @@ static void walkdiv(Node**, NodeList**);
static int bounded(Node*, int64);
static Mpint mpzero;
-// can this code branch reach the end
-// without an unconditional RETURN
-// this is hard, so it is conservative
-static int
-walkret(NodeList *l)
-{
- Node *n;
-
-loop:
- while(l && l->next)
- l = l->next;
- if(l == nil)
- return 1;
-
- // at this point, we have the last
- // statement of the function
- n = l->n;
- switch(n->op) {
- case OBLOCK:
- l = n->list;
- goto loop;
-
- case OGOTO:
- case ORETURN:
- case OPANIC:
- return 0;
- break;
- }
-
- // all other statements
- // will flow to the end
- return 1;
-}
-
void
walk(Node *fn)
{
@@ -76,9 +42,6 @@ walk(Node *fn)
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
dumplist(s, curfn->nbody);
}
- if(curfn->type->outtuple)
- if(walkret(curfn->nbody))
- yyerror("function ends without a return statement");
lno = lineno;
@@ -221,6 +184,7 @@ walkstmt(Node **np)
case OLABEL:
case ODCLCONST:
case ODCLTYPE:
+ case OCHECKNOTNIL:
break;
case OBLOCK:
@@ -433,13 +397,28 @@ walkexpr(Node **np, NodeList **init)
case OIMAG:
case ODOTMETH:
case ODOTINTER:
+ walkexpr(&n->left, init);
+ goto ret;
+
case OIND:
+ if(n->left->type->type->width == 0) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
walkexpr(&n->left, init);
goto ret;
case ODOT:
+ usefield(n);
+ walkexpr(&n->left, init);
+ goto ret;
+
case ODOTPTR:
usefield(n);
+ if(n->op == ODOTPTR && n->left->type->type->width == 0) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
walkexpr(&n->left, init);
goto ret;
@@ -561,13 +540,6 @@ walkexpr(Node **np, NodeList **init)
if(n->list && n->list->n->op == OAS)
goto ret;
- /*
- if(n->left->op == OCLOSURE) {
- walkcallclosure(n, init);
- t = n->left->type;
- }
- */
-
walkexpr(&n->left, init);
walkexprlist(n->list, init);
@@ -673,8 +645,48 @@ walkexpr(Node **np, NodeList **init)
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
- fn = mapfn("mapaccess2", r->left->type);
- r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right);
+ t = r->left->type;
+ p = nil;
+ if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ switch(simsimtype(t->down)) {
+ case TINT32:
+ case TUINT32:
+ p = "mapaccess2_fast32";
+ break;
+ case TINT64:
+ case TUINT64:
+ p = "mapaccess2_fast64";
+ break;
+ case TSTRING:
+ p = "mapaccess2_faststr";
+ break;
+ }
+ }
+ if(p != nil) {
+ // from:
+ // a,b = m[i]
+ // to:
+ // var,b = mapaccess2_fast*(t, m, i)
+ // a = *var
+ a = n->list->n;
+ var = temp(ptrto(t->type));
+ var->typecheck = 1;
+
+ fn = mapfn(p, t);
+ r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right);
+ n->rlist = list1(r);
+ n->op = OAS2FUNC;
+ n->list->n = var;
+ walkexpr(&n, init);
+ *init = list(*init, n);
+
+ n = nod(OAS, a, nod(OIND, var, N));
+ typecheck(&n, Etop);
+ walkexpr(&n, init);
+ goto ret;
+ }
+ fn = mapfn("mapaccess2", t);
+ r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right);
n->rlist = list1(r);
n->op = OAS2FUNC;
goto as2func;
@@ -1041,7 +1053,33 @@ walkexpr(Node **np, NodeList **init)
goto ret;
t = n->left->type;
- n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
+ p = nil;
+ if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ switch(simsimtype(t->down)) {
+ case TINT32:
+ case TUINT32:
+ p = "mapaccess1_fast32";
+ break;
+ case TINT64:
+ case TUINT64:
+ p = "mapaccess1_fast64";
+ break;
+ case TSTRING:
+ p = "mapaccess1_faststr";
+ break;
+ }
+ }
+ if(p != nil) {
+ // use fast version. The fast versions return a pointer to the value - we need
+ // to dereference it to get the result.
+ n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, n->right);
+ n = nod(OIND, n, N);
+ n->type = t->type;
+ n->typecheck = 1;
+ } else {
+ // no fast version for this key
+ n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
+ }
goto ret;
case ORECV:
@@ -1292,6 +1330,10 @@ walkexpr(Node **np, NodeList **init)
case OCLOSURE:
n = walkclosure(n, init);
goto ret;
+
+ case OCALLPART:
+ n = walkpartialcall(n, init);
+ goto ret;
}
fatal("missing switch %O", n->op);
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
index 75175455e..dee793998 100644
--- a/src/cmd/gc/y.tab.c
+++ b/src/cmd/gc/y.tab.c
@@ -662,35 +662,35 @@ static const yytype_uint16 yyrline[] =
304, 308, 312, 318, 324, 330, 335, 339, 343, 349,
355, 359, 363, 369, 373, 379, 380, 384, 390, 399,
405, 423, 428, 440, 456, 461, 468, 488, 506, 515,
- 534, 533, 545, 544, 575, 578, 585, 584, 595, 601,
- 610, 621, 627, 630, 638, 637, 648, 654, 666, 670,
- 675, 665, 696, 695, 708, 711, 717, 720, 732, 736,
- 731, 754, 753, 769, 770, 774, 778, 782, 786, 790,
- 794, 798, 802, 806, 810, 814, 818, 822, 826, 830,
- 834, 838, 842, 847, 853, 854, 858, 869, 873, 877,
- 881, 886, 890, 900, 904, 909, 917, 921, 922, 933,
- 937, 941, 945, 949, 950, 956, 963, 969, 976, 979,
- 986, 992, 1009, 1016, 1017, 1024, 1025, 1044, 1045, 1048,
- 1051, 1055, 1066, 1075, 1081, 1084, 1087, 1094, 1095, 1101,
- 1116, 1124, 1136, 1141, 1147, 1148, 1149, 1150, 1151, 1152,
- 1158, 1159, 1160, 1161, 1167, 1168, 1169, 1170, 1171, 1177,
- 1178, 1181, 1184, 1185, 1186, 1187, 1188, 1191, 1192, 1205,
- 1209, 1214, 1219, 1224, 1228, 1229, 1232, 1238, 1245, 1251,
- 1258, 1264, 1275, 1289, 1318, 1358, 1383, 1401, 1410, 1413,
- 1421, 1425, 1429, 1436, 1442, 1447, 1459, 1462, 1472, 1473,
- 1479, 1480, 1486, 1490, 1496, 1497, 1503, 1507, 1513, 1536,
- 1541, 1547, 1553, 1560, 1569, 1578, 1593, 1599, 1604, 1608,
- 1615, 1628, 1629, 1635, 1641, 1644, 1648, 1654, 1657, 1666,
- 1669, 1670, 1674, 1675, 1681, 1682, 1683, 1684, 1685, 1687,
- 1686, 1701, 1706, 1710, 1714, 1718, 1722, 1727, 1746, 1752,
- 1760, 1764, 1770, 1774, 1780, 1784, 1790, 1794, 1803, 1807,
- 1811, 1815, 1821, 1824, 1832, 1833, 1835, 1836, 1839, 1842,
- 1845, 1848, 1851, 1854, 1857, 1860, 1863, 1866, 1869, 1872,
- 1875, 1878, 1884, 1888, 1892, 1896, 1900, 1904, 1924, 1931,
- 1942, 1943, 1944, 1947, 1948, 1951, 1955, 1965, 1969, 1973,
- 1977, 1981, 1985, 1989, 1995, 2001, 2009, 2017, 2023, 2030,
- 2046, 2064, 2068, 2074, 2077, 2080, 2084, 2094, 2098, 2113,
- 2121, 2122, 2134, 2135, 2138, 2142, 2148, 2152, 2158, 2162
+ 534, 533, 548, 547, 578, 581, 588, 587, 598, 604,
+ 613, 624, 630, 633, 641, 640, 651, 657, 669, 673,
+ 678, 668, 699, 698, 711, 714, 720, 723, 735, 739,
+ 734, 757, 756, 772, 773, 777, 781, 785, 789, 793,
+ 797, 801, 805, 809, 813, 817, 821, 825, 829, 833,
+ 837, 841, 845, 850, 856, 857, 861, 872, 876, 880,
+ 884, 889, 893, 903, 907, 912, 920, 924, 925, 936,
+ 940, 944, 948, 952, 953, 959, 966, 972, 979, 982,
+ 989, 995, 1012, 1019, 1020, 1027, 1028, 1047, 1048, 1051,
+ 1054, 1058, 1069, 1078, 1084, 1087, 1090, 1097, 1098, 1104,
+ 1119, 1127, 1139, 1144, 1150, 1151, 1152, 1153, 1154, 1155,
+ 1161, 1162, 1163, 1164, 1170, 1171, 1172, 1173, 1174, 1180,
+ 1181, 1184, 1187, 1188, 1189, 1190, 1191, 1194, 1195, 1208,
+ 1212, 1217, 1222, 1227, 1231, 1232, 1235, 1241, 1248, 1254,
+ 1261, 1267, 1278, 1292, 1321, 1361, 1386, 1404, 1413, 1416,
+ 1424, 1428, 1432, 1439, 1445, 1450, 1462, 1465, 1475, 1476,
+ 1482, 1483, 1489, 1493, 1499, 1500, 1506, 1510, 1516, 1539,
+ 1544, 1550, 1556, 1563, 1572, 1581, 1596, 1602, 1607, 1611,
+ 1618, 1631, 1632, 1638, 1644, 1647, 1651, 1657, 1660, 1669,
+ 1672, 1673, 1677, 1678, 1684, 1685, 1686, 1687, 1688, 1690,
+ 1689, 1704, 1709, 1713, 1717, 1721, 1725, 1730, 1749, 1755,
+ 1763, 1767, 1773, 1777, 1783, 1787, 1793, 1797, 1806, 1810,
+ 1814, 1818, 1824, 1827, 1835, 1836, 1838, 1839, 1842, 1845,
+ 1848, 1851, 1854, 1857, 1860, 1863, 1866, 1869, 1872, 1875,
+ 1878, 1881, 1887, 1891, 1895, 1899, 1903, 1907, 1927, 1934,
+ 1945, 1946, 1947, 1950, 1951, 1954, 1958, 1968, 1972, 1976,
+ 1980, 1984, 1988, 1992, 1998, 2004, 2012, 2020, 2026, 2033,
+ 2049, 2067, 2071, 2077, 2080, 2083, 2087, 2097, 2101, 2116,
+ 2124, 2125, 2137, 2138, 2141, 2145, 2151, 2155, 2161, 2165
};
#endif
@@ -2867,13 +2867,16 @@ yyreduce:
case 61:
#line 538 "go.y"
{
- (yyval.node) = liststmt((yyvsp[(3) - (4)].list));
+ if((yyvsp[(3) - (4)].list) == nil)
+ (yyval.node) = nod(OEMPTY, N, N);
+ else
+ (yyval.node) = liststmt((yyvsp[(3) - (4)].list));
popdcl();
}
break;
case 62:
-#line 545 "go.y"
+#line 548 "go.y"
{
// If the last token read by the lexer was consumed
// as part of the case, clear it (parser has cleared yychar).
@@ -2886,7 +2889,7 @@ yyreduce:
break;
case 63:
-#line 555 "go.y"
+#line 558 "go.y"
{
int last;
@@ -2908,28 +2911,28 @@ yyreduce:
break;
case 64:
-#line 575 "go.y"
+#line 578 "go.y"
{
(yyval.list) = nil;
}
break;
case 65:
-#line 579 "go.y"
+#line 582 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
}
break;
case 66:
-#line 585 "go.y"
+#line 588 "go.y"
{
markdcl();
}
break;
case 67:
-#line 589 "go.y"
+#line 592 "go.y"
{
(yyval.list) = (yyvsp[(3) - (4)].list);
popdcl();
@@ -2937,7 +2940,7 @@ yyreduce:
break;
case 68:
-#line 596 "go.y"
+#line 599 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2946,7 +2949,7 @@ yyreduce:
break;
case 69:
-#line 602 "go.y"
+#line 605 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2956,7 +2959,7 @@ yyreduce:
break;
case 70:
-#line 611 "go.y"
+#line 614 "go.y"
{
// init ; test ; incr
if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
@@ -2970,7 +2973,7 @@ yyreduce:
break;
case 71:
-#line 622 "go.y"
+#line 625 "go.y"
{
// normal test
(yyval.node) = nod(OFOR, N, N);
@@ -2979,7 +2982,7 @@ yyreduce:
break;
case 73:
-#line 631 "go.y"
+#line 634 "go.y"
{
(yyval.node) = (yyvsp[(1) - (2)].node);
(yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
@@ -2987,14 +2990,14 @@ yyreduce:
break;
case 74:
-#line 638 "go.y"
+#line 641 "go.y"
{
markdcl();
}
break;
case 75:
-#line 642 "go.y"
+#line 645 "go.y"
{
(yyval.node) = (yyvsp[(3) - (3)].node);
popdcl();
@@ -3002,7 +3005,7 @@ yyreduce:
break;
case 76:
-#line 649 "go.y"
+#line 652 "go.y"
{
// test
(yyval.node) = nod(OIF, N, N);
@@ -3011,7 +3014,7 @@ yyreduce:
break;
case 77:
-#line 655 "go.y"
+#line 658 "go.y"
{
// init ; test
(yyval.node) = nod(OIF, N, N);
@@ -3022,14 +3025,14 @@ yyreduce:
break;
case 78:
-#line 666 "go.y"
+#line 669 "go.y"
{
markdcl();
}
break;
case 79:
-#line 670 "go.y"
+#line 673 "go.y"
{
if((yyvsp[(3) - (3)].node)->ntest == N)
yyerror("missing condition in if statement");
@@ -3037,14 +3040,14 @@ yyreduce:
break;
case 80:
-#line 675 "go.y"
+#line 678 "go.y"
{
(yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
}
break;
case 81:
-#line 679 "go.y"
+#line 682 "go.y"
{
Node *n;
NodeList *nn;
@@ -3062,14 +3065,14 @@ yyreduce:
break;
case 82:
-#line 696 "go.y"
+#line 699 "go.y"
{
markdcl();
}
break;
case 83:
-#line 700 "go.y"
+#line 703 "go.y"
{
if((yyvsp[(4) - (5)].node)->ntest == N)
yyerror("missing condition in if statement");
@@ -3079,28 +3082,28 @@ yyreduce:
break;
case 84:
-#line 708 "go.y"
+#line 711 "go.y"
{
(yyval.list) = nil;
}
break;
case 85:
-#line 712 "go.y"
+#line 715 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
}
break;
case 86:
-#line 717 "go.y"
+#line 720 "go.y"
{
(yyval.list) = nil;
}
break;
case 87:
-#line 721 "go.y"
+#line 724 "go.y"
{
NodeList *node;
@@ -3112,14 +3115,14 @@ yyreduce:
break;
case 88:
-#line 732 "go.y"
+#line 735 "go.y"
{
markdcl();
}
break;
case 89:
-#line 736 "go.y"
+#line 739 "go.y"
{
Node *n;
n = (yyvsp[(3) - (3)].node)->ntest;
@@ -3130,7 +3133,7 @@ yyreduce:
break;
case 90:
-#line 744 "go.y"
+#line 747 "go.y"
{
(yyval.node) = (yyvsp[(3) - (7)].node);
(yyval.node)->op = OSWITCH;
@@ -3141,14 +3144,14 @@ yyreduce:
break;
case 91:
-#line 754 "go.y"
+#line 757 "go.y"
{
typesw = nod(OXXX, typesw, N);
}
break;
case 92:
-#line 758 "go.y"
+#line 761 "go.y"
{
(yyval.node) = nod(OSELECT, N, N);
(yyval.node)->lineno = typesw->lineno;
@@ -3158,154 +3161,154 @@ yyreduce:
break;
case 94:
-#line 771 "go.y"
+#line 774 "go.y"
{
(yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 95:
-#line 775 "go.y"
+#line 778 "go.y"
{
(yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 96:
-#line 779 "go.y"
+#line 782 "go.y"
{
(yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 97:
-#line 783 "go.y"
+#line 786 "go.y"
{
(yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 98:
-#line 787 "go.y"
+#line 790 "go.y"
{
(yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 99:
-#line 791 "go.y"
+#line 794 "go.y"
{
(yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 100:
-#line 795 "go.y"
+#line 798 "go.y"
{
(yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 101:
-#line 799 "go.y"
+#line 802 "go.y"
{
(yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 102:
-#line 803 "go.y"
+#line 806 "go.y"
{
(yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 103:
-#line 807 "go.y"
+#line 810 "go.y"
{
(yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 104:
-#line 811 "go.y"
+#line 814 "go.y"
{
(yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 105:
-#line 815 "go.y"
+#line 818 "go.y"
{
(yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 106:
-#line 819 "go.y"
+#line 822 "go.y"
{
(yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 107:
-#line 823 "go.y"
+#line 826 "go.y"
{
(yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 108:
-#line 827 "go.y"
+#line 830 "go.y"
{
(yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 109:
-#line 831 "go.y"
+#line 834 "go.y"
{
(yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 110:
-#line 835 "go.y"
+#line 838 "go.y"
{
(yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 111:
-#line 839 "go.y"
+#line 842 "go.y"
{
(yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 112:
-#line 843 "go.y"
+#line 846 "go.y"
{
(yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 113:
-#line 848 "go.y"
+#line 851 "go.y"
{
(yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 115:
-#line 855 "go.y"
+#line 858 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 116:
-#line 859 "go.y"
+#line 862 "go.y"
{
if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
// Special case for &T{...}: turn into (*T){...}.
@@ -3319,28 +3322,28 @@ yyreduce:
break;
case 117:
-#line 870 "go.y"
+#line 873 "go.y"
{
(yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
}
break;
case 118:
-#line 874 "go.y"
+#line 877 "go.y"
{
(yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
}
break;
case 119:
-#line 878 "go.y"
+#line 881 "go.y"
{
(yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
}
break;
case 120:
-#line 882 "go.y"
+#line 885 "go.y"
{
yyerror("the bitwise complement operator is ^");
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
@@ -3348,28 +3351,28 @@ yyreduce:
break;
case 121:
-#line 887 "go.y"
+#line 890 "go.y"
{
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
}
break;
case 122:
-#line 891 "go.y"
+#line 894 "go.y"
{
(yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
}
break;
case 123:
-#line 901 "go.y"
+#line 904 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
}
break;
case 124:
-#line 905 "go.y"
+#line 908 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3377,7 +3380,7 @@ yyreduce:
break;
case 125:
-#line 910 "go.y"
+#line 913 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
(yyval.node)->list = (yyvsp[(3) - (6)].list);
@@ -3386,14 +3389,14 @@ yyreduce:
break;
case 126:
-#line 918 "go.y"
+#line 921 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
case 128:
-#line 923 "go.y"
+#line 926 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3407,35 +3410,35 @@ yyreduce:
break;
case 129:
-#line 934 "go.y"
+#line 937 "go.y"
{
(yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
}
break;
case 130:
-#line 938 "go.y"
+#line 941 "go.y"
{
(yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
}
break;
case 131:
-#line 942 "go.y"
+#line 945 "go.y"
{
(yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
}
break;
case 132:
-#line 946 "go.y"
+#line 949 "go.y"
{
(yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
}
break;
case 134:
-#line 951 "go.y"
+#line 954 "go.y"
{
// conversion
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
@@ -3444,7 +3447,7 @@ yyreduce:
break;
case 135:
-#line 957 "go.y"
+#line 960 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3454,7 +3457,7 @@ yyreduce:
break;
case 136:
-#line 964 "go.y"
+#line 967 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3463,7 +3466,7 @@ yyreduce:
break;
case 137:
-#line 970 "go.y"
+#line 973 "go.y"
{
yyerror("cannot parenthesize type in composite literal");
(yyval.node) = (yyvsp[(5) - (7)].node);
@@ -3473,7 +3476,7 @@ yyreduce:
break;
case 139:
-#line 979 "go.y"
+#line 982 "go.y"
{
// composite expression.
// make node early so we get the right line number.
@@ -3482,14 +3485,14 @@ yyreduce:
break;
case 140:
-#line 987 "go.y"
+#line 990 "go.y"
{
(yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 141:
-#line 993 "go.y"
+#line 996 "go.y"
{
// These nodes do not carry line numbers.
// Since a composite literal commonly spans several lines,
@@ -3509,7 +3512,7 @@ yyreduce:
break;
case 142:
-#line 1010 "go.y"
+#line 1013 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3517,7 +3520,7 @@ yyreduce:
break;
case 144:
-#line 1018 "go.y"
+#line 1021 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3525,7 +3528,7 @@ yyreduce:
break;
case 146:
-#line 1026 "go.y"
+#line 1029 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -3545,21 +3548,21 @@ yyreduce:
break;
case 150:
-#line 1052 "go.y"
+#line 1055 "go.y"
{
(yyval.i) = LBODY;
}
break;
case 151:
-#line 1056 "go.y"
+#line 1059 "go.y"
{
(yyval.i) = '{';
}
break;
case 152:
-#line 1067 "go.y"
+#line 1070 "go.y"
{
if((yyvsp[(1) - (1)].sym) == S)
(yyval.node) = N;
@@ -3569,21 +3572,21 @@ yyreduce:
break;
case 153:
-#line 1076 "go.y"
+#line 1079 "go.y"
{
(yyval.node) = dclname((yyvsp[(1) - (1)].sym));
}
break;
case 154:
-#line 1081 "go.y"
+#line 1084 "go.y"
{
(yyval.node) = N;
}
break;
case 156:
-#line 1088 "go.y"
+#line 1091 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -3593,14 +3596,14 @@ yyreduce:
break;
case 158:
-#line 1096 "go.y"
+#line 1099 "go.y"
{
(yyval.sym) = S;
}
break;
case 159:
-#line 1102 "go.y"
+#line 1105 "go.y"
{
Pkg *p;
@@ -3616,7 +3619,7 @@ yyreduce:
break;
case 160:
-#line 1117 "go.y"
+#line 1120 "go.y"
{
(yyval.node) = oldname((yyvsp[(1) - (1)].sym));
if((yyval.node)->pack != N)
@@ -3625,7 +3628,7 @@ yyreduce:
break;
case 162:
-#line 1137 "go.y"
+#line 1140 "go.y"
{
yyerror("final argument in variadic function missing type");
(yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
@@ -3633,35 +3636,35 @@ yyreduce:
break;
case 163:
-#line 1142 "go.y"
+#line 1145 "go.y"
{
(yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
}
break;
case 169:
-#line 1153 "go.y"
+#line 1156 "go.y"
{
(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
}
break;
case 173:
-#line 1162 "go.y"
+#line 1165 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 178:
-#line 1172 "go.y"
+#line 1175 "go.y"
{
(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
}
break;
case 188:
-#line 1193 "go.y"
+#line 1196 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3675,14 +3678,14 @@ yyreduce:
break;
case 189:
-#line 1206 "go.y"
+#line 1209 "go.y"
{
(yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
}
break;
case 190:
-#line 1210 "go.y"
+#line 1213 "go.y"
{
// array literal of nelem
(yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
@@ -3690,7 +3693,7 @@ yyreduce:
break;
case 191:
-#line 1215 "go.y"
+#line 1218 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
(yyval.node)->etype = Cboth;
@@ -3698,7 +3701,7 @@ yyreduce:
break;
case 192:
-#line 1220 "go.y"
+#line 1223 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Csend;
@@ -3706,21 +3709,21 @@ yyreduce:
break;
case 193:
-#line 1225 "go.y"
+#line 1228 "go.y"
{
(yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
}
break;
case 196:
-#line 1233 "go.y"
+#line 1236 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 197:
-#line 1239 "go.y"
+#line 1242 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Crecv;
@@ -3728,7 +3731,7 @@ yyreduce:
break;
case 198:
-#line 1246 "go.y"
+#line 1249 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3737,7 +3740,7 @@ yyreduce:
break;
case 199:
-#line 1252 "go.y"
+#line 1255 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
@@ -3745,7 +3748,7 @@ yyreduce:
break;
case 200:
-#line 1259 "go.y"
+#line 1262 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3754,7 +3757,7 @@ yyreduce:
break;
case 201:
-#line 1265 "go.y"
+#line 1268 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
@@ -3762,7 +3765,7 @@ yyreduce:
break;
case 202:
-#line 1276 "go.y"
+#line 1279 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
if((yyval.node) == N)
@@ -3777,7 +3780,7 @@ yyreduce:
break;
case 203:
-#line 1290 "go.y"
+#line 1293 "go.y"
{
Node *t;
@@ -3809,7 +3812,7 @@ yyreduce:
break;
case 204:
-#line 1319 "go.y"
+#line 1322 "go.y"
{
Node *rcvr, *t;
@@ -3850,7 +3853,7 @@ yyreduce:
break;
case 205:
-#line 1359 "go.y"
+#line 1362 "go.y"
{
Sym *s;
Type *t;
@@ -3878,7 +3881,7 @@ yyreduce:
break;
case 206:
-#line 1384 "go.y"
+#line 1387 "go.y"
{
(yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right);
(yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list));
@@ -3897,7 +3900,7 @@ yyreduce:
break;
case 207:
-#line 1402 "go.y"
+#line 1405 "go.y"
{
(yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
(yyval.node) = nod(OTFUNC, N, N);
@@ -3907,14 +3910,14 @@ yyreduce:
break;
case 208:
-#line 1410 "go.y"
+#line 1413 "go.y"
{
(yyval.list) = nil;
}
break;
case 209:
-#line 1414 "go.y"
+#line 1417 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
if((yyval.list) == nil)
@@ -3923,21 +3926,21 @@ yyreduce:
break;
case 210:
-#line 1422 "go.y"
+#line 1425 "go.y"
{
(yyval.list) = nil;
}
break;
case 211:
-#line 1426 "go.y"
+#line 1429 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
}
break;
case 212:
-#line 1430 "go.y"
+#line 1433 "go.y"
{
(yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
(yyval.list) = (yyvsp[(2) - (3)].list);
@@ -3945,14 +3948,14 @@ yyreduce:
break;
case 213:
-#line 1437 "go.y"
+#line 1440 "go.y"
{
closurehdr((yyvsp[(1) - (1)].node));
}
break;
case 214:
-#line 1443 "go.y"
+#line 1446 "go.y"
{
(yyval.node) = closurebody((yyvsp[(3) - (4)].list));
fixlbrace((yyvsp[(2) - (4)].i));
@@ -3960,21 +3963,21 @@ yyreduce:
break;
case 215:
-#line 1448 "go.y"
+#line 1451 "go.y"
{
(yyval.node) = closurebody(nil);
}
break;
case 216:
-#line 1459 "go.y"
+#line 1462 "go.y"
{
(yyval.list) = nil;
}
break;
case 217:
-#line 1463 "go.y"
+#line 1466 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
if(nsyntaxerrors == 0)
@@ -3985,56 +3988,56 @@ yyreduce:
break;
case 219:
-#line 1474 "go.y"
+#line 1477 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 221:
-#line 1481 "go.y"
+#line 1484 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 222:
-#line 1487 "go.y"
+#line 1490 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 223:
-#line 1491 "go.y"
+#line 1494 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 225:
-#line 1498 "go.y"
+#line 1501 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 226:
-#line 1504 "go.y"
+#line 1507 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 227:
-#line 1508 "go.y"
+#line 1511 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 228:
-#line 1514 "go.y"
+#line 1517 "go.y"
{
NodeList *l;
@@ -4060,7 +4063,7 @@ yyreduce:
break;
case 229:
-#line 1537 "go.y"
+#line 1540 "go.y"
{
(yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
(yyval.list) = list1((yyvsp[(1) - (2)].node));
@@ -4068,7 +4071,7 @@ yyreduce:
break;
case 230:
-#line 1542 "go.y"
+#line 1545 "go.y"
{
(yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
(yyval.list) = list1((yyvsp[(2) - (4)].node));
@@ -4077,7 +4080,7 @@ yyreduce:
break;
case 231:
-#line 1548 "go.y"
+#line 1551 "go.y"
{
(yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
(yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
@@ -4086,7 +4089,7 @@ yyreduce:
break;
case 232:
-#line 1554 "go.y"
+#line 1557 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4096,7 +4099,7 @@ yyreduce:
break;
case 233:
-#line 1561 "go.y"
+#line 1564 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4106,7 +4109,7 @@ yyreduce:
break;
case 234:
-#line 1570 "go.y"
+#line 1573 "go.y"
{
Node *n;
@@ -4118,7 +4121,7 @@ yyreduce:
break;
case 235:
-#line 1579 "go.y"
+#line 1582 "go.y"
{
Pkg *pkg;
@@ -4134,14 +4137,14 @@ yyreduce:
break;
case 236:
-#line 1594 "go.y"
+#line 1597 "go.y"
{
(yyval.node) = embedded((yyvsp[(1) - (1)].sym));
}
break;
case 237:
-#line 1600 "go.y"
+#line 1603 "go.y"
{
(yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
ifacedcl((yyval.node));
@@ -4149,14 +4152,14 @@ yyreduce:
break;
case 238:
-#line 1605 "go.y"
+#line 1608 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
}
break;
case 239:
-#line 1609 "go.y"
+#line 1612 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
yyerror("cannot parenthesize embedded type");
@@ -4164,7 +4167,7 @@ yyreduce:
break;
case 240:
-#line 1616 "go.y"
+#line 1619 "go.y"
{
// without func keyword
(yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
@@ -4175,7 +4178,7 @@ yyreduce:
break;
case 242:
-#line 1630 "go.y"
+#line 1633 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4184,7 +4187,7 @@ yyreduce:
break;
case 243:
-#line 1636 "go.y"
+#line 1639 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4193,56 +4196,56 @@ yyreduce:
break;
case 245:
-#line 1645 "go.y"
+#line 1648 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 246:
-#line 1649 "go.y"
+#line 1652 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 247:
-#line 1654 "go.y"
+#line 1657 "go.y"
{
(yyval.list) = nil;
}
break;
case 248:
-#line 1658 "go.y"
+#line 1661 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
case 249:
-#line 1666 "go.y"
+#line 1669 "go.y"
{
(yyval.node) = N;
}
break;
case 251:
-#line 1671 "go.y"
+#line 1674 "go.y"
{
(yyval.node) = liststmt((yyvsp[(1) - (1)].list));
}
break;
case 253:
-#line 1676 "go.y"
+#line 1679 "go.y"
{
(yyval.node) = N;
}
break;
case 259:
-#line 1687 "go.y"
+#line 1690 "go.y"
{
(yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N);
(yyvsp[(1) - (2)].node)->sym = dclstack; // context, for goto restrictions
@@ -4250,7 +4253,7 @@ yyreduce:
break;
case 260:
-#line 1692 "go.y"
+#line 1695 "go.y"
{
NodeList *l;
@@ -4263,7 +4266,7 @@ yyreduce:
break;
case 261:
-#line 1702 "go.y"
+#line 1705 "go.y"
{
// will be converted to OFALL
(yyval.node) = nod(OXFALL, N, N);
@@ -4271,35 +4274,35 @@ yyreduce:
break;
case 262:
-#line 1707 "go.y"
+#line 1710 "go.y"
{
(yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
}
break;
case 263:
-#line 1711 "go.y"
+#line 1714 "go.y"
{
(yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
}
break;
case 264:
-#line 1715 "go.y"
+#line 1718 "go.y"
{
(yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
}
break;
case 265:
-#line 1719 "go.y"
+#line 1722 "go.y"
{
(yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
}
break;
case 266:
-#line 1723 "go.y"
+#line 1726 "go.y"
{
(yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
(yyval.node)->sym = dclstack; // context, for goto restrictions
@@ -4307,7 +4310,7 @@ yyreduce:
break;
case 267:
-#line 1728 "go.y"
+#line 1731 "go.y"
{
(yyval.node) = nod(ORETURN, N, N);
(yyval.node)->list = (yyvsp[(2) - (2)].list);
@@ -4327,7 +4330,7 @@ yyreduce:
break;
case 268:
-#line 1747 "go.y"
+#line 1750 "go.y"
{
(yyval.list) = nil;
if((yyvsp[(1) - (1)].node) != N)
@@ -4336,7 +4339,7 @@ yyreduce:
break;
case 269:
-#line 1753 "go.y"
+#line 1756 "go.y"
{
(yyval.list) = (yyvsp[(1) - (3)].list);
if((yyvsp[(3) - (3)].node) != N)
@@ -4345,189 +4348,189 @@ yyreduce:
break;
case 270:
-#line 1761 "go.y"
+#line 1764 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 271:
-#line 1765 "go.y"
+#line 1768 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 272:
-#line 1771 "go.y"
+#line 1774 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 273:
-#line 1775 "go.y"
+#line 1778 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 274:
-#line 1781 "go.y"
+#line 1784 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 275:
-#line 1785 "go.y"
+#line 1788 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 276:
-#line 1791 "go.y"
+#line 1794 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 277:
-#line 1795 "go.y"
+#line 1798 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 278:
-#line 1804 "go.y"
+#line 1807 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 279:
-#line 1808 "go.y"
+#line 1811 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 280:
-#line 1812 "go.y"
+#line 1815 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 281:
-#line 1816 "go.y"
+#line 1819 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 282:
-#line 1821 "go.y"
+#line 1824 "go.y"
{
(yyval.list) = nil;
}
break;
case 283:
-#line 1825 "go.y"
+#line 1828 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
case 288:
-#line 1839 "go.y"
+#line 1842 "go.y"
{
(yyval.node) = N;
}
break;
case 290:
-#line 1845 "go.y"
+#line 1848 "go.y"
{
(yyval.list) = nil;
}
break;
case 292:
-#line 1851 "go.y"
+#line 1854 "go.y"
{
(yyval.node) = N;
}
break;
case 294:
-#line 1857 "go.y"
+#line 1860 "go.y"
{
(yyval.list) = nil;
}
break;
case 296:
-#line 1863 "go.y"
+#line 1866 "go.y"
{
(yyval.list) = nil;
}
break;
case 298:
-#line 1869 "go.y"
+#line 1872 "go.y"
{
(yyval.list) = nil;
}
break;
case 300:
-#line 1875 "go.y"
+#line 1878 "go.y"
{
(yyval.val).ctype = CTxxx;
}
break;
case 302:
-#line 1885 "go.y"
+#line 1888 "go.y"
{
importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
}
break;
case 303:
-#line 1889 "go.y"
+#line 1892 "go.y"
{
importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
}
break;
case 304:
-#line 1893 "go.y"
+#line 1896 "go.y"
{
importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
}
break;
case 305:
-#line 1897 "go.y"
+#line 1900 "go.y"
{
importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
}
break;
case 306:
-#line 1901 "go.y"
+#line 1904 "go.y"
{
importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
}
break;
case 307:
-#line 1905 "go.y"
+#line 1908 "go.y"
{
if((yyvsp[(2) - (4)].node) == N) {
dclcontext = PEXTERN; // since we skip the funcbody below
@@ -4548,7 +4551,7 @@ yyreduce:
break;
case 308:
-#line 1925 "go.y"
+#line 1928 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
structpkg = (yyval.sym)->pkg;
@@ -4556,7 +4559,7 @@ yyreduce:
break;
case 309:
-#line 1932 "go.y"
+#line 1935 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
importsym((yyvsp[(1) - (1)].sym), OTYPE);
@@ -4564,14 +4567,14 @@ yyreduce:
break;
case 315:
-#line 1952 "go.y"
+#line 1955 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
}
break;
case 316:
-#line 1956 "go.y"
+#line 1959 "go.y"
{
// predefined name like uint8
(yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
@@ -4584,49 +4587,49 @@ yyreduce:
break;
case 317:
-#line 1966 "go.y"
+#line 1969 "go.y"
{
(yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
}
break;
case 318:
-#line 1970 "go.y"
+#line 1973 "go.y"
{
(yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
}
break;
case 319:
-#line 1974 "go.y"
+#line 1977 "go.y"
{
(yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
}
break;
case 320:
-#line 1978 "go.y"
+#line 1981 "go.y"
{
(yyval.type) = tostruct((yyvsp[(3) - (4)].list));
}
break;
case 321:
-#line 1982 "go.y"
+#line 1985 "go.y"
{
(yyval.type) = tointerface((yyvsp[(3) - (4)].list));
}
break;
case 322:
-#line 1986 "go.y"
+#line 1989 "go.y"
{
(yyval.type) = ptrto((yyvsp[(2) - (2)].type));
}
break;
case 323:
-#line 1990 "go.y"
+#line 1993 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(2) - (2)].type);
@@ -4635,7 +4638,7 @@ yyreduce:
break;
case 324:
-#line 1996 "go.y"
+#line 1999 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (4)].type);
@@ -4644,7 +4647,7 @@ yyreduce:
break;
case 325:
-#line 2002 "go.y"
+#line 2005 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4653,7 +4656,7 @@ yyreduce:
break;
case 326:
-#line 2010 "go.y"
+#line 2013 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4662,14 +4665,14 @@ yyreduce:
break;
case 327:
-#line 2018 "go.y"
+#line 2021 "go.y"
{
(yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
}
break;
case 328:
-#line 2024 "go.y"
+#line 2027 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
if((yyvsp[(1) - (3)].sym))
@@ -4679,7 +4682,7 @@ yyreduce:
break;
case 329:
-#line 2031 "go.y"
+#line 2034 "go.y"
{
Type *t;
@@ -4696,7 +4699,7 @@ yyreduce:
break;
case 330:
-#line 2047 "go.y"
+#line 2050 "go.y"
{
Sym *s;
@@ -4715,49 +4718,49 @@ yyreduce:
break;
case 331:
-#line 2065 "go.y"
+#line 2068 "go.y"
{
(yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
}
break;
case 332:
-#line 2069 "go.y"
+#line 2072 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
}
break;
case 333:
-#line 2074 "go.y"
+#line 2077 "go.y"
{
(yyval.list) = nil;
}
break;
case 335:
-#line 2081 "go.y"
+#line 2084 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
}
break;
case 336:
-#line 2085 "go.y"
+#line 2088 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
}
break;
case 337:
-#line 2095 "go.y"
+#line 2098 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
case 338:
-#line 2099 "go.y"
+#line 2102 "go.y"
{
(yyval.node) = nodlit((yyvsp[(2) - (2)].val));
switch((yyval.node)->val.ctype){
@@ -4775,7 +4778,7 @@ yyreduce:
break;
case 339:
-#line 2114 "go.y"
+#line 2117 "go.y"
{
(yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
if((yyval.node)->op != OLITERAL)
@@ -4784,7 +4787,7 @@ yyreduce:
break;
case 341:
-#line 2123 "go.y"
+#line 2126 "go.y"
{
if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
(yyval.node) = (yyvsp[(2) - (5)].node);
@@ -4798,42 +4801,42 @@ yyreduce:
break;
case 344:
-#line 2139 "go.y"
+#line 2142 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 345:
-#line 2143 "go.y"
+#line 2146 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 346:
-#line 2149 "go.y"
+#line 2152 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 347:
-#line 2153 "go.y"
+#line 2156 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 348:
-#line 2159 "go.y"
+#line 2162 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 349:
-#line 2163 "go.y"
+#line 2166 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
@@ -4841,7 +4844,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 4846 "y.tab.c"
+#line 4849 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -5055,7 +5058,7 @@ yyreturn:
}
-#line 2167 "go.y"
+#line 2170 "go.y"
static void
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 38fc43ef1..e7f3fb5bb 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -40,9 +40,13 @@ build writes the resulting executable to output.
Otherwise build compiles the packages but discards the results,
serving only as a check that the packages can be built.
-The -o flag specifies the output file name. If not specified, the
-name is packagename.a (for a non-main package) or the base
-name of the first source file (for a main package).
+The -o flag specifies the output file name. If not specified, the
+output file name depends on the arguments and derives from the name
+of the package, such as p.a for package p, unless p is 'main'. If
+the package is main and file names are provided, the file name
+derives from the first file name mentioned, such as f1 for 'go build
+f1.go f2.go'; with no files provided ('go build'), the output file
+name is the base name of the containing directory.
The build flags are shared by the build, install, run, and test commands:
@@ -53,6 +57,9 @@ The build flags are shared by the build, install, run, and test commands:
-p n
the number of builds that can be run in parallel.
The default is the number of CPUs available.
+ -race
+ enable data race detection.
+ Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-v
print the names of packages as they are compiled.
-work
@@ -60,20 +67,22 @@ The build flags are shared by the build, install, run, and test commands:
do not delete it when exiting.
-x
print the commands.
- -race
- enable data race detection.
- Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-ccflags 'arg list'
- arguments to pass on each 5c, 6c, or 8c compiler invocation
+ arguments to pass on each 5c, 6c, or 8c compiler invocation.
-compiler name
- name of compiler to use, as in runtime.Compiler (gccgo or gc)
+ name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags 'arg list'
- arguments to pass on each gccgo compiler/linker invocation
+ arguments to pass on each gccgo compiler/linker invocation.
-gcflags 'arg list'
- arguments to pass on each 5g, 6g, or 8g compiler invocation
+ arguments to pass on each 5g, 6g, or 8g compiler invocation.
+ -installsuffix suffix
+ a suffix to use in the name of the package installation directory,
+ in order to keep output separate from default builds.
+ If using the -race flag, the install suffix is automatically set to race
+ or, if set explicitly, has _race appended to it.
-ldflags 'flag list'
- arguments to pass on each 5l, 6l, or 8l linker invocation
+ arguments to pass on each 5l, 6l, or 8l linker invocation.
-tags 'tag list'
a list of build tags to consider satisfied during the build.
See the documentation for the go/build package for
@@ -153,6 +162,7 @@ func addBuildFlags(cmd *Command) {
cmd.Flag.BoolVar(&buildA, "a", false, "")
cmd.Flag.BoolVar(&buildN, "n", false, "")
cmd.Flag.IntVar(&buildP, "p", buildP, "")
+ cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
cmd.Flag.BoolVar(&buildV, "v", false, "")
cmd.Flag.BoolVar(&buildX, "x", false, "")
cmd.Flag.BoolVar(&buildWork, "work", false, "")
@@ -391,7 +401,9 @@ var (
func (b *builder) init() {
var err error
- b.print = fmt.Print
+ b.print = func(a ...interface{}) (int, error) {
+ return fmt.Fprint(os.Stderr, a...)
+ }
b.actionCache = make(map[cacheKey]*action)
b.mkdirCache = make(map[string]bool)
@@ -1289,7 +1301,6 @@ func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt
return buf.Bytes(), err
}
- panic("unreachable")
}
// mkdir makes the named directory.
@@ -1632,7 +1643,7 @@ func (b *builder) libgcc(p *Package) (string, error) {
// print function to capture the command-line. This
// let's us assign it to $LIBGCC and produce a valid
// buildscript for cgo packages.
- b.print = func(a ...interface{}) (n int, err error) {
+ b.print = func(a ...interface{}) (int, error) {
return fmt.Fprint(&buf, a...)
}
}
@@ -2083,6 +2094,9 @@ func raceInit() {
buildGcflags = append(buildGcflags, "-race")
buildLdflags = append(buildLdflags, "-race")
buildCcflags = append(buildCcflags, "-D", "RACE")
- buildContext.InstallTag = "race"
+ if buildContext.InstallSuffix != "" {
+ buildContext.InstallSuffix += "_"
+ }
+ buildContext.InstallSuffix += "race"
buildContext.BuildTags = append(buildContext.BuildTags, "race")
}
diff --git a/src/cmd/go/discovery.go b/src/cmd/go/discovery.go
index d9f930867..047834050 100644
--- a/src/cmd/go/discovery.go
+++ b/src/cmd/go/discovery.go
@@ -48,7 +48,6 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport) {
})
}
}
- return
}
// attrValue returns the attribute value for the case-insensitive key
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index 0297b7602..a8a9b66aa 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -2,6 +2,9 @@
// 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. GENERATED BY mkdoc.sh.
+// Edit the documentation in other files and rerun mkdoc.sh to generate this one.
+
/*
Go is a tool for managing Go source code.
@@ -56,9 +59,13 @@ build writes the resulting executable to output.
Otherwise build compiles the packages but discards the results,
serving only as a check that the packages can be built.
-The -o flag specifies the output file name. If not specified, the
-name is packagename.a (for a non-main package) or the base
-name of the first source file (for a main package).
+The -o flag specifies the output file name. If not specified, the
+output file name depends on the arguments and derives from the name
+of the package, such as p.a for package p, unless p is 'main'. If
+the package is main and file names are provided, the file name
+derives from the first file name mentioned, such as f1 for 'go build
+f1.go f2.go'; with no files provided ('go build'), the output file
+name is the base name of the containing directory.
The build flags are shared by the build, install, run, and test commands:
@@ -69,6 +76,9 @@ The build flags are shared by the build, install, run, and test commands:
-p n
the number of builds that can be run in parallel.
The default is the number of CPUs available.
+ -race
+ enable data race detection.
+ Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-v
print the names of packages as they are compiled.
-work
@@ -76,20 +86,22 @@ The build flags are shared by the build, install, run, and test commands:
do not delete it when exiting.
-x
print the commands.
- -race
- enable data race detection.
- Supported only on linux/amd64, darwin/amd64 and windows/amd64.
-ccflags 'arg list'
- arguments to pass on each 5c, 6c, or 8c compiler invocation
+ arguments to pass on each 5c, 6c, or 8c compiler invocation.
-compiler name
- name of compiler to use, as in runtime.Compiler (gccgo or gc)
+ name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags 'arg list'
- arguments to pass on each gccgo compiler/linker invocation
+ arguments to pass on each gccgo compiler/linker invocation.
-gcflags 'arg list'
- arguments to pass on each 5g, 6g, or 8g compiler invocation
+ arguments to pass on each 5g, 6g, or 8g compiler invocation.
+ -installsuffix suffix
+ a suffix to use in the name of the package installation directory,
+ in order to keep output separate from default builds.
+ If using the -race flag, the install suffix is automatically set to race
+ or, if set explicitly, has _race appended to it.
-ldflags 'flag list'
- arguments to pass on each 5l, 6l, or 8l linker invocation
+ arguments to pass on each 5l, 6l, or 8l linker invocation.
-tags 'tag list'
a list of build tags to consider satisfied during the build.
See the documentation for the go/build package for
@@ -679,6 +691,11 @@ Description of testing flags
The 'go test' command takes both flags that apply to 'go test' itself
and flags that apply to the resulting test binary.
+Several of the flags control profiling and write an execution profile
+suitable for "go tool pprof"; run "go tool pprof help" for more
+information. The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+
The following flags are recognized by the 'go test' command and
control the execution of any test:
@@ -716,8 +733,8 @@ control the execution of any test:
Write a CPU profile to the specified file before exiting.
-memprofile mem.out
- Write a memory profile to the specified file when all tests
- are complete.
+ Write a memory profile to the specified file after all tests
+ have passed.
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
diff --git a/src/cmd/go/go11.go b/src/cmd/go/go11.go
new file mode 100644
index 000000000..8a434dfed
--- /dev/null
+++ b/src/cmd/go/go11.go
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.1
+
+package main
+
+// Test that go1.1 tag above is included in builds. main.go refers to this definition.
+const go11tag = true
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index bf1dad40f..61e629968 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -108,6 +108,7 @@ func setExitStatus(n int) {
}
func main() {
+ _ = go11tag
flag.Usage = usage
flag.Parse()
log.SetFlags(0)
@@ -129,8 +130,11 @@ func main() {
fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
} else {
for _, p := range filepath.SplitList(gopath) {
- if strings.Contains(p, "~") && runtime.GOOS != "windows" {
- fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot contain shell metacharacter '~': %q\n", p)
+ // Note: using HasPrefix instead of Contains because a ~ can appear
+ // in the middle of directory elements, such as /tmp/git-1.8.2~rc3
+ // or C:\PROGRA~1. Only ~ as a path prefix has meaning to the shell.
+ if strings.HasPrefix(p, "~") {
+ fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p)
os.Exit(2)
}
if build.IsLocalImport(p) {
@@ -189,6 +193,9 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
// 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. GENERATED BY mkdoc.sh.
+// Edit the documentation in other files and rerun mkdoc.sh to generate this one.
+
/*
{{range .}}{{if .Short}}{{.Short | capitalize}}
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index 7fc61fd86..b33d800bf 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -72,6 +72,7 @@ type Package struct {
imports []*Package
deps []*Package
gofiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+ sfiles []string
allgofiles []string // gofiles + IgnoredGoFiles, absolute paths
target string // installed file for this package (may be executable)
fake bool // synthesized package
@@ -366,6 +367,12 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
sort.Strings(p.gofiles)
+ p.sfiles = stringList(p.SFiles)
+ for i := range p.sfiles {
+ p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i])
+ }
+ sort.Strings(p.sfiles)
+
p.allgofiles = stringList(p.IgnoredGoFiles)
for i := range p.allgofiles {
p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash
index 460061a11..e2264a46e 100755
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -11,18 +11,19 @@ ok=true
unset GOPATH
unset GOBIN
-# Test that error messages have file:line information
-# at beginning of line.
-for i in testdata/errmsg/*.go
-do
- # TODO: |cat should not be necessary here but is.
- ./testgo test $i 2>&1 | cat >err.out || true
- if ! grep -q "^$i:" err.out; then
- echo "$i: missing file:line in error message"
- cat err.out
- ok=false
- fi
-done
+# Test that error messages have file:line information at beginning of
+# the line. Also test issue 4917: that the error is on stderr.
+d=$(mktemp -d -t testgoXXX)
+fn=$d/err.go
+echo "package main" > $fn
+echo 'import "bar"' >> $fn
+./testgo run $fn 2>$d/err.out || true
+if ! grep -q "^$fn:" $d/err.out; then
+ echo "missing file:line in error message"
+ cat $d/err.out
+ ok=false
+fi
+rm -r $d
# Test local (./) imports.
testlocal() {
@@ -51,7 +52,7 @@ testlocal() {
ok=false
fi
- rm -f err.out hello.out hello
+ rm -f hello.out hello
# Test that go install x.go fails.
if ./testgo install "testdata/$local/easy.go" >/dev/null 2>&1; then
@@ -183,7 +184,7 @@ fi
# issue 4186. go get cannot be used to download packages to $GOROOT
# Test that without GOPATH set, go get should fail
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src/pkg
if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
@@ -191,7 +192,7 @@ if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch
fi
rm -rf $d
# Test that with GOPATH=$GOROOT, go get should fail
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src/pkg
if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
@@ -200,7 +201,7 @@ fi
rm -rf $d
# issue 3941: args with spaces
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
cat >$d/main.go<<EOF
package main
var extern string
@@ -226,7 +227,7 @@ rm -f strings.prof strings.test
# issue 4568. test that symlinks don't screw things up too badly.
old=$(pwd)
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src
(
ln -s $d $d/src/dir1
@@ -247,7 +248,7 @@ fi
rm -rf $d
# issue 4515.
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src/example/a $d/src/example/b $d/bin
cat >$d/src/example/a/main.go <<EOF
package main
@@ -280,7 +281,7 @@ unset GOPATH
rm -rf $d
# issue 4773. case-insensitive collisions
-d=$(mktemp -d -t testgo)
+d=$(mktemp -d -t testgoXXX)
export GOPATH=$d
mkdir -p $d/src/example/a $d/src/example/b
cat >$d/src/example/a/a.go <<EOF
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index 3132ab210..de69efe8f 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -81,6 +81,11 @@ var helpTestflag = &Command{
The 'go test' command takes both flags that apply to 'go test' itself
and flags that apply to the resulting test binary.
+Several of the flags control profiling and write an execution profile
+suitable for "go tool pprof"; run "go tool pprof help" for more
+information. The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+
The following flags are recognized by the 'go test' command and
control the execution of any test:
@@ -118,8 +123,8 @@ control the execution of any test:
Write a CPU profile to the specified file before exiting.
-memprofile mem.out
- Write a memory profile to the specified file when all tests
- are complete.
+ Write a memory profile to the specified file after all tests
+ have passed.
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
diff --git a/src/cmd/go/testdata/errmsg/x.go b/src/cmd/go/testdata/errmsg/x.go
deleted file mode 100644
index 60f5b6e98..000000000
--- a/src/cmd/go/testdata/errmsg/x.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package foo
-
-import "bar"
diff --git a/src/cmd/go/testdata/errmsg/x1_test.go b/src/cmd/go/testdata/errmsg/x1_test.go
deleted file mode 100644
index eb1a6798c..000000000
--- a/src/cmd/go/testdata/errmsg/x1_test.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package foo_test
-
-import "bar"
diff --git a/src/cmd/go/testdata/errmsg/x_test.go b/src/cmd/go/testdata/errmsg/x_test.go
deleted file mode 100644
index 60f5b6e98..000000000
--- a/src/cmd/go/testdata/errmsg/x_test.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package foo
-
-import "bar"
diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go
index eb0b89cca..503e16362 100644
--- a/src/cmd/go/vet.go
+++ b/src/cmd/go/vet.go
@@ -32,6 +32,6 @@ func runVet(cmd *Command, args []string) {
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
- run(tool("vet"), relPaths(pkg.gofiles))
+ run(tool("vet"), relPaths(stringList(pkg.gofiles, pkg.sfiles)))
}
}
diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go
index ddb6d2687..e5f5324cd 100644
--- a/src/cmd/godoc/doc.go
+++ b/src/cmd/godoc/doc.go
@@ -67,6 +67,9 @@ The flags are:
-maxresults=10000
maximum number of full text search results shown
(no full text index is built if maxresults <= 0)
+ -notes="BUG"
+ regular expression matching note markers to show
+ (e.g., "BUG|TODO", ".*")
-html
print HTML in command-line mode
-goroot=$GOROOT
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index 872b0dc1e..577432113 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -84,15 +84,11 @@ var (
cmdHandler docServer
pkgHandler docServer
- // which code 'Notes' to show
- notes = flag.String("notes", "BUG", "comma separated list of Note markers as per pkg:go/doc")
- // list of 'Notes' to show
- notesToShow []string
+ // source code notes
+ notes = flag.String("notes", "BUG", "regular expression matching note markers to show")
)
func initHandlers() {
- notesToShow = strings.Split(*notes, ",")
-
fileServer = http.FileServer(&httpFS{fs})
cmdHandler = docServer{"/cmd/", "/src/cmd"}
pkgHandler = docServer{"/pkg/", "/src/pkg"}
@@ -911,12 +907,12 @@ type PageInfo struct {
Err error // error or nil
// package info
- FSet *token.FileSet // nil if no package documentation
- PDoc *doc.Package // nil if no package documentation
- Examples []*doc.Example // nil if no example code
- Notes map[string][]string // nil if no package Notes
- PAst *ast.File // nil if no AST with package exports
- IsMain bool // true for package main
+ FSet *token.FileSet // nil if no package documentation
+ PDoc *doc.Package // nil if no package documentation
+ Examples []*doc.Example // nil if no example code
+ Notes map[string][]*doc.Note // nil if no package Notes
+ PAst *ast.File // nil if no AST with package exports
+ IsMain bool // true for package main
// directory info
Dirs *DirList // nil if no directory information
@@ -1100,10 +1096,15 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (inf
// collect any notes that we want to show
if info.PDoc.Notes != nil {
- info.Notes = make(map[string][]string)
- for _, m := range notesToShow {
- if n := info.PDoc.Notes[m]; n != nil {
- info.Notes[m] = n
+ // could regexp.Compile only once per godoc, but probably not worth it
+ if rx, err := regexp.Compile(*notes); err == nil {
+ for m, n := range info.PDoc.Notes {
+ if rx.MatchString(m) {
+ if info.Notes == nil {
+ info.Notes = make(map[string][]*doc.Note)
+ }
+ info.Notes[m] = n
+ }
}
}
}
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 6c6b1be43..b70d4636c 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -33,6 +33,7 @@
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
+#include "../ld/macho.h"
#include "../ld/pe.h"
#include "../../pkg/runtime/mgc0.h"
@@ -135,11 +136,7 @@ addrel(Sym *s)
s->maxr = 4;
else
s->maxr <<= 1;
- s->r = realloc(s->r, s->maxr*sizeof s->r[0]);
- if(s->r == 0) {
- diag("out of memory");
- errorexit();
- }
+ s->r = erealloc(s->r, s->maxr*sizeof s->r[0]);
memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
}
return &s->r[s->nr++];
@@ -158,6 +155,7 @@ relocsym(Sym *s)
cursym = s;
memset(&p, 0, sizeof p);
for(r=s->r; r<s->r+s->nr; r++) {
+ r->done = 1;
off = r->off;
siz = r->siz;
if(off < 0 || off+siz > s->np) {
@@ -180,35 +178,72 @@ relocsym(Sym *s)
switch(r->type) {
default:
o = 0;
- if(isobj || archreloc(r, s, &o) < 0)
+ if(linkmode == LinkExternal || archreloc(r, s, &o) < 0)
diag("unknown reloc %d", r->type);
break;
case D_ADDR:
- o = symaddr(r->sym) + r->add;
- if(isobj && r->sym->type != SCONST) {
- if(thechar == '6')
- o = 0;
- else {
- // set up addend for eventual relocation via outer symbol
- rs = r->sym;
- while(rs->outer != nil)
- rs = rs->outer;
- o -= symaddr(rs);
+ if(linkmode == LinkExternal && r->sym->type != SCONST) {
+ r->done = 0;
+
+ // set up addend for eventual relocation via outer symbol.
+ rs = r->sym;
+ r->xadd = r->add;
+ while(rs->outer != nil) {
+ r->xadd += symaddr(rs) - symaddr(rs->outer);
+ rs = rs->outer;
+ }
+ if(rs->type != SHOSTOBJ && rs->sect == nil)
+ diag("missing section for %s", rs->name);
+ r->xsym = rs;
+
+ o = r->xadd;
+ if(iself) {
+ if(thechar == '6')
+ o = 0;
+ } else if(HEADTYPE == Hdarwin) {
+ if(rs->type != SHOSTOBJ)
+ o += symaddr(rs);
+ } else {
+ diag("unhandled pcrel relocation for %s", headtype);
}
+ break;
}
+ o = symaddr(r->sym) + r->add;
break;
case D_PCREL:
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
+ if(linkmode == LinkExternal && r->sym && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
+ r->done = 0;
+
+ // set up addend for eventual relocation via outer symbol.
+ rs = r->sym;
+ r->xadd = r->add;
+ while(rs->outer != nil) {
+ r->xadd += symaddr(rs) - symaddr(rs->outer);
+ rs = rs->outer;
+ }
+ r->xadd -= r->siz; // relative to address after the relocated chunk
+ if(rs->type != SHOSTOBJ && rs->sect == nil)
+ diag("missing section for %s", rs->name);
+ r->xsym = rs;
+
+ o = r->xadd;
+ if(iself) {
+ if(thechar == '6')
+ o = 0;
+ } else if(HEADTYPE == Hdarwin) {
+ if(rs->type != SHOSTOBJ)
+ o += symaddr(rs) - rs->sect->vaddr;
+ o -= r->off; // WTF?
+ } else {
+ diag("unhandled pcrel relocation for %s", headtype);
+ }
+ break;
+ }
o = 0;
if(r->sym)
o += symaddr(r->sym);
o += r->add - (s->value + r->off + r->siz);
- if(isobj && r->sym->type != SCONST) {
- if(thechar == '6')
- o = 0;
- else
- o = r->add - r->siz;
- }
break;
case D_SIZE:
o = r->sym->size + r->add;
@@ -300,7 +335,7 @@ dynrelocsym(Sym *s)
for(r=s->r; r<s->r+s->nr; r++) {
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
adddynrel(s, r);
- if(flag_shared && r->sym != S && (r->sym->dynimpname == nil || r->sym->dynexport) && r->type == D_ADDR
+ if(flag_shared && r->sym != S && s->type != SDYNIMPORT && r->type == D_ADDR
&& (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
// Create address based RELATIVE relocation
adddynrela(rel, s, r);
@@ -342,11 +377,7 @@ symgrow(Sym *s, int32 siz)
s->maxp = 8;
while(s->maxp < siz)
s->maxp <<= 1;
- s->p = realloc(s->p, s->maxp);
- if(s->p == nil) {
- diag("out of memory");
- errorexit();
- }
+ s->p = erealloc(s->p, s->maxp);
memset(s->p+s->np, 0, s->maxp-s->np);
}
s->np = siz;
@@ -560,8 +591,10 @@ void
datblk(int32 addr, int32 size)
{
Sym *sym;
- int32 eaddr;
+ int32 i, eaddr;
uchar *p, *ep;
+ char *typ, *rsname;
+ Reloc *r;
if(debug['a'])
Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos());
@@ -581,23 +614,46 @@ datblk(int32 addr, int32 size)
if(sym->value >= eaddr)
break;
if(addr < sym->value) {
- Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(pre-pad)", addr);
+ Bprint(&bso, "\t%.8ux| 00 ...\n", addr);
addr = sym->value;
}
- Bprint(&bso, "%-20s %.8ux|", sym->name, (uint)addr);
+ Bprint(&bso, "%s\n\t%.8ux|", sym->name, (uint)addr);
p = sym->p;
ep = p + sym->np;
- while(p < ep)
+ while(p < ep) {
+ if(p > sym->p && (int)(p-sym->p)%16 == 0)
+ Bprint(&bso, "\n\t%.8ux|", (uint)(addr+(p-sym->p)));
Bprint(&bso, " %.2ux", *p++);
+ }
addr += sym->np;
for(; addr < sym->value+sym->size; addr++)
Bprint(&bso, " %.2ux", 0);
Bprint(&bso, "\n");
+
+ if(linkmode == LinkExternal) {
+ for(i=0; i<sym->nr; i++) {
+ r = &sym->r[i];
+ rsname = "";
+ if(r->sym)
+ rsname = r->sym->name;
+ typ = "?";
+ switch(r->type) {
+ case D_ADDR:
+ typ = "addr";
+ break;
+ case D_PCREL:
+ typ = "pcrel";
+ break;
+ }
+ Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n",
+ (uint)(sym->value+r->off), r->siz, typ, rsname, r->add, r->sym->value+r->add);
+ }
+ }
}
if(addr < eaddr)
- Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(post-pad)", (uint)addr);
- Bprint(&bso, "%-20s %.8ux|\n", "", (uint)eaddr);
+ Bprint(&bso, "\t%.8ux| 00 ...\n", (uint)addr);
+ Bprint(&bso, "\t%.8ux|\n", (uint)eaddr);
}
void
@@ -883,36 +939,41 @@ dosymtype(void)
}
static int32
-alignsymsize(int32 s)
+symalign(Sym *s)
{
- if(s >= 8)
- s = rnd(s, 8);
- else if(s >= PtrSize)
- s = rnd(s, PtrSize);
- else if(s > 2)
- s = rnd(s, 4);
- return s;
-}
+ int32 align;
+
+ if(s->align != 0)
+ return s->align;
+ align = MaxAlign;
+ while(align > s->size && align > 1)
+ align >>= 1;
+ if(align < s->align)
+ align = s->align;
+ return align;
+}
+
static int32
aligndatsize(int32 datsize, Sym *s)
{
- int32 t;
+ return rnd(datsize, symalign(s));
+}
- if(s->align != 0) {
- datsize = rnd(datsize, s->align);
- } else {
- t = alignsymsize(s->size);
- if(t & 1) {
- ;
- } else if(t & 2)
- datsize = rnd(datsize, 2);
- else if(t & 4)
- datsize = rnd(datsize, 4);
- else
- datsize = rnd(datsize, 8);
+// maxalign returns the maximum required alignment for
+// the list of symbols s; the list stops when s->type exceeds type.
+static int32
+maxalign(Sym *s, int type)
+{
+ int32 align, max;
+
+ max = 0;
+ for(; s != S && s->type <= type; s = s->next) {
+ align = symalign(s);
+ if(max < align)
+ max = align;
}
- return datsize;
+ return max;
}
static void
@@ -946,7 +1007,7 @@ gcaddsym(Sym *gc, Sym *s, int32 off)
void
dodata(void)
{
- int32 t, datsize;
+ int32 n, datsize;
Section *sect;
Sym *s, *last, **l;
Sym *gcdata1, *gcbss1;
@@ -956,11 +1017,11 @@ dodata(void)
Bflush(&bso);
// define garbage collection symbols
- gcdata1 = lookup("gcdata1", 0);
- gcdata1->type = SGCDATA;
+ gcdata1 = lookup("gcdata", 0);
+ gcdata1->type = STYPE;
gcdata1->reachable = 1;
- gcbss1 = lookup("gcbss1", 0);
- gcbss1->type = SGCBSS;
+ gcbss1 = lookup("gcbss", 0);
+ gcbss1->type = STYPE;
gcbss1->reachable = 1;
// size of .data and .bss section. the zero value is later replaced by the actual size of the section.
@@ -995,7 +1056,11 @@ dodata(void)
* to assign addresses, record all the necessary
* dynamic relocations. these will grow the relocation
* symbol, which is itself data.
+ *
+ * on darwin, we need the symbol table numbers for dynreloc.
*/
+ if(HEADTYPE == Hdarwin)
+ machosymorder();
dynreloc();
/* some symbols may no longer belong in datap (Mach-O) */
@@ -1034,52 +1099,54 @@ dodata(void)
datsize = 0;
for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
sect = addsection(&segdata, s->name, 06);
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ sect->align = symalign(s);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
s->sect = sect;
s->type = SDATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
sect->len = datsize - sect->vaddr;
}
/* pointer-free data */
sect = addsection(&segdata, ".noptrdata", 06);
+ sect->align = maxalign(s, SDATARELRO-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("noptrdata", 0)->sect = sect;
lookup("enoptrdata", 0)->sect = sect;
for(; s != nil && s->type < SDATARELRO; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SDATA;
- t = alignsymsize(s->size);
- datsize = aligndatsize(datsize, s);
s->value = datsize;
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* dynamic relocated rodata */
if(flag_shared) {
sect = addsection(&segdata, ".data.rel.ro", 06);
+ sect->align = maxalign(s, SDATARELRO);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("datarelro", 0)->sect = sect;
lookup("edatarelro", 0)->sect = sect;
for(; s != nil && s->type == SDATARELRO; s = s->next) {
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SDATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
}
/* data */
sect = addsection(&segdata, ".data", 06);
+ sect->align = maxalign(s, SBSS-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("data", 0)->sect = sect;
lookup("edata", 0)->sect = sect;
@@ -1090,39 +1157,39 @@ dodata(void)
}
s->sect = sect;
s->type = SDATA;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
s->value = datsize;
gcaddsym(gcdata1, s, datsize - sect->vaddr); // gc
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
adduintxx(gcdata1, GC_END, PtrSize);
setuintxx(gcdata1, 0, sect->len, PtrSize);
/* bss */
sect = addsection(&segdata, ".bss", 06);
+ sect->align = maxalign(s, SNOPTRBSS-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("bss", 0)->sect = sect;
lookup("ebss", 0)->sect = sect;
for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
s->sect = sect;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
s->value = datsize;
gcaddsym(gcbss1, s, datsize - sect->vaddr); // gc
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
adduintxx(gcbss1, GC_END, PtrSize);
setuintxx(gcbss1, 0, sect->len, PtrSize);
/* pointer-free bss */
sect = addsection(&segdata, ".noptrbss", 06);
+ sect->align = maxalign(s, SNOPTRBSS);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("noptrbss", 0)->sect = sect;
lookup("enoptrbss", 0)->sect = sect;
@@ -1131,117 +1198,101 @@ dodata(void)
cursym = s;
diag("unexpected symbol type %d", s->type);
}
- s->sect = sect;
- t = alignsymsize(s->size);
datsize = aligndatsize(datsize, s);
+ s->sect = sect;
s->value = datsize;
- datsize += t;
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
lookup("end", 0)->sect = sect;
/* we finished segdata, begin segtext */
+ s = datap;
+ datsize = 0;
/* read-only data */
sect = addsection(&segtext, ".rodata", 04);
+ sect->align = maxalign(s, STYPELINK-1);
sect->vaddr = 0;
lookup("rodata", 0)->sect = sect;
lookup("erodata", 0)->sect = sect;
datsize = 0;
- s = datap;
for(; s != nil && s->type < STYPELINK; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
s->type = SRODATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
- /* type */
+ /* typelink */
sect = addsection(&segtext, ".typelink", 04);
+ sect->align = maxalign(s, STYPELINK);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("typelink", 0)->sect = sect;
lookup("etypelink", 0)->sect = sect;
for(; s != nil && s->type == STYPELINK; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
-
- /* gcdata */
- sect = addsection(&segtext, ".gcdata", 04);
- sect->vaddr = datsize;
- lookup("gcdata", 0)->sect = sect;
- lookup("egcdata", 0)->sect = sect;
- for(; s != nil && s->type == SGCDATA; s = s->next) {
- s->sect = sect;
- s->type = SRODATA;
- s->value = datsize;
- datsize += s->size;
- }
- sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
-
- /* gcbss */
- sect = addsection(&segtext, ".gcbss", 04);
- sect->vaddr = datsize;
- lookup("gcbss", 0)->sect = sect;
- lookup("egcbss", 0)->sect = sect;
- for(; s != nil && s->type == SGCBSS; s = s->next) {
- s->sect = sect;
- s->type = SRODATA;
- s->value = datsize;
- datsize += s->size;
- }
- sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gosymtab */
sect = addsection(&segtext, ".gosymtab", 04);
+ sect->align = maxalign(s, SPCLNTAB-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("symtab", 0)->sect = sect;
lookup("esymtab", 0)->sect = sect;
for(; s != nil && s->type < SPCLNTAB; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
/* gopclntab */
sect = addsection(&segtext, ".gopclntab", 04);
+ sect->align = maxalign(s, SELFROSECT-1);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
lookup("pclntab", 0)->sect = sect;
lookup("epclntab", 0)->sect = sect;
for(; s != nil && s->type < SELFROSECT; s = s->next) {
+ datsize = aligndatsize(datsize, s);
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
datsize += s->size;
}
sect->len = datsize - sect->vaddr;
- datsize = rnd(datsize, PtrSize);
- /* read-only ELF sections */
+ /* read-only ELF, Mach-O sections */
for(; s != nil && s->type < SELFSECT; s = s->next) {
sect = addsection(&segtext, s->name, 04);
- if(s->align != 0)
- datsize = rnd(datsize, s->align);
+ sect->align = symalign(s);
+ datsize = rnd(datsize, sect->align);
sect->vaddr = datsize;
s->sect = sect;
s->type = SRODATA;
s->value = datsize;
- datsize += rnd(s->size, PtrSize);
+ datsize += s->size;
sect->len = datsize - sect->vaddr;
}
+
+ /* number the sections */
+ n = 1;
+ for(sect = segtext.sect; sect != nil; sect = sect->next)
+ sect->extnum = n++;
+ for(sect = segdata.sect; sect != nil; sect = sect->next)
+ sect->extnum = n++;
}
// assign addresses to text
@@ -1259,6 +1310,7 @@ textaddress(void)
// Could parallelize, by assigning to text
// and then letting threads copy down, but probably not worth it.
sect = segtext.sect;
+ sect->align = FuncAlign;
lookup("text", 0)->sect = sect;
lookup("etext", 0)->sect = sect;
va = INITTEXT;
@@ -1282,11 +1334,6 @@ textaddress(void)
}
va += sym->size;
}
-
- // Align end of code so that rodata starts aligned.
- // 128 bytes is likely overkill but definitely cheap.
- va = rnd(va, 128);
-
sect->len = va - sect->vaddr;
}
@@ -1295,17 +1342,19 @@ void
address(void)
{
Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
- Section *gcdata, *gcbss, *typelink;
+ Section *typelink;
Sym *sym, *sub;
uvlong va;
+ vlong vlen;
va = INITTEXT;
segtext.rwx = 05;
segtext.vaddr = va;
segtext.fileoff = HEADR;
for(s=segtext.sect; s != nil; s=s->next) {
+ va = rnd(va, s->align);
s->vaddr = va;
- va += rnd(s->len, PtrSize);
+ va += s->len;
}
segtext.len = va - INITTEXT;
segtext.filelen = segtext.len;
@@ -1326,9 +1375,11 @@ address(void)
noptrbss = nil;
datarelro = nil;
for(s=segdata.sect; s != nil; s=s->next) {
+ vlen = s->len;
+ if(s->next)
+ vlen = s->next->vaddr - s->vaddr;
s->vaddr = va;
- va += s->len;
- segdata.filelen += s->len;
+ va += vlen;
segdata.len = va - segdata.vaddr;
if(strcmp(s->name, ".data") == 0)
data = s;
@@ -1341,14 +1392,12 @@ address(void)
if(strcmp(s->name, ".data.rel.ro") == 0)
datarelro = s;
}
- segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
+ segdata.filelen = bss->vaddr - segdata.vaddr;
text = segtext.sect;
rodata = text->next;
typelink = rodata->next;
- gcdata = typelink->next;
- gcbss = gcdata->next;
- symtab = gcbss->next;
+ symtab = typelink->next;
pclntab = symtab->next;
for(sym = datap; sym != nil; sym = sym->next) {
@@ -1371,10 +1420,15 @@ address(void)
xdefine("datarelro", SRODATA, datarelro->vaddr);
xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
}
- xdefine("gcdata", SGCDATA, gcdata->vaddr);
- xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
- xdefine("gcbss", SGCBSS, gcbss->vaddr);
- xdefine("egcbss", SGCBSS, gcbss->vaddr + gcbss->len);
+
+ sym = lookup("gcdata", 0);
+ xdefine("egcdata", STYPE, symaddr(sym) + sym->size);
+ lookup("egcdata", 0)->sect = sym->sect;
+
+ sym = lookup("gcbss", 0);
+ xdefine("egcbss", STYPE, symaddr(sym) + sym->size);
+ lookup("egcbss", 0)->sect = sym->sect;
+
xdefine("symtab", SRODATA, symtab->vaddr);
xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
xdefine("pclntab", SRODATA, pclntab->vaddr);
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index d6a357e49..4bf788e64 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -41,9 +41,13 @@ static vlong arangeso;
static vlong arangessize;
static vlong gdbscripto;
static vlong gdbscriptsize;
+static vlong inforeloco;
+static vlong inforelocsize;
static char gdbscript[1024];
+static Sym *dsym;
+
/*
* Basic I/O
*/
@@ -150,6 +154,7 @@ enum
DW_ABRV_IFACETYPE,
DW_ABRV_MAPTYPE,
DW_ABRV_PTRTYPE,
+ DW_ABRV_BARE_PTRTYPE, // only for void*, no DW_AT_type attr to please gdb 6.
DW_ABRV_SLICETYPE,
DW_ABRV_STRINGTYPE,
DW_ABRV_STRUCTTYPE,
@@ -303,6 +308,12 @@ static struct DWAbbrev {
DW_AT_type, DW_FORM_ref_addr,
0, 0
},
+ /* BARE_PTRTYPE */
+ {
+ DW_TAG_pointer_type, DW_CHILDREN_no,
+ DW_AT_name, DW_FORM_string,
+ 0, 0
+ },
/* SLICETYPE */
{
@@ -485,26 +496,43 @@ mkindex(DWDie *die)
die->hash = mal(HASHSIZE * sizeof(DWDie*));
}
+static DWDie*
+walktypedef(DWDie *die)
+{
+ DWAttr *attr;
+
+ // Resolve typedef if present.
+ if (die->abbrev == DW_ABRV_TYPEDECL) {
+ for (attr = die->attr; attr; attr = attr->link) {
+ if (attr->atr == DW_AT_type && attr->cls == DW_CLS_REFERENCE && attr->data != nil) {
+ return (DWDie*)attr->data;
+ }
+ }
+ }
+ return die;
+}
+
// Find child by AT_name using hashtable if available or linear scan
// if not.
static DWDie*
find(DWDie *die, char* name)
{
- DWDie *a, *b;
+ DWDie *a, *b, *die2;
int h;
+top:
if (die->hash == nil) {
for (a = die->child; a != nil; a = a->link)
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
return a;
- return nil;
+ goto notfound;
}
h = hashstr(name);
a = die->hash[h];
if (a == nil)
- return nil;
+ goto notfound;
if (strcmp(name, getattr(a, DW_AT_name)->data) == 0)
@@ -522,6 +550,14 @@ find(DWDie *die, char* name)
a = b;
b = b->hlink;
}
+
+notfound:
+ die2 = walktypedef(die);
+ if(die2 != die) {
+ die = die2;
+ goto top;
+ }
+
return nil;
}
@@ -531,7 +567,7 @@ find_or_diag(DWDie *die, char* name)
DWDie *r;
r = find(die, name);
if (r == nil) {
- diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name);
+ diag("dwarf find: %s %p has no %s", getattr(die, DW_AT_name)->data, die, name);
errorexit();
}
return r;
@@ -548,14 +584,33 @@ newrefattr(DWDie *die, uint8 attr, DWDie* ref)
static int fwdcount;
static void
-putattr(int form, int cls, vlong value, char *data)
+putattr(int abbrev, int form, int cls, vlong value, char *data)
{
+ Reloc *r;
+
switch(form) {
case DW_FORM_addr: // address
addrput(value);
break;
case DW_FORM_block1: // block
+ if(cls == DW_CLS_ADDRESS) {
+ cput(1+PtrSize);
+ cput(DW_OP_addr);
+ if(linkmode == LinkExternal) {
+ r = addrel(dsym);
+ r->sym = (Sym*)data;
+ r->xsym = r->sym;
+ r->off = cpos() - infoo;
+ r->siz = PtrSize;
+ r->type = D_ADDR;
+ r->add = value - r->sym->value;
+ r->xadd = r->add;
+ value = r->add;
+ }
+ addrput(value);
+ break;
+ }
value &= 0xff;
cput(value);
while(value--)
@@ -615,13 +670,23 @@ putattr(int form, int cls, vlong value, char *data)
break;
case DW_FORM_ref_addr: // reference to a DIE in the .info section
+ // In DWARF 2 (which is what we claim to generate),
+ // the ref_addr is the same size as a normal address.
+ // In DWARF 3 it is always 32 bits, unless emitting a large
+ // (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
if (data == nil) {
- diag("dwarf: null reference");
- LPUT(0); // invalid dwarf, gdb will complain.
+ diag("dwarf: null reference in %d", abbrev);
+ if(PtrSize == 8)
+ VPUT(0); // invalid dwarf, gdb will complain.
+ else
+ LPUT(0); // invalid dwarf, gdb will complain.
} else {
if (((DWDie*)data)->offs == 0)
fwdcount++;
- LPUT(((DWDie*)data)->offs);
+ if(PtrSize == 8)
+ VPUT(((DWDie*)data)->offs);
+ else
+ LPUT(((DWDie*)data)->offs);
}
break;
@@ -654,12 +719,12 @@ putattrs(int abbrev, DWAttr* attr)
for(af = abbrevs[abbrev].attr; af->attr; af++)
if (attrs[af->attr])
- putattr(af->form,
+ putattr(abbrev, af->form,
attrs[af->attr]->cls,
attrs[af->attr]->value,
attrs[af->attr]->data);
else
- putattr(af->form, 0, 0, 0);
+ putattr(abbrev, af->form, 0, 0, nil);
}
static void putdie(DWDie* die);
@@ -729,16 +794,9 @@ newmemberoffsetattr(DWDie *die, int32 offs)
// GDB doesn't like DW_FORM_addr for DW_AT_location, so emit a
// location expression that evals to a const.
static void
-newabslocexprattr(DWDie *die, vlong addr)
+newabslocexprattr(DWDie *die, vlong addr, Sym *sym)
{
- char block[10];
- int i;
-
- i = 0;
- block[i++] = DW_OP_constu;
- i += uleb128enc(addr, block+i);
- newattr(die, DW_AT_location, DW_CLS_BLOCK, i, mal(i));
- memmove(die->attr->data, block, i);
+ newattr(die, DW_AT_location, DW_CLS_ADDRESS, addr, (char*)sym);
}
@@ -766,6 +824,31 @@ lookup_or_diag(char *n)
return s;
}
+static void
+dotypedef(DWDie *parent, char *name, DWDie *def)
+{
+ DWDie *die;
+
+ // Only emit typedefs for real names.
+ if(strncmp(name, "map[", 4) == 0)
+ return;
+ if(strncmp(name, "struct {", 8) == 0)
+ return;
+ if(strncmp(name, "chan ", 5) == 0)
+ return;
+ if(*name == '[' || *name == '*')
+ return;
+ if(def == nil)
+ diag("dwarf: bad def in dotypedef");
+
+ // The typedef entry must be created after the def,
+ // so that future lookups will find the typedef instead
+ // of the real definition. This hooks the typedef into any
+ // circular definition loops, so that gdb can understand them.
+ die = newdie(parent, DW_ABRV_TYPEDECL, name);
+ newrefattr(die, DW_AT_type, def);
+}
+
// Define gotype, for composite ones recurse into constituents.
static DWDie*
defgotype(Sym *gotype)
@@ -840,6 +923,7 @@ defgotype(Sym *gotype)
case KindArray:
die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
@@ -857,6 +941,7 @@ defgotype(Sym *gotype)
case KindFunc:
die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name);
+ dotypedef(&dwtypes, name, die);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "void"));
nfields = decodetype_funcincount(gotype);
for (i = 0; i < nfields; i++) {
@@ -876,6 +961,7 @@ defgotype(Sym *gotype)
case KindInterface:
die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_ifacemethodcount(gotype);
if (nfields == 0)
@@ -895,12 +981,14 @@ defgotype(Sym *gotype)
case KindPtr:
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
+ dotypedef(&dwtypes, name, die);
s = decodetype_ptrelem(gotype);
newrefattr(die, DW_AT_type, defgotype(s));
break;
case KindSlice:
die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
s = decodetype_arrayelem(gotype);
newrefattr(die, DW_AT_internal_elem_type, defgotype(s));
@@ -913,6 +1001,7 @@ defgotype(Sym *gotype)
case KindStruct:
die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name);
+ dotypedef(&dwtypes, name, die);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0);
nfields = decodetype_structfieldcount(gotype);
for (i = 0; i < nfields; i++) {
@@ -927,8 +1016,7 @@ defgotype(Sym *gotype)
break;
case KindUnsafePointer:
- die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name);
- newrefattr(die, DW_AT_type, find(&dwtypes, "void"));
+ die = newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, name);
break;
default:
@@ -998,7 +1086,7 @@ synthesizestringtypes(DWDie* die)
{
DWDie *prototype;
- prototype = defgotype(lookup_or_diag("type.runtime._string"));
+ prototype = walktypedef(defgotype(lookup_or_diag("type.runtime._string")));
if (prototype == nil)
return;
@@ -1014,7 +1102,7 @@ synthesizeslicetypes(DWDie *die)
{
DWDie *prototype, *elem;
- prototype = defgotype(lookup_or_diag("type.runtime.slice"));
+ prototype = walktypedef(defgotype(lookup_or_diag("type.runtime.slice")));
if (prototype == nil)
return;
@@ -1043,33 +1131,17 @@ mkinternaltypename(char *base, char *arg1, char *arg2)
}
-// synthesizemaptypes is way too closely married to runtime/hashmap.c
-enum {
- MaxValsize = 256 - 64
-};
-
static void
synthesizemaptypes(DWDie *die)
{
- DWDie *hash, *hash_subtable, *hash_entry,
- *dwh, *dwhs, *dwhe, *dwhash, *keytype, *valtype, *fld;
- int hashsize, keysize, valsize, datsize, valsize_in_hash, datavo;
- DWAttr *a;
+ DWDie *hash, *dwh, *keytype, *valtype;
hash = defgotype(lookup_or_diag("type.runtime.hmap"));
- hash_subtable = defgotype(lookup_or_diag("type.runtime.hash_subtable"));
- hash_entry = defgotype(lookup_or_diag("type.runtime.hash_entry"));
- if (hash == nil || hash_subtable == nil || hash_entry == nil)
+ if (hash == nil)
return;
- dwhash = (DWDie*)getattr(find_or_diag(hash_entry, "hash"), DW_AT_type)->data;
- if (dwhash == nil)
- return;
-
- hashsize = getattr(dwhash, DW_AT_byte_size)->value;
-
for (; die != nil; die = die->link) {
if (die->abbrev != DW_ABRV_MAPTYPE)
continue;
@@ -1077,63 +1149,12 @@ synthesizemaptypes(DWDie *die)
keytype = (DWDie*) getattr(die, DW_AT_internal_key_type)->data;
valtype = (DWDie*) getattr(die, DW_AT_internal_val_type)->data;
- a = getattr(keytype, DW_AT_byte_size);
- keysize = a ? a->value : PtrSize; // We don't store size with Pointers
-
- a = getattr(valtype, DW_AT_byte_size);
- valsize = a ? a->value : PtrSize;
-
- // This is what happens in hash_init and makemap_c
- valsize_in_hash = valsize;
- if (valsize > MaxValsize)
- valsize_in_hash = PtrSize;
- datavo = keysize;
- if (valsize_in_hash >= PtrSize)
- datavo = rnd(keysize, PtrSize);
- datsize = datavo + valsize_in_hash;
- if (datsize < PtrSize)
- datsize = PtrSize;
- datsize = rnd(datsize, PtrSize);
-
- // Construct struct hash_entry<K,V>
- dwhe = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hash_entry",
- getattr(keytype, DW_AT_name)->data,
- getattr(valtype, DW_AT_name)->data));
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "hash");
- newrefattr(fld, DW_AT_type, dwhash);
- newmemberoffsetattr(fld, 0);
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "key");
- newrefattr(fld, DW_AT_type, keytype);
- newmemberoffsetattr(fld, hashsize);
-
- fld = newdie(dwhe, DW_ABRV_STRUCTFIELD, "val");
- if (valsize > MaxValsize)
- valtype = defptrto(valtype);
- newrefattr(fld, DW_AT_type, valtype);
- newmemberoffsetattr(fld, hashsize + datavo);
- newattr(dwhe, DW_AT_byte_size, DW_CLS_CONSTANT, hashsize + datsize, nil);
-
- // Construct hash_subtable<hash_entry<K,V>>
- dwhs = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
- mkinternaltypename("hash_subtable",
- getattr(keytype, DW_AT_name)->data,
- getattr(valtype, DW_AT_name)->data));
- copychildren(dwhs, hash_subtable);
- substitutetype(dwhs, "last", defptrto(dwhe));
- substitutetype(dwhs, "entry", dwhe); // todo: []hash_entry with dynamic size
- newattr(dwhs, DW_AT_byte_size, DW_CLS_CONSTANT,
- getattr(hash_subtable, DW_AT_byte_size)->value, nil);
-
// Construct hash<K,V>
dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
mkinternaltypename("hash",
getattr(keytype, DW_AT_name)->data,
getattr(valtype, DW_AT_name)->data));
copychildren(dwh, hash);
- substitutetype(dwh, "st", defptrto(dwhs));
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
getattr(hash, DW_AT_byte_size)->value, nil);
@@ -1149,9 +1170,9 @@ synthesizechantypes(DWDie *die)
DWAttr *a;
int elemsize, sudogsize;
- sudog = defgotype(lookup_or_diag("type.runtime.sudog"));
- waitq = defgotype(lookup_or_diag("type.runtime.waitq"));
- hchan = defgotype(lookup_or_diag("type.runtime.hchan"));
+ sudog = walktypedef(defgotype(lookup_or_diag("type.runtime.sudog")));
+ waitq = walktypedef(defgotype(lookup_or_diag("type.runtime.waitq")));
+ hchan = walktypedef(defgotype(lookup_or_diag("type.runtime.hchan")));
if (sudog == nil || waitq == nil || hchan == nil)
return;
@@ -1220,7 +1241,7 @@ defdwsymb(Sym* sym, char *s, int t, vlong v, vlong size, int ver, Sym *gotype)
case 'D':
case 'B':
dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s);
- newabslocexprattr(dv, v);
+ newabslocexprattr(dv, v, sym);
if (ver == 0)
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0);
// fallthrough
@@ -1260,7 +1281,7 @@ dwarfaddfrag(int n, char *frag)
if (n >= ftabsize) {
s = ftabsize;
ftabsize = 1 + n + (n >> 2);
- ftab = realloc(ftab, ftabsize * sizeof(ftab[0]));
+ ftab = erealloc(ftab, ftabsize * sizeof(ftab[0]));
memset(ftab + s, 0, (ftabsize - s) * sizeof(ftab[0]));
}
@@ -1342,7 +1363,7 @@ addhistfile(char *zentry)
if (histfilesize == histfilecap) {
histfilecap = 2 * histfilecap + 2;
- histfile = realloc(histfile, histfilecap * sizeof(char*));
+ histfile = erealloc(histfile, histfilecap * sizeof(char*));
}
if (histfilesize == 0)
histfile[histfilesize++] = "<eof>";
@@ -1412,7 +1433,7 @@ checknesting(void)
includestacksize += 1;
includestacksize <<= 2;
// print("checknesting: growing to %d\n", includestacksize);
- includestack = realloc(includestack, includestacksize * sizeof *includestack);
+ includestack = erealloc(includestack, includestacksize * sizeof *includestack);
}
}
@@ -1581,12 +1602,12 @@ mkvarname(char* name, int da)
// flush previous compilation unit.
static void
-flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
+flushunit(DWDie *dwinfo, vlong pc, Sym *pcsym, vlong unitstart, int32 header_length)
{
vlong here;
if (dwinfo != nil && pc != 0) {
- newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, 0);
+ newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, (char*)pcsym);
}
if (unitstart >= 0) {
@@ -1597,7 +1618,7 @@ flushunit(DWDie *dwinfo, vlong pc, vlong unitstart, int32 header_length)
here = cpos();
cseek(unitstart);
LPUT(here - unitstart - sizeof(int32)); // unit_length
- WPUT(3); // dwarf version
+ WPUT(2); // dwarf version
LPUT(header_length); // header length starting here
cseek(here);
}
@@ -1607,7 +1628,7 @@ static void
writelines(void)
{
Prog *q;
- Sym *s;
+ Sym *s, *epcs;
Auto *a;
vlong unitstart, headerend, offs;
vlong pc, epc, lc, llc, lline;
@@ -1622,6 +1643,7 @@ writelines(void)
headerend = -1;
pc = 0;
epc = 0;
+ epcs = S;
lc = 1;
llc = 1;
currfile = -1;
@@ -1637,7 +1659,7 @@ writelines(void)
// we're entering a new compilation unit
if (inithist(s->autom)) {
- flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
+ flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
unitstart = cpos();
if(debug['v'] > 1) {
@@ -1651,15 +1673,15 @@ writelines(void)
lang = guesslang(histfile[1]);
finddebugruntimepath();
- dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, strdup(histfile[1]));
+ dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1]));
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0);
newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0);
- newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, 0);
+ newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, (char*)s);
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
LPUT(0); // unit_length (*), will be filled in by flushunit.
- WPUT(3); // dwarf version (appendix F)
+ WPUT(2); // dwarf version (appendix F)
LPUT(0); // header_length (*), filled in by flushunit.
// cpos == unitstart + 4 + 2 + 4
cput(1); // minimum_instruction_length
@@ -1683,6 +1705,7 @@ writelines(void)
pc = s->text->pc;
epc = pc;
+ epcs = s;
currfile = 1;
lc = 1;
llc = 1;
@@ -1701,9 +1724,9 @@ writelines(void)
}
dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s->name);
- newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, 0);
+ newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, (char*)s);
epc = s->value + s->size;
- newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, 0);
+ newattr(dwfunc, DW_AT_high_pc, DW_CLS_ADDRESS, epc, (char*)s);
if (s->version == 0)
newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0);
@@ -1785,7 +1808,7 @@ writelines(void)
dwfunc->hash = nil;
}
- flushunit(dwinfo, epc, unitstart, headerend - unitstart - 10);
+ flushunit(dwinfo, epc, epcs, unitstart, headerend - unitstart - 10);
linesize = cpos() - lineo;
}
@@ -1909,6 +1932,9 @@ writeinfo(void)
vlong unitstart, here;
fwdcount = 0;
+ if (dsym == S)
+ dsym = lookup(".dwarfinfo", 0);
+ dsym->nr = 0;
for (compunit = dwroot.child; compunit; compunit = compunit->link) {
unitstart = cpos();
@@ -1917,7 +1943,7 @@ writeinfo(void)
// Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above.
LPUT(0); // unit_length (*), will be filled in later.
- WPUT(3); // dwarf version (appendix F)
+ WPUT(2); // dwarf version (appendix F)
LPUT(0); // debug_abbrev_offset (*)
cput(PtrSize); // address_size
@@ -2057,6 +2083,27 @@ align(vlong size)
strnput("", rnd(size, PEFILEALIGN) - size);
}
+static vlong
+writeinforeloc(void)
+{
+ int i;
+ vlong start;
+ Reloc *r;
+
+ start = cpos();
+ for(r = dsym->r; r < dsym->r+dsym->nr; r++) {
+ if(iself)
+ i = elfreloc1(r, r->off);
+ else if(HEADTYPE == Hdarwin)
+ i = machoreloc1(r, r->off);
+ else
+ i = -1;
+ if(i < 0)
+ diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
+ }
+ return start;
+}
+
/*
* This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up
@@ -2085,8 +2132,7 @@ dwarfemitdebugsections(void)
// Some types that must exist to define other ones.
newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>");
newdie(&dwtypes, DW_ABRV_NULLTYPE, "void");
- newrefattr(newdie(&dwtypes, DW_ABRV_PTRTYPE, "unsafe.Pointer"),
- DW_AT_type, find(&dwtypes, "void"));
+ newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer");
die = newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr"); // needed for array size
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0);
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
@@ -2157,6 +2203,10 @@ dwarfemitdebugsections(void)
gdbscripto = writegdbscript();
gdbscriptsize = cpos() - gdbscripto;
align(gdbscriptsize);
+
+ inforeloco = writeinforeloc();
+ inforelocsize = cpos() - inforeloco;
+ align(inforelocsize);
}
/*
@@ -2298,42 +2348,44 @@ dwarfaddmachoheaders(void)
ms->fileoffset = fakestart;
ms->filesize = abbrevo-fakestart;
- msect = newMachoSect(ms, "__debug_abbrev");
+ msect = newMachoSect(ms, "__debug_abbrev", "__DWARF");
msect->off = abbrevo;
msect->size = abbrevsize;
ms->filesize += msect->size;
- msect = newMachoSect(ms, "__debug_line");
+ msect = newMachoSect(ms, "__debug_line", "__DWARF");
msect->off = lineo;
msect->size = linesize;
ms->filesize += msect->size;
- msect = newMachoSect(ms, "__debug_frame");
+ msect = newMachoSect(ms, "__debug_frame", "__DWARF");
msect->off = frameo;
msect->size = framesize;
ms->filesize += msect->size;
- msect = newMachoSect(ms, "__debug_info");
+ msect = newMachoSect(ms, "__debug_info", "__DWARF");
msect->off = infoo;
msect->size = infosize;
+ msect->reloc = inforeloco;
+ msect->nreloc = inforelocsize / 8;
ms->filesize += msect->size;
if (pubnamessize > 0) {
- msect = newMachoSect(ms, "__debug_pubnames");
+ msect = newMachoSect(ms, "__debug_pubnames", "__DWARF");
msect->off = pubnameso;
msect->size = pubnamessize;
ms->filesize += msect->size;
}
if (pubtypessize > 0) {
- msect = newMachoSect(ms, "__debug_pubtypes");
+ msect = newMachoSect(ms, "__debug_pubtypes", "__DWARF");
msect->off = pubtypeso;
msect->size = pubtypessize;
ms->filesize += msect->size;
}
if (arangessize > 0) {
- msect = newMachoSect(ms, "__debug_aranges");
+ msect = newMachoSect(ms, "__debug_aranges", "__DWARF");
msect->off = arangeso;
msect->size = arangessize;
ms->filesize += msect->size;
@@ -2341,7 +2393,7 @@ dwarfaddmachoheaders(void)
// TODO(lvd) fix gdb/python to load MachO (16 char section name limit)
if (gdbscriptsize > 0) {
- msect = newMachoSect(ms, "__debug_gdb_scripts");
+ msect = newMachoSect(ms, "__debug_gdb_scripts", "__DWARF");
msect->off = gdbscripto;
msect->size = gdbscriptsize;
ms->filesize += msect->size;
diff --git a/src/cmd/ld/dwarf_defs.h b/src/cmd/ld/dwarf_defs.h
index eed143dff..93e99ff74 100644
--- a/src/cmd/ld/dwarf_defs.h
+++ b/src/cmd/ld/dwarf_defs.h
@@ -93,6 +93,7 @@ enum
DW_CLS_FLAG,
DW_CLS_PTR, // lineptr, loclistptr, macptr, rangelistptr
DW_CLS_REFERENCE,
+ DW_CLS_ADDRLOC,
DW_CLS_STRING
};
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 630906653..f5cce9c52 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -605,9 +605,7 @@ elfdynhash(void)
if(sy->dynimpvers)
need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);
- name = sy->dynimpname;
- if(name == nil)
- name = sy->name;
+ name = sy->extname;
hc = elfhash((uchar*)name);
b = hc % nbucket;
@@ -760,9 +758,9 @@ elfshbits(Section *sect)
sh->flags |= SHF_EXECINSTR;
if(sect->rwx & 2)
sh->flags |= SHF_WRITE;
- if(!isobj)
+ if(linkmode != LinkExternal)
sh->addr = sect->vaddr;
- sh->addralign = PtrSize;
+ sh->addralign = sect->align;
sh->size = sect->len;
sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
@@ -807,10 +805,9 @@ elfshreloc(Section *sect)
void
elfrelocsect(Section *sect, Sym *first)
{
- Sym *sym, *rs;
+ Sym *sym;
int32 eaddr;
Reloc *r;
- int64 add;
// If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab.
@@ -836,28 +833,15 @@ elfrelocsect(Section *sect, Sym *first)
cursym = sym;
for(r = sym->r; r < sym->r+sym->nr; r++) {
- // Ignore relocations handled by reloc already.
- switch(r->type) {
- case D_SIZE:
+ if(r->done)
+ continue;
+ if(r->xsym == nil) {
+ diag("missing xsym in relocation");
continue;
- case D_ADDR:
- case D_PCREL:
- if(r->sym->type == SCONST)
- continue;
- break;
- }
-
- add = r->add;
- rs = r->sym;
- while(rs->outer != nil) {
- add += rs->value - rs->outer->value;
- rs = rs->outer;
}
-
- if(rs->elfsym == 0)
- diag("reloc %d to non-elf symbol %s (rs=%s) %d", r->type, r->sym->name, rs->name, rs->type);
-
- if(elfreloc1(r, sym->value - sect->vaddr + r->off, rs->elfsym, add) < 0)
+ if(r->xsym->elfsym == 0)
+ diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type);
+ if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0)
diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
}
}
@@ -915,7 +899,7 @@ doelf(void)
addstring(shstrtab, ".gosymtab");
addstring(shstrtab, ".gopclntab");
- if(isobj) {
+ if(linkmode == LinkExternal) {
debug['s'] = 0;
debug['d'] = 1;
@@ -1147,7 +1131,7 @@ asmbelf(vlong symo)
resoff = ELFRESERVE;
pph = nil;
- if(isobj) {
+ if(linkmode == LinkExternal) {
/* skip program headers */
eh->phoff = 0;
eh->phentsize = 0;
@@ -1408,7 +1392,7 @@ elfobj:
for(sect=segdata.sect; sect!=nil; sect=sect->next)
elfshbits(sect);
- if(isobj) {
+ if(linkmode == LinkExternal) {
for(sect=segtext.sect; sect!=nil; sect=sect->next)
elfshreloc(sect);
for(sect=segdata.sect; sect!=nil; sect=sect->next)
@@ -1431,8 +1415,8 @@ elfobj:
sh->size = elfstrsize;
sh->addralign = 1;
- // TODO(rsc): Enable for isobj too, once we know it works.
- if(!isobj)
+ // TODO(rsc): Enable for linkmode == LinkExternal too, once we know it works.
+ if(linkmode != LinkExternal)
dwarfaddelfheaders();
}
@@ -1456,12 +1440,12 @@ elfobj:
if(flag_shared)
eh->type = ET_DYN;
- else if(isobj)
+ else if(linkmode == LinkExternal)
eh->type = ET_REL;
else
eh->type = ET_EXEC;
- if(!isobj)
+ if(linkmode != LinkExternal)
eh->entry = entryvalue();
eh->version = EV_CURRENT;
@@ -1478,7 +1462,7 @@ elfobj:
a += elfwriteshdrs();
if(!debug['d'])
a += elfwriteinterp();
- if(!isobj) {
+ if(linkmode != LinkExternal) {
if(HEADTYPE == Hnetbsd)
a += elfwritenetbsdsig();
if(HEADTYPE == Hopenbsd)
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index 3e22125b2..336fab4b4 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -1005,7 +1005,7 @@ extern char linuxdynld[];
extern char freebsddynld[];
extern char netbsddynld[];
extern char openbsddynld[];
-int elfreloc1(Reloc*, vlong off, int32 elfsym, vlong add);
+int elfreloc1(Reloc*, vlong sectoff);
EXTERN int elfstrsize;
EXTERN char* elfstrdat;
diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c
index b2527b13e..f933cbba3 100644
--- a/src/cmd/ld/go.c
+++ b/src/cmd/ld/go.c
@@ -59,7 +59,7 @@ ilookup(char *name)
if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
return x;
x = mal(sizeof *x);
- x->name = strdup(name);
+ x->name = estrdup(name);
x->hash = ihash[h];
ihash[h] = x;
nimport++;
@@ -71,8 +71,6 @@ static void loadcgo(char*, char*, char*, int);
static int parsemethod(char**, char*, char**);
static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
-static Sym **dynexp;
-
void
ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
{
@@ -205,14 +203,14 @@ loadpkgdata(char *file, char *pkg, char *data, int len)
char *p, *ep, *prefix, *name, *def;
Import *x;
- file = strdup(file);
+ file = estrdup(file);
p = data;
ep = data + len;
while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) {
x = ilookup(name);
if(x->prefix == nil) {
x->prefix = prefix;
- x->def = strdup(def);
+ x->def = estrdup(def);
x->file = file;
} else if(strcmp(x->prefix, prefix) != 0) {
fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
@@ -244,7 +242,7 @@ expandpkg(char *t0, char *pkg)
n++;
if(n == 0)
- return strdup(t0);
+ return estrdup(t0);
// use malloc, not mal, so that caller can free
w0 = malloc(strlen(t0) + strlen(pkg)*n);
@@ -429,7 +427,7 @@ loadcgo(char *file, char *pkg, char *p, int n)
*next++ = '\0';
free(p0);
- p0 = strdup(p); // save for error message
+ p0 = estrdup(p); // save for error message
nf = tokenize(p, f, nelem(f));
if(strcmp(f[0], "cgo_import_dynamic") == 0) {
@@ -467,7 +465,7 @@ loadcgo(char *file, char *pkg, char *p, int n)
free(local);
if(s->type == 0 || s->type == SXREF) {
s->dynimplib = lib;
- s->dynimpname = remote;
+ s->extname = remote;
s->dynimpvers = q;
s->type = SDYNIMPORT;
havedynamic = 1;
@@ -478,16 +476,18 @@ loadcgo(char *file, char *pkg, char *p, int n)
if(strcmp(f[0], "cgo_import_static") == 0) {
if(nf != 2)
goto err;
- if(isobj) {
- local = f[1];
- s = lookup(local, 0);
- s->type = SHOSTOBJ;
- s->size = 0;
- }
+ local = f[1];
+ s = lookup(local, 0);
+ s->type = SHOSTOBJ;
+ s->size = 0;
continue;
}
- if(strcmp(f[0], "cgo_export") == 0) {
+ if(strcmp(f[0], "cgo_export_static") == 0 || strcmp(f[0], "cgo_export_dynamic") == 0) {
+ // TODO: Remove once we know Windows is okay.
+ if(strcmp(f[0], "cgo_export_static") == 0 && HEADTYPE == Hwindows)
+ continue;
+
if(nf < 2 || nf > 3)
goto err;
local = f[1];
@@ -497,17 +497,30 @@ loadcgo(char *file, char *pkg, char *p, int n)
remote = local;
local = expandpkg(local, pkg);
s = lookup(local, 0);
+
+ // export overrides import, for openbsd/cgo.
+ // see issue 4878.
if(s->dynimplib != nil) {
- fprint(2, "%s: symbol is both imported and exported: %s\n", argv0, local);
- nerrors++;
+ s->dynimplib = nil;
+ s->extname = nil;
+ s->dynimpvers = nil;
+ s->type = 0;
}
- s->dynimpname = remote;
- s->dynexport = 1;
-
- if(ndynexp%32 == 0)
- dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
- dynexp[ndynexp++] = s;
+ if(s->cgoexport == 0) {
+ if(strcmp(f[0], "cgo_export_static") == 0)
+ s->cgoexport |= CgoExportStatic;
+ else
+ s->cgoexport |= CgoExportDynamic;
+ s->extname = remote;
+ if(ndynexp%32 == 0)
+ dynexp = erealloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
+ dynexp[ndynexp++] = s;
+ } else if(strcmp(s->extname, remote) != 0) {
+ fprint(2, "%s: conflicting cgo_export directives: %s as %s and %s\n", argv0, s->name, s->extname, remote);
+ nerrors++;
+ return;
+ }
if(local != f[1])
free(local);
continue;
@@ -524,10 +537,19 @@ loadcgo(char *file, char *pkg, char *p, int n)
return;
}
free(interpreter);
- interpreter = strdup(f[1]);
+ interpreter = estrdup(f[1]);
}
continue;
}
+
+ if(strcmp(f[0], "cgo_ldflag") == 0) {
+ if(nf != 2)
+ goto err;
+ if(nldflag%32 == 0)
+ ldflag = erealloc(ldflag, (nldflag+32)*sizeof ldflag[0]);
+ ldflag[nldflag++] = estrdup(f[1]);
+ continue;
+ }
}
free(p0);
return;
@@ -751,6 +773,9 @@ addexport(void)
{
int i;
+ if(HEADTYPE == Hdarwin)
+ return;
+
for(i=0; i<ndynexp; i++)
adddynsym(dynexp[i]);
}
@@ -829,7 +854,7 @@ getpkg(char *path)
if(strcmp(p->path, path) == 0)
return p;
p = mal(sizeof *p);
- p->path = strdup(path);
+ p->path = estrdup(path);
p->next = phash[h];
phash[h] = p;
p->all = pkgall;
@@ -853,7 +878,7 @@ imported(char *pkg, char *import)
i->mimpby *= 2;
if(i->mimpby == 0)
i->mimpby = 16;
- i->impby = realloc(i->impby, i->mimpby*sizeof i->impby[0]);
+ i->impby = erealloc(i->impby, i->mimpby*sizeof i->impby[0]);
}
i->impby[i->nimpby++] = p;
free(pkg);
@@ -899,27 +924,17 @@ importcycles(void)
cycle(p);
}
-static int
-scmp(const void *p1, const void *p2)
-{
- Sym *s1, *s2;
-
- s1 = *(Sym**)p1;
- s2 = *(Sym**)p2;
- return strcmp(s1->dynimpname, s2->dynimpname);
-}
void
-sortdynexp(void)
+setlinkmode(char *arg)
{
- int i;
-
- // On Mac OS X Mountain Lion, we must sort exported symbols
- // So we sort them here and pre-allocate dynid for them
- // See http://golang.org/issue/4029
- if(HEADTYPE != Hdarwin)
- return;
- qsort(dynexp, ndynexp, sizeof dynexp[0], scmp);
- for(i=0; i<ndynexp; i++) {
- dynexp[i]->dynid = -i-100; // also known to [68]l/asm.c:^adddynsym
+ if(strcmp(arg, "internal") == 0)
+ linkmode = LinkInternal;
+ else if(strcmp(arg, "external") == 0)
+ linkmode = LinkExternal;
+ else if(strcmp(arg, "auto") == 0)
+ linkmode = LinkAuto;
+ else {
+ fprint(2, "unknown link mode -linkmode %s\n", arg);
+ errorexit();
}
}
diff --git a/src/cmd/ld/ldelf.c b/src/cmd/ld/ldelf.c
index 2bbf4f83e..27041bc47 100644
--- a/src/cmd/ld/ldelf.c
+++ b/src/cmd/ld/ldelf.c
@@ -595,10 +595,8 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
s->sub = sect->sym->sub;
sect->sym->sub = s;
s->type = sect->sym->type | (s->type&~SMASK) | SSUB;
- if(!s->dynexport) {
+ if(!(s->cgoexport & CgoExportDynamic))
s->dynimplib = nil; // satisfy dynimport
- s->dynimpname = nil; // satisfy dynimport
- }
s->value = sym.value;
s->size = sym.size;
s->outer = sect->sym;
diff --git a/src/cmd/ld/ldmacho.c b/src/cmd/ld/ldmacho.c
index 41852f17c..098cb7bef 100644
--- a/src/cmd/ld/ldmacho.c
+++ b/src/cmd/ld/ldmacho.c
@@ -639,10 +639,8 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
s->size = (sym+1)->value - sym->value;
else
s->size = sect->addr + sect->size - sym->value;
- if(!s->dynexport) {
+ if(!(s->cgoexport & CgoExportDynamic))
s->dynimplib = nil; // satisfy dynimport
- s->dynimpname = nil; // satisfy dynimport
- }
if(outer->type == STEXT) {
Prog *p;
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index 39c15e6a1..98923bfbf 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -135,7 +135,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
{
char *name;
int32 base;
- int i, j, l, numaux;
+ uint32 l;
+ int i, j, numaux;
PeObj *obj;
PeSect *sect, *rsect;
IMAGE_SECTION_HEADER sh;
@@ -170,11 +171,12 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
// TODO return error if found .cormeta
}
// load string table
- Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
- if(Bread(f, &l, sizeof l) != sizeof l)
+ Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0);
+ if(Bread(f, symbuf, 4) != 4)
goto bad;
+ l = le32(symbuf);
obj->snames = mal(l);
- Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
+ Bseek(f, base+obj->fh.PointerToSymbolTable+sizeof(symbuf)*obj->fh.NumberOfSymbols, 0);
if(Bread(f, obj->snames, l) != l)
goto bad;
// read symbols
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index 26fa4f2ac..18cae3175 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -44,6 +44,8 @@ int nlibdir = 0;
static int maxlibdir = 0;
static int cout = -1;
+static void hostlinksetup(void);
+
char* goroot;
char* goarch;
char* goos;
@@ -59,11 +61,7 @@ Lflag(char *arg)
maxlibdir = 8;
else
maxlibdir *= 2;
- p = realloc(libdir, maxlibdir * sizeof(*p));
- if (p == nil) {
- print("too many -L's: %d\n", nlibdir);
- usage();
- }
+ p = erealloc(libdir, maxlibdir * sizeof(*p));
libdir = p;
}
libdir[nlibdir++] = arg;
@@ -95,7 +93,7 @@ libinit(void)
#endif
cout = create(outfile, 1, 0775);
if(cout < 0) {
- diag("cannot create %s", outfile);
+ diag("cannot create %s: %r", outfile);
errorexit();
}
@@ -242,7 +240,7 @@ addlibpath(char *srcref, char *objref, char *file, char *pkg)
if(libraryp == nlibrary){
nlibrary = 50 + 2*libraryp;
- library = realloc(library, sizeof library[0] * nlibrary);
+ library = erealloc(library, sizeof library[0] * nlibrary);
}
l = &library[libraryp++];
@@ -288,7 +286,8 @@ loadinternal(char *name)
void
loadlib(void)
{
- int i;
+ int i, w, x;
+ Sym *s;
loadinternal("runtime");
if(thechar == '5')
@@ -303,6 +302,37 @@ loadlib(void)
objfile(library[i].file, library[i].pkg);
}
+ if(linkmode == LinkExternal && !iscgo)
+ linkmode = LinkInternal;
+
+ // If we got this far in automatic mode, there were no
+ // cgo uses that suggest we need external mode.
+ // Switch to internal.
+ if(linkmode == LinkAuto) {
+ linkmode = LinkInternal;
+ // Drop all the cgo_import_static declarations.
+ // Turns out we won't be needing them.
+ for(s = allsym; s != S; s = s->allsym)
+ if(s->type == SHOSTOBJ)
+ s->type = 0;
+ }
+
+ // Now that we know the link mode, trim the dynexp list.
+ x = CgoExportDynamic;
+ if(linkmode == LinkExternal)
+ x = CgoExportStatic;
+ w = 0;
+ for(i=0; i<ndynexp; i++)
+ if(dynexp[i]->cgoexport & x)
+ dynexp[w++] = dynexp[i];
+ ndynexp = w;
+
+ // In internal link mode, read the host object files.
+ if(linkmode == LinkInternal)
+ hostobjs();
+ else
+ hostlinksetup();
+
// We've loaded all the code now.
// If there are no dynamic libraries needed, gcc disables dynamic linking.
// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
@@ -316,7 +346,6 @@ loadlib(void)
debug['d'] = 1;
importcycles();
- sortdynexp();
}
/*
@@ -375,7 +404,7 @@ objfile(char *file, char *pkg)
/* load it as a regular file */
l = Bseek(f, 0L, 2);
Bseek(f, 0L, 0);
- ldobj(f, pkg, l, file, FileObj);
+ ldobj(f, pkg, l, file, file, FileObj);
Bterm(f);
free(pkg);
return;
@@ -434,7 +463,7 @@ objfile(char *file, char *pkg)
l--;
snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
l = atolwhex(arhdr.size);
- ldobj(f, pkg, l, pname, ArchiveObj);
+ ldobj(f, pkg, l, pname, file, ArchiveObj);
}
out:
@@ -442,8 +471,229 @@ out:
free(pkg);
}
+static void
+dowrite(int fd, char *p, int n)
+{
+ int m;
+
+ while(n > 0) {
+ m = write(fd, p, n);
+ if(m <= 0) {
+ cursym = S;
+ diag("write error: %r");
+ errorexit();
+ }
+ n -= m;
+ p += m;
+ }
+}
+
+typedef struct Hostobj Hostobj;
+
+struct Hostobj
+{
+ void (*ld)(Biobuf*, char*, int64, char*);
+ char *pkg;
+ char *pn;
+ char *file;
+ int64 off;
+ int64 len;
+};
+
+Hostobj *hostobj;
+int nhostobj;
+int mhostobj;
+
+// These packages can use internal linking mode.
+// Others trigger external mode.
+const char *internalpkg[] = {
+ "crypto/x509",
+ "net",
+ "os/user",
+ "runtime/cgo",
+ "runtime/race"
+};
+
+void
+ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file)
+{
+ int i, isinternal;
+ Hostobj *h;
+
+ isinternal = 0;
+ for(i=0; i<nelem(internalpkg); i++) {
+ if(strcmp(pkg, internalpkg[i]) == 0) {
+ isinternal = 1;
+ break;
+ }
+ }
+
+ if(!isinternal && linkmode == LinkAuto)
+ linkmode = LinkExternal;
+
+ if(nhostobj >= mhostobj) {
+ if(mhostobj == 0)
+ mhostobj = 16;
+ else
+ mhostobj *= 2;
+ hostobj = erealloc(hostobj, mhostobj*sizeof hostobj[0]);
+ }
+ h = &hostobj[nhostobj++];
+ h->ld = ld;
+ h->pkg = estrdup(pkg);
+ h->pn = estrdup(pn);
+ h->file = estrdup(file);
+ h->off = Boffset(f);
+ h->len = len;
+}
+
+void
+hostobjs(void)
+{
+ int i;
+ Biobuf *f;
+ Hostobj *h;
+
+ for(i=0; i<nhostobj; i++) {
+ h = &hostobj[i];
+ f = Bopen(h->file, OREAD);
+ if(f == nil) {
+ cursym = S;
+ diag("cannot reopen %s: %r", h->pn);
+ errorexit();
+ }
+ Bseek(f, h->off, 0);
+ h->ld(f, h->pkg, h->len, h->pn);
+ Bterm(f);
+ }
+}
+
+// provided by lib9
+int runcmd(char**);
+char* mktempdir(void);
+void removeall(char*);
+
+static void
+rmtemp(void)
+{
+ removeall(tmpdir);
+}
+
+static void
+hostlinksetup(void)
+{
+ char *p;
+
+ if(linkmode != LinkExternal)
+ return;
+
+ // create temporary directory and arrange cleanup
+ if(tmpdir == nil) {
+ tmpdir = mktempdir();
+ atexit(rmtemp);
+ }
+
+ // change our output to temporary object file
+ close(cout);
+ p = smprint("%s/go.o", tmpdir);
+ cout = create(p, 1, 0775);
+ if(cout < 0) {
+ diag("cannot create %s: %r", p);
+ errorexit();
+ }
+ free(p);
+}
+
void
-ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
+hostlink(void)
+{
+ char *p, **argv;
+ int i, w, n, argc, len;
+ Hostobj *h;
+ Biobuf *f;
+ static char buf[64<<10];
+
+ if(linkmode != LinkExternal || nerrors > 0)
+ return;
+
+ argv = malloc((10+nhostobj+nldflag)*sizeof argv[0]);
+ argc = 0;
+ // TODO: Add command-line flag to override gcc path and specify additional leading options.
+ // TODO: Add command-line flag to specify additional trailing options.
+ argv[argc++] = "gcc";
+ switch(thechar){
+ case '8':
+ argv[argc++] = "-m32";
+ break;
+ case '6':
+ argv[argc++] = "-m64";
+ break;
+ }
+ if(!debug['s'])
+ argv[argc++] = "-gdwarf-2";
+ if(HEADTYPE == Hdarwin)
+ argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
+ argv[argc++] = "-o";
+ argv[argc++] = outfile;
+
+ // Force global symbols to be exported for dlopen, etc.
+ // NOTE: May not work on OS X or Windows. We'll see.
+ argv[argc++] = "-rdynamic";
+
+ // already wrote main object file
+ // copy host objects to temporary directory
+ for(i=0; i<nhostobj; i++) {
+ h = &hostobj[i];
+ f = Bopen(h->file, OREAD);
+ if(f == nil) {
+ cursym = S;
+ diag("cannot reopen %s: %r", h->pn);
+ errorexit();
+ }
+ Bseek(f, h->off, 0);
+ p = smprint("%s/%06d.o", tmpdir, i);
+ argv[argc++] = p;
+ w = create(p, 1, 0775);
+ if(w < 0) {
+ diag("cannot create %s: %r", p);
+ errorexit();
+ }
+ len = h->len;
+ while(len > 0 && (n = Bread(f, buf, sizeof buf)) > 0){
+ if(n > len)
+ n = len;
+ dowrite(w, buf, n);
+ len -= n;
+ }
+ if(close(w) < 0) {
+ diag("cannot write %s: %r", p);
+ errorexit();
+ }
+ Bterm(f);
+ }
+
+ argv[argc++] = smprint("%s/go.o", tmpdir);
+ for(i=0; i<nldflag; i++)
+ argv[argc++] = ldflag[i];
+ argv[argc] = nil;
+
+ quotefmtinstall();
+ if(debug['v']) {
+ Bprint(&bso, "host link:");
+ for(i=0; i<argc; i++)
+ Bprint(&bso, " %q", argv[i]);
+ Bprint(&bso, "\n");
+ Bflush(&bso);
+ }
+
+ if(runcmd(argv) < 0) {
+ diag("%s: running %s failed: %r", argv0, argv[0]);
+ errorexit();
+ }
+}
+
+void
+ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
{
char *line;
int n, c1, c2, c3, c4;
@@ -453,7 +703,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
eof = Boffset(f) + len;
- pn = strdup(pn);
+ pn = estrdup(pn);
c1 = Bgetc(f);
c2 = Bgetc(f);
@@ -466,18 +716,15 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
magic = c1<<24 | c2<<16 | c3<<8 | c4;
if(magic == 0x7f454c46) { // \x7F E L F
- ldelf(f, pkg, len, pn);
- free(pn);
+ ldhostobj(ldelf, f, pkg, len, pn, file);
return;
}
if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
- ldmacho(f, pkg, len, pn);
- free(pn);
+ ldhostobj(ldmacho, f, pkg, len, pn, file);
return;
}
if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
- ldpe(f, pkg, len, pn);
- free(pn);
+ ldhostobj(ldpe, f, pkg, len, pn, file);
return;
}
@@ -524,7 +771,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
line[n] = '\0';
if(n-10 > strlen(t)) {
if(theline == nil)
- theline = strdup(line+10);
+ theline = estrdup(line+10);
else if(strcmp(theline, line+10) != 0) {
line[n] = '\0';
diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
@@ -615,6 +862,7 @@ _lookup(char *symb, int v, int creat)
return nil;
s = newsym(symb, v);
+ s->extname = s->name;
s->hash = hash[h];
hash[h] = s;
@@ -1027,6 +1275,7 @@ addsection(Segment *seg, char *name, int rwx)
sect->rwx = rwx;
sect->name = name;
sect->seg = seg;
+ sect->align = PtrSize; // everything is at least pointer-aligned
*l = sect;
return sect;
}
@@ -1460,23 +1709,6 @@ Yconv(Fmt *fp)
vlong coutpos;
-static void
-dowrite(int fd, char *p, int n)
-{
- int m;
-
- while(n > 0) {
- m = write(fd, p, n);
- if(m <= 0) {
- cursym = S;
- diag("write error: %r");
- errorexit();
- }
- n -= m;
- p += m;
- }
-}
-
void
cflush(void)
{
@@ -1576,7 +1808,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
put(s, s->name, 'T', s->value, s->size, s->version, 0);
for(s=allsym; s!=S; s=s->allsym) {
- if(s->hide)
+ if(s->hide || (s->name[0] == '.' && s->version == 0 && strcmp(s->name, ".rathole") != 0))
continue;
switch(s->type&SMASK) {
case SCONST:
@@ -1591,8 +1823,6 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case SSTRING:
case SGOSTRING:
case SWINDOWS:
- case SGCDATA:
- case SGCBSS:
if(!s->reachable)
continue;
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
@@ -1664,3 +1894,27 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
Bprint(&bso, "symsize = %ud\n", symsize);
Bflush(&bso);
}
+
+char*
+estrdup(char *p)
+{
+ p = strdup(p);
+ if(p == nil) {
+ cursym = S;
+ diag("out of memory");
+ errorexit();
+ }
+ return p;
+}
+
+void*
+erealloc(void *p, long n)
+{
+ p = realloc(p, n);
+ if(p == nil) {
+ cursym = S;
+ diag("out of memory");
+ errorexit();
+ }
+ return p;
+}
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index 94ad76ecc..a5ca7d3c3 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -34,30 +34,28 @@ enum
/* order here is order in output file */
STEXT,
- SMACHOPLT,
STYPE,
SSTRING,
SGOSTRING,
SRODATA,
STYPELINK,
- SGCDATA,
- SGCBSS,
SSYMTAB,
SPCLNTAB,
SELFROSECT,
+ SMACHOPLT,
SELFSECT,
+ SMACHO, /* Mach-O __nl_symbol_ptr */
+ SMACHOGOT,
SNOPTRDATA,
SDATARELRO,
SDATA,
- SMACHO, /* Mach-O __nl_symbol_ptr */
- SMACHOGOT,
SWINDOWS,
SBSS,
SNOPTRBSS,
SXREF,
- SMACHODYNSTR,
- SMACHODYNSYM,
+ SMACHOSYMSTR,
+ SMACHOSYMTAB,
SMACHOINDIRECTPLT,
SMACHOINDIRECTGOT,
SFILE,
@@ -104,6 +102,8 @@ struct Segment
struct Section
{
uchar rwx;
+ int16 extnum;
+ int32 align;
char *name;
uvlong vaddr;
uvlong len;
@@ -138,20 +138,38 @@ EXTERN char* outfile;
EXTERN int32 nsymbol;
EXTERN char* thestring;
EXTERN int ndynexp;
+EXTERN Sym** dynexp;
+EXTERN int nldflag;
+EXTERN char** ldflag;
EXTERN int havedynamic;
EXTERN int iscgo;
-EXTERN int isobj;
EXTERN int elfglobalsymndx;
EXTERN int flag_race;
EXTERN int flag_shared;
EXTERN char* tracksym;
EXTERN char* interpreter;
+EXTERN char* tmpdir;
+
+enum
+{
+ LinkAuto = 0,
+ LinkInternal,
+ LinkExternal,
+};
+EXTERN int linkmode;
+
+// for dynexport field of Sym
+enum
+{
+ CgoExportDynamic = 1<<0,
+ CgoExportStatic = 1<<1,
+};
EXTERN Segment segtext;
EXTERN Segment segdata;
-EXTERN Segment segsym;
-EXTERN Segment segdwarf;
+EXTERN Segment segdwarf;
+void setlinkmode(char*);
void addlib(char *src, char *obj);
void addlibpath(char *srcref, char *objref, char *file, char *pkg);
Section* addsection(Segment*, char*, int);
@@ -185,7 +203,7 @@ void adddynrel(Sym*, Reloc*);
void adddynrela(Sym*, Sym*, Reloc*);
Sym* lookuprel(void);
void ldobj1(Biobuf *f, char*, int64 len, char *pn);
-void ldobj(Biobuf*, char*, int64, char*, int);
+void ldobj(Biobuf*, char*, int64, char*, char*, int);
void ldelf(Biobuf*, char*, int64, char*);
void ldmacho(Biobuf*, char*, int64, char*);
void ldpe(Biobuf*, char*, int64, char*);
@@ -207,6 +225,7 @@ vlong adduint8(Sym*, uint8);
vlong adduint16(Sym*, uint16);
vlong adduint32(Sym*, uint32);
vlong adduint64(Sym*, uint64);
+vlong adduintxx(Sym*, uint64, int);
vlong addaddr(Sym*, Sym*);
vlong addaddrplus(Sym*, Sym*, int32);
vlong addpcrelplus(Sym*, Sym*, int32);
@@ -240,6 +259,10 @@ void usage(void);
void setinterp(char*);
Sym* listsort(Sym*, int(*cmp)(Sym*, Sym*), int);
int valuecmp(Sym*, Sym*);
+void hostobjs(void);
+void hostlink(void);
+char* estrdup(char*);
+void* erealloc(void*, long);
int pathchar(void);
void* mal(uint32);
@@ -359,5 +382,3 @@ char* decodetype_structfieldname(Sym*, int);
Sym* decodetype_structfieldtype(Sym*, int);
vlong decodetype_structfieldoffs(Sym*, int);
vlong decodetype_ifacemethodcount(Sym*);
-
-void sortdynexp(void);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 6781c25a4..d135a92da 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -14,9 +14,20 @@ static int macho64;
static MachoHdr hdr;
static MachoLoad *load;
static MachoSeg seg[16];
-static MachoDebug xdebug[16];
static int nload, mload, nseg, ndebug, nsect;
+enum
+{
+ SymKindLocal = 0,
+ SymKindExtdef,
+ SymKindUndef,
+ NumSymKind
+};
+
+static int nkind[NumSymKind];
+static Sym** sortsym;
+static int nsortsym;
+
// Amount of space left for adding load commands
// that refer to dynamic libraries. Because these have
// to go in the Mach-O header, we can't just pick a
@@ -25,6 +36,8 @@ static int nload, mload, nseg, ndebug, nsect;
// up about 1300 bytes; we overestimate that as 2k.
static int load_budget = INITIAL_MACHO_HEADR - 2*1024;
+static void machodysymtab(void);
+
void
machoinit(void)
{
@@ -56,11 +69,7 @@ newMachoLoad(uint32 type, uint32 ndata)
mload = 1;
else
mload *= 2;
- load = realloc(load, mload*sizeof load[0]);
- if(load == nil) {
- diag("out of memory");
- errorexit();
- }
+ load = erealloc(load, mload*sizeof load[0]);
}
if(macho64 && (ndata & 1))
@@ -90,7 +99,7 @@ newMachoSeg(char *name, int msect)
}
MachoSect*
-newMachoSect(MachoSeg *seg, char *name)
+newMachoSect(MachoSeg *seg, char *name, char *segname)
{
MachoSect *s;
@@ -100,21 +109,11 @@ newMachoSect(MachoSeg *seg, char *name)
}
s = &seg->sect[seg->nsect++];
s->name = name;
+ s->segname = segname;
nsect++;
return s;
}
-MachoDebug*
-newMachoDebug(void)
-{
- if(ndebug >= nelem(xdebug)) {
- diag("too many debugs");
- errorexit();
- }
- return &xdebug[ndebug++];
-}
-
-
// Generic linking code.
static char **dylib;
@@ -130,7 +129,6 @@ machowrite(void)
int i, j;
MachoSeg *s;
MachoSect *t;
- MachoDebug *d;
MachoLoad *l;
o1 = cpos();
@@ -152,7 +150,10 @@ machowrite(void)
LPUT(0xfeedface);
LPUT(hdr.cpu);
LPUT(hdr.subcpu);
- LPUT(2); /* file type - mach executable */
+ if(linkmode == LinkExternal)
+ LPUT(1); /* file type - mach object */
+ else
+ LPUT(2); /* file type - mach executable */
LPUT(nload+nseg+ndebug);
LPUT(loadsize);
LPUT(1); /* flags - no undefines */
@@ -190,7 +191,7 @@ machowrite(void)
t = &s->sect[j];
if(macho64) {
strnput(t->name, 16);
- strnput(s->name, 16);
+ strnput(t->segname, 16);
VPUT(t->addr);
VPUT(t->size);
LPUT(t->off);
@@ -203,7 +204,7 @@ machowrite(void)
LPUT(0); /* reserved */
} else {
strnput(t->name, 16);
- strnput(s->name, 16);
+ strnput(t->segname, 16);
LPUT(t->addr);
LPUT(t->size);
LPUT(t->off);
@@ -225,14 +226,6 @@ machowrite(void)
LPUT(l->data[j]);
}
- for(i=0; i<ndebug; i++) {
- d = &xdebug[i];
- LPUT(3); /* obsolete gdb debug info */
- LPUT(16); /* size of symseg command */
- LPUT(d->fileoffset);
- LPUT(d->filesize);
- }
-
return cpos() - o1;
}
@@ -245,31 +238,34 @@ domacho(void)
return;
// empirically, string table must begin with " \x00".
- s = lookup(".dynstr", 0);
- s->type = SMACHODYNSTR;
+ s = lookup(".machosymstr", 0);
+ s->type = SMACHOSYMSTR;
s->reachable = 1;
adduint8(s, ' ');
adduint8(s, '\0');
- s = lookup(".dynsym", 0);
- s->type = SMACHODYNSYM;
+ s = lookup(".machosymtab", 0);
+ s->type = SMACHOSYMTAB;
s->reachable = 1;
- s = lookup(".plt", 0); // will be __symbol_stub
- s->type = SMACHOPLT;
- s->reachable = 1;
+ if(linkmode != LinkExternal) {
+ s = lookup(".plt", 0); // will be __symbol_stub
+ s->type = SMACHOPLT;
+ s->reachable = 1;
- s = lookup(".got", 0); // will be __nl_symbol_ptr
- s->type = SMACHOGOT;
- s->reachable = 1;
+ s = lookup(".got", 0); // will be __nl_symbol_ptr
+ s->type = SMACHOGOT;
+ s->reachable = 1;
+ s->align = 4;
- s = lookup(".linkedit.plt", 0); // indirect table for .plt
- s->type = SMACHOINDIRECTPLT;
- s->reachable = 1;
+ s = lookup(".linkedit.plt", 0); // indirect table for .plt
+ s->type = SMACHOINDIRECTPLT;
+ s->reachable = 1;
- s = lookup(".linkedit.got", 0); // indirect table for .got
- s->type = SMACHOINDIRECTGOT;
- s->reachable = 1;
+ s = lookup(".linkedit.got", 0); // indirect table for .got
+ s->type = SMACHOINDIRECTGOT;
+ s->reachable = 1;
+ }
}
void
@@ -286,16 +282,62 @@ machoadddynlib(char *lib)
load_budget += 4096;
}
- if(ndylib%32 == 0) {
- dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
- if(dylib == nil) {
- diag("out of memory");
- errorexit();
- }
- }
+ if(ndylib%32 == 0)
+ dylib = erealloc(dylib, (ndylib+32)*sizeof dylib[0]);
dylib[ndylib++] = lib;
}
+static void
+machoshbits(MachoSeg *mseg, Section *sect, char *segname)
+{
+ MachoSect *msect;
+ char buf[40];
+ char *p;
+
+ snprint(buf, sizeof buf, "__%s", sect->name+1);
+ for(p=buf; *p; p++)
+ if(*p == '.')
+ *p = '_';
+
+ msect = newMachoSect(mseg, estrdup(buf), segname);
+ if(sect->rellen > 0) {
+ msect->reloc = sect->reloff;
+ msect->nreloc = sect->rellen / 8;
+ }
+
+ while(1<<msect->align < sect->align)
+ msect->align++;
+ msect->addr = sect->vaddr;
+ msect->size = sect->len;
+
+ if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen) {
+ // data in file
+ if(sect->len > sect->seg->vaddr + sect->seg->filelen - sect->vaddr)
+ diag("macho cannot represent section %s crossing data and bss", sect->name);
+ msect->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
+ } else {
+ // zero fill
+ msect->off = 0;
+ msect->flag |= 1;
+ }
+
+ if(sect->rwx & 1)
+ msect->flag |= 0x400; /* has instructions */
+
+ if(strcmp(sect->name, ".plt") == 0) {
+ msect->name = "__symbol_stub1";
+ msect->flag = 0x80000408; /* only instructions, code, symbol stubs */
+ msect->res1 = 0;//nkind[SymKindLocal];
+ msect->res2 = 6;
+ }
+
+ if(strcmp(sect->name, ".got") == 0) {
+ msect->name = "__nl_symbol_ptr";
+ msect->flag = 6; /* section with nonlazy symbol pointers */
+ msect->res1 = lookup(".linkedit.plt", 0)->size / 4; /* offset into indirect symbol table */
+ }
+}
+
void
asmbmacho(void)
{
@@ -303,11 +345,9 @@ asmbmacho(void)
vlong va;
int a, i;
MachoHdr *mh;
- MachoSect *msect;
MachoSeg *ms;
- MachoDebug *md;
MachoLoad *ml;
- Sym *s;
+ Section *sect;
/* apple MACH */
va = INITTEXT - HEADR;
@@ -325,179 +365,305 @@ asmbmacho(void)
mh->subcpu = MACHO_SUBCPU_X86;
break;
}
+
+ ms = nil;
+ if(linkmode == LinkExternal) {
+ /* segment for entire file */
+ ms = newMachoSeg("", 40);
+ ms->fileoffset = segtext.fileoff;
+ ms->filesize = segdata.fileoff + segdata.filelen - segtext.fileoff;
+ }
/* segment for zero page */
- ms = newMachoSeg("__PAGEZERO", 0);
- ms->vsize = va;
+ if(linkmode != LinkExternal) {
+ ms = newMachoSeg("__PAGEZERO", 0);
+ ms->vsize = va;
+ }
/* text */
v = rnd(HEADR+segtext.len, INITRND);
- ms = newMachoSeg("__TEXT", 2);
- ms->vaddr = va;
- ms->vsize = v;
- ms->filesize = v;
- ms->prot1 = 7;
- ms->prot2 = 5;
-
- msect = newMachoSect(ms, "__text");
- msect->addr = INITTEXT;
- msect->size = segtext.sect->len;
- msect->off = INITTEXT - va;
- msect->flag = 0x400; /* flag - some instructions */
-
- s = lookup(".plt", 0);
- if(s->size > 0) {
- msect = newMachoSect(ms, "__symbol_stub1");
- msect->addr = symaddr(s);
- msect->size = s->size;
- msect->off = ms->fileoffset + msect->addr - ms->vaddr;
- msect->flag = 0x80000408; /* flag */
- msect->res1 = 0; /* index into indirect symbol table */
- msect->res2 = 6; /* size of stubs */
+ if(linkmode != LinkExternal) {
+ ms = newMachoSeg("__TEXT", 20);
+ ms->vaddr = va;
+ ms->vsize = v;
+ ms->fileoffset = 0;
+ ms->filesize = v;
+ ms->prot1 = 7;
+ ms->prot2 = 5;
}
+ for(sect=segtext.sect; sect!=nil; sect=sect->next)
+ machoshbits(ms, sect, "__TEXT");
+
/* data */
- w = segdata.len;
- ms = newMachoSeg("__DATA", 3);
- ms->vaddr = va+v;
- ms->vsize = w;
- ms->fileoffset = v;
- ms->filesize = segdata.filelen;
- ms->prot1 = 7;
- ms->prot2 = 3;
-
- msect = newMachoSect(ms, "__data");
- msect->addr = va+v;
- msect->off = v;
- msect->size = segdata.filelen;
-
- s = lookup(".got", 0);
- if(s->size > 0) {
- msect->size = symaddr(s) - msect->addr;
-
- msect = newMachoSect(ms, "__nl_symbol_ptr");
- msect->addr = symaddr(s);
- msect->size = s->size;
- msect->off = datoff(msect->addr);
- msect->align = 2;
- msect->flag = 6; /* section with nonlazy symbol pointers */
- msect->res1 = lookup(".linkedit.plt", 0)->size / 4; /* offset into indirect symbol table */
+ if(linkmode != LinkExternal) {
+ w = segdata.len;
+ ms = newMachoSeg("__DATA", 20);
+ ms->vaddr = va+v;
+ ms->vsize = w;
+ ms->fileoffset = v;
+ ms->filesize = segdata.filelen;
+ ms->prot1 = 3;
+ ms->prot2 = 3;
}
- msect = newMachoSect(ms, "__bss");
- msect->addr = va+v+segdata.filelen;
- msect->size = segdata.len - segdata.filelen;
- msect->flag = 1; /* flag - zero fill */
+ for(sect=segdata.sect; sect!=nil; sect=sect->next)
+ machoshbits(ms, sect, "__DATA");
- switch(thechar) {
- default:
- diag("unknown macho architecture");
- errorexit();
- case '6':
- ml = newMachoLoad(5, 42+2); /* unix thread */
- ml->data[0] = 4; /* thread type */
- ml->data[1] = 42; /* word count */
- ml->data[2+32] = entryvalue(); /* start pc */
- ml->data[2+32+1] = entryvalue()>>16>>16; // hide >>32 for 8l
- break;
- case '8':
- ml = newMachoLoad(5, 16+2); /* unix thread */
- ml->data[0] = 1; /* thread type */
- ml->data[1] = 16; /* word count */
- ml->data[2+10] = entryvalue(); /* start pc */
- break;
+ if(linkmode != LinkExternal) {
+ switch(thechar) {
+ default:
+ diag("unknown macho architecture");
+ errorexit();
+ case '6':
+ ml = newMachoLoad(5, 42+2); /* unix thread */
+ ml->data[0] = 4; /* thread type */
+ ml->data[1] = 42; /* word count */
+ ml->data[2+32] = entryvalue(); /* start pc */
+ ml->data[2+32+1] = entryvalue()>>16>>16; // hide >>32 for 8l
+ break;
+ case '8':
+ ml = newMachoLoad(5, 16+2); /* unix thread */
+ ml->data[0] = 1; /* thread type */
+ ml->data[1] = 16; /* word count */
+ ml->data[2+10] = entryvalue(); /* start pc */
+ break;
+ }
}
-
+
if(!debug['d']) {
Sym *s1, *s2, *s3, *s4;
// must match domacholink below
- s1 = lookup(".dynsym", 0);
+ s1 = lookup(".machosymtab", 0);
s2 = lookup(".linkedit.plt", 0);
s3 = lookup(".linkedit.got", 0);
- s4 = lookup(".dynstr", 0);
-
- ms = newMachoSeg("__LINKEDIT", 0);
- ms->vaddr = va+v+rnd(segdata.len, INITRND);
- ms->vsize = s1->size + s2->size + s3->size + s4->size;
- ms->fileoffset = linkoff;
- ms->filesize = ms->vsize;
- ms->prot1 = 7;
- ms->prot2 = 3;
+ s4 = lookup(".machosymstr", 0);
+
+ if(linkmode != LinkExternal) {
+ ms = newMachoSeg("__LINKEDIT", 0);
+ ms->vaddr = va+v+rnd(segdata.len, INITRND);
+ ms->vsize = s1->size + s2->size + s3->size + s4->size;
+ ms->fileoffset = linkoff;
+ ms->filesize = ms->vsize;
+ ms->prot1 = 7;
+ ms->prot2 = 3;
+ }
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
ml->data[0] = linkoff; /* symoff */
- ml->data[1] = s1->size / (macho64 ? 16 : 12); /* nsyms */
+ ml->data[1] = nsortsym; /* nsyms */
ml->data[2] = linkoff + s1->size + s2->size + s3->size; /* stroff */
ml->data[3] = s4->size; /* strsize */
- ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
- ml->data[0] = 0; /* ilocalsym */
- ml->data[1] = 0; /* nlocalsym */
- ml->data[2] = 0; /* iextdefsym */
- ml->data[3] = ndynexp; /* nextdefsym */
- ml->data[4] = ndynexp; /* iundefsym */
- ml->data[5] = (s1->size / (macho64 ? 16 : 12)) - ndynexp; /* nundefsym */
- ml->data[6] = 0; /* tocoffset */
- ml->data[7] = 0; /* ntoc */
- ml->data[8] = 0; /* modtaboff */
- ml->data[9] = 0; /* nmodtab */
- ml->data[10] = 0; /* extrefsymoff */
- ml->data[11] = 0; /* nextrefsyms */
- ml->data[12] = linkoff + s1->size; /* indirectsymoff */
- ml->data[13] = (s2->size + s3->size) / 4; /* nindirectsyms */
- ml->data[14] = 0; /* extreloff */
- ml->data[15] = 0; /* nextrel */
- ml->data[16] = 0; /* locreloff */
- ml->data[17] = 0; /* nlocrel */
-
- ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
- ml->data[0] = 12; /* offset to string */
- strcpy((char*)&ml->data[1], "/usr/lib/dyld");
-
- for(i=0; i<ndylib; i++) {
- ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
- ml->data[0] = 24; /* offset of string from beginning of load */
- ml->data[1] = 0; /* time stamp */
- ml->data[2] = 0; /* version */
- ml->data[3] = 0; /* compatibility version */
- strcpy((char*)&ml->data[4], dylib[i]);
+ machodysymtab();
+
+ if(linkmode != LinkExternal) {
+ ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
+ ml->data[0] = 12; /* offset to string */
+ strcpy((char*)&ml->data[1], "/usr/lib/dyld");
+
+ for(i=0; i<ndylib; i++) {
+ ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
+ ml->data[0] = 24; /* offset of string from beginning of load */
+ ml->data[1] = 0; /* time stamp */
+ ml->data[2] = 0; /* version */
+ ml->data[3] = 0; /* compatibility version */
+ strcpy((char*)&ml->data[4], dylib[i]);
+ }
}
}
- if(!debug['s']) {
- Sym *s;
-
- md = newMachoDebug();
- s = lookup("symtab", 0);
- md->fileoffset = datoff(s->value);
- md->filesize = s->size;
-
- md = newMachoDebug();
- s = lookup("pclntab", 0);
- md->fileoffset = datoff(s->value);
- md->filesize = s->size;
-
+ // TODO: dwarf headers go in ms too
+ if(!debug['s'] && linkmode != LinkExternal)
dwarfaddmachoheaders();
- }
a = machowrite();
if(a > HEADR)
diag("HEADR too small: %d > %d", a, HEADR);
}
+static int
+symkind(Sym *s)
+{
+ if(s->type == SDYNIMPORT)
+ return SymKindUndef;
+ if(s->cgoexport)
+ return SymKindExtdef;
+ return SymKindLocal;
+}
+
+static void
+addsym(Sym *s, char *name, int type, vlong addr, vlong size, int ver, Sym *gotype)
+{
+ USED(name);
+ USED(addr);
+ USED(size);
+ USED(ver);
+ USED(gotype);
+
+ if(s == nil)
+ return;
+
+ switch(type) {
+ default:
+ return;
+ case 'D':
+ case 'B':
+ case 'T':
+ break;
+ }
+
+ if(sortsym) {
+ sortsym[nsortsym] = s;
+ nkind[symkind(s)]++;
+ }
+ nsortsym++;
+}
+
+static int
+scmp(const void *p1, const void *p2)
+{
+ Sym *s1, *s2;
+ int k1, k2;
+
+ s1 = *(Sym**)p1;
+ s2 = *(Sym**)p2;
+
+ k1 = symkind(s1);
+ k2 = symkind(s2);
+ if(k1 != k2)
+ return k1 - k2;
+
+ return strcmp(s1->extname, s2->extname);
+}
+
+static void
+machogenasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
+{
+ Sym *s;
+
+ genasmsym(put);
+ for(s=allsym; s; s=s->allsym)
+ if(s->type == SDYNIMPORT || s->type == SHOSTOBJ)
+ if(s->reachable)
+ put(s, nil, 'D', 0, 0, 0, nil);
+}
+
+void
+machosymorder(void)
+{
+ int i;
+
+ // On Mac OS X Mountain Lion, we must sort exported symbols
+ // So we sort them here and pre-allocate dynid for them
+ // See http://golang.org/issue/4029
+ for(i=0; i<ndynexp; i++)
+ dynexp[i]->reachable = 1;
+ machogenasmsym(addsym);
+ sortsym = mal(nsortsym * sizeof sortsym[0]);
+ nsortsym = 0;
+ machogenasmsym(addsym);
+ qsort(sortsym, nsortsym, sizeof sortsym[0], scmp);
+ for(i=0; i<nsortsym; i++)
+ sortsym[i]->dynid = i;
+}
+
+static void
+machosymtab(void)
+{
+ int i;
+ Sym *symtab, *symstr, *s, *o;
+
+ symtab = lookup(".machosymtab", 0);
+ symstr = lookup(".machosymstr", 0);
+
+ for(i=0; i<nsortsym; i++) {
+ s = sortsym[i];
+ adduint32(symtab, symstr->size);
+
+ // Only add _ to C symbols. Go symbols have dot in the name.
+ if(strstr(s->extname, ".") == nil)
+ adduint8(symstr, '_');
+ addstring(symstr, s->extname);
+ if(s->type == SDYNIMPORT || s->type == SHOSTOBJ) {
+ adduint8(symtab, 0x01); // type N_EXT, external symbol
+ adduint8(symtab, 0); // no section
+ adduint16(symtab, 0); // desc
+ adduintxx(symtab, 0, PtrSize); // no value
+ } else {
+ if(s->cgoexport)
+ adduint8(symtab, 0x0f);
+ else
+ adduint8(symtab, 0x0e);
+ o = s;
+ while(o->outer != nil)
+ o = o->outer;
+ if(o->sect == nil) {
+ diag("missing section for %s", s->name);
+ adduint8(symtab, 0);
+ } else
+ adduint8(symtab, o->sect->extnum);
+ adduint16(symtab, 0); // desc
+ adduintxx(symtab, symaddr(s), PtrSize);
+ }
+ }
+}
+
+static void
+machodysymtab(void)
+{
+ int n;
+ MachoLoad *ml;
+ Sym *s1, *s2, *s3;
+
+ ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
+
+ n = 0;
+ ml->data[0] = n; /* ilocalsym */
+ ml->data[1] = nkind[SymKindLocal]; /* nlocalsym */
+ n += nkind[SymKindLocal];
+
+ ml->data[2] = n; /* iextdefsym */
+ ml->data[3] = nkind[SymKindExtdef]; /* nextdefsym */
+ n += nkind[SymKindExtdef];
+
+ ml->data[4] = n; /* iundefsym */
+ ml->data[5] = nkind[SymKindUndef]; /* nundefsym */
+
+ ml->data[6] = 0; /* tocoffset */
+ ml->data[7] = 0; /* ntoc */
+ ml->data[8] = 0; /* modtaboff */
+ ml->data[9] = 0; /* nmodtab */
+ ml->data[10] = 0; /* extrefsymoff */
+ ml->data[11] = 0; /* nextrefsyms */
+
+ // must match domacholink below
+ s1 = lookup(".machosymtab", 0);
+ s2 = lookup(".linkedit.plt", 0);
+ s3 = lookup(".linkedit.got", 0);
+ ml->data[12] = linkoff + s1->size; /* indirectsymoff */
+ ml->data[13] = (s2->size + s3->size) / 4; /* nindirectsyms */
+
+ ml->data[14] = 0; /* extreloff */
+ ml->data[15] = 0; /* nextrel */
+ ml->data[16] = 0; /* locreloff */
+ ml->data[17] = 0; /* nlocrel */
+}
+
vlong
domacholink(void)
{
int size;
Sym *s1, *s2, *s3, *s4;
+ machosymtab();
+
// write data that will be linkedit section
- s1 = lookup(".dynsym", 0);
- relocsym(s1);
+ s1 = lookup(".machosymtab", 0);
s2 = lookup(".linkedit.plt", 0);
s3 = lookup(".linkedit.got", 0);
- s4 = lookup(".dynstr", 0);
+ s4 = lookup(".machosymstr", 0);
// Force the linkedit section to end on a 16-byte
// boundary. This allows pure (non-cgo) Go binaries
@@ -533,3 +699,57 @@ domacholink(void)
return rnd(size, INITRND);
}
+
+
+void
+machorelocsect(Section *sect, Sym *first)
+{
+ Sym *sym;
+ int32 eaddr;
+ Reloc *r;
+
+ // If main section has no bits, nothing to relocate.
+ if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
+ return;
+
+ sect->reloff = cpos();
+ for(sym = first; sym != nil; sym = sym->next) {
+ if(!sym->reachable)
+ continue;
+ if(sym->value >= sect->vaddr)
+ break;
+ }
+
+ eaddr = sect->vaddr + sect->len;
+ for(; sym != nil; sym = sym->next) {
+ if(!sym->reachable)
+ continue;
+ if(sym->value >= eaddr)
+ break;
+ cursym = sym;
+
+ for(r = sym->r; r < sym->r+sym->nr; r++) {
+ if(r->done)
+ continue;
+ if(machoreloc1(r, sym->value+r->off - sect->vaddr) < 0)
+ diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
+ }
+ }
+
+ sect->rellen = cpos() - sect->reloff;
+}
+
+void
+machoemitreloc(void)
+{
+ Section *sect;
+
+ while(cpos()&7)
+ cput(0);
+
+ machorelocsect(segtext.sect, textp);
+ for(sect=segtext.sect->next; sect!=nil; sect=sect->next)
+ machorelocsect(sect, datap);
+ for(sect=segdata.sect; sect!=nil; sect=sect->next)
+ machorelocsect(sect, datap);
+}
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
index baea6ff03..d759f4b0f 100644
--- a/src/cmd/ld/macho.h
+++ b/src/cmd/ld/macho.h
@@ -11,6 +11,7 @@ struct MachoHdr {
typedef struct MachoSect MachoSect;
struct MachoSect {
char* name;
+ char* segname;
uint64 addr;
uint64 size;
uint32 off;
@@ -44,19 +45,15 @@ struct MachoLoad {
uint32 *data;
};
-typedef struct MachoDebug MachoDebug;
-struct MachoDebug {
- uint32 fileoffset;
- uint32 filesize;
-};
-
MachoHdr* getMachoHdr(void);
MachoSeg* newMachoSeg(char*, int);
-MachoSect* newMachoSect(MachoSeg*, char*);
+MachoSect* newMachoSect(MachoSeg*, char*, char*);
MachoLoad* newMachoLoad(uint32, uint32);
-MachoDebug* newMachoDebug(void);
int machowrite(void);
void machoinit(void);
+void machosymorder(void);
+void machoemitreloc(void);
+int machoreloc1(Reloc*, vlong);
/*
* Total amount of space to reserve at the start of the file
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index f2903ba0f..090d083f5 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -195,7 +195,7 @@ initdynimport(void)
dr = nil;
m = nil;
for(s = allsym; s != S; s = s->allsym) {
- if(!s->reachable || !s->dynimpname || s->dynexport)
+ if(!s->reachable || s->type != SDYNIMPORT)
continue;
for(d = dr; d != nil; d = d->next) {
if(strcmp(d->name,s->dynimplib) == 0) {
@@ -262,7 +262,7 @@ addimports(IMAGE_SECTION_HEADER *datsect)
for(m = d->ms; m != nil; m = m->next) {
m->off = nextsectoff + cpos() - startoff;
wputl(0); // hint
- strput(m->s->dynimpname);
+ strput(m->s->extname);
}
}
@@ -325,7 +325,7 @@ scmp(const void *p1, const void *p2)
s1 = *(Sym**)p1;
s2 = *(Sym**)p2;
- return strcmp(s1->dynimpname, s2->dynimpname);
+ return strcmp(s1->extname, s2->extname);
}
static void
@@ -335,7 +335,7 @@ initdynexport(void)
nexport = 0;
for(s = allsym; s != S; s = s->allsym) {
- if(!s->reachable || !s->dynimpname || !s->dynexport)
+ if(!s->reachable || !(s->cgoexport & CgoExportDynamic))
continue;
if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) {
diag("pe dynexport table is full");
@@ -358,7 +358,7 @@ addexports(void)
size = sizeof e + 10*nexport + strlen(outfile) + 1;
for(i=0; i<nexport; i++)
- size += strlen(dexport[i]->dynimpname) + 1;
+ size += strlen(dexport[i]->extname) + 1;
if (nexport == 0)
return;
@@ -394,7 +394,7 @@ addexports(void)
v = e.Name + strlen(outfile)+1;
for(i=0; i<nexport; i++) {
lputl(v);
- v += strlen(dexport[i]->dynimpname)+1;
+ v += strlen(dexport[i]->extname)+1;
}
// put EXPORT Ordinal Table
for(i=0; i<nexport; i++)
@@ -402,7 +402,7 @@ addexports(void)
// put Names
strnput(outfile, strlen(outfile)+1);
for(i=0; i<nexport; i++)
- strnput(dexport[i]->dynimpname, strlen(dexport[i]->dynimpname)+1);
+ strnput(dexport[i]->extname, strlen(dexport[i]->extname)+1);
strnput("", sect->SizeOfRawData - size);
}
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 89a594872..698194f84 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -121,12 +121,22 @@ putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
// One pass for each binding: STB_LOCAL, STB_GLOBAL,
// maybe one day STB_WEAK.
- bind = (ver || (x->type & SHIDDEN)) ? STB_LOCAL : STB_GLOBAL;
+ bind = STB_GLOBAL;
+ if(ver || (x->type & SHIDDEN))
+ bind = STB_LOCAL;
+
+ // In external linking mode, we have to invoke gcc with -rdynamic
+ // to get the exported symbols put into the dynamic symbol table.
+ // To avoid filling the dynamic table with lots of unnecessary symbols,
+ // mark all Go symbols local (not global) in the final executable.
+ if(linkmode == LinkExternal && !(x->cgoexport&CgoExportStatic))
+ bind = STB_LOCAL;
+
if(bind != elfbind)
return;
off = putelfstr(s);
- if(isobj)
+ if(linkmode == LinkExternal)
addr -= xo->sect->vaddr;
putelfsyment(off, addr, size, (bind<<4)|(type&0xf), xo->sect->elfsect->shnum, (x->type & SHIDDEN) ? 2 : 0);
x->elfsym = numelfsym++;
@@ -424,10 +434,8 @@ symtab(void)
xdefine("datarelro", SDATARELRO, 0);
xdefine("edatarelro", SDATARELRO, 0);
}
- xdefine("gcdata", SGCDATA, 0);
- xdefine("egcdata", SGCDATA, 0);
- xdefine("gcbss", SGCBSS, 0);
- xdefine("egcbss", SGCBSS, 0);
+ xdefine("egcdata", STYPE, 0);
+ xdefine("egcbss", STYPE, 0);
xdefine("noptrdata", SNOPTRDATA, 0);
xdefine("enoptrdata", SNOPTRDATA, 0);
xdefine("data", SDATA, 0);
diff --git a/src/cmd/vet/Makefile b/src/cmd/vet/Makefile
index 307f4729c..45bd29170 100644
--- a/src/cmd/vet/Makefile
+++ b/src/cmd/vet/Makefile
@@ -2,7 +2,11 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
+# Assumes go/types is installed
test testshort:
- go build -tags vet_test
- ../../../test/errchk ./vet -compositewhitelist=false -printfuncs='Warn:1,Warnf:1' *.go
+ go build -tags 'vet_test gotypes'
+ ../../../test/errchk ./vet -printfuncs='Warn:1,Warnf:1' *.go *.s
+test_notypes:
+ go build -tags 'vet_test'
+ ../../../test/errchk ./vet -printfuncs='Warn:1,Warnf:1' *.go *.s
diff --git a/src/cmd/vet/asmdecl.go b/src/cmd/vet/asmdecl.go
new file mode 100644
index 000000000..2cfaa938f
--- /dev/null
+++ b/src/cmd/vet/asmdecl.go
@@ -0,0 +1,532 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Identify mismatches between assembly files and Go func declarations.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/token"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+// 'kind' is a kind of assembly variable.
+// The kinds 1, 2, 4, 8 stand for values of that size.
+type asmKind int
+
+// These special kinds are not valid sizes.
+const (
+ asmString asmKind = 100 + iota
+ asmSlice
+ asmInterface
+ asmEmptyInterface
+)
+
+// An asmArch describes assembly parameters for an architecture
+type asmArch struct {
+ name string
+ ptrSize int
+ intSize int
+ bigEndian bool
+}
+
+// An asmFunc describes the expected variables for a function on a given architecture.
+type asmFunc struct {
+ arch *asmArch
+ size int // size of all arguments
+ vars map[string]*asmVar
+ varByOffset map[int]*asmVar
+}
+
+// An asmVar describes a single assembly variable.
+type asmVar struct {
+ name string
+ kind asmKind
+ typ string
+ off int
+ size int
+ inner []*asmVar
+}
+
+var (
+ asmArch386 = asmArch{"386", 4, 4, false}
+ asmArchArm = asmArch{"arm", 4, 4, false}
+ asmArchAmd64 = asmArch{"amd64", 8, 8, false}
+
+ arches = []*asmArch{
+ &asmArch386,
+ &asmArchArm,
+ &asmArchAmd64,
+ }
+)
+
+var (
+ re = regexp.MustCompile
+ asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
+ asmTEXT = re(`\bTEXT\b.*·([^\(]+)\(SB\)(?:\s*,\s*([0-9]+))?(?:\s*,\s*\$([0-9]+)(?:-([0-9]+))?)?`)
+ asmDATA = re(`\b(DATA|GLOBL)\b`)
+ asmNamedFP = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
+ asmUnnamedFP = re(`[^+\-0-9]](([0-9]+)\(FP\))`)
+ asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
+)
+
+func asmCheck(pkg *Package) {
+ if !vet("asmdecl") {
+ return
+ }
+
+ // No work if no assembly files.
+ if !pkg.hasFileWithSuffix(".s") {
+ return
+ }
+
+ // Gather declarations. knownFunc[name][arch] is func description.
+ knownFunc := make(map[string]map[string]*asmFunc)
+
+ for _, f := range pkg.files {
+ if f.file != nil {
+ for _, decl := range f.file.Decls {
+ if decl, ok := decl.(*ast.FuncDecl); ok && decl.Body == nil {
+ knownFunc[decl.Name.Name] = f.asmParseDecl(decl)
+ }
+ }
+ }
+ }
+
+ var fn *asmFunc
+ for _, f := range pkg.files {
+ if !strings.HasSuffix(f.name, ".s") {
+ continue
+ }
+
+ // Determine architecture from file name if possible.
+ var arch string
+ for _, a := range arches {
+ if strings.HasSuffix(f.name, "_"+a.name+".s") {
+ arch = a.name
+ break
+ }
+ }
+
+ lines := strings.SplitAfter(string(f.content), "\n")
+ for lineno, line := range lines {
+ lineno++
+
+ warnf := func(format string, args ...interface{}) {
+ f.Warnf(token.NoPos, "%s:%d: [%s] %s", f.name, lineno, arch, fmt.Sprintf(format, args...))
+ }
+
+ if arch == "" {
+ // Determine architecture from +build line if possible.
+ if m := asmPlusBuild.FindStringSubmatch(line); m != nil {
+ Fields:
+ for _, fld := range strings.Fields(m[1]) {
+ for _, a := range arches {
+ if a.name == fld {
+ arch = a.name
+ break Fields
+ }
+ }
+ }
+ }
+ }
+
+ if m := asmTEXT.FindStringSubmatch(line); m != nil {
+ if arch == "" {
+ f.Warnf(token.NoPos, "%s: cannot determine architecture for assembly file", f.name)
+ return
+ }
+ fn = knownFunc[m[1]][arch]
+ if fn != nil {
+ size, _ := strconv.Atoi(m[4])
+ if size != fn.size && (m[2] != "7" || size != 0) {
+ warnf("wrong argument size %d; expected $...-%d", size, fn.size)
+ }
+ }
+ continue
+ } else if strings.Contains(line, "TEXT") && strings.Contains(line, "SB") {
+ // function, but not visible from Go (didn't match asmTEXT), so stop checking
+ fn = nil
+ continue
+ }
+
+ if asmDATA.FindStringSubmatch(line) != nil {
+ fn = nil
+ }
+ if fn == nil {
+ continue
+ }
+
+ for _, m := range asmUnnamedFP.FindAllStringSubmatch(line, -1) {
+ warnf("use of unnamed argument %s", m[1])
+ }
+
+ for _, m := range asmNamedFP.FindAllStringSubmatch(line, -1) {
+ name := m[1]
+ off := 0
+ if m[2] != "" {
+ off, _ = strconv.Atoi(m[2])
+ }
+ v := fn.vars[name]
+ if v == nil {
+ // Allow argframe+0(FP).
+ if name == "argframe" && off == 0 {
+ continue
+ }
+ v = fn.varByOffset[off]
+ if v != nil {
+ warnf("unknown variable %s; offset %d is %s+%d(FP)", name, off, v.name, v.off)
+ } else {
+ warnf("unknown variable %s", name)
+ }
+ continue
+ }
+ asmCheckVar(warnf, fn, line, m[0], off, v)
+ }
+ }
+ }
+}
+
+// asmParseDecl parses a function decl for expected assembly variables.
+func (f *File) asmParseDecl(decl *ast.FuncDecl) map[string]*asmFunc {
+ var (
+ arch *asmArch
+ fn *asmFunc
+ offset int
+ failed bool
+ )
+
+ addVar := func(outer string, v asmVar) {
+ if vo := fn.vars[outer]; vo != nil {
+ vo.inner = append(vo.inner, &v)
+ }
+ fn.vars[v.name] = &v
+ for i := 0; i < v.size; i++ {
+ fn.varByOffset[v.off+i] = &v
+ }
+ }
+
+ addParams := func(list []*ast.Field) {
+ for i, fld := range list {
+ // Determine alignment, size, and kind of type in declaration.
+ var align, size int
+ var kind asmKind
+ names := fld.Names
+ typ := f.gofmt(fld.Type)
+ switch t := fld.Type.(type) {
+ default:
+ switch typ {
+ default:
+ f.Warnf(fld.Type.Pos(), "unknown assembly argument type %s", typ)
+ failed = true
+ return
+ case "int8", "uint8", "byte", "bool":
+ size = 1
+ case "int16", "uint16":
+ size = 2
+ case "int32", "uint32", "float32":
+ size = 4
+ case "int64", "uint64", "float64":
+ align = arch.ptrSize
+ size = 8
+ case "int", "uint":
+ size = arch.intSize
+ case "uintptr", "iword", "Word", "Errno", "unsafe.Pointer":
+ size = arch.ptrSize
+ case "string":
+ size = arch.ptrSize * 2
+ align = arch.ptrSize
+ kind = asmString
+ }
+ case *ast.ChanType, *ast.FuncType, *ast.MapType, *ast.StarExpr:
+ size = arch.ptrSize
+ case *ast.InterfaceType:
+ align = arch.ptrSize
+ size = 2 * arch.ptrSize
+ if len(t.Methods.List) > 0 {
+ kind = asmInterface
+ } else {
+ kind = asmEmptyInterface
+ }
+ case *ast.ArrayType:
+ if t.Len == nil {
+ size = arch.ptrSize + 2*arch.intSize
+ align = arch.ptrSize
+ kind = asmSlice
+ break
+ }
+ f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+ failed = true
+ case *ast.StructType:
+ f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
+ failed = true
+ }
+ if align == 0 {
+ align = size
+ }
+ if kind == 0 {
+ kind = asmKind(size)
+ }
+ offset += -offset & (align - 1)
+
+ // Create variable for each name being declared with this type.
+ if len(names) == 0 {
+ name := "unnamed"
+ if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 && &list[0] == &decl.Type.Results.List[0] && i == 0 {
+ // Assume assembly will refer to single unnamed result as r.
+ name = "ret"
+ }
+ names = []*ast.Ident{{Name: name}}
+ }
+ for _, id := range names {
+ name := id.Name
+ addVar("", asmVar{
+ name: name,
+ kind: kind,
+ typ: typ,
+ off: offset,
+ size: size,
+ })
+ switch kind {
+ case 8:
+ if arch.ptrSize == 4 {
+ w1, w2 := "lo", "hi"
+ if arch.bigEndian {
+ w1, w2 = w2, w1
+ }
+ addVar(name, asmVar{
+ name: name + "_" + w1,
+ kind: 4,
+ typ: "half " + typ,
+ off: offset,
+ size: 4,
+ })
+ addVar(name, asmVar{
+ name: name + "_" + w2,
+ kind: 4,
+ typ: "half " + typ,
+ off: offset + 4,
+ size: 4,
+ })
+ }
+
+ case asmEmptyInterface:
+ addVar(name, asmVar{
+ name: name + "_type",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface type",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_data",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface data",
+ off: offset + arch.ptrSize,
+ size: arch.ptrSize,
+ })
+
+ case asmInterface:
+ addVar(name, asmVar{
+ name: name + "_itable",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface itable",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_data",
+ kind: asmKind(arch.ptrSize),
+ typ: "interface data",
+ off: offset + arch.ptrSize,
+ size: arch.ptrSize,
+ })
+
+ case asmSlice:
+ addVar(name, asmVar{
+ name: name + "_base",
+ kind: asmKind(arch.ptrSize),
+ typ: "slice base",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_len",
+ kind: asmKind(arch.intSize),
+ typ: "slice len",
+ off: offset + arch.ptrSize,
+ size: arch.intSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_cap",
+ kind: asmKind(arch.intSize),
+ typ: "slice cap",
+ off: offset + arch.ptrSize + arch.intSize,
+ size: arch.intSize,
+ })
+
+ case asmString:
+ addVar(name, asmVar{
+ name: name + "_base",
+ kind: asmKind(arch.ptrSize),
+ typ: "string base",
+ off: offset,
+ size: arch.ptrSize,
+ })
+ addVar(name, asmVar{
+ name: name + "_len",
+ kind: asmKind(arch.intSize),
+ typ: "string len",
+ off: offset + arch.ptrSize,
+ size: arch.intSize,
+ })
+ }
+ offset += size
+ }
+ }
+ }
+
+ m := make(map[string]*asmFunc)
+ for _, arch = range arches {
+ fn = &asmFunc{
+ arch: arch,
+ vars: make(map[string]*asmVar),
+ varByOffset: make(map[int]*asmVar),
+ }
+ offset = 0
+ addParams(decl.Type.Params.List)
+ if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {
+ offset += -offset & (arch.ptrSize - 1)
+ addParams(decl.Type.Results.List)
+ }
+ fn.size = offset
+ m[arch.name] = fn
+ }
+
+ if failed {
+ return nil
+ }
+ return m
+}
+
+// asmCheckVar checks a single variable reference.
+func asmCheckVar(warnf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar) {
+ m := asmOpcode.FindStringSubmatch(line)
+ if m == nil {
+ warnf("cannot find assembly opcode")
+ }
+
+ // Determine operand sizes from instruction.
+ // Typically the suffix suffices, but there are exceptions.
+ var src, dst, kind asmKind
+ op := m[1]
+ switch fn.arch.name + "." + op {
+ case "386.FMOVLP":
+ src, dst = 8, 4
+ case "arm.MOVD":
+ src = 8
+ case "arm.MOVW":
+ src = 4
+ case "arm.MOVH", "arm.MOVHU":
+ src = 2
+ case "arm.MOVB", "arm.MOVBU":
+ src = 1
+ default:
+ if fn.arch.name == "386" || fn.arch.name == "amd64" {
+ if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "D") || strings.HasSuffix(op, "DP")) {
+ // FMOVDP, FXCHD, etc
+ src = 8
+ break
+ }
+ if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "F") || strings.HasSuffix(op, "FP")) {
+ // FMOVFP, FXCHF, etc
+ src = 4
+ break
+ }
+ if strings.HasSuffix(op, "SD") {
+ // MOVSD, SQRTSD, etc
+ src = 8
+ break
+ }
+ if strings.HasSuffix(op, "SS") {
+ // MOVSS, SQRTSS, etc
+ src = 4
+ break
+ }
+ if strings.HasPrefix(op, "SET") {
+ // SETEQ, etc
+ src = 1
+ break
+ }
+ switch op[len(op)-1] {
+ case 'B':
+ src = 1
+ case 'W':
+ src = 2
+ case 'L':
+ src = 4
+ case 'D', 'Q':
+ src = 8
+ }
+ }
+ }
+ if dst == 0 {
+ dst = src
+ }
+
+ // Determine whether the match we're holding
+ // is the first or second argument.
+ if strings.Index(line, expr) > strings.Index(line, ",") {
+ kind = dst
+ } else {
+ kind = src
+ }
+
+ vk := v.kind
+ vt := v.typ
+ switch vk {
+ case asmInterface, asmEmptyInterface, asmString, asmSlice:
+ // allow reference to first word (pointer)
+ vk = v.inner[0].kind
+ vt = v.inner[0].typ
+ }
+
+ if off != v.off {
+ var inner bytes.Buffer
+ for i, vi := range v.inner {
+ if len(v.inner) > 1 {
+ fmt.Fprintf(&inner, ",")
+ }
+ fmt.Fprintf(&inner, " ")
+ if i == len(v.inner)-1 {
+ fmt.Fprintf(&inner, "or ")
+ }
+ fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+ }
+ warnf("invalid offset %s; expected %s+%d(FP)%s", expr, v.name, v.off, inner.String())
+ return
+ }
+ if kind != 0 && kind != vk {
+ var inner bytes.Buffer
+ if len(v.inner) > 0 {
+ fmt.Fprintf(&inner, " containing")
+ for i, vi := range v.inner {
+ if i > 0 && len(v.inner) > 2 {
+ fmt.Fprintf(&inner, ",")
+ }
+ fmt.Fprintf(&inner, " ")
+ if i > 0 && i == len(v.inner)-1 {
+ fmt.Fprintf(&inner, "and ")
+ }
+ fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
+ }
+ }
+ warnf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vk, inner.String())
+ }
+}
diff --git a/src/cmd/vet/assign.go b/src/cmd/vet/assign.go
new file mode 100644
index 000000000..a11f0f875
--- /dev/null
+++ b/src/cmd/vet/assign.go
@@ -0,0 +1,44 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+This file contains the code to check for useless assignments.
+*/
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+ "reflect"
+)
+
+// TODO: should also check for assignments to struct fields inside methods
+// that are on T instead of *T.
+
+// checkAssignStmt checks for assignments of the form "<expr> = <expr>".
+// These are almost always useless, and even when they aren't they are usually a mistake.
+func (f *File) checkAssignStmt(stmt *ast.AssignStmt) {
+ if !vet("assign") {
+ return
+ }
+ if stmt.Tok != token.ASSIGN {
+ return // ignore :=
+ }
+ if len(stmt.Lhs) != len(stmt.Rhs) {
+ // If LHS and RHS have different cardinality, they can't be the same.
+ return
+ }
+ for i, lhs := range stmt.Lhs {
+ rhs := stmt.Rhs[i]
+ if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
+ continue // short-circuit the heavy-weight gofmt check
+ }
+ le := f.gofmt(lhs)
+ re := f.gofmt(rhs)
+ if le == re {
+ f.Warnf(stmt.Pos(), "self-assignment of %s to %s", re, le)
+ }
+ }
+}
diff --git a/src/cmd/vet/buildtag.go b/src/cmd/vet/buildtag.go
index 4b7580457..0ab13cb8a 100644
--- a/src/cmd/vet/buildtag.go
+++ b/src/cmd/vet/buildtag.go
@@ -72,7 +72,7 @@ func checkBuildTag(name string, data []byte) {
elem = elem[1:]
}
for _, c := range elem {
- if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
+ if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg)
setExit(1)
break Args
diff --git a/src/cmd/vet/deadcode.go b/src/cmd/vet/deadcode.go
new file mode 100644
index 000000000..f90fc14a4
--- /dev/null
+++ b/src/cmd/vet/deadcode.go
@@ -0,0 +1,280 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check for syntactically unreachable code.
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+type deadState struct {
+ f *File
+ hasBreak map[ast.Stmt]bool
+ hasGoto map[string]bool
+ labels map[string]ast.Stmt
+ breakTarget ast.Stmt
+
+ reachable bool
+}
+
+// checkUnreachable checks a function body for dead code.
+func (f *File) checkUnreachable(body *ast.BlockStmt) {
+ if !vet("unreachable") || body == nil {
+ return
+ }
+
+ d := &deadState{
+ f: f,
+ hasBreak: make(map[ast.Stmt]bool),
+ hasGoto: make(map[string]bool),
+ labels: make(map[string]ast.Stmt),
+ }
+
+ d.findLabels(body)
+
+ d.reachable = true
+ d.findDead(body)
+}
+
+// findLabels gathers information about the labels defined and used by stmt
+// and about which statements break, whether a label is involved or not.
+func (d *deadState) findLabels(stmt ast.Stmt) {
+ switch x := stmt.(type) {
+ default:
+ d.f.Warnf(x.Pos(), "internal error in findLabels: unexpected statement %T", x)
+
+ case *ast.AssignStmt,
+ *ast.BadStmt,
+ *ast.DeclStmt,
+ *ast.DeferStmt,
+ *ast.EmptyStmt,
+ *ast.ExprStmt,
+ *ast.GoStmt,
+ *ast.IncDecStmt,
+ *ast.ReturnStmt,
+ *ast.SendStmt:
+ // no statements inside
+
+ case *ast.BlockStmt:
+ for _, stmt := range x.List {
+ d.findLabels(stmt)
+ }
+
+ case *ast.BranchStmt:
+ switch x.Tok {
+ case token.GOTO:
+ d.hasGoto[x.Label.Name] = true
+
+ case token.BREAK:
+ stmt := d.breakTarget
+ if x.Label != nil {
+ stmt = d.labels[x.Label.Name]
+ }
+ if stmt != nil {
+ d.hasBreak[stmt] = true
+ }
+ }
+
+ case *ast.IfStmt:
+ d.findLabels(x.Body)
+ if x.Else != nil {
+ d.findLabels(x.Else)
+ }
+
+ case *ast.LabeledStmt:
+ d.labels[x.Label.Name] = x.Stmt
+ d.findLabels(x.Stmt)
+
+ // These cases are all the same, but the x.Body only works
+ // when the specific type of x is known, so the cases cannot
+ // be merged.
+ case *ast.ForStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.RangeStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.SelectStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.SwitchStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.TypeSwitchStmt:
+ outer := d.breakTarget
+ d.breakTarget = x
+ d.findLabels(x.Body)
+ d.breakTarget = outer
+
+ case *ast.CommClause:
+ for _, stmt := range x.Body {
+ d.findLabels(stmt)
+ }
+
+ case *ast.CaseClause:
+ for _, stmt := range x.Body {
+ d.findLabels(stmt)
+ }
+ }
+}
+
+// findDead walks the statement looking for dead code.
+// If d.reachable is false on entry, stmt itself is dead.
+// When findDead returns, d.reachable tells whether the
+// statement following stmt is reachable.
+func (d *deadState) findDead(stmt ast.Stmt) {
+ // Is this a labeled goto target?
+ // If so, assume it is reachable due to the goto.
+ // This is slightly conservative, in that we don't
+ // check that the goto is reachable, so
+ // L: goto L
+ // will not provoke a warning.
+ // But it's good enough.
+ if x, isLabel := stmt.(*ast.LabeledStmt); isLabel && d.hasGoto[x.Label.Name] {
+ d.reachable = true
+ }
+
+ if !d.reachable {
+ switch stmt.(type) {
+ case *ast.EmptyStmt:
+ // do not warn about unreachable empty statements
+ default:
+ d.f.Warnf(stmt.Pos(), "unreachable code")
+ d.reachable = true // silence error about next statement
+ }
+ }
+
+ switch x := stmt.(type) {
+ default:
+ d.f.Warnf(x.Pos(), "internal error in findDead: unexpected statement %T", x)
+
+ case *ast.AssignStmt,
+ *ast.BadStmt,
+ *ast.DeclStmt,
+ *ast.DeferStmt,
+ *ast.EmptyStmt,
+ *ast.GoStmt,
+ *ast.IncDecStmt,
+ *ast.SendStmt:
+ // no control flow
+
+ case *ast.BlockStmt:
+ for _, stmt := range x.List {
+ d.findDead(stmt)
+ }
+
+ case *ast.BranchStmt:
+ switch x.Tok {
+ case token.BREAK, token.GOTO, token.FALLTHROUGH:
+ d.reachable = false
+ case token.CONTINUE:
+ // NOTE: We accept "continue" statements as terminating.
+ // They are not necessary in the spec definition of terminating,
+ // because a continue statement cannot be the final statement
+ // before a return. But for the more general problem of syntactically
+ // identifying dead code, continue redirects control flow just
+ // like the other terminating statements.
+ d.reachable = false
+ }
+
+ case *ast.ExprStmt:
+ // Call to panic?
+ call, ok := x.X.(*ast.CallExpr)
+ if ok {
+ name, ok := call.Fun.(*ast.Ident)
+ if ok && name.Name == "panic" && name.Obj == nil {
+ d.reachable = false
+ }
+ }
+
+ case *ast.ForStmt:
+ d.findDead(x.Body)
+ d.reachable = x.Cond != nil || d.hasBreak[x]
+
+ case *ast.IfStmt:
+ d.findDead(x.Body)
+ if x.Else != nil {
+ r := d.reachable
+ d.reachable = true
+ d.findDead(x.Else)
+ d.reachable = d.reachable || r
+ } else {
+ // might not have executed if statement
+ d.reachable = true
+ }
+
+ case *ast.LabeledStmt:
+ d.findDead(x.Stmt)
+
+ case *ast.RangeStmt:
+ d.findDead(x.Body)
+ d.reachable = true
+
+ case *ast.ReturnStmt:
+ d.reachable = false
+
+ case *ast.SelectStmt:
+ // NOTE: Unlike switch and type switch below, we don't care
+ // whether a select has a default, because a select without a
+ // default blocks until one of the cases can run. That's different
+ // from a switch without a default, which behaves like it has
+ // a default with an empty body.
+ anyReachable := false
+ for _, comm := range x.Body.List {
+ d.reachable = true
+ for _, stmt := range comm.(*ast.CommClause).Body {
+ d.findDead(stmt)
+ }
+ anyReachable = anyReachable || d.reachable
+ }
+ d.reachable = anyReachable || d.hasBreak[x]
+
+ case *ast.SwitchStmt:
+ anyReachable := false
+ hasDefault := false
+ for _, cas := range x.Body.List {
+ cc := cas.(*ast.CaseClause)
+ if cc.List == nil {
+ hasDefault = true
+ }
+ d.reachable = true
+ for _, stmt := range cc.Body {
+ d.findDead(stmt)
+ }
+ anyReachable = anyReachable || d.reachable
+ }
+ d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+
+ case *ast.TypeSwitchStmt:
+ anyReachable := false
+ hasDefault := false
+ for _, cas := range x.Body.List {
+ cc := cas.(*ast.CaseClause)
+ if cc.List == nil {
+ hasDefault = true
+ }
+ d.reachable = true
+ for _, stmt := range cc.Body {
+ d.findDead(stmt)
+ }
+ anyReachable = anyReachable || d.reachable
+ }
+ d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
+ }
+}
diff --git a/src/cmd/vet/doc.go b/src/cmd/vet/doc.go
index f164eaca2..eb1e436f0 100644
--- a/src/cmd/vet/doc.go
+++ b/src/cmd/vet/doc.go
@@ -9,6 +9,12 @@ calls whose arguments do not align with the format string. Vet uses heuristics
that do not guarantee all reports are genuine problems, but it can find errors
not caught by the compilers.
+Its exit code is 2 for erroneous invocation of the tool, 1 if a
+problem was reported, and 0 otherwise. Note that the tool does not
+check every possible problem and depends on unreliable heuristics
+so it should be used as guidance only, not as a firm indicator of
+program correctness.
+
By default all checks are performed, but if explicit flags are provided, only
those identified by the flags are performed.
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index 20f6cca1a..2fefa0b47 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -15,7 +15,6 @@ import (
"go/parser"
"go/printer"
"go/token"
- "go/types"
"io/ioutil"
"os"
"path/filepath"
@@ -29,14 +28,17 @@ var exitCode = 0
// Flags to control which checks to perform. "all" is set to true here, and disabled later if
// a flag is set explicitly.
var report = map[string]*bool{
- "all": flag.Bool("all", true, "check everything; disabled if any explicit check is requested"),
- "atomic": flag.Bool("atomic", false, "check for common mistaken usages of the sync/atomic package"),
- "buildtags": flag.Bool("buildtags", false, "check that +build tags are valid"),
- "composites": flag.Bool("composites", false, "check that composite literals used type-tagged elements"),
- "methods": flag.Bool("methods", false, "check that canonically named methods are canonically defined"),
- "printf": flag.Bool("printf", false, "check printf-like invocations"),
- "structtags": flag.Bool("structtags", false, "check that struct field tags have canonical format"),
- "rangeloops": flag.Bool("rangeloops", false, "check that range loop variables are used correctly"),
+ "all": flag.Bool("all", true, "check everything; disabled if any explicit check is requested"),
+ "asmdecl": flag.Bool("asmdecl", false, "check assembly against Go declarations"),
+ "assign": flag.Bool("assign", false, "check for useless assignments"),
+ "atomic": flag.Bool("atomic", false, "check for common mistaken usages of the sync/atomic package"),
+ "buildtags": flag.Bool("buildtags", false, "check that +build tags are valid"),
+ "composites": flag.Bool("composites", false, "check that composite literals used type-tagged elements"),
+ "methods": flag.Bool("methods", false, "check that canonically named methods are canonically defined"),
+ "printf": flag.Bool("printf", false, "check printf-like invocations"),
+ "rangeloops": flag.Bool("rangeloops", false, "check that range loop variables are used correctly"),
+ "structtags": flag.Bool("structtags", false, "check that struct field tags have canonical format"),
+ "unreachable": flag.Bool("unreachable", false, "check for unreachable code"),
}
// vet tells whether to report errors for the named check, a flag name.
@@ -64,11 +66,12 @@ func Usage() {
// File is a wrapper for the state of a file used in the parser.
// The parse tree walkers are all methods of this type.
type File struct {
- pkg *Package
- fset *token.FileSet
- name string
- file *ast.File
- b bytes.Buffer // for use by methods
+ pkg *Package
+ fset *token.FileSet
+ name string
+ content []byte
+ file *ast.File
+ b bytes.Buffer // for use by methods
}
func main() {
@@ -163,6 +166,7 @@ func doPackageDir(directory string) {
names = append(names, pkg.GoFiles...)
names = append(names, pkg.CgoFiles...)
names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
+ names = append(names, pkg.SFiles...)
prefixDirectory(directory, names)
doPackage(names)
// Is there also a "foo_test" package? If so, do that one as well.
@@ -174,8 +178,9 @@ func doPackageDir(directory string) {
}
type Package struct {
- types map[ast.Expr]types.Type
+ types map[ast.Expr]Type
values map[ast.Expr]interface{}
+ files []*File
}
// doPackage analyzes the single package constructed from the named files.
@@ -186,50 +191,48 @@ func doPackage(names []string) {
for _, name := range names {
f, err := os.Open(name)
if err != nil {
- errorf("%s: %s", name, err)
+ // Warn but continue to next package.
+ warnf("%s: %s", name, err)
+ return
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
- errorf("%s: %s", name, err)
+ warnf("%s: %s", name, err)
+ return
}
checkBuildTag(name, data)
- parsedFile, err := parser.ParseFile(fs, name, bytes.NewReader(data), 0)
- if err != nil {
- errorf("%s: %s", name, err)
+ var parsedFile *ast.File
+ if strings.HasSuffix(name, ".go") {
+ parsedFile, err = parser.ParseFile(fs, name, bytes.NewReader(data), 0)
+ if err != nil {
+ warnf("%s: %s", name, err)
+ return
+ }
+ astFiles = append(astFiles, parsedFile)
}
- files = append(files, &File{fset: fs, name: name, file: parsedFile})
- astFiles = append(astFiles, parsedFile)
+ files = append(files, &File{fset: fs, content: data, name: name, file: parsedFile})
}
pkg := new(Package)
- pkg.types = make(map[ast.Expr]types.Type)
- pkg.values = make(map[ast.Expr]interface{})
- exprFn := func(x ast.Expr, typ types.Type, val interface{}) {
- pkg.types[x] = typ
- if val != nil {
- pkg.values[x] = val
- }
- }
- // By providing the Context with our own error function, it will continue
- // past the first error. There is no need for that function to do anything.
- context := types.Context{
- Expr: exprFn,
- Error: func(error) {},
- }
+ pkg.files = files
// Type check the package.
- _, err := context.Check(fs, astFiles)
+ err := pkg.check(fs, astFiles)
if err != nil && *verbose {
warnf("%s", err)
}
for _, file := range files {
file.pkg = pkg
- file.walkFile(file.name, file.file)
+ if file.file != nil {
+ file.walkFile(file.name, file.file)
+ }
}
+ asmCheck(pkg)
}
func visit(path string, f os.FileInfo, err error) error {
if err != nil {
- errorf("walk error: %s", err)
+ warnf("walk error: %s", err)
+ return err
}
// One package per directory. Ignore the files themselves.
if !f.IsDir() {
@@ -239,7 +242,16 @@ func visit(path string, f os.FileInfo, err error) error {
return nil
}
-// walkDir recursively walks the tree looking for .go files.
+func (pkg *Package) hasFileWithSuffix(suffix string) bool {
+ for _, f := range pkg.files {
+ if strings.HasSuffix(f.name, suffix) {
+ return true
+ }
+ }
+ return false
+}
+
+// walkDir recursively walks the tree looking for Go packages.
func walkDir(root string) {
filepath.Walk(root, visit)
}
@@ -287,6 +299,9 @@ func (f *File) Badf(pos token.Pos, format string, args ...interface{}) {
}
func (f *File) loc(pos token.Pos) string {
+ if pos == token.NoPos {
+ return ""
+ }
// Do not print columns. Because the pos often points to the start of an
// expression instead of the inner part with the actual error, the
// precision can mislead.
@@ -322,7 +337,9 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
case *ast.Field:
f.walkFieldTag(n)
case *ast.FuncDecl:
- f.walkMethodDecl(n)
+ f.walkFuncDecl(n)
+ case *ast.FuncLit:
+ f.walkFuncLit(n)
case *ast.InterfaceType:
f.walkInterfaceType(n)
case *ast.RangeStmt:
@@ -333,6 +350,7 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
// walkAssignStmt walks an assignment statement
func (f *File) walkAssignStmt(stmt *ast.AssignStmt) {
+ f.checkAssignStmt(stmt)
f.checkAtomicAssignment(stmt)
}
@@ -364,18 +382,22 @@ func (f *File) walkFieldTag(field *ast.Field) {
f.checkCanonicalFieldTag(field)
}
-// walkMethodDecl walks the method's signature.
+// walkMethod walks the method's signature.
func (f *File) walkMethod(id *ast.Ident, t *ast.FuncType) {
f.checkCanonicalMethod(id, t)
}
-// walkMethodDecl walks the method signature in the declaration.
-func (f *File) walkMethodDecl(d *ast.FuncDecl) {
- if d.Recv == nil {
- // not a method
- return
+// walkFuncDecl walks a function declaration.
+func (f *File) walkFuncDecl(d *ast.FuncDecl) {
+ f.checkUnreachable(d.Body)
+ if d.Recv != nil {
+ f.walkMethod(d.Name, d.Type)
}
- f.walkMethod(d.Name, d.Type)
+}
+
+// walkFuncLit walks a function literal.
+func (f *File) walkFuncLit(x *ast.FuncLit) {
+ f.checkUnreachable(x.Body)
}
// walkInterfaceType walks the method signatures of an interface.
diff --git a/src/cmd/vet/method.go b/src/cmd/vet/method.go
index bf982dc7a..8064235f4 100644
--- a/src/cmd/vet/method.go
+++ b/src/cmd/vet/method.go
@@ -93,7 +93,7 @@ func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
actual = strings.TrimPrefix(actual, "func")
actual = id.Name + actual
- f.Warnf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
+ f.Badf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
}
}
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go
index fb0fb9f9b..debfbf0bf 100644
--- a/src/cmd/vet/print.go
+++ b/src/cmd/vet/print.go
@@ -10,7 +10,6 @@ import (
"flag"
"go/ast"
"go/token"
- "go/types"
"strconv"
"strings"
"unicode/utf8"
@@ -302,59 +301,6 @@ func (f *File) checkPrintfArg(call *ast.CallExpr, verb rune, flags []byte, argNu
f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
}
-func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
- // TODO: for now, we can only test builtin types and untyped constants.
- typ := f.pkg.types[arg]
- if typ == nil {
- return true
- }
- basic, ok := typ.(*types.Basic)
- if !ok {
- return true
- }
- switch basic.Kind {
- case types.Bool:
- return t&argBool != 0
- case types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
- fallthrough
- case types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64, types.Uintptr:
- return t&argInt != 0
- case types.Float32, types.Float64, types.Complex64, types.Complex128:
- return t&argFloat != 0
- case types.String:
- return t&argString != 0
- case types.UnsafePointer:
- return t&(argPointer|argInt) != 0
- case types.UntypedBool:
- return t&argBool != 0
- case types.UntypedComplex:
- return t&argFloat != 0
- case types.UntypedFloat:
- // If it's integral, we can use an int format.
- switch f.pkg.values[arg].(type) {
- case int, int8, int16, int32, int64:
- return t&(argInt|argFloat) != 0
- case uint, uint8, uint16, uint32, uint64:
- return t&(argInt|argFloat) != 0
- }
- return t&argFloat != 0
- case types.UntypedInt:
- return t&argInt != 0
- case types.UntypedRune:
- return t&(argInt|argRune) != 0
- case types.UntypedString:
- return t&argString != 0
- case types.UntypedNil:
- return t&argPointer != 0 // TODO?
- case types.Invalid:
- if *verbose {
- f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", arg)
- }
- return true // Probably a type check problem.
- }
- return false
-}
-
// checkPrint checks a call to an unformatted print routine such as Println.
// call.Args[firstArg] is the first argument to be printed.
func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
@@ -366,7 +312,7 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
if sel, ok := args[0].(*ast.SelectorExpr); ok {
if x, ok := sel.X.(*ast.Ident); ok {
if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
- f.Warnf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
+ f.Badf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
}
}
}
@@ -403,64 +349,3 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
}
}
}
-
-// numArgsInSignature tells how many formal arguments the function type
-// being called has.
-func (f *File) numArgsInSignature(call *ast.CallExpr) int {
- // Check the type of the function or method declaration
- typ := f.pkg.types[call.Fun]
- if typ == nil {
- return 0
- }
- // The type must be a signature, but be sure for safety.
- sig, ok := typ.(*types.Signature)
- if !ok {
- return 0
- }
- return len(sig.Params)
-}
-
-// isErrorMethodCall reports whether the call is of a method with signature
-// func Error() string
-// where "string" is the universe's string type. We know the method is called "Error".
-func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
- // Is it a selector expression? Otherwise it's a function call, not a method call.
- sel, ok := call.Fun.(*ast.SelectorExpr)
- if !ok {
- return false
- }
- // The package is type-checked, so if there are no arguments, we're done.
- if len(call.Args) > 0 {
- return false
- }
- // Check the type of the method declaration
- typ := f.pkg.types[sel]
- if typ == nil {
- return false
- }
- // The type must be a signature, but be sure for safety.
- sig, ok := typ.(*types.Signature)
- if !ok {
- return false
- }
- // There must be a receiver for it to be a method call. Otherwise it is
- // a function, not something that satisfies the error interface.
- if sig.Recv == nil {
- return false
- }
- // There must be no arguments. Already verified by type checking, but be thorough.
- if len(sig.Params) > 0 {
- return false
- }
- // Finally the real questions.
- // There must be one result.
- if len(sig.Results) != 1 {
- return false
- }
- // It must have return type "string" from the universe.
- result := sig.Results[0].Type
- if types.IsIdentical(result, types.Typ[types.String]) {
- return true
- }
- return false
-}
diff --git a/src/cmd/vet/structtag.go b/src/cmd/vet/structtag.go
index 545e420c1..d83578836 100644
--- a/src/cmd/vet/structtag.go
+++ b/src/cmd/vet/structtag.go
@@ -23,7 +23,7 @@ func (f *File) checkCanonicalFieldTag(field *ast.Field) {
tag, err := strconv.Unquote(field.Tag.Value)
if err != nil {
- f.Warnf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
+ f.Badf(field.Pos(), "unable to read struct tag %s", field.Tag.Value)
return
}
@@ -31,7 +31,7 @@ func (f *File) checkCanonicalFieldTag(field *ast.Field) {
// new key:value to end and checking that
// the tag parsing code can find it.
if reflect.StructTag(tag+` _gofix:"_magic"`).Get("_gofix") != "_magic" {
- f.Warnf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
+ f.Badf(field.Pos(), "struct field tag %s not compatible with reflect.StructTag.Get", field.Tag.Value)
return
}
}
diff --git a/src/cmd/vet/taglit.go b/src/cmd/vet/taglit.go
index 0324e37b0..bcad2fe0a 100644
--- a/src/cmd/vet/taglit.go
+++ b/src/cmd/vet/taglit.go
@@ -9,32 +9,52 @@ package main
import (
"flag"
"go/ast"
- "go/types"
"strings"
)
var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")
-// checkUntaggedLiteral checks if a composite literal is an struct literal with
+// checkUntaggedLiteral checks if a composite literal is a struct literal with
// untagged fields.
func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
if !vet("composites") {
return
}
- // Check that the CompositeLit's type is a slice or array (which needs no tag), if possible.
- typ := f.pkg.types[c]
- if typ != nil {
- // If it's a named type, pull out the underlying type.
- if namedType, ok := typ.(*types.NamedType); ok {
- typ = namedType.Underlying
- }
- switch typ.(type) {
- case *types.Slice:
- return
- case *types.Array:
- return
+ typ := c.Type
+ for {
+ if typ1, ok := c.Type.(*ast.ParenExpr); ok {
+ typ = typ1
+ continue
}
+ break
+ }
+
+ switch typ.(type) {
+ case *ast.ArrayType:
+ return
+ case *ast.MapType:
+ return
+ case *ast.StructType:
+ return // a literal struct type does not need to use tags
+ case *ast.Ident:
+ // A simple type name like t or T does not need tags either,
+ // since it is almost certainly declared in the current package.
+ // (The exception is names being used via import . "pkg", but
+ // those are already breaking the Go 1 compatibility promise,
+ // so not reporting potential additional breakage seems okay.)
+ return
+ }
+
+ // Otherwise the type is a selector like pkg.Name.
+ // We only care if pkg.Name is a struct, not if it's a map, array, or slice.
+ isStruct, typeString := f.pkg.isStruct(c)
+ if !isStruct {
+ return
+ }
+
+ if typeString == "" { // isStruct doesn't know
+ typeString = f.gofmt(typ)
}
// It's a struct, or we can't tell it's not a struct because we don't have types.
@@ -64,7 +84,7 @@ func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
// Convert the package name to an import path, and compare to a whitelist.
path := pkgPath(f, pkg.Name)
if path == "" {
- f.Warnf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name)
+ f.Badf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name)
return
}
typeName := path + "." + s.Sel.Name
@@ -72,7 +92,7 @@ func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
return
}
- f.Warnf(c.Pos(), "%s composite literal uses untagged fields", typ)
+ f.Warn(c.Pos(), typeString+" composite literal uses untagged fields")
}
// pkgPath returns the import path "image/png" for the package name "png".
@@ -119,8 +139,6 @@ var untaggedLiteralWhitelist = map[string]bool{
"encoding/xml.CharData": true,
"encoding/xml.Comment": true,
"encoding/xml.Directive": true,
- "exp/norm.Decomposition": true,
- "exp/types.ObjList": true,
"go/scanner.ErrorList": true,
"image/color.Palette": true,
"net.HardwareAddr": true,
diff --git a/src/cmd/vet/test_asm.go b/src/cmd/vet/test_asm.go
new file mode 100644
index 000000000..098bdd15c
--- /dev/null
+++ b/src/cmd/vet/test_asm.go
@@ -0,0 +1,24 @@
+// 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.
+
+// +build ignore
+
+// This file contains declarations to test the assembly in test_asm.s.
+
+package main
+
+func arg1(x int8, y uint8)
+func arg2(x int16, y uint16)
+func arg4(x int32, y uint32)
+func arg8(x int64, y uint64)
+func argint(x int, y uint)
+func argptr(x *byte, y *byte, c chan int, m map[int]int, f func())
+func argstring(x, y string)
+func argslice(x, y []string)
+func argiface(x interface{}, y interface {
+ m()
+})
+func returnint() int
+func returnbyte(x int) byte
+func returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)
diff --git a/src/cmd/vet/test_asm1.s b/src/cmd/vet/test_asm1.s
new file mode 100644
index 000000000..2fe31963a
--- /dev/null
+++ b/src/cmd/vet/test_asm1.s
@@ -0,0 +1,249 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64
+// +build ignore
+
+package main
+
+TEXT ·arg1(SB),0,$0-2
+ MOVB x+0(FP), AX
+ MOVB y+1(FP), BX
+ MOVW x+0(FP), AX // ERROR "\[amd64\] invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+ MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+ MOVL y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+ MOVQ y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+ MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ TESTB x+0(FP), AX
+ TESTB y+1(FP), BX
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+ TESTW y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+ TESTL y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+ TESTQ y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+ TESTB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ TESTB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ RET
+
+TEXT ·arg2(SB),0,$0-4
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+ MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+2(FP), BX
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+ MOVL y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+ MOVQ y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ MOVW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+ TESTB y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+0(FP), AX
+ TESTW y+2(FP), BX
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+ TESTL y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+ TESTQ y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ TESTW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value"
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int is 8-byte value"
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int is 8-byte value"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint is 8-byte value"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); \*byte is 8-byte value"
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); \*byte is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); \*byte is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); \*byte is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); \*byte is 8-byte value"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); \*byte is 8-byte value"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ MOVL c+16(FP), AX // ERROR "invalid MOVL of c\+16\(FP\); chan int is 8-byte value"
+ MOVL m+24(FP), AX // ERROR "invalid MOVL of m\+24\(FP\); map\[int\]int is 8-byte value"
+ MOVL f+32(FP), AX // ERROR "invalid MOVL of f\+32\(FP\); func\(\) is 8-byte value"
+ RET
+
+TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); string base is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
+ MOVL x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); string base is 8-byte value"
+ MOVQ x_base+0(FP), AX
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVW x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
+ MOVL x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); string len is 8-byte value"
+ MOVQ x_len+8(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
+ MOVQ y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
+ RET
+
+TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); slice base is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
+ MOVL x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); slice base is 8-byte value"
+ MOVQ x_base+0(FP), AX
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
+ MOVW x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
+ MOVL x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); slice len is 8-byte value"
+ MOVQ x_len+8(FP), AX
+ MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+ MOVL x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+ MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
+ MOVW x_cap+16(FP), AX // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
+ MOVL x_cap+16(FP), AX // ERROR "invalid MOVL of x_cap\+16\(FP\); slice cap is 8-byte value"
+ MOVQ x_cap+16(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
+ MOVQ y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
+ MOVQ y_cap+16(FP), AX // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
+ RET
+
+TEXT ·argiface(SB),0,$0-32
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); interface type is 8-byte value"
+ MOVQ x+0(FP), AX
+ MOVW x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
+ MOVL x_type+0(FP), AX // ERROR "invalid MOVL of x_type\+0\(FP\); interface type is 8-byte value"
+ MOVQ x_type+0(FP), AX
+ MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+ MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+ MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+ MOVL x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+ MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
+ MOVW x_data+8(FP), AX // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
+ MOVL x_data+8(FP), AX // ERROR "invalid MOVL of x_data\+8\(FP\); interface data is 8-byte value"
+ MOVQ x_data+8(FP), AX
+ MOVW y+16(FP), AX // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
+ MOVL y+16(FP), AX // ERROR "invalid MOVL of y\+16\(FP\); interface itable is 8-byte value"
+ MOVQ y+16(FP), AX
+ MOVW y_itable+16(FP), AX // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
+ MOVL y_itable+16(FP), AX // ERROR "invalid MOVL of y_itable\+16\(FP\); interface itable is 8-byte value"
+ MOVQ y_itable+16(FP), AX
+ MOVQ y_type+16(FP), AX // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
+ MOVW y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+ MOVL y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+ MOVQ y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
+ MOVW y_data+24(FP), AX // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
+ MOVL y_data+24(FP), AX // ERROR "invalid MOVL of y_data\+24\(FP\); interface data is 8-byte value"
+ MOVQ y_data+24(FP), AX
+ RET
+
+TEXT ·returnint(SB),0,$0-8
+ MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
+ MOVW AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
+ MOVL AX, ret+0(FP) // ERROR "invalid MOVL of ret\+0\(FP\); int is 8-byte value"
+ MOVQ AX, ret+0(FP)
+ MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+ MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+ RET
+
+TEXT ·returnbyte(SB),0,$0-9
+ MOVQ x+0(FP), AX
+ MOVB AX, ret+8(FP)
+ MOVW AX, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
+ MOVL AX, ret+8(FP) // ERROR "invalid MOVL of ret\+8\(FP\); byte is 1-byte value"
+ MOVQ AX, ret+8(FP) // ERROR "invalid MOVQ of ret\+8\(FP\); byte is 1-byte value"
+ MOVB AX, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
+ RET
+
+TEXT ·returnnamed(SB),0,$0-41
+ MOVB x+0(FP), AX
+ MOVQ AX, r1+8(FP)
+ MOVW AX, r2+16(FP)
+ MOVQ AX, r3+24(FP)
+ MOVQ AX, r3_base+24(FP)
+ MOVQ AX, r3_len+32(FP)
+ MOVB AX, r4+40(FP)
+ MOVL AX, r1+8(FP) // ERROR "invalid MOVL of r1\+8\(FP\); int is 8-byte value"
+ RET
diff --git a/src/cmd/vet/test_asm2.s b/src/cmd/vet/test_asm2.s
new file mode 100644
index 000000000..73a4ad4be
--- /dev/null
+++ b/src/cmd/vet/test_asm2.s
@@ -0,0 +1,253 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build 386
+// +build ignore
+
+package main
+
+TEXT ·arg1(SB),0,$0-2
+ MOVB x+0(FP), AX
+ MOVB y+1(FP), BX
+ MOVW x+0(FP), AX // ERROR "\[386\] invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+ MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
+ MOVL y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
+ MOVQ y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
+ MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ TESTB x+0(FP), AX
+ TESTB y+1(FP), BX
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
+ TESTW y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
+ TESTL y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
+ TESTQ y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
+ TESTB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ TESTB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ RET
+
+TEXT ·arg2(SB),0,$0-4
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+ MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+2(FP), BX
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
+ MOVL y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
+ MOVQ y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
+ MOVW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ MOVW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
+ TESTB y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+0(FP), AX
+ TESTW y+2(FP), BX
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
+ TESTL y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
+ TESTQ y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
+ TESTW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ TESTW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
+ MOVL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
+ TESTL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
+ MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+ MOVL x_lo+0(FP), AX
+ MOVL x_hi+4(FP), AX
+ MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+ MOVL y_lo+8(FP), AX
+ MOVL y_hi+12(FP), AX
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
+ TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
+ TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
+ TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+ TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+ TESTQ x+0(FP), AX
+ TESTQ y+8(FP), AX
+ TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint is 4-byte value"
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint is 4-byte value"
+ TESTQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 4-byte value"
+ MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); \*byte is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVL y+4(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); \*byte is 4-byte value"
+ MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); \*byte is 4-byte value"
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 4-byte value"
+ TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); \*byte is 4-byte value"
+ TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 4-byte value"
+ TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); \*byte is 4-byte value"
+ TESTL x+0(FP), AX
+ TESTL y+4(FP), AX
+ TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); \*byte is 4-byte value"
+ TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); \*byte is 4-byte value"
+ TESTQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ MOVW c+8(FP), AX // ERROR "invalid MOVW of c\+8\(FP\); chan int is 4-byte value"
+ MOVW m+12(FP), AX // ERROR "invalid MOVW of m\+12\(FP\); map\[int\]int is 4-byte value"
+ MOVW f+16(FP), AX // ERROR "invalid MOVW of f\+16\(FP\); func\(\) is 4-byte value"
+ RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); string base is 4-byte value"
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 4-byte value"
+ MOVL x_base+0(FP), AX
+ MOVQ x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); string base is 4-byte value"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); string len is 4-byte value"
+ MOVL x_len+4(FP), AX
+ MOVQ x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); string len is 4-byte value"
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+ RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); slice base is 4-byte value"
+ MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 4-byte value"
+ MOVL x_base+0(FP), AX
+ MOVQ x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); slice base is 4-byte value"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); slice len is 4-byte value"
+ MOVL x_len+4(FP), AX
+ MOVQ x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); slice len is 4-byte value"
+ MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVL x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVW x_cap+8(FP), AX // ERROR "invalid MOVW of x_cap\+8\(FP\); slice cap is 4-byte value"
+ MOVL x_cap+8(FP), AX
+ MOVQ x_cap+8(FP), AX // ERROR "invalid MOVQ of x_cap\+8\(FP\); slice cap is 4-byte value"
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+ MOVQ y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+ RET
+
+TEXT ·argiface(SB),0,$0-16
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 4-byte value"
+ MOVL x+0(FP), AX
+ MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); interface type is 4-byte value"
+ MOVW x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 4-byte value"
+ MOVL x_type+0(FP), AX
+ MOVQ x_type+0(FP), AX // ERROR "invalid MOVQ of x_type\+0\(FP\); interface type is 4-byte value"
+ MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+ MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+ MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVL x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVW x_data+4(FP), AX // ERROR "invalid MOVW of x_data\+4\(FP\); interface data is 4-byte value"
+ MOVL x_data+4(FP), AX
+ MOVQ x_data+4(FP), AX // ERROR "invalid MOVQ of x_data\+4\(FP\); interface data is 4-byte value"
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); interface itable is 4-byte value"
+ MOVL y+8(FP), AX
+ MOVQ y+8(FP), AX // ERROR "invalid MOVQ of y\+8\(FP\); interface itable is 4-byte value"
+ MOVW y_itable+8(FP), AX // ERROR "invalid MOVW of y_itable\+8\(FP\); interface itable is 4-byte value"
+ MOVL y_itable+8(FP), AX
+ MOVQ y_itable+8(FP), AX // ERROR "invalid MOVQ of y_itable\+8\(FP\); interface itable is 4-byte value"
+ MOVQ y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+ MOVW y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVL y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVQ y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVW y_data+12(FP), AX // ERROR "invalid MOVW of y_data\+12\(FP\); interface data is 4-byte value"
+ MOVL y_data+12(FP), AX
+ MOVQ y_data+12(FP), AX // ERROR "invalid MOVQ of y_data\+12\(FP\); interface data is 4-byte value"
+ RET
+
+TEXT ·returnint(SB),0,$0-4
+ MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+ MOVW AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 4-byte value"
+ MOVL AX, ret+0(FP)
+ MOVQ AX, ret+0(FP) // ERROR "invalid MOVQ of ret\+0\(FP\); int is 4-byte value"
+ MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+ MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+ RET
+
+TEXT ·returnbyte(SB),0,$0-5
+ MOVL x+0(FP), AX
+ MOVB AX, ret+4(FP)
+ MOVW AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+ MOVL AX, ret+4(FP) // ERROR "invalid MOVL of ret\+4\(FP\); byte is 1-byte value"
+ MOVQ AX, ret+4(FP) // ERROR "invalid MOVQ of ret\+4\(FP\); byte is 1-byte value"
+ MOVB AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+ RET
+
+TEXT ·returnnamed(SB),0,$0-21
+ MOVB x+0(FP), AX
+ MOVL AX, r1+4(FP)
+ MOVW AX, r2+8(FP)
+ MOVL AX, r3+12(FP)
+ MOVL AX, r3_base+12(FP)
+ MOVL AX, r3_len+16(FP)
+ MOVB AX, r4+20(FP)
+ MOVQ AX, r1+4(FP) // ERROR "invalid MOVQ of r1\+4\(FP\); int is 4-byte value"
+ RET
diff --git a/src/cmd/vet/test_asm3.s b/src/cmd/vet/test_asm3.s
new file mode 100644
index 000000000..2c1a54f3e
--- /dev/null
+++ b/src/cmd/vet/test_asm3.s
@@ -0,0 +1,168 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm
+// +build ignore
+
+package main
+
+TEXT ·arg1(SB),0,$0-2
+ MOVB x+0(FP), AX
+ MOVB y+1(FP), BX
+ MOVH x+0(FP), AX // ERROR "\[arm\] invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
+ MOVH y+1(FP), AX // ERROR "invalid MOVH of y\+1\(FP\); uint8 is 1-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
+ MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
+ MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
+ MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
+ RET
+
+TEXT ·arg2(SB),0,$0-4
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
+ MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
+ MOVH x+0(FP), AX
+ MOVH y+2(FP), BX
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int16 is 2-byte value"
+ MOVW y+2(FP), AX // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
+ MOVH x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
+ MOVH y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
+ RET
+
+TEXT ·arg4(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
+ MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+4(FP), AX
+ MOVW x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVW y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
+ MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
+ MOVH y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
+ MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
+ MOVW x_lo+0(FP), AX
+ MOVW x_hi+4(FP), AX
+ MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
+ MOVW y_lo+8(FP), AX
+ MOVW y_hi+12(FP), AX
+ MOVQ x+0(FP), AX
+ MOVQ y+8(FP), AX
+ MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
+ RET
+
+TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int is 4-byte value"
+ MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+4(FP), AX
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ RET
+
+TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
+ MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
+ MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 4-byte value"
+ MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); \*byte is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVW y+4(FP), AX
+ MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
+ MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
+ MOVH c+8(FP), AX // ERROR "invalid MOVH of c\+8\(FP\); chan int is 4-byte value"
+ MOVH m+12(FP), AX // ERROR "invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value"
+ MOVH f+16(FP), AX // ERROR "invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value"
+ RET
+
+TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); string base is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVH x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 4-byte value"
+ MOVW x_base+0(FP), AX
+ MOVH x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVH x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); string len is 4-byte value"
+ MOVW x_len+4(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
+ RET
+
+TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); slice base is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVH x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value"
+ MOVW x_base+0(FP), AX
+ MOVH x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
+ MOVH x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value"
+ MOVW x_len+4(FP), AX
+ MOVH x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
+ MOVH x_cap+8(FP), AX // ERROR "invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value"
+ MOVW x_cap+8(FP), AX
+ MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
+ MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
+ MOVQ y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
+ RET
+
+TEXT ·argiface(SB),0,$0-16
+ MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); interface type is 4-byte value"
+ MOVW x+0(FP), AX
+ MOVH x_type+0(FP), AX // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value"
+ MOVW x_type+0(FP), AX
+ MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
+ MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
+ MOVH x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
+ MOVH x_data+4(FP), AX // ERROR "invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value"
+ MOVW x_data+4(FP), AX
+ MOVH y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); interface itable is 4-byte value"
+ MOVW y+8(FP), AX
+ MOVH y_itable+8(FP), AX // ERROR "invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value"
+ MOVW y_itable+8(FP), AX
+ MOVQ y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
+ MOVH y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVW y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVQ y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
+ MOVH y_data+12(FP), AX // ERROR "invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value"
+ MOVW y_data+12(FP), AX
+ RET
+
+TEXT ·returnint(SB),0,$0-4
+ MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
+ MOVH AX, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 4-byte value"
+ MOVW AX, ret+0(FP)
+ MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
+ MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
+ RET
+
+TEXT ·returnbyte(SB),0,$0-5
+ MOVW x+0(FP), AX
+ MOVB AX, ret+4(FP)
+ MOVH AX, ret+4(FP) // ERROR "invalid MOVH of ret\+4\(FP\); byte is 1-byte value"
+ MOVW AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
+ MOVB AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
+ RET
+
+TEXT ·returnnamed(SB),0,$0-21
+ MOVB x+0(FP), AX
+ MOVW AX, r1+4(FP)
+ MOVH AX, r2+8(FP)
+ MOVW AX, r3+12(FP)
+ MOVW AX, r3_base+12(FP)
+ MOVW AX, r3_len+16(FP)
+ MOVB AX, r4+20(FP)
+ MOVB AX, r1+4(FP) // ERROR "invalid MOVB of r1\+4\(FP\); int is 4-byte value"
+ RET
diff --git a/src/cmd/vet/test_assign.go b/src/cmd/vet/test_assign.go
new file mode 100644
index 000000000..8e0f45e53
--- /dev/null
+++ b/src/cmd/vet/test_assign.go
@@ -0,0 +1,20 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the useless-assignment checker.
+
+// +build vet_test
+
+package main
+
+type ST struct {
+ x int
+}
+
+func (s *ST) SetX(x int) {
+ // Accidental self-assignment; it should be "s.x = x"
+ x = x // ERROR "self-assignment of x to x"
+ // Another mistake
+ s.x = s.x // ERROR "self-assignment of s.x to s.x"
+}
diff --git a/src/cmd/vet/test_deadcode.go b/src/cmd/vet/test_deadcode.go
new file mode 100644
index 000000000..3ded80ca2
--- /dev/null
+++ b/src/cmd/vet/test_deadcode.go
@@ -0,0 +1,2121 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build vet_test
+// +build ignore
+
+// This file contains tests for the dead code checker.
+
+package main
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+}
+
+func _() int {
+ print(1)
+}
+
+func _() int {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+ println() // ok
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ for {
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ for {
+ for {
+ break
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ for {
+ for {
+ break
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+func _() int {
+ for {
+ for {
+ continue
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+func _() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ for {
+ break
+ }
+ println() // ok
+}
+
+func _() int {
+ for {
+ for {
+ }
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ for x == nil {
+ }
+ println() // ok
+}
+
+func _() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ for true {
+ }
+ println() // ok
+}
+
+func _() int {
+ for true {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {}
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ default:
+ select {}
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select {}
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ default:
+ break
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select {}
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+ println() // ok
+}
+
+func _() int {
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ panic(2)
+ println() // ok
+}
+
+func _() int {
+ {
+ return 2
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ {
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+L:
+ {
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+func _() int {
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+func _() int {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+L:
+ goto L
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+ {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+L:
+ {
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+func _() int {
+ {
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+func _() int {
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+// again, with func literals
+
+var _ = func() int {
+}
+
+var _ = func() int {
+ print(1)
+}
+
+var _ = func() int {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ for {
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ for {
+ continue
+ println() // ERROR "unreachable code"
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ for {
+ break
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for {
+ for {
+ }
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ for x == nil {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ for true {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for true {
+ for {
+ break
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {}
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for {
+ }
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ println() // ERROR "unreachable code"
+ default:
+ select {}
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select {}
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L // ERROR "unreachable code"
+ case c <- 1:
+ print(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ default:
+ break
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for {
+ break L
+ }
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select {}
+ break // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case 1:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L // ERROR "unreachable code"
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break // ERROR "unreachable code"
+ case int:
+ print(2)
+ panic(3)
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+ println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+var _ = func() int {
+ println() // ok
+}
+
+var _ = func() int {
+ return 2
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ goto L
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ panic(2)
+ println() // ERROR "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ panic(2)
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ return 2
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ {
+ return 2
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ println() // ERROR "unreachable code"
+ }
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ println() // ERROR "unreachable code"
+}
+
+var _ = func() int {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ goto L
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ return 2
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ {
+ } // ERROR "unreachable code"
+ }
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ return 2
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ {
+ } // ERROR "unreachable code"
+ println() // ok
+}
diff --git a/src/cmd/vet/test_taglit.go b/src/cmd/vet/test_taglit.go
index 0d83b18fd..f34062f18 100644
--- a/src/cmd/vet/test_taglit.go
+++ b/src/cmd/vet/test_taglit.go
@@ -15,6 +15,40 @@ import (
"go/scanner"
)
+var Okay1 = []string{
+ "Name",
+ "Usage",
+ "DefValue",
+}
+
+var Okay2 = map[string]bool{
+ "Name": true,
+ "Usage": true,
+ "DefValue": true,
+}
+
+var Okay3 = struct {
+ X string
+ Y string
+ Z string
+}{
+ "Name",
+ "Usage",
+ "DefValue",
+}
+
+type MyStruct struct {
+ X string
+ Y string
+ Z string
+}
+
+var Okay4 = MyStruct{
+ "Name",
+ "Usage",
+ "DefValue",
+}
+
// Testing is awkward because we need to reference things from a separate package
// to trigger the warnings.
diff --git a/src/cmd/vet/types.go b/src/cmd/vet/types.go
new file mode 100644
index 000000000..75f195b0f
--- /dev/null
+++ b/src/cmd/vet/types.go
@@ -0,0 +1,179 @@
+// 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.
+
+// +build gotypes
+
+// This file contains the pieces of the tool that require the go/types package.
+// To compile this file, you must first run
+// $ go get code.google.com/p/go.exp/go/types
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+
+ "code.google.com/p/go.exp/go/types"
+)
+
+// Type is equivalent to go/types.Type. Repeating it here allows us to avoid
+// depending on the go/types package.
+type Type interface {
+ String() string
+}
+
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
+ pkg.types = make(map[ast.Expr]Type)
+ pkg.values = make(map[ast.Expr]interface{})
+ exprFn := func(x ast.Expr, typ types.Type, val interface{}) {
+ pkg.types[x] = typ
+ if val != nil {
+ pkg.values[x] = val
+ }
+ }
+ // By providing the Context with our own error function, it will continue
+ // past the first error. There is no need for that function to do anything.
+ context := types.Context{
+ Expr: exprFn,
+ Error: func(error) {},
+ }
+ _, err := context.Check(fs, astFiles)
+ return err
+}
+
+// isStruct reports whether the composite literal c is a struct.
+// If it is not (probably a struct), it returns a printable form of the type.
+func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
+ // Check that the CompositeLit's type is a slice or array (which needs no tag), if possible.
+ typ := pkg.types[c]
+ // If it's a named type, pull out the underlying type.
+ actual := typ
+ if namedType, ok := typ.(*types.NamedType); ok {
+ actual = namedType.Underlying
+ }
+ if actual == nil {
+ // No type information available. Assume true, so we do the check.
+ return true, ""
+ }
+ switch actual.(type) {
+ case *types.Struct:
+ return true, typ.String()
+ default:
+ return false, ""
+ }
+}
+
+func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
+ // TODO: for now, we can only test builtin types and untyped constants.
+ typ := f.pkg.types[arg]
+ if typ == nil {
+ return true
+ }
+ basic, ok := typ.(*types.Basic)
+ if !ok {
+ return true
+ }
+ switch basic.Kind {
+ case types.Bool:
+ return t&argBool != 0
+ case types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
+ fallthrough
+ case types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64, types.Uintptr:
+ return t&argInt != 0
+ case types.Float32, types.Float64, types.Complex64, types.Complex128:
+ return t&argFloat != 0
+ case types.String:
+ return t&argString != 0
+ case types.UnsafePointer:
+ return t&(argPointer|argInt) != 0
+ case types.UntypedBool:
+ return t&argBool != 0
+ case types.UntypedComplex:
+ return t&argFloat != 0
+ case types.UntypedFloat:
+ // If it's integral, we can use an int format.
+ switch f.pkg.values[arg].(type) {
+ case int, int8, int16, int32, int64:
+ return t&(argInt|argFloat) != 0
+ case uint, uint8, uint16, uint32, uint64:
+ return t&(argInt|argFloat) != 0
+ }
+ return t&argFloat != 0
+ case types.UntypedInt:
+ return t&argInt != 0
+ case types.UntypedRune:
+ return t&(argInt|argRune) != 0
+ case types.UntypedString:
+ return t&argString != 0
+ case types.UntypedNil:
+ return t&argPointer != 0 // TODO?
+ case types.Invalid:
+ if *verbose {
+ f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", arg)
+ }
+ return true // Probably a type check problem.
+ }
+ return false
+}
+
+// numArgsInSignature tells how many formal arguments the function type
+// being called has.
+func (f *File) numArgsInSignature(call *ast.CallExpr) int {
+ // Check the type of the function or method declaration
+ typ := f.pkg.types[call.Fun]
+ if typ == nil {
+ return 0
+ }
+ // The type must be a signature, but be sure for safety.
+ sig, ok := typ.(*types.Signature)
+ if !ok {
+ return 0
+ }
+ return len(sig.Params)
+}
+
+// isErrorMethodCall reports whether the call is of a method with signature
+// func Error() string
+// where "string" is the universe's string type. We know the method is called "Error".
+func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
+ // Is it a selector expression? Otherwise it's a function call, not a method call.
+ sel, ok := call.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return false
+ }
+ // The package is type-checked, so if there are no arguments, we're done.
+ if len(call.Args) > 0 {
+ return false
+ }
+ // Check the type of the method declaration
+ typ := f.pkg.types[sel]
+ if typ == nil {
+ return false
+ }
+ // The type must be a signature, but be sure for safety.
+ sig, ok := typ.(*types.Signature)
+ if !ok {
+ return false
+ }
+ // There must be a receiver for it to be a method call. Otherwise it is
+ // a function, not something that satisfies the error interface.
+ if sig.Recv == nil {
+ return false
+ }
+ // There must be no arguments. Already verified by type checking, but be thorough.
+ if len(sig.Params) > 0 {
+ return false
+ }
+ // Finally the real questions.
+ // There must be one result.
+ if len(sig.Results) != 1 {
+ return false
+ }
+ // It must have return type "string" from the universe.
+ result := sig.Results[0].Type
+ if types.IsIdentical(result, types.Typ[types.String]) {
+ return true
+ }
+ return false
+}
diff --git a/src/cmd/vet/typestub.go b/src/cmd/vet/typestub.go
new file mode 100644
index 000000000..fabbbe19d
--- /dev/null
+++ b/src/cmd/vet/typestub.go
@@ -0,0 +1,45 @@
+// 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.
+
+// +build !gotypes
+
+// This file contains stubs for the pieces of the tool that require the go/types package,
+// to be used if go/types is not available.
+
+package main
+
+import (
+ "go/ast"
+ "go/token"
+)
+
+// Type is equivalent to go/types.Type. Repeating it here allows us to avoid
+// depending on the go/types package.
+type Type interface {
+ String() string
+}
+
+func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
+ return nil
+}
+
+func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
+ return true, "" // Assume true, so we do the check.
+}
+
+func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
+ return true // We can't tell without types.
+}
+
+func (f *File) numArgsInSignature(call *ast.CallExpr) int {
+ return 0 // We don't know.
+}
+
+func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
+ // Is it a selector expression? Otherwise it's a function call, not a method call.
+ if _, ok := call.Fun.(*ast.SelectorExpr); !ok {
+ return false
+ }
+ return true // Best guess we can make without types.
+}
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index 0c18f93b6..76b3aeac5 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -3164,7 +3164,6 @@ func ungetrune(f *bufio.Reader, c rune) {
func write(f *bufio.Writer, b []byte, n int) int {
panic("write")
- return 0
}
func open(s string) *bufio.Reader {
diff --git a/src/lib9/run_plan9.c b/src/lib9/run_plan9.c
new file mode 100644
index 000000000..2b043cc2c
--- /dev/null
+++ b/src/lib9/run_plan9.c
@@ -0,0 +1,38 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <libc.h>
+
+int
+runcmd(char **argv)
+{
+ int pid;
+ Waitmsg *w;
+
+ switch(pid = fork()) {
+ case -1:
+ return -1;
+ case 0:
+ exec(argv[0], argv);
+ fprint(2, "exec %s: %r", argv[0]);
+ exits("exec");
+ }
+
+ w = wait();
+ if(w == nil)
+ return -1;
+ if(w->pid != pid) {
+ werrstr("unexpected pid in wait");
+ free(w);
+ return -1;
+ }
+ if(w->msg[0]) {
+ werrstr("unsuccessful exit status: %s", w->msg);
+ free(w);
+ return -1;
+ }
+ free(w);
+ return 0;
+}
diff --git a/src/lib9/run_unix.c b/src/lib9/run_unix.c
new file mode 100644
index 000000000..1b4c6de1b
--- /dev/null
+++ b/src/lib9/run_unix.c
@@ -0,0 +1,43 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+#include <u.h>
+#include <errno.h>
+#include <sys/wait.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+int
+runcmd(char **argv)
+{
+ int pid, pid1, status;
+
+ switch(pid = fork()) {
+ case -1:
+ return -1;
+ case 0:
+ execvp(argv[0], argv);
+ fprint(2, "exec %s: %r", argv[0]);
+ _exit(1);
+ }
+
+ while((pid1 = wait(&status)) < 0) {
+ if(errno != EINTR) {
+ werrstr("waitpid: %r");
+ return -1;
+ }
+ }
+ if(pid1 != pid) {
+ werrstr("unexpected pid in wait");
+ return -1;
+ }
+ if(!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ werrstr("unsuccessful exit status %#x", status);
+ return -1;
+ }
+ return 0;
+}
+
diff --git a/src/lib9/run_windows.c b/src/lib9/run_windows.c
new file mode 100644
index 000000000..87875b42d
--- /dev/null
+++ b/src/lib9/run_windows.c
@@ -0,0 +1,83 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <windows.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+#include "win.h"
+
+int
+runcmd(char **argv)
+{
+ // Mostly copied from ../cmd/dist/windows.c.
+ // If there's a bug here, fix the logic there too.
+ int i, j, nslash;
+ Fmt fmt;
+ char *q;
+ WinRune *r;
+ STARTUPINFOW si;
+ PROCESS_INFORMATION pi;
+ DWORD code;
+
+ fmtstrinit(&fmt);
+ for(i=0; argv[i]; i++) {
+ if(i > 0)
+ fmtprint(&fmt, " ");
+ q = argv[i];
+ if(strstr(q, " ") || strstr(q, "\t") || strstr(q, "\"") || strstr(q, "\\\\") || (strlen(q) > 0 && q[strlen(q)-1] == '\\')) {
+ fmtprint(&fmt, "\"");
+ nslash = 0;
+ for(; *q; q++) {
+ if(*q == '\\') {
+ nslash++;
+ continue;
+ }
+ if(*q == '"') {
+ for(j=0; j<2*nslash+1; j++)
+ fmtprint(&fmt, "\\");
+ nslash = 0;
+ }
+ for(j=0; j<nslash; j++)
+ fmtprint(&fmt, "\\");
+ nslash = 0;
+ fmtprint(&fmt, "\"");
+ }
+ for(j=0; j<2*nslash; j++)
+ fmtprint(&fmt, "\\");
+ fmtprint(&fmt, "\"");
+ } else {
+ fmtprint(&fmt, "%s", q);
+ }
+ }
+
+ q = fmtstrflush(&fmt);
+ r = torune(q);
+ free(q);
+
+ memset(&si, 0, sizeof si);
+ si.cb = sizeof si;
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+
+ if(!CreateProcessW(nil, r, nil, nil, TRUE, 0, nil, nil, &si, &pi)) {
+ free(r);
+ return -1;
+ }
+
+ free(r);
+ if(WaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE) != 0)
+ return -1;
+ i = GetExitCodeProcess(pi.hProcess, &code);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ if(!i)
+ return -1;
+ if(code != 0) {
+ werrstr("unsuccessful exit status: %d", (int)code);
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/lib9/tempdir_plan9.c b/src/lib9/tempdir_plan9.c
new file mode 100644
index 000000000..092d00d16
--- /dev/null
+++ b/src/lib9/tempdir_plan9.c
@@ -0,0 +1,54 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <libc.h>
+
+char*
+mktempdir(void)
+{
+ char *p;
+ int fd, i;
+
+ p = smprint("/tmp/go-link-XXXXXX");
+ for(i=0; i<1000; i++) {
+ sprint(p, "/tmp/go-link-%06x", nrand((1<<24)-1));
+ fd = create(p, OREAD|OEXCL, 0700|DMDIR);
+ if(fd >= 0) {
+ close(fd);
+ return p;
+ }
+ }
+ free(p);
+ return nil;
+}
+
+void
+removeall(char *p)
+{
+ int fd, n, i;
+ Dir *d;
+ char *q;
+
+ if(remove(p) >= 0)
+ return;
+ if((d = dirstat(p)) == nil)
+ return;
+ if(!(d->mode & DMDIR)) {
+ free(d);
+ return;
+ }
+ free(d);
+
+ if((fd = open(p, OREAD)) < 0)
+ return;
+ n = dirreadall(fd, &d);
+ close(fd);
+ for(i=0; i<n; i++) {
+ q = smprint("%s/%s", p, d[i].name);
+ removeall(q);
+ free(q);
+ }
+ free(d);
+}
diff --git a/src/lib9/tempdir_unix.c b/src/lib9/tempdir_unix.c
new file mode 100644
index 000000000..7b7e58b4d
--- /dev/null
+++ b/src/lib9/tempdir_unix.c
@@ -0,0 +1,52 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+#include <u.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#define NOPLAN9DEFINES
+#include <libc.h>
+
+char*
+mktempdir(void)
+{
+ char *tmp, *p;
+
+ tmp = getenv("TMPDIR");
+ if(tmp == nil)
+ tmp = "/var/tmp";
+ p = smprint("%s/go-link-XXXXXX", tmp);
+ if(mkdtemp(p) == nil)
+ return nil;
+ return p;
+}
+
+void
+removeall(char *p)
+{
+ DIR *d;
+ struct dirent *dp;
+ char *q;
+ struct stat st;
+
+ if(stat(p, &st) < 0)
+ return;
+ if(!S_ISDIR(st.st_mode)) {
+ unlink(p);
+ return;
+ }
+
+ d = opendir(p);
+ while((dp = readdir(d)) != nil) {
+ if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+ continue;
+ q = smprint("%s/%s", p, dp->d_name);
+ removeall(q);
+ free(q);
+ }
+ closedir(d);
+ rmdir(p);
+}
diff --git a/src/lib9/tempdir_windows.c b/src/lib9/tempdir_windows.c
new file mode 100644
index 000000000..1a530059a
--- /dev/null
+++ b/src/lib9/tempdir_windows.c
@@ -0,0 +1,110 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <u.h>
+#include <windows.h>
+#include <libc.h>
+#include "win.h"
+
+char*
+toutf(WinRune *r)
+{
+ Rune *r1;
+ int i, n;
+ char *p;
+
+ n = 0;
+ while(r[n] != '\0')
+ n++;
+ n++;
+ r1 = malloc(n*sizeof r1[0]);
+ for(i=0; i<n; i++)
+ r1[i] = r[i];
+ p = smprint("%S", r1);
+ free(r1);
+ return p;
+}
+
+WinRune*
+torune(char *p)
+{
+ int i, n;
+ Rune rr;
+ WinRune *r;
+
+ n = utflen(p);
+ r = malloc((n+1)*sizeof r[0]);
+ for(i=0; i<n; i++) {
+ p += chartorune(&rr, p);
+ r[i] = rr;
+ }
+ r[n] = '\0';
+ return r;
+}
+
+char*
+mktempdir(void)
+{
+ WinRune buf[1024];
+ WinRune tmp[MAX_PATH];
+ WinRune golink[] = {'g', 'o', 'l', 'i', 'n', 'k', '\0'};
+ int n;
+
+ n = GetTempPathW(nelem(buf), buf);
+ if(n <= 0)
+ return nil;
+ buf[n] = '\0';
+
+ if(GetTempFileNameW(buf, golink, 0, tmp) == 0)
+ return nil;
+ DeleteFileW(tmp);
+ if(!CreateDirectoryW(tmp, nil))
+ return nil;
+
+ return toutf(tmp);
+}
+
+void
+removeall(char *p)
+{
+ WinRune *r, *r1;
+ DWORD attr;
+ char *q, *elem;
+ HANDLE h;
+ WIN32_FIND_DATAW data;
+
+ r = torune(p);
+ attr = GetFileAttributesW(r);
+ if(attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
+ DeleteFileW(r);
+ free(r);
+ return;
+ }
+
+ q = smprint("%s\\*", p);
+ r1 = torune(q);
+ free(q);
+ h = FindFirstFileW(r1, &data);
+ if(h == INVALID_HANDLE_VALUE)
+ goto done;
+ do{
+ q = toutf(data.cFileName);
+ elem = strrchr(q, '\\');
+ if(elem != nil) {
+ elem++;
+ if(strcmp(elem, ".") == 0 || strcmp(elem, "..") == 0) {
+ free(q);
+ continue;
+ }
+ }
+ removeall(q);
+ free(q);
+ }while(FindNextFileW(h, &data));
+ FindClose(h);
+
+done:
+ free(r1);
+ RemoveDirectoryW(r);
+ free(r);
+}
diff --git a/src/lib9/win.h b/src/lib9/win.h
new file mode 100644
index 000000000..d9df319af
--- /dev/null
+++ b/src/lib9/win.h
@@ -0,0 +1,8 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+typedef unsigned short WinRune;
+
+WinRune* torune(char*);
+char *toutf(WinRune*);
diff --git a/src/libmach/executable.c b/src/libmach/executable.c
index a93a8c268..91c0cbe76 100644
--- a/src/libmach/executable.c
+++ b/src/libmach/executable.c
@@ -1030,8 +1030,8 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
uvlong textsize, datasize, bsssize;
uchar *cmdbuf;
uchar *cmdp;
- int i, hdrsize;
- uint32 textva, textoff, datava, dataoff;
+ int i, j, hdrsize;
+ uint32 textva, textoff, datava, dataoff, symoff, symsize, pclnoff, pclnsize;
mp = &hp->e.machhdr;
if (leswal(mp->filetype) != MACH_EXECUTABLE_TYPE) {
@@ -1116,6 +1116,10 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
textsize = 0;
datasize = 0;
bsssize = 0;
+ symoff = 0;
+ symsize = 0;
+ pclnoff = 0;
+ pclnsize = 0;
for (i = 0; i < mp->ncmds; i++) {
MachCmd *c;
@@ -1141,33 +1145,24 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
if (strcmp(seg32->segname, "__TEXT") == 0) {
textva = seg32->vmaddr;
textoff = seg32->fileoff;
+ textsize = seg32->vmsize;
sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
- if (strcmp(sect32->sectname, "__text") == 0) {
- textsize = swal(sect32->size);
- } else {
- werrstr("no text section");
- goto bad;
+ for(j = 0; j < seg32->nsects; j++, sect32++) {
+ if (strcmp(sect32->sectname, "__gosymtab") == 0) {
+ symoff = swal(sect32->offset);
+ symsize = swal(sect32->size);
+ }
+ if (strcmp(sect32->sectname, "__gopclntab") == 0) {
+ pclnoff = swal(sect32->offset);
+ pclnsize = swal(sect32->size);
+ }
}
}
if (strcmp(seg32->segname, "__DATA") == 0) {
datava = seg32->vmaddr;
dataoff = seg32->fileoff;
- sect32 = (MachSect32*)(cmdp + sizeof(MachSeg32));
- if (strcmp(sect32->sectname, "__data") == 0) {
- datasize = swal(sect32->size);
- } else {
- werrstr("no data section");
- goto bad;
- }
- sect32++;
- if (strcmp(sect32->sectname, "__nl_symbol_ptr") == 0)
- sect32++;
- if (strcmp(sect32->sectname, "__bss") == 0) {
- bsssize = swal(sect32->size);
- } else {
- werrstr("no bss section");
- goto bad;
- }
+ datasize = seg32->filesize;
+ bsssize = seg32->vmsize - seg32->filesize;
}
break;
@@ -1188,42 +1183,38 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
if (strcmp(seg->segname, "__TEXT") == 0) {
textva = seg->vmaddr;
textoff = seg->fileoff;
+ textsize = seg->vmsize;
sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
- if (strcmp(sect->sectname, "__text") == 0) {
- textsize = swav(sect->size);
- } else {
- werrstr("no text section");
- goto bad;
+ for(j = 0; j < seg->nsects; j++, sect++) {
+ if (strcmp(sect->sectname, "__gosymtab") == 0) {
+ symoff = swal(sect->offset);
+ symsize = swal(sect->size);
+ }
+ if (strcmp(sect->sectname, "__gopclntab") == 0) {
+ pclnoff = swal(sect->offset);
+ pclnsize = swal(sect->size);
+ }
}
}
if (strcmp(seg->segname, "__DATA") == 0) {
datava = seg->vmaddr;
dataoff = seg->fileoff;
- sect = (MachSect64*)(cmdp + sizeof(MachSeg64));
- if (strcmp(sect->sectname, "__data") == 0) {
- datasize = swav(sect->size);
- } else {
- werrstr("no data section");
- goto bad;
- }
- sect++;
- if (strcmp(sect->sectname, "__nl_symbol_ptr") == 0)
- sect++;
- if (strcmp(sect->sectname, "__bss") == 0) {
- bsssize = swav(sect->size);
- } else {
- werrstr("no bss section");
- goto bad;
- }
+ datasize = seg->filesize;
+ bsssize = seg->vmsize - seg->filesize;
}
break;
case MACH_UNIXTHREAD:
break;
case MACH_SYMSEG:
- if (symtab == 0)
+ if (symtab == 0) {
symtab = (MachSymSeg*)c;
- else if (pclntab == 0)
+ symoff = swal(symtab->fileoff);
+ symsize = swal(symtab->filesize);
+ } else if (pclntab == 0) {
pclntab = (MachSymSeg*)c;
+ pclnoff = swal(pclntab->fileoff);
+ pclnsize = swal(pclntab->filesize);
+ }
break;
}
cmdp += c->size;
@@ -1236,8 +1227,8 @@ machdotout(int fd, Fhdr *fp, ExecHdr *hp)
/* compute entry by taking address after header - weird - BUG? */
settext(fp, textva+sizeof(Machhdr) + mp->sizeofcmds, textva, textsize, textoff);
setdata(fp, datava, datasize, dataoff, bsssize);
- if(symtab != 0)
- setsym(fp, symtab->fileoff, symtab->filesize, 0, 0, 0, pclntab? pclntab->filesize : 0);
+ if(symoff > 0)
+ setsym(fp, symoff, symsize, 0, 0, pclnoff, pclnsize);
free(cmd);
free(cmdbuf);
return 1;
@@ -1335,13 +1326,45 @@ typedef struct {
IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER;
+typedef struct {
+ uint16 Magic;
+ uint8 MajorLinkerVersion;
+ uint8 MinorLinkerVersion;
+ uint32 SizeOfCode;
+ uint32 SizeOfInitializedData;
+ uint32 SizeOfUninitializedData;
+ uint32 AddressOfEntryPoint;
+ uint32 BaseOfCode;
+ uint64 ImageBase;
+ uint32 SectionAlignment;
+ uint32 FileAlignment;
+ uint16 MajorOperatingSystemVersion;
+ uint16 MinorOperatingSystemVersion;
+ uint16 MajorImageVersion;
+ uint16 MinorImageVersion;
+ uint16 MajorSubsystemVersion;
+ uint16 MinorSubsystemVersion;
+ uint32 Win32VersionValue;
+ uint32 SizeOfImage;
+ uint32 SizeOfHeaders;
+ uint32 CheckSum;
+ uint16 Subsystem;
+ uint16 DllCharacteristics;
+ uint64 SizeOfStackReserve;
+ uint64 SizeOfStackCommit;
+ uint64 SizeOfHeapReserve;
+ uint64 SizeOfHeapCommit;
+ uint32 LoaderFlags;
+ uint32 NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[16];
+} PE64_IMAGE_OPTIONAL_HEADER;
+
static int
match8(void *buf, char *cmp)
{
return strncmp((char*)buf, cmp, 8) == 0;
}
-/* TODO(czaplinski): 64b windows? */
/*
* Read from Windows PE/COFF .exe file image.
*/
@@ -1353,9 +1376,10 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
IMAGE_FILE_HEADER fh;
IMAGE_SECTION_HEADER sh;
IMAGE_OPTIONAL_HEADER oh;
+ PE64_IMAGE_OPTIONAL_HEADER oh64;
uint8 sym[18];
- uint32 *valp, ib;
- int i;
+ uint32 *valp, ib, entry;
+ int i, ohoffset;
USED(hp);
seek(fd, 0x3c, 0);
@@ -1384,6 +1408,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
return 0;
}
+ ohoffset = seek(fd, 0, 1);
if (readn(fd, &oh, sizeof(oh)) != sizeof(oh)) {
werrstr("crippled PE Optional Header");
return 0;
@@ -1392,17 +1417,24 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
switch(oh.Magic) {
case 0x10b: // PE32
fp->type = FI386;
+ ib = leswal(oh.ImageBase);
+ entry = leswal(oh.AddressOfEntryPoint);
break;
case 0x20b: // PE32+
fp->type = FAMD64;
+ seek(fd, ohoffset, 0);
+ if (readn(fd, &oh64, sizeof(oh64)) != sizeof(oh64)) {
+ werrstr("crippled PE32+ Optional Header");
+ return 0;
+ }
+ ib = leswal(oh64.ImageBase);
+ entry = leswal(oh64.AddressOfEntryPoint);
break;
default:
- werrstr("invalid PE Optional magic number");
+ werrstr("invalid PE Optional Header magic number");
return 0;
}
- ib=leswal(oh.ImageBase);
- seek(fd, start+sizeof(magic)+sizeof(fh)+leswab(fh.SizeOfOptionalHeader), 0);
fp->txtaddr = 0;
fp->dataddr = 0;
for (i=0; i<leswab(fh.NumberOfSections); i++) {
@@ -1411,7 +1443,7 @@ pedotout(int fd, Fhdr *fp, ExecHdr *hp)
return 0;
}
if (match8(sh.Name, ".text"))
- settext(fp, ib+leswal(oh.AddressOfEntryPoint), ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
+ settext(fp, ib+entry, ib+leswal(sh.VirtualAddress), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
if (match8(sh.Name, ".data"))
setdata(fp, ib+leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
}
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go
index ee69c2d31..df3501f2c 100644
--- a/src/pkg/bufio/bufio.go
+++ b/src/pkg/bufio/bufio.go
@@ -274,7 +274,6 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
return b.buf, ErrBufferFull
}
}
- panic("not reached")
}
// ReadLine is a low-level line-reading primitive. Most callers should use
diff --git a/src/pkg/bufio/bufio_test.go b/src/pkg/bufio/bufio_test.go
index b0e811443..79ed0f178 100644
--- a/src/pkg/bufio/bufio_test.go
+++ b/src/pkg/bufio/bufio_test.go
@@ -7,6 +7,7 @@ package bufio_test
import (
. "bufio"
"bytes"
+ "errors"
"fmt"
"io"
"io/ioutil"
@@ -434,9 +435,12 @@ func TestWriteErrors(t *testing.T) {
t.Errorf("Write hello to %v: %v", w, e)
continue
}
- e = buf.Flush()
- if e != w.expect {
- t.Errorf("Flush %v: got %v, wanted %v", w, e, w.expect)
+ // Two flushes, to verify the error is sticky.
+ for i := 0; i < 2; i++ {
+ e = buf.Flush()
+ if e != w.expect {
+ t.Errorf("Flush %d/2 %v: got %v, wanted %v", i+1, w, e, w.expect)
+ }
}
}
}
@@ -962,6 +966,43 @@ func TestNegativeRead(t *testing.T) {
b.Read(make([]byte, 100))
}
+var errFake = errors.New("fake error")
+
+type errorThenGoodReader struct {
+ didErr bool
+ nread int
+}
+
+func (r *errorThenGoodReader) Read(p []byte) (int, error) {
+ r.nread++
+ if !r.didErr {
+ r.didErr = true
+ return 0, errFake
+ }
+ return len(p), nil
+}
+
+func TestReaderClearError(t *testing.T) {
+ r := &errorThenGoodReader{}
+ b := NewReader(r)
+ buf := make([]byte, 1)
+ if _, err := b.Read(nil); err != nil {
+ t.Fatalf("1st nil Read = %v; want nil", err)
+ }
+ if _, err := b.Read(buf); err != errFake {
+ t.Fatalf("1st Read = %v; want errFake", err)
+ }
+ if _, err := b.Read(nil); err != nil {
+ t.Fatalf("2nd nil Read = %v; want nil", err)
+ }
+ if _, err := b.Read(buf); err != nil {
+ t.Fatalf("3rd Read with buffer = %v; want nil", err)
+ }
+ if r.nread != 2 {
+ t.Errorf("num reads = %d; want 2", r.nread)
+ }
+}
+
// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
type onlyReader struct {
r io.Reader
diff --git a/src/pkg/bufio/example_test.go b/src/pkg/bufio/example_test.go
index b545ce39a..08a39441e 100644
--- a/src/pkg/bufio/example_test.go
+++ b/src/pkg/bufio/example_test.go
@@ -19,7 +19,7 @@ func ExampleScanner_lines() {
fmt.Println(scanner.Text()) // Println will add back the final '\n'
}
if err := scanner.Err(); err != nil {
- fmt.Fprintln(os.Stdout, "reading standard input:", err)
+ fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
}
@@ -37,7 +37,7 @@ func ExampleScanner_words() {
count++
}
if err := scanner.Err(); err != nil {
- fmt.Fprintln(os.Stdout, "reading input:", err)
+ fmt.Fprintln(os.Stderr, "reading input:", err)
}
fmt.Printf("%d\n", count)
// Output: 15
diff --git a/src/pkg/bufio/scan.go b/src/pkg/bufio/scan.go
index 268ce6d1d..d94f7f9ad 100644
--- a/src/pkg/bufio/scan.go
+++ b/src/pkg/bufio/scan.go
@@ -27,8 +27,6 @@ import (
// control over error handling or large tokens, or must run sequential scans
// on a reader, should use bufio.Reader instead.
//
-// TODO(r): Provide executable examples.
-//
type Scanner struct {
r io.Reader // The reader provided by the client.
split SplitFunc // The function to split the tokens.
@@ -169,7 +167,6 @@ func (s *Scanner) Scan() bool {
}
s.end += n
}
- panic("not reached")
}
// advance consumes n bytes of the buffer. It reports whether the advance was legal.
diff --git a/src/pkg/bytes/asm_386.s b/src/pkg/bytes/asm_386.s
index c444b55e1..997738fe2 100644
--- a/src/pkg/bytes/asm_386.s
+++ b/src/pkg/bytes/asm_386.s
@@ -4,21 +4,21 @@
TEXT ·IndexByte(SB),7,$0
MOVL s+0(FP), SI
- MOVL s+4(FP), CX
+ MOVL s_len+4(FP), CX
MOVB c+12(FP), AL
MOVL SI, DI
CLD; REPN; SCASB
JZ 3(PC)
- MOVL $-1, r+16(FP)
+ MOVL $-1, ret+16(FP)
RET
SUBL SI, DI
SUBL $1, DI
- MOVL DI, r+16(FP)
+ MOVL DI, ret+16(FP)
RET
TEXT ·Equal(SB),7,$0
- MOVL a+4(FP), BX
- MOVL b+16(FP), CX
+ MOVL a_len+4(FP), BX
+ MOVL b_len+16(FP), CX
MOVL $0, AX
CMPL BX, CX
JNE eqret
@@ -29,5 +29,5 @@ TEXT ·Equal(SB),7,$0
JNE eqret
MOVL $1, AX
eqret:
- MOVB AX, r+24(FP)
+ MOVB AX, ret+24(FP)
RET
diff --git a/src/pkg/bytes/asm_amd64.s b/src/pkg/bytes/asm_amd64.s
index 482422642..b8f9f1b81 100644
--- a/src/pkg/bytes/asm_amd64.s
+++ b/src/pkg/bytes/asm_amd64.s
@@ -4,7 +4,7 @@
TEXT ·IndexByte(SB),7,$0
MOVQ s+0(FP), SI
- MOVQ s+8(FP), BX
+ MOVQ s_len+8(FP), BX
MOVB c+24(FP), AL
MOVQ SI, DI
@@ -63,7 +63,7 @@ condition:
JZ success
failure:
- MOVQ $-1, r+32(FP)
+ MOVQ $-1, ret+32(FP)
RET
// handle for lengths < 16
@@ -71,7 +71,7 @@ small:
MOVQ BX, CX
REPN; SCASB
JZ success
- MOVQ $-1, r+32(FP)
+ MOVQ $-1, ret+32(FP)
RET
// we've found the chunk containing the byte
@@ -81,18 +81,18 @@ ssesuccess:
BSFW DX, DX
SUBQ SI, DI
ADDQ DI, DX
- MOVQ DX, r+32(FP)
+ MOVQ DX, ret+32(FP)
RET
success:
SUBQ SI, DI
SUBL $1, DI
- MOVQ DI, r+32(FP)
+ MOVQ DI, ret+32(FP)
RET
TEXT ·Equal(SB),7,$0
- MOVQ a+8(FP), BX
- MOVQ b+32(FP), CX
+ MOVQ a_len+8(FP), BX
+ MOVQ b_len+32(FP), CX
MOVL $0, AX
CMPQ BX, CX
JNE eqret
@@ -103,6 +103,6 @@ TEXT ·Equal(SB),7,$0
MOVL $1, DX
CMOVLEQ DX, AX
eqret:
- MOVB AX, r+48(FP)
+ MOVB AX, ret+48(FP)
RET
diff --git a/src/pkg/bytes/asm_arm.s b/src/pkg/bytes/asm_arm.s
index c7685f041..2e9f805a4 100644
--- a/src/pkg/bytes/asm_arm.s
+++ b/src/pkg/bytes/asm_arm.s
@@ -4,7 +4,7 @@
TEXT ·IndexByte(SB),7,$0
MOVW s+0(FP), R0
- MOVW s+4(FP), R1
+ MOVW s_len+4(FP), R1
MOVBU c+12(FP), R2 // byte to find
MOVW R0, R4 // store base for later
ADD R0, R1 // end
@@ -18,17 +18,17 @@ _loop:
SUB $1, R0 // R0 will be one beyond the position we want
SUB R4, R0 // remove base
- MOVW R0, r+16(FP)
+ MOVW R0, ret+16(FP)
RET
_notfound:
MOVW $-1, R0
- MOVW R0, r+16(FP)
+ MOVW R0, ret+16(FP)
RET
TEXT ·Equal(SB),7,$0
- MOVW a+4(FP), R1
- MOVW b+16(FP), R3
+ MOVW a_len+4(FP), R1
+ MOVW b_len+16(FP), R3
CMP R1, R3 // unequal lengths are not equal
B.NE _notequal
@@ -47,10 +47,10 @@ _next:
_notequal:
MOVW $0, R0
- MOVBU R0, r+24(FP)
+ MOVBU R0, ret+24(FP)
RET
_equal:
MOVW $1, R0
- MOVBU R0, r+24(FP)
+ MOVBU R0, ret+24(FP)
RET
diff --git a/src/pkg/bytes/bytes.go b/src/pkg/bytes/bytes.go
index 3bab65ef9..e42f74439 100644
--- a/src/pkg/bytes/bytes.go
+++ b/src/pkg/bytes/bytes.go
@@ -461,10 +461,10 @@ func isSeparator(r rune) bool {
return unicode.IsSpace(r)
}
-// BUG(r): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
-
// Title returns a copy of s with all Unicode letters that begin words
// mapped to their title case.
+//
+// BUG: The rule Title uses for word boundaries does not handle Unicode punctuation properly.
func Title(s []byte) []byte {
// Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling
diff --git a/src/pkg/compress/bzip2/huffman.go b/src/pkg/compress/bzip2/huffman.go
index 078c1cb89..f755019bb 100644
--- a/src/pkg/compress/bzip2/huffman.go
+++ b/src/pkg/compress/bzip2/huffman.go
@@ -54,8 +54,6 @@ func (t huffmanTree) Decode(br *bitReader) (v uint16) {
nodeIndex = node.right
}
}
-
- panic("unreachable")
}
// newHuffmanTree builds a Huffman tree from a slice containing the code
diff --git a/src/pkg/compress/flate/deflate_test.go b/src/pkg/compress/flate/deflate_test.go
index 8f4e196b4..8c4a6d6b3 100644
--- a/src/pkg/compress/flate/deflate_test.go
+++ b/src/pkg/compress/flate/deflate_test.go
@@ -158,7 +158,6 @@ func (b *syncBuffer) Read(p []byte) (n int, err error) {
}
<-b.ready
}
- panic("unreachable")
}
func (b *syncBuffer) signal() {
diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go
index a8d646019..beca34b4d 100644
--- a/src/pkg/compress/flate/inflate.go
+++ b/src/pkg/compress/flate/inflate.go
@@ -263,7 +263,6 @@ func (f *decompressor) Read(b []byte) (int, error) {
}
f.step(f)
}
- panic("unreachable")
}
func (f *decompressor) Close() error {
@@ -495,7 +494,6 @@ func (f *decompressor) huffmanBlock() {
return
}
}
- panic("unreached")
}
// copyHist copies f.copyLen bytes from f.hist (f.copyDist bytes ago) to itself.
@@ -642,7 +640,6 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) {
return int(chunk >> huffmanValueShift), nil
}
}
- return 0, CorruptInputError(f.roffset)
}
// Flush any buffered output to the underlying writer.
diff --git a/src/pkg/compress/flate/token.go b/src/pkg/compress/flate/token.go
index 38aea5fa6..4d4917687 100644
--- a/src/pkg/compress/flate/token.go
+++ b/src/pkg/compress/flate/token.go
@@ -99,5 +99,4 @@ func offsetCode(off uint32) uint32 {
default:
return offsetCodes[off>>14] + 28
}
- panic("unreachable")
}
diff --git a/src/pkg/compress/gzip/gunzip.go b/src/pkg/compress/gzip/gunzip.go
index 33736f635..1fb9b0964 100644
--- a/src/pkg/compress/gzip/gunzip.go
+++ b/src/pkg/compress/gzip/gunzip.go
@@ -120,7 +120,6 @@ func (z *Reader) readString() (string, error) {
return string(z.buf[0:i]), nil
}
}
- panic("not reached")
}
func (z *Reader) read2() (uint32, error) {
diff --git a/src/pkg/compress/lzw/reader.go b/src/pkg/compress/lzw/reader.go
index 0ed742c89..efbc758f9 100644
--- a/src/pkg/compress/lzw/reader.go
+++ b/src/pkg/compress/lzw/reader.go
@@ -121,7 +121,6 @@ func (d *decoder) Read(b []byte) (int, error) {
}
d.decode()
}
- panic("unreachable")
}
// decode decompresses bytes from r and leaves them in d.toRead.
@@ -203,7 +202,6 @@ func (d *decoder) decode() {
return
}
}
- panic("unreachable")
}
func (d *decoder) flush() {
diff --git a/src/pkg/crypto/cipher/example_test.go b/src/pkg/crypto/cipher/example_test.go
index e0027cac2..373f6791b 100644
--- a/src/pkg/crypto/cipher/example_test.go
+++ b/src/pkg/crypto/cipher/example_test.go
@@ -233,7 +233,7 @@ func ExampleStreamReader() {
}
defer outFile.Close()
- reader := &cipher.StreamReader{stream, inFile}
+ reader := &cipher.StreamReader{S: stream, R: inFile}
// Copy the input file to the output file, decrypting as we go.
if _, err := io.Copy(outFile, reader); err != nil {
panic(err)
@@ -270,7 +270,7 @@ func ExampleStreamWriter() {
}
defer outFile.Close()
- writer := &cipher.StreamWriter{stream, outFile, nil}
+ writer := &cipher.StreamWriter{S: stream, W: outFile}
// Copy the input file to the output file, encrypting as we go.
if _, err := io.Copy(writer, inFile); err != nil {
panic(err)
diff --git a/src/pkg/crypto/dsa/dsa.go b/src/pkg/crypto/dsa/dsa.go
index 05766a2f1..5a2a65744 100644
--- a/src/pkg/crypto/dsa/dsa.go
+++ b/src/pkg/crypto/dsa/dsa.go
@@ -144,8 +144,6 @@ GeneratePrimes:
params.G = g
return
}
-
- panic("unreachable")
}
// GenerateKey generates a public&private key pair. The Parameters of the
diff --git a/src/pkg/crypto/dsa/dsa_test.go b/src/pkg/crypto/dsa/dsa_test.go
index 177aa444d..568416d0d 100644
--- a/src/pkg/crypto/dsa/dsa_test.go
+++ b/src/pkg/crypto/dsa/dsa_test.go
@@ -63,8 +63,9 @@ func testParameterGeneration(t *testing.T, sizes ParameterSizes, L, N int) {
}
func TestParameterGeneration(t *testing.T) {
- // This test is too slow to run all the time.
- return
+ if testing.Short() {
+ t.Skip("skipping parameter generation test in short mode")
+ }
testParameterGeneration(t, L1024N160, 1024, 160)
testParameterGeneration(t, L2048N224, 2048, 224)
diff --git a/src/pkg/crypto/md5/gen.go b/src/pkg/crypto/md5/gen.go
index 966bdae26..275b4aeea 100644
--- a/src/pkg/crypto/md5/gen.go
+++ b/src/pkg/crypto/md5/gen.go
@@ -161,6 +161,11 @@ var data = Data{
}
var program = `
+// DO NOT EDIT.
+// Generate with: go run gen.go{{if .Full}} -full{{end}} | gofmt >md5block.go
+
+// +build !amd64
+
package md5
import (
@@ -186,6 +191,16 @@ import (
}
{{end}}
+const x86 = runtime.GOARCH == "amd64" || runtime.GOARCH == "386"
+
+var littleEndian bool
+
+func init() {
+ x := uint32(0x04030201)
+ y := [4]byte{0x1, 0x2, 0x3, 0x4}
+ littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y
+}
+
func block(dig *digest, p []byte) {
a := dig.s[0]
b := dig.s[1]
@@ -197,13 +212,13 @@ func block(dig *digest, p []byte) {
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" {
+ if x86 {
// 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 if uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+ } else if littleEndian && uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
X = (*[16]uint32)(unsafe.Pointer(&p[0]))
} else {
X = &xbuf
diff --git a/src/pkg/crypto/md5/md5block.go b/src/pkg/crypto/md5/md5block.go
index 0ca421774..a376fbee9 100644
--- a/src/pkg/crypto/md5/md5block.go
+++ b/src/pkg/crypto/md5/md5block.go
@@ -1,3 +1,8 @@
+// DO NOT EDIT.
+// Generate with: go run gen.go -full | gofmt >md5block.go
+
+// +build !amd64,!386
+
package md5
import (
diff --git a/src/pkg/crypto/md5/md5block_386.s b/src/pkg/crypto/md5/md5block_386.s
new file mode 100644
index 000000000..3ce15e37f
--- /dev/null
+++ b/src/pkg/crypto/md5/md5block_386.s
@@ -0,0 +1,180 @@
+// Original source:
+// http://www.zorinaq.com/papers/md5-amd64.html
+// http://www.zorinaq.com/papers/md5-amd64.tar.bz2
+//
+// Translated from Perl generating GNU assembly into
+// #defines generating 8a assembly, and adjusted for 386,
+// by the Go Authors.
+
+// MD5 optimized for AMD64.
+//
+// Author: Marc Bevand <bevand_m (at) epita.fr>
+// Licence: I hereby disclaim the copyright on this code and place it
+// in the public domain.
+
+#define ROUND1(a, b, c, d, index, const, shift) \
+ XORL c, BP; \
+ LEAL const(a)(DI*1), a; \
+ ANDL b, BP; \
+ XORL d, BP; \
+ MOVL (index*4)(SI), DI; \
+ ADDL BP, a; \
+ ROLL $shift, a; \
+ MOVL c, BP; \
+ ADDL b, a
+
+#define ROUND2(a, b, c, d, index, const, shift) \
+ LEAL const(a)(DI*1),a; \
+ MOVL d, DI; \
+ ANDL b, DI; \
+ MOVL d, BP; \
+ NOTL BP; \
+ ANDL c, BP; \
+ ORL DI, BP; \
+ MOVL (index*4)(SI),DI; \
+ ADDL BP, a; \
+ ROLL $shift, a; \
+ ADDL b, a
+
+#define ROUND3(a, b, c, d, index, const, shift) \
+ LEAL const(a)(DI*1),a; \
+ MOVL (index*4)(SI),DI; \
+ XORL d, BP; \
+ XORL b, BP; \
+ ADDL BP, a; \
+ ROLL $shift, a; \
+ MOVL b, BP; \
+ ADDL b, a
+
+#define ROUND4(a, b, c, d, index, const, shift) \
+ LEAL const(a)(DI*1),a; \
+ ORL b, BP; \
+ XORL c, BP; \
+ ADDL BP, a; \
+ MOVL (index*4)(SI),DI; \
+ MOVL $0xffffffff, BP; \
+ ROLL $shift, a; \
+ XORL c, BP; \
+ ADDL b, a
+
+TEXT ·block(SB),7,$24-16
+ MOVL dig+0(FP), BP
+ MOVL p+4(FP), SI
+ MOVL p_len+8(FP), DX
+ SHRL $6, DX
+ SHLL $6, DX
+
+ LEAL (SI)(DX*1), DI
+ MOVL (0*4)(BP), AX
+ MOVL (1*4)(BP), BX
+ MOVL (2*4)(BP), CX
+ MOVL (3*4)(BP), DX
+
+ CMPL SI, DI
+ JEQ end
+
+ MOVL DI, 16(SP)
+
+loop:
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ MOVL CX, 8(SP)
+ MOVL DX, 12(SP)
+
+ MOVL (0*4)(SI), DI
+ MOVL DX, BP
+
+ ROUND1(AX,BX,CX,DX, 1,0xd76aa478, 7);
+ ROUND1(DX,AX,BX,CX, 2,0xe8c7b756,12);
+ ROUND1(CX,DX,AX,BX, 3,0x242070db,17);
+ ROUND1(BX,CX,DX,AX, 4,0xc1bdceee,22);
+ ROUND1(AX,BX,CX,DX, 5,0xf57c0faf, 7);
+ ROUND1(DX,AX,BX,CX, 6,0x4787c62a,12);
+ ROUND1(CX,DX,AX,BX, 7,0xa8304613,17);
+ ROUND1(BX,CX,DX,AX, 8,0xfd469501,22);
+ ROUND1(AX,BX,CX,DX, 9,0x698098d8, 7);
+ ROUND1(DX,AX,BX,CX,10,0x8b44f7af,12);
+ ROUND1(CX,DX,AX,BX,11,0xffff5bb1,17);
+ ROUND1(BX,CX,DX,AX,12,0x895cd7be,22);
+ ROUND1(AX,BX,CX,DX,13,0x6b901122, 7);
+ ROUND1(DX,AX,BX,CX,14,0xfd987193,12);
+ ROUND1(CX,DX,AX,BX,15,0xa679438e,17);
+ ROUND1(BX,CX,DX,AX, 0,0x49b40821,22);
+
+ MOVL (1*4)(SI), DI
+ MOVL DX, BP
+
+ ROUND2(AX,BX,CX,DX, 6,0xf61e2562, 5);
+ ROUND2(DX,AX,BX,CX,11,0xc040b340, 9);
+ ROUND2(CX,DX,AX,BX, 0,0x265e5a51,14);
+ ROUND2(BX,CX,DX,AX, 5,0xe9b6c7aa,20);
+ ROUND2(AX,BX,CX,DX,10,0xd62f105d, 5);
+ ROUND2(DX,AX,BX,CX,15, 0x2441453, 9);
+ ROUND2(CX,DX,AX,BX, 4,0xd8a1e681,14);
+ ROUND2(BX,CX,DX,AX, 9,0xe7d3fbc8,20);
+ ROUND2(AX,BX,CX,DX,14,0x21e1cde6, 5);
+ ROUND2(DX,AX,BX,CX, 3,0xc33707d6, 9);
+ ROUND2(CX,DX,AX,BX, 8,0xf4d50d87,14);
+ ROUND2(BX,CX,DX,AX,13,0x455a14ed,20);
+ ROUND2(AX,BX,CX,DX, 2,0xa9e3e905, 5);
+ ROUND2(DX,AX,BX,CX, 7,0xfcefa3f8, 9);
+ ROUND2(CX,DX,AX,BX,12,0x676f02d9,14);
+ ROUND2(BX,CX,DX,AX, 0,0x8d2a4c8a,20);
+
+ MOVL (5*4)(SI), DI
+ MOVL CX, BP
+
+ ROUND3(AX,BX,CX,DX, 8,0xfffa3942, 4);
+ ROUND3(DX,AX,BX,CX,11,0x8771f681,11);
+ ROUND3(CX,DX,AX,BX,14,0x6d9d6122,16);
+ ROUND3(BX,CX,DX,AX, 1,0xfde5380c,23);
+ ROUND3(AX,BX,CX,DX, 4,0xa4beea44, 4);
+ ROUND3(DX,AX,BX,CX, 7,0x4bdecfa9,11);
+ ROUND3(CX,DX,AX,BX,10,0xf6bb4b60,16);
+ ROUND3(BX,CX,DX,AX,13,0xbebfbc70,23);
+ ROUND3(AX,BX,CX,DX, 0,0x289b7ec6, 4);
+ ROUND3(DX,AX,BX,CX, 3,0xeaa127fa,11);
+ ROUND3(CX,DX,AX,BX, 6,0xd4ef3085,16);
+ ROUND3(BX,CX,DX,AX, 9, 0x4881d05,23);
+ ROUND3(AX,BX,CX,DX,12,0xd9d4d039, 4);
+ ROUND3(DX,AX,BX,CX,15,0xe6db99e5,11);
+ ROUND3(CX,DX,AX,BX, 2,0x1fa27cf8,16);
+ ROUND3(BX,CX,DX,AX, 0,0xc4ac5665,23);
+
+ MOVL (0*4)(SI), DI
+ MOVL $0xffffffff, BP
+ XORL DX, BP
+
+ ROUND4(AX,BX,CX,DX, 7,0xf4292244, 6);
+ ROUND4(DX,AX,BX,CX,14,0x432aff97,10);
+ ROUND4(CX,DX,AX,BX, 5,0xab9423a7,15);
+ ROUND4(BX,CX,DX,AX,12,0xfc93a039,21);
+ ROUND4(AX,BX,CX,DX, 3,0x655b59c3, 6);
+ ROUND4(DX,AX,BX,CX,10,0x8f0ccc92,10);
+ ROUND4(CX,DX,AX,BX, 1,0xffeff47d,15);
+ ROUND4(BX,CX,DX,AX, 8,0x85845dd1,21);
+ ROUND4(AX,BX,CX,DX,15,0x6fa87e4f, 6);
+ ROUND4(DX,AX,BX,CX, 6,0xfe2ce6e0,10);
+ ROUND4(CX,DX,AX,BX,13,0xa3014314,15);
+ ROUND4(BX,CX,DX,AX, 4,0x4e0811a1,21);
+ ROUND4(AX,BX,CX,DX,11,0xf7537e82, 6);
+ ROUND4(DX,AX,BX,CX, 2,0xbd3af235,10);
+ ROUND4(CX,DX,AX,BX, 9,0x2ad7d2bb,15);
+ ROUND4(BX,CX,DX,AX, 0,0xeb86d391,21);
+
+ ADDL 0(SP), AX
+ ADDL 4(SP), BX
+ ADDL 8(SP), CX
+ ADDL 12(SP), DX
+
+ ADDL $64, SI
+ CMPL SI, 16(SP)
+ JB loop
+
+end:
+ MOVL dig+0(FP), BP
+ MOVL AX, (0*4)(BP)
+ MOVL BX, (1*4)(BP)
+ MOVL CX, (2*4)(BP)
+ MOVL DX, (3*4)(BP)
+ RET
diff --git a/src/pkg/crypto/md5/md5block_amd64.s b/src/pkg/crypto/md5/md5block_amd64.s
new file mode 100644
index 000000000..e6420a28a
--- /dev/null
+++ b/src/pkg/crypto/md5/md5block_amd64.s
@@ -0,0 +1,177 @@
+// Original source:
+// http://www.zorinaq.com/papers/md5-amd64.html
+// http://www.zorinaq.com/papers/md5-amd64.tar.bz2
+//
+// Translated from Perl generating GNU assembly into
+// #defines generating 6a assembly by the Go Authors.
+
+// MD5 optimized for AMD64.
+//
+// Author: Marc Bevand <bevand_m (at) epita.fr>
+// Licence: I hereby disclaim the copyright on this code and place it
+// in the public domain.
+
+TEXT ·block(SB),7,$0-32
+ MOVQ dig+0(FP), BP
+ MOVQ p+8(FP), SI
+ MOVQ p_len+16(FP), DX
+ SHRQ $6, DX
+ SHLQ $6, DX
+
+ LEAQ (SI)(DX*1), DI
+ MOVL (0*4)(BP), AX
+ MOVL (1*4)(BP), BX
+ MOVL (2*4)(BP), CX
+ MOVL (3*4)(BP), DX
+
+ CMPQ SI, DI
+ JEQ end
+
+loop:
+ MOVL AX, R12
+ MOVL BX, R13
+ MOVL CX, R14
+ MOVL DX, R15
+
+ MOVL (0*4)(SI), R8
+ MOVL DX, R9
+
+#define ROUND1(a, b, c, d, index, const, shift) \
+ XORL c, R9; \
+ LEAL const(a)(R8*1), a; \
+ ANDL b, R9; \
+ XORL d, R9; \
+ MOVL (index*4)(SI), R8; \
+ ADDL R9, a; \
+ ROLL $shift, a; \
+ MOVL c, R9; \
+ ADDL b, a
+
+ ROUND1(AX,BX,CX,DX, 1,0xd76aa478, 7);
+ ROUND1(DX,AX,BX,CX, 2,0xe8c7b756,12);
+ ROUND1(CX,DX,AX,BX, 3,0x242070db,17);
+ ROUND1(BX,CX,DX,AX, 4,0xc1bdceee,22);
+ ROUND1(AX,BX,CX,DX, 5,0xf57c0faf, 7);
+ ROUND1(DX,AX,BX,CX, 6,0x4787c62a,12);
+ ROUND1(CX,DX,AX,BX, 7,0xa8304613,17);
+ ROUND1(BX,CX,DX,AX, 8,0xfd469501,22);
+ ROUND1(AX,BX,CX,DX, 9,0x698098d8, 7);
+ ROUND1(DX,AX,BX,CX,10,0x8b44f7af,12);
+ ROUND1(CX,DX,AX,BX,11,0xffff5bb1,17);
+ ROUND1(BX,CX,DX,AX,12,0x895cd7be,22);
+ ROUND1(AX,BX,CX,DX,13,0x6b901122, 7);
+ ROUND1(DX,AX,BX,CX,14,0xfd987193,12);
+ ROUND1(CX,DX,AX,BX,15,0xa679438e,17);
+ ROUND1(BX,CX,DX,AX, 0,0x49b40821,22);
+
+ MOVL (1*4)(SI), R8
+ MOVL DX, R9
+ MOVL DX, R10
+
+#define ROUND2(a, b, c, d, index, const, shift) \
+ NOTL R9; \
+ LEAL const(a)(R8*1),a; \
+ ANDL b, R10; \
+ ANDL c, R9; \
+ MOVL (index*4)(SI),R8; \
+ ORL R9, R10; \
+ MOVL c, R9; \
+ ADDL R10, a; \
+ MOVL c, R10; \
+ ROLL $shift, a; \
+ ADDL b, a
+
+ ROUND2(AX,BX,CX,DX, 6,0xf61e2562, 5);
+ ROUND2(DX,AX,BX,CX,11,0xc040b340, 9);
+ ROUND2(CX,DX,AX,BX, 0,0x265e5a51,14);
+ ROUND2(BX,CX,DX,AX, 5,0xe9b6c7aa,20);
+ ROUND2(AX,BX,CX,DX,10,0xd62f105d, 5);
+ ROUND2(DX,AX,BX,CX,15, 0x2441453, 9);
+ ROUND2(CX,DX,AX,BX, 4,0xd8a1e681,14);
+ ROUND2(BX,CX,DX,AX, 9,0xe7d3fbc8,20);
+ ROUND2(AX,BX,CX,DX,14,0x21e1cde6, 5);
+ ROUND2(DX,AX,BX,CX, 3,0xc33707d6, 9);
+ ROUND2(CX,DX,AX,BX, 8,0xf4d50d87,14);
+ ROUND2(BX,CX,DX,AX,13,0x455a14ed,20);
+ ROUND2(AX,BX,CX,DX, 2,0xa9e3e905, 5);
+ ROUND2(DX,AX,BX,CX, 7,0xfcefa3f8, 9);
+ ROUND2(CX,DX,AX,BX,12,0x676f02d9,14);
+ ROUND2(BX,CX,DX,AX, 0,0x8d2a4c8a,20);
+
+ MOVL (5*4)(SI), R8
+ MOVL CX, R9
+
+#define ROUND3(a, b, c, d, index, const, shift) \
+ LEAL const(a)(R8*1),a; \
+ MOVL (index*4)(SI),R8; \
+ XORL d, R9; \
+ XORL b, R9; \
+ ADDL R9, a; \
+ ROLL $shift, a; \
+ MOVL b, R9; \
+ ADDL b, a
+
+ ROUND3(AX,BX,CX,DX, 8,0xfffa3942, 4);
+ ROUND3(DX,AX,BX,CX,11,0x8771f681,11);
+ ROUND3(CX,DX,AX,BX,14,0x6d9d6122,16);
+ ROUND3(BX,CX,DX,AX, 1,0xfde5380c,23);
+ ROUND3(AX,BX,CX,DX, 4,0xa4beea44, 4);
+ ROUND3(DX,AX,BX,CX, 7,0x4bdecfa9,11);
+ ROUND3(CX,DX,AX,BX,10,0xf6bb4b60,16);
+ ROUND3(BX,CX,DX,AX,13,0xbebfbc70,23);
+ ROUND3(AX,BX,CX,DX, 0,0x289b7ec6, 4);
+ ROUND3(DX,AX,BX,CX, 3,0xeaa127fa,11);
+ ROUND3(CX,DX,AX,BX, 6,0xd4ef3085,16);
+ ROUND3(BX,CX,DX,AX, 9, 0x4881d05,23);
+ ROUND3(AX,BX,CX,DX,12,0xd9d4d039, 4);
+ ROUND3(DX,AX,BX,CX,15,0xe6db99e5,11);
+ ROUND3(CX,DX,AX,BX, 2,0x1fa27cf8,16);
+ ROUND3(BX,CX,DX,AX, 0,0xc4ac5665,23);
+
+ MOVL (0*4)(SI), R8
+ MOVL $0xffffffff, R9
+ XORL DX, R9
+
+#define ROUND4(a, b, c, d, index, const, shift) \
+ LEAL const(a)(R8*1),a; \
+ ORL b, R9; \
+ XORL c, R9; \
+ ADDL R9, a; \
+ MOVL (index*4)(SI),R8; \
+ MOVL $0xffffffff, R9; \
+ ROLL $shift, a; \
+ XORL c, R9; \
+ ADDL b, a
+
+ ROUND4(AX,BX,CX,DX, 7,0xf4292244, 6);
+ ROUND4(DX,AX,BX,CX,14,0x432aff97,10);
+ ROUND4(CX,DX,AX,BX, 5,0xab9423a7,15);
+ ROUND4(BX,CX,DX,AX,12,0xfc93a039,21);
+ ROUND4(AX,BX,CX,DX, 3,0x655b59c3, 6);
+ ROUND4(DX,AX,BX,CX,10,0x8f0ccc92,10);
+ ROUND4(CX,DX,AX,BX, 1,0xffeff47d,15);
+ ROUND4(BX,CX,DX,AX, 8,0x85845dd1,21);
+ ROUND4(AX,BX,CX,DX,15,0x6fa87e4f, 6);
+ ROUND4(DX,AX,BX,CX, 6,0xfe2ce6e0,10);
+ ROUND4(CX,DX,AX,BX,13,0xa3014314,15);
+ ROUND4(BX,CX,DX,AX, 4,0x4e0811a1,21);
+ ROUND4(AX,BX,CX,DX,11,0xf7537e82, 6);
+ ROUND4(DX,AX,BX,CX, 2,0xbd3af235,10);
+ ROUND4(CX,DX,AX,BX, 9,0x2ad7d2bb,15);
+ ROUND4(BX,CX,DX,AX, 0,0xeb86d391,21);
+
+ ADDL R12, AX
+ ADDL R13, BX
+ ADDL R14, CX
+ ADDL R15, DX
+
+ ADDQ $64, SI
+ CMPQ SI, DI
+ JB loop
+
+end:
+ MOVL AX, (0*4)(BP)
+ MOVL BX, (1*4)(BP)
+ MOVL CX, (2*4)(BP)
+ MOVL DX, (3*4)(BP)
+ RET
diff --git a/src/pkg/crypto/md5/md5block_decl.go b/src/pkg/crypto/md5/md5block_decl.go
new file mode 100644
index 000000000..14190c6ff
--- /dev/null
+++ b/src/pkg/crypto/md5/md5block_decl.go
@@ -0,0 +1,9 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64 386
+
+package md5
+
+func block(dig *digest, p []byte)
diff --git a/src/pkg/crypto/rand/util.go b/src/pkg/crypto/rand/util.go
index 50e5b162b..21608dbac 100644
--- a/src/pkg/crypto/rand/util.go
+++ b/src/pkg/crypto/rand/util.go
@@ -98,8 +98,6 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) {
return
}
}
-
- return
}
// Int returns a uniform random value in [0, max).
@@ -130,6 +128,4 @@ func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
return
}
}
-
- return
}
diff --git a/src/pkg/crypto/rc4/rc4.go b/src/pkg/crypto/rc4/rc4.go
index e0c33fa4b..3d717c63b 100644
--- a/src/pkg/crypto/rc4/rc4.go
+++ b/src/pkg/crypto/rc4/rc4.go
@@ -13,7 +13,7 @@ import "strconv"
// A Cipher is an instance of RC4 using a particular key.
type Cipher struct {
- s [256]byte
+ s [256]uint32
i, j uint8
}
@@ -32,11 +32,11 @@ func NewCipher(key []byte) (*Cipher, error) {
}
var c Cipher
for i := 0; i < 256; i++ {
- c.s[i] = uint8(i)
+ c.s[i] = uint32(i)
}
var j uint8 = 0
for i := 0; i < 256; i++ {
- j += c.s[i] + key[i%k]
+ j += uint8(c.s[i]) + key[i%k]
c.s[i], c.s[j] = c.s[j], c.s[i]
}
return &c, nil
diff --git a/src/pkg/crypto/rc4/rc4_386.s b/src/pkg/crypto/rc4/rc4_386.s
new file mode 100644
index 000000000..c80ef2a3a
--- /dev/null
+++ b/src/pkg/crypto/rc4/rc4_386.s
@@ -0,0 +1,51 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+TEXT ·xorKeyStream(SB),7,$0
+ MOVL dst+0(FP), DI
+ MOVL src+4(FP), SI
+ MOVL state+12(FP), BP
+
+ MOVL i+16(FP), AX
+ MOVBLZX (AX), AX
+ MOVL j+20(FP), BX
+ MOVBLZX (BX), BX
+ CMPL n+8(FP), $0
+ JEQ done
+
+loop:
+ // i += 1
+ INCB AX
+
+ // j += c.s[i]
+ MOVBLZX (BP)(AX*4), DX
+ ADDB DX, BX
+ MOVBLZX BX, BX
+
+ // c.s[i], c.s[j] = c.s[j], c.s[i]
+ MOVBLZX (BP)(BX*4), CX
+ MOVB CX, (BP)(AX*4)
+ MOVB DX, (BP)(BX*4)
+
+ // *dst = *src ^ c.s[c.s[i]+c.s[j]]
+ ADDB DX, CX
+ MOVBLZX CX, CX
+ MOVB (BP)(CX*4), CX
+ XORB (SI), CX
+ MOVBLZX CX, CX
+ MOVB CX, (DI)
+
+ INCL SI
+ INCL DI
+ DECL n+8(FP)
+ JNE loop
+
+done:
+ MOVL i+16(FP), CX
+ MOVB AX, (CX)
+ MOVL j+20(FP), CX
+ MOVB BX, (CX)
+
+ RET
diff --git a/src/pkg/crypto/rc4/rc4_amd64.s b/src/pkg/crypto/rc4/rc4_amd64.s
index ffe9ada85..353fe3720 100644
--- a/src/pkg/crypto/rc4/rc4_amd64.s
+++ b/src/pkg/crypto/rc4/rc4_amd64.s
@@ -1,53 +1,177 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
+// Original source:
+// http://www.zorinaq.com/papers/rc4-amd64.html
+// http://www.zorinaq.com/papers/rc4-amd64.tar.bz2
+
+// Local modifications:
+//
+// Transliterated from GNU to 6a assembly syntax by the Go authors.
+// The comments and spacing are from the original.
+//
+// The new EXTEND macros avoid a bad stall on some systems after 8-bit math.
+//
+// The original code accumulated 64 bits of key stream in an integer
+// register and then XOR'ed the key stream into the data 8 bytes at a time.
+// Modified to accumulate 128 bits of key stream into an XMM register
+// and then XOR the key stream into the data 16 bytes at a time.
+// Approximately doubles throughput.
+
+// NOTE: Changing EXTEND to a no-op makes the code run 1.2x faster on Core i5
+// but makes the code run 2.0x slower on Xeon.
+#define EXTEND(r) MOVBLZX r, r
+
+/*
+** RC4 implementation optimized for AMD64.
+**
+** Author: Marc Bevand <bevand_m (at) epita.fr>
+** Licence: I hereby disclaim the copyright on this code and place it
+** in the public domain.
+**
+** The code has been designed to be easily integrated into openssl:
+** the exported RC4() function can replace the actual implementations
+** openssl already contains. Please note that when linking with openssl,
+** it requires that sizeof(RC4_INT) == 8. So openssl must be compiled
+** with -DRC4_INT='unsigned long'.
+**
+** The throughput achieved by this code is about 320 MBytes/sec, on
+** a 1.8 GHz AMD Opteron (rev C0) processor.
+*/
-// func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
TEXT ·xorKeyStream(SB),7,$0
- MOVQ dst+0(FP), DI
- MOVQ src+8(FP), SI
- MOVQ n+16(FP), CX
- MOVQ state+24(FP), R8
+ MOVQ n+16(FP), BX // rbx = ARG(len)
+ MOVQ src+8(FP), SI // in = ARG(in)
+ MOVQ dst+0(FP), DI // out = ARG(out)
+ MOVQ state+24(FP), BP // d = ARG(data)
+ MOVQ i+32(FP), AX
+ MOVBQZX 0(AX), CX // x = *xp
+ MOVQ j+40(FP), AX
+ MOVBQZX 0(AX), DX // y = *yp
+
+ LEAQ (SI)(BX*1), R9 // limit = in+len
+
+l1: CMPQ SI, R9 // cmp in with in+len
+ JGE finished // jump if (in >= in+len)
+
+ INCB CX
+ EXTEND(CX)
+ TESTL $15, CX
+ JZ wordloop
+
+ MOVBLZX (BP)(CX*4), AX
+
+ ADDB AX, DX // y += tx
+ EXTEND(DX)
+ MOVBLZX (BP)(DX*4), BX // ty = d[y]
+ MOVB BX, (BP)(CX*4) // d[x] = ty
+ ADDB AX, BX // val = ty+tx
+ EXTEND(BX)
+ MOVB AX, (BP)(DX*4) // d[y] = tx
+ MOVBLZX (BP)(BX*4), R8 // val = d[val]
+ XORB (SI), R8 // xor 1 byte
+ MOVB R8, (DI)
+ INCQ SI // in++
+ INCQ DI // out++
+ JMP l1
+
+wordloop:
+ SUBQ $16, R9
+ CMPQ SI, R9
+ JGT end
+
+start:
+ ADDQ $16, SI // increment in
+ ADDQ $16, DI // increment out
+
+ // Each KEYROUND generates one byte of key and
+ // inserts it into an XMM register at the given 16-bit index.
+ // The key state array is uint32 words only using the bottom
+ // byte of each word, so the 16-bit OR only copies 8 useful bits.
+ // We accumulate alternating bytes into X0 and X1, and then at
+ // the end we OR X1<<8 into X0 to produce the actual key.
+ //
+ // At the beginning of the loop, CX%16 == 0, so the 16 loads
+ // at state[CX], state[CX+1], ..., state[CX+15] can precompute
+ // (state+CX) as R12 and then become R12[0], R12[1], ... R12[15],
+ // without fear of the byte computation CX+15 wrapping around.
+ //
+ // The first round needs R12[0], the second needs R12[1], and so on.
+ // We can avoid memory stalls by starting the load for round n+1
+ // before the end of round n, using the LOAD macro.
+ LEAQ (BP)(CX*4), R12
- MOVQ xPtr+32(FP), AX
- MOVBQZX (AX), AX
- MOVQ yPtr+40(FP), BX
- MOVBQZX (BX), BX
+#define KEYROUND(xmm, load, off, r1, r2, index) \
+ MOVBLZX (BP)(DX*4), R8; \
+ MOVB r1, (BP)(DX*4); \
+ load((off+1), r2); \
+ MOVB R8, (off*4)(R12); \
+ ADDB r1, R8; \
+ EXTEND(R8); \
+ PINSRW $index, (BP)(R8*4), xmm
-loop:
- CMPQ CX, $0
- JE done
+#define LOAD(off, reg) \
+ MOVBLZX (off*4)(R12), reg; \
+ ADDB reg, DX; \
+ EXTEND(DX)
- // c.i += 1
- INCB AX
+#define SKIP(off, reg)
- // c.j += c.s[c.i]
- MOVB (R8)(AX*1), R9
- ADDB R9, BX
+ LOAD(0, AX)
+ KEYROUND(X0, LOAD, 0, AX, BX, 0)
+ KEYROUND(X1, LOAD, 1, BX, AX, 0)
+ KEYROUND(X0, LOAD, 2, AX, BX, 1)
+ KEYROUND(X1, LOAD, 3, BX, AX, 1)
+ KEYROUND(X0, LOAD, 4, AX, BX, 2)
+ KEYROUND(X1, LOAD, 5, BX, AX, 2)
+ KEYROUND(X0, LOAD, 6, AX, BX, 3)
+ KEYROUND(X1, LOAD, 7, BX, AX, 3)
+ KEYROUND(X0, LOAD, 8, AX, BX, 4)
+ KEYROUND(X1, LOAD, 9, BX, AX, 4)
+ KEYROUND(X0, LOAD, 10, AX, BX, 5)
+ KEYROUND(X1, LOAD, 11, BX, AX, 5)
+ KEYROUND(X0, LOAD, 12, AX, BX, 6)
+ KEYROUND(X1, LOAD, 13, BX, AX, 6)
+ KEYROUND(X0, LOAD, 14, AX, BX, 7)
+ KEYROUND(X1, SKIP, 15, BX, AX, 7)
+
+ ADDB $16, CX
- MOVBQZX (R8)(BX*1), R10
+ PSLLQ $8, X1
+ PXOR X1, X0
+ MOVOU -16(SI), X2
+ PXOR X0, X2
+ MOVOU X2, -16(DI)
- MOVB R10, (R8)(AX*1)
- MOVB R9, (R8)(BX*1)
+ CMPQ SI, R9 // cmp in with in+len-16
+ JLE start // jump if (in <= in+len-16)
- // R11 = c.s[c.i]+c.s[c.j]
- MOVQ R10, R11
- ADDB R9, R11
+end:
+ DECB CX
+ ADDQ $16, R9 // tmp = in+len
- MOVB (R8)(R11*1), R11
- MOVB (SI), R12
- XORB R11, R12
- MOVB R12, (DI)
+ // handle the last bytes, one by one
+l2: CMPQ SI, R9 // cmp in with in+len
+ JGE finished // jump if (in >= in+len)
- INCQ SI
- INCQ DI
- DECQ CX
+ INCB CX
+ EXTEND(CX)
+ MOVBLZX (BP)(CX*4), AX
- JMP loop
-done:
- MOVQ xPtr+32(FP), R8
- MOVB AX, (R8)
- MOVQ yPtr+40(FP), R8
- MOVB BX, (R8)
+ ADDB AX, DX // y += tx
+ EXTEND(DX)
+ MOVBLZX (BP)(DX*4), BX // ty = d[y]
+ MOVB BX, (BP)(CX*4) // d[x] = ty
+ ADDB AX, BX // val = ty+tx
+ EXTEND(BX)
+ MOVB AX, (BP)(DX*4) // d[y] = tx
+ MOVBLZX (BP)(BX*4), R8 // val = d[val]
+ XORB (SI), R8 // xor 1 byte
+ MOVB R8, (DI)
+ INCQ SI // in++
+ INCQ DI // out++
+ JMP l2
+finished:
+ MOVQ j+40(FP), BX
+ MOVB DX, 0(BX)
+ MOVQ i+32(FP), AX
+ MOVB CX, 0(AX)
RET
diff --git a/src/pkg/crypto/rc4/rc4_arm.s b/src/pkg/crypto/rc4/rc4_arm.s
index 51a332f62..307cb7148 100644
--- a/src/pkg/crypto/rc4/rc4_arm.s
+++ b/src/pkg/crypto/rc4/rc4_arm.s
@@ -31,19 +31,19 @@ loop:
// i += 1; j += state[i]
ADD $1, R(i)
AND $0xff, R(i)
- MOVBU R(i)<<0(R(state)), R(t)
+ MOVBU R(i)<<2(R(state)), R(t)
ADD R(t), R(j)
AND $0xff, R(j)
// swap state[i] <-> state[j]
- MOVBU R(j)<<0(R(state)), R(t2)
- MOVB R(t2), R(i)<<0(R(state))
- MOVB R(t), R(j)<<0(R(state))
+ MOVBU R(j)<<2(R(state)), R(t2)
+ MOVB R(t2), R(i)<<2(R(state))
+ MOVB R(t), R(j)<<2(R(state))
// dst[k] = src[k] ^ state[state[i] + state[j]]
ADD R(t2), R(t)
AND $0xff, R(t)
- MOVBU R(t)<<0(R(state)), R(t)
+ MOVBU R(t)<<2(R(state)), R(t)
MOVBU R(k)<<0(R(src)), R(t2)
EOR R(t), R(t2)
MOVB R(t2), R(k)<<0(R(dst))
diff --git a/src/pkg/crypto/rc4/rc4_asm.go b/src/pkg/crypto/rc4/rc4_asm.go
index 0b66e4a9e..c582a4488 100644
--- a/src/pkg/crypto/rc4/rc4_asm.go
+++ b/src/pkg/crypto/rc4/rc4_asm.go
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build amd64 arm
+// +build amd64 arm 386
package rc4
-func xorKeyStream(dst, src *byte, n int, state *[256]byte, i, j *uint8)
+func xorKeyStream(dst, src *byte, n int, state *[256]uint32, i, j *uint8)
// XORKeyStream sets dst to the result of XORing src with the key stream.
// Dst and src may be the same slice but otherwise should not overlap.
diff --git a/src/pkg/crypto/rc4/rc4_ref.go b/src/pkg/crypto/rc4/rc4_ref.go
index 1018548c2..44d380436 100644
--- a/src/pkg/crypto/rc4/rc4_ref.go
+++ b/src/pkg/crypto/rc4/rc4_ref.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 !amd64,!arm
+// +build !amd64,!arm,!386
package rc4
diff --git a/src/pkg/crypto/rc4/rc4_test.go b/src/pkg/crypto/rc4/rc4_test.go
index 9e12789f7..7b4df6791 100644
--- a/src/pkg/crypto/rc4/rc4_test.go
+++ b/src/pkg/crypto/rc4/rc4_test.go
@@ -5,6 +5,8 @@
package rc4
import (
+ "bytes"
+ "fmt"
"testing"
)
@@ -72,25 +74,68 @@ var golden = []rc4Test{
},
}
+func testEncrypt(t *testing.T, desc string, c *Cipher, src, expect []byte) {
+ dst := make([]byte, len(src))
+ c.XORKeyStream(dst, src)
+ for i, v := range dst {
+ if v != expect[i] {
+ t.Fatalf("%s: mismatch at byte %d:\nhave %x\nwant %x", desc, i, dst, expect)
+ }
+ }
+}
+
func TestGolden(t *testing.T) {
- for i := 0; i < len(golden); i++ {
- g := golden[i]
- c, err := NewCipher(g.key)
- if err != nil {
- t.Errorf("Failed to create cipher at golden index %d", i)
- return
+ for gi, g := range golden {
+ data := make([]byte, len(g.keystream))
+ for i := range data {
+ data[i] = byte(i)
}
- keystream := make([]byte, len(g.keystream))
- c.XORKeyStream(keystream, keystream)
- for j, v := range keystream {
- if g.keystream[j] != v {
- t.Errorf("Failed at golden index %d:\n%x\nvs\n%x", i, keystream, g.keystream)
- break
+
+ expect := make([]byte, len(g.keystream))
+ for i := range expect {
+ expect[i] = byte(i) ^ g.keystream[i]
+ }
+
+ for size := 1; size <= len(g.keystream); size++ {
+ c, err := NewCipher(g.key)
+ if err != nil {
+ t.Fatalf("#%d: NewCipher: %v", gi, err)
+ }
+
+ off := 0
+ for off < len(g.keystream) {
+ n := len(g.keystream) - off
+ if n > size {
+ n = size
+ }
+ desc := fmt.Sprintf("#%d@[%d:%d]", gi, off, off+n)
+ testEncrypt(t, desc, c, data[off:off+n], expect[off:off+n])
+ off += n
}
}
}
}
+func TestBlock(t *testing.T) {
+ c1a, _ := NewCipher(golden[0].key)
+ c1b, _ := NewCipher(golden[1].key)
+ data1 := make([]byte, 1<<20)
+ for i := range data1 {
+ c1a.XORKeyStream(data1[i:i+1], data1[i:i+1])
+ c1b.XORKeyStream(data1[i:i+1], data1[i:i+1])
+ }
+
+ c2a, _ := NewCipher(golden[0].key)
+ c2b, _ := NewCipher(golden[1].key)
+ data2 := make([]byte, 1<<20)
+ c2a.XORKeyStream(data2, data2)
+ c2b.XORKeyStream(data2, data2)
+
+ if !bytes.Equal(data1, data2) {
+ t.Fatalf("bad block")
+ }
+}
+
func benchmark(b *testing.B, size int64) {
buf := make([]byte, size)
c, err := NewCipher(golden[0].key)
diff --git a/src/pkg/crypto/sha1/sha1block.go b/src/pkg/crypto/sha1/sha1block.go
index 1c9507c68..92224fc0e 100644
--- a/src/pkg/crypto/sha1/sha1block.go
+++ b/src/pkg/crypto/sha1/sha1block.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 !amd64,!386
+
// SHA1 block step.
// In its own file so that a faster assembly or C version
// can be substituted easily.
diff --git a/src/pkg/crypto/sha1/sha1block_386.s b/src/pkg/crypto/sha1/sha1block_386.s
new file mode 100644
index 000000000..e60a7b9b0
--- /dev/null
+++ b/src/pkg/crypto/sha1/sha1block_386.s
@@ -0,0 +1,233 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// SHA1 block routine. See sha1block.go for Go equivalent.
+//
+// There are 80 rounds of 4 types:
+// - rounds 0-15 are type 1 and load data (ROUND1 macro).
+// - rounds 16-19 are type 1 and do not load data (ROUND1x macro).
+// - rounds 20-39 are type 2 and do not load data (ROUND2 macro).
+// - rounds 40-59 are type 3 and do not load data (ROUND3 macro).
+// - rounds 60-79 are type 4 and do not load data (ROUND4 macro).
+//
+// Each round loads or shuffles the data, then computes a per-round
+// function of b, c, d, and then mixes the result into and rotates the
+// five registers a, b, c, d, e holding the intermediate results.
+//
+// The register rotation is implemented by rotating the arguments to
+// the round macros instead of by explicit move instructions.
+
+// Like sha1block_amd64.s, but we keep the data and limit pointers on the stack.
+// To free up the word pointer (R10 on amd64, DI here), we add it to e during
+// LOAD/SHUFFLE instead of during MIX.
+//
+// The stack holds the intermediate word array - 16 uint32s - at 0(SP) up to 64(SP).
+// The saved a, b, c, d, e (R11 through R15 on amd64) are at 64(SP) up to 84(SP).
+// The saved limit pointer (DI on amd64) is at 84(SP).
+// The saved data pointer (SI on amd64) is at 88(SP).
+
+#define LOAD(index, e) \
+ MOVL 88(SP), SI; \
+ MOVL (index*4)(SI), DI; \
+ BSWAPL DI; \
+ MOVL DI, (index*4)(SP); \
+ ADDL DI, e
+
+#define SHUFFLE(index, e) \
+ MOVL (((index)&0xf)*4)(SP), DI; \
+ XORL (((index-3)&0xf)*4)(SP), DI; \
+ XORL (((index-8)&0xf)*4)(SP), DI; \
+ XORL (((index-14)&0xf)*4)(SP), DI; \
+ ROLL $1, DI; \
+ MOVL DI, (((index)&0xf)*4)(SP); \
+ ADDL DI, e
+
+#define FUNC1(a, b, c, d, e) \
+ MOVL b, SI; \
+ ANDL c, SI; \
+ MOVL b, DI; \
+ NOTL DI; \
+ ANDL d, DI; \
+ ORL SI, DI
+
+#define FUNC2(a, b, c, d, e) \
+ MOVL b, DI; \
+ XORL c, DI; \
+ XORL d, DI
+
+#define FUNC3(a, b, c, d, e) \
+ MOVL b, SI; \
+ ORL c, SI; \
+ ANDL d, SI; \
+ MOVL b, DI; \
+ ANDL c, DI; \
+ ORL SI, DI
+
+#define FUNC4 FUNC2
+
+#define MIX(a, b, c, d, e, const) \
+ ROLL $30, b; \
+ ADDL DI, e; \
+ MOVL a, SI; \
+ ROLL $5, SI; \
+ LEAL const(e)(SI*1), e
+
+#define ROUND1(a, b, c, d, e, index) \
+ LOAD(index, e); \
+ FUNC1(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x5A827999)
+
+#define ROUND1x(a, b, c, d, e, index) \
+ SHUFFLE(index, e); \
+ FUNC1(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x5A827999)
+
+#define ROUND2(a, b, c, d, e, index) \
+ SHUFFLE(index, e); \
+ FUNC2(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x6ED9EBA1)
+
+#define ROUND3(a, b, c, d, e, index) \
+ SHUFFLE(index, e); \
+ FUNC3(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x8F1BBCDC)
+
+#define ROUND4(a, b, c, d, e, index) \
+ SHUFFLE(index, e); \
+ FUNC4(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0xCA62C1D6)
+
+// func block(dig *digest, p []byte)
+TEXT ·block(SB),7,$92-16
+ MOVL dig+0(FP), BP
+ MOVL p+4(FP), SI
+ MOVL p_len+8(FP), DX
+ SHRL $6, DX
+ SHLL $6, DX
+
+ LEAL (SI)(DX*1), DI
+ MOVL (0*4)(BP), AX
+ MOVL (1*4)(BP), BX
+ MOVL (2*4)(BP), CX
+ MOVL (3*4)(BP), DX
+ MOVL (4*4)(BP), BP
+
+ CMPL SI, DI
+ JEQ end
+
+ MOVL DI, 84(SP)
+
+loop:
+ MOVL SI, 88(SP)
+
+ MOVL AX, 64(SP)
+ MOVL BX, 68(SP)
+ MOVL CX, 72(SP)
+ MOVL DX, 76(SP)
+ MOVL BP, 80(SP)
+
+ ROUND1(AX, BX, CX, DX, BP, 0)
+ ROUND1(BP, AX, BX, CX, DX, 1)
+ ROUND1(DX, BP, AX, BX, CX, 2)
+ ROUND1(CX, DX, BP, AX, BX, 3)
+ ROUND1(BX, CX, DX, BP, AX, 4)
+ ROUND1(AX, BX, CX, DX, BP, 5)
+ ROUND1(BP, AX, BX, CX, DX, 6)
+ ROUND1(DX, BP, AX, BX, CX, 7)
+ ROUND1(CX, DX, BP, AX, BX, 8)
+ ROUND1(BX, CX, DX, BP, AX, 9)
+ ROUND1(AX, BX, CX, DX, BP, 10)
+ ROUND1(BP, AX, BX, CX, DX, 11)
+ ROUND1(DX, BP, AX, BX, CX, 12)
+ ROUND1(CX, DX, BP, AX, BX, 13)
+ ROUND1(BX, CX, DX, BP, AX, 14)
+ ROUND1(AX, BX, CX, DX, BP, 15)
+
+ ROUND1x(BP, AX, BX, CX, DX, 16)
+ ROUND1x(DX, BP, AX, BX, CX, 17)
+ ROUND1x(CX, DX, BP, AX, BX, 18)
+ ROUND1x(BX, CX, DX, BP, AX, 19)
+
+ ROUND2(AX, BX, CX, DX, BP, 20)
+ ROUND2(BP, AX, BX, CX, DX, 21)
+ ROUND2(DX, BP, AX, BX, CX, 22)
+ ROUND2(CX, DX, BP, AX, BX, 23)
+ ROUND2(BX, CX, DX, BP, AX, 24)
+ ROUND2(AX, BX, CX, DX, BP, 25)
+ ROUND2(BP, AX, BX, CX, DX, 26)
+ ROUND2(DX, BP, AX, BX, CX, 27)
+ ROUND2(CX, DX, BP, AX, BX, 28)
+ ROUND2(BX, CX, DX, BP, AX, 29)
+ ROUND2(AX, BX, CX, DX, BP, 30)
+ ROUND2(BP, AX, BX, CX, DX, 31)
+ ROUND2(DX, BP, AX, BX, CX, 32)
+ ROUND2(CX, DX, BP, AX, BX, 33)
+ ROUND2(BX, CX, DX, BP, AX, 34)
+ ROUND2(AX, BX, CX, DX, BP, 35)
+ ROUND2(BP, AX, BX, CX, DX, 36)
+ ROUND2(DX, BP, AX, BX, CX, 37)
+ ROUND2(CX, DX, BP, AX, BX, 38)
+ ROUND2(BX, CX, DX, BP, AX, 39)
+
+ ROUND3(AX, BX, CX, DX, BP, 40)
+ ROUND3(BP, AX, BX, CX, DX, 41)
+ ROUND3(DX, BP, AX, BX, CX, 42)
+ ROUND3(CX, DX, BP, AX, BX, 43)
+ ROUND3(BX, CX, DX, BP, AX, 44)
+ ROUND3(AX, BX, CX, DX, BP, 45)
+ ROUND3(BP, AX, BX, CX, DX, 46)
+ ROUND3(DX, BP, AX, BX, CX, 47)
+ ROUND3(CX, DX, BP, AX, BX, 48)
+ ROUND3(BX, CX, DX, BP, AX, 49)
+ ROUND3(AX, BX, CX, DX, BP, 50)
+ ROUND3(BP, AX, BX, CX, DX, 51)
+ ROUND3(DX, BP, AX, BX, CX, 52)
+ ROUND3(CX, DX, BP, AX, BX, 53)
+ ROUND3(BX, CX, DX, BP, AX, 54)
+ ROUND3(AX, BX, CX, DX, BP, 55)
+ ROUND3(BP, AX, BX, CX, DX, 56)
+ ROUND3(DX, BP, AX, BX, CX, 57)
+ ROUND3(CX, DX, BP, AX, BX, 58)
+ ROUND3(BX, CX, DX, BP, AX, 59)
+
+ ROUND4(AX, BX, CX, DX, BP, 60)
+ ROUND4(BP, AX, BX, CX, DX, 61)
+ ROUND4(DX, BP, AX, BX, CX, 62)
+ ROUND4(CX, DX, BP, AX, BX, 63)
+ ROUND4(BX, CX, DX, BP, AX, 64)
+ ROUND4(AX, BX, CX, DX, BP, 65)
+ ROUND4(BP, AX, BX, CX, DX, 66)
+ ROUND4(DX, BP, AX, BX, CX, 67)
+ ROUND4(CX, DX, BP, AX, BX, 68)
+ ROUND4(BX, CX, DX, BP, AX, 69)
+ ROUND4(AX, BX, CX, DX, BP, 70)
+ ROUND4(BP, AX, BX, CX, DX, 71)
+ ROUND4(DX, BP, AX, BX, CX, 72)
+ ROUND4(CX, DX, BP, AX, BX, 73)
+ ROUND4(BX, CX, DX, BP, AX, 74)
+ ROUND4(AX, BX, CX, DX, BP, 75)
+ ROUND4(BP, AX, BX, CX, DX, 76)
+ ROUND4(DX, BP, AX, BX, CX, 77)
+ ROUND4(CX, DX, BP, AX, BX, 78)
+ ROUND4(BX, CX, DX, BP, AX, 79)
+
+ ADDL 64(SP), AX
+ ADDL 68(SP), BX
+ ADDL 72(SP), CX
+ ADDL 76(SP), DX
+ ADDL 80(SP), BP
+
+ MOVL 88(SP), SI
+ ADDL $64, SI
+ CMPL SI, 84(SP)
+ JB loop
+
+end:
+ MOVL dig+0(FP), DI
+ MOVL AX, (0*4)(DI)
+ MOVL BX, (1*4)(DI)
+ MOVL CX, (2*4)(DI)
+ MOVL DX, (3*4)(DI)
+ MOVL BP, (4*4)(DI)
+ RET
diff --git a/src/pkg/crypto/sha1/sha1block_amd64.s b/src/pkg/crypto/sha1/sha1block_amd64.s
new file mode 100644
index 000000000..452578aa4
--- /dev/null
+++ b/src/pkg/crypto/sha1/sha1block_amd64.s
@@ -0,0 +1,216 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// SHA1 block routine. See sha1block.go for Go equivalent.
+//
+// There are 80 rounds of 4 types:
+// - rounds 0-15 are type 1 and load data (ROUND1 macro).
+// - rounds 16-19 are type 1 and do not load data (ROUND1x macro).
+// - rounds 20-39 are type 2 and do not load data (ROUND2 macro).
+// - rounds 40-59 are type 3 and do not load data (ROUND3 macro).
+// - rounds 60-79 are type 4 and do not load data (ROUND4 macro).
+//
+// Each round loads or shuffles the data, then computes a per-round
+// function of b, c, d, and then mixes the result into and rotates the
+// five registers a, b, c, d, e holding the intermediate results.
+//
+// The register rotation is implemented by rotating the arguments to
+// the round macros instead of by explicit move instructions.
+
+#define LOAD(index) \
+ MOVL (index*4)(SI), R10; \
+ BSWAPL R10; \
+ MOVL R10, (index*4)(SP)
+
+#define SHUFFLE(index) \
+ MOVL (((index)&0xf)*4)(SP), R10; \
+ XORL (((index-3)&0xf)*4)(SP), R10; \
+ XORL (((index-8)&0xf)*4)(SP), R10; \
+ XORL (((index-14)&0xf)*4)(SP), R10; \
+ ROLL $1, R10; \
+ MOVL R10, (((index)&0xf)*4)(SP)
+
+#define FUNC1(a, b, c, d, e) \
+ MOVL b, R8; \
+ ANDL c, R8; \
+ MOVL b, R9; \
+ NOTL R9; \
+ ANDL d, R9; \
+ ORL R8, R9
+
+#define FUNC2(a, b, c, d, e) \
+ MOVL b, R9; \
+ XORL c, R9; \
+ XORL d, R9
+
+#define FUNC3(a, b, c, d, e) \
+ MOVL b, R8; \
+ ORL c, R8; \
+ ANDL d, R8; \
+ MOVL b, R9; \
+ ANDL c, R9; \
+ ORL R8, R9
+
+#define FUNC4 FUNC2
+
+#define MIX(a, b, c, d, e, const) \
+ ROLL $30, b; \
+ ADDL R9, e; \
+ MOVL a, R8; \
+ ROLL $5, R8; \
+ LEAL const(e)(R10*1), e; \
+ ADDL R8, e
+
+#define ROUND1(a, b, c, d, e, index) \
+ LOAD(index); \
+ FUNC1(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x5A827999)
+
+#define ROUND1x(a, b, c, d, e, index) \
+ SHUFFLE(index); \
+ FUNC1(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x5A827999)
+
+#define ROUND2(a, b, c, d, e, index) \
+ SHUFFLE(index); \
+ FUNC2(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x6ED9EBA1)
+
+#define ROUND3(a, b, c, d, e, index) \
+ SHUFFLE(index); \
+ FUNC3(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0x8F1BBCDC)
+
+#define ROUND4(a, b, c, d, e, index) \
+ SHUFFLE(index); \
+ FUNC4(a, b, c, d, e); \
+ MIX(a, b, c, d, e, 0xCA62C1D6)
+
+TEXT ·block(SB),7,$64-32
+ MOVQ dig+0(FP), BP
+ MOVQ p_base+8(FP), SI
+ MOVQ p_len+16(FP), DX
+ SHRQ $6, DX
+ SHLQ $6, DX
+
+ LEAQ (SI)(DX*1), DI
+ MOVL (0*4)(BP), AX
+ MOVL (1*4)(BP), BX
+ MOVL (2*4)(BP), CX
+ MOVL (3*4)(BP), DX
+ MOVL (4*4)(BP), BP
+
+ CMPQ SI, DI
+ JEQ end
+
+loop:
+ MOVL AX, R11
+ MOVL BX, R12
+ MOVL CX, R13
+ MOVL DX, R14
+ MOVL BP, R15
+
+ ROUND1(AX, BX, CX, DX, BP, 0)
+ ROUND1(BP, AX, BX, CX, DX, 1)
+ ROUND1(DX, BP, AX, BX, CX, 2)
+ ROUND1(CX, DX, BP, AX, BX, 3)
+ ROUND1(BX, CX, DX, BP, AX, 4)
+ ROUND1(AX, BX, CX, DX, BP, 5)
+ ROUND1(BP, AX, BX, CX, DX, 6)
+ ROUND1(DX, BP, AX, BX, CX, 7)
+ ROUND1(CX, DX, BP, AX, BX, 8)
+ ROUND1(BX, CX, DX, BP, AX, 9)
+ ROUND1(AX, BX, CX, DX, BP, 10)
+ ROUND1(BP, AX, BX, CX, DX, 11)
+ ROUND1(DX, BP, AX, BX, CX, 12)
+ ROUND1(CX, DX, BP, AX, BX, 13)
+ ROUND1(BX, CX, DX, BP, AX, 14)
+ ROUND1(AX, BX, CX, DX, BP, 15)
+
+ ROUND1x(BP, AX, BX, CX, DX, 16)
+ ROUND1x(DX, BP, AX, BX, CX, 17)
+ ROUND1x(CX, DX, BP, AX, BX, 18)
+ ROUND1x(BX, CX, DX, BP, AX, 19)
+
+ ROUND2(AX, BX, CX, DX, BP, 20)
+ ROUND2(BP, AX, BX, CX, DX, 21)
+ ROUND2(DX, BP, AX, BX, CX, 22)
+ ROUND2(CX, DX, BP, AX, BX, 23)
+ ROUND2(BX, CX, DX, BP, AX, 24)
+ ROUND2(AX, BX, CX, DX, BP, 25)
+ ROUND2(BP, AX, BX, CX, DX, 26)
+ ROUND2(DX, BP, AX, BX, CX, 27)
+ ROUND2(CX, DX, BP, AX, BX, 28)
+ ROUND2(BX, CX, DX, BP, AX, 29)
+ ROUND2(AX, BX, CX, DX, BP, 30)
+ ROUND2(BP, AX, BX, CX, DX, 31)
+ ROUND2(DX, BP, AX, BX, CX, 32)
+ ROUND2(CX, DX, BP, AX, BX, 33)
+ ROUND2(BX, CX, DX, BP, AX, 34)
+ ROUND2(AX, BX, CX, DX, BP, 35)
+ ROUND2(BP, AX, BX, CX, DX, 36)
+ ROUND2(DX, BP, AX, BX, CX, 37)
+ ROUND2(CX, DX, BP, AX, BX, 38)
+ ROUND2(BX, CX, DX, BP, AX, 39)
+
+ ROUND3(AX, BX, CX, DX, BP, 40)
+ ROUND3(BP, AX, BX, CX, DX, 41)
+ ROUND3(DX, BP, AX, BX, CX, 42)
+ ROUND3(CX, DX, BP, AX, BX, 43)
+ ROUND3(BX, CX, DX, BP, AX, 44)
+ ROUND3(AX, BX, CX, DX, BP, 45)
+ ROUND3(BP, AX, BX, CX, DX, 46)
+ ROUND3(DX, BP, AX, BX, CX, 47)
+ ROUND3(CX, DX, BP, AX, BX, 48)
+ ROUND3(BX, CX, DX, BP, AX, 49)
+ ROUND3(AX, BX, CX, DX, BP, 50)
+ ROUND3(BP, AX, BX, CX, DX, 51)
+ ROUND3(DX, BP, AX, BX, CX, 52)
+ ROUND3(CX, DX, BP, AX, BX, 53)
+ ROUND3(BX, CX, DX, BP, AX, 54)
+ ROUND3(AX, BX, CX, DX, BP, 55)
+ ROUND3(BP, AX, BX, CX, DX, 56)
+ ROUND3(DX, BP, AX, BX, CX, 57)
+ ROUND3(CX, DX, BP, AX, BX, 58)
+ ROUND3(BX, CX, DX, BP, AX, 59)
+
+ ROUND4(AX, BX, CX, DX, BP, 60)
+ ROUND4(BP, AX, BX, CX, DX, 61)
+ ROUND4(DX, BP, AX, BX, CX, 62)
+ ROUND4(CX, DX, BP, AX, BX, 63)
+ ROUND4(BX, CX, DX, BP, AX, 64)
+ ROUND4(AX, BX, CX, DX, BP, 65)
+ ROUND4(BP, AX, BX, CX, DX, 66)
+ ROUND4(DX, BP, AX, BX, CX, 67)
+ ROUND4(CX, DX, BP, AX, BX, 68)
+ ROUND4(BX, CX, DX, BP, AX, 69)
+ ROUND4(AX, BX, CX, DX, BP, 70)
+ ROUND4(BP, AX, BX, CX, DX, 71)
+ ROUND4(DX, BP, AX, BX, CX, 72)
+ ROUND4(CX, DX, BP, AX, BX, 73)
+ ROUND4(BX, CX, DX, BP, AX, 74)
+ ROUND4(AX, BX, CX, DX, BP, 75)
+ ROUND4(BP, AX, BX, CX, DX, 76)
+ ROUND4(DX, BP, AX, BX, CX, 77)
+ ROUND4(CX, DX, BP, AX, BX, 78)
+ ROUND4(BX, CX, DX, BP, AX, 79)
+
+ ADDL R11, AX
+ ADDL R12, BX
+ ADDL R13, CX
+ ADDL R14, DX
+ ADDL R15, BP
+
+ ADDQ $64, SI
+ CMPQ SI, DI
+ JB loop
+
+end:
+ MOVQ dig+0(FP), DI
+ MOVL AX, (0*4)(DI)
+ MOVL BX, (1*4)(DI)
+ MOVL CX, (2*4)(DI)
+ MOVL DX, (3*4)(DI)
+ MOVL BP, (4*4)(DI)
+ RET
diff --git a/src/pkg/crypto/sha1/sha1block_decl.go b/src/pkg/crypto/sha1/sha1block_decl.go
new file mode 100644
index 000000000..3512a5829
--- /dev/null
+++ b/src/pkg/crypto/sha1/sha1block_decl.go
@@ -0,0 +1,9 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64 386
+
+package sha1
+
+func block(dig *digest, p []byte)
diff --git a/src/pkg/crypto/tls/common.go b/src/pkg/crypto/tls/common.go
index a888df762..f86c90de7 100644
--- a/src/pkg/crypto/tls/common.go
+++ b/src/pkg/crypto/tls/common.go
@@ -204,7 +204,24 @@ type Config struct {
// connections using that key are compromised.
SessionTicketKey [32]byte
- serverInitOnce sync.Once
+ serverInitOnce sync.Once // guards calling (*Config).serverInit
+}
+
+func (c *Config) serverInit() {
+ if c.SessionTicketsDisabled {
+ return
+ }
+
+ // If the key has already been set then we have nothing to do.
+ for _, b := range c.SessionTicketKey {
+ if b != 0 {
+ return
+ }
+ }
+
+ if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
+ c.SessionTicketsDisabled = true
+ }
}
func (c *Config) rand() io.Reader {
diff --git a/src/pkg/crypto/tls/handshake_server.go b/src/pkg/crypto/tls/handshake_server.go
index 730991016..823730c60 100644
--- a/src/pkg/crypto/tls/handshake_server.go
+++ b/src/pkg/crypto/tls/handshake_server.go
@@ -33,22 +33,7 @@ func (c *Conn) serverHandshake() error {
// 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
- }
- })
+ config.serverInitOnce.Do(config.serverInit)
hs := serverHandshakeState{
c: c,
diff --git a/src/pkg/crypto/x509/pkcs8.go b/src/pkg/crypto/x509/pkcs8.go
index 30caacb3c..8e1585e15 100644
--- a/src/pkg/crypto/x509/pkcs8.go
+++ b/src/pkg/crypto/x509/pkcs8.go
@@ -51,6 +51,4 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
default:
return nil, fmt.Errorf("crypto/x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
}
-
- panic("unreachable")
}
diff --git a/src/pkg/crypto/x509/x509.go b/src/pkg/crypto/x509/x509.go
index b802bf4eb..4dfea2c94 100644
--- a/src/pkg/crypto/x509/x509.go
+++ b/src/pkg/crypto/x509/x509.go
@@ -729,7 +729,6 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
default:
return nil, nil
}
- panic("unreachable")
}
func parseCertificate(in *certificate) (*Certificate, error) {
diff --git a/src/pkg/database/sql/convert.go b/src/pkg/database/sql/convert.go
index 853a7826c..5530a5d90 100644
--- a/src/pkg/database/sql/convert.go
+++ b/src/pkg/database/sql/convert.go
@@ -19,9 +19,13 @@ var errNilPtr = errors.New("destination pointer is nil") // embedded in descript
// 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) {
+// The statement ds may be nil, if no statement is available.
+func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) {
dargs := make([]driver.Value, len(args))
+ var si driver.Stmt
+ if ds != nil {
+ si = ds.si
+ }
cc, ok := si.(driver.ColumnConverter)
// Normal path, for a driver.Stmt that is not a ColumnConverter.
@@ -60,7 +64,9 @@ func driverArgs(si driver.Stmt, args []interface{}) ([]driver.Value, error) {
// column before going across the network to get the
// same error.
var err error
+ ds.Lock()
dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
+ ds.Unlock()
if err != nil {
return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err)
}
@@ -116,6 +122,12 @@ func convertAssign(dest, src interface{}) error {
}
*d = s
return nil
+ case *RawBytes:
+ if d == nil {
+ return errNilPtr
+ }
+ *d = s
+ return nil
}
case nil:
switch d := dest.(type) {
@@ -125,6 +137,12 @@ func convertAssign(dest, src interface{}) error {
}
*d = nil
return nil
+ case *RawBytes:
+ if d == nil {
+ return errNilPtr
+ }
+ *d = nil
+ return nil
}
}
@@ -141,6 +159,26 @@ func convertAssign(dest, src interface{}) error {
*d = fmt.Sprintf("%v", src)
return nil
}
+ case *[]byte:
+ sv = reflect.ValueOf(src)
+ switch sv.Kind() {
+ case reflect.Bool,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Float32, reflect.Float64:
+ *d = []byte(fmt.Sprintf("%v", src))
+ return nil
+ }
+ case *RawBytes:
+ sv = reflect.ValueOf(src)
+ switch sv.Kind() {
+ case reflect.Bool,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Float32, reflect.Float64:
+ *d = RawBytes(fmt.Sprintf("%v", src))
+ return nil
+ }
case *bool:
bv, err := driver.Bool.ConvertValue(src)
if err == nil {
diff --git a/src/pkg/database/sql/convert_test.go b/src/pkg/database/sql/convert_test.go
index 9c362d732..6aedeb0a4 100644
--- a/src/pkg/database/sql/convert_test.go
+++ b/src/pkg/database/sql/convert_test.go
@@ -22,6 +22,8 @@ type conversionTest struct {
wantint int64
wantuint uint64
wantstr string
+ wantbytes []byte
+ wantraw RawBytes
wantf32 float32
wantf64 float64
wanttime time.Time
@@ -35,6 +37,8 @@ type conversionTest struct {
// Target variables for scanning into.
var (
scanstr string
+ scanbytes []byte
+ scanraw RawBytes
scanint int
scanint8 int8
scanint16 int16
@@ -56,6 +60,7 @@ var conversionTests = []conversionTest{
{s: someTime, d: &scantime, wanttime: someTime},
// To strings
+ {s: "string", d: &scanstr, wantstr: "string"},
{s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"},
{s: 123, d: &scanstr, wantstr: "123"},
{s: int8(123), d: &scanstr, wantstr: "123"},
@@ -66,6 +71,31 @@ var conversionTests = []conversionTest{
{s: uint64(123), d: &scanstr, wantstr: "123"},
{s: 1.5, d: &scanstr, wantstr: "1.5"},
+ // To []byte
+ {s: nil, d: &scanbytes, wantbytes: nil},
+ {s: "string", d: &scanbytes, wantbytes: []byte("string")},
+ {s: []byte("byteslice"), d: &scanbytes, wantbytes: []byte("byteslice")},
+ {s: 123, d: &scanbytes, wantbytes: []byte("123")},
+ {s: int8(123), d: &scanbytes, wantbytes: []byte("123")},
+ {s: int64(123), d: &scanbytes, wantbytes: []byte("123")},
+ {s: uint8(123), d: &scanbytes, wantbytes: []byte("123")},
+ {s: uint16(123), d: &scanbytes, wantbytes: []byte("123")},
+ {s: uint32(123), d: &scanbytes, wantbytes: []byte("123")},
+ {s: uint64(123), d: &scanbytes, wantbytes: []byte("123")},
+ {s: 1.5, d: &scanbytes, wantbytes: []byte("1.5")},
+
+ // To RawBytes
+ {s: nil, d: &scanraw, wantraw: nil},
+ {s: []byte("byteslice"), d: &scanraw, wantraw: RawBytes("byteslice")},
+ {s: 123, d: &scanraw, wantraw: RawBytes("123")},
+ {s: int8(123), d: &scanraw, wantraw: RawBytes("123")},
+ {s: int64(123), d: &scanraw, wantraw: RawBytes("123")},
+ {s: uint8(123), d: &scanraw, wantraw: RawBytes("123")},
+ {s: uint16(123), d: &scanraw, wantraw: RawBytes("123")},
+ {s: uint32(123), d: &scanraw, wantraw: RawBytes("123")},
+ {s: uint64(123), d: &scanraw, wantraw: RawBytes("123")},
+ {s: 1.5, d: &scanraw, wantraw: RawBytes("1.5")},
+
// Strings to integers
{s: "255", d: &scanuint8, wantuint: 255},
{s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
diff --git a/src/pkg/database/sql/sql.go b/src/pkg/database/sql/sql.go
index 4faaa11b1..bc92ecd8e 100644
--- a/src/pkg/database/sql/sql.go
+++ b/src/pkg/database/sql/sql.go
@@ -177,26 +177,49 @@ var ErrNoRows = errors.New("sql: no rows in result set")
// DB is a database handle. It's safe for concurrent use by multiple
// goroutines.
//
-// If the underlying database driver has the concept of a connection
-// and per-connection session state, the sql package manages creating
-// and freeing connections automatically, including maintaining a free
-// pool of idle connections. If observing session state is required,
-// either do not share a *DB between multiple concurrent goroutines or
-// create and observe all state only within a transaction. Once
-// DB.Open is called, the returned Tx is bound to a single isolated
-// connection. Once Tx.Commit or Tx.Rollback is called, that
-// connection is returned to DB's idle connection pool.
+// The sql package creates and frees connections automatically; it
+// also maintains a free pool of idle connections. If the database has
+// a concept of per-connection state, such state can only be reliably
+// observed within a transaction. Once DB.Begin is called, the
+// returned Tx is bound to a single connection. Once Commit or
+// Rollback is called on the transaction, that transaction's
+// connection is returned to DB's idle connection pool. The pool size
+// can be controlled with SetMaxIdleConns.
type DB struct {
driver driver.Driver
dsn string
mu sync.Mutex // protects following fields
- outConn map[driver.Conn]bool // whether the conn is in use
- freeConn []driver.Conn
+ outConn map[*driverConn]bool // whether the conn is in use
+ freeConn []*driverConn
closed bool
dep map[finalCloser]depSet
- onConnPut map[driver.Conn][]func() // code (with mu held) run when conn is next returned
- lastPut map[driver.Conn]string // stacktrace of last conn's put; debug only
+ onConnPut map[*driverConn][]func() // code (with mu held) run when conn is next returned
+ lastPut map[*driverConn]string // stacktrace of last conn's put; debug only
+ maxIdle int // zero means defaultMaxIdleConns; negative means 0
+}
+
+// driverConn wraps a driver.Conn with a mutex, to
+// be held during all calls into the Conn. (including any calls onto
+// interfaces returned via that Conn, such as calls on Tx, Stmt,
+// Result, Rows)
+type driverConn struct {
+ sync.Mutex
+ ci driver.Conn
+}
+
+// driverStmt associates a driver.Stmt with the
+// *driverConn from which it came, so the driverConn's lock can be
+// held during calls.
+type driverStmt struct {
+ sync.Locker // the *driverConn
+ si driver.Stmt
+}
+
+func (ds *driverStmt) Close() error {
+ ds.Lock()
+ defer ds.Unlock()
+ return ds.si.Close()
}
// depSet is a finalCloser's outstanding dependencies
@@ -258,30 +281,48 @@ func (db *DB) removeDep(x finalCloser, dep interface{}) error {
//
// Most users will open a database via a driver-specific connection
// helper function that returns a *DB.
+//
+// Open may just validate its arguments without creating a connection
+// to the database. To verify that the data source name is valid, call
+// Ping.
func Open(driverName, dataSourceName string) (*DB, error) {
driveri, ok := drivers[driverName]
if !ok {
return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
}
- // TODO: optionally proactively connect to a Conn to check
- // the dataSourceName: golang.org/issue/4804
db := &DB{
driver: driveri,
dsn: dataSourceName,
- outConn: make(map[driver.Conn]bool),
- lastPut: make(map[driver.Conn]string),
- onConnPut: make(map[driver.Conn][]func()),
+ outConn: make(map[*driverConn]bool),
+ lastPut: make(map[*driverConn]string),
+ onConnPut: make(map[*driverConn][]func()),
}
return db, nil
}
+// Ping verifies a connection to the database is still alive,
+// establishing a connection if necessary.
+func (db *DB) Ping() error {
+ // TODO(bradfitz): give drivers an optional hook to implement
+ // this in a more efficient or more reliable way, if they
+ // have one.
+ dc, err := db.conn()
+ if err != nil {
+ return err
+ }
+ db.putConn(dc, nil)
+ return nil
+}
+
// Close closes the database, releasing any open resources.
func (db *DB) Close() error {
db.mu.Lock()
defer db.mu.Unlock()
var err error
- for _, c := range db.freeConn {
- err1 := c.Close()
+ for _, dc := range db.freeConn {
+ dc.Lock()
+ err1 := dc.ci.Close()
+ dc.Unlock()
if err1 != nil {
err = err1
}
@@ -291,15 +332,49 @@ func (db *DB) Close() error {
return err
}
-func (db *DB) maxIdleConns() int {
- const defaultMaxIdleConns = 2
- // TODO(bradfitz): ask driver, if supported, for its default preference
- // TODO(bradfitz): let users override?
- return defaultMaxIdleConns
+const defaultMaxIdleConns = 2
+
+func (db *DB) maxIdleConnsLocked() int {
+ n := db.maxIdle
+ switch {
+ case n == 0:
+ // TODO(bradfitz): ask driver, if supported, for its default preference
+ return defaultMaxIdleConns
+ case n < 0:
+ return 0
+ default:
+ return n
+ }
+}
+
+// SetMaxIdleConns sets the maximum number of connections in the idle
+// connection pool.
+//
+// If n <= 0, no idle connections are retained.
+func (db *DB) SetMaxIdleConns(n int) {
+ db.mu.Lock()
+ defer db.mu.Unlock()
+ if n > 0 {
+ db.maxIdle = n
+ } else {
+ // No idle connections.
+ db.maxIdle = -1
+ }
+ for len(db.freeConn) > 0 && len(db.freeConn) > n {
+ nfree := len(db.freeConn)
+ dc := db.freeConn[nfree-1]
+ db.freeConn[nfree-1] = nil
+ db.freeConn = db.freeConn[:nfree-1]
+ go func() {
+ dc.Lock()
+ dc.ci.Close()
+ dc.Unlock()
+ }()
+ }
}
-// conn returns a newly-opened or cached driver.Conn
-func (db *DB) conn() (driver.Conn, error) {
+// conn returns a newly-opened or cached *driverConn
+func (db *DB) conn() (*driverConn, error) {
db.mu.Lock()
if db.closed {
db.mu.Unlock()
@@ -313,13 +388,16 @@ func (db *DB) conn() (driver.Conn, error) {
return conn, nil
}
db.mu.Unlock()
- conn, err := db.driver.Open(db.dsn)
- if err == nil {
- db.mu.Lock()
- db.outConn[conn] = true
- db.mu.Unlock()
+
+ ci, err := db.driver.Open(db.dsn)
+ if err != nil {
+ return nil, err
}
- return conn, err
+ dc := &driverConn{ci: ci}
+ db.mu.Lock()
+ db.outConn[dc] = true
+ db.mu.Unlock()
+ return dc, nil
}
// connIfFree returns (wanted, true) if wanted is still a valid conn and
@@ -327,7 +405,7 @@ func (db *DB) conn() (driver.Conn, error) {
//
// If wanted is valid but in use, connIfFree returns (wanted, false).
// If wanted is invalid, connIfFre returns (nil, false).
-func (db *DB) connIfFree(wanted driver.Conn) (conn driver.Conn, ok bool) {
+func (db *DB) connIfFree(wanted *driverConn) (conn *driverConn, ok bool) {
db.mu.Lock()
defer db.mu.Unlock()
if db.outConn[wanted] {
@@ -346,12 +424,12 @@ func (db *DB) connIfFree(wanted driver.Conn) (conn driver.Conn, ok bool) {
}
// putConnHook is a hook for testing.
-var putConnHook func(*DB, driver.Conn)
+var putConnHook func(*DB, *driverConn)
// noteUnusedDriverStatement notes that si is no longer used and should
// be closed whenever possible (when c is next not in use), unless c is
// already closed.
-func (db *DB) noteUnusedDriverStatement(c driver.Conn, si driver.Stmt) {
+func (db *DB) noteUnusedDriverStatement(c *driverConn, si driver.Stmt) {
db.mu.Lock()
defer db.mu.Unlock()
if db.outConn[c] {
@@ -369,24 +447,24 @@ const debugGetPut = false
// putConn adds a connection to the db's free pool.
// err is optionally the last error that occurred on this connection.
-func (db *DB) putConn(c driver.Conn, err error) {
+func (db *DB) putConn(dc *driverConn, err error) {
db.mu.Lock()
- if !db.outConn[c] {
+ if !db.outConn[dc] {
if debugGetPut {
- fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", c, stack(), db.lastPut[c])
+ fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", dc, stack(), db.lastPut[dc])
}
panic("sql: connection returned that was never out")
}
if debugGetPut {
- db.lastPut[c] = stack()
+ db.lastPut[dc] = stack()
}
- delete(db.outConn, c)
+ delete(db.outConn, dc)
- if fns, ok := db.onConnPut[c]; ok {
+ if fns, ok := db.onConnPut[dc]; ok {
for _, fn := range fns {
fn()
}
- delete(db.onConnPut, c)
+ delete(db.onConnPut, dc)
}
if err == driver.ErrBadConn {
@@ -395,17 +473,20 @@ func (db *DB) putConn(c driver.Conn, err error) {
return
}
if putConnHook != nil {
- putConnHook(db, c)
+ putConnHook(db, dc)
}
- if n := len(db.freeConn); !db.closed && n < db.maxIdleConns() {
- db.freeConn = append(db.freeConn, c)
+ if n := len(db.freeConn); !db.closed && n < db.maxIdleConnsLocked() {
+ db.freeConn = append(db.freeConn, dc)
db.mu.Unlock()
return
}
// TODO: check to see if we need this Conn for any prepared
// statements which are still active?
db.mu.Unlock()
- c.Close()
+
+ dc.Lock()
+ dc.ci.Close()
+ dc.Unlock()
}
// Prepare creates a prepared statement for later queries or executions.
@@ -430,21 +511,24 @@ func (db *DB) prepare(query string) (*Stmt, error) {
// to a connection, and to execute this prepared statement
// we either need to use this connection (if it's free), else
// get a new connection + re-prepare + execute on that one.
- ci, err := db.conn()
+ dc, err := db.conn()
if err != nil {
return nil, err
}
- si, err := ci.Prepare(query)
+ dc.Lock()
+ si, err := dc.ci.Prepare(query)
+ dc.Unlock()
if err != nil {
- db.putConn(ci, err)
+ db.putConn(dc, err)
return nil, err
}
stmt := &Stmt{
db: db,
query: query,
- css: []connStmt{{ci, si}},
+ css: []connStmt{{dc, si}},
}
db.addDep(stmt, stmt)
+ db.putConn(dc, nil)
return stmt, nil
}
@@ -463,35 +547,39 @@ func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
}
func (db *DB) exec(query string, args []interface{}) (res Result, err error) {
- ci, err := db.conn()
+ dc, err := db.conn()
if err != nil {
return nil, err
}
defer func() {
- db.putConn(ci, err)
+ db.putConn(dc, err)
}()
- if execer, ok := ci.(driver.Execer); ok {
+ if execer, ok := dc.ci.(driver.Execer); ok {
dargs, err := driverArgs(nil, args)
if err != nil {
return nil, err
}
+ dc.Lock()
resi, err := execer.Exec(query, dargs)
+ dc.Unlock()
if err != driver.ErrSkip {
if err != nil {
return nil, err
}
- return result{resi}, nil
+ return driverResult{dc, resi}, nil
}
}
- sti, err := ci.Prepare(query)
+ dc.Lock()
+ si, err := dc.ci.Prepare(query)
+ dc.Unlock()
if err != nil {
return nil, err
}
- defer sti.Close()
+ defer withLock(dc, func() { si.Close() })
- return resultFromStatement(sti, args...)
+ return resultFromStatement(driverStmt{dc, si}, args...)
}
// Query executes a query that returns rows, typically a SELECT.
@@ -521,24 +609,26 @@ func (db *DB) query(query string, args []interface{}) (*Rows, error) {
// queryConn executes a query on the given connection.
// The connection gets released by the releaseConn function.
-func (db *DB) queryConn(ci driver.Conn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
- if queryer, ok := ci.(driver.Queryer); ok {
+func (db *DB) queryConn(dc *driverConn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
+ if queryer, ok := dc.ci.(driver.Queryer); ok {
dargs, err := driverArgs(nil, args)
if err != nil {
releaseConn(err)
return nil, err
}
+ dc.Lock()
rowsi, err := queryer.Query(query, dargs)
+ dc.Unlock()
if err != driver.ErrSkip {
if err != nil {
releaseConn(err)
return nil, err
}
- // Note: ownership of ci passes to the *Rows, to be freed
+ // Note: ownership of dc passes to the *Rows, to be freed
// with releaseConn.
rows := &Rows{
db: db,
- ci: ci,
+ dc: dc,
releaseConn: releaseConn,
rowsi: rowsi,
}
@@ -546,16 +636,21 @@ func (db *DB) queryConn(ci driver.Conn, releaseConn func(error), query string, a
}
}
- sti, err := ci.Prepare(query)
+ dc.Lock()
+ si, err := dc.ci.Prepare(query)
+ dc.Unlock()
if err != nil {
releaseConn(err)
return nil, err
}
- rowsi, err := rowsiFromStatement(sti, args...)
+ ds := driverStmt{dc, si}
+ rowsi, err := rowsiFromStatement(ds, args...)
if err != nil {
releaseConn(err)
- sti.Close()
+ dc.Lock()
+ si.Close()
+ dc.Unlock()
return nil, err
}
@@ -563,10 +658,10 @@ func (db *DB) queryConn(ci driver.Conn, releaseConn func(error), query string, a
// with releaseConn.
rows := &Rows{
db: db,
- ci: ci,
+ dc: dc,
releaseConn: releaseConn,
rowsi: rowsi,
- closeStmt: sti,
+ closeStmt: si,
}
return rows, nil
}
@@ -594,18 +689,20 @@ func (db *DB) Begin() (*Tx, error) {
}
func (db *DB) begin() (tx *Tx, err error) {
- ci, err := db.conn()
+ dc, err := db.conn()
if err != nil {
return nil, err
}
- txi, err := ci.Begin()
+ dc.Lock()
+ txi, err := dc.ci.Begin()
+ dc.Unlock()
if err != nil {
- db.putConn(ci, err)
+ db.putConn(dc, err)
return nil, err
}
return &Tx{
db: db,
- ci: ci,
+ dc: dc,
txi: txi,
}, nil
}
@@ -624,15 +721,11 @@ func (db *DB) Driver() driver.Driver {
type Tx struct {
db *DB
- // ci is owned exclusively until Commit or Rollback, at which point
+ // dc is owned exclusively until Commit or Rollback, at which point
// it's returned with putConn.
- ci driver.Conn
+ dc *driverConn
txi driver.Tx
- // cimu is held while somebody is using ci (between grabConn
- // and releaseConn)
- cimu sync.Mutex
-
// done transitions from false to true exactly once, on Commit
// or Rollback. once done, all operations fail with
// ErrTxDone.
@@ -646,21 +739,16 @@ func (tx *Tx) close() {
panic("double close") // internal error
}
tx.done = true
- tx.db.putConn(tx.ci, nil)
- tx.ci = nil
+ tx.db.putConn(tx.dc, nil)
+ tx.dc = nil
tx.txi = nil
}
-func (tx *Tx) grabConn() (driver.Conn, error) {
+func (tx *Tx) grabConn() (*driverConn, error) {
if tx.done {
return nil, ErrTxDone
}
- tx.cimu.Lock()
- return tx.ci, nil
-}
-
-func (tx *Tx) releaseConn() {
- tx.cimu.Unlock()
+ return tx.dc, nil
}
// Commit commits the transaction.
@@ -669,6 +757,8 @@ func (tx *Tx) Commit() error {
return ErrTxDone
}
defer tx.close()
+ tx.dc.Lock()
+ defer tx.dc.Unlock()
return tx.txi.Commit()
}
@@ -678,6 +768,8 @@ func (tx *Tx) Rollback() error {
return ErrTxDone
}
defer tx.close()
+ tx.dc.Lock()
+ defer tx.dc.Unlock()
return tx.txi.Rollback()
}
@@ -701,21 +793,25 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
// Perhaps just looking at the reference count (by noting
// Stmt.Close) would be enough. We might also want a finalizer
// on Stmt to drop the reference count.
- ci, err := tx.grabConn()
+ dc, err := tx.grabConn()
if err != nil {
return nil, err
}
- defer tx.releaseConn()
- si, err := ci.Prepare(query)
+ dc.Lock()
+ si, err := dc.ci.Prepare(query)
+ dc.Unlock()
if err != nil {
return nil, err
}
stmt := &Stmt{
- db: tx.db,
- tx: tx,
- txsi: si,
+ db: tx.db,
+ tx: tx,
+ txsi: &driverStmt{
+ Locker: dc,
+ si: si,
+ },
query: query,
}
return stmt, nil
@@ -739,16 +835,20 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
if tx.db != stmt.db {
return &Stmt{stickyErr: errors.New("sql: Tx.Stmt: statement from different database used")}
}
- ci, err := tx.grabConn()
+ dc, err := tx.grabConn()
if err != nil {
return &Stmt{stickyErr: err}
}
- defer tx.releaseConn()
- si, err := ci.Prepare(stmt.query)
+ dc.Lock()
+ si, err := dc.ci.Prepare(stmt.query)
+ dc.Unlock()
return &Stmt{
- db: tx.db,
- tx: tx,
- txsi: si,
+ db: tx.db,
+ tx: tx,
+ txsi: &driverStmt{
+ Locker: dc,
+ si: si,
+ },
query: stmt.query,
stickyErr: err,
}
@@ -757,45 +857,46 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
// Exec executes a query that doesn't return rows.
// For example: an INSERT and UPDATE.
func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
- ci, err := tx.grabConn()
+ dc, err := tx.grabConn()
if err != nil {
return nil, err
}
- defer tx.releaseConn()
- if execer, ok := ci.(driver.Execer); ok {
+ if execer, ok := dc.ci.(driver.Execer); ok {
dargs, err := driverArgs(nil, args)
if err != nil {
return nil, err
}
+ dc.Lock()
resi, err := execer.Exec(query, dargs)
+ dc.Unlock()
if err == nil {
- return result{resi}, nil
+ return driverResult{dc, resi}, nil
}
if err != driver.ErrSkip {
return nil, err
}
}
- sti, err := ci.Prepare(query)
+ dc.Lock()
+ si, err := dc.ci.Prepare(query)
+ dc.Unlock()
if err != nil {
return nil, err
}
- defer sti.Close()
+ defer withLock(dc, func() { si.Close() })
- return resultFromStatement(sti, args...)
+ return resultFromStatement(driverStmt{dc, si}, args...)
}
// Query executes a query that returns rows, typically a SELECT.
func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
- ci, err := tx.grabConn()
+ dc, err := tx.grabConn()
if err != nil {
return nil, err
}
-
- releaseConn := func(err error) { tx.releaseConn() }
-
- return tx.db.queryConn(ci, releaseConn, query, args)
+ releaseConn := func(error) {}
+ return tx.db.queryConn(dc, releaseConn, query, args)
}
// QueryRow executes a query that is expected to return at most one row.
@@ -808,7 +909,7 @@ func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
// connStmt is a prepared statement on a particular connection.
type connStmt struct {
- ci driver.Conn
+ dc *driverConn
si driver.Stmt
}
@@ -823,7 +924,7 @@ type Stmt struct {
// If in a transaction, else both nil:
tx *Tx
- txsi driver.Stmt
+ txsi *driverStmt
mu sync.Mutex // protects the rest of the fields
closed bool
@@ -840,39 +941,45 @@ type Stmt struct {
func (s *Stmt) Exec(args ...interface{}) (Result, error) {
s.closemu.RLock()
defer s.closemu.RUnlock()
- _, releaseConn, si, err := s.connStmt()
+ dc, releaseConn, si, err := s.connStmt()
if err != nil {
return nil, err
}
defer releaseConn(nil)
- return resultFromStatement(si, args...)
+ return resultFromStatement(driverStmt{dc, si}, args...)
}
-func resultFromStatement(si driver.Stmt, args ...interface{}) (Result, error) {
+func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) {
+ ds.Lock()
+ want := ds.si.NumInput()
+ ds.Unlock()
+
// -1 means the driver doesn't know how to count the number of
// placeholders, so we won't sanity check input here and instead let the
// driver deal with errors.
- if want := si.NumInput(); want != -1 && len(args) != want {
+ if want != -1 && len(args) != want {
return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
}
- dargs, err := driverArgs(si, args)
+ dargs, err := driverArgs(&ds, args)
if err != nil {
return nil, err
}
- resi, err := si.Exec(dargs)
+ ds.Lock()
+ resi, err := ds.si.Exec(dargs)
+ ds.Unlock()
if err != nil {
return nil, err
}
- return result{resi}, nil
+ return driverResult{ds.Locker, resi}, nil
}
// connStmt returns a free driver connection on which to execute the
// statement, a function to call to release the connection, and a
// statement bound to that connection.
-func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(error), si driver.Stmt, err error) {
+func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.Stmt, err error) {
if err = s.stickyErr; err != nil {
return
}
@@ -891,8 +998,8 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(error), si driver.St
if err != nil {
return
}
- releaseConn = func(error) { s.tx.releaseConn() }
- return ci, releaseConn, s.txsi, nil
+ releaseConn = func(error) {}
+ return ci, releaseConn, s.txsi.si, nil
}
var cs connStmt
@@ -900,7 +1007,7 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(error), si driver.St
for _, v := range s.css {
// TODO(bradfitz): lazily clean up entries in this
// list with dead conns while enumerating
- if _, match = s.db.connIfFree(v.ci); match {
+ if _, match = s.db.connIfFree(v.dc); match {
cs = v
break
}
@@ -911,11 +1018,13 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(error), si driver.St
// TODO(bradfitz): or wait for one? make configurable later?
if !match {
for i := 0; ; i++ {
- ci, err := s.db.conn()
+ dc, err := s.db.conn()
if err != nil {
return nil, nil, nil, err
}
- si, err := ci.Prepare(s.query)
+ dc.Lock()
+ si, err := dc.ci.Prepare(s.query)
+ dc.Unlock()
if err == driver.ErrBadConn && i < 10 {
continue
}
@@ -923,14 +1032,14 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(error), si driver.St
return nil, nil, nil, err
}
s.mu.Lock()
- cs = connStmt{ci, si}
+ cs = connStmt{dc, si}
s.css = append(s.css, cs)
s.mu.Unlock()
break
}
}
- conn := cs.ci
+ conn := cs.dc
releaseConn = func(err error) { s.db.putConn(conn, err) }
return conn, releaseConn, cs.si, nil
}
@@ -941,12 +1050,13 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
s.closemu.RLock()
defer s.closemu.RUnlock()
- ci, releaseConn, si, err := s.connStmt()
+ dc, releaseConn, si, err := s.connStmt()
if err != nil {
return nil, err
}
- rowsi, err := rowsiFromStatement(si, args...)
+ ds := driverStmt{dc, si}
+ rowsi, err := rowsiFromStatement(ds, args...)
if err != nil {
releaseConn(err)
return nil, err
@@ -956,7 +1066,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
// with releaseConn.
rows := &Rows{
db: s.db,
- ci: ci,
+ dc: dc,
rowsi: rowsi,
// releaseConn set below
}
@@ -968,20 +1078,26 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
return rows, nil
}
-func rowsiFromStatement(si driver.Stmt, args ...interface{}) (driver.Rows, error) {
+func rowsiFromStatement(ds driverStmt, args ...interface{}) (driver.Rows, error) {
+ ds.Lock()
+ want := ds.si.NumInput()
+ ds.Unlock()
+
// -1 means the driver doesn't know how to count the number of
// placeholders, so we won't sanity check input here and instead let the
// driver deal with errors.
- if want := si.NumInput(); want != -1 && len(args) != want {
- return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", si.NumInput(), len(args))
+ if want != -1 && len(args) != want {
+ return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", want, len(args))
}
- dargs, err := driverArgs(si, args)
+ dargs, err := driverArgs(&ds, args)
if err != nil {
return nil, err
}
- rowsi, err := si.Query(dargs)
+ ds.Lock()
+ rowsi, err := ds.si.Query(dargs)
+ ds.Unlock()
if err != nil {
return nil, err
}
@@ -1032,7 +1148,7 @@ func (s *Stmt) Close() error {
func (s *Stmt) finalClose() error {
for _, v := range s.css {
- s.db.noteUnusedDriverStatement(v.ci, v.si)
+ s.db.noteUnusedDriverStatement(v.dc, v.si)
}
s.css = nil
return nil
@@ -1053,7 +1169,7 @@ func (s *Stmt) finalClose() error {
// ...
type Rows struct {
db *DB
- ci driver.Conn // owned; must call releaseConn when closed to release
+ dc *driverConn // owned; must call releaseConn when closed to release
releaseConn func(error)
rowsi driver.Rows
@@ -1226,11 +1342,31 @@ type Result interface {
RowsAffected() (int64, error)
}
-type result struct {
- driver.Result
+type driverResult struct {
+ sync.Locker // the *driverConn
+ resi driver.Result
+}
+
+func (dr driverResult) LastInsertId() (int64, error) {
+ dr.Lock()
+ defer dr.Unlock()
+ return dr.resi.LastInsertId()
+}
+
+func (dr driverResult) RowsAffected() (int64, error) {
+ dr.Lock()
+ defer dr.Unlock()
+ return dr.resi.RowsAffected()
}
func stack() string {
var buf [1024]byte
return string(buf[:runtime.Stack(buf[:], false)])
}
+
+// withLock runs while holding lk.
+func withLock(lk sync.Locker, fn func()) {
+ lk.Lock()
+ fn()
+ lk.Unlock()
+}
diff --git a/src/pkg/database/sql/sql_test.go b/src/pkg/database/sql/sql_test.go
index 53b229600..2a9592e10 100644
--- a/src/pkg/database/sql/sql_test.go
+++ b/src/pkg/database/sql/sql_test.go
@@ -5,7 +5,6 @@
package sql
import (
- "database/sql/driver"
"fmt"
"reflect"
"strings"
@@ -16,10 +15,10 @@ import (
func init() {
type dbConn struct {
db *DB
- c driver.Conn
+ c *driverConn
}
freedFrom := make(map[dbConn]string)
- putConnHook = func(db *DB, c driver.Conn) {
+ putConnHook = func(db *DB, c *driverConn) {
for _, oc := range db.freeConn {
if oc == c {
// print before panic, as panic may get lost due to conflicting panic
@@ -78,7 +77,7 @@ func numPrepares(t *testing.T, db *DB) int {
if n := len(db.freeConn); n != 1 {
t.Fatalf("free conns = %d; want 1", n)
}
- return db.freeConn[0].(*fakeConn).numPrepare
+ return db.freeConn[0].ci.(*fakeConn).numPrepare
}
func TestQuery(t *testing.T) {
@@ -576,7 +575,7 @@ func TestQueryRowClosingStmt(t *testing.T) {
if len(db.freeConn) != 1 {
t.Fatalf("expected 1 free conn")
}
- fakeConn := db.freeConn[0].(*fakeConn)
+ fakeConn := db.freeConn[0].ci.(*fakeConn)
if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed {
t.Errorf("statement close mismatch: made %d, closed %d", made, closed)
}
@@ -708,3 +707,86 @@ func TestQueryRowNilScanDest(t *testing.T) {
t.Errorf("error = %q; want %q", err.Error(), want)
}
}
+
+func TestIssue4902(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ driver := db.driver.(*fakeDriver)
+ opens0 := driver.openCount
+
+ var stmt *Stmt
+ var err error
+ for i := 0; i < 10; i++ {
+ stmt, err = db.Prepare("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = stmt.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ opens := driver.openCount - opens0
+ if opens > 1 {
+ t.Errorf("opens = %d; want <= 1", opens)
+ t.Logf("db = %#v", db)
+ t.Logf("driver = %#v", driver)
+ t.Logf("stmt = %#v", stmt)
+ }
+}
+
+// Issue 3857
+// This used to deadlock.
+func TestSimultaneousQueries(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer tx.Rollback()
+
+ r1, err := tx.Query("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r1.Close()
+
+ r2, err := tx.Query("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r2.Close()
+}
+
+func TestMaxIdleConns(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ tx.Commit()
+ if got := len(db.freeConn); got != 1 {
+ t.Errorf("freeConns = %d; want 1", got)
+ }
+
+ db.SetMaxIdleConns(0)
+
+ if got := len(db.freeConn); got != 0 {
+ t.Errorf("freeConns after set to zero = %d; want 0", got)
+ }
+
+ tx, err = db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ tx.Commit()
+ if got := len(db.freeConn); got != 0 {
+ t.Errorf("freeConns = %d; want 0", got)
+ }
+}
diff --git a/src/pkg/debug/dwarf/buf.go b/src/pkg/debug/dwarf/buf.go
index 6dc28d256..53c46eb4b 100644
--- a/src/pkg/debug/dwarf/buf.go
+++ b/src/pkg/debug/dwarf/buf.go
@@ -13,17 +13,45 @@ import (
// Data buffer being decoded.
type buf struct {
- dwarf *Data
- order binary.ByteOrder
- name string
- off Offset
- data []byte
- addrsize int
- err error
+ dwarf *Data
+ order binary.ByteOrder
+ format dataFormat
+ name string
+ off Offset
+ data []byte
+ err error
}
-func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf {
- return buf{d, d.order, name, off, data, addrsize, nil}
+// Data format, other than byte order. This affects the handling of
+// certain field formats.
+type dataFormat interface {
+ // DWARF version number. Zero means unknown.
+ version() int
+
+ // 64-bit DWARF format?
+ dwarf64() (dwarf64 bool, isKnown bool)
+
+ // Size of an address, in bytes. Zero means unknown.
+ addrsize() int
+}
+
+// Some parts of DWARF have no data format, e.g., abbrevs.
+type unknownFormat struct{}
+
+func (u unknownFormat) version() int {
+ return 0
+}
+
+func (u unknownFormat) dwarf64() (bool, bool) {
+ return false, false
+}
+
+func (u unknownFormat) addrsize() int {
+ return 0
+}
+
+func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf {
+ return buf{d, d.order, format, name, off, data, nil}
}
func (b *buf) uint8() uint8 {
@@ -121,7 +149,7 @@ func (b *buf) int() int64 {
// Address-sized uint.
func (b *buf) addr() uint64 {
- switch b.addrsize {
+ switch b.format.addrsize() {
case 1:
return uint64(b.uint8())
case 2:
diff --git a/src/pkg/debug/dwarf/entry.go b/src/pkg/debug/dwarf/entry.go
index f376e4088..13d8d5ecf 100644
--- a/src/pkg/debug/dwarf/entry.go
+++ b/src/pkg/debug/dwarf/entry.go
@@ -40,7 +40,7 @@ func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) {
} else {
data = data[off:]
}
- b := makeBuf(d, "abbrev", 0, data, 0)
+ b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
// Error handling is simplified by the buf getters
// returning an endless stream of 0s after an error.
@@ -192,7 +192,21 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
// reference to other entry
case formRefAddr:
- val = Offset(b.addr())
+ vers := b.format.version()
+ if vers == 0 {
+ b.error("unknown version for DW_FORM_ref_addr")
+ } else if vers == 2 {
+ val = Offset(b.addr())
+ } else {
+ is64, known := b.format.dwarf64()
+ if !known {
+ b.error("unknown size for DW_FORM_ref_addr")
+ } else if is64 {
+ val = Offset(b.uint64())
+ } else {
+ val = Offset(b.uint32())
+ }
+ }
case formRef1:
val = Offset(b.uint8()) + ubase
case formRef2:
@@ -212,7 +226,7 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
if b.err != nil {
return nil
}
- b1 := makeBuf(b.dwarf, "str", 0, b.dwarf.str, 0)
+ b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str)
b1.skip(int(off))
val = b1.string()
if b1.err != nil {
@@ -262,7 +276,7 @@ func (r *Reader) Seek(off Offset) {
}
u := &d.unit[0]
r.unit = 0
- r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize)
+ r.b = makeBuf(r.d, u, "info", u.off, u.data)
return
}
@@ -273,7 +287,7 @@ func (r *Reader) Seek(off Offset) {
u = &d.unit[i]
if u.off <= off && off < u.off+Offset(len(u.data)) {
r.unit = i
- r.b = makeBuf(r.d, "info", off, u.data[off-u.off:], u.addrsize)
+ r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
return
}
}
@@ -285,7 +299,7 @@ func (r *Reader) maybeNextUnit() {
for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
r.unit++
u := &r.d.unit[r.unit]
- r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize)
+ r.b = makeBuf(r.d, u, "info", u.off, u.data)
}
}
diff --git a/src/pkg/debug/dwarf/type.go b/src/pkg/debug/dwarf/type.go
index 450235502..54000fbd7 100644
--- a/src/pkg/debug/dwarf/type.go
+++ b/src/pkg/debug/dwarf/type.go
@@ -435,7 +435,9 @@ func (d *Data) Type(off Offset) (Type, error) {
goto Error
}
if loc, ok := kid.Val(AttrDataMemberLoc).([]byte); ok {
- b := makeBuf(d, "location", 0, loc, d.addrsize)
+ // TODO: Should have original compilation
+ // unit here, not unknownFormat.
+ b := makeBuf(d, unknownFormat{}, "location", 0, loc)
if b.uint8() != opPlusUconst {
err = DecodeError{"info", kid.Offset, "unexpected opcode"}
goto Error
diff --git a/src/pkg/debug/dwarf/unit.go b/src/pkg/debug/dwarf/unit.go
index c10d75dbd..270cd2e33 100644
--- a/src/pkg/debug/dwarf/unit.go
+++ b/src/pkg/debug/dwarf/unit.go
@@ -10,19 +10,44 @@ import "strconv"
// Each unit has its own abbreviation table and address size.
type unit struct {
- base Offset // byte offset of header within the aggregate info
- off Offset // byte offset of data within the aggregate info
- data []byte
- atable abbrevTable
- addrsize int
+ base Offset // byte offset of header within the aggregate info
+ off Offset // byte offset of data within the aggregate info
+ data []byte
+ atable abbrevTable
+ asize int
+ vers int
+ is64 bool // True for 64-bit DWARF format
+}
+
+// Implement the dataFormat interface.
+
+func (u *unit) version() int {
+ return u.vers
+}
+
+func (u *unit) dwarf64() (bool, bool) {
+ return u.is64, true
+}
+
+func (u *unit) addrsize() int {
+ return u.asize
}
func (d *Data) parseUnits() ([]unit, error) {
// Count units.
nunit := 0
- b := makeBuf(d, "info", 0, d.info, 0)
+ b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
for len(b.data) > 0 {
- b.skip(int(b.uint32()))
+ len := b.uint32()
+ if len == 0xffffffff {
+ len64 := b.uint64()
+ if len64 != uint64(uint32(len64)) {
+ b.error("unit length overflow")
+ break
+ }
+ len = uint32(len64)
+ }
+ b.skip(int(len))
nunit++
}
if b.err != nil {
@@ -30,16 +55,22 @@ func (d *Data) parseUnits() ([]unit, error) {
}
// Again, this time writing them down.
- b = makeBuf(d, "info", 0, d.info, 0)
+ b = makeBuf(d, unknownFormat{}, "info", 0, d.info)
units := make([]unit, nunit)
for i := range units {
u := &units[i]
u.base = b.off
n := b.uint32()
- if vers := b.uint16(); vers != 2 {
+ if n == 0xffffffff {
+ u.is64 = true
+ n = uint32(b.uint64())
+ }
+ vers := b.uint16()
+ if vers != 2 && vers != 3 {
b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
break
}
+ u.vers = int(vers)
atable, err := d.parseAbbrev(b.uint32())
if err != nil {
if b.err == nil {
@@ -48,7 +79,7 @@ func (d *Data) parseUnits() ([]unit, error) {
break
}
u.atable = atable
- u.addrsize = int(b.uint8())
+ u.asize = int(b.uint8())
u.off = b.off
u.data = b.bytes(int(n - (2 + 4 + 1)))
}
diff --git a/src/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go
index acb9817af..a55c37ea9 100644
--- a/src/pkg/debug/elf/file.go
+++ b/src/pkg/debug/elf/file.go
@@ -422,6 +422,10 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
return nil, nil, errors.New("cannot load string table section")
}
+ // The first entry is all zeros.
+ var skip [Sym32Size]byte
+ symtab.Read(skip[:])
+
symbols := make([]Symbol, symtab.Len()/Sym32Size)
i := 0
@@ -461,6 +465,10 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
return nil, nil, errors.New("cannot load string table section")
}
+ // The first entry is all zeros.
+ var skip [Sym64Size]byte
+ symtab.Read(skip[:])
+
symbols := make([]Symbol, symtab.Len()/Sym64Size)
i := 0
@@ -533,10 +541,10 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
symNo := rela.Info >> 32
t := R_X86_64(rela.Info & 0xffff)
- if symNo >= uint64(len(symbols)) {
+ if symNo == 0 || symNo > uint64(len(symbols)) {
continue
}
- sym := &symbols[symNo]
+ sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION {
// We don't handle non-section relocations for now.
continue
@@ -597,6 +605,10 @@ func (f *File) DWARF() (*dwarf.Data, error) {
}
// Symbols returns the symbol table for f.
+//
+// For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
+// After retrieving the symbols as symtab, an externally supplied index x
+// corresponds to symtab[x-1], not symtab[x].
func (f *File) Symbols() ([]Symbol, error) {
sym, _, err := f.getSymbols(SHT_SYMTAB)
return sym, err
@@ -706,7 +718,7 @@ func (f *File) gnuVersionInit(str []byte) {
// which came from offset i of the symbol table.
func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
// Each entry is two bytes.
- i = i * 2
+ i = (i + 1) * 2
if i >= len(f.gnuVersym) {
return
}
diff --git a/src/pkg/debug/macho/file.go b/src/pkg/debug/macho/file.go
index fa73a315c..f5f0dedb7 100644
--- a/src/pkg/debug/macho/file.go
+++ b/src/pkg/debug/macho/file.go
@@ -142,6 +142,8 @@ type Dysymtab struct {
* Mach-O reader
*/
+// FormatError is returned by some operations if the data does
+// not have the correct format for an object file.
type FormatError struct {
off int64
msg string
diff --git a/src/pkg/encoding/ascii85/ascii85.go b/src/pkg/encoding/ascii85/ascii85.go
index 705022792..e2afc5871 100644
--- a/src/pkg/encoding/ascii85/ascii85.go
+++ b/src/pkg/encoding/ascii85/ascii85.go
@@ -296,5 +296,4 @@ func (d *decoder) Read(p []byte) (n int, err error) {
nn, d.readErr = d.r.Read(d.buf[d.nbuf:])
d.nbuf += nn
}
- panic("unreachable")
}
diff --git a/src/pkg/encoding/asn1/marshal.go b/src/pkg/encoding/asn1/marshal.go
index 0c216fdb3..adaf80dcd 100644
--- a/src/pkg/encoding/asn1/marshal.go
+++ b/src/pkg/encoding/asn1/marshal.go
@@ -460,7 +460,6 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
default:
return marshalUTF8String(out, v.String())
}
- return
}
return StructuralError{"unknown Go type"}
diff --git a/src/pkg/encoding/base32/base32.go b/src/pkg/encoding/base32/base32.go
index dbefc48fa..fe17b7322 100644
--- a/src/pkg/encoding/base32/base32.go
+++ b/src/pkg/encoding/base32/base32.go
@@ -6,8 +6,10 @@
package base32
import (
+ "bytes"
"io"
"strconv"
+ "strings"
)
/*
@@ -48,6 +50,13 @@ var StdEncoding = NewEncoding(encodeStd)
// It is typically used in DNS.
var HexEncoding = NewEncoding(encodeHex)
+var removeNewlinesMapper = func(r rune) rune {
+ if r == '\r' || r == '\n' {
+ return -1
+ }
+ return r
+}
+
/*
* Encoder
*/
@@ -228,40 +237,47 @@ func (e CorruptInputError) Error() string {
// decode is like Decode but returns an additional 'end' value, which
// indicates if end-of-message padding was encountered and thus any
-// additional data is an error.
+// additional data is an error. This method assumes that src has been
+// stripped of all supported whitespace ('\r' and '\n').
func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
- osrc := src
+ olen := len(src)
for len(src) > 0 && !end {
// Decode quantum using the base32 alphabet
var dbuf [8]byte
dlen := 8
- // do the top bytes contain any data?
for j := 0; j < 8; {
if len(src) == 0 {
- return n, false, CorruptInputError(len(osrc) - len(src) - j)
+ return n, false, CorruptInputError(olen - len(src) - j)
}
in := src[0]
src = src[1:]
- if in == '\r' || in == '\n' {
- // Ignore this character.
- continue
- }
if in == '=' && j >= 2 && len(src) < 8 {
- // We've reached the end and there's
- // padding, the rest should be padded
- for k := 0; k < 8-j-1; k++ {
+ // We've reached the end and there's padding
+ if len(src)+j < 8-1 {
+ // not enough padding
+ return n, false, CorruptInputError(olen)
+ }
+ for k := 0; k < 8-1-j; k++ {
if len(src) > k && src[k] != '=' {
- return n, false, CorruptInputError(len(osrc) - len(src) + k - 1)
+ // incorrect padding
+ return n, false, CorruptInputError(olen - len(src) + k - 1)
}
}
- dlen = j
- end = true
+ dlen, end = j, true
+ // 7, 5 and 2 are not valid padding lengths, and so 1, 3 and 6 are not
+ // valid dlen values. See RFC 4648 Section 6 "Base 32 Encoding" listing
+ // the five valid padding lengths, and Section 9 "Illustrations and
+ // Examples" for an illustration for how the the 1st, 3rd and 6th base32
+ // src bytes do not yield enough information to decode a dst byte.
+ if dlen == 1 || dlen == 3 || dlen == 6 {
+ return n, false, CorruptInputError(olen - len(src) - 1)
+ }
break
}
dbuf[j] = enc.decodeMap[in]
if dbuf[j] == 0xFF {
- return n, false, CorruptInputError(len(osrc) - len(src) - 1)
+ return n, false, CorruptInputError(olen - len(src) - 1)
}
j++
}
@@ -269,16 +285,16 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
// Pack 8x 5-bit source blocks into 5 byte destination
// quantum
switch dlen {
- case 7, 8:
+ case 8:
dst[4] = dbuf[6]<<5 | dbuf[7]
fallthrough
- case 6, 5:
+ case 7:
dst[3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
fallthrough
- case 4:
+ case 5:
dst[2] = dbuf[3]<<4 | dbuf[4]>>1
fallthrough
- case 3:
+ case 4:
dst[1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
fallthrough
case 2:
@@ -288,11 +304,11 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
switch dlen {
case 2:
n += 1
- case 3, 4:
+ case 4:
n += 2
case 5:
n += 3
- case 6, 7:
+ case 7:
n += 4
case 8:
n += 5
@@ -307,12 +323,14 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
// number of bytes successfully written and CorruptInputError.
// New line characters (\r and \n) are ignored.
func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
+ src = bytes.Map(removeNewlinesMapper, src)
n, _, err = enc.decode(dst, src)
return
}
// DecodeString returns the bytes represented by the base32 string s.
func (enc *Encoding) DecodeString(s string) ([]byte, error) {
+ s = strings.Map(removeNewlinesMapper, s)
dbuf := make([]byte, enc.DecodedLen(len(s)))
n, err := enc.Decode(dbuf, []byte(s))
return dbuf[:n], err
@@ -377,9 +395,34 @@ func (d *decoder) Read(p []byte) (n int, err error) {
return n, d.err
}
+type newlineFilteringReader struct {
+ wrapped io.Reader
+}
+
+func (r *newlineFilteringReader) Read(p []byte) (int, error) {
+ n, err := r.wrapped.Read(p)
+ for n > 0 {
+ offset := 0
+ for i, b := range p[0:n] {
+ if b != '\r' && b != '\n' {
+ if i != offset {
+ p[offset] = b
+ }
+ offset++
+ }
+ }
+ if offset > 0 {
+ return offset, err
+ }
+ // Previous buffer entirely whitespace, read again
+ n, err = r.wrapped.Read(p)
+ }
+ return n, err
+}
+
// NewDecoder constructs a new base32 stream decoder.
func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
- return &decoder{enc: enc, r: r}
+ return &decoder{enc: enc, r: &newlineFilteringReader{r}}
}
// DecodedLen returns the maximum length in bytes of the decoded data
diff --git a/src/pkg/encoding/base32/base32_test.go b/src/pkg/encoding/base32/base32_test.go
index 98365e18c..63298d1c9 100644
--- a/src/pkg/encoding/base32/base32_test.go
+++ b/src/pkg/encoding/base32/base32_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"io"
"io/ioutil"
+ "strings"
"testing"
)
@@ -137,27 +138,48 @@ func TestDecoderBuffering(t *testing.T) {
}
func TestDecodeCorrupt(t *testing.T) {
- type corrupt struct {
- e string
- p int
- }
- examples := []corrupt{
+ testCases := []struct {
+ input string
+ offset int // -1 means no corruption.
+ }{
+ {"", -1},
{"!!!!", 0},
{"x===", 0},
{"AA=A====", 2},
{"AAA=AAAA", 3},
{"MMMMMMMMM", 8},
{"MMMMMM", 0},
+ {"A=", 1},
+ {"AA=", 3},
+ {"AA==", 4},
+ {"AA===", 5},
+ {"AAAA=", 5},
+ {"AAAA==", 6},
+ {"AAAAA=", 6},
+ {"AAAAA==", 7},
+ {"A=======", 1},
+ {"AA======", -1},
+ {"AAA=====", 3},
+ {"AAAA====", -1},
+ {"AAAAA===", -1},
+ {"AAAAAA==", 6},
+ {"AAAAAAA=", -1},
+ {"AAAAAAAA", -1},
}
-
- for _, e := range examples {
- dbuf := make([]byte, StdEncoding.DecodedLen(len(e.e)))
- _, err := StdEncoding.Decode(dbuf, []byte(e.e))
+ for _, tc := range testCases {
+ dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
+ _, err := StdEncoding.Decode(dbuf, []byte(tc.input))
+ if tc.offset == -1 {
+ if err != nil {
+ t.Error("Decoder wrongly detected coruption in", tc.input)
+ }
+ continue
+ }
switch err := err.(type) {
case CorruptInputError:
- testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
+ testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
default:
- t.Error("Decoder failed to detect corruption in", e)
+ t.Error("Decoder failed to detect corruption in", tc)
}
}
}
@@ -195,9 +217,21 @@ func TestBig(t *testing.T) {
}
}
+func testStringEncoding(t *testing.T, expected string, examples []string) {
+ for _, e := range examples {
+ buf, err := StdEncoding.DecodeString(e)
+ if err != nil {
+ t.Errorf("Decode(%q) failed: %v", e, err)
+ continue
+ }
+ if s := string(buf); s != expected {
+ t.Errorf("Decode(%q) = %q, want %q", e, s, expected)
+ }
+ }
+}
+
func TestNewLineCharacters(t *testing.T) {
// Each of these should decode to the string "sure", without errors.
- const expected = "sure"
examples := []string{
"ON2XEZI=",
"ON2XEZI=\r",
@@ -209,14 +243,44 @@ func TestNewLineCharacters(t *testing.T) {
"ON2XEZ\nI=",
"ON2XEZI\n=",
}
- for _, e := range examples {
- buf, err := StdEncoding.DecodeString(e)
- if err != nil {
- t.Errorf("Decode(%q) failed: %v", e, err)
- continue
- }
- if s := string(buf); s != expected {
- t.Errorf("Decode(%q) = %q, want %q", e, s, expected)
- }
+ testStringEncoding(t, "sure", examples)
+
+ // Each of these should decode to the string "foobar", without errors.
+ examples = []string{
+ "MZXW6YTBOI======",
+ "MZXW6YTBOI=\r\n=====",
+ }
+ testStringEncoding(t, "foobar", examples)
+}
+
+func TestDecoderIssue4779(t *testing.T) {
+ encoded := `JRXXEZLNEBUXA43VNUQGI33MN5ZCA43JOQQGC3LFOQWCAY3PNZZWKY3UMV2HK4
+RAMFSGS4DJONUWG2LOM4QGK3DJOQWCA43FMQQGI3YKMVUXK43NN5SCA5DFNVYG64RANFXGG2LENFSH
+K3TUEB2XIIDMMFRG64TFEBSXIIDEN5WG64TFEBWWCZ3OMEQGC3DJOF2WCLRAKV2CAZLONFWQUYLEEB
+WWS3TJNUQHMZLONFQW2LBAOF2WS4ZANZXXG5DSOVSCAZLYMVZGG2LUMF2GS33OEB2WY3DBNVRW6IDM
+MFRG64TJOMQG42LTNEQHK5AKMFWGS4LVNFYCAZLYEBSWCIDDN5WW233EN4QGG33OONSXC5LBOQXCAR
+DVNFZSAYLVORSSA2LSOVZGKIDEN5WG64RANFXAU4TFOBZGK2DFNZSGK4TJOQQGS3RAOZXWY5LQORQX
+IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF
+2HK4ROEBCXQY3FOB2GK5LSEBZWS3TUEBXWGY3BMVRWC5BAMN2XA2LEMF2GC5BANZXW4IDQOJXWSZDF
+NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42
+LNEBUWIIDFON2CA3DBMJXXE5LNFY==
+====`
+ encodedShort := strings.Replace(encoded, "\n", "", -1)
+
+ dec := NewDecoder(StdEncoding, bytes.NewBufferString(encoded))
+ res1, err := ioutil.ReadAll(dec)
+ if err != nil {
+ t.Errorf("ReadAll failed: %v", err)
+ }
+
+ dec = NewDecoder(StdEncoding, bytes.NewBufferString(encodedShort))
+ var res2 []byte
+ res2, err = ioutil.ReadAll(dec)
+ if err != nil {
+ t.Errorf("ReadAll failed: %v", err)
+ }
+
+ if !bytes.Equal(res1, res2) {
+ t.Error("Decoded results not equal")
}
}
diff --git a/src/pkg/encoding/base64/base64.go b/src/pkg/encoding/base64/base64.go
index e66672a1c..85e398fd0 100644
--- a/src/pkg/encoding/base64/base64.go
+++ b/src/pkg/encoding/base64/base64.go
@@ -6,8 +6,10 @@
package base64
import (
+ "bytes"
"io"
"strconv"
+ "strings"
)
/*
@@ -49,6 +51,13 @@ var StdEncoding = NewEncoding(encodeStd)
// It is typically used in URLs and file names.
var URLEncoding = NewEncoding(encodeURL)
+var removeNewlinesMapper = func(r rune) rune {
+ if r == '\r' || r == '\n' {
+ return -1
+ }
+ return r
+}
+
/*
* Encoder
*/
@@ -208,9 +217,10 @@ func (e CorruptInputError) Error() string {
// decode is like Decode but returns an additional 'end' value, which
// indicates if end-of-message padding was encountered and thus any
-// additional data is an error.
+// additional data is an error. This method assumes that src has been
+// stripped of all supported whitespace ('\r' and '\n').
func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
- osrc := src
+ olen := len(src)
for len(src) > 0 && !end {
// Decode quantum using the base64 alphabet
var dbuf [4]byte
@@ -218,32 +228,26 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
for j := 0; j < 4; {
if len(src) == 0 {
- return n, false, CorruptInputError(len(osrc) - len(src) - j)
+ return n, false, CorruptInputError(olen - len(src) - j)
}
in := src[0]
src = src[1:]
- if in == '\r' || in == '\n' {
- // Ignore this character.
- continue
- }
if in == '=' && j >= 2 && len(src) < 4 {
- // We've reached the end and there's
- // padding
- if len(src) == 0 && j == 2 {
+ // We've reached the end and there's padding
+ if len(src)+j < 4-1 {
// not enough padding
- return n, false, CorruptInputError(len(osrc))
+ return n, false, CorruptInputError(olen)
}
if len(src) > 0 && src[0] != '=' {
// incorrect padding
- return n, false, CorruptInputError(len(osrc) - len(src) - 1)
+ return n, false, CorruptInputError(olen - len(src) - 1)
}
- dlen = j
- end = true
+ dlen, end = j, true
break
}
dbuf[j] = enc.decodeMap[in]
if dbuf[j] == 0xFF {
- return n, false, CorruptInputError(len(osrc) - len(src) - 1)
+ return n, false, CorruptInputError(olen - len(src) - 1)
}
j++
}
@@ -273,12 +277,14 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
// number of bytes successfully written and CorruptInputError.
// New line characters (\r and \n) are ignored.
func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
+ src = bytes.Map(removeNewlinesMapper, src)
n, _, err = enc.decode(dst, src)
return
}
// DecodeString returns the bytes represented by the base64 string s.
func (enc *Encoding) DecodeString(s string) ([]byte, error) {
+ s = strings.Map(removeNewlinesMapper, s)
dbuf := make([]byte, enc.DecodedLen(len(s)))
n, err := enc.Decode(dbuf, []byte(s))
return dbuf[:n], err
@@ -343,9 +349,34 @@ func (d *decoder) Read(p []byte) (n int, err error) {
return n, d.err
}
+type newlineFilteringReader struct {
+ wrapped io.Reader
+}
+
+func (r *newlineFilteringReader) Read(p []byte) (int, error) {
+ n, err := r.wrapped.Read(p)
+ for n > 0 {
+ offset := 0
+ for i, b := range p[0:n] {
+ if b != '\r' && b != '\n' {
+ if i != offset {
+ p[offset] = b
+ }
+ offset++
+ }
+ }
+ if offset > 0 {
+ return offset, err
+ }
+ // Previous buffer entirely whitespace, read again
+ n, err = r.wrapped.Read(p)
+ }
+ return n, err
+}
+
// NewDecoder constructs a new base64 stream decoder.
func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
- return &decoder{enc: enc, r: r}
+ return &decoder{enc: enc, r: &newlineFilteringReader{r}}
}
// DecodedLen returns the maximum length in bytes of the decoded data
diff --git a/src/pkg/encoding/base64/base64_test.go b/src/pkg/encoding/base64/base64_test.go
index 2166abd7a..579591a88 100644
--- a/src/pkg/encoding/base64/base64_test.go
+++ b/src/pkg/encoding/base64/base64_test.go
@@ -9,6 +9,7 @@ import (
"errors"
"io"
"io/ioutil"
+ "strings"
"testing"
"time"
)
@@ -142,11 +143,11 @@ func TestDecoderBuffering(t *testing.T) {
}
func TestDecodeCorrupt(t *testing.T) {
- type corrupt struct {
- e string
- p int
- }
- examples := []corrupt{
+ testCases := []struct {
+ input string
+ offset int // -1 means no corruption.
+ }{
+ {"", -1},
{"!!!!", 0},
{"x===", 1},
{"AA=A", 2},
@@ -154,18 +155,27 @@ func TestDecodeCorrupt(t *testing.T) {
{"AAAAA", 4},
{"AAAAAA", 4},
{"A=", 1},
+ {"A==", 1},
{"AA=", 3},
+ {"AA==", -1},
+ {"AAA=", -1},
+ {"AAAA", -1},
{"AAAAAA=", 7},
}
-
- for _, e := range examples {
- dbuf := make([]byte, StdEncoding.DecodedLen(len(e.e)))
- _, err := StdEncoding.Decode(dbuf, []byte(e.e))
+ for _, tc := range testCases {
+ dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
+ _, err := StdEncoding.Decode(dbuf, []byte(tc.input))
+ if tc.offset == -1 {
+ if err != nil {
+ t.Error("Decoder wrongly detected coruption in", tc.input)
+ }
+ continue
+ }
switch err := err.(type) {
case CorruptInputError:
- testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
+ testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
default:
- t.Error("Decoder failed to detect corruption in", e)
+ t.Error("Decoder failed to detect corruption in", tc)
}
}
}
@@ -216,6 +226,8 @@ func TestNewLineCharacters(t *testing.T) {
"c3V\nyZ\rQ==",
"c3VyZ\nQ==",
"c3VyZQ\n==",
+ "c3VyZQ=\n=",
+ "c3VyZQ=\r\n\r\n=",
}
for _, e := range examples {
buf, err := StdEncoding.DecodeString(e)
@@ -276,3 +288,40 @@ func TestDecoderIssue3577(t *testing.T) {
t.Errorf("timeout; Decoder blocked without returning an error")
}
}
+
+func TestDecoderIssue4779(t *testing.T) {
+ encoded := `CP/EAT8AAAEF
+AQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAAB
+BAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHx
+Y3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm
+9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS
+0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0
+pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A9VSSSSUpJJJJSkkkJ+Tj
+1kiy1jCJJDnAcCTykpKkuQ6p/jN6FgmxlNduXawwAzaGH+V6jn/R/wCt71zdn+N/qL3kVYFNYB4N
+ji6PDVjWpKp9TSXnvTf8bFNjg3qOEa2n6VlLpj/rT/pf567DpX1i6L1hs9Py67X8mqdtg/rUWbbf
++gkp0kkkklKSSSSUpJJJJT//0PVUkkklKVLq3WMDpGI7KzrNjADtYNXvI/Mqr/Pd/q9W3vaxjnvM
+NaCXE9gNSvGPrf8AWS3qmba5jjsJhoB0DAf0NDf6sevf+/lf8Hj0JJATfWT6/dV6oXU1uOLQeKKn
+EQP+Hubtfe/+R7Mf/g7f5xcocp++Z11JMCJPgFBxOg7/AOuqDx8I/ikpkXkmSdU8mJIJA/O8EMAy
+j+mSARB/17pKVXYWHXjsj7yIex0PadzXMO1zT5KHoNA3HT8ietoGhgjsfA+CSnvvqh/jJtqsrwOv
+2b6NGNzXfTYexzJ+nU7/ALkf4P8Awv6P9KvTQQ4AgyDqCF85Pho3CTB7eHwXoH+LT65uZbX9X+o2
+bqbPb06551Y4
+`
+ encodedShort := strings.Replace(encoded, "\n", "", -1)
+
+ dec := NewDecoder(StdEncoding, bytes.NewBufferString(encoded))
+ res1, err := ioutil.ReadAll(dec)
+ if err != nil {
+ t.Errorf("ReadAll failed: %v", err)
+ }
+
+ dec = NewDecoder(StdEncoding, bytes.NewBufferString(encodedShort))
+ var res2 []byte
+ res2, err = ioutil.ReadAll(dec)
+ if err != nil {
+ t.Errorf("ReadAll failed: %v", err)
+ }
+
+ if !bytes.Equal(res1, res2) {
+ t.Error("Decoded results not equal")
+ }
+}
diff --git a/src/pkg/encoding/binary/varint.go b/src/pkg/encoding/binary/varint.go
index 7035529f2..3a2dfa3c7 100644
--- a/src/pkg/encoding/binary/varint.go
+++ b/src/pkg/encoding/binary/varint.go
@@ -120,7 +120,6 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
x |= uint64(b&0x7f) << s
s += 7
}
- panic("unreachable")
}
// ReadVarint reads an encoded signed integer from r and returns it as an int64.
diff --git a/src/pkg/encoding/csv/reader.go b/src/pkg/encoding/csv/reader.go
index db4d98852..b099caf60 100644
--- a/src/pkg/encoding/csv/reader.go
+++ b/src/pkg/encoding/csv/reader.go
@@ -171,7 +171,6 @@ func (r *Reader) ReadAll() (records [][]string, err error) {
}
records = append(records, record)
}
- panic("unreachable")
}
// readRune reads one rune from r, folding \r\n to \n and keeping track
@@ -213,7 +212,6 @@ func (r *Reader) skip(delim rune) error {
return nil
}
}
- panic("unreachable")
}
// parseRecord reads and parses a single csv record from r.
@@ -250,7 +248,6 @@ func (r *Reader) parseRecord() (fields []string, err error) {
return nil, err
}
}
- panic("unreachable")
}
// parseField parses the next field in the record. The read field is
diff --git a/src/pkg/encoding/gob/codec_test.go b/src/pkg/encoding/gob/codec_test.go
index 482212b74..9e38e31d5 100644
--- a/src/pkg/encoding/gob/codec_test.go
+++ b/src/pkg/encoding/gob/codec_test.go
@@ -1191,10 +1191,8 @@ func TestInterface(t *testing.T) {
if v1 != nil || v2 != nil {
t.Errorf("item %d inconsistent nils", i)
}
- continue
- if v1.Square() != v2.Square() {
- t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
- }
+ } else if v1.Square() != v2.Square() {
+ t.Errorf("item %d inconsistent values: %v %v", i, v1, v2)
}
}
}
diff --git a/src/pkg/encoding/gob/decode.go b/src/pkg/encoding/gob/decode.go
index a80d9f919..7cc756540 100644
--- a/src/pkg/encoding/gob/decode.go
+++ b/src/pkg/encoding/gob/decode.go
@@ -1066,7 +1066,6 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[re
case reflect.Struct:
return true
}
- return true
}
// typeString returns a human-readable description of the type identified by remoteId.
diff --git a/src/pkg/encoding/gob/timing_test.go b/src/pkg/encoding/gob/timing_test.go
index 13eb11925..f589675dd 100644
--- a/src/pkg/encoding/gob/timing_test.go
+++ b/src/pkg/encoding/gob/timing_test.go
@@ -9,6 +9,7 @@ import (
"fmt"
"io"
"os"
+ "runtime"
"testing"
)
@@ -49,6 +50,10 @@ func BenchmarkEndToEndByteBuffer(b *testing.B) {
}
func TestCountEncodeMallocs(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
+
const N = 1000
var buf bytes.Buffer
@@ -65,6 +70,10 @@ func TestCountEncodeMallocs(t *testing.T) {
}
func TestCountDecodeMallocs(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
+
const N = 1000
var buf bytes.Buffer
diff --git a/src/pkg/encoding/gob/type.go b/src/pkg/encoding/gob/type.go
index ea0db4eac..7fa0b499f 100644
--- a/src/pkg/encoding/gob/type.go
+++ b/src/pkg/encoding/gob/type.go
@@ -526,7 +526,6 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, err
default:
return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String())
}
- return nil, nil
}
// isExported reports whether this is an exported - upper case - name.
diff --git a/src/pkg/encoding/json/decode.go b/src/pkg/encoding/json/decode.go
index f2ec9cb67..62ac294b8 100644
--- a/src/pkg/encoding/json/decode.go
+++ b/src/pkg/encoding/json/decode.go
@@ -261,6 +261,16 @@ func (d *decodeState) value(v reflect.Value) {
}
d.scan.step(&d.scan, '"')
d.scan.step(&d.scan, '"')
+
+ n := len(d.scan.parseState)
+ if n > 0 && d.scan.parseState[n-1] == parseObjectKey {
+ // d.scan thinks we just read an object key; finish the object
+ d.scan.step(&d.scan, ':')
+ d.scan.step(&d.scan, '"')
+ d.scan.step(&d.scan, '"')
+ d.scan.step(&d.scan, '}')
+ }
+
return
}
@@ -739,6 +749,7 @@ func (d *decodeState) valueInterface() interface{} {
switch d.scanWhile(scanSkipSpace) {
default:
d.error(errPhase)
+ panic("unreachable")
case scanBeginArray:
return d.arrayInterface()
case scanBeginObject:
@@ -746,7 +757,6 @@ func (d *decodeState) valueInterface() interface{} {
case scanBeginLiteral:
return d.literalInterface()
}
- panic("unreachable")
}
// arrayInterface is like array but returns []interface{}.
@@ -858,7 +868,6 @@ func (d *decodeState) literalInterface() interface{} {
}
return n
}
- panic("unreachable")
}
// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
diff --git a/src/pkg/encoding/json/decode_test.go b/src/pkg/encoding/json/decode_test.go
index e1bd918dd..037c5b236 100644
--- a/src/pkg/encoding/json/decode_test.go
+++ b/src/pkg/encoding/json/decode_test.go
@@ -1178,3 +1178,16 @@ func TestUnmarshalJSONLiteralError(t *testing.T) {
t.Errorf("got err = %v; want out of range error", err)
}
}
+
+// Test that extra object elements in an array do not result in a
+// "data changing underfoot" error.
+// Issue 3717
+func TestSkipArrayObjects(t *testing.T) {
+ json := `[{}]`
+ var dest [0]interface{}
+
+ err := Unmarshal([]byte(json), &dest)
+ if err != nil {
+ t.Errorf("got error %q, want nil", err)
+ }
+}
diff --git a/src/pkg/encoding/xml/marshal.go b/src/pkg/encoding/xml/marshal.go
index ea58ce254..47b001763 100644
--- a/src/pkg/encoding/xml/marshal.go
+++ b/src/pkg/encoding/xml/marshal.go
@@ -120,11 +120,76 @@ func (enc *Encoder) Encode(v interface{}) error {
type printer struct {
*bufio.Writer
+ seq int
indent string
prefix string
depth int
indentedIn bool
putNewline bool
+ attrNS map[string]string // map prefix -> name space
+ attrPrefix map[string]string // map name space -> prefix
+}
+
+// createAttrPrefix finds the name space prefix attribute to use for the given name space,
+// defining a new prefix if necessary. It returns the prefix and whether it is new.
+func (p *printer) createAttrPrefix(url string) (prefix string, isNew bool) {
+ if prefix = p.attrPrefix[url]; prefix != "" {
+ return prefix, false
+ }
+
+ // The "http://www.w3.org/XML/1998/namespace" name space is predefined as "xml"
+ // and must be referred to that way.
+ // (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns",
+ // but users should not be trying to use that one directly - that's our job.)
+ if url == xmlURL {
+ return "xml", false
+ }
+
+ // Need to define a new name space.
+ if p.attrPrefix == nil {
+ p.attrPrefix = make(map[string]string)
+ p.attrNS = make(map[string]string)
+ }
+
+ // Pick a name. We try to use the final element of the path
+ // but fall back to _.
+ prefix = strings.TrimRight(url, "/")
+ if i := strings.LastIndex(prefix, "/"); i >= 0 {
+ prefix = prefix[i+1:]
+ }
+ if prefix == "" || !isName([]byte(prefix)) || strings.Contains(prefix, ":") {
+ prefix = "_"
+ }
+ if strings.HasPrefix(prefix, "xml") {
+ // xmlanything is reserved.
+ prefix = "_" + prefix
+ }
+ if p.attrNS[prefix] != "" {
+ // Name is taken. Find a better one.
+ for p.seq++; ; p.seq++ {
+ if id := prefix + "_" + strconv.Itoa(p.seq); p.attrNS[id] == "" {
+ prefix = id
+ break
+ }
+ }
+ }
+
+ p.attrPrefix[url] = prefix
+ p.attrNS[prefix] = url
+
+ p.WriteString(`xmlns:`)
+ p.WriteString(prefix)
+ p.WriteString(`="`)
+ EscapeText(p, []byte(url))
+ p.WriteString(`" `)
+
+ return prefix, true
+}
+
+// deleteAttrPrefix removes an attribute name space prefix.
+func (p *printer) deleteAttrPrefix(prefix string) {
+ delete(p.attrPrefix, p.attrNS[prefix])
+ delete(p.attrNS, prefix)
}
// marshalValue writes one or more XML elements representing val.
@@ -210,6 +275,14 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
continue
}
p.WriteByte(' ')
+ if finfo.xmlns != "" {
+ prefix, created := p.createAttrPrefix(finfo.xmlns)
+ if created {
+ defer p.deleteAttrPrefix(prefix)
+ }
+ p.WriteString(prefix)
+ p.WriteByte(':')
+ }
p.WriteString(finfo.name)
p.WriteString(`="`)
if err := p.marshalSimple(fv.Type(), fv); err != nil {
@@ -286,7 +359,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
s := parentStack{printer: p}
for i := range tinfo.fields {
finfo := &tinfo.fields[i]
- if finfo.flags&(fAttr) != 0 {
+ if finfo.flags&fAttr != 0 {
continue
}
vf := finfo.value(val)
diff --git a/src/pkg/encoding/xml/marshal_test.go b/src/pkg/encoding/xml/marshal_test.go
index 3a190def6..ca14a1e53 100644
--- a/src/pkg/encoding/xml/marshal_test.go
+++ b/src/pkg/encoding/xml/marshal_test.go
@@ -266,6 +266,16 @@ type Plain struct {
V interface{}
}
+type MyInt int
+
+type EmbedInt struct {
+ MyInt
+}
+
+type Strings struct {
+ X []string `xml:"A>B,omitempty"`
+}
+
// Unless explicitly stated as such (or *Plain), all of the
// tests below are two-way tests. When introducing new tests,
// please try to make them two-way as well to ensure that
@@ -790,6 +800,17 @@ var marshalTests = []struct {
},
UnmarshalOnly: true,
},
+ {
+ ExpectXML: `<EmbedInt><MyInt>42</MyInt></EmbedInt>`,
+ Value: &EmbedInt{
+ MyInt: 42,
+ },
+ },
+ // Test omitempty with parent chain; see golang.org/issue/4168.
+ {
+ ExpectXML: `<Strings><A></A></Strings>`,
+ Value: &Strings{},
+ },
}
func TestMarshal(t *testing.T) {
@@ -812,6 +833,10 @@ func TestMarshal(t *testing.T) {
}
}
+type AttrParent struct {
+ X string `xml:"X>Y,attr"`
+}
+
var marshalErrorTests = []struct {
Value interface{}
Err string
@@ -839,6 +864,11 @@ var marshalErrorTests = []struct {
Value: &Domain{Comment: []byte("f--bar")},
Err: `xml: comments must not contain "--"`,
},
+ // Reject parent chain with attr, never worked; see golang.org/issue/5033.
+ {
+ Value: &AttrParent{},
+ Err: `xml: X>Y chain not valid with attr flag`,
+ },
}
var marshalIndentTests = []struct {
@@ -861,8 +891,12 @@ var marshalIndentTests = []struct {
func TestMarshalErrors(t *testing.T) {
for idx, test := range marshalErrorTests {
- _, err := Marshal(test.Value)
- if err == nil || err.Error() != test.Err {
+ data, err := Marshal(test.Value)
+ if err == nil {
+ t.Errorf("#%d: marshal(%#v) = [success] %q, want error %v", idx, test.Value, data, test.Err)
+ continue
+ }
+ if err.Error() != test.Err {
t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
}
if test.Kind != reflect.Invalid {
diff --git a/src/pkg/encoding/xml/read.go b/src/pkg/encoding/xml/read.go
index 344ab514e..a7a2a9655 100644
--- a/src/pkg/encoding/xml/read.go
+++ b/src/pkg/encoding/xml/read.go
@@ -263,7 +263,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
strv := finfo.value(sv)
// Look for attribute.
for _, a := range start.Attr {
- if a.Name.Local == finfo.name {
+ if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
copyValue(strv, []byte(a.Value))
break
}
@@ -441,7 +441,7 @@ func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []str
Loop:
for i := range tinfo.fields {
finfo := &tinfo.fields[i]
- if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) {
+ if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) || finfo.xmlns != "" && finfo.xmlns != start.Name.Space {
continue
}
for j := range parents {
@@ -493,7 +493,6 @@ Loop:
return true, nil
}
}
- panic("unreachable")
}
// Skip reads tokens until it has consumed the end element
@@ -517,5 +516,4 @@ func (d *Decoder) Skip() error {
return nil
}
}
- panic("unreachable")
}
diff --git a/src/pkg/encoding/xml/read_test.go b/src/pkg/encoding/xml/read_test.go
index b45e2f0e6..7d28c5d7d 100644
--- a/src/pkg/encoding/xml/read_test.go
+++ b/src/pkg/encoding/xml/read_test.go
@@ -6,6 +6,7 @@ package xml
import (
"reflect"
+ "strings"
"testing"
"time"
)
@@ -399,3 +400,224 @@ func TestUnmarshalAttr(t *testing.T) {
t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p3.Int, 1)
}
}
+
+type Tables struct {
+ HTable string `xml:"http://www.w3.org/TR/html4/ table"`
+ FTable string `xml:"http://www.w3schools.com/furniture table"`
+}
+
+var tables = []struct {
+ xml string
+ tab Tables
+ ns string
+}{
+ {
+ xml: `<Tables>` +
+ `<table xmlns="http://www.w3.org/TR/html4/">hello</table>` +
+ `<table xmlns="http://www.w3schools.com/furniture">world</table>` +
+ `</Tables>`,
+ tab: Tables{"hello", "world"},
+ },
+ {
+ xml: `<Tables>` +
+ `<table xmlns="http://www.w3schools.com/furniture">world</table>` +
+ `<table xmlns="http://www.w3.org/TR/html4/">hello</table>` +
+ `</Tables>`,
+ tab: Tables{"hello", "world"},
+ },
+ {
+ xml: `<Tables xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/">` +
+ `<f:table>world</f:table>` +
+ `<h:table>hello</h:table>` +
+ `</Tables>`,
+ tab: Tables{"hello", "world"},
+ },
+ {
+ xml: `<Tables>` +
+ `<table>bogus</table>` +
+ `</Tables>`,
+ tab: Tables{},
+ },
+ {
+ xml: `<Tables>` +
+ `<table>only</table>` +
+ `</Tables>`,
+ tab: Tables{HTable: "only"},
+ ns: "http://www.w3.org/TR/html4/",
+ },
+ {
+ xml: `<Tables>` +
+ `<table>only</table>` +
+ `</Tables>`,
+ tab: Tables{FTable: "only"},
+ ns: "http://www.w3schools.com/furniture",
+ },
+ {
+ xml: `<Tables>` +
+ `<table>only</table>` +
+ `</Tables>`,
+ tab: Tables{},
+ ns: "something else entirely",
+ },
+}
+
+func TestUnmarshalNS(t *testing.T) {
+ for i, tt := range tables {
+ var dst Tables
+ var err error
+ if tt.ns != "" {
+ d := NewDecoder(strings.NewReader(tt.xml))
+ d.DefaultSpace = tt.ns
+ err = d.Decode(&dst)
+ } else {
+ err = Unmarshal([]byte(tt.xml), &dst)
+ }
+ if err != nil {
+ t.Errorf("#%d: Unmarshal: %v", i, err)
+ continue
+ }
+ want := tt.tab
+ if dst != want {
+ t.Errorf("#%d: dst=%+v, want %+v", i, dst, want)
+ }
+ }
+}
+
+func TestMarshalNS(t *testing.T) {
+ dst := Tables{"hello", "world"}
+ data, err := Marshal(&dst)
+ if err != nil {
+ t.Fatalf("Marshal: %v", err)
+ }
+ want := `<Tables><table xmlns="http://www.w3.org/TR/html4/">hello</table><table xmlns="http://www.w3schools.com/furniture">world</table></Tables>`
+ str := string(data)
+ if str != want {
+ t.Errorf("have: %q\nwant: %q\n", str, want)
+ }
+}
+
+type TableAttrs struct {
+ TAttr TAttr
+}
+
+type TAttr struct {
+ HTable string `xml:"http://www.w3.org/TR/html4/ table,attr"`
+ FTable string `xml:"http://www.w3schools.com/furniture table,attr"`
+ Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"`
+ Other1 string `xml:"http://golang.org/xml/ other,attr,omitempty"`
+ Other2 string `xml:"http://golang.org/xmlfoo/ other,attr,omitempty"`
+ Other3 string `xml:"http://golang.org/json/ other,attr,omitempty"`
+ Other4 string `xml:"http://golang.org/2/json/ other,attr,omitempty"`
+}
+
+var tableAttrs = []struct {
+ xml string
+ tab TableAttrs
+ ns string
+}{
+ {
+ xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+ `h:table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+ },
+ {
+ xml: `<TableAttrs><TAttr xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` +
+ `h:table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+ },
+ {
+ xml: `<TableAttrs><TAttr ` +
+ `h:table="hello" f:table="world" xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}},
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+ `h:table="hello" table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}},
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr xmlns="http://www.w3.org/TR/html4/" ` +
+ `table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "", FTable: "world"}},
+ },
+ {
+ xml: `<TableAttrs><TAttr ` +
+ `table="bogus" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{},
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` +
+ `h:table="hello" table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}},
+ ns: "http://www.w3schools.com/furniture",
+ },
+ {
+ // Default space does not apply to attribute names.
+ xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr ` +
+ `table="hello" f:table="world" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{TAttr{HTable: "", FTable: "world"}},
+ ns: "http://www.w3.org/TR/html4/",
+ },
+ {
+ xml: `<TableAttrs><TAttr ` +
+ `table="bogus" ` +
+ `/></TableAttrs>`,
+ tab: TableAttrs{},
+ ns: "something else entirely",
+ },
+}
+
+func TestUnmarshalNSAttr(t *testing.T) {
+ for i, tt := range tableAttrs {
+ var dst TableAttrs
+ var err error
+ if tt.ns != "" {
+ d := NewDecoder(strings.NewReader(tt.xml))
+ d.DefaultSpace = tt.ns
+ err = d.Decode(&dst)
+ } else {
+ err = Unmarshal([]byte(tt.xml), &dst)
+ }
+ if err != nil {
+ t.Errorf("#%d: Unmarshal: %v", i, err)
+ continue
+ }
+ want := tt.tab
+ if dst != want {
+ t.Errorf("#%d: dst=%+v, want %+v", i, dst, want)
+ }
+ }
+}
+
+func TestMarshalNSAttr(t *testing.T) {
+ src := TableAttrs{TAttr{"hello", "world", "en_US", "other1", "other2", "other3", "other4"}}
+ data, err := Marshal(&src)
+ if err != nil {
+ t.Fatalf("Marshal: %v", err)
+ }
+ want := `<TableAttrs><TAttr xmlns:html4="http://www.w3.org/TR/html4/" html4:table="hello" xmlns:furniture="http://www.w3schools.com/furniture" furniture:table="world" xml:lang="en_US" xmlns:_xml="http://golang.org/xml/" _xml:other="other1" xmlns:_xmlfoo="http://golang.org/xmlfoo/" _xmlfoo:other="other2" xmlns:json="http://golang.org/json/" json:other="other3" xmlns:json_1="http://golang.org/2/json/" json_1:other="other4"></TAttr></TableAttrs>`
+ str := string(data)
+ if str != want {
+ t.Errorf("Marshal:\nhave: %#q\nwant: %#q\n", str, want)
+ }
+
+ var dst TableAttrs
+ if err := Unmarshal(data, &dst); err != nil {
+ t.Errorf("Unmarshal: %v", err)
+ }
+
+ if dst != src {
+ t.Errorf("Unmarshal = %q, want %q", dst, src)
+ }
+}
diff --git a/src/pkg/encoding/xml/typeinfo.go b/src/pkg/encoding/xml/typeinfo.go
index bbeb28d87..83e65402c 100644
--- a/src/pkg/encoding/xml/typeinfo.go
+++ b/src/pkg/encoding/xml/typeinfo.go
@@ -70,20 +70,19 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
- if t.Kind() != reflect.Struct {
- continue
- }
- inner, err := getTypeInfo(t)
- if err != nil {
- return nil, err
- }
- for _, finfo := range inner.fields {
- finfo.idx = append([]int{i}, finfo.idx...)
- if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
+ if t.Kind() == reflect.Struct {
+ inner, err := getTypeInfo(t)
+ if err != nil {
return nil, err
}
+ for _, finfo := range inner.fields {
+ finfo.idx = append([]int{i}, finfo.idx...)
+ if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
+ return nil, err
+ }
+ }
+ continue
}
- continue
}
finfo, err := structFieldInfo(typ, &f)
@@ -193,16 +192,19 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
}
// Prepare field name and parents.
- tokens = strings.Split(tag, ">")
- if tokens[0] == "" {
- tokens[0] = f.Name
+ parents := strings.Split(tag, ">")
+ if parents[0] == "" {
+ parents[0] = f.Name
}
- if tokens[len(tokens)-1] == "" {
+ if parents[len(parents)-1] == "" {
return nil, fmt.Errorf("xml: trailing '>' in field %s of type %s", f.Name, typ)
}
- finfo.name = tokens[len(tokens)-1]
- if len(tokens) > 1 {
- finfo.parents = tokens[:len(tokens)-1]
+ finfo.name = parents[len(parents)-1]
+ if len(parents) > 1 {
+ if (finfo.flags & fElement) == 0 {
+ return nil, fmt.Errorf("xml: %s chain not valid with %s flag", tag, strings.Join(tokens[1:], ","))
+ }
+ finfo.parents = parents[:len(parents)-1]
}
// If the field type has an XMLName field, the names must match
@@ -268,6 +270,9 @@ Loop:
if oldf.flags&fMode != newf.flags&fMode {
continue
}
+ if oldf.xmlns != "" && newf.xmlns != "" && oldf.xmlns != newf.xmlns {
+ continue
+ }
minl := min(len(newf.parents), len(oldf.parents))
for p := 0; p < minl; p++ {
if oldf.parents[p] != newf.parents[p] {
diff --git a/src/pkg/encoding/xml/xml.go b/src/pkg/encoding/xml/xml.go
index 143fec554..021f7e47d 100644
--- a/src/pkg/encoding/xml/xml.go
+++ b/src/pkg/encoding/xml/xml.go
@@ -169,6 +169,11 @@ type Decoder struct {
// the CharsetReader's result values must be non-nil.
CharsetReader func(charset string, input io.Reader) (io.Reader, error)
+ // DefaultSpace sets the default name space used for unadorned tags,
+ // as if the entire XML stream were wrapped in an element containing
+ // the attribute xmlns="DefaultSpace".
+ DefaultSpace string
+
r io.ByteReader
buf bytes.Buffer
saved *bytes.Buffer
@@ -268,6 +273,8 @@ func (d *Decoder) Token() (t Token, err error) {
return
}
+const xmlURL = "http://www.w3.org/XML/1998/namespace"
+
// Apply name space translation to name n.
// The default name space (for Space=="")
// applies only to element names, not to attribute names.
@@ -277,11 +284,15 @@ func (d *Decoder) translate(n *Name, isElementName bool) {
return
case n.Space == "" && !isElementName:
return
+ case n.Space == "xml":
+ n.Space = xmlURL
case n.Space == "" && n.Local == "xmlns":
return
}
if v, ok := d.ns[n.Space]; ok {
n.Space = v
+ } else if n.Space == "" {
+ n.Space = d.DefaultSpace
}
}
@@ -956,7 +967,7 @@ Input:
b0, b1 = 0, 0
continue Input
}
- ent := string(d.buf.Bytes()[before])
+ ent := string(d.buf.Bytes()[before:])
if ent[len(ent)-1] != ';' {
ent += " (no semicolon)"
}
@@ -1718,6 +1729,7 @@ var (
esc_tab = []byte("&#x9;")
esc_nl = []byte("&#xA;")
esc_cr = []byte("&#xD;")
+ esc_fffd = []byte("\uFFFD") // Unicode replacement character
)
// EscapeText writes to w the properly escaped XML equivalent
@@ -1725,8 +1737,10 @@ var (
func EscapeText(w io.Writer, s []byte) error {
var esc []byte
last := 0
- for i, c := range s {
- switch c {
+ for i := 0; i < len(s); {
+ r, width := utf8.DecodeRune(s[i:])
+ i += width
+ switch r {
case '"':
esc = esc_quot
case '\'':
@@ -1744,15 +1758,19 @@ func EscapeText(w io.Writer, s []byte) error {
case '\r':
esc = esc_cr
default:
+ if !isInCharacterRange(r) {
+ esc = esc_fffd
+ break
+ }
continue
}
- if _, err := w.Write(s[last:i]); err != nil {
+ if _, err := w.Write(s[last : i-width]); err != nil {
return err
}
if _, err := w.Write(esc); err != nil {
return err
}
- last = i + 1
+ last = i
}
if _, err := w.Write(s[last:]); err != nil {
return err
diff --git a/src/pkg/encoding/xml/xml_test.go b/src/pkg/encoding/xml/xml_test.go
index 54dab5484..eeedbe575 100644
--- a/src/pkg/encoding/xml/xml_test.go
+++ b/src/pkg/encoding/xml/xml_test.go
@@ -5,6 +5,7 @@
package xml
import (
+ "bytes"
"fmt"
"io"
"reflect"
@@ -595,13 +596,6 @@ func TestEntityInsideCDATA(t *testing.T) {
}
}
-// The last three tests (respectively one for characters in attribute
-// names and two for character entities) pass not because of code
-// changed for issue 1259, but instead pass with the given messages
-// from other parts of xml.Decoder. I provide these to note the
-// current behavior of situations where one might think that character
-// range checking would detect the error, but it does not in fact.
-
var characterTests = []struct {
in string
err string
@@ -611,8 +605,10 @@ 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>&abc\x01;</doc>", "invalid character entity &abc (no semicolon)"},
{"<doc>&\x01;</doc>", "invalid character entity & (no semicolon)"},
- {"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity & (no semicolon)"},
+ {"<doc>&\xef\xbf\xbe;</doc>", "invalid character entity &\uFFFE;"},
+ {"<doc>&hello;</doc>", "invalid character entity &hello;"},
}
func TestDisallowedCharacters(t *testing.T) {
@@ -629,7 +625,7 @@ func TestDisallowedCharacters(t *testing.T) {
t.Fatalf("input %d d.Token() = _, %v, want _, *SyntaxError", i, err)
}
if synerr.Msg != tt.err {
- t.Fatalf("input %d synerr.Msg wrong: want '%s', got '%s'", i, tt.err, synerr.Msg)
+ t.Fatalf("input %d synerr.Msg wrong: want %q, got %q", i, tt.err, synerr.Msg)
}
}
}
@@ -700,6 +696,21 @@ func TestEscapeTextIOErrors(t *testing.T) {
err := EscapeText(errWriter{}, []byte{'A'})
if err == nil || err.Error() != expectErr {
- t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr)
+ t.Errorf("have %v, want %v", err, expectErr)
+ }
+}
+
+func TestEscapeTextInvalidChar(t *testing.T) {
+ input := []byte("A \x00 terminated string.")
+ expected := "A \uFFFD terminated string."
+
+ buff := new(bytes.Buffer)
+ if err := EscapeText(buff, input); err != nil {
+ t.Fatalf("have %v, want nil", err)
+ }
+ text := buff.String()
+
+ if text != expected {
+ t.Errorf("have %v, want %v", text, expected)
}
}
diff --git a/src/pkg/exp/norm/Makefile b/src/pkg/exp/norm/Makefile
deleted file mode 100644
index f278eb02f..000000000
--- a/src/pkg/exp/norm/Makefile
+++ /dev/null
@@ -1,30 +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.
-
-maketables: maketables.go triegen.go
- go build $^
-
-maketesttables: maketesttables.go triegen.go
- go build $^
-
-normregtest: normregtest.go
- go build $^
-
-tables: maketables
- ./maketables > tables.go
- gofmt -w tables.go
-
-trietesttables: maketesttables
- ./maketesttables > triedata_test.go
- gofmt -w triedata_test.go
-
-# Downloads from www.unicode.org, so not part
-# of standard test scripts.
-test: testtables regtest
-
-testtables: maketables
- ./maketables -test -tables=
-
-regtest: normregtest
- ./normregtest
diff --git a/src/pkg/exp/norm/composition.go b/src/pkg/exp/norm/composition.go
deleted file mode 100644
index 2d52f99dc..000000000
--- a/src/pkg/exp/norm/composition.go
+++ /dev/null
@@ -1,382 +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 norm
-
-import "unicode/utf8"
-
-const (
- maxCombiningChars = 30
- maxBufferSize = maxCombiningChars + 2 // +1 to hold starter +1 to hold CGJ
- maxBackRunes = maxCombiningChars - 1
- maxNFCExpansion = 3 // NFC(0x1D160)
- maxNFKCExpansion = 18 // NFKC(0xFDFA)
-
- maxByteBufferSize = utf8.UTFMax * maxBufferSize // 128
-)
-
-// reorderBuffer is used to normalize a single segment. Characters inserted with
-// insert are decomposed and reordered based on CCC. The compose method can
-// be used to recombine characters. Note that the byte buffer does not hold
-// 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]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
- nsrc int
- tmpBytes input
-}
-
-func (rb *reorderBuffer) init(f Form, src []byte) {
- rb.f = *formTable[f]
- rb.src.setBytes(src)
- rb.nsrc = len(src)
-}
-
-func (rb *reorderBuffer) initString(f Form, src string) {
- rb.f = *formTable[f]
- rb.src.setString(src)
- rb.nsrc = len(src)
-}
-
-// reset discards all characters from the buffer.
-func (rb *reorderBuffer) reset() {
- rb.nrune = 0
- rb.nbyte = 0
-}
-
-// flush appends the normalized segment to out and resets rb.
-func (rb *reorderBuffer) flush(out []byte) []byte {
- for i := 0; i < rb.nrune; i++ {
- start := rb.rune[i].pos
- end := start + rb.rune[i].size
- out = append(out, rb.byte[start:end]...)
- }
- rb.reset()
- return out
-}
-
-// flushCopy copies the normalized segment to buf and resets rb.
-// It returns the number of bytes written to buf.
-func (rb *reorderBuffer) flushCopy(buf []byte) int {
- p := 0
- for i := 0; i < rb.nrune; i++ {
- runep := rb.rune[i]
- p += copy(buf[p:], rb.byte[runep.pos:runep.pos+runep.size])
- }
- rb.reset()
- return p
-}
-
-// 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 Properties) bool {
- n := rb.nrune
- if n >= maxCombiningChars+1 {
- return false
- }
- b := rb.rune[:]
- cc := info.ccc
- if cc > 0 {
- // Find insertion position + move elements to make room.
- for ; n > 0; n-- {
- if b[n-1].ccc <= cc {
- break
- }
- b[n] = b[n-1]
- }
- }
- rb.nrune += 1
- pos := uint8(rb.nbyte)
- rb.nbyte += utf8.UTFMax
- info.pos = pos
- b[n] = info
- return true
-}
-
-// 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 Properties) bool {
- if rune := src.hangul(i); rune != 0 {
- return rb.decomposeHangul(rune)
- }
- if info.hasDecomposition() {
- return rb.insertDecomposed(info.Decomposition())
- }
- return rb.insertSingle(src, i, info)
-}
-
-// insertDecomposed inserts an entry in to the reorderBuffer for each rune
-// in dcomp. dcomp must be a sequence of decomposed UTF-8-encoded runes.
-func (rb *reorderBuffer) insertDecomposed(dcomp []byte) bool {
- saveNrune, saveNbyte := rb.nrune, rb.nbyte
- rb.tmpBytes.setBytes(dcomp)
- for i := 0; i < len(dcomp); {
- info := rb.f.info(rb.tmpBytes, i)
- pos := rb.nbyte
- if !rb.insertOrdered(info) {
- rb.nrune, rb.nbyte = saveNrune, saveNbyte
- return false
- }
- i += copy(rb.byte[pos:], dcomp[i:i+int(info.size)])
- }
- return true
-}
-
-// 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 Properties) bool {
- // insertOrder changes nbyte
- pos := rb.nbyte
- if !rb.insertOrdered(info) {
- return false
- }
- src.copySlice(rb.byte[pos:], i, i+int(info.size))
- return true
-}
-
-// appendRune inserts a rune at the end of the buffer. It is used for Hangul.
-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] = Properties{pos: bn, size: uint8(sz)}
- rb.nrune++
-}
-
-// assignRune sets a rune at position pos. It is used for Hangul and recomposition.
-func (rb *reorderBuffer) assignRune(pos int, r rune) {
- bn := rb.rune[pos].pos
- sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
- rb.rune[pos] = Properties{pos: bn, size: uint8(sz)}
-}
-
-// runeAt returns the rune at position n. It is used for Hangul and recomposition.
-func (rb *reorderBuffer) runeAt(n int) rune {
- inf := rb.rune[n]
- r, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
- return r
-}
-
-// bytesAt returns the UTF-8 encoding of the rune at position n.
-// It is used for Hangul and recomposition.
-func (rb *reorderBuffer) bytesAt(n int) []byte {
- inf := rb.rune[n]
- return rb.byte[inf.pos : int(inf.pos)+int(inf.size)]
-}
-
-// For Hangul we combine algorithmically, instead of using tables.
-const (
- hangulBase = 0xAC00 // UTF-8(hangulBase) -> EA B0 80
- hangulBase0 = 0xEA
- hangulBase1 = 0xB0
- hangulBase2 = 0x80
-
- hangulEnd = hangulBase + jamoLVTCount // UTF-8(0xD7A4) -> ED 9E A4
- hangulEnd0 = 0xED
- hangulEnd1 = 0x9E
- hangulEnd2 = 0xA4
-
- jamoLBase = 0x1100 // UTF-8(jamoLBase) -> E1 84 00
- jamoLBase0 = 0xE1
- jamoLBase1 = 0x84
- jamoLEnd = 0x1113
- jamoVBase = 0x1161
- jamoVEnd = 0x1176
- jamoTBase = 0x11A7
- jamoTEnd = 0x11C3
-
- jamoTCount = 28
- jamoVCount = 21
- jamoVTCount = 21 * 28
- jamoLVTCount = 19 * 21 * 28
-)
-
-const hangulUTF8Size = 3
-
-func isHangul(b []byte) bool {
- if len(b) < hangulUTF8Size {
- return false
- }
- b0 := b[0]
- if b0 < hangulBase0 {
- return false
- }
- b1 := b[1]
- switch {
- case b0 == hangulBase0:
- return b1 >= hangulBase1
- case b0 < hangulEnd0:
- return true
- case b0 > hangulEnd0:
- return false
- case b1 < hangulEnd1:
- return true
- }
- return b1 == hangulEnd1 && b[2] < hangulEnd2
-}
-
-func isHangulString(b string) bool {
- if len(b) < hangulUTF8Size {
- return false
- }
- b0 := b[0]
- if b0 < hangulBase0 {
- return false
- }
- b1 := b[1]
- switch {
- case b0 == hangulBase0:
- return b1 >= hangulBase1
- case b0 < hangulEnd0:
- return true
- case b0 > hangulEnd0:
- return false
- case b1 < hangulEnd1:
- return true
- }
- return b1 == hangulEnd1 && b[2] < hangulEnd2
-}
-
-// Caller must ensure len(b) >= 2.
-func isJamoVT(b []byte) bool {
- // True if (rune & 0xff00) == jamoLBase
- return b[0] == jamoLBase0 && (b[1]&0xFC) == jamoLBase1
-}
-
-func isHangulWithoutJamoT(b []byte) bool {
- c, _ := utf8.DecodeRune(b)
- c -= hangulBase
- return c < jamoLVTCount && c%jamoTCount == 0
-}
-
-// decomposeHangul writes the decomposed Hangul to buf and returns the number
-// of bytes written. len(buf) should be at least 9.
-func decomposeHangul(buf []byte, r rune) int {
- const JamoUTF8Len = 3
- r -= hangulBase
- x := r % jamoTCount
- r /= jamoTCount
- utf8.EncodeRune(buf, jamoLBase+r/jamoVCount)
- utf8.EncodeRune(buf[JamoUTF8Len:], jamoVBase+r%jamoVCount)
- if x != 0 {
- utf8.EncodeRune(buf[2*JamoUTF8Len:], jamoTBase+x)
- return 3 * JamoUTF8Len
- }
- return 2 * JamoUTF8Len
-}
-
-// decomposeHangul algorithmically decomposes a Hangul rune into
-// its Jamo components.
-// See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul.
-func (rb *reorderBuffer) decomposeHangul(r rune) bool {
- b := rb.rune[:]
- n := rb.nrune
- if n+3 > len(b) {
- return false
- }
- r -= hangulBase
- x := r % jamoTCount
- r /= jamoTCount
- rb.appendRune(jamoLBase + r/jamoVCount)
- rb.appendRune(jamoVBase + r%jamoVCount)
- if x != 0 {
- rb.appendRune(jamoTBase + x)
- }
- return true
-}
-
-// combineHangul algorithmically combines Jamo character components into Hangul.
-// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul.
-func (rb *reorderBuffer) combineHangul(s, i, k int) {
- b := rb.rune[:]
- bn := rb.nrune
- for ; i < bn; i++ {
- cccB := b[k-1].ccc
- cccC := b[i].ccc
- if cccB == 0 {
- s = k - 1
- }
- if s != k-1 && cccB >= cccC {
- // b[i] is blocked by greater-equal cccX below it
- b[k] = b[i]
- k++
- } else {
- l := rb.runeAt(s) // also used to compare to hangulBase
- v := rb.runeAt(i) // also used to compare to jamoT
- switch {
- case jamoLBase <= l && l < jamoLEnd &&
- jamoVBase <= v && v < jamoVEnd:
- // 11xx plus 116x to LV
- rb.assignRune(s, hangulBase+
- (l-jamoLBase)*jamoVTCount+(v-jamoVBase)*jamoTCount)
- case hangulBase <= l && l < hangulEnd &&
- jamoTBase < v && v < jamoTEnd &&
- ((l-hangulBase)%jamoTCount) == 0:
- // ACxx plus 11Ax to LVT
- rb.assignRune(s, l+v-jamoTBase)
- default:
- b[k] = b[i]
- k++
- }
- }
- }
- rb.nrune = k
-}
-
-// compose recombines the runes in the buffer.
-// It should only be used to recompose a single segment, as it will not
-// handle alternations between Hangul and non-Hangul characters correctly.
-func (rb *reorderBuffer) compose() {
- // UAX #15, section X5 , including Corrigendum #5
- // "In any character sequence beginning with starter S, a character C is
- // blocked from S if and only if there is some character B between S
- // and C, and either B is a starter or it has the same or higher
- // combining class as C."
- bn := rb.nrune
- if bn == 0 {
- return
- }
- k := 1
- b := rb.rune[:]
- for s, i := 0, 1; i < bn; i++ {
- if isJamoVT(rb.bytesAt(i)) {
- // Redo from start in Hangul mode. Necessary to support
- // U+320E..U+321E in NFKC mode.
- rb.combineHangul(s, i, k)
- return
- }
- ii := b[i]
- // We can only use combineForward as a filter if we later
- // get the info for the combined character. This is more
- // expensive than using the filter. Using combinesBackward()
- // is safe.
- if ii.combinesBackward() {
- cccB := b[k-1].ccc
- cccC := ii.ccc
- blocked := false // b[i] blocked by starter or greater or equal CCC?
- if cccB == 0 {
- s = k - 1
- } else {
- blocked = s != k-1 && cccB >= cccC
- }
- if !blocked {
- combined := combine(rb.runeAt(s), rb.runeAt(i))
- if combined != 0 {
- rb.assignRune(s, combined)
- continue
- }
- }
- }
- b[k] = b[i]
- k++
- }
- rb.nrune = k
-}
diff --git a/src/pkg/exp/norm/composition_test.go b/src/pkg/exp/norm/composition_test.go
deleted file mode 100644
index 976aa21ed..000000000
--- a/src/pkg/exp/norm/composition_test.go
+++ /dev/null
@@ -1,143 +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 norm
-
-import "testing"
-
-// TestCase is used for most tests.
-type TestCase struct {
- in []rune
- out []rune
-}
-
-type insertFunc func(rb *reorderBuffer, r rune) bool
-
-func insert(rb *reorderBuffer, r rune) bool {
- src := inputString(string(r))
- return rb.insert(src, 0, rb.f.info(src, 0))
-}
-
-func runTests(t *testing.T, name string, fm Form, f insertFunc, tests []TestCase) {
- rb := reorderBuffer{}
- rb.init(fm, nil)
- for i, test := range tests {
- rb.reset()
- for j, rune := range test.in {
- b := []byte(string(rune))
- src := inputBytes(b)
- if !rb.insert(src, 0, rb.f.info(src, 0)) {
- t.Errorf("%s:%d: insert failed for rune %d", name, i, j)
- }
- }
- if rb.f.composing {
- rb.compose()
- }
- if rb.nrune != len(test.out) {
- t.Errorf("%s:%d: length = %d; want %d", name, i, rb.nrune, len(test.out))
- continue
- }
- for j, want := range test.out {
- found := rune(rb.runeAt(j))
- if found != want {
- t.Errorf("%s:%d: runeAt(%d) = %U; want %U", name, i, j, found, want)
- }
- }
- }
-}
-
-type flushFunc func(rb *reorderBuffer) []byte
-
-func testFlush(t *testing.T, name string, fn flushFunc) {
- rb := reorderBuffer{}
- rb.init(NFC, nil)
- out := fn(&rb)
- if len(out) != 0 {
- t.Errorf("%s: wrote bytes on flush of empty buffer. (len(out) = %d)", name, len(out))
- }
-
- for _, r := range []rune("world!") {
- insert(&rb, r)
- }
-
- out = []byte("Hello ")
- out = rb.flush(out)
- want := "Hello world!"
- if string(out) != want {
- t.Errorf(`%s: output after flush was "%s"; want "%s"`, name, string(out), want)
- }
- if rb.nrune != 0 {
- t.Errorf("%s: non-null size of info buffer (rb.nrune == %d)", name, rb.nrune)
- }
- if rb.nbyte != 0 {
- t.Errorf("%s: non-null size of byte buffer (rb.nbyte == %d)", name, rb.nbyte)
- }
-}
-
-func flushF(rb *reorderBuffer) []byte {
- out := make([]byte, 0)
- return rb.flush(out)
-}
-
-func flushCopyF(rb *reorderBuffer) []byte {
- out := make([]byte, maxByteBufferSize)
- n := rb.flushCopy(out)
- return out[:n]
-}
-
-func TestFlush(t *testing.T) {
- testFlush(t, "flush", flushF)
- testFlush(t, "flushCopy", flushCopyF)
-}
-
-var insertTests = []TestCase{
- {[]rune{'a'}, []rune{'a'}},
- {[]rune{0x300}, []rune{0x300}},
- {[]rune{0x300, 0x316}, []rune{0x316, 0x300}}, // CCC(0x300)==230; CCC(0x316)==220
- {[]rune{0x316, 0x300}, []rune{0x316, 0x300}},
- {[]rune{0x41, 0x316, 0x300}, []rune{0x41, 0x316, 0x300}},
- {[]rune{0x41, 0x300, 0x316}, []rune{0x41, 0x316, 0x300}},
- {[]rune{0x300, 0x316, 0x41}, []rune{0x316, 0x300, 0x41}},
- {[]rune{0x41, 0x300, 0x40, 0x316}, []rune{0x41, 0x300, 0x40, 0x316}},
-}
-
-func TestInsert(t *testing.T) {
- runTests(t, "TestInsert", NFD, insert, insertTests)
-}
-
-var decompositionNFDTest = []TestCase{
- {[]rune{0xC0}, []rune{0x41, 0x300}},
- {[]rune{0xAC00}, []rune{0x1100, 0x1161}},
- {[]rune{0x01C4}, []rune{0x01C4}},
- {[]rune{0x320E}, []rune{0x320E}},
- {[]rune("음ẻ과"), []rune{0x110B, 0x1173, 0x11B7, 0x65, 0x309, 0x1100, 0x116A}},
-}
-
-var decompositionNFKDTest = []TestCase{
- {[]rune{0xC0}, []rune{0x41, 0x300}},
- {[]rune{0xAC00}, []rune{0x1100, 0x1161}},
- {[]rune{0x01C4}, []rune{0x44, 0x5A, 0x030C}},
- {[]rune{0x320E}, []rune{0x28, 0x1100, 0x1161, 0x29}},
-}
-
-func TestDecomposition(t *testing.T) {
- runTests(t, "TestDecompositionNFD", NFD, insert, decompositionNFDTest)
- runTests(t, "TestDecompositionNFKD", NFKD, insert, decompositionNFKDTest)
-}
-
-var compositionTest = []TestCase{
- {[]rune{0x41, 0x300}, []rune{0xC0}},
- {[]rune{0x41, 0x316}, []rune{0x41, 0x316}},
- {[]rune{0x41, 0x300, 0x35D}, []rune{0xC0, 0x35D}},
- {[]rune{0x41, 0x316, 0x300}, []rune{0xC0, 0x316}},
- // blocking starter
- {[]rune{0x41, 0x316, 0x40, 0x300}, []rune{0x41, 0x316, 0x40, 0x300}},
- {[]rune{0x1100, 0x1161}, []rune{0xAC00}},
- // parenthesized Hangul, alternate between ASCII and Hangul.
- {[]rune{0x28, 0x1100, 0x1161, 0x29}, []rune{0x28, 0xAC00, 0x29}},
-}
-
-func TestComposition(t *testing.T) {
- runTests(t, "TestComposition", NFC, insert, compositionTest)
-}
diff --git a/src/pkg/exp/norm/example_iter_test.go b/src/pkg/exp/norm/example_iter_test.go
deleted file mode 100644
index edb9fcf55..000000000
--- a/src/pkg/exp/norm/example_iter_test.go
+++ /dev/null
@@ -1,81 +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.
-
-package norm_test
-
-import (
- "bytes"
- "exp/norm"
- "fmt"
- "unicode/utf8"
-)
-
-// EqualSimple uses a norm.Iter to compare two non-normalized
-// strings for equivalence.
-func EqualSimple(a, b string) bool {
- var ia, ib norm.Iter
- ia.InitString(norm.NFKD, a)
- ib.InitString(norm.NFKD, b)
- for !ia.Done() && !ib.Done() {
- if !bytes.Equal(ia.Next(), ib.Next()) {
- return false
- }
- }
- return ia.Done() && ib.Done()
-}
-
-// FindPrefix finds the longest common prefix of ASCII characters
-// of a and b.
-func FindPrefix(a, b string) int {
- i := 0
- for ; i < len(a) && i < len(b) && a[i] < utf8.RuneSelf && a[i] == b[i]; i++ {
- }
- return i
-}
-
-// EqualOpt is like EqualSimple, but optimizes the special
-// case for ASCII characters.
-func EqualOpt(a, b string) bool {
- n := FindPrefix(a, b)
- a, b = a[n:], b[n:]
- var ia, ib norm.Iter
- ia.InitString(norm.NFKD, a)
- ib.InitString(norm.NFKD, b)
- for !ia.Done() && !ib.Done() {
- if !bytes.Equal(ia.Next(), ib.Next()) {
- return false
- }
- if n := int64(FindPrefix(a[ia.Pos():], b[ib.Pos():])); n != 0 {
- ia.Seek(n, 1)
- ib.Seek(n, 1)
- }
- }
- return ia.Done() && ib.Done()
-}
-
-var compareTests = []struct{ a, b string }{
- {"aaa", "aaa"},
- {"aaa", "aab"},
- {"a\u0300a", "\u00E0a"},
- {"a\u0300\u0320b", "a\u0320\u0300b"},
- {"\u1E0A\u0323", "\x44\u0323\u0307"},
- // A character that decomposes into multiple segments
- // spans several iterations.
- {"\u3304", "\u30A4\u30CB\u30F3\u30AF\u3099"},
-}
-
-func ExampleIter() {
- for i, t := range compareTests {
- r0 := EqualSimple(t.a, t.b)
- r1 := EqualOpt(t.a, t.b)
- fmt.Printf("%d: %v %v\n", i, r0, r1)
- }
- // Output:
- // 0: true true
- // 1: false false
- // 2: true true
- // 3: true true
- // 4: true true
- // 5: true true
-}
diff --git a/src/pkg/exp/norm/forminfo.go b/src/pkg/exp/norm/forminfo.go
deleted file mode 100644
index 7f7ee72e8..000000000
--- a/src/pkg/exp/norm/forminfo.go
+++ /dev/null
@@ -1,229 +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 norm
-
-// This file contains Form-specific logic and wrappers for data in tables.go.
-
-// Rune info is stored in a separate trie per composing form. A composing form
-// and its corresponding decomposing form share the same trie. Each trie maps
-// a rune to a uint16. The values take two forms. For v >= 0x8000:
-// bits
-// 0..8: ccc
-// 9..12: qcInfo (see below). isYesD is always true (no decompostion).
-// 16: 1
-// For v < 0x8000, the respective rune has a decomposition and v is an index
-// into a byte array of UTF-8 decomposition sequences and additional info and
-// has the form:
-// <header> <decomp_byte>* [<tccc> [<lccc>]]
-// The header contains the number of bytes in the decomposition (excluding this
-// length byte). The two most significant bits of this length byte correspond
-// to bit 2 and 3 of qcIfo (see below). The byte sequence itself starts at v+1.
-// The byte sequence is followed by a trailing and leading CCC if the values
-// for these are not zero. The value of v determines which ccc are appended
-// to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
-// the sequence is followed by a trailing ccc, and for v >= firstLeadingCC
-// there is an additional leading ccc.
-
-const (
- qcInfoMask = 0xF // to clear all but the relevant bits in a qcInfo
- headerLenMask = 0x3F // extract the length value from the header byte
- headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
-)
-
-// 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)
- tccc uint8 // trailing canonical combining class (ccc if not decomposition)
- flags qcInfo // quick check flags
- index uint16
-}
-
-// functions dispatchable per form
-type lookupFunc func(b input, i int) Properties
-
-// formInfo holds Form-specific functions and tables.
-type formInfo struct {
- form Form
- composing, compatibility bool // form type
- info lookupFunc
- nextMain iterFunc
-}
-
-var formTable []*formInfo
-
-func init() {
- formTable = make([]*formInfo, 4)
-
- for i := range formTable {
- f := &formInfo{}
- formTable[i] = f
- f.form = Form(i)
- if Form(i) == NFKD || Form(i) == NFKC {
- f.compatibility = true
- f.info = lookupInfoNFKC
- } else {
- f.info = lookupInfoNFC
- }
- f.nextMain = nextDecomposed
- if Form(i) == NFC || Form(i) == NFKC {
- f.nextMain = nextComposed
- f.composing = true
- }
- }
-}
-
-// 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
-// perspective it is not a good boundary. We will therefore always use the
-// boundaries for the combining variants.
-
-// 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
- // is always non-zero if different from info.ccc and that we can return
- // false at this point. This is verified by maketables.
- return false
-}
-
-// 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:
-// 0: NFD_QC Yes (0) or No (1). No also means there is a decomposition.
-// 1..2: NFC_QC Yes(00), No (10), or Maybe (11)
-// 3: Combines forward (0 == false, 1 == true)
-//
-// When all 4 bits are zero, the character is inert, meaning it is never
-// influenced by normalization.
-type qcInfo uint8
-
-func (p Properties) isYesC() bool { return p.flags&0x4 == 0 }
-func (p Properties) isYesD() bool { return p.flags&0x1 == 0 }
-
-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 (p Properties) isInert() bool {
- return p.flags&0xf == 0 && p.ccc == 0
-}
-
-func (p Properties) multiSegment() bool {
- return p.index >= firstMulti && p.index < endMulti
-}
-
-// 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
- }
- 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
-// We use 32-bit keys instead of 64-bit for the two codepoint keys.
-// This clips off the bits of three entries, but we know this will not
-// result in a collision. In the unlikely event that changes to
-// UnicodeData.txt introduce collisions, the compiler will catch it.
-// Note that the recomposition map for NFC and NFKC are identical.
-
-// combine returns the combined rune or 0 if it doesn't exist.
-func combine(a, b rune) rune {
- key := uint32(uint16(a))<<16 + uint32(uint16(b))
- return recompMap[key]
-}
-
-func lookupInfoNFC(b input, i int) Properties {
- v, sz := b.charinfoNFC(i)
- return compInfo(v, sz)
-}
-
-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 Properties. See the comment at the top of the file
-// for more information on the format.
-func compInfo(v uint16, sz int) Properties {
- if v == 0 {
- return Properties{size: uint8(sz)}
- } else if v >= 0x8000 {
- return Properties{
- size: uint8(sz),
- ccc: uint8(v),
- tccc: uint8(v),
- flags: qcInfo(v>>8) & qcInfoMask,
- }
- }
- // has decomposition
- h := decomps[v]
- f := (qcInfo(h&headerFlagsMask) >> 4) | 0x1
- ri := Properties{size: uint8(sz), flags: f, index: v}
- if v >= firstCCC {
- v += uint16(h&headerLenMask) + 1
- ri.tccc = decomps[v]
- if v >= firstLeadingCCC {
- ri.ccc = decomps[v+1]
- }
- }
- return ri
-}
diff --git a/src/pkg/exp/norm/input.go b/src/pkg/exp/norm/input.go
deleted file mode 100644
index d0177a14a..000000000
--- a/src/pkg/exp/norm/input.go
+++ /dev/null
@@ -1,105 +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 norm
-
-import "unicode/utf8"
-
-type input struct {
- str string
- bytes []byte
-}
-
-func inputBytes(str []byte) input {
- return input{bytes: str}
-}
-
-func inputString(str string) input {
- return input{str: str}
-}
-
-func (in *input) setBytes(str []byte) {
- in.str = ""
- in.bytes = str
-}
-
-func (in *input) setString(str string) {
- in.str = str
- in.bytes = nil
-}
-
-func (in *input) _byte(p int) byte {
- if in.bytes == nil {
- return in.str[p]
- }
- return in.bytes[p]
-}
-
-func (in *input) skipASCII(p, max int) int {
- if in.bytes == nil {
- for ; p < max && in.str[p] < utf8.RuneSelf; p++ {
- }
- } else {
- for ; p < max && in.bytes[p] < utf8.RuneSelf; p++ {
- }
- }
- return p
-}
-
-func (in *input) skipNonStarter(p int) int {
- if in.bytes == nil {
- for ; p < len(in.str) && !utf8.RuneStart(in.str[p]); p++ {
- }
- } else {
- for ; p < len(in.bytes) && !utf8.RuneStart(in.bytes[p]); p++ {
- }
- }
- return p
-}
-
-func (in *input) appendSlice(buf []byte, b, e int) []byte {
- if in.bytes != nil {
- return append(buf, in.bytes[b:e]...)
- }
- for i := b; i < e; i++ {
- buf = append(buf, in.str[i])
- }
- return buf
-}
-
-func (in *input) copySlice(buf []byte, b, e int) int {
- if in.bytes == nil {
- return copy(buf, in.str[b:e])
- }
- return copy(buf, in.bytes[b:e])
-}
-
-func (in *input) charinfoNFC(p int) (uint16, int) {
- if in.bytes == nil {
- return nfcTrie.lookupString(in.str[p:])
- }
- return nfcTrie.lookup(in.bytes[p:])
-}
-
-func (in *input) charinfoNFKC(p int) (uint16, int) {
- if in.bytes == nil {
- return nfkcTrie.lookupString(in.str[p:])
- }
- return nfkcTrie.lookup(in.bytes[p:])
-}
-
-func (in *input) hangul(p int) (r rune) {
- if in.bytes == nil {
- if !isHangulString(in.str[p:]) {
- return 0
- }
- r, _ = utf8.DecodeRuneInString(in.str[p:])
- } else {
- if !isHangul(in.bytes[p:]) {
- return 0
- }
- r, _ = utf8.DecodeRune(in.bytes[p:])
- }
- return r
-}
diff --git a/src/pkg/exp/norm/iter.go b/src/pkg/exp/norm/iter.go
deleted file mode 100644
index a9546247c..000000000
--- a/src/pkg/exp/norm/iter.go
+++ /dev/null
@@ -1,401 +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 norm
-
-import (
- "fmt"
- "unicode/utf8"
-)
-
-const MaxSegmentSize = maxByteBufferSize
-
-// An Iter iterates over a string or byte slice, while normalizing it
-// to a given Form.
-type Iter struct {
- rb reorderBuffer
- buf [maxByteBufferSize]byte
- info Properties // first character saved from previous iteration
- next iterFunc // implementation of next depends on form
- asciiF iterFunc
-
- p int // current position in input source
- multiSeg []byte // remainder of multi-segment decomposition
-}
-
-type iterFunc func(*Iter) []byte
-
-// Init initializes i to iterate over src after normalizing it to Form f.
-func (i *Iter) Init(f Form, src []byte) {
- i.p = 0
- if len(src) == 0 {
- i.setDone()
- i.rb.nsrc = 0
- return
- }
- i.multiSeg = nil
- i.rb.init(f, src)
- i.next = i.rb.f.nextMain
- i.asciiF = nextASCIIBytes
- i.info = i.rb.f.info(i.rb.src, i.p)
-}
-
-// InitString initializes i to iterate over src after normalizing it to Form f.
-func (i *Iter) InitString(f Form, src string) {
- i.p = 0
- if len(src) == 0 {
- i.setDone()
- i.rb.nsrc = 0
- return
- }
- i.multiSeg = nil
- i.rb.initString(f, src)
- i.next = i.rb.f.nextMain
- i.asciiF = nextASCIIString
- i.info = i.rb.f.info(i.rb.src, i.p)
-}
-
-// Seek sets the segment to be returned by the next call to Next to start
-// at position p. It is the responsibility of the caller to set p to the
-// start of a UTF8 rune.
-func (i *Iter) Seek(offset int64, whence int) (int64, error) {
- var abs int64
- switch whence {
- case 0:
- abs = offset
- case 1:
- abs = int64(i.p) + offset
- case 2:
- abs = int64(i.rb.nsrc) + offset
- default:
- return 0, fmt.Errorf("norm: invalid whence")
- }
- if abs < 0 {
- return 0, fmt.Errorf("norm: negative position")
- }
- if int(abs) >= i.rb.nsrc {
- i.setDone()
- return int64(i.p), nil
- }
- i.p = int(abs)
- i.multiSeg = nil
- i.next = i.rb.f.nextMain
- i.info = i.rb.f.info(i.rb.src, i.p)
- return abs, nil
-}
-
-// returnSlice returns a slice of the underlying input type as a byte slice.
-// If the underlying is of type []byte, it will simply return a slice.
-// If the underlying is of type string, it will copy the slice to the buffer
-// and return that.
-func (i *Iter) returnSlice(a, b int) []byte {
- if i.rb.src.bytes == nil {
- return i.buf[:copy(i.buf[:], i.rb.src.str[a:b])]
- }
- return i.rb.src.bytes[a:b]
-}
-
-// Pos returns the byte position at which the next call to Next will commence processing.
-func (i *Iter) Pos() int {
- return i.p
-}
-
-func (i *Iter) setDone() {
- i.next = nextDone
- i.p = i.rb.nsrc
-}
-
-// Done returns true if there is no more input to process.
-func (i *Iter) Done() bool {
- return i.p >= i.rb.nsrc
-}
-
-// Next returns f(i.input[i.Pos():n]), where n is a boundary of i.input.
-// For any input a and b for which f(a) == f(b), subsequent calls
-// to Next will return the same segments.
-// Modifying runes are grouped together with the preceding starter, if such a starter exists.
-// Although not guaranteed, n will typically be the smallest possible n.
-func (i *Iter) Next() []byte {
- return i.next(i)
-}
-
-func nextASCIIBytes(i *Iter) []byte {
- p := i.p + 1
- if p >= i.rb.nsrc {
- i.setDone()
- return i.rb.src.bytes[i.p:p]
- }
- if i.rb.src.bytes[p] < utf8.RuneSelf {
- p0 := i.p
- i.p = p
- return i.rb.src.bytes[p0:p]
- }
- i.info = i.rb.f.info(i.rb.src, i.p)
- i.next = i.rb.f.nextMain
- return i.next(i)
-}
-
-func nextASCIIString(i *Iter) []byte {
- p := i.p + 1
- if p >= i.rb.nsrc {
- i.buf[0] = i.rb.src.str[i.p]
- i.setDone()
- return i.buf[:1]
- }
- if i.rb.src.str[p] < utf8.RuneSelf {
- i.buf[0] = i.rb.src.str[i.p]
- i.p = p
- return i.buf[:1]
- }
- i.info = i.rb.f.info(i.rb.src, i.p)
- i.next = i.rb.f.nextMain
- return i.next(i)
-}
-
-func nextHangul(i *Iter) []byte {
- if r := i.rb.src.hangul(i.p); r != 0 {
- i.p += hangulUTF8Size
- if i.p >= i.rb.nsrc {
- i.setDone()
- }
- return i.buf[:decomposeHangul(i.buf[:], r)]
- }
- i.info = i.rb.f.info(i.rb.src, i.p)
- i.next = i.rb.f.nextMain
- return i.next(i)
-}
-
-func nextDone(i *Iter) []byte {
- return nil
-}
-
-// nextMulti is used for iterating over multi-segment decompositions
-// for decomposing normal forms.
-func nextMulti(i *Iter) []byte {
- j := 0
- d := i.multiSeg
- // skip first rune
- for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
- }
- for j < len(d) {
- info := i.rb.f.info(input{bytes: d}, j)
- if info.ccc == 0 {
- i.multiSeg = d[j:]
- return d[:j]
- }
- j += int(info.size)
- }
- // treat last segment as normal decomposition
- i.next = i.rb.f.nextMain
- return i.next(i)
-}
-
-// nextMultiNorm is used for iterating over multi-segment decompositions
-// for composing normal forms.
-func nextMultiNorm(i *Iter) []byte {
- j := 0
- d := i.multiSeg
- // skip first rune
- for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
- }
- for j < len(d) {
- info := i.rb.f.info(input{bytes: d}, j)
- if info.ccc == 0 {
- i.multiSeg = d[j:]
- return d[:j]
- }
- j += int(info.size)
- }
- i.multiSeg = nil
- i.next = nextComposed
- i.p++ // restore old valud of i.p. See nextComposed.
- if i.p >= i.rb.nsrc {
- i.setDone()
- }
- return d
-}
-
-// nextDecomposed is the implementation of Next for forms NFD and NFKD.
-func nextDecomposed(i *Iter) (next []byte) {
- startp, outp := i.p, 0
- inCopyStart, outCopyStart := i.p, 0
- for {
- if sz := int(i.info.size); sz <= 1 {
- p := i.p
- i.p++ // ASCII or illegal byte. Either way, advance by 1.
- if i.p >= i.rb.nsrc {
- i.setDone()
- return i.returnSlice(p, i.p)
- } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
- i.next = i.asciiF
- return i.returnSlice(p, i.p)
- }
- outp++
- } else if d := i.info.Decomposition(); d != nil {
- // Note: If leading CCC != 0, then len(d) == 2 and last is also non-zero.
- // Case 1: there is a leftover to copy. In this case the decomposition
- // must begin with a modifier and should always be appended.
- // Case 2: no leftover. Simply return d if followed by a ccc == 0 value.
- p := outp + len(d)
- if outp > 0 {
- i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
- if p > len(i.buf) {
- return i.buf[:outp]
- }
- } else if i.info.multiSegment() {
- // outp must be 0 as multi-segment decompositions always
- // start a new segment.
- if i.multiSeg == nil {
- i.multiSeg = d
- i.next = nextMulti
- return nextMulti(i)
- }
- // We are in the last segment. Treat as normal decomposition.
- d = i.multiSeg
- i.multiSeg = nil
- p = len(d)
- }
- prevCC := i.info.tccc
- if i.p += sz; i.p >= i.rb.nsrc {
- i.setDone()
- i.info = Properties{} // Force BoundaryBefore to succeed.
- } else {
- i.info = i.rb.f.info(i.rb.src, i.p)
- }
- if i.info.BoundaryBefore() {
- if outp > 0 {
- copy(i.buf[outp:], d)
- return i.buf[:p]
- }
- return d
- }
- copy(i.buf[outp:], d)
- outp = p
- inCopyStart, outCopyStart = i.p, outp
- if i.info.ccc < prevCC {
- goto doNorm
- }
- continue
- } else if r := i.rb.src.hangul(i.p); r != 0 {
- i.next = nextHangul
- i.p += hangulUTF8Size
- if i.p >= i.rb.nsrc {
- i.setDone()
- }
- return i.buf[:decomposeHangul(i.buf[:], r)]
- } else {
- p := outp + sz
- if p > len(i.buf) {
- break
- }
- outp = p
- i.p += sz
- }
- if i.p >= i.rb.nsrc {
- i.setDone()
- break
- }
- prevCC := i.info.tccc
- i.info = i.rb.f.info(i.rb.src, i.p)
- if i.info.BoundaryBefore() {
- break
- } else if i.info.ccc < prevCC {
- goto doNorm
- }
- }
- if outCopyStart == 0 {
- return i.returnSlice(inCopyStart, i.p)
- } else if inCopyStart < i.p {
- i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
- }
- return i.buf[:outp]
-doNorm:
- // Insert what we have decomposed so far in the reorderBuffer.
- // As we will only reorder, there will always be enough room.
- i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
- if !i.rb.insertDecomposed(i.buf[0:outp]) {
- // Start over to prevent decompositions from crossing segment boundaries.
- // This is a rare occurrence.
- i.p = startp
- i.info = i.rb.f.info(i.rb.src, i.p)
- }
- for {
- if !i.rb.insert(i.rb.src, i.p, i.info) {
- break
- }
- if i.p += int(i.info.size); i.p >= i.rb.nsrc {
- i.setDone()
- break
- }
- i.info = i.rb.f.info(i.rb.src, i.p)
- if i.info.ccc == 0 {
- break
- }
- }
- // new segment or too many combining characters: exit normalization
- return i.buf[:i.rb.flushCopy(i.buf[:])]
-}
-
-// nextComposed is the implementation of Next for forms NFC and NFKC.
-func nextComposed(i *Iter) []byte {
- outp, startp := 0, i.p
- var prevCC uint8
- for {
- if !i.info.isYesC() {
- goto doNorm
- }
- if cc := i.info.ccc; cc == 0 && outp > 0 {
- break
- } else if cc < prevCC {
- goto doNorm
- }
- prevCC = i.info.tccc
- sz := int(i.info.size)
- if sz == 0 {
- sz = 1 // illegal rune: copy byte-by-byte
- }
- p := outp + sz
- if p > len(i.buf) {
- break
- }
- outp = p
- i.p += sz
- if i.p >= i.rb.nsrc {
- i.setDone()
- break
- } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
- i.next = i.asciiF
- break
- }
- i.info = i.rb.f.info(i.rb.src, i.p)
- }
- return i.returnSlice(startp, i.p)
-doNorm:
- multi := false
- i.p = startp
- i.info = i.rb.f.info(i.rb.src, i.p)
- for {
- if !i.rb.insert(i.rb.src, i.p, i.info) {
- break
- }
- multi = multi || i.info.multiSegment()
- if i.p += int(i.info.size); i.p >= i.rb.nsrc {
- i.setDone()
- break
- }
- i.info = i.rb.f.info(i.rb.src, i.p)
- if i.info.BoundaryBefore() {
- break
- }
- }
- i.rb.compose()
- seg := i.buf[:i.rb.flushCopy(i.buf[:])]
- if multi {
- i.p-- // fake not being done yet
- i.multiSeg = seg
- i.next = nextMultiNorm
- return nextMultiNorm(i)
- }
- return seg
-}
diff --git a/src/pkg/exp/norm/iter_test.go b/src/pkg/exp/norm/iter_test.go
deleted file mode 100644
index 826119362..000000000
--- a/src/pkg/exp/norm/iter_test.go
+++ /dev/null
@@ -1,188 +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 norm
-
-import (
- "strings"
- "testing"
-)
-
-func doIterNorm(f Form, s string) []byte {
- acc := []byte{}
- i := Iter{}
- i.InitString(f, s)
- for !i.Done() {
- acc = append(acc, i.Next()...)
- }
- return acc
-}
-
-func runIterTests(t *testing.T, name string, f Form, tests []AppendTest, norm bool) {
- for i, test := range tests {
- in := test.left + test.right
- gold := test.out
- if norm {
- gold = string(f.AppendString(nil, test.out))
- }
- out := string(doIterNorm(f, in))
- if len(out) != len(gold) {
- const msg = "%s:%d: length is %d; want %d"
- t.Errorf(msg, name, i, len(out), len(gold))
- }
- if out != gold {
- // Find first rune that differs and show context.
- ir := []rune(out)
- ig := []rune(gold)
- t.Errorf("\n%X != \n%X", ir, ig)
- for j := 0; j < len(ir) && j < len(ig); j++ {
- if ir[j] == ig[j] {
- continue
- }
- if j -= 3; j < 0 {
- j = 0
- }
- for e := j + 7; j < e && j < len(ir) && j < len(ig); j++ {
- const msg = "%s:%d: runeAt(%d) = %U; want %U"
- t.Errorf(msg, name, i, j, ir[j], ig[j])
- }
- break
- }
- }
- }
-}
-
-func rep(r rune, n int) string {
- return strings.Repeat(string(r), n)
-}
-
-const segSize = maxByteBufferSize
-
-var iterTests = []AppendTest{
- {"", ascii, ascii},
- {"", txt_all, txt_all},
- {"", "a" + rep(0x0300, segSize/2), "a" + rep(0x0300, segSize/2)},
-}
-
-var iterTestsD = []AppendTest{
- { // segment overflow on unchanged character
- "",
- "a" + rep(0x0300, segSize/2) + "\u0316",
- "a" + rep(0x0300, segSize/2-1) + "\u0316\u0300",
- },
- { // segment overflow on unchanged character + start value
- "",
- "a" + rep(0x0300, segSize/2+maxCombiningChars+4) + "\u0316",
- "a" + rep(0x0300, segSize/2+maxCombiningChars) + "\u0316" + rep(0x300, 4),
- },
- { // segment overflow on decomposition
- "",
- "a" + rep(0x0300, segSize/2-1) + "\u0340",
- "a" + rep(0x0300, segSize/2),
- },
- { // segment overflow on decomposition + start value
- "",
- "a" + rep(0x0300, segSize/2-1) + "\u0340" + rep(0x300, maxCombiningChars+4) + "\u0320",
- "a" + rep(0x0300, segSize/2-1) + rep(0x300, maxCombiningChars+1) + "\u0320" + rep(0x300, 4),
- },
- { // start value after ASCII overflow
- "",
- rep('a', segSize) + rep(0x300, maxCombiningChars+2) + "\u0320",
- rep('a', segSize) + rep(0x300, maxCombiningChars) + "\u0320\u0300\u0300",
- },
- { // start value after Hangul overflow
- "",
- rep(0xAC00, segSize/6) + rep(0x300, maxCombiningChars+2) + "\u0320",
- strings.Repeat("\u1100\u1161", segSize/6) + rep(0x300, maxCombiningChars+1) + "\u0320" + rep(0x300, 1),
- },
- { // start value after cc=0
- "",
- "您您" + rep(0x300, maxCombiningChars+4) + "\u0320",
- "您您" + rep(0x300, maxCombiningChars) + "\u0320" + rep(0x300, 4),
- },
- { // start value after normalization
- "",
- "\u0300\u0320a" + rep(0x300, maxCombiningChars+4) + "\u0320",
- "\u0320\u0300a" + rep(0x300, maxCombiningChars) + "\u0320" + rep(0x300, 4),
- },
-}
-
-var iterTestsC = []AppendTest{
- { // ordering of non-composing combining characters
- "",
- "\u0305\u0316",
- "\u0316\u0305",
- },
- { // segment overflow
- "",
- "a" + rep(0x0305, segSize/2+4) + "\u0316",
- "a" + rep(0x0305, segSize/2-1) + "\u0316" + rep(0x305, 5),
- },
-}
-
-func TestIterNextD(t *testing.T) {
- runIterTests(t, "IterNextD1", NFKD, appendTests, true)
- runIterTests(t, "IterNextD2", NFKD, iterTests, true)
- runIterTests(t, "IterNextD3", NFKD, iterTestsD, false)
-}
-
-func TestIterNextC(t *testing.T) {
- runIterTests(t, "IterNextC1", NFKC, appendTests, true)
- runIterTests(t, "IterNextC2", NFKC, iterTests, true)
- runIterTests(t, "IterNextC3", NFKC, iterTestsC, false)
-}
-
-type SegmentTest struct {
- in string
- out []string
-}
-
-var segmentTests = []SegmentTest{
- {"\u1E0A\u0323a", []string{"\x44\u0323\u0307", "a", ""}},
- {rep('a', segSize), append(strings.Split(rep('a', segSize), ""), "")},
- {rep('a', segSize+2), append(strings.Split(rep('a', segSize+2), ""), "")},
- {rep('a', segSize) + "\u0300aa",
- append(strings.Split(rep('a', segSize-1), ""), "a\u0300", "a", "a", "")},
-}
-
-var segmentTestsK = []SegmentTest{
- {"\u3332", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u3099", ""}},
- // last segment of multi-segment decomposition needs normalization
- {"\u3332\u093C", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u093C\u3099", ""}},
- // Hangul and Jamo are grouped togeter.
- {"\uAC00", []string{"\u1100\u1161", ""}},
- {"\uAC01", []string{"\u1100\u1161\u11A8", ""}},
- {"\u1100\u1161", []string{"\u1100\u1161", ""}},
-}
-
-// Note that, by design, segmentation is equal for composing and decomposing forms.
-func TestIterSegmentation(t *testing.T) {
- segmentTest(t, "SegmentTestD", NFD, segmentTests)
- segmentTest(t, "SegmentTestC", NFC, segmentTests)
- segmentTest(t, "SegmentTestD", NFKD, segmentTestsK)
- segmentTest(t, "SegmentTestC", NFKC, segmentTestsK)
-}
-
-func segmentTest(t *testing.T, name string, f Form, tests []SegmentTest) {
- iter := Iter{}
- for i, tt := range tests {
- iter.InitString(f, tt.in)
- for j, seg := range tt.out {
- if seg == "" {
- if !iter.Done() {
- res := string(iter.Next())
- t.Errorf(`%s:%d:%d: expected Done()==true, found segment "%s"`, name, i, j, res)
- }
- continue
- }
- if iter.Done() {
- t.Errorf("%s:%d:%d: Done()==true, want false", name, i, j)
- }
- seg = f.String(seg)
- if res := string(iter.Next()); res != seg {
- t.Errorf(`%s:%d:%d" segment was "%s" (%d); want "%s" (%d) %X %X`, name, i, j, res, len(res), seg, len(seg), []rune(res), []rune(seg))
- }
- }
- }
-}
diff --git a/src/pkg/exp/norm/maketables.go b/src/pkg/exp/norm/maketables.go
deleted file mode 100644
index 50c0c310a..000000000
--- a/src/pkg/exp/norm/maketables.go
+++ /dev/null
@@ -1,923 +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 ignore
-
-// Normalization table generator.
-// Data read from the web.
-// See forminfo.go for a description of the trie values associated with each rune.
-
-package main
-
-import (
- "bufio"
- "bytes"
- "flag"
- "fmt"
- "io"
- "log"
- "net/http"
- "os"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "unicode"
-)
-
-func main() {
- flag.Parse()
- loadUnicodeData()
- loadCompositionExclusions()
- completeCharFields(FCanonical)
- completeCharFields(FCompatibility)
- verifyComputed()
- printChars()
- makeTables()
- testDerived()
-}
-
-var url = flag.String("url",
- "http://www.unicode.org/Public/"+unicode.Version+"/ucd/",
- "URL of Unicode database directory")
-var tablelist = flag.String("tables",
- "all",
- "comma-separated list of which tables to generate; "+
- "can be 'decomp', 'recomp', 'info' and 'all'")
-var test = flag.Bool("test",
- false,
- "test existing tables; can be used to compare web data with package data")
-var verbose = flag.Bool("verbose",
- false,
- "write data to stdout as it is parsed")
-var localFiles = flag.Bool("local",
- false,
- "data files have been copied to the current directory; for debugging only")
-
-var logger = log.New(os.Stderr, "", log.Lshortfile)
-
-// UnicodeData.txt has form:
-// 0037;DIGIT SEVEN;Nd;0;EN;;7;7;7;N;;;;;
-// 007A;LATIN SMALL LETTER Z;Ll;0;L;;;;;N;;;005A;;005A
-// See http://unicode.org/reports/tr44/ for full explanation
-// The fields:
-const (
- FCodePoint = iota
- FName
- FGeneralCategory
- FCanonicalCombiningClass
- FBidiClass
- FDecompMapping
- FDecimalValue
- FDigitValue
- FNumericValue
- FBidiMirrored
- FUnicode1Name
- FISOComment
- FSimpleUppercaseMapping
- FSimpleLowercaseMapping
- FSimpleTitlecaseMapping
- NumField
-
- MaxChar = 0x10FFFF // anything above this shouldn't exist
-)
-
-// Quick Check properties of runes allow us to quickly
-// determine whether a rune may occur in a normal form.
-// For a given normal form, a rune may be guaranteed to occur
-// verbatim (QC=Yes), may or may not combine with another
-// rune (QC=Maybe), or may not occur (QC=No).
-type QCResult int
-
-const (
- QCUnknown QCResult = iota
- QCYes
- QCNo
- QCMaybe
-)
-
-func (r QCResult) String() string {
- switch r {
- case QCYes:
- return "Yes"
- case QCNo:
- return "No"
- case QCMaybe:
- return "Maybe"
- }
- return "***UNKNOWN***"
-}
-
-const (
- FCanonical = iota // NFC or NFD
- FCompatibility // NFKC or NFKD
- FNumberOfFormTypes
-)
-
-const (
- MComposed = iota // NFC or NFKC
- MDecomposed // NFD or NFKD
- MNumberOfModes
-)
-
-// This contains only the properties we're interested in.
-type Char struct {
- name string
- codePoint rune // if zero, this index is not a valid code point.
- ccc uint8 // canonical combining class
- excludeInComp bool // from CompositionExclusions.txt
- compatDecomp bool // it has a compatibility expansion
-
- forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility
-
- state State
-}
-
-var chars = make([]Char, MaxChar+1)
-
-func (c Char) String() string {
- buf := new(bytes.Buffer)
-
- fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name)
- fmt.Fprintf(buf, " ccc: %v\n", c.ccc)
- fmt.Fprintf(buf, " excludeInComp: %v\n", c.excludeInComp)
- fmt.Fprintf(buf, " compatDecomp: %v\n", c.compatDecomp)
- fmt.Fprintf(buf, " state: %v\n", c.state)
- fmt.Fprintf(buf, " NFC:\n")
- fmt.Fprint(buf, c.forms[FCanonical])
- fmt.Fprintf(buf, " NFKC:\n")
- fmt.Fprint(buf, c.forms[FCompatibility])
-
- return buf.String()
-}
-
-// In UnicodeData.txt, some ranges are marked like this:
-// 3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
-// 4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
-// parseCharacter keeps a state variable indicating the weirdness.
-type State int
-
-const (
- SNormal State = iota // known to be zero for the type
- SFirst
- SLast
- SMissing
-)
-
-var lastChar = rune('\u0000')
-
-func (c Char) isValid() bool {
- return c.codePoint != 0 && c.state != SMissing
-}
-
-type FormInfo struct {
- quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed
- verified [MNumberOfModes]bool // index: MComposed or MDecomposed
-
- combinesForward bool // May combine with rune on the right
- combinesBackward bool // May combine with rune on the left
- isOneWay bool // Never appears in result
- inDecomp bool // Some decompositions result in this char.
- decomp Decomposition
- expandedDecomp Decomposition
-}
-
-func (f FormInfo) String() string {
- buf := bytes.NewBuffer(make([]byte, 0))
-
- fmt.Fprintf(buf, " quickCheck[C]: %v\n", f.quickCheck[MComposed])
- fmt.Fprintf(buf, " quickCheck[D]: %v\n", f.quickCheck[MDecomposed])
- fmt.Fprintf(buf, " cmbForward: %v\n", f.combinesForward)
- fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward)
- fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay)
- fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp)
- fmt.Fprintf(buf, " decomposition: %X\n", f.decomp)
- fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp)
-
- return buf.String()
-}
-
-type Decomposition []rune
-
-func openReader(file string) (input io.ReadCloser) {
- if *localFiles {
- f, err := os.Open(file)
- if err != nil {
- logger.Fatal(err)
- }
- input = f
- } else {
- path := *url + file
- resp, err := http.Get(path)
- if err != nil {
- logger.Fatal(err)
- }
- if resp.StatusCode != 200 {
- logger.Fatal("bad GET status for "+file, resp.Status)
- }
- input = resp.Body
- }
- return
-}
-
-func parseDecomposition(s string, skipfirst bool) (a []rune, e error) {
- decomp := strings.Split(s, " ")
- if len(decomp) > 0 && skipfirst {
- decomp = decomp[1:]
- }
- for _, d := range decomp {
- point, err := strconv.ParseUint(d, 16, 64)
- if err != nil {
- return a, err
- }
- a = append(a, rune(point))
- }
- return a, nil
-}
-
-func parseCharacter(line string) {
- field := strings.Split(line, ";")
- if len(field) != NumField {
- logger.Fatalf("%5s: %d fields (expected %d)\n", line, len(field), NumField)
- }
- x, err := strconv.ParseUint(field[FCodePoint], 16, 64)
- point := int(x)
- if err != nil {
- logger.Fatalf("%.5s...: %s", line, err)
- }
- if point == 0 {
- return // not interesting and we use 0 as unset
- }
- if point > MaxChar {
- logger.Fatalf("%5s: Rune %X > MaxChar (%X)", line, point, MaxChar)
- return
- }
- state := SNormal
- switch {
- case strings.Index(field[FName], ", First>") > 0:
- state = SFirst
- case strings.Index(field[FName], ", Last>") > 0:
- state = SLast
- }
- firstChar := lastChar + 1
- lastChar = rune(point)
- if state != SLast {
- firstChar = lastChar
- }
- x, err = strconv.ParseUint(field[FCanonicalCombiningClass], 10, 64)
- if err != nil {
- logger.Fatalf("%U: bad ccc field: %s", int(x), err)
- }
- ccc := uint8(x)
- decmap := field[FDecompMapping]
- exp, e := parseDecomposition(decmap, false)
- isCompat := false
- if e != nil {
- if len(decmap) > 0 {
- exp, e = parseDecomposition(decmap, true)
- if e != nil {
- logger.Fatalf(`%U: bad decomp |%v|: "%s"`, int(x), decmap, e)
- }
- isCompat = true
- }
- }
- for i := firstChar; i <= lastChar; i++ {
- char := &chars[i]
- char.name = field[FName]
- char.codePoint = i
- char.forms[FCompatibility].decomp = exp
- if !isCompat {
- char.forms[FCanonical].decomp = exp
- } else {
- char.compatDecomp = true
- }
- if len(decmap) > 0 {
- char.forms[FCompatibility].decomp = exp
- }
- char.ccc = ccc
- char.state = SMissing
- if i == lastChar {
- char.state = state
- }
- }
- return
-}
-
-func loadUnicodeData() {
- f := openReader("UnicodeData.txt")
- defer f.Close()
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- parseCharacter(scanner.Text())
- }
- if scanner.Err() != nil {
- logger.Fatal(scanner.Err())
- }
-}
-
-var singlePointRe = regexp.MustCompile(`^([0-9A-F]+) *$`)
-
-// CompositionExclusions.txt has form:
-// 0958 # ...
-// See http://unicode.org/reports/tr44/ for full explanation
-func parseExclusion(line string) int {
- comment := strings.Index(line, "#")
- if comment >= 0 {
- line = line[0:comment]
- }
- if len(line) == 0 {
- return 0
- }
- matches := singlePointRe.FindStringSubmatch(line)
- if len(matches) != 2 {
- logger.Fatalf("%s: %d matches (expected 1)\n", line, len(matches))
- }
- point, err := strconv.ParseUint(matches[1], 16, 64)
- if err != nil {
- logger.Fatalf("%.5s...: %s", line, err)
- }
- return int(point)
-}
-
-func loadCompositionExclusions() {
- f := openReader("CompositionExclusions.txt")
- defer f.Close()
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- point := parseExclusion(scanner.Text())
- if point == 0 {
- continue
- }
- c := &chars[point]
- if c.excludeInComp {
- logger.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint)
- }
- c.excludeInComp = true
- }
- if scanner.Err() != nil {
- log.Fatal(scanner.Err())
- }
-}
-
-// hasCompatDecomp returns true if any of the recursive
-// decompositions contains a compatibility expansion.
-// In this case, the character may not occur in NFK*.
-func hasCompatDecomp(r rune) bool {
- c := &chars[r]
- if c.compatDecomp {
- return true
- }
- for _, d := range c.forms[FCompatibility].decomp {
- if hasCompatDecomp(d) {
- return true
- }
- }
- return false
-}
-
-// Hangul related constants.
-const (
- HangulBase = 0xAC00
- HangulEnd = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28)
-
- JamoLBase = 0x1100
- JamoLEnd = 0x1113
- JamoVBase = 0x1161
- JamoVEnd = 0x1176
- JamoTBase = 0x11A8
- JamoTEnd = 0x11C3
-)
-
-func isHangul(r rune) bool {
- return HangulBase <= r && r < HangulEnd
-}
-
-func ccc(r rune) uint8 {
- return chars[r].ccc
-}
-
-// Insert a rune in a buffer, ordered by Canonical Combining Class.
-func insertOrdered(b Decomposition, r rune) Decomposition {
- n := len(b)
- b = append(b, 0)
- cc := ccc(r)
- if cc > 0 {
- // Use bubble sort.
- for ; n > 0; n-- {
- if ccc(b[n-1]) <= cc {
- break
- }
- b[n] = b[n-1]
- }
- }
- b[n] = r
- return b
-}
-
-// Recursively decompose.
-func decomposeRecursive(form int, r rune, d Decomposition) Decomposition {
- if isHangul(r) {
- return d
- }
- dcomp := chars[r].forms[form].decomp
- if len(dcomp) == 0 {
- return insertOrdered(d, r)
- }
- for _, c := range dcomp {
- d = decomposeRecursive(form, c, d)
- }
- return d
-}
-
-func completeCharFields(form int) {
- // Phase 0: pre-expand decomposition.
- for i := range chars {
- f := &chars[i].forms[form]
- if len(f.decomp) == 0 {
- continue
- }
- exp := make(Decomposition, 0)
- for _, c := range f.decomp {
- exp = decomposeRecursive(form, c, exp)
- }
- f.expandedDecomp = exp
- }
-
- // Phase 1: composition exclusion, mark decomposition.
- for i := range chars {
- c := &chars[i]
- f := &c.forms[form]
-
- // Marks script-specific exclusions and version restricted.
- f.isOneWay = c.excludeInComp
-
- // Singletons
- f.isOneWay = f.isOneWay || len(f.decomp) == 1
-
- // Non-starter decompositions
- if len(f.decomp) > 1 {
- chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0
- f.isOneWay = f.isOneWay || chk
- }
-
- // Runes that decompose into more than two runes.
- f.isOneWay = f.isOneWay || len(f.decomp) > 2
-
- if form == FCompatibility {
- f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint)
- }
-
- for _, r := range f.decomp {
- chars[r].forms[form].inDecomp = true
- }
- }
-
- // Phase 2: forward and backward combining.
- for i := range chars {
- c := &chars[i]
- f := &c.forms[form]
-
- if !f.isOneWay && len(f.decomp) == 2 {
- f0 := &chars[f.decomp[0]].forms[form]
- f1 := &chars[f.decomp[1]].forms[form]
- if !f0.isOneWay {
- f0.combinesForward = true
- }
- if !f1.isOneWay {
- f1.combinesBackward = true
- }
- }
- }
-
- // Phase 3: quick check values.
- for i := range chars {
- c := &chars[i]
- f := &c.forms[form]
-
- switch {
- case len(f.decomp) > 0:
- f.quickCheck[MDecomposed] = QCNo
- case isHangul(rune(i)):
- f.quickCheck[MDecomposed] = QCNo
- default:
- f.quickCheck[MDecomposed] = QCYes
- }
- switch {
- case f.isOneWay:
- f.quickCheck[MComposed] = QCNo
- case (i & 0xffff00) == JamoLBase:
- f.quickCheck[MComposed] = QCYes
- if JamoLBase <= i && i < JamoLEnd {
- f.combinesForward = true
- }
- if JamoVBase <= i && i < JamoVEnd {
- f.quickCheck[MComposed] = QCMaybe
- f.combinesBackward = true
- f.combinesForward = true
- }
- if JamoTBase <= i && i < JamoTEnd {
- f.quickCheck[MComposed] = QCMaybe
- f.combinesBackward = true
- }
- case !f.combinesBackward:
- f.quickCheck[MComposed] = QCYes
- default:
- f.quickCheck[MComposed] = QCMaybe
- }
- }
-}
-
-func printBytes(b []byte, name string) {
- fmt.Printf("// %s: %d bytes\n", name, len(b))
- fmt.Printf("var %s = [...]byte {", name)
- for i, c := range b {
- switch {
- case i%64 == 0:
- fmt.Printf("\n// Bytes %x - %x\n", i, i+63)
- case i%8 == 0:
- fmt.Printf("\n")
- }
- fmt.Printf("0x%.2X, ", c)
- }
- fmt.Print("\n}\n\n")
-}
-
-// See forminfo.go for format.
-func makeEntry(f *FormInfo) uint16 {
- e := uint16(0)
- if f.combinesForward {
- e |= 0x8
- }
- if f.quickCheck[MDecomposed] == QCNo {
- e |= 0x1
- }
- switch f.quickCheck[MComposed] {
- case QCYes:
- case QCNo:
- e |= 0x4
- case QCMaybe:
- e |= 0x6
- default:
- log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed])
- }
- return e
-}
-
-// decompSet keeps track of unique decompositions, grouped by whether
-// the decomposition is followed by a trailing and/or leading CCC.
-type decompSet [6]map[string]bool
-
-const (
- normalDecomp = iota
- firstMulti
- firstCCC
- endMulti
- firstLeadingCCC
- firstCCCZeroExcept
- lastDecomp
-)
-
-var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "lastDecomp"}
-
-func makeDecompSet() decompSet {
- m := decompSet{}
- for i := range m {
- m[i] = make(map[string]bool)
- }
- return m
-}
-func (m *decompSet) insert(key int, s string) {
- m[key][s] = true
-}
-
-func printCharInfoTables() int {
- mkstr := func(r rune, f *FormInfo) (int, string) {
- d := f.expandedDecomp
- s := string([]rune(d))
- if max := 1 << 6; len(s) >= max {
- const msg = "%U: too many bytes in decomposition: %d >= %d"
- logger.Fatalf(msg, r, len(s), max)
- }
- head := uint8(len(s))
- if f.quickCheck[MComposed] != QCYes {
- head |= 0x40
- }
- if f.combinesForward {
- head |= 0x80
- }
- s = string([]byte{head}) + s
-
- 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)
- }
- index := normalDecomp
- if tccc > 0 || lccc > 0 {
- s += string([]byte{tccc})
- index = endMulti
- for _, r := range d[1:] {
- if ccc(r) == 0 {
- index = firstCCC
- }
- }
- if lccc > 0 {
- s += string([]byte{lccc})
- if index == firstCCC {
- logger.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r)
- }
- index = firstLeadingCCC
- }
- if cc != lccc {
- if cc != 0 {
- logger.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc)
- }
- index = firstCCCZeroExcept
- }
- } else if len(d) > 1 {
- index = firstMulti
- }
- return index, s
- }
-
- decompSet := makeDecompSet()
-
- // Store the uniqued decompositions in a byte buffer,
- // preceded by their byte length.
- for _, c := range chars {
- for _, f := range c.forms {
- if len(f.expandedDecomp) == 0 {
- continue
- }
- if f.combinesBackward {
- logger.Fatalf("%U: combinesBackward and decompose", c.codePoint)
- }
- index, s := mkstr(c.codePoint, &f)
- decompSet.insert(index, s)
- }
- }
-
- decompositions := bytes.NewBuffer(make([]byte, 0, 10000))
- size := 0
- positionMap := make(map[string]uint16)
- decompositions.WriteString("\000")
- fmt.Println("const (")
- for i, m := range decompSet {
- sa := []string{}
- for s := range m {
- sa = append(sa, s)
- }
- sort.Strings(sa)
- for _, s := range sa {
- p := decompositions.Len()
- decompositions.WriteString(s)
- positionMap[s] = uint16(p)
- }
- if cname[i] != "" {
- fmt.Printf("%s = 0x%X\n", cname[i], decompositions.Len())
- }
- }
- fmt.Println("maxDecomp = 0x8000")
- fmt.Println(")")
- b := decompositions.Bytes()
- printBytes(b, "decomps")
- size += len(b)
-
- varnames := []string{"nfc", "nfkc"}
- for i := 0; i < FNumberOfFormTypes; i++ {
- trie := newNode()
- for r, c := range chars {
- f := c.forms[i]
- d := f.expandedDecomp
- if len(d) != 0 {
- _, key := mkstr(c.codePoint, &f)
- trie.insert(rune(r), positionMap[key])
- if c.ccc != ccc(d[0]) {
- // We assume the lead ccc of a decomposition !=0 in this case.
- if ccc(d[0]) == 0 {
- logger.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc)
- }
- }
- } else if v := makeEntry(&f)<<8 | uint16(c.ccc); v != 0 {
- trie.insert(c.codePoint, 0x8000|v)
- }
- }
- size += trie.printTables(varnames[i])
- }
- return size
-}
-
-func contains(sa []string, s string) bool {
- for _, a := range sa {
- if a == s {
- return true
- }
- }
- return false
-}
-
-// Extract the version number from the URL.
-func version() string {
- // From http://www.unicode.org/standard/versions/#Version_Numbering:
- // for the later Unicode versions, data files are located in
- // versioned directories.
- fields := strings.Split(*url, "/")
- for _, f := range fields {
- if match, _ := regexp.MatchString(`[0-9]\.[0-9]\.[0-9]`, f); match {
- return f
- }
- }
- logger.Fatal("unknown version")
- return "Unknown"
-}
-
-const fileHeader = `// Generated by running
-// maketables --tables=%s --url=%s
-// DO NOT EDIT
-
-package norm
-
-`
-
-func makeTables() {
- size := 0
- if *tablelist == "" {
- return
- }
- list := strings.Split(*tablelist, ",")
- if *tablelist == "all" {
- list = []string{"recomp", "info"}
- }
- fmt.Printf(fileHeader, *tablelist, *url)
-
- fmt.Println("// Version is the Unicode edition from which the tables are derived.")
- fmt.Printf("const Version = %q\n\n", version())
-
- if contains(list, "info") {
- size += printCharInfoTables()
- }
-
- if contains(list, "recomp") {
- // Note that we use 32 bit keys, instead of 64 bit.
- // This clips the bits of three entries, but we know
- // this won't cause a collision. The compiler will catch
- // any changes made to UnicodeData.txt that introduces
- // a collision.
- // Note that the recomposition map for NFC and NFKC
- // are identical.
-
- // Recomposition map
- nrentries := 0
- for _, c := range chars {
- f := c.forms[FCanonical]
- if !f.isOneWay && len(f.decomp) > 0 {
- nrentries++
- }
- }
- sz := nrentries * 8
- size += sz
- fmt.Printf("// recompMap: %d bytes (entries only)\n", sz)
- fmt.Println("var recompMap = map[uint32]rune{")
- for i, c := range chars {
- f := c.forms[FCanonical]
- d := f.decomp
- if !f.isOneWay && len(d) > 0 {
- key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1]))
- fmt.Printf("0x%.8X: 0x%.4X,\n", key, i)
- }
- }
- fmt.Printf("}\n\n")
- }
-
- fmt.Printf("// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size)
-}
-
-func printChars() {
- if *verbose {
- for _, c := range chars {
- if !c.isValid() || c.state == SMissing {
- continue
- }
- fmt.Println(c)
- }
- }
-}
-
-// verifyComputed does various consistency tests.
-func verifyComputed() {
- for i, c := range chars {
- for _, f := range c.forms {
- isNo := (f.quickCheck[MDecomposed] == QCNo)
- if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) {
- log.Fatalf("%U: NF*D must be no if rune decomposes", i)
- }
-
- isMaybe := f.quickCheck[MComposed] == QCMaybe
- if f.combinesBackward != isMaybe {
- log.Fatalf("%U: NF*C must be maybe if combinesBackward", i)
- }
- }
- nfc := c.forms[FCanonical]
- nfkc := c.forms[FCompatibility]
- if nfc.combinesBackward != nfkc.combinesBackward {
- logger.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint)
- }
- }
-}
-
-var qcRe = regexp.MustCompile(`([0-9A-F\.]+) *; (NF.*_QC); ([YNM]) #.*`)
-
-// Use values in DerivedNormalizationProps.txt to compare against the
-// values we computed.
-// DerivedNormalizationProps.txt has form:
-// 00C0..00C5 ; NFD_QC; N # ...
-// 0374 ; NFD_QC; N # ...
-// See http://unicode.org/reports/tr44/ for full explanation
-func testDerived() {
- if !*test {
- return
- }
- f := openReader("DerivedNormalizationProps.txt")
- defer f.Close()
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- qc := qcRe.FindStringSubmatch(line)
- if qc == nil {
- continue
- }
- rng := strings.Split(qc[1], "..")
- i, err := strconv.ParseUint(rng[0], 16, 64)
- if err != nil {
- log.Fatal(err)
- }
- j := i
- if len(rng) > 1 {
- j, err = strconv.ParseUint(rng[1], 16, 64)
- if err != nil {
- log.Fatal(err)
- }
- }
- var ftype, mode int
- qt := strings.TrimSpace(qc[2])
- switch qt {
- case "NFC_QC":
- ftype, mode = FCanonical, MComposed
- case "NFD_QC":
- ftype, mode = FCanonical, MDecomposed
- case "NFKC_QC":
- ftype, mode = FCompatibility, MComposed
- case "NFKD_QC":
- ftype, mode = FCompatibility, MDecomposed
- default:
- log.Fatalf(`Unexpected quick check type "%s"`, qt)
- }
- var qr QCResult
- switch qc[3] {
- case "Y":
- qr = QCYes
- case "N":
- qr = QCNo
- case "M":
- qr = QCMaybe
- default:
- log.Fatalf(`Unexpected quick check value "%s"`, qc[3])
- }
- var lastFailed bool
- // Verify current
- for ; i <= j; i++ {
- c := &chars[int(i)]
- c.forms[ftype].verified[mode] = true
- curqr := c.forms[ftype].quickCheck[mode]
- if curqr != qr {
- if !lastFailed {
- logger.Printf("%s: %.4X..%.4X -- %s\n",
- qt, int(i), int(j), line[0:50])
- }
- logger.Printf("%U: FAILED %s (was %v need %v)\n",
- int(i), qt, curqr, qr)
- lastFailed = true
- }
- }
- }
- if scanner.Err() != nil {
- logger.Fatal(scanner.Err())
- }
- // Any unspecified value must be QCYes. Verify this.
- for i, c := range chars {
- for j, fd := range c.forms {
- for k, qr := range fd.quickCheck {
- if !fd.verified[k] && qr != QCYes {
- m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n"
- logger.Printf(m, i, j, k, qr, c.name)
- }
- }
- }
- }
-}
diff --git a/src/pkg/exp/norm/maketesttables.go b/src/pkg/exp/norm/maketesttables.go
deleted file mode 100644
index 6d11ec069..000000000
--- a/src/pkg/exp/norm/maketesttables.go
+++ /dev/null
@@ -1,45 +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 ignore
-
-// Generate test data for trie code.
-
-package main
-
-import (
- "fmt"
-)
-
-func main() {
- printTestTables()
-}
-
-// 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
-}
-
-const fileHeader = `// Generated by running
-// maketesttables
-// DO NOT EDIT
-
-package norm
-
-`
-
-func printTestTables() {
- fmt.Print(fileHeader)
- fmt.Printf("var testRunes = %#v\n\n", testRunes)
- t := newNode()
- for i, r := range testRunes {
- t.insert(r, uint16(i))
- }
- t.printTables("testdata")
-}
diff --git a/src/pkg/exp/norm/norm_test.go b/src/pkg/exp/norm/norm_test.go
deleted file mode 100644
index 12dacfcf3..000000000
--- a/src/pkg/exp/norm/norm_test.go
+++ /dev/null
@@ -1,14 +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 norm_test
-
-import (
- "testing"
-)
-
-func TestPlaceHolder(t *testing.T) {
- // Does nothing, just allows the Makefile to be canonical
- // while waiting for the package itself to be written.
-}
diff --git a/src/pkg/exp/norm/normalize.go b/src/pkg/exp/norm/normalize.go
deleted file mode 100644
index 1c3e49b77..000000000
--- a/src/pkg/exp/norm/normalize.go
+++ /dev/null
@@ -1,478 +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 norm contains types and functions for normalizing Unicode strings.
-package norm
-
-import "unicode/utf8"
-
-// A Form denotes a canonical representation of Unicode code points.
-// The Unicode-defined normalization and equivalence forms are:
-//
-// NFC Unicode Normalization Form C
-// NFD Unicode Normalization Form D
-// NFKC Unicode Normalization Form KC
-// NFKD Unicode Normalization Form KD
-//
-// For a Form f, this documentation uses the notation f(x) to mean
-// the bytes or string x converted to the given form.
-// A position n in x is called a boundary if conversion to the form can
-// proceed independently on both sides:
-// f(x) == append(f(x[0:n]), f(x[n:])...)
-//
-// References: http://unicode.org/reports/tr15/ and
-// http://unicode.org/notes/tn5/.
-type Form int
-
-const (
- NFC Form = iota
- NFD
- NFKC
- NFKD
-)
-
-// Bytes returns f(b). May return b if f(b) = b.
-func (f Form) Bytes(b []byte) []byte {
- rb := reorderBuffer{}
- rb.init(f, b)
- n := quickSpan(&rb, 0)
- if n == len(b) {
- return b
- }
- out := make([]byte, n, len(b))
- copy(out, b[0:n])
- return doAppend(&rb, out, n)
-}
-
-// String returns f(s).
-func (f Form) String(s string) string {
- rb := reorderBuffer{}
- rb.initString(f, s)
- n := quickSpan(&rb, 0)
- if n == len(s) {
- return s
- }
- out := make([]byte, n, len(s))
- copy(out, s[0:n])
- return string(doAppend(&rb, out, n))
-}
-
-// IsNormal returns true if b == f(b).
-func (f Form) IsNormal(b []byte) bool {
- rb := reorderBuffer{}
- rb.init(f, b)
- bp := quickSpan(&rb, 0)
- if bp == len(b) {
- return true
- }
- for bp < len(b) {
- decomposeSegment(&rb, bp)
- if rb.f.composing {
- rb.compose()
- }
- for i := 0; i < rb.nrune; i++ {
- info := rb.rune[i]
- if bp+int(info.size) > len(b) {
- return false
- }
- p := info.pos
- pe := p + info.size
- for ; p < pe; p++ {
- if b[bp] != rb.byte[p] {
- return false
- }
- bp++
- }
- }
- rb.reset()
- bp = quickSpan(&rb, bp)
- }
- return true
-}
-
-// IsNormalString returns true if s == f(s).
-func (f Form) IsNormalString(s string) bool {
- rb := reorderBuffer{}
- rb.initString(f, s)
- bp := quickSpan(&rb, 0)
- if bp == len(s) {
- return true
- }
- for bp < len(s) {
- decomposeSegment(&rb, bp)
- if rb.f.composing {
- rb.compose()
- }
- for i := 0; i < rb.nrune; i++ {
- info := rb.rune[i]
- if bp+int(info.size) > len(s) {
- return false
- }
- p := info.pos
- pe := p + info.size
- for ; p < pe; p++ {
- if s[bp] != rb.byte[p] {
- return false
- }
- bp++
- }
- }
- rb.reset()
- bp = quickSpan(&rb, bp)
- }
- return true
-}
-
-// patchTail fixes a case where a rune may be incorrectly normalized
-// if it is followed by illegal continuation bytes. It returns the
-// patched buffer and whether there were trailing continuation bytes.
-func patchTail(rb *reorderBuffer, buf []byte) ([]byte, bool) {
- info, p := lastRuneStart(&rb.f, buf)
- if p == -1 || info.size == 0 {
- return buf, false
- }
- end := p + int(info.size)
- extra := len(buf) - end
- if extra > 0 {
- // Potentially allocating memory. However, this only
- // happens with ill-formed UTF-8.
- x := make([]byte, 0)
- x = append(x, buf[len(buf)-extra:]...)
- buf = decomposeToLastBoundary(rb, buf[:end])
- if rb.f.composing {
- rb.compose()
- }
- buf = rb.flush(buf)
- return append(buf, x...), true
- }
- return buf, false
-}
-
-func appendQuick(rb *reorderBuffer, dst []byte, i int) ([]byte, int) {
- if rb.nsrc == i {
- return dst, i
- }
- end := quickSpan(rb, i)
- return rb.src.appendSlice(dst, i, end), end
-}
-
-// Append returns f(append(out, b...)).
-// The buffer out must be nil, empty, or equal to f(out).
-func (f Form) Append(out []byte, src ...byte) []byte {
- if len(src) == 0 {
- return out
- }
- rb := reorderBuffer{}
- rb.init(f, src)
- return doAppend(&rb, out, 0)
-}
-
-func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
- src, n := rb.src, rb.nsrc
- doMerge := len(out) > 0
- if q := src.skipNonStarter(p); q > p {
- // Move leading non-starters to destination.
- out = src.appendSlice(out, p, q)
- buf, endsInError := patchTail(rb, out)
- if endsInError {
- out = buf
- doMerge = false // no need to merge, ends with illegal UTF-8
- } else {
- out = decomposeToLastBoundary(rb, buf) // force decomposition
- }
- p = q
- }
- fd := &rb.f
- if doMerge {
- var info Properties
- if p < n {
- info = fd.info(src, p)
- if p == 0 && !info.BoundaryBefore() {
- out = decomposeToLastBoundary(rb, out)
- }
- }
- if info.size == 0 || info.BoundaryBefore() {
- if fd.composing {
- rb.compose()
- }
- out = rb.flush(out)
- if info.size == 0 {
- // Append incomplete UTF-8 encoding.
- return src.appendSlice(out, p, n)
- }
- }
- }
- if rb.nrune == 0 {
- out, p = appendQuick(rb, out, p)
- }
- for p < n {
- p = decomposeSegment(rb, p)
- if fd.composing {
- rb.compose()
- }
- out = rb.flush(out)
- out, p = appendQuick(rb, out, p)
- }
- return out
-}
-
-// AppendString returns f(append(out, []byte(s))).
-// The buffer out must be nil, empty, or equal to f(out).
-func (f Form) AppendString(out []byte, src string) []byte {
- if len(src) == 0 {
- return out
- }
- rb := reorderBuffer{}
- rb.initString(f, src)
- return doAppend(&rb, out, 0)
-}
-
-// QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
-// It is not guaranteed to return the largest such n.
-func (f Form) QuickSpan(b []byte) int {
- rb := reorderBuffer{}
- rb.init(f, b)
- n := quickSpan(&rb, 0)
- return n
-}
-
-func quickSpan(rb *reorderBuffer, i int) int {
- var lastCC uint8
- var nc int
- lastSegStart := i
- src, n := rb.src, rb.nsrc
- for i < n {
- if j := src.skipASCII(i, n); i != j {
- i = j
- lastSegStart = i - 1
- lastCC = 0
- nc = 0
- continue
- }
- info := rb.f.info(src, i)
- if info.size == 0 {
- // include incomplete runes
- return n
- }
- cc := info.ccc
- if rb.f.composing {
- if !info.isYesC() {
- break
- }
- } else {
- if !info.isYesD() {
- break
- }
- }
- if cc == 0 {
- lastSegStart = i
- nc = 0
- } else {
- if nc >= maxCombiningChars {
- lastSegStart = i
- lastCC = cc
- nc = 1
- } else {
- if lastCC > cc {
- return lastSegStart
- }
- nc++
- }
- }
- lastCC = cc
- i += int(info.size)
- }
- if i == n {
- return n
- }
- if rb.f.composing {
- return lastSegStart
- }
- return i
-}
-
-// QuickSpanString returns a boundary n such that b[0:n] == f(s[0:n]).
-// It is not guaranteed to return the largest such n.
-func (f Form) QuickSpanString(s string) int {
- rb := reorderBuffer{}
- rb.initString(f, s)
- return quickSpan(&rb, 0)
-}
-
-// FirstBoundary returns the position i of the first boundary in b
-// or -1 if b contains no boundary.
-func (f Form) FirstBoundary(b []byte) int {
- rb := reorderBuffer{}
- rb.init(f, b)
- return firstBoundary(&rb)
-}
-
-func firstBoundary(rb *reorderBuffer) int {
- src, nsrc := rb.src, rb.nsrc
- i := src.skipNonStarter(0)
- if i >= nsrc {
- return -1
- }
- fd := &rb.f
- info := fd.info(src, i)
- for n := 0; info.size != 0 && !info.BoundaryBefore(); {
- i += int(info.size)
- if n++; n >= maxCombiningChars {
- return i
- }
- if i >= nsrc {
- if !info.BoundaryAfter() {
- return -1
- }
- return nsrc
- }
- info = fd.info(src, i)
- }
- if info.size == 0 {
- return -1
- }
- return i
-}
-
-// FirstBoundaryInString returns the position i of the first boundary in s
-// or -1 if s contains no boundary.
-func (f Form) FirstBoundaryInString(s string) int {
- rb := reorderBuffer{}
- rb.initString(f, s)
- return firstBoundary(&rb)
-}
-
-// LastBoundary returns the position i of the last boundary in b
-// or -1 if b contains no boundary.
-func (f Form) LastBoundary(b []byte) int {
- return lastBoundary(formTable[f], b)
-}
-
-func lastBoundary(fd *formInfo, b []byte) int {
- i := len(b)
- info, p := lastRuneStart(fd, b)
- if p == -1 {
- return -1
- }
- if info.size == 0 { // ends with incomplete rune
- if p == 0 { // starts with incomplete rune
- return -1
- }
- i = p
- info, p = lastRuneStart(fd, b[:i])
- if p == -1 { // incomplete UTF-8 encoding or non-starter bytes without a starter
- return i
- }
- }
- if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
- return i
- }
- if info.BoundaryAfter() {
- return i
- }
- i = p
- for n := 0; i >= 0 && !info.BoundaryBefore(); {
- info, p = lastRuneStart(fd, b[:i])
- if n++; n >= maxCombiningChars {
- return len(b)
- }
- if p+int(info.size) != i {
- if p == -1 { // no boundary found
- return -1
- }
- return i // boundary after an illegal UTF-8 encoding
- }
- i = p
- }
- return i
-}
-
-// decomposeSegment scans the first segment in src into rb.
-// It returns the number of bytes consumed from src.
-// TODO(mpvl): consider inserting U+034f (Combining Grapheme Joiner)
-// when we detect a sequence of 30+ non-starter chars.
-func decomposeSegment(rb *reorderBuffer, sp int) int {
- // Force one character to be consumed.
- info := rb.f.info(rb.src, sp)
- if info.size == 0 {
- return 0
- }
- for rb.insert(rb.src, sp, info) {
- sp += int(info.size)
- if sp >= rb.nsrc {
- break
- }
- info = rb.f.info(rb.src, sp)
- bound := info.BoundaryBefore()
- if bound || info.size == 0 {
- break
- }
- }
- return sp
-}
-
-// 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) (Properties, int) {
- p := len(buf) - 1
- for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
- }
- if p < 0 {
- return Properties{}, -1
- }
- return fd.info(inputBytes(buf), p), p
-}
-
-// decomposeToLastBoundary finds an open segment at the end of the buffer
-// and scans it into rb. Returns the buffer minus the last segment.
-func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
- fd := &rb.f
- info, i := lastRuneStart(fd, buf)
- if int(info.size) != len(buf)-i {
- // illegal trailing continuation bytes
- return buf
- }
- if info.BoundaryAfter() {
- return buf
- }
- 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) {
- info, i = lastRuneStart(fd, buf[:p])
- if int(info.size) != p-i {
- break
- }
- // Check that decomposition doesn't result in overflow.
- if info.hasDecomposition() {
- if isHangul(buf) {
- i += int(info.size)
- n++
- } else {
- dcomp := info.Decomposition()
- for i := 0; i < len(dcomp); {
- inf := rb.f.info(inputBytes(dcomp), i)
- i += int(inf.size)
- n++
- }
- }
- } else {
- n++
- }
- if n > maxBackRunes {
- break
- }
- add[padd] = info
- padd++
- }
- pp := p
- for padd--; padd >= 0; padd-- {
- info = add[padd]
- rb.insert(inputBytes(buf), pp, info)
- pp += int(info.size)
- }
- return buf[:p]
-}
diff --git a/src/pkg/exp/norm/normalize_test.go b/src/pkg/exp/norm/normalize_test.go
deleted file mode 100644
index 9a6b46e41..000000000
--- a/src/pkg/exp/norm/normalize_test.go
+++ /dev/null
@@ -1,750 +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 norm
-
-import (
- "bytes"
- "io"
- "strings"
- "testing"
-)
-
-type PositionTest struct {
- input string
- pos int
- buffer string // expected contents of reorderBuffer, if applicable
-}
-
-type positionFunc func(rb *reorderBuffer, s string) int
-
-func runPosTests(t *testing.T, name string, f Form, fn positionFunc, tests []PositionTest) {
- rb := reorderBuffer{}
- rb.init(f, nil)
- for i, test := range tests {
- rb.reset()
- rb.src = inputString(test.input)
- rb.nsrc = len(test.input)
- pos := fn(&rb, test.input)
- if pos != test.pos {
- t.Errorf("%s:%d: position is %d; want %d", name, i, pos, test.pos)
- }
- runes := []rune(test.buffer)
- if rb.nrune != len(runes) {
- t.Errorf("%s:%d: reorder buffer length is %d; want %d", name, i, rb.nrune, len(runes))
- continue
- }
- for j, want := range runes {
- found := rune(rb.runeAt(j))
- if found != want {
- t.Errorf("%s:%d: rune at %d is %U; want %U", name, i, j, found, want)
- }
- }
- }
-}
-
-var decomposeSegmentTests = []PositionTest{
- // illegal runes
- {"\xC0", 0, ""},
- {"\u00E0\x80", 2, "\u0061\u0300"},
- // starter
- {"a", 1, "a"},
- {"ab", 1, "a"},
- // starter + composing
- {"a\u0300", 3, "a\u0300"},
- {"a\u0300b", 3, "a\u0300"},
- // with decomposition
- {"\u00C0", 2, "A\u0300"},
- {"\u00C0b", 2, "A\u0300"},
- // long
- {strings.Repeat("\u0300", 31), 62, strings.Repeat("\u0300", 31)},
- // ends with incomplete UTF-8 encoding
- {"\xCC", 0, ""},
- {"\u0300\xCC", 2, "\u0300"},
-}
-
-func decomposeSegmentF(rb *reorderBuffer, s string) int {
- rb.src = inputString(s)
- rb.nsrc = len(s)
- return decomposeSegment(rb, 0)
-}
-
-func TestDecomposeSegment(t *testing.T) {
- runPosTests(t, "TestDecomposeSegment", NFC, decomposeSegmentF, decomposeSegmentTests)
-}
-
-var firstBoundaryTests = []PositionTest{
- // no boundary
- {"", -1, ""},
- {"\u0300", -1, ""},
- {"\x80\x80", -1, ""},
- // illegal runes
- {"\xff", 0, ""},
- {"\u0300\xff", 2, ""},
- {"\u0300\xc0\x80\x80", 2, ""},
- // boundaries
- {"a", 0, ""},
- {"\u0300a", 2, ""},
- // Hangul
- {"\u1103\u1161", 0, ""},
- {"\u110B\u1173\u11B7", 0, ""},
- {"\u1161\u110B\u1173\u11B7", 3, ""},
- {"\u1173\u11B7\u1103\u1161", 6, ""},
- // too many combining characters.
- {strings.Repeat("\u0300", maxCombiningChars-1), -1, ""},
- {strings.Repeat("\u0300", maxCombiningChars), 60, ""},
- {strings.Repeat("\u0300", maxCombiningChars+1), 60, ""},
-}
-
-func firstBoundaryF(rb *reorderBuffer, s string) int {
- return rb.f.form.FirstBoundary([]byte(s))
-}
-
-func firstBoundaryStringF(rb *reorderBuffer, s string) int {
- return rb.f.form.FirstBoundaryInString(s)
-}
-
-func TestFirstBoundary(t *testing.T) {
- runPosTests(t, "TestFirstBoundary", NFC, firstBoundaryF, firstBoundaryTests)
- runPosTests(t, "TestFirstBoundaryInString", NFC, firstBoundaryStringF, firstBoundaryTests)
-}
-
-var decomposeToLastTests = []PositionTest{
- // ends with inert character
- {"Hello!", 6, ""},
- {"\u0632", 2, ""},
- {"a\u0301\u0635", 5, ""},
- // ends with non-inert starter
- {"a", 0, "a"},
- {"a\u0301a", 3, "a"},
- {"a\u0301\u03B9", 3, "\u03B9"},
- {"a\u0327", 0, "a\u0327"},
- // illegal runes
- {"\xFF", 1, ""},
- {"aa\xFF", 3, ""},
- {"\xC0\x80\x80", 3, ""},
- {"\xCC\x80\x80", 3, ""},
- // ends with incomplete UTF-8 encoding
- {"a\xCC", 2, ""},
- // ends with combining characters
- {"\u0300\u0301", 0, "\u0300\u0301"},
- {"a\u0300\u0301", 0, "a\u0300\u0301"},
- {"a\u0301\u0308", 0, "a\u0301\u0308"},
- {"a\u0308\u0301", 0, "a\u0308\u0301"},
- {"aaaa\u0300\u0301", 3, "a\u0300\u0301"},
- {"\u0300a\u0300\u0301", 2, "a\u0300\u0301"},
- {"\u00C0", 0, "A\u0300"},
- {"a\u00C0", 1, "A\u0300"},
- // decomposing
- {"a\u0300\uFDC0", 3, "\u0645\u062C\u064A"},
- {"\uFDC0" + strings.Repeat("\u0300", 26), 0, "\u0645\u062C\u064A" + strings.Repeat("\u0300", 26)},
- // Hangul
- {"a\u1103", 1, "\u1103"},
- {"a\u110B", 1, "\u110B"},
- {"a\u110B\u1173", 1, "\u110B\u1173"},
- // See comment in composition.go:compBoundaryAfter.
- {"a\u110B\u1173\u11B7", 1, "\u110B\u1173\u11B7"},
- {"a\uC73C", 1, "\u110B\u1173"},
- {"다음", 3, "\u110B\u1173\u11B7"},
- {"다", 0, "\u1103\u1161"},
- {"\u1103\u1161\u110B\u1173\u11B7", 6, "\u110B\u1173\u11B7"},
- {"\u110B\u1173\u11B7\u1103\u1161", 9, "\u1103\u1161"},
- {"다음음", 6, "\u110B\u1173\u11B7"},
- {"음다다", 6, "\u1103\u1161"},
- // buffer overflow
- {"a" + strings.Repeat("\u0300", 30), 3, strings.Repeat("\u0300", 29)},
- {"\uFDFA" + strings.Repeat("\u0300", 14), 3, strings.Repeat("\u0300", 14)},
- // weird UTF-8
- {"a\u0300\u11B7", 0, "a\u0300\u11B7"},
-}
-
-func decomposeToLast(rb *reorderBuffer, s string) int {
- buf := decomposeToLastBoundary(rb, []byte(s))
- return len(buf)
-}
-
-func TestDecomposeToLastBoundary(t *testing.T) {
- runPosTests(t, "TestDecomposeToLastBoundary", NFKC, decomposeToLast, decomposeToLastTests)
-}
-
-var lastBoundaryTests = []PositionTest{
- // ends with inert character
- {"Hello!", 6, ""},
- {"\u0632", 2, ""},
- // ends with non-inert starter
- {"a", 0, ""},
- // illegal runes
- {"\xff", 1, ""},
- {"aa\xff", 3, ""},
- {"a\xff\u0300", 1, ""},
- {"\xc0\x80\x80", 3, ""},
- {"\xc0\x80\x80\u0300", 3, ""},
- // ends with incomplete UTF-8 encoding
- {"\xCC", -1, ""},
- {"\xE0\x80", -1, ""},
- {"\xF0\x80\x80", -1, ""},
- {"a\xCC", 0, ""},
- {"\x80\xCC", 1, ""},
- {"\xCC\xCC", 1, ""},
- // ends with combining characters
- {"a\u0300\u0301", 0, ""},
- {"aaaa\u0300\u0301", 3, ""},
- {"\u0300a\u0300\u0301", 2, ""},
- {"\u00C0", 0, ""},
- {"a\u00C0", 1, ""},
- // decomposition may recombine
- {"\u0226", 0, ""},
- // no boundary
- {"", -1, ""},
- {"\u0300\u0301", -1, ""},
- {"\u0300", -1, ""},
- {"\x80\x80", -1, ""},
- {"\x80\x80\u0301", -1, ""},
- // Hangul
- {"다음", 3, ""},
- {"다", 0, ""},
- {"\u1103\u1161\u110B\u1173\u11B7", 6, ""},
- {"\u110B\u1173\u11B7\u1103\u1161", 9, ""},
- // too many combining characters.
- {strings.Repeat("\u0300", maxCombiningChars-1), -1, ""},
- {strings.Repeat("\u0300", maxCombiningChars), 60, ""},
- {strings.Repeat("\u0300", maxCombiningChars+1), 62, ""},
-}
-
-func lastBoundaryF(rb *reorderBuffer, s string) int {
- return rb.f.form.LastBoundary([]byte(s))
-}
-
-func TestLastBoundary(t *testing.T) {
- runPosTests(t, "TestLastBoundary", NFC, lastBoundaryF, lastBoundaryTests)
-}
-
-var quickSpanTests = []PositionTest{
- {"", 0, ""},
- // starters
- {"a", 1, ""},
- {"abc", 3, ""},
- {"\u043Eb", 3, ""},
- // incomplete last rune.
- {"\xCC", 1, ""},
- {"a\xCC", 2, ""},
- // incorrectly ordered combining characters
- {"\u0300\u0316", 0, ""},
- {"\u0300\u0316cd", 0, ""},
- // have a maximum number of combining characters.
- {strings.Repeat("\u035D", 30) + "\u035B", 62, ""},
- {"a" + strings.Repeat("\u035D", 30) + "\u035B", 63, ""},
- {"Ɵ" + strings.Repeat("\u035D", 30) + "\u035B", 64, ""},
- {"aa" + strings.Repeat("\u035D", 30) + "\u035B", 64, ""},
-}
-
-var quickSpanNFDTests = []PositionTest{
- // needs decomposing
- {"\u00C0", 0, ""},
- {"abc\u00C0", 3, ""},
- // correctly ordered combining characters
- {"\u0300", 2, ""},
- {"ab\u0300", 4, ""},
- {"ab\u0300cd", 6, ""},
- {"\u0300cd", 4, ""},
- {"\u0316\u0300", 4, ""},
- {"ab\u0316\u0300", 6, ""},
- {"ab\u0316\u0300cd", 8, ""},
- {"ab\u0316\u0300\u00C0", 6, ""},
- {"\u0316\u0300cd", 6, ""},
- {"\u043E\u0308b", 5, ""},
- // incorrectly ordered combining characters
- {"ab\u0300\u0316", 1, ""}, // TODO: we could skip 'b' as well.
- {"ab\u0300\u0316cd", 1, ""},
- // Hangul
- {"같은", 0, ""},
-}
-
-var quickSpanNFCTests = []PositionTest{
- // okay composed
- {"\u00C0", 2, ""},
- {"abc\u00C0", 5, ""},
- // correctly ordered combining characters
- {"ab\u0300", 1, ""},
- {"ab\u0300cd", 1, ""},
- {"ab\u0316\u0300", 1, ""},
- {"ab\u0316\u0300cd", 1, ""},
- {"\u00C0\u035D", 4, ""},
- // we do not special case leading combining characters
- {"\u0300cd", 0, ""},
- {"\u0300", 0, ""},
- {"\u0316\u0300", 0, ""},
- {"\u0316\u0300cd", 0, ""},
- // incorrectly ordered combining characters
- {"ab\u0300\u0316", 1, ""},
- {"ab\u0300\u0316cd", 1, ""},
- // Hangul
- {"같은", 6, ""},
-}
-
-func doQuickSpan(rb *reorderBuffer, s string) int {
- return rb.f.form.QuickSpan([]byte(s))
-}
-
-func doQuickSpanString(rb *reorderBuffer, s string) int {
- return rb.f.form.QuickSpanString(s)
-}
-
-func TestQuickSpan(t *testing.T) {
- runPosTests(t, "TestQuickSpanNFD1", NFD, doQuickSpan, quickSpanTests)
- runPosTests(t, "TestQuickSpanNFD2", NFD, doQuickSpan, quickSpanNFDTests)
- runPosTests(t, "TestQuickSpanNFC1", NFC, doQuickSpan, quickSpanTests)
- runPosTests(t, "TestQuickSpanNFC2", NFC, doQuickSpan, quickSpanNFCTests)
-
- runPosTests(t, "TestQuickSpanStringNFD1", NFD, doQuickSpanString, quickSpanTests)
- runPosTests(t, "TestQuickSpanStringNFD2", NFD, doQuickSpanString, quickSpanNFDTests)
- runPosTests(t, "TestQuickSpanStringNFC1", NFC, doQuickSpanString, quickSpanTests)
- runPosTests(t, "TestQuickSpanStringNFC2", NFC, doQuickSpanString, quickSpanNFCTests)
-}
-
-var isNormalTests = []PositionTest{
- {"", 1, ""},
- // illegal runes
- {"\xff", 1, ""},
- // starters
- {"a", 1, ""},
- {"abc", 1, ""},
- {"\u043Eb", 1, ""},
- // incorrectly ordered combining characters
- {"\u0300\u0316", 0, ""},
- {"ab\u0300\u0316", 0, ""},
- {"ab\u0300\u0316cd", 0, ""},
- {"\u0300\u0316cd", 0, ""},
-}
-var isNormalNFDTests = []PositionTest{
- // needs decomposing
- {"\u00C0", 0, ""},
- {"abc\u00C0", 0, ""},
- // correctly ordered combining characters
- {"\u0300", 1, ""},
- {"ab\u0300", 1, ""},
- {"ab\u0300cd", 1, ""},
- {"\u0300cd", 1, ""},
- {"\u0316\u0300", 1, ""},
- {"ab\u0316\u0300", 1, ""},
- {"ab\u0316\u0300cd", 1, ""},
- {"\u0316\u0300cd", 1, ""},
- {"\u043E\u0308b", 1, ""},
- // Hangul
- {"같은", 0, ""},
-}
-var isNormalNFCTests = []PositionTest{
- // okay composed
- {"\u00C0", 1, ""},
- {"abc\u00C0", 1, ""},
- // need reordering
- {"a\u0300", 0, ""},
- {"a\u0300cd", 0, ""},
- {"a\u0316\u0300", 0, ""},
- {"a\u0316\u0300cd", 0, ""},
- // correctly ordered combining characters
- {"ab\u0300", 1, ""},
- {"ab\u0300cd", 1, ""},
- {"ab\u0316\u0300", 1, ""},
- {"ab\u0316\u0300cd", 1, ""},
- {"\u00C0\u035D", 1, ""},
- {"\u0300", 1, ""},
- {"\u0316\u0300cd", 1, ""},
- // Hangul
- {"같은", 1, ""},
-}
-
-func isNormalF(rb *reorderBuffer, s string) int {
- if rb.f.form.IsNormal([]byte(s)) {
- return 1
- }
- return 0
-}
-
-func TestIsNormal(t *testing.T) {
- runPosTests(t, "TestIsNormalNFD1", NFD, isNormalF, isNormalTests)
- runPosTests(t, "TestIsNormalNFD2", NFD, isNormalF, isNormalNFDTests)
- runPosTests(t, "TestIsNormalNFC1", NFC, isNormalF, isNormalTests)
- runPosTests(t, "TestIsNormalNFC2", NFC, isNormalF, isNormalNFCTests)
-}
-
-type AppendTest struct {
- left string
- right string
- out string
-}
-
-type appendFunc func(f Form, out []byte, s string) []byte
-
-func runAppendTests(t *testing.T, name string, f Form, fn appendFunc, tests []AppendTest) {
- for i, test := range tests {
- out := []byte(test.left)
- out = fn(f, out, test.right)
- outs := string(out)
- if len(outs) != len(test.out) {
- t.Errorf("%s:%d: length is %d; want %d", name, i, len(outs), len(test.out))
- }
- if outs != test.out {
- // Find first rune that differs and show context.
- ir := []rune(outs)
- ig := []rune(test.out)
- for j := 0; j < len(ir) && j < len(ig); j++ {
- if ir[j] == ig[j] {
- continue
- }
- if j -= 3; j < 0 {
- j = 0
- }
- for e := j + 7; j < e && j < len(ir) && j < len(ig); j++ {
- t.Errorf("%s:%d: runeAt(%d) = %U; want %U", name, i, j, ir[j], ig[j])
- }
- break
- }
- }
- }
-}
-
-var appendTests = []AppendTest{
- // empty buffers
- {"", "", ""},
- {"a", "", "a"},
- {"", "a", "a"},
- {"", "\u0041\u0307\u0304", "\u01E0"},
- // segment split across buffers
- {"", "a\u0300b", "\u00E0b"},
- {"a", "\u0300b", "\u00E0b"},
- {"a", "\u0300\u0316", "\u00E0\u0316"},
- {"a", "\u0316\u0300", "\u00E0\u0316"},
- {"a", "\u0300a\u0300", "\u00E0\u00E0"},
- {"a", "\u0300a\u0300a\u0300", "\u00E0\u00E0\u00E0"},
- {"a", "\u0300aaa\u0300aaa\u0300", "\u00E0aa\u00E0aa\u00E0"},
- {"a\u0300", "\u0327", "\u00E0\u0327"},
- {"a\u0327", "\u0300", "\u00E0\u0327"},
- {"a\u0316", "\u0300", "\u00E0\u0316"},
- {"\u0041\u0307", "\u0304", "\u01E0"},
- // Hangul
- {"", "\u110B\u1173", "\uC73C"},
- {"", "\u1103\u1161", "\uB2E4"},
- {"", "\u110B\u1173\u11B7", "\uC74C"},
- {"", "\u320E", "\x28\uAC00\x29"},
- {"", "\x28\u1100\u1161\x29", "\x28\uAC00\x29"},
- {"\u1103", "\u1161", "\uB2E4"},
- {"\u110B", "\u1173\u11B7", "\uC74C"},
- {"\u110B\u1173", "\u11B7", "\uC74C"},
- {"\uC73C", "\u11B7", "\uC74C"},
- // UTF-8 encoding split across buffers
- {"a\xCC", "\x80", "\u00E0"},
- {"a\xCC", "\x80b", "\u00E0b"},
- {"a\xCC", "\x80a\u0300", "\u00E0\u00E0"},
- {"a\xCC", "\x80\x80", "\u00E0\x80"},
- {"a\xCC", "\x80\xCC", "\u00E0\xCC"},
- {"a\u0316\xCC", "\x80a\u0316\u0300", "\u00E0\u0316\u00E0\u0316"},
- // ending in incomplete UTF-8 encoding
- {"", "\xCC", "\xCC"},
- {"a", "\xCC", "a\xCC"},
- {"a", "b\xCC", "ab\xCC"},
- {"\u0226", "\xCC", "\u0226\xCC"},
- // illegal runes
- {"", "\x80", "\x80"},
- {"", "\x80\x80\x80", "\x80\x80\x80"},
- {"", "\xCC\x80\x80\x80", "\xCC\x80\x80\x80"},
- {"", "a\x80", "a\x80"},
- {"", "a\x80\x80\x80", "a\x80\x80\x80"},
- {"", "a\x80\x80\x80\x80\x80\x80", "a\x80\x80\x80\x80\x80\x80"},
- {"a", "\x80\x80\x80", "a\x80\x80\x80"},
- // overflow
- {"", strings.Repeat("\x80", 33), strings.Repeat("\x80", 33)},
- {strings.Repeat("\x80", 33), "", strings.Repeat("\x80", 33)},
- {strings.Repeat("\x80", 33), strings.Repeat("\x80", 33), strings.Repeat("\x80", 66)},
- // overflow of combining characters
- {strings.Repeat("\u0300", 33), "", strings.Repeat("\u0300", 33)},
- // weird UTF-8
- {"\u00E0\xE1", "\x86", "\u00E0\xE1\x86"},
- {"a\u0300\u11B7", "\u0300", "\u00E0\u11B7\u0300"},
- {"a\u0300\u11B7\u0300", "\u0300", "\u00E0\u11B7\u0300\u0300"},
- {"\u0300", "\xF8\x80\x80\x80\x80\u0300", "\u0300\xF8\x80\x80\x80\x80\u0300"},
- {"\u0300", "\xFC\x80\x80\x80\x80\x80\u0300", "\u0300\xFC\x80\x80\x80\x80\x80\u0300"},
- {"\xF8\x80\x80\x80\x80\u0300", "\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
- {"\xFC\x80\x80\x80\x80\x80\u0300", "\u0300", "\xFC\x80\x80\x80\x80\x80\u0300\u0300"},
- {"\xF8\x80\x80\x80", "\x80\u0300\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
-}
-
-func appendF(f Form, out []byte, s string) []byte {
- return f.Append(out, []byte(s)...)
-}
-
-func appendStringF(f Form, out []byte, s string) []byte {
- return f.AppendString(out, s)
-}
-
-func bytesF(f Form, out []byte, s string) []byte {
- buf := []byte{}
- buf = append(buf, out...)
- buf = append(buf, s...)
- return f.Bytes(buf)
-}
-
-func stringF(f Form, out []byte, s string) []byte {
- outs := string(out) + s
- return []byte(f.String(outs))
-}
-
-func TestAppend(t *testing.T) {
- runAppendTests(t, "TestAppend", NFKC, appendF, appendTests)
- runAppendTests(t, "TestAppendString", NFKC, appendStringF, appendTests)
- runAppendTests(t, "TestBytes", NFKC, bytesF, appendTests)
- runAppendTests(t, "TestString", NFKC, stringF, appendTests)
-}
-
-func appendBench(f Form, in []byte) func() {
- buf := make([]byte, 0, 4*len(in))
- return func() {
- f.Append(buf, in...)
- }
-}
-
-func iterBench(f Form, in []byte) func() {
- iter := Iter{}
- return func() {
- iter.Init(f, in)
- for !iter.Done() {
- iter.Next()
- }
- }
-}
-
-func readerBench(f Form, in []byte) func() {
- buf := make([]byte, 4*len(in))
- return func() {
- r := f.Reader(bytes.NewReader(in))
- var err error
- for err == nil {
- _, err = r.Read(buf)
- }
- if err != io.EOF {
- panic("")
- }
- }
-}
-
-func writerBench(f Form, in []byte) func() {
- buf := make([]byte, 0, 4*len(in))
- return func() {
- r := f.Writer(bytes.NewBuffer(buf))
- if _, err := r.Write(in); err != nil {
- panic("")
- }
- }
-}
-
-func appendBenchmarks(bm []func(), f Form, in []byte) []func() {
- //bm = append(bm, appendBench(f, in))
- bm = append(bm, iterBench(f, in))
- //bm = append(bm, readerBench(f, in))
- //bm = append(bm, writerBench(f, in))
- return bm
-}
-
-func doFormBenchmark(b *testing.B, inf, f Form, s string) {
- b.StopTimer()
- in := inf.Bytes([]byte(s))
- bm := appendBenchmarks(nil, f, in)
- b.SetBytes(int64(len(in) * len(bm)))
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- for _, fn := range bm {
- fn()
- }
- }
-}
-
-var ascii = strings.Repeat("There is nothing to change here! ", 500)
-
-func BenchmarkNormalizeAsciiNFC(b *testing.B) {
- doFormBenchmark(b, NFC, NFC, ascii)
-}
-func BenchmarkNormalizeAsciiNFD(b *testing.B) {
- doFormBenchmark(b, NFC, NFD, ascii)
-}
-func BenchmarkNormalizeAsciiNFKC(b *testing.B) {
- doFormBenchmark(b, NFC, NFKC, ascii)
-}
-func BenchmarkNormalizeAsciiNFKD(b *testing.B) {
- doFormBenchmark(b, NFC, NFKD, ascii)
-}
-
-func BenchmarkNormalizeNFC2NFC(b *testing.B) {
- doFormBenchmark(b, NFC, NFC, txt_all)
-}
-func BenchmarkNormalizeNFC2NFD(b *testing.B) {
- doFormBenchmark(b, NFC, NFD, txt_all)
-}
-func BenchmarkNormalizeNFD2NFC(b *testing.B) {
- doFormBenchmark(b, NFD, NFC, txt_all)
-}
-func BenchmarkNormalizeNFD2NFD(b *testing.B) {
- doFormBenchmark(b, NFD, NFD, txt_all)
-}
-
-// Hangul is often special-cased, so we test it separately.
-func BenchmarkNormalizeHangulNFC2NFC(b *testing.B) {
- doFormBenchmark(b, NFC, NFC, txt_kr)
-}
-func BenchmarkNormalizeHangulNFC2NFD(b *testing.B) {
- doFormBenchmark(b, NFC, NFD, txt_kr)
-}
-func BenchmarkNormalizeHangulNFD2NFC(b *testing.B) {
- doFormBenchmark(b, NFD, NFC, txt_kr)
-}
-func BenchmarkNormalizeHangulNFD2NFD(b *testing.B) {
- doFormBenchmark(b, NFD, NFD, txt_kr)
-}
-
-var forms = []Form{NFC, NFD, NFKC, NFKD}
-
-func doTextBenchmark(b *testing.B, s string) {
- b.StopTimer()
- in := []byte(s)
- bm := []func(){}
- for _, f := range forms {
- bm = appendBenchmarks(bm, f, in)
- }
- b.SetBytes(int64(len(s) * len(bm)))
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- for _, f := range bm {
- f()
- }
- }
-}
-
-func BenchmarkCanonicalOrdering(b *testing.B) {
- doTextBenchmark(b, txt_canon)
-}
-func BenchmarkExtendedLatin(b *testing.B) {
- doTextBenchmark(b, txt_vn)
-}
-func BenchmarkMiscTwoByteUtf8(b *testing.B) {
- doTextBenchmark(b, twoByteUtf8)
-}
-func BenchmarkMiscThreeByteUtf8(b *testing.B) {
- doTextBenchmark(b, threeByteUtf8)
-}
-func BenchmarkHangul(b *testing.B) {
- doTextBenchmark(b, txt_kr)
-}
-func BenchmarkJapanese(b *testing.B) {
- doTextBenchmark(b, txt_jp)
-}
-func BenchmarkChinese(b *testing.B) {
- doTextBenchmark(b, txt_cn)
-}
-func BenchmarkOverflow(b *testing.B) {
- doTextBenchmark(b, overflow)
-}
-
-var overflow = string(bytes.Repeat([]byte("\u035D"), 4096)) + "\u035B"
-
-// Tests sampled from the Canonical ordering tests (Part 2) of
-// http://unicode.org/Public/UNIDATA/NormalizationTest.txt
-const txt_canon = `\u0061\u0315\u0300\u05AE\u0300\u0062 \u0061\u0300\u0315\u0300\u05AE\u0062
-\u0061\u0302\u0315\u0300\u05AE\u0062 \u0061\u0307\u0315\u0300\u05AE\u0062
-\u0061\u0315\u0300\u05AE\u030A\u0062 \u0061\u059A\u0316\u302A\u031C\u0062
-\u0061\u032E\u059A\u0316\u302A\u0062 \u0061\u0338\u093C\u0334\u0062
-\u0061\u059A\u0316\u302A\u0339 \u0061\u0341\u0315\u0300\u05AE\u0062
-\u0061\u0348\u059A\u0316\u302A\u0062 \u0061\u0361\u0345\u035D\u035C\u0062
-\u0061\u0366\u0315\u0300\u05AE\u0062 \u0061\u0315\u0300\u05AE\u0486\u0062
-\u0061\u05A4\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0613\u0062
-\u0061\u0315\u0300\u05AE\u0615\u0062 \u0061\u0617\u0315\u0300\u05AE\u0062
-\u0061\u0619\u0618\u064D\u064E\u0062 \u0061\u0315\u0300\u05AE\u0654\u0062
-\u0061\u0315\u0300\u05AE\u06DC\u0062 \u0061\u0733\u0315\u0300\u05AE\u0062
-\u0061\u0744\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0745\u0062
-\u0061\u09CD\u05B0\u094D\u3099\u0062 \u0061\u0E38\u0E48\u0E38\u0C56\u0062
-\u0061\u0EB8\u0E48\u0E38\u0E49\u0062 \u0061\u0F72\u0F71\u0EC8\u0F71\u0062
-\u0061\u1039\u05B0\u094D\u3099\u0062 \u0061\u05B0\u094D\u3099\u1A60\u0062
-\u0061\u3099\u093C\u0334\u1BE6\u0062 \u0061\u3099\u093C\u0334\u1C37\u0062
-\u0061\u1CD9\u059A\u0316\u302A\u0062 \u0061\u2DED\u0315\u0300\u05AE\u0062
-\u0061\u2DEF\u0315\u0300\u05AE\u0062 \u0061\u302D\u302E\u059A\u0316\u0062`
-
-// Taken from http://creativecommons.org/licenses/by-sa/3.0/vn/
-const txt_vn = `Với các điều kiện sau: Ghi nhận công của tác giả.
-Nếu bạn sử dụng, chuyển đổi, hoặc xây dựng dự án từ
-nội dung được chia sẻ này, bạn phải áp dụng giấy phép này hoặc
-một giấy phép khác có các điều khoản tương tự như giấy phép này
-cho dự án của bạn. Hiểu rằng: Miễn — Bất kỳ các điều kiện nào
-trên đây cũng có thể được miễn bỏ nếu bạn được sự cho phép của
-người sở hữu bản quyền. Phạm vi công chúng — Khi tác phẩm hoặc
-bất kỳ chương nào của tác phẩm đã trong vùng dành cho công
-chúng theo quy định của pháp luật thì tình trạng của nó không
-bị ảnh hưởng bởi giấy phép trong bất kỳ trường hợp nào.`
-
-// Taken from http://creativecommons.org/licenses/by-sa/1.0/deed.ru
-const txt_ru = `При обязательном соблюдении следующих условий:
-Attribution — Вы должны атрибутировать произведение (указывать
-автора и источник) в порядке, предусмотренном автором или
-лицензиаром (но только так, чтобы никоим образом не подразумевалось,
-что они поддерживают вас или использование вами данного произведения).
-Υπό τις ακόλουθες προϋποθέσεις:`
-
-// Taken from http://creativecommons.org/licenses/by-sa/3.0/gr/
-const txt_gr = `Αναφορά Δημιουργού — Θα πρέπει να κάνετε την αναφορά στο έργο με τον
-τρόπο που έχει οριστεί από το δημιουργό ή το χορηγούντο την άδεια
-(χωρίς όμως να εννοείται με οποιονδήποτε τρόπο ότι εγκρίνουν εσάς ή
-τη χρήση του έργου από εσάς). Παρόμοια Διανομή — Εάν αλλοιώσετε,
-τροποποιήσετε ή δημιουργήσετε περαιτέρω βασισμένοι στο έργο θα
-μπορείτε να διανέμετε το έργο που θα προκύψει μόνο με την ίδια ή
-παρόμοια άδεια.`
-
-// Taken from http://creativecommons.org/licenses/by-sa/3.0/deed.ar
-const txt_ar = `بموجب الشروط التالية نسب المصنف — يجب عليك أن
-تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من
-الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).
-المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة
-من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد
-لهذا الترخيص.`
-
-// Taken from http://creativecommons.org/licenses/by-sa/1.0/il/
-const txt_il = `בכפוף לתנאים הבאים: ייחוס — עליך לייחס את היצירה (לתת קרדיט) באופן
-המצויין על-ידי היוצר או מעניק הרישיון (אך לא בשום אופן המרמז על כך
-שהם תומכים בך או בשימוש שלך ביצירה). שיתוף זהה — אם תחליט/י לשנות,
-לעבד או ליצור יצירה נגזרת בהסתמך על יצירה זו, תוכל/י להפיץ את יצירתך
-החדשה רק תחת אותו הרישיון או רישיון דומה לרישיון זה.`
-
-const twoByteUtf8 = txt_ru + txt_gr + txt_ar + txt_il
-
-// Taken from http://creativecommons.org/licenses/by-sa/2.0/kr/
-const txt_kr = `다음과 같은 조건을 따라야 합니다: 저작자표시
-(Attribution) — 저작자나 이용허락자가 정한 방법으로 저작물의
-원저작자를 표시하여야 합니다(그러나 원저작자가 이용자나 이용자의
-이용을 보증하거나 추천한다는 의미로 표시해서는 안됩니다).
-동일조건변경허락 — 이 저작물을 이용하여 만든 이차적 저작물에는 본
-라이선스와 동일한 라이선스를 적용해야 합니다.`
-
-// Taken from http://creativecommons.org/licenses/by-sa/3.0/th/
-const txt_th = `ภายใต้เงื่อนไข ดังต่อไปนี้ : แสดงที่มา — คุณต้องแสดงที่
-มาของงานดังกล่าว ตามรูปแบบที่ผู้สร้างสรรค์หรือผู้อนุญาตกำหนด (แต่
-ไม่ใช่ในลักษณะที่ว่า พวกเขาสนับสนุนคุณหรือสนับสนุนการที่
-คุณนำงานไปใช้) อนุญาตแบบเดียวกัน — หากคุณดัดแปลง เปลี่ยนรูป หรื
-อต่อเติมงานนี้ คุณต้องใช้สัญญาอนุญาตแบบเดียวกันหรือแบบที่เหมื
-อนกับสัญญาอนุญาตที่ใช้กับงานนี้เท่านั้น`
-
-const threeByteUtf8 = txt_th
-
-// Taken from http://creativecommons.org/licenses/by-sa/2.0/jp/
-const txt_jp = `あなたの従うべき条件は以下の通りです。
-表示 — あなたは原著作者のクレジットを表示しなければなりません。
-継承 — もしあなたがこの作品を改変、変形または加工した場合、
-あなたはその結果生じた作品をこの作品と同一の許諾条件の下でのみ
-頒布することができます。`
-
-// http://creativecommons.org/licenses/by-sa/2.5/cn/
-const txt_cn = `您可以自由: 复制、发行、展览、表演、放映、
-广播或通过信息网络传播本作品 创作演绎作品
-对本作品进行商业性使用 惟须遵守下列条件:
-署名 — 您必须按照作者或者许可人指定的方式对作品进行署名。
-相同方式共享 — 如果您改变、转换本作品或者以本作品为基础进行创作,
-您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。`
-
-const txt_cjk = txt_cn + txt_jp + txt_kr
-const txt_all = txt_vn + twoByteUtf8 + threeByteUtf8 + txt_cjk
diff --git a/src/pkg/exp/norm/normregtest.go b/src/pkg/exp/norm/normregtest.go
deleted file mode 100644
index b77b5b545..000000000
--- a/src/pkg/exp/norm/normregtest.go
+++ /dev/null
@@ -1,304 +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 ignore
-
-package main
-
-import (
- "bufio"
- "bytes"
- "exp/norm"
- "flag"
- "fmt"
- "log"
- "net/http"
- "os"
- "path"
- "regexp"
- "runtime"
- "strconv"
- "strings"
- "time"
- "unicode"
- "unicode/utf8"
-)
-
-func main() {
- flag.Parse()
- loadTestData()
- CharacterByCharacterTests()
- StandardTests()
- PerformanceTest()
- if errorCount == 0 {
- fmt.Println("PASS")
- }
-}
-
-const file = "NormalizationTest.txt"
-
-var url = flag.String("url",
- "http://www.unicode.org/Public/"+unicode.Version+"/ucd/"+file,
- "URL of Unicode database directory")
-var localFiles = flag.Bool("local",
- false,
- "data files have been copied to the current directory; for debugging only")
-
-var logger = log.New(os.Stderr, "", log.Lshortfile)
-
-// This regression test runs the test set in NormalizationTest.txt
-// (taken from http://www.unicode.org/Public/<unicode.Version>/ucd/).
-//
-// NormalizationTest.txt has form:
-// @Part0 # Specific cases
-// #
-// 1E0A;1E0A;0044 0307;1E0A;0044 0307; # (Ḋ; Ḋ; D◌̇; Ḋ; D◌̇; ) LATIN CAPITAL LETTER D WITH DOT ABOVE
-// 1E0C;1E0C;0044 0323;1E0C;0044 0323; # (Ḍ; Ḍ; D◌̣; Ḍ; D◌̣; ) LATIN CAPITAL LETTER D WITH DOT BELOW
-//
-// Each test has 5 columns (c1, c2, c3, c4, c5), where
-// (c1, c2, c3, c4, c5) == (c1, NFC(c1), NFD(c1), NFKC(c1), NFKD(c1))
-//
-// CONFORMANCE:
-// 1. The following invariants must be true for all conformant implementations
-//
-// NFC
-// c2 == NFC(c1) == NFC(c2) == NFC(c3)
-// c4 == NFC(c4) == NFC(c5)
-//
-// NFD
-// c3 == NFD(c1) == NFD(c2) == NFD(c3)
-// c5 == NFD(c4) == NFD(c5)
-//
-// NFKC
-// c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
-//
-// NFKD
-// c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
-//
-// 2. For every code point X assigned in this version of Unicode that is not
-// specifically listed in Part 1, the following invariants must be true
-// for all conformant implementations:
-//
-// X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
-//
-
-// Column types.
-const (
- cRaw = iota
- cNFC
- cNFD
- cNFKC
- cNFKD
- cMaxColumns
-)
-
-// Holds data from NormalizationTest.txt
-var part []Part
-
-type Part struct {
- name string
- number int
- tests []Test
-}
-
-type Test struct {
- name string
- partnr int
- number int
- r rune // used for character by character test
- cols [cMaxColumns]string // Each has 5 entries, see below.
-}
-
-func (t Test) Name() string {
- if t.number < 0 {
- return part[t.partnr].name
- }
- return fmt.Sprintf("%s:%d", part[t.partnr].name, t.number)
-}
-
-var partRe = regexp.MustCompile(`@Part(\d) # (.*)$`)
-var testRe = regexp.MustCompile(`^` + strings.Repeat(`([\dA-F ]+);`, 5) + ` # (.*)$`)
-
-var counter int
-
-// Load the data form NormalizationTest.txt
-func loadTestData() {
- if *localFiles {
- pwd, _ := os.Getwd()
- *url = "file://" + path.Join(pwd, file)
- }
- t := &http.Transport{}
- t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
- c := &http.Client{Transport: t}
- resp, err := c.Get(*url)
- if err != nil {
- logger.Fatal(err)
- }
- if resp.StatusCode != 200 {
- logger.Fatal("bad GET status for "+file, resp.Status)
- }
- f := resp.Body
- defer f.Close()
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- if len(line) == 0 || line[0] == '#' {
- continue
- }
- m := partRe.FindStringSubmatch(line)
- if m != nil {
- if len(m) < 3 {
- logger.Fatal("Failed to parse Part: ", line)
- }
- i, err := strconv.Atoi(m[1])
- if err != nil {
- logger.Fatal(err)
- }
- name := m[2]
- part = append(part, Part{name: name[:len(name)-1], number: i})
- continue
- }
- m = testRe.FindStringSubmatch(line)
- if m == nil || len(m) < 7 {
- logger.Fatalf(`Failed to parse: "%s" result: %#v`, line, m)
- }
- test := Test{name: m[6], partnr: len(part) - 1, number: counter}
- counter++
- for j := 1; j < len(m)-1; j++ {
- for _, split := range strings.Split(m[j], " ") {
- r, err := strconv.ParseUint(split, 16, 64)
- if err != nil {
- logger.Fatal(err)
- }
- if test.r == 0 {
- // save for CharacterByCharacterTests
- test.r = rune(r)
- }
- var buf [utf8.UTFMax]byte
- sz := utf8.EncodeRune(buf[:], rune(r))
- test.cols[j-1] += string(buf[:sz])
- }
- }
- part := &part[len(part)-1]
- part.tests = append(part.tests, test)
- }
- if scanner.Err() != nil {
- logger.Fatal(scanner.Err())
- }
-}
-
-var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"}
-
-var errorCount int
-
-func cmpResult(t *Test, name string, f norm.Form, gold, test, result string) {
- if gold != result {
- errorCount++
- if errorCount > 20 {
- return
- }
- st, sr, sg := []rune(test), []rune(result), []rune(gold)
- logger.Printf("%s:%s: %s(%X)=%X; want:%X: %s",
- t.Name(), name, fstr[f], st, sr, sg, t.name)
- }
-}
-
-func cmpIsNormal(t *Test, name string, f norm.Form, test string, result, want bool) {
- if result != want {
- errorCount++
- if errorCount > 20 {
- return
- }
- logger.Printf("%s:%s: %s(%X)=%v; want: %v", t.Name(), name, fstr[f], []rune(test), result, want)
- }
-}
-
-func doTest(t *Test, f norm.Form, gold, test string) {
- result := f.Bytes([]byte(test))
- cmpResult(t, "Bytes", f, gold, test, string(result))
- sresult := f.String(test)
- cmpResult(t, "String", f, gold, test, sresult)
- acc := []byte{}
- i := norm.Iter{}
- i.InitString(f, test)
- for !i.Done() {
- acc = append(acc, i.Next()...)
- }
- cmpResult(t, "Iter.Next", f, gold, test, string(acc))
- for i := range test {
- out := f.Append(f.Bytes([]byte(test[:i])), []byte(test[i:])...)
- cmpResult(t, fmt.Sprintf(":Append:%d", i), f, gold, test, string(out))
- }
- cmpIsNormal(t, "IsNormal", f, test, f.IsNormal([]byte(test)), test == gold)
-}
-
-func doConformanceTests(t *Test, partn int) {
- for i := 0; i <= 2; i++ {
- doTest(t, norm.NFC, t.cols[1], t.cols[i])
- doTest(t, norm.NFD, t.cols[2], t.cols[i])
- doTest(t, norm.NFKC, t.cols[3], t.cols[i])
- doTest(t, norm.NFKD, t.cols[4], t.cols[i])
- }
- for i := 3; i <= 4; i++ {
- doTest(t, norm.NFC, t.cols[3], t.cols[i])
- doTest(t, norm.NFD, t.cols[4], t.cols[i])
- doTest(t, norm.NFKC, t.cols[3], t.cols[i])
- doTest(t, norm.NFKD, t.cols[4], t.cols[i])
- }
-}
-
-func CharacterByCharacterTests() {
- tests := part[1].tests
- var last rune = 0
- for i := 0; i <= len(tests); i++ { // last one is special case
- var r rune
- if i == len(tests) {
- r = 0x2FA1E // Don't have to go to 0x10FFFF
- } else {
- r = tests[i].r
- }
- for last++; last < r; last++ {
- // Check all characters that were not explicitly listed in the test.
- t := &Test{partnr: 1, number: -1}
- char := string(last)
- doTest(t, norm.NFC, char, char)
- doTest(t, norm.NFD, char, char)
- doTest(t, norm.NFKC, char, char)
- doTest(t, norm.NFKD, char, char)
- }
- if i < len(tests) {
- doConformanceTests(&tests[i], 1)
- }
- }
-}
-
-func StandardTests() {
- for _, j := range []int{0, 2, 3} {
- for _, test := range part[j].tests {
- doConformanceTests(&test, j)
- }
- }
-}
-
-// PerformanceTest verifies that normalization is O(n). If any of the
-// code does not properly check for maxCombiningChars, normalization
-// may exhibit O(n**2) behavior.
-func PerformanceTest() {
- runtime.GOMAXPROCS(2)
- success := make(chan bool, 1)
- go func() {
- buf := bytes.Repeat([]byte("\u035D"), 1024*1024)
- buf = append(buf, "\u035B"...)
- norm.NFC.Append(nil, buf...)
- success <- true
- }()
- timeout := time.After(1 * time.Second)
- select {
- case <-success:
- // test completed before the timeout
- case <-timeout:
- errorCount++
- logger.Printf(`unexpectedly long time to complete PerformanceTest`)
- }
-}
diff --git a/src/pkg/exp/norm/readwriter.go b/src/pkg/exp/norm/readwriter.go
deleted file mode 100644
index 2682894de..000000000
--- a/src/pkg/exp/norm/readwriter.go
+++ /dev/null
@@ -1,126 +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 norm
-
-import "io"
-
-type normWriter struct {
- rb reorderBuffer
- w io.Writer
- buf []byte
-}
-
-// Write implements the standard write interface. If the last characters are
-// not at a normalization boundary, the bytes will be buffered for the next
-// write. The remaining bytes will be written on close.
-func (w *normWriter) Write(data []byte) (n int, err error) {
- // Process data in pieces to keep w.buf size bounded.
- const chunk = 4000
-
- for len(data) > 0 {
- // Normalize into w.buf.
- m := len(data)
- if m > chunk {
- m = chunk
- }
- w.rb.src = inputBytes(data[:m])
- w.rb.nsrc = m
- w.buf = doAppend(&w.rb, w.buf, 0)
- data = data[m:]
- n += m
-
- // Write out complete prefix, save remainder.
- // Note that lastBoundary looks back at most 30 runes.
- i := lastBoundary(&w.rb.f, w.buf)
- if i == -1 {
- i = 0
- }
- if i > 0 {
- if _, err = w.w.Write(w.buf[:i]); err != nil {
- break
- }
- bn := copy(w.buf, w.buf[i:])
- w.buf = w.buf[:bn]
- }
- }
- return n, err
-}
-
-// Close forces data that remains in the buffer to be written.
-func (w *normWriter) Close() error {
- if len(w.buf) > 0 {
- _, err := w.w.Write(w.buf)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-// Writer returns a new writer that implements Write(b)
-// by writing f(b) to w. The returned writer may use an
-// an internal buffer to maintain state across Write calls.
-// Calling its Close method writes any buffered data to w.
-func (f Form) Writer(w io.Writer) io.WriteCloser {
- wr := &normWriter{rb: reorderBuffer{}, w: w}
- wr.rb.init(f, nil)
- return wr
-}
-
-type normReader struct {
- rb reorderBuffer
- r io.Reader
- inbuf []byte
- outbuf []byte
- bufStart int
- lastBoundary int
- err error
-}
-
-// Read implements the standard read interface.
-func (r *normReader) Read(p []byte) (int, error) {
- for {
- if r.lastBoundary-r.bufStart > 0 {
- n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
- r.bufStart += n
- if r.lastBoundary-r.bufStart > 0 {
- return n, nil
- }
- return n, r.err
- }
- if r.err != nil {
- return 0, r.err
- }
- outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
- r.outbuf = r.outbuf[0:outn]
- r.bufStart = 0
-
- n, err := r.r.Read(r.inbuf)
- r.rb.src = inputBytes(r.inbuf[0:n])
- r.rb.nsrc, r.err = n, err
- if n > 0 {
- r.outbuf = doAppend(&r.rb, r.outbuf, 0)
- }
- if err == io.EOF {
- r.lastBoundary = len(r.outbuf)
- } else {
- r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
- if r.lastBoundary == -1 {
- r.lastBoundary = 0
- }
- }
- }
- panic("should not reach here")
-}
-
-// Reader returns a new reader that implements Read
-// by reading data from r and returning f(data).
-func (f Form) Reader(r io.Reader) io.Reader {
- const chunk = 4000
- buf := make([]byte, chunk)
- rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
- rr.rb.init(f, buf)
- return rr
-}
diff --git a/src/pkg/exp/norm/readwriter_test.go b/src/pkg/exp/norm/readwriter_test.go
deleted file mode 100644
index 3b49eb0a2..000000000
--- a/src/pkg/exp/norm/readwriter_test.go
+++ /dev/null
@@ -1,68 +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 norm
-
-import (
- "bytes"
- "fmt"
- "strings"
- "testing"
-)
-
-var ioTests = []AppendTest{
- {"", strings.Repeat("a\u0316\u0300", 6), strings.Repeat("\u00E0\u0316", 6)},
- {"", strings.Repeat("a\u0300\u0316", 4000), strings.Repeat("\u00E0\u0316", 4000)},
- {"", strings.Repeat("\x80\x80", 4000), strings.Repeat("\x80\x80", 4000)},
- {"", "\u0041\u0307\u0304", "\u01E0"},
-}
-
-var bufSizes = []int{1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 102, 103, 4000, 4001, 4002, 4003}
-
-func readFunc(size int) appendFunc {
- return func(f Form, out []byte, s string) []byte {
- out = append(out, s...)
- r := f.Reader(bytes.NewBuffer(out))
- buf := make([]byte, size)
- result := []byte{}
- for n, err := 0, error(nil); err == nil; {
- n, err = r.Read(buf)
- result = append(result, buf[:n]...)
- }
- return result
- }
-}
-
-func TestReader(t *testing.T) {
- for _, s := range bufSizes {
- name := fmt.Sprintf("TestReader%da", s)
- runAppendTests(t, name, NFKC, readFunc(s), appendTests)
- name = fmt.Sprintf("TestReader%db", s)
- runAppendTests(t, name, NFKC, readFunc(s), ioTests)
- }
-}
-
-func writeFunc(size int) appendFunc {
- return func(f Form, out []byte, s string) []byte {
- in := append(out, s...)
- result := new(bytes.Buffer)
- w := f.Writer(result)
- buf := make([]byte, size)
- for n := 0; len(in) > 0; in = in[n:] {
- n = copy(buf, in)
- _, _ = w.Write(buf[:n])
- }
- w.Close()
- return result.Bytes()
- }
-}
-
-func TestWriter(t *testing.T) {
- for _, s := range bufSizes {
- name := fmt.Sprintf("TestWriter%da", s)
- runAppendTests(t, name, NFKC, writeFunc(s), appendTests)
- name = fmt.Sprintf("TestWriter%db", s)
- runAppendTests(t, name, NFKC, writeFunc(s), ioTests)
- }
-}
diff --git a/src/pkg/exp/norm/tables.go b/src/pkg/exp/norm/tables.go
deleted file mode 100644
index fa33a34a1..000000000
--- a/src/pkg/exp/norm/tables.go
+++ /dev/null
@@ -1,6779 +0,0 @@
-// Generated by running
-// maketables --tables=all --url=http://www.unicode.org/Public/6.2.0/ucd/
-// DO NOT EDIT
-
-package norm
-
-// Version is the Unicode edition from which the tables are derived.
-const Version = "6.2.0"
-
-const (
- firstMulti = 0x18CF
- firstCCC = 0x2E74
- endMulti = 0x2F4A
- firstLeadingCCC = 0x4994
- firstCCCZeroExcept = 0x49AA
- lastDecomp = 0x49D1
- maxDecomp = 0x8000
-)
-
-// decomps: 18897 bytes
-var decomps = [...]byte{
- // Bytes 0 - 3f
- 0x00, 0x41, 0x20, 0x41, 0x21, 0x41, 0x22, 0x41,
- 0x23, 0x41, 0x24, 0x41, 0x25, 0x41, 0x26, 0x41,
- 0x27, 0x41, 0x28, 0x41, 0x29, 0x41, 0x2A, 0x41,
- 0x2B, 0x41, 0x2C, 0x41, 0x2D, 0x41, 0x2E, 0x41,
- 0x2F, 0x41, 0x30, 0x41, 0x31, 0x41, 0x32, 0x41,
- 0x33, 0x41, 0x34, 0x41, 0x35, 0x41, 0x36, 0x41,
- 0x37, 0x41, 0x38, 0x41, 0x39, 0x41, 0x3A, 0x41,
- 0x3B, 0x41, 0x3C, 0x41, 0x3D, 0x41, 0x3E, 0x41,
- // Bytes 40 - 7f
- 0x3F, 0x41, 0x40, 0x41, 0x41, 0x41, 0x42, 0x41,
- 0x43, 0x41, 0x44, 0x41, 0x45, 0x41, 0x46, 0x41,
- 0x47, 0x41, 0x48, 0x41, 0x49, 0x41, 0x4A, 0x41,
- 0x4B, 0x41, 0x4C, 0x41, 0x4D, 0x41, 0x4E, 0x41,
- 0x4F, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41,
- 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41,
- 0x57, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x41,
- 0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41,
- // Bytes 80 - bf
- 0x5F, 0x41, 0x60, 0x41, 0x61, 0x41, 0x62, 0x41,
- 0x63, 0x41, 0x64, 0x41, 0x65, 0x41, 0x66, 0x41,
- 0x67, 0x41, 0x68, 0x41, 0x69, 0x41, 0x6A, 0x41,
- 0x6B, 0x41, 0x6C, 0x41, 0x6D, 0x41, 0x6E, 0x41,
- 0x6F, 0x41, 0x70, 0x41, 0x71, 0x41, 0x72, 0x41,
- 0x73, 0x41, 0x74, 0x41, 0x75, 0x41, 0x76, 0x41,
- 0x77, 0x41, 0x78, 0x41, 0x79, 0x41, 0x7A, 0x41,
- 0x7B, 0x41, 0x7C, 0x41, 0x7D, 0x41, 0x7E, 0x42,
- // Bytes c0 - ff
- 0xC2, 0xA2, 0x42, 0xC2, 0xA3, 0x42, 0xC2, 0xA5,
- 0x42, 0xC2, 0xA6, 0x42, 0xC2, 0xAC, 0x42, 0xC2,
- 0xB4, 0x42, 0xC2, 0xB7, 0x42, 0xC3, 0x86, 0x42,
- 0xC3, 0xB0, 0x42, 0xC4, 0xA6, 0x42, 0xC4, 0xA7,
- 0x42, 0xC4, 0xB1, 0x42, 0xC5, 0x8B, 0x42, 0xC5,
- 0x93, 0x42, 0xC6, 0x8E, 0x42, 0xC6, 0x90, 0x42,
- 0xC6, 0xAB, 0x42, 0xC8, 0xA2, 0x42, 0xC8, 0xB7,
- 0x42, 0xC9, 0x90, 0x42, 0xC9, 0x91, 0x42, 0xC9,
- // Bytes 100 - 13f
- 0x92, 0x42, 0xC9, 0x94, 0x42, 0xC9, 0x95, 0x42,
- 0xC9, 0x99, 0x42, 0xC9, 0x9B, 0x42, 0xC9, 0x9C,
- 0x42, 0xC9, 0x9F, 0x42, 0xC9, 0xA1, 0x42, 0xC9,
- 0xA3, 0x42, 0xC9, 0xA5, 0x42, 0xC9, 0xA6, 0x42,
- 0xC9, 0xA8, 0x42, 0xC9, 0xA9, 0x42, 0xC9, 0xAA,
- 0x42, 0xC9, 0xAD, 0x42, 0xC9, 0xAF, 0x42, 0xC9,
- 0xB0, 0x42, 0xC9, 0xB1, 0x42, 0xC9, 0xB2, 0x42,
- 0xC9, 0xB3, 0x42, 0xC9, 0xB4, 0x42, 0xC9, 0xB5,
- // Bytes 140 - 17f
- 0x42, 0xC9, 0xB8, 0x42, 0xC9, 0xB9, 0x42, 0xC9,
- 0xBB, 0x42, 0xCA, 0x81, 0x42, 0xCA, 0x82, 0x42,
- 0xCA, 0x83, 0x42, 0xCA, 0x89, 0x42, 0xCA, 0x8A,
- 0x42, 0xCA, 0x8B, 0x42, 0xCA, 0x8C, 0x42, 0xCA,
- 0x90, 0x42, 0xCA, 0x91, 0x42, 0xCA, 0x92, 0x42,
- 0xCA, 0x95, 0x42, 0xCA, 0x9D, 0x42, 0xCA, 0x9F,
- 0x42, 0xCA, 0xB9, 0x42, 0xCE, 0x91, 0x42, 0xCE,
- 0x92, 0x42, 0xCE, 0x93, 0x42, 0xCE, 0x94, 0x42,
- // Bytes 180 - 1bf
- 0xCE, 0x95, 0x42, 0xCE, 0x96, 0x42, 0xCE, 0x97,
- 0x42, 0xCE, 0x98, 0x42, 0xCE, 0x99, 0x42, 0xCE,
- 0x9A, 0x42, 0xCE, 0x9B, 0x42, 0xCE, 0x9C, 0x42,
- 0xCE, 0x9D, 0x42, 0xCE, 0x9E, 0x42, 0xCE, 0x9F,
- 0x42, 0xCE, 0xA0, 0x42, 0xCE, 0xA1, 0x42, 0xCE,
- 0xA3, 0x42, 0xCE, 0xA4, 0x42, 0xCE, 0xA5, 0x42,
- 0xCE, 0xA6, 0x42, 0xCE, 0xA7, 0x42, 0xCE, 0xA8,
- 0x42, 0xCE, 0xA9, 0x42, 0xCE, 0xB1, 0x42, 0xCE,
- // Bytes 1c0 - 1ff
- 0xB2, 0x42, 0xCE, 0xB3, 0x42, 0xCE, 0xB4, 0x42,
- 0xCE, 0xB5, 0x42, 0xCE, 0xB6, 0x42, 0xCE, 0xB7,
- 0x42, 0xCE, 0xB8, 0x42, 0xCE, 0xB9, 0x42, 0xCE,
- 0xBA, 0x42, 0xCE, 0xBB, 0x42, 0xCE, 0xBC, 0x42,
- 0xCE, 0xBD, 0x42, 0xCE, 0xBE, 0x42, 0xCE, 0xBF,
- 0x42, 0xCF, 0x80, 0x42, 0xCF, 0x81, 0x42, 0xCF,
- 0x82, 0x42, 0xCF, 0x83, 0x42, 0xCF, 0x84, 0x42,
- 0xCF, 0x85, 0x42, 0xCF, 0x86, 0x42, 0xCF, 0x87,
- // Bytes 200 - 23f
- 0x42, 0xCF, 0x88, 0x42, 0xCF, 0x89, 0x42, 0xCF,
- 0x9C, 0x42, 0xCF, 0x9D, 0x42, 0xD0, 0xBD, 0x42,
- 0xD7, 0x90, 0x42, 0xD7, 0x91, 0x42, 0xD7, 0x92,
- 0x42, 0xD7, 0x93, 0x42, 0xD7, 0x94, 0x42, 0xD7,
- 0x9B, 0x42, 0xD7, 0x9C, 0x42, 0xD7, 0x9D, 0x42,
- 0xD7, 0xA2, 0x42, 0xD7, 0xA8, 0x42, 0xD7, 0xAA,
- 0x42, 0xD8, 0xA1, 0x42, 0xD8, 0xA7, 0x42, 0xD8,
- 0xA8, 0x42, 0xD8, 0xA9, 0x42, 0xD8, 0xAA, 0x42,
- // Bytes 240 - 27f
- 0xD8, 0xAB, 0x42, 0xD8, 0xAC, 0x42, 0xD8, 0xAD,
- 0x42, 0xD8, 0xAE, 0x42, 0xD8, 0xAF, 0x42, 0xD8,
- 0xB0, 0x42, 0xD8, 0xB1, 0x42, 0xD8, 0xB2, 0x42,
- 0xD8, 0xB3, 0x42, 0xD8, 0xB4, 0x42, 0xD8, 0xB5,
- 0x42, 0xD8, 0xB6, 0x42, 0xD8, 0xB7, 0x42, 0xD8,
- 0xB8, 0x42, 0xD8, 0xB9, 0x42, 0xD8, 0xBA, 0x42,
- 0xD9, 0x81, 0x42, 0xD9, 0x82, 0x42, 0xD9, 0x83,
- 0x42, 0xD9, 0x84, 0x42, 0xD9, 0x85, 0x42, 0xD9,
- // Bytes 280 - 2bf
- 0x86, 0x42, 0xD9, 0x87, 0x42, 0xD9, 0x88, 0x42,
- 0xD9, 0x89, 0x42, 0xD9, 0x8A, 0x42, 0xD9, 0xAE,
- 0x42, 0xD9, 0xAF, 0x42, 0xD9, 0xB1, 0x42, 0xD9,
- 0xB9, 0x42, 0xD9, 0xBA, 0x42, 0xD9, 0xBB, 0x42,
- 0xD9, 0xBE, 0x42, 0xD9, 0xBF, 0x42, 0xDA, 0x80,
- 0x42, 0xDA, 0x83, 0x42, 0xDA, 0x84, 0x42, 0xDA,
- 0x86, 0x42, 0xDA, 0x87, 0x42, 0xDA, 0x88, 0x42,
- 0xDA, 0x8C, 0x42, 0xDA, 0x8D, 0x42, 0xDA, 0x8E,
- // Bytes 2c0 - 2ff
- 0x42, 0xDA, 0x91, 0x42, 0xDA, 0x98, 0x42, 0xDA,
- 0xA1, 0x42, 0xDA, 0xA4, 0x42, 0xDA, 0xA6, 0x42,
- 0xDA, 0xA9, 0x42, 0xDA, 0xAD, 0x42, 0xDA, 0xAF,
- 0x42, 0xDA, 0xB1, 0x42, 0xDA, 0xB3, 0x42, 0xDA,
- 0xBA, 0x42, 0xDA, 0xBB, 0x42, 0xDA, 0xBE, 0x42,
- 0xDB, 0x81, 0x42, 0xDB, 0x85, 0x42, 0xDB, 0x86,
- 0x42, 0xDB, 0x87, 0x42, 0xDB, 0x88, 0x42, 0xDB,
- 0x89, 0x42, 0xDB, 0x8B, 0x42, 0xDB, 0x8C, 0x42,
- // Bytes 300 - 33f
- 0xDB, 0x90, 0x42, 0xDB, 0x92, 0x43, 0xE0, 0xBC,
- 0x8B, 0x43, 0xE1, 0x83, 0x9C, 0x43, 0xE1, 0x84,
- 0x80, 0x43, 0xE1, 0x84, 0x81, 0x43, 0xE1, 0x84,
- 0x82, 0x43, 0xE1, 0x84, 0x83, 0x43, 0xE1, 0x84,
- 0x84, 0x43, 0xE1, 0x84, 0x85, 0x43, 0xE1, 0x84,
- 0x86, 0x43, 0xE1, 0x84, 0x87, 0x43, 0xE1, 0x84,
- 0x88, 0x43, 0xE1, 0x84, 0x89, 0x43, 0xE1, 0x84,
- 0x8A, 0x43, 0xE1, 0x84, 0x8B, 0x43, 0xE1, 0x84,
- // Bytes 340 - 37f
- 0x8C, 0x43, 0xE1, 0x84, 0x8D, 0x43, 0xE1, 0x84,
- 0x8E, 0x43, 0xE1, 0x84, 0x8F, 0x43, 0xE1, 0x84,
- 0x90, 0x43, 0xE1, 0x84, 0x91, 0x43, 0xE1, 0x84,
- 0x92, 0x43, 0xE1, 0x84, 0x94, 0x43, 0xE1, 0x84,
- 0x95, 0x43, 0xE1, 0x84, 0x9A, 0x43, 0xE1, 0x84,
- 0x9C, 0x43, 0xE1, 0x84, 0x9D, 0x43, 0xE1, 0x84,
- 0x9E, 0x43, 0xE1, 0x84, 0xA0, 0x43, 0xE1, 0x84,
- 0xA1, 0x43, 0xE1, 0x84, 0xA2, 0x43, 0xE1, 0x84,
- // Bytes 380 - 3bf
- 0xA3, 0x43, 0xE1, 0x84, 0xA7, 0x43, 0xE1, 0x84,
- 0xA9, 0x43, 0xE1, 0x84, 0xAB, 0x43, 0xE1, 0x84,
- 0xAC, 0x43, 0xE1, 0x84, 0xAD, 0x43, 0xE1, 0x84,
- 0xAE, 0x43, 0xE1, 0x84, 0xAF, 0x43, 0xE1, 0x84,
- 0xB2, 0x43, 0xE1, 0x84, 0xB6, 0x43, 0xE1, 0x85,
- 0x80, 0x43, 0xE1, 0x85, 0x87, 0x43, 0xE1, 0x85,
- 0x8C, 0x43, 0xE1, 0x85, 0x97, 0x43, 0xE1, 0x85,
- 0x98, 0x43, 0xE1, 0x85, 0x99, 0x43, 0xE1, 0x85,
- // Bytes 3c0 - 3ff
- 0xA0, 0x43, 0xE1, 0x85, 0xA1, 0x43, 0xE1, 0x85,
- 0xA2, 0x43, 0xE1, 0x85, 0xA3, 0x43, 0xE1, 0x85,
- 0xA4, 0x43, 0xE1, 0x85, 0xA5, 0x43, 0xE1, 0x85,
- 0xA6, 0x43, 0xE1, 0x85, 0xA7, 0x43, 0xE1, 0x85,
- 0xA8, 0x43, 0xE1, 0x85, 0xA9, 0x43, 0xE1, 0x85,
- 0xAA, 0x43, 0xE1, 0x85, 0xAB, 0x43, 0xE1, 0x85,
- 0xAC, 0x43, 0xE1, 0x85, 0xAD, 0x43, 0xE1, 0x85,
- 0xAE, 0x43, 0xE1, 0x85, 0xAF, 0x43, 0xE1, 0x85,
- // Bytes 400 - 43f
- 0xB0, 0x43, 0xE1, 0x85, 0xB1, 0x43, 0xE1, 0x85,
- 0xB2, 0x43, 0xE1, 0x85, 0xB3, 0x43, 0xE1, 0x85,
- 0xB4, 0x43, 0xE1, 0x85, 0xB5, 0x43, 0xE1, 0x86,
- 0x84, 0x43, 0xE1, 0x86, 0x85, 0x43, 0xE1, 0x86,
- 0x88, 0x43, 0xE1, 0x86, 0x91, 0x43, 0xE1, 0x86,
- 0x92, 0x43, 0xE1, 0x86, 0x94, 0x43, 0xE1, 0x86,
- 0x9E, 0x43, 0xE1, 0x86, 0xA1, 0x43, 0xE1, 0x86,
- 0xAA, 0x43, 0xE1, 0x86, 0xAC, 0x43, 0xE1, 0x86,
- // Bytes 440 - 47f
- 0xAD, 0x43, 0xE1, 0x86, 0xB0, 0x43, 0xE1, 0x86,
- 0xB1, 0x43, 0xE1, 0x86, 0xB2, 0x43, 0xE1, 0x86,
- 0xB3, 0x43, 0xE1, 0x86, 0xB4, 0x43, 0xE1, 0x86,
- 0xB5, 0x43, 0xE1, 0x87, 0x87, 0x43, 0xE1, 0x87,
- 0x88, 0x43, 0xE1, 0x87, 0x8C, 0x43, 0xE1, 0x87,
- 0x8E, 0x43, 0xE1, 0x87, 0x93, 0x43, 0xE1, 0x87,
- 0x97, 0x43, 0xE1, 0x87, 0x99, 0x43, 0xE1, 0x87,
- 0x9D, 0x43, 0xE1, 0x87, 0x9F, 0x43, 0xE1, 0x87,
- // Bytes 480 - 4bf
- 0xB1, 0x43, 0xE1, 0x87, 0xB2, 0x43, 0xE1, 0xB4,
- 0x82, 0x43, 0xE1, 0xB4, 0x96, 0x43, 0xE1, 0xB4,
- 0x97, 0x43, 0xE1, 0xB4, 0x9C, 0x43, 0xE1, 0xB4,
- 0x9D, 0x43, 0xE1, 0xB4, 0xA5, 0x43, 0xE1, 0xB5,
- 0xBB, 0x43, 0xE1, 0xB6, 0x85, 0x43, 0xE2, 0x80,
- 0x82, 0x43, 0xE2, 0x80, 0x83, 0x43, 0xE2, 0x80,
- 0x90, 0x43, 0xE2, 0x80, 0x93, 0x43, 0xE2, 0x80,
- 0x94, 0x43, 0xE2, 0x82, 0xA9, 0x43, 0xE2, 0x86,
- // Bytes 4c0 - 4ff
- 0x90, 0x43, 0xE2, 0x86, 0x91, 0x43, 0xE2, 0x86,
- 0x92, 0x43, 0xE2, 0x86, 0x93, 0x43, 0xE2, 0x88,
- 0x82, 0x43, 0xE2, 0x88, 0x87, 0x43, 0xE2, 0x88,
- 0x91, 0x43, 0xE2, 0x88, 0x92, 0x43, 0xE2, 0x94,
- 0x82, 0x43, 0xE2, 0x96, 0xA0, 0x43, 0xE2, 0x97,
- 0x8B, 0x43, 0xE2, 0xA6, 0x85, 0x43, 0xE2, 0xA6,
- 0x86, 0x43, 0xE2, 0xB5, 0xA1, 0x43, 0xE3, 0x80,
- 0x81, 0x43, 0xE3, 0x80, 0x82, 0x43, 0xE3, 0x80,
- // Bytes 500 - 53f
- 0x88, 0x43, 0xE3, 0x80, 0x89, 0x43, 0xE3, 0x80,
- 0x8A, 0x43, 0xE3, 0x80, 0x8B, 0x43, 0xE3, 0x80,
- 0x8C, 0x43, 0xE3, 0x80, 0x8D, 0x43, 0xE3, 0x80,
- 0x8E, 0x43, 0xE3, 0x80, 0x8F, 0x43, 0xE3, 0x80,
- 0x90, 0x43, 0xE3, 0x80, 0x91, 0x43, 0xE3, 0x80,
- 0x92, 0x43, 0xE3, 0x80, 0x94, 0x43, 0xE3, 0x80,
- 0x95, 0x43, 0xE3, 0x80, 0x96, 0x43, 0xE3, 0x80,
- 0x97, 0x43, 0xE3, 0x82, 0xA1, 0x43, 0xE3, 0x82,
- // Bytes 540 - 57f
- 0xA2, 0x43, 0xE3, 0x82, 0xA3, 0x43, 0xE3, 0x82,
- 0xA4, 0x43, 0xE3, 0x82, 0xA5, 0x43, 0xE3, 0x82,
- 0xA6, 0x43, 0xE3, 0x82, 0xA7, 0x43, 0xE3, 0x82,
- 0xA8, 0x43, 0xE3, 0x82, 0xA9, 0x43, 0xE3, 0x82,
- 0xAA, 0x43, 0xE3, 0x82, 0xAB, 0x43, 0xE3, 0x82,
- 0xAD, 0x43, 0xE3, 0x82, 0xAF, 0x43, 0xE3, 0x82,
- 0xB1, 0x43, 0xE3, 0x82, 0xB3, 0x43, 0xE3, 0x82,
- 0xB5, 0x43, 0xE3, 0x82, 0xB7, 0x43, 0xE3, 0x82,
- // Bytes 580 - 5bf
- 0xB9, 0x43, 0xE3, 0x82, 0xBB, 0x43, 0xE3, 0x82,
- 0xBD, 0x43, 0xE3, 0x82, 0xBF, 0x43, 0xE3, 0x83,
- 0x81, 0x43, 0xE3, 0x83, 0x83, 0x43, 0xE3, 0x83,
- 0x84, 0x43, 0xE3, 0x83, 0x86, 0x43, 0xE3, 0x83,
- 0x88, 0x43, 0xE3, 0x83, 0x8A, 0x43, 0xE3, 0x83,
- 0x8B, 0x43, 0xE3, 0x83, 0x8C, 0x43, 0xE3, 0x83,
- 0x8D, 0x43, 0xE3, 0x83, 0x8E, 0x43, 0xE3, 0x83,
- 0x8F, 0x43, 0xE3, 0x83, 0x92, 0x43, 0xE3, 0x83,
- // Bytes 5c0 - 5ff
- 0x95, 0x43, 0xE3, 0x83, 0x98, 0x43, 0xE3, 0x83,
- 0x9B, 0x43, 0xE3, 0x83, 0x9E, 0x43, 0xE3, 0x83,
- 0x9F, 0x43, 0xE3, 0x83, 0xA0, 0x43, 0xE3, 0x83,
- 0xA1, 0x43, 0xE3, 0x83, 0xA2, 0x43, 0xE3, 0x83,
- 0xA3, 0x43, 0xE3, 0x83, 0xA4, 0x43, 0xE3, 0x83,
- 0xA5, 0x43, 0xE3, 0x83, 0xA6, 0x43, 0xE3, 0x83,
- 0xA7, 0x43, 0xE3, 0x83, 0xA8, 0x43, 0xE3, 0x83,
- 0xA9, 0x43, 0xE3, 0x83, 0xAA, 0x43, 0xE3, 0x83,
- // Bytes 600 - 63f
- 0xAB, 0x43, 0xE3, 0x83, 0xAC, 0x43, 0xE3, 0x83,
- 0xAD, 0x43, 0xE3, 0x83, 0xAF, 0x43, 0xE3, 0x83,
- 0xB0, 0x43, 0xE3, 0x83, 0xB1, 0x43, 0xE3, 0x83,
- 0xB2, 0x43, 0xE3, 0x83, 0xB3, 0x43, 0xE3, 0x83,
- 0xBB, 0x43, 0xE3, 0x83, 0xBC, 0x43, 0xE3, 0x92,
- 0x9E, 0x43, 0xE3, 0x92, 0xB9, 0x43, 0xE3, 0x92,
- 0xBB, 0x43, 0xE3, 0x93, 0x9F, 0x43, 0xE3, 0x94,
- 0x95, 0x43, 0xE3, 0x9B, 0xAE, 0x43, 0xE3, 0x9B,
- // Bytes 640 - 67f
- 0xBC, 0x43, 0xE3, 0x9E, 0x81, 0x43, 0xE3, 0xA0,
- 0xAF, 0x43, 0xE3, 0xA1, 0xA2, 0x43, 0xE3, 0xA1,
- 0xBC, 0x43, 0xE3, 0xA3, 0x87, 0x43, 0xE3, 0xA3,
- 0xA3, 0x43, 0xE3, 0xA4, 0x9C, 0x43, 0xE3, 0xA4,
- 0xBA, 0x43, 0xE3, 0xA8, 0xAE, 0x43, 0xE3, 0xA9,
- 0xAC, 0x43, 0xE3, 0xAB, 0xA4, 0x43, 0xE3, 0xAC,
- 0x88, 0x43, 0xE3, 0xAC, 0x99, 0x43, 0xE3, 0xAD,
- 0x89, 0x43, 0xE3, 0xAE, 0x9D, 0x43, 0xE3, 0xB0,
- // Bytes 680 - 6bf
- 0x98, 0x43, 0xE3, 0xB1, 0x8E, 0x43, 0xE3, 0xB4,
- 0xB3, 0x43, 0xE3, 0xB6, 0x96, 0x43, 0xE3, 0xBA,
- 0xAC, 0x43, 0xE3, 0xBA, 0xB8, 0x43, 0xE3, 0xBC,
- 0x9B, 0x43, 0xE3, 0xBF, 0xBC, 0x43, 0xE4, 0x80,
- 0x88, 0x43, 0xE4, 0x80, 0x98, 0x43, 0xE4, 0x80,
- 0xB9, 0x43, 0xE4, 0x81, 0x86, 0x43, 0xE4, 0x82,
- 0x96, 0x43, 0xE4, 0x83, 0xA3, 0x43, 0xE4, 0x84,
- 0xAF, 0x43, 0xE4, 0x88, 0x82, 0x43, 0xE4, 0x88,
- // Bytes 6c0 - 6ff
- 0xA7, 0x43, 0xE4, 0x8A, 0xA0, 0x43, 0xE4, 0x8C,
- 0x81, 0x43, 0xE4, 0x8C, 0xB4, 0x43, 0xE4, 0x8D,
- 0x99, 0x43, 0xE4, 0x8F, 0x95, 0x43, 0xE4, 0x8F,
- 0x99, 0x43, 0xE4, 0x90, 0x8B, 0x43, 0xE4, 0x91,
- 0xAB, 0x43, 0xE4, 0x94, 0xAB, 0x43, 0xE4, 0x95,
- 0x9D, 0x43, 0xE4, 0x95, 0xA1, 0x43, 0xE4, 0x95,
- 0xAB, 0x43, 0xE4, 0x97, 0x97, 0x43, 0xE4, 0x97,
- 0xB9, 0x43, 0xE4, 0x98, 0xB5, 0x43, 0xE4, 0x9A,
- // Bytes 700 - 73f
- 0xBE, 0x43, 0xE4, 0x9B, 0x87, 0x43, 0xE4, 0xA6,
- 0x95, 0x43, 0xE4, 0xA7, 0xA6, 0x43, 0xE4, 0xA9,
- 0xAE, 0x43, 0xE4, 0xA9, 0xB6, 0x43, 0xE4, 0xAA,
- 0xB2, 0x43, 0xE4, 0xAC, 0xB3, 0x43, 0xE4, 0xAF,
- 0x8E, 0x43, 0xE4, 0xB3, 0x8E, 0x43, 0xE4, 0xB3,
- 0xAD, 0x43, 0xE4, 0xB3, 0xB8, 0x43, 0xE4, 0xB5,
- 0x96, 0x43, 0xE4, 0xB8, 0x80, 0x43, 0xE4, 0xB8,
- 0x81, 0x43, 0xE4, 0xB8, 0x83, 0x43, 0xE4, 0xB8,
- // Bytes 740 - 77f
- 0x89, 0x43, 0xE4, 0xB8, 0x8A, 0x43, 0xE4, 0xB8,
- 0x8B, 0x43, 0xE4, 0xB8, 0x8D, 0x43, 0xE4, 0xB8,
- 0x99, 0x43, 0xE4, 0xB8, 0xA6, 0x43, 0xE4, 0xB8,
- 0xA8, 0x43, 0xE4, 0xB8, 0xAD, 0x43, 0xE4, 0xB8,
- 0xB2, 0x43, 0xE4, 0xB8, 0xB6, 0x43, 0xE4, 0xB8,
- 0xB8, 0x43, 0xE4, 0xB8, 0xB9, 0x43, 0xE4, 0xB8,
- 0xBD, 0x43, 0xE4, 0xB8, 0xBF, 0x43, 0xE4, 0xB9,
- 0x81, 0x43, 0xE4, 0xB9, 0x99, 0x43, 0xE4, 0xB9,
- // Bytes 780 - 7bf
- 0x9D, 0x43, 0xE4, 0xBA, 0x82, 0x43, 0xE4, 0xBA,
- 0x85, 0x43, 0xE4, 0xBA, 0x86, 0x43, 0xE4, 0xBA,
- 0x8C, 0x43, 0xE4, 0xBA, 0x94, 0x43, 0xE4, 0xBA,
- 0xA0, 0x43, 0xE4, 0xBA, 0xA4, 0x43, 0xE4, 0xBA,
- 0xAE, 0x43, 0xE4, 0xBA, 0xBA, 0x43, 0xE4, 0xBB,
- 0x80, 0x43, 0xE4, 0xBB, 0x8C, 0x43, 0xE4, 0xBB,
- 0xA4, 0x43, 0xE4, 0xBC, 0x81, 0x43, 0xE4, 0xBC,
- 0x91, 0x43, 0xE4, 0xBD, 0xA0, 0x43, 0xE4, 0xBE,
- // Bytes 7c0 - 7ff
- 0x80, 0x43, 0xE4, 0xBE, 0x86, 0x43, 0xE4, 0xBE,
- 0x8B, 0x43, 0xE4, 0xBE, 0xAE, 0x43, 0xE4, 0xBE,
- 0xBB, 0x43, 0xE4, 0xBE, 0xBF, 0x43, 0xE5, 0x80,
- 0x82, 0x43, 0xE5, 0x80, 0xAB, 0x43, 0xE5, 0x81,
- 0xBA, 0x43, 0xE5, 0x82, 0x99, 0x43, 0xE5, 0x83,
- 0x8F, 0x43, 0xE5, 0x83, 0x9A, 0x43, 0xE5, 0x83,
- 0xA7, 0x43, 0xE5, 0x84, 0xAA, 0x43, 0xE5, 0x84,
- 0xBF, 0x43, 0xE5, 0x85, 0x80, 0x43, 0xE5, 0x85,
- // Bytes 800 - 83f
- 0x85, 0x43, 0xE5, 0x85, 0x8D, 0x43, 0xE5, 0x85,
- 0x94, 0x43, 0xE5, 0x85, 0xA4, 0x43, 0xE5, 0x85,
- 0xA5, 0x43, 0xE5, 0x85, 0xA7, 0x43, 0xE5, 0x85,
- 0xA8, 0x43, 0xE5, 0x85, 0xA9, 0x43, 0xE5, 0x85,
- 0xAB, 0x43, 0xE5, 0x85, 0xAD, 0x43, 0xE5, 0x85,
- 0xB7, 0x43, 0xE5, 0x86, 0x80, 0x43, 0xE5, 0x86,
- 0x82, 0x43, 0xE5, 0x86, 0x8D, 0x43, 0xE5, 0x86,
- 0x92, 0x43, 0xE5, 0x86, 0x95, 0x43, 0xE5, 0x86,
- // Bytes 840 - 87f
- 0x96, 0x43, 0xE5, 0x86, 0x97, 0x43, 0xE5, 0x86,
- 0x99, 0x43, 0xE5, 0x86, 0xA4, 0x43, 0xE5, 0x86,
- 0xAB, 0x43, 0xE5, 0x86, 0xAC, 0x43, 0xE5, 0x86,
- 0xB5, 0x43, 0xE5, 0x86, 0xB7, 0x43, 0xE5, 0x87,
- 0x89, 0x43, 0xE5, 0x87, 0x8C, 0x43, 0xE5, 0x87,
- 0x9C, 0x43, 0xE5, 0x87, 0x9E, 0x43, 0xE5, 0x87,
- 0xA0, 0x43, 0xE5, 0x87, 0xB5, 0x43, 0xE5, 0x88,
- 0x80, 0x43, 0xE5, 0x88, 0x83, 0x43, 0xE5, 0x88,
- // Bytes 880 - 8bf
- 0x87, 0x43, 0xE5, 0x88, 0x97, 0x43, 0xE5, 0x88,
- 0x9D, 0x43, 0xE5, 0x88, 0xA9, 0x43, 0xE5, 0x88,
- 0xBA, 0x43, 0xE5, 0x88, 0xBB, 0x43, 0xE5, 0x89,
- 0x86, 0x43, 0xE5, 0x89, 0x8D, 0x43, 0xE5, 0x89,
- 0xB2, 0x43, 0xE5, 0x89, 0xB7, 0x43, 0xE5, 0x8A,
- 0x89, 0x43, 0xE5, 0x8A, 0x9B, 0x43, 0xE5, 0x8A,
- 0xA3, 0x43, 0xE5, 0x8A, 0xB3, 0x43, 0xE5, 0x8A,
- 0xB4, 0x43, 0xE5, 0x8B, 0x87, 0x43, 0xE5, 0x8B,
- // Bytes 8c0 - 8ff
- 0x89, 0x43, 0xE5, 0x8B, 0x92, 0x43, 0xE5, 0x8B,
- 0x9E, 0x43, 0xE5, 0x8B, 0xA4, 0x43, 0xE5, 0x8B,
- 0xB5, 0x43, 0xE5, 0x8B, 0xB9, 0x43, 0xE5, 0x8B,
- 0xBA, 0x43, 0xE5, 0x8C, 0x85, 0x43, 0xE5, 0x8C,
- 0x86, 0x43, 0xE5, 0x8C, 0x95, 0x43, 0xE5, 0x8C,
- 0x97, 0x43, 0xE5, 0x8C, 0x9A, 0x43, 0xE5, 0x8C,
- 0xB8, 0x43, 0xE5, 0x8C, 0xBB, 0x43, 0xE5, 0x8C,
- 0xBF, 0x43, 0xE5, 0x8D, 0x81, 0x43, 0xE5, 0x8D,
- // Bytes 900 - 93f
- 0x84, 0x43, 0xE5, 0x8D, 0x85, 0x43, 0xE5, 0x8D,
- 0x89, 0x43, 0xE5, 0x8D, 0x91, 0x43, 0xE5, 0x8D,
- 0x94, 0x43, 0xE5, 0x8D, 0x9A, 0x43, 0xE5, 0x8D,
- 0x9C, 0x43, 0xE5, 0x8D, 0xA9, 0x43, 0xE5, 0x8D,
- 0xB0, 0x43, 0xE5, 0x8D, 0xB3, 0x43, 0xE5, 0x8D,
- 0xB5, 0x43, 0xE5, 0x8D, 0xBD, 0x43, 0xE5, 0x8D,
- 0xBF, 0x43, 0xE5, 0x8E, 0x82, 0x43, 0xE5, 0x8E,
- 0xB6, 0x43, 0xE5, 0x8F, 0x83, 0x43, 0xE5, 0x8F,
- // Bytes 940 - 97f
- 0x88, 0x43, 0xE5, 0x8F, 0x8A, 0x43, 0xE5, 0x8F,
- 0x8C, 0x43, 0xE5, 0x8F, 0x9F, 0x43, 0xE5, 0x8F,
- 0xA3, 0x43, 0xE5, 0x8F, 0xA5, 0x43, 0xE5, 0x8F,
- 0xAB, 0x43, 0xE5, 0x8F, 0xAF, 0x43, 0xE5, 0x8F,
- 0xB1, 0x43, 0xE5, 0x8F, 0xB3, 0x43, 0xE5, 0x90,
- 0x86, 0x43, 0xE5, 0x90, 0x88, 0x43, 0xE5, 0x90,
- 0x8D, 0x43, 0xE5, 0x90, 0x8F, 0x43, 0xE5, 0x90,
- 0x9D, 0x43, 0xE5, 0x90, 0xB8, 0x43, 0xE5, 0x90,
- // Bytes 980 - 9bf
- 0xB9, 0x43, 0xE5, 0x91, 0x82, 0x43, 0xE5, 0x91,
- 0x88, 0x43, 0xE5, 0x91, 0xA8, 0x43, 0xE5, 0x92,
- 0x9E, 0x43, 0xE5, 0x92, 0xA2, 0x43, 0xE5, 0x92,
- 0xBD, 0x43, 0xE5, 0x93, 0xB6, 0x43, 0xE5, 0x94,
- 0x90, 0x43, 0xE5, 0x95, 0x8F, 0x43, 0xE5, 0x95,
- 0x93, 0x43, 0xE5, 0x95, 0x95, 0x43, 0xE5, 0x95,
- 0xA3, 0x43, 0xE5, 0x96, 0x84, 0x43, 0xE5, 0x96,
- 0x87, 0x43, 0xE5, 0x96, 0x99, 0x43, 0xE5, 0x96,
- // Bytes 9c0 - 9ff
- 0x9D, 0x43, 0xE5, 0x96, 0xAB, 0x43, 0xE5, 0x96,
- 0xB3, 0x43, 0xE5, 0x96, 0xB6, 0x43, 0xE5, 0x97,
- 0x80, 0x43, 0xE5, 0x97, 0x82, 0x43, 0xE5, 0x97,
- 0xA2, 0x43, 0xE5, 0x98, 0x86, 0x43, 0xE5, 0x99,
- 0x91, 0x43, 0xE5, 0x99, 0xA8, 0x43, 0xE5, 0x99,
- 0xB4, 0x43, 0xE5, 0x9B, 0x97, 0x43, 0xE5, 0x9B,
- 0x9B, 0x43, 0xE5, 0x9B, 0xB9, 0x43, 0xE5, 0x9C,
- 0x96, 0x43, 0xE5, 0x9C, 0x97, 0x43, 0xE5, 0x9C,
- // Bytes a00 - a3f
- 0x9F, 0x43, 0xE5, 0x9C, 0xB0, 0x43, 0xE5, 0x9E,
- 0x8B, 0x43, 0xE5, 0x9F, 0x8E, 0x43, 0xE5, 0x9F,
- 0xB4, 0x43, 0xE5, 0xA0, 0x8D, 0x43, 0xE5, 0xA0,
- 0xB1, 0x43, 0xE5, 0xA0, 0xB2, 0x43, 0xE5, 0xA1,
- 0x80, 0x43, 0xE5, 0xA1, 0x9A, 0x43, 0xE5, 0xA1,
- 0x9E, 0x43, 0xE5, 0xA2, 0xA8, 0x43, 0xE5, 0xA2,
- 0xAC, 0x43, 0xE5, 0xA2, 0xB3, 0x43, 0xE5, 0xA3,
- 0x98, 0x43, 0xE5, 0xA3, 0x9F, 0x43, 0xE5, 0xA3,
- // Bytes a40 - a7f
- 0xAB, 0x43, 0xE5, 0xA3, 0xAE, 0x43, 0xE5, 0xA3,
- 0xB0, 0x43, 0xE5, 0xA3, 0xB2, 0x43, 0xE5, 0xA3,
- 0xB7, 0x43, 0xE5, 0xA4, 0x82, 0x43, 0xE5, 0xA4,
- 0x86, 0x43, 0xE5, 0xA4, 0x8A, 0x43, 0xE5, 0xA4,
- 0x95, 0x43, 0xE5, 0xA4, 0x9A, 0x43, 0xE5, 0xA4,
- 0x9C, 0x43, 0xE5, 0xA4, 0xA2, 0x43, 0xE5, 0xA4,
- 0xA7, 0x43, 0xE5, 0xA4, 0xA9, 0x43, 0xE5, 0xA5,
- 0x84, 0x43, 0xE5, 0xA5, 0x88, 0x43, 0xE5, 0xA5,
- // Bytes a80 - abf
- 0x91, 0x43, 0xE5, 0xA5, 0x94, 0x43, 0xE5, 0xA5,
- 0xA2, 0x43, 0xE5, 0xA5, 0xB3, 0x43, 0xE5, 0xA7,
- 0x98, 0x43, 0xE5, 0xA7, 0xAC, 0x43, 0xE5, 0xA8,
- 0x9B, 0x43, 0xE5, 0xA8, 0xA7, 0x43, 0xE5, 0xA9,
- 0xA2, 0x43, 0xE5, 0xA9, 0xA6, 0x43, 0xE5, 0xAA,
- 0xB5, 0x43, 0xE5, 0xAC, 0x88, 0x43, 0xE5, 0xAC,
- 0xA8, 0x43, 0xE5, 0xAC, 0xBE, 0x43, 0xE5, 0xAD,
- 0x90, 0x43, 0xE5, 0xAD, 0x97, 0x43, 0xE5, 0xAD,
- // Bytes ac0 - aff
- 0xA6, 0x43, 0xE5, 0xAE, 0x80, 0x43, 0xE5, 0xAE,
- 0x85, 0x43, 0xE5, 0xAE, 0x97, 0x43, 0xE5, 0xAF,
- 0x83, 0x43, 0xE5, 0xAF, 0x98, 0x43, 0xE5, 0xAF,
- 0xA7, 0x43, 0xE5, 0xAF, 0xAE, 0x43, 0xE5, 0xAF,
- 0xB3, 0x43, 0xE5, 0xAF, 0xB8, 0x43, 0xE5, 0xAF,
- 0xBF, 0x43, 0xE5, 0xB0, 0x86, 0x43, 0xE5, 0xB0,
- 0x8F, 0x43, 0xE5, 0xB0, 0xA2, 0x43, 0xE5, 0xB0,
- 0xB8, 0x43, 0xE5, 0xB0, 0xBF, 0x43, 0xE5, 0xB1,
- // Bytes b00 - b3f
- 0xA0, 0x43, 0xE5, 0xB1, 0xA2, 0x43, 0xE5, 0xB1,
- 0xA4, 0x43, 0xE5, 0xB1, 0xA5, 0x43, 0xE5, 0xB1,
- 0xAE, 0x43, 0xE5, 0xB1, 0xB1, 0x43, 0xE5, 0xB2,
- 0x8D, 0x43, 0xE5, 0xB3, 0x80, 0x43, 0xE5, 0xB4,
- 0x99, 0x43, 0xE5, 0xB5, 0x83, 0x43, 0xE5, 0xB5,
- 0x90, 0x43, 0xE5, 0xB5, 0xAB, 0x43, 0xE5, 0xB5,
- 0xAE, 0x43, 0xE5, 0xB5, 0xBC, 0x43, 0xE5, 0xB6,
- 0xB2, 0x43, 0xE5, 0xB6, 0xBA, 0x43, 0xE5, 0xB7,
- // Bytes b40 - b7f
- 0x9B, 0x43, 0xE5, 0xB7, 0xA1, 0x43, 0xE5, 0xB7,
- 0xA2, 0x43, 0xE5, 0xB7, 0xA5, 0x43, 0xE5, 0xB7,
- 0xA6, 0x43, 0xE5, 0xB7, 0xB1, 0x43, 0xE5, 0xB7,
- 0xBD, 0x43, 0xE5, 0xB7, 0xBE, 0x43, 0xE5, 0xB8,
- 0xA8, 0x43, 0xE5, 0xB8, 0xBD, 0x43, 0xE5, 0xB9,
- 0xA9, 0x43, 0xE5, 0xB9, 0xB2, 0x43, 0xE5, 0xB9,
- 0xB4, 0x43, 0xE5, 0xB9, 0xBA, 0x43, 0xE5, 0xB9,
- 0xBC, 0x43, 0xE5, 0xB9, 0xBF, 0x43, 0xE5, 0xBA,
- // Bytes b80 - bbf
- 0xA6, 0x43, 0xE5, 0xBA, 0xB0, 0x43, 0xE5, 0xBA,
- 0xB3, 0x43, 0xE5, 0xBA, 0xB6, 0x43, 0xE5, 0xBB,
- 0x89, 0x43, 0xE5, 0xBB, 0x8A, 0x43, 0xE5, 0xBB,
- 0x92, 0x43, 0xE5, 0xBB, 0x93, 0x43, 0xE5, 0xBB,
- 0x99, 0x43, 0xE5, 0xBB, 0xAC, 0x43, 0xE5, 0xBB,
- 0xB4, 0x43, 0xE5, 0xBB, 0xBE, 0x43, 0xE5, 0xBC,
- 0x84, 0x43, 0xE5, 0xBC, 0x8B, 0x43, 0xE5, 0xBC,
- 0x93, 0x43, 0xE5, 0xBC, 0xA2, 0x43, 0xE5, 0xBD,
- // Bytes bc0 - bff
- 0x90, 0x43, 0xE5, 0xBD, 0x93, 0x43, 0xE5, 0xBD,
- 0xA1, 0x43, 0xE5, 0xBD, 0xA2, 0x43, 0xE5, 0xBD,
- 0xA9, 0x43, 0xE5, 0xBD, 0xAB, 0x43, 0xE5, 0xBD,
- 0xB3, 0x43, 0xE5, 0xBE, 0x8B, 0x43, 0xE5, 0xBE,
- 0x8C, 0x43, 0xE5, 0xBE, 0x97, 0x43, 0xE5, 0xBE,
- 0x9A, 0x43, 0xE5, 0xBE, 0xA9, 0x43, 0xE5, 0xBE,
- 0xAD, 0x43, 0xE5, 0xBF, 0x83, 0x43, 0xE5, 0xBF,
- 0x8D, 0x43, 0xE5, 0xBF, 0x97, 0x43, 0xE5, 0xBF,
- // Bytes c00 - c3f
- 0xB5, 0x43, 0xE5, 0xBF, 0xB9, 0x43, 0xE6, 0x80,
- 0x92, 0x43, 0xE6, 0x80, 0x9C, 0x43, 0xE6, 0x81,
- 0xB5, 0x43, 0xE6, 0x82, 0x81, 0x43, 0xE6, 0x82,
- 0x94, 0x43, 0xE6, 0x83, 0x87, 0x43, 0xE6, 0x83,
- 0x98, 0x43, 0xE6, 0x83, 0xA1, 0x43, 0xE6, 0x84,
- 0x88, 0x43, 0xE6, 0x85, 0x84, 0x43, 0xE6, 0x85,
- 0x88, 0x43, 0xE6, 0x85, 0x8C, 0x43, 0xE6, 0x85,
- 0x8E, 0x43, 0xE6, 0x85, 0xA0, 0x43, 0xE6, 0x85,
- // Bytes c40 - c7f
- 0xA8, 0x43, 0xE6, 0x85, 0xBA, 0x43, 0xE6, 0x86,
- 0x8E, 0x43, 0xE6, 0x86, 0x90, 0x43, 0xE6, 0x86,
- 0xA4, 0x43, 0xE6, 0x86, 0xAF, 0x43, 0xE6, 0x86,
- 0xB2, 0x43, 0xE6, 0x87, 0x9E, 0x43, 0xE6, 0x87,
- 0xB2, 0x43, 0xE6, 0x87, 0xB6, 0x43, 0xE6, 0x88,
- 0x80, 0x43, 0xE6, 0x88, 0x88, 0x43, 0xE6, 0x88,
- 0x90, 0x43, 0xE6, 0x88, 0x9B, 0x43, 0xE6, 0x88,
- 0xAE, 0x43, 0xE6, 0x88, 0xB4, 0x43, 0xE6, 0x88,
- // Bytes c80 - cbf
- 0xB6, 0x43, 0xE6, 0x89, 0x8B, 0x43, 0xE6, 0x89,
- 0x93, 0x43, 0xE6, 0x89, 0x9D, 0x43, 0xE6, 0x8A,
- 0x95, 0x43, 0xE6, 0x8A, 0xB1, 0x43, 0xE6, 0x8B,
- 0x89, 0x43, 0xE6, 0x8B, 0x8F, 0x43, 0xE6, 0x8B,
- 0x93, 0x43, 0xE6, 0x8B, 0x94, 0x43, 0xE6, 0x8B,
- 0xBC, 0x43, 0xE6, 0x8B, 0xBE, 0x43, 0xE6, 0x8C,
- 0x87, 0x43, 0xE6, 0x8C, 0xBD, 0x43, 0xE6, 0x8D,
- 0x90, 0x43, 0xE6, 0x8D, 0x95, 0x43, 0xE6, 0x8D,
- // Bytes cc0 - cff
- 0xA8, 0x43, 0xE6, 0x8D, 0xBB, 0x43, 0xE6, 0x8E,
- 0x83, 0x43, 0xE6, 0x8E, 0xA0, 0x43, 0xE6, 0x8E,
- 0xA9, 0x43, 0xE6, 0x8F, 0x84, 0x43, 0xE6, 0x8F,
- 0x85, 0x43, 0xE6, 0x8F, 0xA4, 0x43, 0xE6, 0x90,
- 0x9C, 0x43, 0xE6, 0x90, 0xA2, 0x43, 0xE6, 0x91,
- 0x92, 0x43, 0xE6, 0x91, 0xA9, 0x43, 0xE6, 0x91,
- 0xB7, 0x43, 0xE6, 0x91, 0xBE, 0x43, 0xE6, 0x92,
- 0x9A, 0x43, 0xE6, 0x92, 0x9D, 0x43, 0xE6, 0x93,
- // Bytes d00 - d3f
- 0x84, 0x43, 0xE6, 0x94, 0xAF, 0x43, 0xE6, 0x94,
- 0xB4, 0x43, 0xE6, 0x95, 0x8F, 0x43, 0xE6, 0x95,
- 0x96, 0x43, 0xE6, 0x95, 0xAC, 0x43, 0xE6, 0x95,
- 0xB8, 0x43, 0xE6, 0x96, 0x87, 0x43, 0xE6, 0x96,
- 0x97, 0x43, 0xE6, 0x96, 0x99, 0x43, 0xE6, 0x96,
- 0xA4, 0x43, 0xE6, 0x96, 0xB0, 0x43, 0xE6, 0x96,
- 0xB9, 0x43, 0xE6, 0x97, 0x85, 0x43, 0xE6, 0x97,
- 0xA0, 0x43, 0xE6, 0x97, 0xA2, 0x43, 0xE6, 0x97,
- // Bytes d40 - d7f
- 0xA3, 0x43, 0xE6, 0x97, 0xA5, 0x43, 0xE6, 0x98,
- 0x93, 0x43, 0xE6, 0x98, 0xA0, 0x43, 0xE6, 0x99,
- 0x89, 0x43, 0xE6, 0x99, 0xB4, 0x43, 0xE6, 0x9A,
- 0x88, 0x43, 0xE6, 0x9A, 0x91, 0x43, 0xE6, 0x9A,
- 0x9C, 0x43, 0xE6, 0x9A, 0xB4, 0x43, 0xE6, 0x9B,
- 0x86, 0x43, 0xE6, 0x9B, 0xB0, 0x43, 0xE6, 0x9B,
- 0xB4, 0x43, 0xE6, 0x9B, 0xB8, 0x43, 0xE6, 0x9C,
- 0x80, 0x43, 0xE6, 0x9C, 0x88, 0x43, 0xE6, 0x9C,
- // Bytes d80 - dbf
- 0x89, 0x43, 0xE6, 0x9C, 0x97, 0x43, 0xE6, 0x9C,
- 0x9B, 0x43, 0xE6, 0x9C, 0xA1, 0x43, 0xE6, 0x9C,
- 0xA8, 0x43, 0xE6, 0x9D, 0x8E, 0x43, 0xE6, 0x9D,
- 0x93, 0x43, 0xE6, 0x9D, 0x96, 0x43, 0xE6, 0x9D,
- 0x9E, 0x43, 0xE6, 0x9D, 0xBB, 0x43, 0xE6, 0x9E,
- 0x85, 0x43, 0xE6, 0x9E, 0x97, 0x43, 0xE6, 0x9F,
- 0xB3, 0x43, 0xE6, 0x9F, 0xBA, 0x43, 0xE6, 0xA0,
- 0x97, 0x43, 0xE6, 0xA0, 0x9F, 0x43, 0xE6, 0xA0,
- // Bytes dc0 - dff
- 0xAA, 0x43, 0xE6, 0xA1, 0x92, 0x43, 0xE6, 0xA2,
- 0x81, 0x43, 0xE6, 0xA2, 0x85, 0x43, 0xE6, 0xA2,
- 0x8E, 0x43, 0xE6, 0xA2, 0xA8, 0x43, 0xE6, 0xA4,
- 0x94, 0x43, 0xE6, 0xA5, 0x82, 0x43, 0xE6, 0xA6,
- 0xA3, 0x43, 0xE6, 0xA7, 0xAA, 0x43, 0xE6, 0xA8,
- 0x82, 0x43, 0xE6, 0xA8, 0x93, 0x43, 0xE6, 0xAA,
- 0xA8, 0x43, 0xE6, 0xAB, 0x93, 0x43, 0xE6, 0xAB,
- 0x9B, 0x43, 0xE6, 0xAC, 0x84, 0x43, 0xE6, 0xAC,
- // Bytes e00 - e3f
- 0xA0, 0x43, 0xE6, 0xAC, 0xA1, 0x43, 0xE6, 0xAD,
- 0x94, 0x43, 0xE6, 0xAD, 0xA2, 0x43, 0xE6, 0xAD,
- 0xA3, 0x43, 0xE6, 0xAD, 0xB2, 0x43, 0xE6, 0xAD,
- 0xB7, 0x43, 0xE6, 0xAD, 0xB9, 0x43, 0xE6, 0xAE,
- 0x9F, 0x43, 0xE6, 0xAE, 0xAE, 0x43, 0xE6, 0xAE,
- 0xB3, 0x43, 0xE6, 0xAE, 0xBA, 0x43, 0xE6, 0xAE,
- 0xBB, 0x43, 0xE6, 0xAF, 0x8B, 0x43, 0xE6, 0xAF,
- 0x8D, 0x43, 0xE6, 0xAF, 0x94, 0x43, 0xE6, 0xAF,
- // Bytes e40 - e7f
- 0x9B, 0x43, 0xE6, 0xB0, 0x8F, 0x43, 0xE6, 0xB0,
- 0x94, 0x43, 0xE6, 0xB0, 0xB4, 0x43, 0xE6, 0xB1,
- 0x8E, 0x43, 0xE6, 0xB1, 0xA7, 0x43, 0xE6, 0xB2,
- 0x88, 0x43, 0xE6, 0xB2, 0xBF, 0x43, 0xE6, 0xB3,
- 0x8C, 0x43, 0xE6, 0xB3, 0x8D, 0x43, 0xE6, 0xB3,
- 0xA5, 0x43, 0xE6, 0xB3, 0xA8, 0x43, 0xE6, 0xB4,
- 0x96, 0x43, 0xE6, 0xB4, 0x9B, 0x43, 0xE6, 0xB4,
- 0x9E, 0x43, 0xE6, 0xB4, 0xB4, 0x43, 0xE6, 0xB4,
- // Bytes e80 - ebf
- 0xBE, 0x43, 0xE6, 0xB5, 0x81, 0x43, 0xE6, 0xB5,
- 0xA9, 0x43, 0xE6, 0xB5, 0xAA, 0x43, 0xE6, 0xB5,
- 0xB7, 0x43, 0xE6, 0xB5, 0xB8, 0x43, 0xE6, 0xB6,
- 0x85, 0x43, 0xE6, 0xB7, 0x8B, 0x43, 0xE6, 0xB7,
- 0x9A, 0x43, 0xE6, 0xB7, 0xAA, 0x43, 0xE6, 0xB7,
- 0xB9, 0x43, 0xE6, 0xB8, 0x9A, 0x43, 0xE6, 0xB8,
- 0xAF, 0x43, 0xE6, 0xB9, 0xAE, 0x43, 0xE6, 0xBA,
- 0x80, 0x43, 0xE6, 0xBA, 0x9C, 0x43, 0xE6, 0xBA,
- // Bytes ec0 - eff
- 0xBA, 0x43, 0xE6, 0xBB, 0x87, 0x43, 0xE6, 0xBB,
- 0x8B, 0x43, 0xE6, 0xBB, 0x91, 0x43, 0xE6, 0xBB,
- 0x9B, 0x43, 0xE6, 0xBC, 0x8F, 0x43, 0xE6, 0xBC,
- 0x94, 0x43, 0xE6, 0xBC, 0xA2, 0x43, 0xE6, 0xBC,
- 0xA3, 0x43, 0xE6, 0xBD, 0xAE, 0x43, 0xE6, 0xBF,
- 0x86, 0x43, 0xE6, 0xBF, 0xAB, 0x43, 0xE6, 0xBF,
- 0xBE, 0x43, 0xE7, 0x80, 0x9B, 0x43, 0xE7, 0x80,
- 0x9E, 0x43, 0xE7, 0x80, 0xB9, 0x43, 0xE7, 0x81,
- // Bytes f00 - f3f
- 0x8A, 0x43, 0xE7, 0x81, 0xAB, 0x43, 0xE7, 0x81,
- 0xB0, 0x43, 0xE7, 0x81, 0xB7, 0x43, 0xE7, 0x81,
- 0xBD, 0x43, 0xE7, 0x82, 0x99, 0x43, 0xE7, 0x82,
- 0xAD, 0x43, 0xE7, 0x83, 0x88, 0x43, 0xE7, 0x83,
- 0x99, 0x43, 0xE7, 0x84, 0xA1, 0x43, 0xE7, 0x85,
- 0x85, 0x43, 0xE7, 0x85, 0x89, 0x43, 0xE7, 0x85,
- 0xAE, 0x43, 0xE7, 0x86, 0x9C, 0x43, 0xE7, 0x87,
- 0x8E, 0x43, 0xE7, 0x87, 0x90, 0x43, 0xE7, 0x88,
- // Bytes f40 - f7f
- 0x90, 0x43, 0xE7, 0x88, 0x9B, 0x43, 0xE7, 0x88,
- 0xA8, 0x43, 0xE7, 0x88, 0xAA, 0x43, 0xE7, 0x88,
- 0xAB, 0x43, 0xE7, 0x88, 0xB5, 0x43, 0xE7, 0x88,
- 0xB6, 0x43, 0xE7, 0x88, 0xBB, 0x43, 0xE7, 0x88,
- 0xBF, 0x43, 0xE7, 0x89, 0x87, 0x43, 0xE7, 0x89,
- 0x90, 0x43, 0xE7, 0x89, 0x99, 0x43, 0xE7, 0x89,
- 0x9B, 0x43, 0xE7, 0x89, 0xA2, 0x43, 0xE7, 0x89,
- 0xB9, 0x43, 0xE7, 0x8A, 0x80, 0x43, 0xE7, 0x8A,
- // Bytes f80 - fbf
- 0x95, 0x43, 0xE7, 0x8A, 0xAC, 0x43, 0xE7, 0x8A,
- 0xAF, 0x43, 0xE7, 0x8B, 0x80, 0x43, 0xE7, 0x8B,
- 0xBC, 0x43, 0xE7, 0x8C, 0xAA, 0x43, 0xE7, 0x8D,
- 0xB5, 0x43, 0xE7, 0x8D, 0xBA, 0x43, 0xE7, 0x8E,
- 0x84, 0x43, 0xE7, 0x8E, 0x87, 0x43, 0xE7, 0x8E,
- 0x89, 0x43, 0xE7, 0x8E, 0x8B, 0x43, 0xE7, 0x8E,
- 0xA5, 0x43, 0xE7, 0x8E, 0xB2, 0x43, 0xE7, 0x8F,
- 0x9E, 0x43, 0xE7, 0x90, 0x86, 0x43, 0xE7, 0x90,
- // Bytes fc0 - fff
- 0x89, 0x43, 0xE7, 0x90, 0xA2, 0x43, 0xE7, 0x91,
- 0x87, 0x43, 0xE7, 0x91, 0x9C, 0x43, 0xE7, 0x91,
- 0xA9, 0x43, 0xE7, 0x91, 0xB1, 0x43, 0xE7, 0x92,
- 0x85, 0x43, 0xE7, 0x92, 0x89, 0x43, 0xE7, 0x92,
- 0x98, 0x43, 0xE7, 0x93, 0x8A, 0x43, 0xE7, 0x93,
- 0x9C, 0x43, 0xE7, 0x93, 0xA6, 0x43, 0xE7, 0x94,
- 0x86, 0x43, 0xE7, 0x94, 0x98, 0x43, 0xE7, 0x94,
- 0x9F, 0x43, 0xE7, 0x94, 0xA4, 0x43, 0xE7, 0x94,
- // Bytes 1000 - 103f
- 0xA8, 0x43, 0xE7, 0x94, 0xB0, 0x43, 0xE7, 0x94,
- 0xB2, 0x43, 0xE7, 0x94, 0xB3, 0x43, 0xE7, 0x94,
- 0xB7, 0x43, 0xE7, 0x94, 0xBB, 0x43, 0xE7, 0x94,
- 0xBE, 0x43, 0xE7, 0x95, 0x99, 0x43, 0xE7, 0x95,
- 0xA5, 0x43, 0xE7, 0x95, 0xB0, 0x43, 0xE7, 0x96,
- 0x8B, 0x43, 0xE7, 0x96, 0x92, 0x43, 0xE7, 0x97,
- 0xA2, 0x43, 0xE7, 0x98, 0x90, 0x43, 0xE7, 0x98,
- 0x9D, 0x43, 0xE7, 0x98, 0x9F, 0x43, 0xE7, 0x99,
- // Bytes 1040 - 107f
- 0x82, 0x43, 0xE7, 0x99, 0xA9, 0x43, 0xE7, 0x99,
- 0xB6, 0x43, 0xE7, 0x99, 0xBD, 0x43, 0xE7, 0x9A,
- 0xAE, 0x43, 0xE7, 0x9A, 0xBF, 0x43, 0xE7, 0x9B,
- 0x8A, 0x43, 0xE7, 0x9B, 0x9B, 0x43, 0xE7, 0x9B,
- 0xA3, 0x43, 0xE7, 0x9B, 0xA7, 0x43, 0xE7, 0x9B,
- 0xAE, 0x43, 0xE7, 0x9B, 0xB4, 0x43, 0xE7, 0x9C,
- 0x81, 0x43, 0xE7, 0x9C, 0x9E, 0x43, 0xE7, 0x9C,
- 0x9F, 0x43, 0xE7, 0x9D, 0x80, 0x43, 0xE7, 0x9D,
- // Bytes 1080 - 10bf
- 0x8A, 0x43, 0xE7, 0x9E, 0x8B, 0x43, 0xE7, 0x9E,
- 0xA7, 0x43, 0xE7, 0x9F, 0x9B, 0x43, 0xE7, 0x9F,
- 0xA2, 0x43, 0xE7, 0x9F, 0xB3, 0x43, 0xE7, 0xA1,
- 0x8E, 0x43, 0xE7, 0xA1, 0xAB, 0x43, 0xE7, 0xA2,
- 0x8C, 0x43, 0xE7, 0xA2, 0x91, 0x43, 0xE7, 0xA3,
- 0x8A, 0x43, 0xE7, 0xA3, 0x8C, 0x43, 0xE7, 0xA3,
- 0xBB, 0x43, 0xE7, 0xA4, 0xAA, 0x43, 0xE7, 0xA4,
- 0xBA, 0x43, 0xE7, 0xA4, 0xBC, 0x43, 0xE7, 0xA4,
- // Bytes 10c0 - 10ff
- 0xBE, 0x43, 0xE7, 0xA5, 0x88, 0x43, 0xE7, 0xA5,
- 0x89, 0x43, 0xE7, 0xA5, 0x90, 0x43, 0xE7, 0xA5,
- 0x96, 0x43, 0xE7, 0xA5, 0x9D, 0x43, 0xE7, 0xA5,
- 0x9E, 0x43, 0xE7, 0xA5, 0xA5, 0x43, 0xE7, 0xA5,
- 0xBF, 0x43, 0xE7, 0xA6, 0x81, 0x43, 0xE7, 0xA6,
- 0x8D, 0x43, 0xE7, 0xA6, 0x8E, 0x43, 0xE7, 0xA6,
- 0x8F, 0x43, 0xE7, 0xA6, 0xAE, 0x43, 0xE7, 0xA6,
- 0xB8, 0x43, 0xE7, 0xA6, 0xBE, 0x43, 0xE7, 0xA7,
- // Bytes 1100 - 113f
- 0x8A, 0x43, 0xE7, 0xA7, 0x98, 0x43, 0xE7, 0xA7,
- 0xAB, 0x43, 0xE7, 0xA8, 0x9C, 0x43, 0xE7, 0xA9,
- 0x80, 0x43, 0xE7, 0xA9, 0x8A, 0x43, 0xE7, 0xA9,
- 0x8F, 0x43, 0xE7, 0xA9, 0xB4, 0x43, 0xE7, 0xA9,
- 0xBA, 0x43, 0xE7, 0xAA, 0x81, 0x43, 0xE7, 0xAA,
- 0xB1, 0x43, 0xE7, 0xAB, 0x8B, 0x43, 0xE7, 0xAB,
- 0xAE, 0x43, 0xE7, 0xAB, 0xB9, 0x43, 0xE7, 0xAC,
- 0xA0, 0x43, 0xE7, 0xAE, 0x8F, 0x43, 0xE7, 0xAF,
- // Bytes 1140 - 117f
- 0x80, 0x43, 0xE7, 0xAF, 0x86, 0x43, 0xE7, 0xAF,
- 0x89, 0x43, 0xE7, 0xB0, 0xBE, 0x43, 0xE7, 0xB1,
- 0xA0, 0x43, 0xE7, 0xB1, 0xB3, 0x43, 0xE7, 0xB1,
- 0xBB, 0x43, 0xE7, 0xB2, 0x92, 0x43, 0xE7, 0xB2,
- 0xBE, 0x43, 0xE7, 0xB3, 0x92, 0x43, 0xE7, 0xB3,
- 0x96, 0x43, 0xE7, 0xB3, 0xA3, 0x43, 0xE7, 0xB3,
- 0xA7, 0x43, 0xE7, 0xB3, 0xA8, 0x43, 0xE7, 0xB3,
- 0xB8, 0x43, 0xE7, 0xB4, 0x80, 0x43, 0xE7, 0xB4,
- // Bytes 1180 - 11bf
- 0x90, 0x43, 0xE7, 0xB4, 0xA2, 0x43, 0xE7, 0xB4,
- 0xAF, 0x43, 0xE7, 0xB5, 0x82, 0x43, 0xE7, 0xB5,
- 0x9B, 0x43, 0xE7, 0xB5, 0xA3, 0x43, 0xE7, 0xB6,
- 0xA0, 0x43, 0xE7, 0xB6, 0xBE, 0x43, 0xE7, 0xB7,
- 0x87, 0x43, 0xE7, 0xB7, 0xB4, 0x43, 0xE7, 0xB8,
- 0x82, 0x43, 0xE7, 0xB8, 0x89, 0x43, 0xE7, 0xB8,
- 0xB7, 0x43, 0xE7, 0xB9, 0x81, 0x43, 0xE7, 0xB9,
- 0x85, 0x43, 0xE7, 0xBC, 0xB6, 0x43, 0xE7, 0xBC,
- // Bytes 11c0 - 11ff
- 0xBE, 0x43, 0xE7, 0xBD, 0x91, 0x43, 0xE7, 0xBD,
- 0xB2, 0x43, 0xE7, 0xBD, 0xB9, 0x43, 0xE7, 0xBD,
- 0xBA, 0x43, 0xE7, 0xBE, 0x85, 0x43, 0xE7, 0xBE,
- 0x8A, 0x43, 0xE7, 0xBE, 0x95, 0x43, 0xE7, 0xBE,
- 0x9A, 0x43, 0xE7, 0xBE, 0xBD, 0x43, 0xE7, 0xBF,
- 0xBA, 0x43, 0xE8, 0x80, 0x81, 0x43, 0xE8, 0x80,
- 0x85, 0x43, 0xE8, 0x80, 0x8C, 0x43, 0xE8, 0x80,
- 0x92, 0x43, 0xE8, 0x80, 0xB3, 0x43, 0xE8, 0x81,
- // Bytes 1200 - 123f
- 0x86, 0x43, 0xE8, 0x81, 0xA0, 0x43, 0xE8, 0x81,
- 0xAF, 0x43, 0xE8, 0x81, 0xB0, 0x43, 0xE8, 0x81,
- 0xBE, 0x43, 0xE8, 0x81, 0xBF, 0x43, 0xE8, 0x82,
- 0x89, 0x43, 0xE8, 0x82, 0x8B, 0x43, 0xE8, 0x82,
- 0xAD, 0x43, 0xE8, 0x82, 0xB2, 0x43, 0xE8, 0x84,
- 0x83, 0x43, 0xE8, 0x84, 0xBE, 0x43, 0xE8, 0x87,
- 0x98, 0x43, 0xE8, 0x87, 0xA3, 0x43, 0xE8, 0x87,
- 0xA8, 0x43, 0xE8, 0x87, 0xAA, 0x43, 0xE8, 0x87,
- // Bytes 1240 - 127f
- 0xAD, 0x43, 0xE8, 0x87, 0xB3, 0x43, 0xE8, 0x87,
- 0xBC, 0x43, 0xE8, 0x88, 0x81, 0x43, 0xE8, 0x88,
- 0x84, 0x43, 0xE8, 0x88, 0x8C, 0x43, 0xE8, 0x88,
- 0x98, 0x43, 0xE8, 0x88, 0x9B, 0x43, 0xE8, 0x88,
- 0x9F, 0x43, 0xE8, 0x89, 0xAE, 0x43, 0xE8, 0x89,
- 0xAF, 0x43, 0xE8, 0x89, 0xB2, 0x43, 0xE8, 0x89,
- 0xB8, 0x43, 0xE8, 0x89, 0xB9, 0x43, 0xE8, 0x8A,
- 0x8B, 0x43, 0xE8, 0x8A, 0x91, 0x43, 0xE8, 0x8A,
- // Bytes 1280 - 12bf
- 0x9D, 0x43, 0xE8, 0x8A, 0xB1, 0x43, 0xE8, 0x8A,
- 0xB3, 0x43, 0xE8, 0x8A, 0xBD, 0x43, 0xE8, 0x8B,
- 0xA5, 0x43, 0xE8, 0x8B, 0xA6, 0x43, 0xE8, 0x8C,
- 0x9D, 0x43, 0xE8, 0x8C, 0xA3, 0x43, 0xE8, 0x8C,
- 0xB6, 0x43, 0xE8, 0x8D, 0x92, 0x43, 0xE8, 0x8D,
- 0x93, 0x43, 0xE8, 0x8D, 0xA3, 0x43, 0xE8, 0x8E,
- 0xAD, 0x43, 0xE8, 0x8E, 0xBD, 0x43, 0xE8, 0x8F,
- 0x89, 0x43, 0xE8, 0x8F, 0x8A, 0x43, 0xE8, 0x8F,
- // Bytes 12c0 - 12ff
- 0x8C, 0x43, 0xE8, 0x8F, 0x9C, 0x43, 0xE8, 0x8F,
- 0xA7, 0x43, 0xE8, 0x8F, 0xAF, 0x43, 0xE8, 0x8F,
- 0xB1, 0x43, 0xE8, 0x90, 0xBD, 0x43, 0xE8, 0x91,
- 0x89, 0x43, 0xE8, 0x91, 0x97, 0x43, 0xE8, 0x93,
- 0xAE, 0x43, 0xE8, 0x93, 0xB1, 0x43, 0xE8, 0x93,
- 0xB3, 0x43, 0xE8, 0x93, 0xBC, 0x43, 0xE8, 0x94,
- 0x96, 0x43, 0xE8, 0x95, 0xA4, 0x43, 0xE8, 0x97,
- 0x8D, 0x43, 0xE8, 0x97, 0xBA, 0x43, 0xE8, 0x98,
- // Bytes 1300 - 133f
- 0x86, 0x43, 0xE8, 0x98, 0x92, 0x43, 0xE8, 0x98,
- 0xAD, 0x43, 0xE8, 0x98, 0xBF, 0x43, 0xE8, 0x99,
- 0x8D, 0x43, 0xE8, 0x99, 0x90, 0x43, 0xE8, 0x99,
- 0x9C, 0x43, 0xE8, 0x99, 0xA7, 0x43, 0xE8, 0x99,
- 0xA9, 0x43, 0xE8, 0x99, 0xAB, 0x43, 0xE8, 0x9A,
- 0x88, 0x43, 0xE8, 0x9A, 0xA9, 0x43, 0xE8, 0x9B,
- 0xA2, 0x43, 0xE8, 0x9C, 0x8E, 0x43, 0xE8, 0x9C,
- 0xA8, 0x43, 0xE8, 0x9D, 0xAB, 0x43, 0xE8, 0x9D,
- // Bytes 1340 - 137f
- 0xB9, 0x43, 0xE8, 0x9E, 0x86, 0x43, 0xE8, 0x9E,
- 0xBA, 0x43, 0xE8, 0x9F, 0xA1, 0x43, 0xE8, 0xA0,
- 0x81, 0x43, 0xE8, 0xA0, 0x9F, 0x43, 0xE8, 0xA1,
- 0x80, 0x43, 0xE8, 0xA1, 0x8C, 0x43, 0xE8, 0xA1,
- 0xA0, 0x43, 0xE8, 0xA1, 0xA3, 0x43, 0xE8, 0xA3,
- 0x82, 0x43, 0xE8, 0xA3, 0x8F, 0x43, 0xE8, 0xA3,
- 0x97, 0x43, 0xE8, 0xA3, 0x9E, 0x43, 0xE8, 0xA3,
- 0xA1, 0x43, 0xE8, 0xA3, 0xB8, 0x43, 0xE8, 0xA3,
- // Bytes 1380 - 13bf
- 0xBA, 0x43, 0xE8, 0xA4, 0x90, 0x43, 0xE8, 0xA5,
- 0x81, 0x43, 0xE8, 0xA5, 0xA4, 0x43, 0xE8, 0xA5,
- 0xBE, 0x43, 0xE8, 0xA6, 0x86, 0x43, 0xE8, 0xA6,
- 0x8B, 0x43, 0xE8, 0xA6, 0x96, 0x43, 0xE8, 0xA7,
- 0x92, 0x43, 0xE8, 0xA7, 0xA3, 0x43, 0xE8, 0xA8,
- 0x80, 0x43, 0xE8, 0xAA, 0xA0, 0x43, 0xE8, 0xAA,
- 0xAA, 0x43, 0xE8, 0xAA, 0xBF, 0x43, 0xE8, 0xAB,
- 0x8B, 0x43, 0xE8, 0xAB, 0x92, 0x43, 0xE8, 0xAB,
- // Bytes 13c0 - 13ff
- 0x96, 0x43, 0xE8, 0xAB, 0xAD, 0x43, 0xE8, 0xAB,
- 0xB8, 0x43, 0xE8, 0xAB, 0xBE, 0x43, 0xE8, 0xAC,
- 0x81, 0x43, 0xE8, 0xAC, 0xB9, 0x43, 0xE8, 0xAD,
- 0x98, 0x43, 0xE8, 0xAE, 0x80, 0x43, 0xE8, 0xAE,
- 0x8A, 0x43, 0xE8, 0xB0, 0xB7, 0x43, 0xE8, 0xB1,
- 0x86, 0x43, 0xE8, 0xB1, 0x88, 0x43, 0xE8, 0xB1,
- 0x95, 0x43, 0xE8, 0xB1, 0xB8, 0x43, 0xE8, 0xB2,
- 0x9D, 0x43, 0xE8, 0xB2, 0xA1, 0x43, 0xE8, 0xB2,
- // Bytes 1400 - 143f
- 0xA9, 0x43, 0xE8, 0xB2, 0xAB, 0x43, 0xE8, 0xB3,
- 0x81, 0x43, 0xE8, 0xB3, 0x82, 0x43, 0xE8, 0xB3,
- 0x87, 0x43, 0xE8, 0xB3, 0x88, 0x43, 0xE8, 0xB3,
- 0x93, 0x43, 0xE8, 0xB4, 0x88, 0x43, 0xE8, 0xB4,
- 0x9B, 0x43, 0xE8, 0xB5, 0xA4, 0x43, 0xE8, 0xB5,
- 0xB0, 0x43, 0xE8, 0xB5, 0xB7, 0x43, 0xE8, 0xB6,
- 0xB3, 0x43, 0xE8, 0xB6, 0xBC, 0x43, 0xE8, 0xB7,
- 0x8B, 0x43, 0xE8, 0xB7, 0xAF, 0x43, 0xE8, 0xB7,
- // Bytes 1440 - 147f
- 0xB0, 0x43, 0xE8, 0xBA, 0xAB, 0x43, 0xE8, 0xBB,
- 0x8A, 0x43, 0xE8, 0xBB, 0x94, 0x43, 0xE8, 0xBC,
- 0xA6, 0x43, 0xE8, 0xBC, 0xAA, 0x43, 0xE8, 0xBC,
- 0xB8, 0x43, 0xE8, 0xBC, 0xBB, 0x43, 0xE8, 0xBD,
- 0xA2, 0x43, 0xE8, 0xBE, 0x9B, 0x43, 0xE8, 0xBE,
- 0x9E, 0x43, 0xE8, 0xBE, 0xB0, 0x43, 0xE8, 0xBE,
- 0xB5, 0x43, 0xE8, 0xBE, 0xB6, 0x43, 0xE9, 0x80,
- 0xA3, 0x43, 0xE9, 0x80, 0xB8, 0x43, 0xE9, 0x81,
- // Bytes 1480 - 14bf
- 0x8A, 0x43, 0xE9, 0x81, 0xA9, 0x43, 0xE9, 0x81,
- 0xB2, 0x43, 0xE9, 0x81, 0xBC, 0x43, 0xE9, 0x82,
- 0x8F, 0x43, 0xE9, 0x82, 0x91, 0x43, 0xE9, 0x82,
- 0x94, 0x43, 0xE9, 0x83, 0x8E, 0x43, 0xE9, 0x83,
- 0x9E, 0x43, 0xE9, 0x83, 0xB1, 0x43, 0xE9, 0x83,
- 0xBD, 0x43, 0xE9, 0x84, 0x91, 0x43, 0xE9, 0x84,
- 0x9B, 0x43, 0xE9, 0x85, 0x89, 0x43, 0xE9, 0x85,
- 0xAA, 0x43, 0xE9, 0x86, 0x99, 0x43, 0xE9, 0x86,
- // Bytes 14c0 - 14ff
- 0xB4, 0x43, 0xE9, 0x87, 0x86, 0x43, 0xE9, 0x87,
- 0x8C, 0x43, 0xE9, 0x87, 0x8F, 0x43, 0xE9, 0x87,
- 0x91, 0x43, 0xE9, 0x88, 0xB4, 0x43, 0xE9, 0x88,
- 0xB8, 0x43, 0xE9, 0x89, 0xB6, 0x43, 0xE9, 0x89,
- 0xBC, 0x43, 0xE9, 0x8B, 0x97, 0x43, 0xE9, 0x8B,
- 0x98, 0x43, 0xE9, 0x8C, 0x84, 0x43, 0xE9, 0x8D,
- 0x8A, 0x43, 0xE9, 0x8F, 0xB9, 0x43, 0xE9, 0x90,
- 0x95, 0x43, 0xE9, 0x95, 0xB7, 0x43, 0xE9, 0x96,
- // Bytes 1500 - 153f
- 0x80, 0x43, 0xE9, 0x96, 0x8B, 0x43, 0xE9, 0x96,
- 0xAD, 0x43, 0xE9, 0x96, 0xB7, 0x43, 0xE9, 0x98,
- 0x9C, 0x43, 0xE9, 0x98, 0xAE, 0x43, 0xE9, 0x99,
- 0x8B, 0x43, 0xE9, 0x99, 0x8D, 0x43, 0xE9, 0x99,
- 0xB5, 0x43, 0xE9, 0x99, 0xB8, 0x43, 0xE9, 0x99,
- 0xBC, 0x43, 0xE9, 0x9A, 0x86, 0x43, 0xE9, 0x9A,
- 0xA3, 0x43, 0xE9, 0x9A, 0xB6, 0x43, 0xE9, 0x9A,
- 0xB7, 0x43, 0xE9, 0x9A, 0xB8, 0x43, 0xE9, 0x9A,
- // Bytes 1540 - 157f
- 0xB9, 0x43, 0xE9, 0x9B, 0x83, 0x43, 0xE9, 0x9B,
- 0xA2, 0x43, 0xE9, 0x9B, 0xA3, 0x43, 0xE9, 0x9B,
- 0xA8, 0x43, 0xE9, 0x9B, 0xB6, 0x43, 0xE9, 0x9B,
- 0xB7, 0x43, 0xE9, 0x9C, 0xA3, 0x43, 0xE9, 0x9C,
- 0xB2, 0x43, 0xE9, 0x9D, 0x88, 0x43, 0xE9, 0x9D,
- 0x91, 0x43, 0xE9, 0x9D, 0x96, 0x43, 0xE9, 0x9D,
- 0x9E, 0x43, 0xE9, 0x9D, 0xA2, 0x43, 0xE9, 0x9D,
- 0xA9, 0x43, 0xE9, 0x9F, 0x8B, 0x43, 0xE9, 0x9F,
- // Bytes 1580 - 15bf
- 0x9B, 0x43, 0xE9, 0x9F, 0xA0, 0x43, 0xE9, 0x9F,
- 0xAD, 0x43, 0xE9, 0x9F, 0xB3, 0x43, 0xE9, 0x9F,
- 0xBF, 0x43, 0xE9, 0xA0, 0x81, 0x43, 0xE9, 0xA0,
- 0x85, 0x43, 0xE9, 0xA0, 0x8B, 0x43, 0xE9, 0xA0,
- 0x98, 0x43, 0xE9, 0xA0, 0xA9, 0x43, 0xE9, 0xA0,
- 0xBB, 0x43, 0xE9, 0xA1, 0x9E, 0x43, 0xE9, 0xA2,
- 0xA8, 0x43, 0xE9, 0xA3, 0x9B, 0x43, 0xE9, 0xA3,
- 0x9F, 0x43, 0xE9, 0xA3, 0xA2, 0x43, 0xE9, 0xA3,
- // Bytes 15c0 - 15ff
- 0xAF, 0x43, 0xE9, 0xA3, 0xBC, 0x43, 0xE9, 0xA4,
- 0xA8, 0x43, 0xE9, 0xA4, 0xA9, 0x43, 0xE9, 0xA6,
- 0x96, 0x43, 0xE9, 0xA6, 0x99, 0x43, 0xE9, 0xA6,
- 0xA7, 0x43, 0xE9, 0xA6, 0xAC, 0x43, 0xE9, 0xA7,
- 0x82, 0x43, 0xE9, 0xA7, 0xB1, 0x43, 0xE9, 0xA7,
- 0xBE, 0x43, 0xE9, 0xA9, 0xAA, 0x43, 0xE9, 0xAA,
- 0xA8, 0x43, 0xE9, 0xAB, 0x98, 0x43, 0xE9, 0xAB,
- 0x9F, 0x43, 0xE9, 0xAC, 0x92, 0x43, 0xE9, 0xAC,
- // Bytes 1600 - 163f
- 0xA5, 0x43, 0xE9, 0xAC, 0xAF, 0x43, 0xE9, 0xAC,
- 0xB2, 0x43, 0xE9, 0xAC, 0xBC, 0x43, 0xE9, 0xAD,
- 0x9A, 0x43, 0xE9, 0xAD, 0xAF, 0x43, 0xE9, 0xB1,
- 0x80, 0x43, 0xE9, 0xB1, 0x97, 0x43, 0xE9, 0xB3,
- 0xA5, 0x43, 0xE9, 0xB3, 0xBD, 0x43, 0xE9, 0xB5,
- 0xA7, 0x43, 0xE9, 0xB6, 0xB4, 0x43, 0xE9, 0xB7,
- 0xBA, 0x43, 0xE9, 0xB8, 0x9E, 0x43, 0xE9, 0xB9,
- 0xB5, 0x43, 0xE9, 0xB9, 0xBF, 0x43, 0xE9, 0xBA,
- // Bytes 1640 - 167f
- 0x97, 0x43, 0xE9, 0xBA, 0x9F, 0x43, 0xE9, 0xBA,
- 0xA5, 0x43, 0xE9, 0xBA, 0xBB, 0x43, 0xE9, 0xBB,
- 0x83, 0x43, 0xE9, 0xBB, 0x8D, 0x43, 0xE9, 0xBB,
- 0x8E, 0x43, 0xE9, 0xBB, 0x91, 0x43, 0xE9, 0xBB,
- 0xB9, 0x43, 0xE9, 0xBB, 0xBD, 0x43, 0xE9, 0xBB,
- 0xBE, 0x43, 0xE9, 0xBC, 0x85, 0x43, 0xE9, 0xBC,
- 0x8E, 0x43, 0xE9, 0xBC, 0x8F, 0x43, 0xE9, 0xBC,
- 0x93, 0x43, 0xE9, 0xBC, 0x96, 0x43, 0xE9, 0xBC,
- // Bytes 1680 - 16bf
- 0xA0, 0x43, 0xE9, 0xBC, 0xBB, 0x43, 0xE9, 0xBD,
- 0x83, 0x43, 0xE9, 0xBD, 0x8A, 0x43, 0xE9, 0xBD,
- 0x92, 0x43, 0xE9, 0xBE, 0x8D, 0x43, 0xE9, 0xBE,
- 0x8E, 0x43, 0xE9, 0xBE, 0x9C, 0x43, 0xE9, 0xBE,
- 0x9F, 0x43, 0xE9, 0xBE, 0xA0, 0x43, 0xEA, 0x9D,
- 0xAF, 0x44, 0xF0, 0xA0, 0x84, 0xA2, 0x44, 0xF0,
- 0xA0, 0x94, 0x9C, 0x44, 0xF0, 0xA0, 0x94, 0xA5,
- 0x44, 0xF0, 0xA0, 0x95, 0x8B, 0x44, 0xF0, 0xA0,
- // Bytes 16c0 - 16ff
- 0x98, 0xBA, 0x44, 0xF0, 0xA0, 0xA0, 0x84, 0x44,
- 0xF0, 0xA0, 0xA3, 0x9E, 0x44, 0xF0, 0xA0, 0xA8,
- 0xAC, 0x44, 0xF0, 0xA0, 0xAD, 0xA3, 0x44, 0xF0,
- 0xA1, 0x93, 0xA4, 0x44, 0xF0, 0xA1, 0x9A, 0xA8,
- 0x44, 0xF0, 0xA1, 0x9B, 0xAA, 0x44, 0xF0, 0xA1,
- 0xA7, 0x88, 0x44, 0xF0, 0xA1, 0xAC, 0x98, 0x44,
- 0xF0, 0xA1, 0xB4, 0x8B, 0x44, 0xF0, 0xA1, 0xB7,
- 0xA4, 0x44, 0xF0, 0xA1, 0xB7, 0xA6, 0x44, 0xF0,
- // Bytes 1700 - 173f
- 0xA2, 0x86, 0x83, 0x44, 0xF0, 0xA2, 0x86, 0x9F,
- 0x44, 0xF0, 0xA2, 0x8C, 0xB1, 0x44, 0xF0, 0xA2,
- 0x9B, 0x94, 0x44, 0xF0, 0xA2, 0xA1, 0x84, 0x44,
- 0xF0, 0xA2, 0xA1, 0x8A, 0x44, 0xF0, 0xA2, 0xAC,
- 0x8C, 0x44, 0xF0, 0xA2, 0xAF, 0xB1, 0x44, 0xF0,
- 0xA3, 0x80, 0x8A, 0x44, 0xF0, 0xA3, 0x8A, 0xB8,
- 0x44, 0xF0, 0xA3, 0x8D, 0x9F, 0x44, 0xF0, 0xA3,
- 0x8E, 0x93, 0x44, 0xF0, 0xA3, 0x8E, 0x9C, 0x44,
- // Bytes 1740 - 177f
- 0xF0, 0xA3, 0x8F, 0x83, 0x44, 0xF0, 0xA3, 0x8F,
- 0x95, 0x44, 0xF0, 0xA3, 0x91, 0xAD, 0x44, 0xF0,
- 0xA3, 0x9A, 0xA3, 0x44, 0xF0, 0xA3, 0xA2, 0xA7,
- 0x44, 0xF0, 0xA3, 0xAA, 0x8D, 0x44, 0xF0, 0xA3,
- 0xAB, 0xBA, 0x44, 0xF0, 0xA3, 0xB2, 0xBC, 0x44,
- 0xF0, 0xA3, 0xB4, 0x9E, 0x44, 0xF0, 0xA3, 0xBB,
- 0x91, 0x44, 0xF0, 0xA3, 0xBD, 0x9E, 0x44, 0xF0,
- 0xA3, 0xBE, 0x8E, 0x44, 0xF0, 0xA4, 0x89, 0xA3,
- // Bytes 1780 - 17bf
- 0x44, 0xF0, 0xA4, 0x8B, 0xAE, 0x44, 0xF0, 0xA4,
- 0x8E, 0xAB, 0x44, 0xF0, 0xA4, 0x98, 0x88, 0x44,
- 0xF0, 0xA4, 0x9C, 0xB5, 0x44, 0xF0, 0xA4, 0xA0,
- 0x94, 0x44, 0xF0, 0xA4, 0xB0, 0xB6, 0x44, 0xF0,
- 0xA4, 0xB2, 0x92, 0x44, 0xF0, 0xA4, 0xBE, 0xA1,
- 0x44, 0xF0, 0xA4, 0xBE, 0xB8, 0x44, 0xF0, 0xA5,
- 0x81, 0x84, 0x44, 0xF0, 0xA5, 0x83, 0xB2, 0x44,
- 0xF0, 0xA5, 0x83, 0xB3, 0x44, 0xF0, 0xA5, 0x84,
- // Bytes 17c0 - 17ff
- 0x99, 0x44, 0xF0, 0xA5, 0x84, 0xB3, 0x44, 0xF0,
- 0xA5, 0x89, 0x89, 0x44, 0xF0, 0xA5, 0x90, 0x9D,
- 0x44, 0xF0, 0xA5, 0x98, 0xA6, 0x44, 0xF0, 0xA5,
- 0x9A, 0x9A, 0x44, 0xF0, 0xA5, 0x9B, 0x85, 0x44,
- 0xF0, 0xA5, 0xA5, 0xBC, 0x44, 0xF0, 0xA5, 0xAA,
- 0xA7, 0x44, 0xF0, 0xA5, 0xAE, 0xAB, 0x44, 0xF0,
- 0xA5, 0xB2, 0x80, 0x44, 0xF0, 0xA5, 0xB3, 0x90,
- 0x44, 0xF0, 0xA5, 0xBE, 0x86, 0x44, 0xF0, 0xA6,
- // Bytes 1800 - 183f
- 0x87, 0x9A, 0x44, 0xF0, 0xA6, 0x88, 0xA8, 0x44,
- 0xF0, 0xA6, 0x89, 0x87, 0x44, 0xF0, 0xA6, 0x8B,
- 0x99, 0x44, 0xF0, 0xA6, 0x8C, 0xBE, 0x44, 0xF0,
- 0xA6, 0x93, 0x9A, 0x44, 0xF0, 0xA6, 0x94, 0xA3,
- 0x44, 0xF0, 0xA6, 0x96, 0xA8, 0x44, 0xF0, 0xA6,
- 0x9E, 0xA7, 0x44, 0xF0, 0xA6, 0x9E, 0xB5, 0x44,
- 0xF0, 0xA6, 0xAC, 0xBC, 0x44, 0xF0, 0xA6, 0xB0,
- 0xB6, 0x44, 0xF0, 0xA6, 0xB3, 0x95, 0x44, 0xF0,
- // Bytes 1840 - 187f
- 0xA6, 0xB5, 0xAB, 0x44, 0xF0, 0xA6, 0xBC, 0xAC,
- 0x44, 0xF0, 0xA6, 0xBE, 0xB1, 0x44, 0xF0, 0xA7,
- 0x83, 0x92, 0x44, 0xF0, 0xA7, 0x8F, 0x8A, 0x44,
- 0xF0, 0xA7, 0x99, 0xA7, 0x44, 0xF0, 0xA7, 0xA2,
- 0xAE, 0x44, 0xF0, 0xA7, 0xA5, 0xA6, 0x44, 0xF0,
- 0xA7, 0xB2, 0xA8, 0x44, 0xF0, 0xA7, 0xBB, 0x93,
- 0x44, 0xF0, 0xA7, 0xBC, 0xAF, 0x44, 0xF0, 0xA8,
- 0x97, 0x92, 0x44, 0xF0, 0xA8, 0x97, 0xAD, 0x44,
- // Bytes 1880 - 18bf
- 0xF0, 0xA8, 0x9C, 0xAE, 0x44, 0xF0, 0xA8, 0xAF,
- 0xBA, 0x44, 0xF0, 0xA8, 0xB5, 0xB7, 0x44, 0xF0,
- 0xA9, 0x85, 0x85, 0x44, 0xF0, 0xA9, 0x87, 0x9F,
- 0x44, 0xF0, 0xA9, 0x88, 0x9A, 0x44, 0xF0, 0xA9,
- 0x90, 0x8A, 0x44, 0xF0, 0xA9, 0x92, 0x96, 0x44,
- 0xF0, 0xA9, 0x96, 0xB6, 0x44, 0xF0, 0xA9, 0xAC,
- 0xB0, 0x44, 0xF0, 0xAA, 0x83, 0x8E, 0x44, 0xF0,
- 0xAA, 0x84, 0x85, 0x44, 0xF0, 0xAA, 0x88, 0x8E,
- // Bytes 18c0 - 18ff
- 0x44, 0xF0, 0xAA, 0x8A, 0x91, 0x44, 0xF0, 0xAA,
- 0x8E, 0x92, 0x44, 0xF0, 0xAA, 0x98, 0x80, 0x06,
- 0xE0, 0xA7, 0x87, 0xE0, 0xA6, 0xBE, 0x06, 0xE0,
- 0xA7, 0x87, 0xE0, 0xA7, 0x97, 0x06, 0xE0, 0xAD,
- 0x87, 0xE0, 0xAC, 0xBE, 0x06, 0xE0, 0xAD, 0x87,
- 0xE0, 0xAD, 0x96, 0x06, 0xE0, 0xAD, 0x87, 0xE0,
- 0xAD, 0x97, 0x06, 0xE0, 0xAE, 0x92, 0xE0, 0xAF,
- 0x97, 0x06, 0xE0, 0xAF, 0x86, 0xE0, 0xAE, 0xBE,
- // Bytes 1900 - 193f
- 0x06, 0xE0, 0xAF, 0x86, 0xE0, 0xAF, 0x97, 0x06,
- 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xBE, 0x06, 0xE0,
- 0xB2, 0xBF, 0xE0, 0xB3, 0x95, 0x06, 0xE0, 0xB3,
- 0x86, 0xE0, 0xB3, 0x95, 0x06, 0xE0, 0xB3, 0x86,
- 0xE0, 0xB3, 0x96, 0x06, 0xE0, 0xB5, 0x86, 0xE0,
- 0xB4, 0xBE, 0x06, 0xE0, 0xB5, 0x86, 0xE0, 0xB5,
- 0x97, 0x06, 0xE0, 0xB5, 0x87, 0xE0, 0xB4, 0xBE,
- 0x06, 0xE0, 0xB7, 0x99, 0xE0, 0xB7, 0x9F, 0x06,
- // Bytes 1940 - 197f
- 0xE1, 0x80, 0xA5, 0xE1, 0x80, 0xAE, 0x06, 0xE1,
- 0xAC, 0x85, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC,
- 0x87, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x89,
- 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x8B, 0xE1,
- 0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x8D, 0xE1, 0xAC,
- 0xB5, 0x06, 0xE1, 0xAC, 0x91, 0xE1, 0xAC, 0xB5,
- 0x06, 0xE1, 0xAC, 0xBA, 0xE1, 0xAC, 0xB5, 0x06,
- 0xE1, 0xAC, 0xBC, 0xE1, 0xAC, 0xB5, 0x06, 0xE1,
- // Bytes 1980 - 19bf
- 0xAC, 0xBE, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC,
- 0xBF, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAD, 0x82,
- 0xE1, 0xAC, 0xB5, 0x08, 0xF0, 0x91, 0x84, 0xB1,
- 0xF0, 0x91, 0x84, 0xA7, 0x08, 0xF0, 0x91, 0x84,
- 0xB2, 0xF0, 0x91, 0x84, 0xA7, 0x09, 0xE0, 0xB3,
- 0x86, 0xE0, 0xB3, 0x82, 0xE0, 0xB3, 0x95, 0x42,
- 0x21, 0x21, 0x42, 0x21, 0x3F, 0x42, 0x2E, 0x2E,
- 0x42, 0x30, 0x2C, 0x42, 0x30, 0x2E, 0x42, 0x31,
- // Bytes 19c0 - 19ff
- 0x2C, 0x42, 0x31, 0x2E, 0x42, 0x31, 0x30, 0x42,
- 0x31, 0x31, 0x42, 0x31, 0x32, 0x42, 0x31, 0x33,
- 0x42, 0x31, 0x34, 0x42, 0x31, 0x35, 0x42, 0x31,
- 0x36, 0x42, 0x31, 0x37, 0x42, 0x31, 0x38, 0x42,
- 0x31, 0x39, 0x42, 0x32, 0x2C, 0x42, 0x32, 0x2E,
- 0x42, 0x32, 0x30, 0x42, 0x32, 0x31, 0x42, 0x32,
- 0x32, 0x42, 0x32, 0x33, 0x42, 0x32, 0x34, 0x42,
- 0x32, 0x35, 0x42, 0x32, 0x36, 0x42, 0x32, 0x37,
- // Bytes 1a00 - 1a3f
- 0x42, 0x32, 0x38, 0x42, 0x32, 0x39, 0x42, 0x33,
- 0x2C, 0x42, 0x33, 0x2E, 0x42, 0x33, 0x30, 0x42,
- 0x33, 0x31, 0x42, 0x33, 0x32, 0x42, 0x33, 0x33,
- 0x42, 0x33, 0x34, 0x42, 0x33, 0x35, 0x42, 0x33,
- 0x36, 0x42, 0x33, 0x37, 0x42, 0x33, 0x38, 0x42,
- 0x33, 0x39, 0x42, 0x34, 0x2C, 0x42, 0x34, 0x2E,
- 0x42, 0x34, 0x30, 0x42, 0x34, 0x31, 0x42, 0x34,
- 0x32, 0x42, 0x34, 0x33, 0x42, 0x34, 0x34, 0x42,
- // Bytes 1a40 - 1a7f
- 0x34, 0x35, 0x42, 0x34, 0x36, 0x42, 0x34, 0x37,
- 0x42, 0x34, 0x38, 0x42, 0x34, 0x39, 0x42, 0x35,
- 0x2C, 0x42, 0x35, 0x2E, 0x42, 0x35, 0x30, 0x42,
- 0x36, 0x2C, 0x42, 0x36, 0x2E, 0x42, 0x37, 0x2C,
- 0x42, 0x37, 0x2E, 0x42, 0x38, 0x2C, 0x42, 0x38,
- 0x2E, 0x42, 0x39, 0x2C, 0x42, 0x39, 0x2E, 0x42,
- 0x3D, 0x3D, 0x42, 0x3F, 0x21, 0x42, 0x3F, 0x3F,
- 0x42, 0x41, 0x55, 0x42, 0x42, 0x71, 0x42, 0x43,
- // Bytes 1a80 - 1abf
- 0x44, 0x42, 0x44, 0x4A, 0x42, 0x44, 0x5A, 0x42,
- 0x44, 0x7A, 0x42, 0x47, 0x42, 0x42, 0x47, 0x79,
- 0x42, 0x48, 0x50, 0x42, 0x48, 0x56, 0x42, 0x48,
- 0x67, 0x42, 0x48, 0x7A, 0x42, 0x49, 0x49, 0x42,
- 0x49, 0x4A, 0x42, 0x49, 0x55, 0x42, 0x49, 0x56,
- 0x42, 0x49, 0x58, 0x42, 0x4B, 0x42, 0x42, 0x4B,
- 0x4B, 0x42, 0x4B, 0x4D, 0x42, 0x4C, 0x4A, 0x42,
- 0x4C, 0x6A, 0x42, 0x4D, 0x42, 0x42, 0x4D, 0x43,
- // Bytes 1ac0 - 1aff
- 0x42, 0x4D, 0x44, 0x42, 0x4D, 0x56, 0x42, 0x4D,
- 0x57, 0x42, 0x4E, 0x4A, 0x42, 0x4E, 0x6A, 0x42,
- 0x4E, 0x6F, 0x42, 0x50, 0x48, 0x42, 0x50, 0x52,
- 0x42, 0x50, 0x61, 0x42, 0x52, 0x73, 0x42, 0x53,
- 0x44, 0x42, 0x53, 0x4D, 0x42, 0x53, 0x53, 0x42,
- 0x53, 0x76, 0x42, 0x54, 0x4D, 0x42, 0x56, 0x49,
- 0x42, 0x57, 0x43, 0x42, 0x57, 0x5A, 0x42, 0x57,
- 0x62, 0x42, 0x58, 0x49, 0x42, 0x63, 0x63, 0x42,
- // Bytes 1b00 - 1b3f
- 0x63, 0x64, 0x42, 0x63, 0x6D, 0x42, 0x64, 0x42,
- 0x42, 0x64, 0x61, 0x42, 0x64, 0x6C, 0x42, 0x64,
- 0x6D, 0x42, 0x64, 0x7A, 0x42, 0x65, 0x56, 0x42,
- 0x66, 0x66, 0x42, 0x66, 0x69, 0x42, 0x66, 0x6C,
- 0x42, 0x66, 0x6D, 0x42, 0x68, 0x61, 0x42, 0x69,
- 0x69, 0x42, 0x69, 0x6A, 0x42, 0x69, 0x6E, 0x42,
- 0x69, 0x76, 0x42, 0x69, 0x78, 0x42, 0x6B, 0x41,
- 0x42, 0x6B, 0x56, 0x42, 0x6B, 0x57, 0x42, 0x6B,
- // Bytes 1b40 - 1b7f
- 0x67, 0x42, 0x6B, 0x6C, 0x42, 0x6B, 0x6D, 0x42,
- 0x6B, 0x74, 0x42, 0x6C, 0x6A, 0x42, 0x6C, 0x6D,
- 0x42, 0x6C, 0x6E, 0x42, 0x6C, 0x78, 0x42, 0x6D,
- 0x32, 0x42, 0x6D, 0x33, 0x42, 0x6D, 0x41, 0x42,
- 0x6D, 0x56, 0x42, 0x6D, 0x57, 0x42, 0x6D, 0x62,
- 0x42, 0x6D, 0x67, 0x42, 0x6D, 0x6C, 0x42, 0x6D,
- 0x6D, 0x42, 0x6D, 0x73, 0x42, 0x6E, 0x41, 0x42,
- 0x6E, 0x46, 0x42, 0x6E, 0x56, 0x42, 0x6E, 0x57,
- // Bytes 1b80 - 1bbf
- 0x42, 0x6E, 0x6A, 0x42, 0x6E, 0x6D, 0x42, 0x6E,
- 0x73, 0x42, 0x6F, 0x56, 0x42, 0x70, 0x41, 0x42,
- 0x70, 0x46, 0x42, 0x70, 0x56, 0x42, 0x70, 0x57,
- 0x42, 0x70, 0x63, 0x42, 0x70, 0x73, 0x42, 0x73,
- 0x72, 0x42, 0x73, 0x74, 0x42, 0x76, 0x69, 0x42,
- 0x78, 0x69, 0x43, 0x28, 0x31, 0x29, 0x43, 0x28,
- 0x32, 0x29, 0x43, 0x28, 0x33, 0x29, 0x43, 0x28,
- 0x34, 0x29, 0x43, 0x28, 0x35, 0x29, 0x43, 0x28,
- // Bytes 1bc0 - 1bff
- 0x36, 0x29, 0x43, 0x28, 0x37, 0x29, 0x43, 0x28,
- 0x38, 0x29, 0x43, 0x28, 0x39, 0x29, 0x43, 0x28,
- 0x41, 0x29, 0x43, 0x28, 0x42, 0x29, 0x43, 0x28,
- 0x43, 0x29, 0x43, 0x28, 0x44, 0x29, 0x43, 0x28,
- 0x45, 0x29, 0x43, 0x28, 0x46, 0x29, 0x43, 0x28,
- 0x47, 0x29, 0x43, 0x28, 0x48, 0x29, 0x43, 0x28,
- 0x49, 0x29, 0x43, 0x28, 0x4A, 0x29, 0x43, 0x28,
- 0x4B, 0x29, 0x43, 0x28, 0x4C, 0x29, 0x43, 0x28,
- // Bytes 1c00 - 1c3f
- 0x4D, 0x29, 0x43, 0x28, 0x4E, 0x29, 0x43, 0x28,
- 0x4F, 0x29, 0x43, 0x28, 0x50, 0x29, 0x43, 0x28,
- 0x51, 0x29, 0x43, 0x28, 0x52, 0x29, 0x43, 0x28,
- 0x53, 0x29, 0x43, 0x28, 0x54, 0x29, 0x43, 0x28,
- 0x55, 0x29, 0x43, 0x28, 0x56, 0x29, 0x43, 0x28,
- 0x57, 0x29, 0x43, 0x28, 0x58, 0x29, 0x43, 0x28,
- 0x59, 0x29, 0x43, 0x28, 0x5A, 0x29, 0x43, 0x28,
- 0x61, 0x29, 0x43, 0x28, 0x62, 0x29, 0x43, 0x28,
- // Bytes 1c40 - 1c7f
- 0x63, 0x29, 0x43, 0x28, 0x64, 0x29, 0x43, 0x28,
- 0x65, 0x29, 0x43, 0x28, 0x66, 0x29, 0x43, 0x28,
- 0x67, 0x29, 0x43, 0x28, 0x68, 0x29, 0x43, 0x28,
- 0x69, 0x29, 0x43, 0x28, 0x6A, 0x29, 0x43, 0x28,
- 0x6B, 0x29, 0x43, 0x28, 0x6C, 0x29, 0x43, 0x28,
- 0x6D, 0x29, 0x43, 0x28, 0x6E, 0x29, 0x43, 0x28,
- 0x6F, 0x29, 0x43, 0x28, 0x70, 0x29, 0x43, 0x28,
- 0x71, 0x29, 0x43, 0x28, 0x72, 0x29, 0x43, 0x28,
- // Bytes 1c80 - 1cbf
- 0x73, 0x29, 0x43, 0x28, 0x74, 0x29, 0x43, 0x28,
- 0x75, 0x29, 0x43, 0x28, 0x76, 0x29, 0x43, 0x28,
- 0x77, 0x29, 0x43, 0x28, 0x78, 0x29, 0x43, 0x28,
- 0x79, 0x29, 0x43, 0x28, 0x7A, 0x29, 0x43, 0x2E,
- 0x2E, 0x2E, 0x43, 0x31, 0x30, 0x2E, 0x43, 0x31,
- 0x31, 0x2E, 0x43, 0x31, 0x32, 0x2E, 0x43, 0x31,
- 0x33, 0x2E, 0x43, 0x31, 0x34, 0x2E, 0x43, 0x31,
- 0x35, 0x2E, 0x43, 0x31, 0x36, 0x2E, 0x43, 0x31,
- // Bytes 1cc0 - 1cff
- 0x37, 0x2E, 0x43, 0x31, 0x38, 0x2E, 0x43, 0x31,
- 0x39, 0x2E, 0x43, 0x32, 0x30, 0x2E, 0x43, 0x3A,
- 0x3A, 0x3D, 0x43, 0x3D, 0x3D, 0x3D, 0x43, 0x43,
- 0x6F, 0x2E, 0x43, 0x46, 0x41, 0x58, 0x43, 0x47,
- 0x48, 0x7A, 0x43, 0x47, 0x50, 0x61, 0x43, 0x49,
- 0x49, 0x49, 0x43, 0x4C, 0x54, 0x44, 0x43, 0x4C,
- 0xC2, 0xB7, 0x43, 0x4D, 0x48, 0x7A, 0x43, 0x4D,
- 0x50, 0x61, 0x43, 0x4D, 0xCE, 0xA9, 0x43, 0x50,
- // Bytes 1d00 - 1d3f
- 0x50, 0x4D, 0x43, 0x50, 0x50, 0x56, 0x43, 0x50,
- 0x54, 0x45, 0x43, 0x54, 0x45, 0x4C, 0x43, 0x54,
- 0x48, 0x7A, 0x43, 0x56, 0x49, 0x49, 0x43, 0x58,
- 0x49, 0x49, 0x43, 0x61, 0x2F, 0x63, 0x43, 0x61,
- 0x2F, 0x73, 0x43, 0x61, 0xCA, 0xBE, 0x43, 0x62,
- 0x61, 0x72, 0x43, 0x63, 0x2F, 0x6F, 0x43, 0x63,
- 0x2F, 0x75, 0x43, 0x63, 0x61, 0x6C, 0x43, 0x63,
- 0x6D, 0x32, 0x43, 0x63, 0x6D, 0x33, 0x43, 0x64,
- // Bytes 1d40 - 1d7f
- 0x6D, 0x32, 0x43, 0x64, 0x6D, 0x33, 0x43, 0x65,
- 0x72, 0x67, 0x43, 0x66, 0x66, 0x69, 0x43, 0x66,
- 0x66, 0x6C, 0x43, 0x67, 0x61, 0x6C, 0x43, 0x68,
- 0x50, 0x61, 0x43, 0x69, 0x69, 0x69, 0x43, 0x6B,
- 0x48, 0x7A, 0x43, 0x6B, 0x50, 0x61, 0x43, 0x6B,
- 0x6D, 0x32, 0x43, 0x6B, 0x6D, 0x33, 0x43, 0x6B,
- 0xCE, 0xA9, 0x43, 0x6C, 0x6F, 0x67, 0x43, 0x6C,
- 0xC2, 0xB7, 0x43, 0x6D, 0x69, 0x6C, 0x43, 0x6D,
- // Bytes 1d80 - 1dbf
- 0x6D, 0x32, 0x43, 0x6D, 0x6D, 0x33, 0x43, 0x6D,
- 0x6F, 0x6C, 0x43, 0x72, 0x61, 0x64, 0x43, 0x76,
- 0x69, 0x69, 0x43, 0x78, 0x69, 0x69, 0x43, 0xC2,
- 0xB0, 0x43, 0x43, 0xC2, 0xB0, 0x46, 0x43, 0xCA,
- 0xBC, 0x6E, 0x43, 0xCE, 0xBC, 0x41, 0x43, 0xCE,
- 0xBC, 0x46, 0x43, 0xCE, 0xBC, 0x56, 0x43, 0xCE,
- 0xBC, 0x57, 0x43, 0xCE, 0xBC, 0x67, 0x43, 0xCE,
- 0xBC, 0x6C, 0x43, 0xCE, 0xBC, 0x6D, 0x43, 0xCE,
- // Bytes 1dc0 - 1dff
- 0xBC, 0x73, 0x44, 0x28, 0x31, 0x30, 0x29, 0x44,
- 0x28, 0x31, 0x31, 0x29, 0x44, 0x28, 0x31, 0x32,
- 0x29, 0x44, 0x28, 0x31, 0x33, 0x29, 0x44, 0x28,
- 0x31, 0x34, 0x29, 0x44, 0x28, 0x31, 0x35, 0x29,
- 0x44, 0x28, 0x31, 0x36, 0x29, 0x44, 0x28, 0x31,
- 0x37, 0x29, 0x44, 0x28, 0x31, 0x38, 0x29, 0x44,
- 0x28, 0x31, 0x39, 0x29, 0x44, 0x28, 0x32, 0x30,
- 0x29, 0x44, 0x30, 0xE7, 0x82, 0xB9, 0x44, 0x31,
- // Bytes 1e00 - 1e3f
- 0xE2, 0x81, 0x84, 0x44, 0x31, 0xE6, 0x97, 0xA5,
- 0x44, 0x31, 0xE6, 0x9C, 0x88, 0x44, 0x31, 0xE7,
- 0x82, 0xB9, 0x44, 0x32, 0xE6, 0x97, 0xA5, 0x44,
- 0x32, 0xE6, 0x9C, 0x88, 0x44, 0x32, 0xE7, 0x82,
- 0xB9, 0x44, 0x33, 0xE6, 0x97, 0xA5, 0x44, 0x33,
- 0xE6, 0x9C, 0x88, 0x44, 0x33, 0xE7, 0x82, 0xB9,
- 0x44, 0x34, 0xE6, 0x97, 0xA5, 0x44, 0x34, 0xE6,
- 0x9C, 0x88, 0x44, 0x34, 0xE7, 0x82, 0xB9, 0x44,
- // Bytes 1e40 - 1e7f
- 0x35, 0xE6, 0x97, 0xA5, 0x44, 0x35, 0xE6, 0x9C,
- 0x88, 0x44, 0x35, 0xE7, 0x82, 0xB9, 0x44, 0x36,
- 0xE6, 0x97, 0xA5, 0x44, 0x36, 0xE6, 0x9C, 0x88,
- 0x44, 0x36, 0xE7, 0x82, 0xB9, 0x44, 0x37, 0xE6,
- 0x97, 0xA5, 0x44, 0x37, 0xE6, 0x9C, 0x88, 0x44,
- 0x37, 0xE7, 0x82, 0xB9, 0x44, 0x38, 0xE6, 0x97,
- 0xA5, 0x44, 0x38, 0xE6, 0x9C, 0x88, 0x44, 0x38,
- 0xE7, 0x82, 0xB9, 0x44, 0x39, 0xE6, 0x97, 0xA5,
- // Bytes 1e80 - 1ebf
- 0x44, 0x39, 0xE6, 0x9C, 0x88, 0x44, 0x39, 0xE7,
- 0x82, 0xB9, 0x44, 0x56, 0x49, 0x49, 0x49, 0x44,
- 0x61, 0x2E, 0x6D, 0x2E, 0x44, 0x6B, 0x63, 0x61,
- 0x6C, 0x44, 0x70, 0x2E, 0x6D, 0x2E, 0x44, 0x76,
- 0x69, 0x69, 0x69, 0x44, 0xD5, 0xA5, 0xD6, 0x82,
- 0x44, 0xD5, 0xB4, 0xD5, 0xA5, 0x44, 0xD5, 0xB4,
- 0xD5, 0xAB, 0x44, 0xD5, 0xB4, 0xD5, 0xAD, 0x44,
- 0xD5, 0xB4, 0xD5, 0xB6, 0x44, 0xD5, 0xBE, 0xD5,
- // Bytes 1ec0 - 1eff
- 0xB6, 0x44, 0xD7, 0x90, 0xD7, 0x9C, 0x44, 0xD8,
- 0xA7, 0xD9, 0xB4, 0x44, 0xD8, 0xA8, 0xD8, 0xAC,
- 0x44, 0xD8, 0xA8, 0xD8, 0xAD, 0x44, 0xD8, 0xA8,
- 0xD8, 0xAE, 0x44, 0xD8, 0xA8, 0xD8, 0xB1, 0x44,
- 0xD8, 0xA8, 0xD8, 0xB2, 0x44, 0xD8, 0xA8, 0xD9,
- 0x85, 0x44, 0xD8, 0xA8, 0xD9, 0x86, 0x44, 0xD8,
- 0xA8, 0xD9, 0x87, 0x44, 0xD8, 0xA8, 0xD9, 0x89,
- 0x44, 0xD8, 0xA8, 0xD9, 0x8A, 0x44, 0xD8, 0xAA,
- // Bytes 1f00 - 1f3f
- 0xD8, 0xAC, 0x44, 0xD8, 0xAA, 0xD8, 0xAD, 0x44,
- 0xD8, 0xAA, 0xD8, 0xAE, 0x44, 0xD8, 0xAA, 0xD8,
- 0xB1, 0x44, 0xD8, 0xAA, 0xD8, 0xB2, 0x44, 0xD8,
- 0xAA, 0xD9, 0x85, 0x44, 0xD8, 0xAA, 0xD9, 0x86,
- 0x44, 0xD8, 0xAA, 0xD9, 0x87, 0x44, 0xD8, 0xAA,
- 0xD9, 0x89, 0x44, 0xD8, 0xAA, 0xD9, 0x8A, 0x44,
- 0xD8, 0xAB, 0xD8, 0xAC, 0x44, 0xD8, 0xAB, 0xD8,
- 0xB1, 0x44, 0xD8, 0xAB, 0xD8, 0xB2, 0x44, 0xD8,
- // Bytes 1f40 - 1f7f
- 0xAB, 0xD9, 0x85, 0x44, 0xD8, 0xAB, 0xD9, 0x86,
- 0x44, 0xD8, 0xAB, 0xD9, 0x87, 0x44, 0xD8, 0xAB,
- 0xD9, 0x89, 0x44, 0xD8, 0xAB, 0xD9, 0x8A, 0x44,
- 0xD8, 0xAC, 0xD8, 0xAD, 0x44, 0xD8, 0xAC, 0xD9,
- 0x85, 0x44, 0xD8, 0xAC, 0xD9, 0x89, 0x44, 0xD8,
- 0xAC, 0xD9, 0x8A, 0x44, 0xD8, 0xAD, 0xD8, 0xAC,
- 0x44, 0xD8, 0xAD, 0xD9, 0x85, 0x44, 0xD8, 0xAD,
- 0xD9, 0x89, 0x44, 0xD8, 0xAD, 0xD9, 0x8A, 0x44,
- // Bytes 1f80 - 1fbf
- 0xD8, 0xAE, 0xD8, 0xAC, 0x44, 0xD8, 0xAE, 0xD8,
- 0xAD, 0x44, 0xD8, 0xAE, 0xD9, 0x85, 0x44, 0xD8,
- 0xAE, 0xD9, 0x89, 0x44, 0xD8, 0xAE, 0xD9, 0x8A,
- 0x44, 0xD8, 0xB3, 0xD8, 0xAC, 0x44, 0xD8, 0xB3,
- 0xD8, 0xAD, 0x44, 0xD8, 0xB3, 0xD8, 0xAE, 0x44,
- 0xD8, 0xB3, 0xD8, 0xB1, 0x44, 0xD8, 0xB3, 0xD9,
- 0x85, 0x44, 0xD8, 0xB3, 0xD9, 0x87, 0x44, 0xD8,
- 0xB3, 0xD9, 0x89, 0x44, 0xD8, 0xB3, 0xD9, 0x8A,
- // Bytes 1fc0 - 1fff
- 0x44, 0xD8, 0xB4, 0xD8, 0xAC, 0x44, 0xD8, 0xB4,
- 0xD8, 0xAD, 0x44, 0xD8, 0xB4, 0xD8, 0xAE, 0x44,
- 0xD8, 0xB4, 0xD8, 0xB1, 0x44, 0xD8, 0xB4, 0xD9,
- 0x85, 0x44, 0xD8, 0xB4, 0xD9, 0x87, 0x44, 0xD8,
- 0xB4, 0xD9, 0x89, 0x44, 0xD8, 0xB4, 0xD9, 0x8A,
- 0x44, 0xD8, 0xB5, 0xD8, 0xAD, 0x44, 0xD8, 0xB5,
- 0xD8, 0xAE, 0x44, 0xD8, 0xB5, 0xD8, 0xB1, 0x44,
- 0xD8, 0xB5, 0xD9, 0x85, 0x44, 0xD8, 0xB5, 0xD9,
- // Bytes 2000 - 203f
- 0x89, 0x44, 0xD8, 0xB5, 0xD9, 0x8A, 0x44, 0xD8,
- 0xB6, 0xD8, 0xAC, 0x44, 0xD8, 0xB6, 0xD8, 0xAD,
- 0x44, 0xD8, 0xB6, 0xD8, 0xAE, 0x44, 0xD8, 0xB6,
- 0xD8, 0xB1, 0x44, 0xD8, 0xB6, 0xD9, 0x85, 0x44,
- 0xD8, 0xB6, 0xD9, 0x89, 0x44, 0xD8, 0xB6, 0xD9,
- 0x8A, 0x44, 0xD8, 0xB7, 0xD8, 0xAD, 0x44, 0xD8,
- 0xB7, 0xD9, 0x85, 0x44, 0xD8, 0xB7, 0xD9, 0x89,
- 0x44, 0xD8, 0xB7, 0xD9, 0x8A, 0x44, 0xD8, 0xB8,
- // Bytes 2040 - 207f
- 0xD9, 0x85, 0x44, 0xD8, 0xB9, 0xD8, 0xAC, 0x44,
- 0xD8, 0xB9, 0xD9, 0x85, 0x44, 0xD8, 0xB9, 0xD9,
- 0x89, 0x44, 0xD8, 0xB9, 0xD9, 0x8A, 0x44, 0xD8,
- 0xBA, 0xD8, 0xAC, 0x44, 0xD8, 0xBA, 0xD9, 0x85,
- 0x44, 0xD8, 0xBA, 0xD9, 0x89, 0x44, 0xD8, 0xBA,
- 0xD9, 0x8A, 0x44, 0xD9, 0x81, 0xD8, 0xAC, 0x44,
- 0xD9, 0x81, 0xD8, 0xAD, 0x44, 0xD9, 0x81, 0xD8,
- 0xAE, 0x44, 0xD9, 0x81, 0xD9, 0x85, 0x44, 0xD9,
- // Bytes 2080 - 20bf
- 0x81, 0xD9, 0x89, 0x44, 0xD9, 0x81, 0xD9, 0x8A,
- 0x44, 0xD9, 0x82, 0xD8, 0xAD, 0x44, 0xD9, 0x82,
- 0xD9, 0x85, 0x44, 0xD9, 0x82, 0xD9, 0x89, 0x44,
- 0xD9, 0x82, 0xD9, 0x8A, 0x44, 0xD9, 0x83, 0xD8,
- 0xA7, 0x44, 0xD9, 0x83, 0xD8, 0xAC, 0x44, 0xD9,
- 0x83, 0xD8, 0xAD, 0x44, 0xD9, 0x83, 0xD8, 0xAE,
- 0x44, 0xD9, 0x83, 0xD9, 0x84, 0x44, 0xD9, 0x83,
- 0xD9, 0x85, 0x44, 0xD9, 0x83, 0xD9, 0x89, 0x44,
- // Bytes 20c0 - 20ff
- 0xD9, 0x83, 0xD9, 0x8A, 0x44, 0xD9, 0x84, 0xD8,
- 0xA7, 0x44, 0xD9, 0x84, 0xD8, 0xAC, 0x44, 0xD9,
- 0x84, 0xD8, 0xAD, 0x44, 0xD9, 0x84, 0xD8, 0xAE,
- 0x44, 0xD9, 0x84, 0xD9, 0x85, 0x44, 0xD9, 0x84,
- 0xD9, 0x87, 0x44, 0xD9, 0x84, 0xD9, 0x89, 0x44,
- 0xD9, 0x84, 0xD9, 0x8A, 0x44, 0xD9, 0x85, 0xD8,
- 0xA7, 0x44, 0xD9, 0x85, 0xD8, 0xAC, 0x44, 0xD9,
- 0x85, 0xD8, 0xAD, 0x44, 0xD9, 0x85, 0xD8, 0xAE,
- // Bytes 2100 - 213f
- 0x44, 0xD9, 0x85, 0xD9, 0x85, 0x44, 0xD9, 0x85,
- 0xD9, 0x89, 0x44, 0xD9, 0x85, 0xD9, 0x8A, 0x44,
- 0xD9, 0x86, 0xD8, 0xAC, 0x44, 0xD9, 0x86, 0xD8,
- 0xAD, 0x44, 0xD9, 0x86, 0xD8, 0xAE, 0x44, 0xD9,
- 0x86, 0xD8, 0xB1, 0x44, 0xD9, 0x86, 0xD8, 0xB2,
- 0x44, 0xD9, 0x86, 0xD9, 0x85, 0x44, 0xD9, 0x86,
- 0xD9, 0x86, 0x44, 0xD9, 0x86, 0xD9, 0x87, 0x44,
- 0xD9, 0x86, 0xD9, 0x89, 0x44, 0xD9, 0x86, 0xD9,
- // Bytes 2140 - 217f
- 0x8A, 0x44, 0xD9, 0x87, 0xD8, 0xAC, 0x44, 0xD9,
- 0x87, 0xD9, 0x85, 0x44, 0xD9, 0x87, 0xD9, 0x89,
- 0x44, 0xD9, 0x87, 0xD9, 0x8A, 0x44, 0xD9, 0x88,
- 0xD9, 0xB4, 0x44, 0xD9, 0x8A, 0xD8, 0xAC, 0x44,
- 0xD9, 0x8A, 0xD8, 0xAD, 0x44, 0xD9, 0x8A, 0xD8,
- 0xAE, 0x44, 0xD9, 0x8A, 0xD8, 0xB1, 0x44, 0xD9,
- 0x8A, 0xD8, 0xB2, 0x44, 0xD9, 0x8A, 0xD9, 0x85,
- 0x44, 0xD9, 0x8A, 0xD9, 0x86, 0x44, 0xD9, 0x8A,
- // Bytes 2180 - 21bf
- 0xD9, 0x87, 0x44, 0xD9, 0x8A, 0xD9, 0x89, 0x44,
- 0xD9, 0x8A, 0xD9, 0x8A, 0x44, 0xD9, 0x8A, 0xD9,
- 0xB4, 0x44, 0xDB, 0x87, 0xD9, 0xB4, 0x45, 0x28,
- 0xE1, 0x84, 0x80, 0x29, 0x45, 0x28, 0xE1, 0x84,
- 0x82, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x83, 0x29,
- 0x45, 0x28, 0xE1, 0x84, 0x85, 0x29, 0x45, 0x28,
- 0xE1, 0x84, 0x86, 0x29, 0x45, 0x28, 0xE1, 0x84,
- 0x87, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x89, 0x29,
- // Bytes 21c0 - 21ff
- 0x45, 0x28, 0xE1, 0x84, 0x8B, 0x29, 0x45, 0x28,
- 0xE1, 0x84, 0x8C, 0x29, 0x45, 0x28, 0xE1, 0x84,
- 0x8E, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x8F, 0x29,
- 0x45, 0x28, 0xE1, 0x84, 0x90, 0x29, 0x45, 0x28,
- 0xE1, 0x84, 0x91, 0x29, 0x45, 0x28, 0xE1, 0x84,
- 0x92, 0x29, 0x45, 0x28, 0xE4, 0xB8, 0x80, 0x29,
- 0x45, 0x28, 0xE4, 0xB8, 0x83, 0x29, 0x45, 0x28,
- 0xE4, 0xB8, 0x89, 0x29, 0x45, 0x28, 0xE4, 0xB9,
- // Bytes 2200 - 223f
- 0x9D, 0x29, 0x45, 0x28, 0xE4, 0xBA, 0x8C, 0x29,
- 0x45, 0x28, 0xE4, 0xBA, 0x94, 0x29, 0x45, 0x28,
- 0xE4, 0xBB, 0xA3, 0x29, 0x45, 0x28, 0xE4, 0xBC,
- 0x81, 0x29, 0x45, 0x28, 0xE4, 0xBC, 0x91, 0x29,
- 0x45, 0x28, 0xE5, 0x85, 0xAB, 0x29, 0x45, 0x28,
- 0xE5, 0x85, 0xAD, 0x29, 0x45, 0x28, 0xE5, 0x8A,
- 0xB4, 0x29, 0x45, 0x28, 0xE5, 0x8D, 0x81, 0x29,
- 0x45, 0x28, 0xE5, 0x8D, 0x94, 0x29, 0x45, 0x28,
- // Bytes 2240 - 227f
- 0xE5, 0x90, 0x8D, 0x29, 0x45, 0x28, 0xE5, 0x91,
- 0xBC, 0x29, 0x45, 0x28, 0xE5, 0x9B, 0x9B, 0x29,
- 0x45, 0x28, 0xE5, 0x9C, 0x9F, 0x29, 0x45, 0x28,
- 0xE5, 0xAD, 0xA6, 0x29, 0x45, 0x28, 0xE6, 0x97,
- 0xA5, 0x29, 0x45, 0x28, 0xE6, 0x9C, 0x88, 0x29,
- 0x45, 0x28, 0xE6, 0x9C, 0x89, 0x29, 0x45, 0x28,
- 0xE6, 0x9C, 0xA8, 0x29, 0x45, 0x28, 0xE6, 0xA0,
- 0xAA, 0x29, 0x45, 0x28, 0xE6, 0xB0, 0xB4, 0x29,
- // Bytes 2280 - 22bf
- 0x45, 0x28, 0xE7, 0x81, 0xAB, 0x29, 0x45, 0x28,
- 0xE7, 0x89, 0xB9, 0x29, 0x45, 0x28, 0xE7, 0x9B,
- 0xA3, 0x29, 0x45, 0x28, 0xE7, 0xA4, 0xBE, 0x29,
- 0x45, 0x28, 0xE7, 0xA5, 0x9D, 0x29, 0x45, 0x28,
- 0xE7, 0xA5, 0xAD, 0x29, 0x45, 0x28, 0xE8, 0x87,
- 0xAA, 0x29, 0x45, 0x28, 0xE8, 0x87, 0xB3, 0x29,
- 0x45, 0x28, 0xE8, 0xB2, 0xA1, 0x29, 0x45, 0x28,
- 0xE8, 0xB3, 0x87, 0x29, 0x45, 0x28, 0xE9, 0x87,
- // Bytes 22c0 - 22ff
- 0x91, 0x29, 0x45, 0x30, 0xE2, 0x81, 0x84, 0x33,
- 0x45, 0x31, 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x31,
- 0x30, 0xE6, 0x9C, 0x88, 0x45, 0x31, 0x30, 0xE7,
- 0x82, 0xB9, 0x45, 0x31, 0x31, 0xE6, 0x97, 0xA5,
- 0x45, 0x31, 0x31, 0xE6, 0x9C, 0x88, 0x45, 0x31,
- 0x31, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x32, 0xE6,
- 0x97, 0xA5, 0x45, 0x31, 0x32, 0xE6, 0x9C, 0x88,
- 0x45, 0x31, 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x31,
- // Bytes 2300 - 233f
- 0x33, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x33, 0xE7,
- 0x82, 0xB9, 0x45, 0x31, 0x34, 0xE6, 0x97, 0xA5,
- 0x45, 0x31, 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x31,
- 0x35, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x35, 0xE7,
- 0x82, 0xB9, 0x45, 0x31, 0x36, 0xE6, 0x97, 0xA5,
- 0x45, 0x31, 0x36, 0xE7, 0x82, 0xB9, 0x45, 0x31,
- 0x37, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x37, 0xE7,
- 0x82, 0xB9, 0x45, 0x31, 0x38, 0xE6, 0x97, 0xA5,
- // Bytes 2340 - 237f
- 0x45, 0x31, 0x38, 0xE7, 0x82, 0xB9, 0x45, 0x31,
- 0x39, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x39, 0xE7,
- 0x82, 0xB9, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x32,
- 0x45, 0x31, 0xE2, 0x81, 0x84, 0x33, 0x45, 0x31,
- 0xE2, 0x81, 0x84, 0x34, 0x45, 0x31, 0xE2, 0x81,
- 0x84, 0x35, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x36,
- 0x45, 0x31, 0xE2, 0x81, 0x84, 0x37, 0x45, 0x31,
- 0xE2, 0x81, 0x84, 0x38, 0x45, 0x31, 0xE2, 0x81,
- // Bytes 2380 - 23bf
- 0x84, 0x39, 0x45, 0x32, 0x30, 0xE6, 0x97, 0xA5,
- 0x45, 0x32, 0x30, 0xE7, 0x82, 0xB9, 0x45, 0x32,
- 0x31, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x31, 0xE7,
- 0x82, 0xB9, 0x45, 0x32, 0x32, 0xE6, 0x97, 0xA5,
- 0x45, 0x32, 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x32,
- 0x33, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x33, 0xE7,
- 0x82, 0xB9, 0x45, 0x32, 0x34, 0xE6, 0x97, 0xA5,
- 0x45, 0x32, 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x32,
- // Bytes 23c0 - 23ff
- 0x35, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x36, 0xE6,
- 0x97, 0xA5, 0x45, 0x32, 0x37, 0xE6, 0x97, 0xA5,
- 0x45, 0x32, 0x38, 0xE6, 0x97, 0xA5, 0x45, 0x32,
- 0x39, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0xE2, 0x81,
- 0x84, 0x33, 0x45, 0x32, 0xE2, 0x81, 0x84, 0x35,
- 0x45, 0x33, 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x33,
- 0x31, 0xE6, 0x97, 0xA5, 0x45, 0x33, 0xE2, 0x81,
- 0x84, 0x34, 0x45, 0x33, 0xE2, 0x81, 0x84, 0x35,
- // Bytes 2400 - 243f
- 0x45, 0x33, 0xE2, 0x81, 0x84, 0x38, 0x45, 0x34,
- 0xE2, 0x81, 0x84, 0x35, 0x45, 0x35, 0xE2, 0x81,
- 0x84, 0x36, 0x45, 0x35, 0xE2, 0x81, 0x84, 0x38,
- 0x45, 0x37, 0xE2, 0x81, 0x84, 0x38, 0x45, 0x41,
- 0xE2, 0x88, 0x95, 0x6D, 0x45, 0x56, 0xE2, 0x88,
- 0x95, 0x6D, 0x45, 0x6D, 0xE2, 0x88, 0x95, 0x73,
- 0x46, 0x31, 0xE2, 0x81, 0x84, 0x31, 0x30, 0x46,
- 0x43, 0xE2, 0x88, 0x95, 0x6B, 0x67, 0x46, 0x6D,
- // Bytes 2440 - 247f
- 0xE2, 0x88, 0x95, 0x73, 0x32, 0x46, 0xD8, 0xA8,
- 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xA8, 0xD8,
- 0xAE, 0xD9, 0x8A, 0x46, 0xD8, 0xAA, 0xD8, 0xAC,
- 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9,
- 0x89, 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x8A,
- 0x46, 0xD8, 0xAA, 0xD8, 0xAD, 0xD8, 0xAC, 0x46,
- 0xD8, 0xAA, 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8,
- 0xAA, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD8, 0xAA,
- // Bytes 2480 - 24bf
- 0xD8, 0xAE, 0xD9, 0x89, 0x46, 0xD8, 0xAA, 0xD8,
- 0xAE, 0xD9, 0x8A, 0x46, 0xD8, 0xAA, 0xD9, 0x85,
- 0xD8, 0xAC, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8,
- 0xAD, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAE,
- 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD9, 0x89, 0x46,
- 0xD8, 0xAA, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8,
- 0xAC, 0xD8, 0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xAC,
- 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xAC, 0xD9,
- // Bytes 24c0 - 24ff
- 0x85, 0xD8, 0xAD, 0x46, 0xD8, 0xAC, 0xD9, 0x85,
- 0xD9, 0x89, 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD9,
- 0x8A, 0x46, 0xD8, 0xAD, 0xD8, 0xAC, 0xD9, 0x8A,
- 0x46, 0xD8, 0xAD, 0xD9, 0x85, 0xD9, 0x89, 0x46,
- 0xD8, 0xAD, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8,
- 0xB3, 0xD8, 0xAC, 0xD8, 0xAD, 0x46, 0xD8, 0xB3,
- 0xD8, 0xAC, 0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8,
- 0xAD, 0xD8, 0xAC, 0x46, 0xD8, 0xB3, 0xD8, 0xAE,
- // Bytes 2500 - 253f
- 0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9,
- 0x8A, 0x46, 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAC,
- 0x46, 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAD, 0x46,
- 0xD8, 0xB3, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8,
- 0xB4, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD8, 0xB4,
- 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8, 0xB4, 0xD8,
- 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xB4, 0xD9, 0x85,
- 0xD8, 0xAE, 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD9,
- // Bytes 2540 - 257f
- 0x85, 0x46, 0xD8, 0xB5, 0xD8, 0xAD, 0xD8, 0xAD,
- 0x46, 0xD8, 0xB5, 0xD8, 0xAD, 0xD9, 0x8A, 0x46,
- 0xD8, 0xB5, 0xD9, 0x84, 0xD9, 0x89, 0x46, 0xD8,
- 0xB5, 0xD9, 0x84, 0xDB, 0x92, 0x46, 0xD8, 0xB5,
- 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB6, 0xD8,
- 0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xB6, 0xD8, 0xAD,
- 0xD9, 0x8A, 0x46, 0xD8, 0xB6, 0xD8, 0xAE, 0xD9,
- 0x85, 0x46, 0xD8, 0xB7, 0xD9, 0x85, 0xD8, 0xAD,
- // Bytes 2580 - 25bf
- 0x46, 0xD8, 0xB7, 0xD9, 0x85, 0xD9, 0x85, 0x46,
- 0xD8, 0xB7, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8,
- 0xB9, 0xD8, 0xAC, 0xD9, 0x85, 0x46, 0xD8, 0xB9,
- 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB9, 0xD9,
- 0x85, 0xD9, 0x89, 0x46, 0xD8, 0xB9, 0xD9, 0x85,
- 0xD9, 0x8A, 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9,
- 0x85, 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x89,
- 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
- // Bytes 25c0 - 25ff
- 0xD9, 0x81, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9,
- 0x81, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x82,
- 0xD9, 0x84, 0xDB, 0x92, 0x46, 0xD9, 0x82, 0xD9,
- 0x85, 0xD8, 0xAD, 0x46, 0xD9, 0x82, 0xD9, 0x85,
- 0xD9, 0x85, 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD9,
- 0x8A, 0x46, 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x85,
- 0x46, 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
- 0xD9, 0x84, 0xD8, 0xAC, 0xD8, 0xAC, 0x46, 0xD9,
- // Bytes 2600 - 263f
- 0x84, 0xD8, 0xAC, 0xD9, 0x85, 0x46, 0xD9, 0x84,
- 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x84, 0xD8,
- 0xAD, 0xD9, 0x85, 0x46, 0xD9, 0x84, 0xD8, 0xAD,
- 0xD9, 0x89, 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9,
- 0x8A, 0x46, 0xD9, 0x84, 0xD8, 0xAE, 0xD9, 0x85,
- 0x46, 0xD9, 0x84, 0xD9, 0x85, 0xD8, 0xAD, 0x46,
- 0xD9, 0x84, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9,
- 0x85, 0xD8, 0xAC, 0xD8, 0xAD, 0x46, 0xD9, 0x85,
- // Bytes 2640 - 267f
- 0xD8, 0xAC, 0xD8, 0xAE, 0x46, 0xD9, 0x85, 0xD8,
- 0xAC, 0xD9, 0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAC,
- 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD8,
- 0xAC, 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85,
- 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x8A, 0x46,
- 0xD9, 0x85, 0xD8, 0xAE, 0xD8, 0xAC, 0x46, 0xD9,
- 0x85, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9, 0x85,
- 0xD8, 0xAE, 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD9,
- // Bytes 2680 - 26bf
- 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD8, 0xAC,
- 0xD8, 0xAD, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9,
- 0x85, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x89,
- 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x8A, 0x46,
- 0xD9, 0x86, 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD9,
- 0x86, 0xD8, 0xAD, 0xD9, 0x89, 0x46, 0xD9, 0x86,
- 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD9,
- 0x85, 0xD9, 0x89, 0x46, 0xD9, 0x86, 0xD9, 0x85,
- // Bytes 26c0 - 26ff
- 0xD9, 0x8A, 0x46, 0xD9, 0x87, 0xD9, 0x85, 0xD8,
- 0xAC, 0x46, 0xD9, 0x87, 0xD9, 0x85, 0xD9, 0x85,
- 0x46, 0xD9, 0x8A, 0xD8, 0xAC, 0xD9, 0x8A, 0x46,
- 0xD9, 0x8A, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9,
- 0x8A, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD9, 0x8A,
- 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x8A, 0xD9,
- 0x94, 0xD8, 0xA7, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
- 0xD8, 0xAC, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8,
- // Bytes 2700 - 273f
- 0xAD, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAE,
- 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xB1, 0x46,
- 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xB2, 0x46, 0xD9,
- 0x8A, 0xD9, 0x94, 0xD9, 0x85, 0x46, 0xD9, 0x8A,
- 0xD9, 0x94, 0xD9, 0x86, 0x46, 0xD9, 0x8A, 0xD9,
- 0x94, 0xD9, 0x87, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
- 0xD9, 0x88, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9,
- 0x89, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x8A,
- // Bytes 2740 - 277f
- 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xDB, 0x86, 0x46,
- 0xD9, 0x8A, 0xD9, 0x94, 0xDB, 0x87, 0x46, 0xD9,
- 0x8A, 0xD9, 0x94, 0xDB, 0x88, 0x46, 0xD9, 0x8A,
- 0xD9, 0x94, 0xDB, 0x90, 0x46, 0xD9, 0x8A, 0xD9,
- 0x94, 0xDB, 0x95, 0x46, 0xE0, 0xB9, 0x8D, 0xE0,
- 0xB8, 0xB2, 0x46, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA,
- 0x99, 0x46, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0xA1,
- 0x46, 0xE0, 0xBB, 0x8D, 0xE0, 0xBA, 0xB2, 0x46,
- // Bytes 2780 - 27bf
- 0xE0, 0xBD, 0x80, 0xE0, 0xBE, 0xB5, 0x46, 0xE0,
- 0xBD, 0x82, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD,
- 0x8C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x91,
- 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x96, 0xE0,
- 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x9B, 0xE0, 0xBE,
- 0xB7, 0x46, 0xE0, 0xBE, 0x90, 0xE0, 0xBE, 0xB5,
- 0x46, 0xE0, 0xBE, 0x92, 0xE0, 0xBE, 0xB7, 0x46,
- 0xE0, 0xBE, 0x9C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0,
- // Bytes 27c0 - 27ff
- 0xBE, 0xA1, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE,
- 0xA6, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xAB,
- 0xE0, 0xBE, 0xB7, 0x46, 0xE1, 0x84, 0x80, 0xE1,
- 0x85, 0xA1, 0x46, 0xE1, 0x84, 0x82, 0xE1, 0x85,
- 0xA1, 0x46, 0xE1, 0x84, 0x83, 0xE1, 0x85, 0xA1,
- 0x46, 0xE1, 0x84, 0x85, 0xE1, 0x85, 0xA1, 0x46,
- 0xE1, 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x46, 0xE1,
- 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84,
- // Bytes 2800 - 283f
- 0x89, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84, 0x8B,
- 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84, 0x8B, 0xE1,
- 0x85, 0xAE, 0x46, 0xE1, 0x84, 0x8C, 0xE1, 0x85,
- 0xA1, 0x46, 0xE1, 0x84, 0x8E, 0xE1, 0x85, 0xA1,
- 0x46, 0xE1, 0x84, 0x8F, 0xE1, 0x85, 0xA1, 0x46,
- 0xE1, 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x46, 0xE1,
- 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84,
- 0x92, 0xE1, 0x85, 0xA1, 0x46, 0xE2, 0x80, 0xB2,
- // Bytes 2840 - 287f
- 0xE2, 0x80, 0xB2, 0x46, 0xE2, 0x80, 0xB5, 0xE2,
- 0x80, 0xB5, 0x46, 0xE2, 0x88, 0xAB, 0xE2, 0x88,
- 0xAB, 0x46, 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE,
- 0x46, 0xE3, 0x81, 0xBB, 0xE3, 0x81, 0x8B, 0x46,
- 0xE3, 0x82, 0x88, 0xE3, 0x82, 0x8A, 0x46, 0xE3,
- 0x82, 0xAD, 0xE3, 0x83, 0xAD, 0x46, 0xE3, 0x82,
- 0xB3, 0xE3, 0x82, 0xB3, 0x46, 0xE3, 0x82, 0xB3,
- 0xE3, 0x83, 0x88, 0x46, 0xE3, 0x83, 0x88, 0xE3,
- // Bytes 2880 - 28bf
- 0x83, 0xB3, 0x46, 0xE3, 0x83, 0x8A, 0xE3, 0x83,
- 0x8E, 0x46, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xB3,
- 0x46, 0xE3, 0x83, 0x9F, 0xE3, 0x83, 0xAA, 0x46,
- 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xA9, 0x46, 0xE3,
- 0x83, 0xAC, 0xE3, 0x83, 0xA0, 0x46, 0xE5, 0xA4,
- 0xA7, 0xE6, 0xAD, 0xA3, 0x46, 0xE5, 0xB9, 0xB3,
- 0xE6, 0x88, 0x90, 0x46, 0xE6, 0x98, 0x8E, 0xE6,
- 0xB2, 0xBB, 0x46, 0xE6, 0x98, 0xAD, 0xE5, 0x92,
- // Bytes 28c0 - 28ff
- 0x8C, 0x47, 0x72, 0x61, 0x64, 0xE2, 0x88, 0x95,
- 0x73, 0x47, 0xE3, 0x80, 0x94, 0x53, 0xE3, 0x80,
- 0x95, 0x48, 0x28, 0xE1, 0x84, 0x80, 0xE1, 0x85,
- 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x82, 0xE1,
- 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x83,
- 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
- 0x85, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
- 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
- // Bytes 2900 - 293f
- 0xE1, 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x29, 0x48,
- 0x28, 0xE1, 0x84, 0x89, 0xE1, 0x85, 0xA1, 0x29,
- 0x48, 0x28, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xA1,
- 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8C, 0xE1, 0x85,
- 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8C, 0xE1,
- 0x85, 0xAE, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8E,
- 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
- 0x8F, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
- // Bytes 2940 - 297f
- 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
- 0xE1, 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x29, 0x48,
- 0x28, 0xE1, 0x84, 0x92, 0xE1, 0x85, 0xA1, 0x29,
- 0x48, 0x72, 0x61, 0x64, 0xE2, 0x88, 0x95, 0x73,
- 0x32, 0x48, 0xD8, 0xA7, 0xD9, 0x83, 0xD8, 0xA8,
- 0xD8, 0xB1, 0x48, 0xD8, 0xA7, 0xD9, 0x84, 0xD9,
- 0x84, 0xD9, 0x87, 0x48, 0xD8, 0xB1, 0xD8, 0xB3,
- 0xD9, 0x88, 0xD9, 0x84, 0x48, 0xD8, 0xB1, 0xDB,
- // Bytes 2980 - 29bf
- 0x8C, 0xD8, 0xA7, 0xD9, 0x84, 0x48, 0xD8, 0xB5,
- 0xD9, 0x84, 0xD8, 0xB9, 0xD9, 0x85, 0x48, 0xD8,
- 0xB9, 0xD9, 0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x48,
- 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85, 0xD8, 0xAF,
- 0x48, 0xD9, 0x88, 0xD8, 0xB3, 0xD9, 0x84, 0xD9,
- 0x85, 0x49, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
- 0xE2, 0x80, 0xB2, 0x49, 0xE2, 0x80, 0xB5, 0xE2,
- 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0x49, 0xE2, 0x88,
- // Bytes 29c0 - 29ff
- 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0x49,
- 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0xE2, 0x88,
- 0xAE, 0x49, 0xE3, 0x80, 0x94, 0xE4, 0xB8, 0x89,
- 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE4,
- 0xBA, 0x8C, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80,
- 0x94, 0xE5, 0x8B, 0x9D, 0xE3, 0x80, 0x95, 0x49,
- 0xE3, 0x80, 0x94, 0xE5, 0xAE, 0x89, 0xE3, 0x80,
- 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE6, 0x89, 0x93,
- // Bytes 2a00 - 2a3f
- 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE6,
- 0x95, 0x97, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80,
- 0x94, 0xE6, 0x9C, 0xAC, 0xE3, 0x80, 0x95, 0x49,
- 0xE3, 0x80, 0x94, 0xE7, 0x82, 0xB9, 0xE3, 0x80,
- 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE7, 0x9B, 0x97,
- 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x82, 0xA2, 0xE3,
- 0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x82,
- 0xA4, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0x49,
- // Bytes 2a40 - 2a7f
- 0xE3, 0x82, 0xA6, 0xE3, 0x82, 0xA9, 0xE3, 0x83,
- 0xB3, 0x49, 0xE3, 0x82, 0xAA, 0xE3, 0x83, 0xB3,
- 0xE3, 0x82, 0xB9, 0x49, 0xE3, 0x82, 0xAA, 0xE3,
- 0x83, 0xBC, 0xE3, 0x83, 0xA0, 0x49, 0xE3, 0x82,
- 0xAB, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAA, 0x49,
- 0xE3, 0x82, 0xB1, 0xE3, 0x83, 0xBC, 0xE3, 0x82,
- 0xB9, 0x49, 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0xAB,
- 0xE3, 0x83, 0x8A, 0x49, 0xE3, 0x82, 0xBB, 0xE3,
- // Bytes 2a80 - 2abf
- 0x83, 0xB3, 0xE3, 0x83, 0x81, 0x49, 0xE3, 0x82,
- 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88, 0x49,
- 0xE3, 0x83, 0x86, 0xE3, 0x82, 0x99, 0xE3, 0x82,
- 0xB7, 0x49, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99,
- 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x8E, 0xE3,
- 0x83, 0x83, 0xE3, 0x83, 0x88, 0x49, 0xE3, 0x83,
- 0x8F, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0x84, 0x49,
- 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x99, 0xE3, 0x83,
- // Bytes 2ac0 - 2aff
- 0xAB, 0x49, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A,
- 0xE3, 0x82, 0xB3, 0x49, 0xE3, 0x83, 0x95, 0xE3,
- 0x83, 0xA9, 0xE3, 0x83, 0xB3, 0x49, 0xE3, 0x83,
- 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xBD, 0x49,
- 0xE3, 0x83, 0x98, 0xE3, 0x83, 0xAB, 0xE3, 0x83,
- 0x84, 0x49, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xBC,
- 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x9B, 0xE3,
- 0x83, 0xBC, 0xE3, 0x83, 0xB3, 0x49, 0xE3, 0x83,
- // Bytes 2b00 - 2b3f
- 0x9E, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAB, 0x49,
- 0xE3, 0x83, 0x9E, 0xE3, 0x83, 0x83, 0xE3, 0x83,
- 0x8F, 0x49, 0xE3, 0x83, 0x9E, 0xE3, 0x83, 0xAB,
- 0xE3, 0x82, 0xAF, 0x49, 0xE3, 0x83, 0xA4, 0xE3,
- 0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83,
- 0xA6, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xB3, 0x49,
- 0xE3, 0x83, 0xAF, 0xE3, 0x83, 0x83, 0xE3, 0x83,
- 0x88, 0x4C, 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xAE,
- // Bytes 2b40 - 2b7f
- 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xB4, 0x4C, 0xE2,
- 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
- 0xE2, 0x80, 0xB2, 0x4C, 0xE2, 0x88, 0xAB, 0xE2,
- 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB,
- 0x4C, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xAB, 0xE3,
- 0x83, 0x95, 0xE3, 0x82, 0xA1, 0x4C, 0xE3, 0x82,
- 0xA8, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xAB, 0xE3,
- 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
- // Bytes 2b80 - 2bbf
- 0x99, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xB3, 0x4C,
- 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
- 0xB3, 0xE3, 0x83, 0x9E, 0x4C, 0xE3, 0x82, 0xAB,
- 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0x83, 0xE3, 0x83,
- 0x88, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x83, 0xAD,
- 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC, 0x4C, 0xE3,
- 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0x8B,
- 0xE3, 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAD, 0xE3,
- // Bytes 2bc0 - 2bff
- 0x83, 0xA5, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC,
- 0x4C, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3,
- 0x83, 0xA9, 0xE3, 0x83, 0xA0, 0x4C, 0xE3, 0x82,
- 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xBC, 0xE3,
- 0x83, 0x8D, 0x4C, 0xE3, 0x82, 0xB5, 0xE3, 0x82,
- 0xA4, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C,
- 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
- 0xBC, 0xE3, 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x8F,
- // Bytes 2c00 - 2c3f
- 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
- 0x84, 0x4C, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A,
- 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
- 0x83, 0x95, 0xE3, 0x82, 0xA3, 0xE3, 0x83, 0xBC,
- 0xE3, 0x83, 0x88, 0x4C, 0xE3, 0x83, 0x98, 0xE3,
- 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xBF,
- 0x4C, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3,
- 0x83, 0x8B, 0xE3, 0x83, 0x92, 0x4C, 0xE3, 0x83,
- // Bytes 2c40 - 2c7f
- 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xB3, 0xE3,
- 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
- 0x99, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x88, 0x4C,
- 0xE3, 0x83, 0x9E, 0xE3, 0x82, 0xA4, 0xE3, 0x82,
- 0xAF, 0xE3, 0x83, 0xAD, 0x4C, 0xE3, 0x83, 0x9F,
- 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83,
- 0xB3, 0x4C, 0xE3, 0x83, 0xA1, 0xE3, 0x83, 0xBC,
- 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
- // Bytes 2c80 - 2cbf
- 0x83, 0xAA, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88,
- 0xE3, 0x83, 0xAB, 0x4C, 0xE3, 0x83, 0xAB, 0xE3,
- 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC,
- 0x4C, 0xE6, 0xA0, 0xAA, 0xE5, 0xBC, 0x8F, 0xE4,
- 0xBC, 0x9A, 0xE7, 0xA4, 0xBE, 0x4E, 0x28, 0xE1,
- 0x84, 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x92,
- 0xE1, 0x85, 0xAE, 0x29, 0x4F, 0xD8, 0xAC, 0xD9,
- 0x84, 0x20, 0xD8, 0xAC, 0xD9, 0x84, 0xD8, 0xA7,
- // Bytes 2cc0 - 2cff
- 0xD9, 0x84, 0xD9, 0x87, 0x4F, 0xE1, 0x84, 0x8E,
- 0xE1, 0x85, 0xA1, 0xE1, 0x86, 0xB7, 0xE1, 0x84,
- 0x80, 0xE1, 0x85, 0xA9, 0x4F, 0xE3, 0x82, 0xA2,
- 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83,
- 0xBC, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xA2,
- 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x98, 0xE3, 0x82,
- 0x9A, 0xE3, 0x82, 0xA2, 0x4F, 0xE3, 0x82, 0xAD,
- 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xAF, 0xE3, 0x83,
- // Bytes 2d00 - 2d3f
- 0x83, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xB5,
- 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0xE3, 0x83,
- 0xBC, 0xE3, 0x83, 0xA0, 0x4F, 0xE3, 0x83, 0x8F,
- 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
- 0xAC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x98,
- 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0xBF, 0xE3, 0x83,
- 0xBC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x9B,
- 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xA4, 0xE3, 0x83,
- // Bytes 2d40 - 2d7f
- 0xB3, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x83, 0x9E,
- 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB7, 0xE3, 0x83,
- 0xA7, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xA1,
- 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
- 0x88, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xAB,
- 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x95, 0xE3, 0x82,
- 0x99, 0xE3, 0x83, 0xAB, 0x51, 0x28, 0xE1, 0x84,
- 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x8C, 0xE1,
- // Bytes 2d80 - 2dbf
- 0x85, 0xA5, 0xE1, 0x86, 0xAB, 0x29, 0x52, 0xE3,
- 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB,
- 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
- 0xBC, 0x52, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD,
- 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
- 0xA9, 0xE3, 0x83, 0xA0, 0x52, 0xE3, 0x82, 0xAD,
- 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xA1, 0xE3, 0x83,
- 0xBC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x52,
- // Bytes 2dc0 - 2dff
- 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
- 0xA9, 0xE3, 0x83, 0xA0, 0xE3, 0x83, 0x88, 0xE3,
- 0x83, 0xB3, 0x52, 0xE3, 0x82, 0xAF, 0xE3, 0x83,
- 0xAB, 0xE3, 0x82, 0xBB, 0xE3, 0x82, 0x99, 0xE3,
- 0x82, 0xA4, 0xE3, 0x83, 0xAD, 0x52, 0xE3, 0x83,
- 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3,
- 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88,
- 0x52, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3,
- // Bytes 2e00 - 2e3f
- 0x82, 0xA2, 0xE3, 0x82, 0xB9, 0xE3, 0x83, 0x88,
- 0xE3, 0x83, 0xAB, 0x52, 0xE3, 0x83, 0x95, 0xE3,
- 0x82, 0x99, 0xE3, 0x83, 0x83, 0xE3, 0x82, 0xB7,
- 0xE3, 0x82, 0xA7, 0xE3, 0x83, 0xAB, 0x52, 0xE3,
- 0x83, 0x9F, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0x8F,
- 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
- 0xAB, 0x52, 0xE3, 0x83, 0xAC, 0xE3, 0x83, 0xB3,
- 0xE3, 0x83, 0x88, 0xE3, 0x82, 0xB1, 0xE3, 0x82,
- // Bytes 2e40 - 2e7f
- 0x99, 0xE3, 0x83, 0xB3, 0x61, 0xD8, 0xB5, 0xD9,
- 0x84, 0xD9, 0x89, 0x20, 0xD8, 0xA7, 0xD9, 0x84,
- 0xD9, 0x84, 0xD9, 0x87, 0x20, 0xD8, 0xB9, 0xD9,
- 0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x20, 0xD9, 0x88,
- 0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x86, 0xE0,
- 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0x86, 0xE0, 0xB7,
- 0x99, 0xE0, 0xB7, 0x8F, 0x09, 0xE0, 0xB7, 0x99,
- 0xE0, 0xB7, 0x8F, 0xE0, 0xB7, 0x8A, 0x09, 0x44,
- // Bytes 2e80 - 2ebf
- 0x44, 0x5A, 0xCC, 0x8C, 0xE6, 0x44, 0x44, 0x7A,
- 0xCC, 0x8C, 0xE6, 0x44, 0x64, 0x7A, 0xCC, 0x8C,
- 0xE6, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x93,
- 0xE6, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x94,
- 0xE6, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x95,
- 0xDC, 0x49, 0xE3, 0x83, 0xA1, 0xE3, 0x82, 0xAB,
- 0xE3, 0x82, 0x99, 0x08, 0x4C, 0xE3, 0x82, 0xAD,
- 0xE3, 0x82, 0x99, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
- // Bytes 2ec0 - 2eff
- 0x99, 0x08, 0x4C, 0xE3, 0x82, 0xB3, 0xE3, 0x83,
- 0xBC, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A, 0x08,
- 0x4C, 0xE3, 0x83, 0xA4, 0xE3, 0x83, 0xBC, 0xE3,
- 0x83, 0x88, 0xE3, 0x82, 0x99, 0x08, 0x4F, 0xE3,
- 0x82, 0xA4, 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0xB3,
- 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x08, 0x4F,
- 0xE3, 0x82, 0xB7, 0xE3, 0x83, 0xAA, 0xE3, 0x83,
- 0xB3, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x08,
- // Bytes 2f00 - 2f3f
- 0x4F, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3,
- 0x83, 0xBC, 0xE3, 0x82, 0xB7, 0xE3, 0x82, 0x99,
- 0x08, 0x4F, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A,
- 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88, 0xE3, 0x82,
- 0x99, 0x08, 0x52, 0xE3, 0x82, 0xA8, 0xE3, 0x82,
- 0xB9, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xBC, 0xE3,
- 0x83, 0x88, 0xE3, 0x82, 0x99, 0x08, 0x52, 0xE3,
- 0x83, 0x95, 0xE3, 0x82, 0xA1, 0xE3, 0x83, 0xA9,
- // Bytes 2f40 - 2f7f
- 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0xE3, 0x82,
- 0x99, 0x08, 0x03, 0x3C, 0xCC, 0xB8, 0x01, 0x03,
- 0x3D, 0xCC, 0xB8, 0x01, 0x03, 0x3E, 0xCC, 0xB8,
- 0x01, 0x03, 0x41, 0xCC, 0x80, 0xE6, 0x03, 0x41,
- 0xCC, 0x81, 0xE6, 0x03, 0x41, 0xCC, 0x83, 0xE6,
- 0x03, 0x41, 0xCC, 0x84, 0xE6, 0x03, 0x41, 0xCC,
- 0x89, 0xE6, 0x03, 0x41, 0xCC, 0x8C, 0xE6, 0x03,
- 0x41, 0xCC, 0x8F, 0xE6, 0x03, 0x41, 0xCC, 0x91,
- // Bytes 2f80 - 2fbf
- 0xE6, 0x03, 0x41, 0xCC, 0xA5, 0xDC, 0x03, 0x41,
- 0xCC, 0xA8, 0xCA, 0x03, 0x42, 0xCC, 0x87, 0xE6,
- 0x03, 0x42, 0xCC, 0xA3, 0xDC, 0x03, 0x42, 0xCC,
- 0xB1, 0xDC, 0x03, 0x43, 0xCC, 0x81, 0xE6, 0x03,
- 0x43, 0xCC, 0x82, 0xE6, 0x03, 0x43, 0xCC, 0x87,
- 0xE6, 0x03, 0x43, 0xCC, 0x8C, 0xE6, 0x03, 0x44,
- 0xCC, 0x87, 0xE6, 0x03, 0x44, 0xCC, 0x8C, 0xE6,
- 0x03, 0x44, 0xCC, 0xA3, 0xDC, 0x03, 0x44, 0xCC,
- // Bytes 2fc0 - 2fff
- 0xA7, 0xCA, 0x03, 0x44, 0xCC, 0xAD, 0xDC, 0x03,
- 0x44, 0xCC, 0xB1, 0xDC, 0x03, 0x45, 0xCC, 0x80,
- 0xE6, 0x03, 0x45, 0xCC, 0x81, 0xE6, 0x03, 0x45,
- 0xCC, 0x83, 0xE6, 0x03, 0x45, 0xCC, 0x86, 0xE6,
- 0x03, 0x45, 0xCC, 0x87, 0xE6, 0x03, 0x45, 0xCC,
- 0x88, 0xE6, 0x03, 0x45, 0xCC, 0x89, 0xE6, 0x03,
- 0x45, 0xCC, 0x8C, 0xE6, 0x03, 0x45, 0xCC, 0x8F,
- 0xE6, 0x03, 0x45, 0xCC, 0x91, 0xE6, 0x03, 0x45,
- // Bytes 3000 - 303f
- 0xCC, 0xA8, 0xCA, 0x03, 0x45, 0xCC, 0xAD, 0xDC,
- 0x03, 0x45, 0xCC, 0xB0, 0xDC, 0x03, 0x46, 0xCC,
- 0x87, 0xE6, 0x03, 0x47, 0xCC, 0x81, 0xE6, 0x03,
- 0x47, 0xCC, 0x82, 0xE6, 0x03, 0x47, 0xCC, 0x84,
- 0xE6, 0x03, 0x47, 0xCC, 0x86, 0xE6, 0x03, 0x47,
- 0xCC, 0x87, 0xE6, 0x03, 0x47, 0xCC, 0x8C, 0xE6,
- 0x03, 0x47, 0xCC, 0xA7, 0xCA, 0x03, 0x48, 0xCC,
- 0x82, 0xE6, 0x03, 0x48, 0xCC, 0x87, 0xE6, 0x03,
- // Bytes 3040 - 307f
- 0x48, 0xCC, 0x88, 0xE6, 0x03, 0x48, 0xCC, 0x8C,
- 0xE6, 0x03, 0x48, 0xCC, 0xA3, 0xDC, 0x03, 0x48,
- 0xCC, 0xA7, 0xCA, 0x03, 0x48, 0xCC, 0xAE, 0xDC,
- 0x03, 0x49, 0xCC, 0x80, 0xE6, 0x03, 0x49, 0xCC,
- 0x81, 0xE6, 0x03, 0x49, 0xCC, 0x82, 0xE6, 0x03,
- 0x49, 0xCC, 0x83, 0xE6, 0x03, 0x49, 0xCC, 0x84,
- 0xE6, 0x03, 0x49, 0xCC, 0x86, 0xE6, 0x03, 0x49,
- 0xCC, 0x87, 0xE6, 0x03, 0x49, 0xCC, 0x89, 0xE6,
- // Bytes 3080 - 30bf
- 0x03, 0x49, 0xCC, 0x8C, 0xE6, 0x03, 0x49, 0xCC,
- 0x8F, 0xE6, 0x03, 0x49, 0xCC, 0x91, 0xE6, 0x03,
- 0x49, 0xCC, 0xA3, 0xDC, 0x03, 0x49, 0xCC, 0xA8,
- 0xCA, 0x03, 0x49, 0xCC, 0xB0, 0xDC, 0x03, 0x4A,
- 0xCC, 0x82, 0xE6, 0x03, 0x4B, 0xCC, 0x81, 0xE6,
- 0x03, 0x4B, 0xCC, 0x8C, 0xE6, 0x03, 0x4B, 0xCC,
- 0xA3, 0xDC, 0x03, 0x4B, 0xCC, 0xA7, 0xCA, 0x03,
- 0x4B, 0xCC, 0xB1, 0xDC, 0x03, 0x4C, 0xCC, 0x81,
- // Bytes 30c0 - 30ff
- 0xE6, 0x03, 0x4C, 0xCC, 0x8C, 0xE6, 0x03, 0x4C,
- 0xCC, 0xA7, 0xCA, 0x03, 0x4C, 0xCC, 0xAD, 0xDC,
- 0x03, 0x4C, 0xCC, 0xB1, 0xDC, 0x03, 0x4D, 0xCC,
- 0x81, 0xE6, 0x03, 0x4D, 0xCC, 0x87, 0xE6, 0x03,
- 0x4D, 0xCC, 0xA3, 0xDC, 0x03, 0x4E, 0xCC, 0x80,
- 0xE6, 0x03, 0x4E, 0xCC, 0x81, 0xE6, 0x03, 0x4E,
- 0xCC, 0x83, 0xE6, 0x03, 0x4E, 0xCC, 0x87, 0xE6,
- 0x03, 0x4E, 0xCC, 0x8C, 0xE6, 0x03, 0x4E, 0xCC,
- // Bytes 3100 - 313f
- 0xA3, 0xDC, 0x03, 0x4E, 0xCC, 0xA7, 0xCA, 0x03,
- 0x4E, 0xCC, 0xAD, 0xDC, 0x03, 0x4E, 0xCC, 0xB1,
- 0xDC, 0x03, 0x4F, 0xCC, 0x80, 0xE6, 0x03, 0x4F,
- 0xCC, 0x81, 0xE6, 0x03, 0x4F, 0xCC, 0x86, 0xE6,
- 0x03, 0x4F, 0xCC, 0x89, 0xE6, 0x03, 0x4F, 0xCC,
- 0x8B, 0xE6, 0x03, 0x4F, 0xCC, 0x8C, 0xE6, 0x03,
- 0x4F, 0xCC, 0x8F, 0xE6, 0x03, 0x4F, 0xCC, 0x91,
- 0xE6, 0x03, 0x50, 0xCC, 0x81, 0xE6, 0x03, 0x50,
- // Bytes 3140 - 317f
- 0xCC, 0x87, 0xE6, 0x03, 0x52, 0xCC, 0x81, 0xE6,
- 0x03, 0x52, 0xCC, 0x87, 0xE6, 0x03, 0x52, 0xCC,
- 0x8C, 0xE6, 0x03, 0x52, 0xCC, 0x8F, 0xE6, 0x03,
- 0x52, 0xCC, 0x91, 0xE6, 0x03, 0x52, 0xCC, 0xA7,
- 0xCA, 0x03, 0x52, 0xCC, 0xB1, 0xDC, 0x03, 0x53,
- 0xCC, 0x82, 0xE6, 0x03, 0x53, 0xCC, 0x87, 0xE6,
- 0x03, 0x53, 0xCC, 0xA6, 0xDC, 0x03, 0x53, 0xCC,
- 0xA7, 0xCA, 0x03, 0x54, 0xCC, 0x87, 0xE6, 0x03,
- // Bytes 3180 - 31bf
- 0x54, 0xCC, 0x8C, 0xE6, 0x03, 0x54, 0xCC, 0xA3,
- 0xDC, 0x03, 0x54, 0xCC, 0xA6, 0xDC, 0x03, 0x54,
- 0xCC, 0xA7, 0xCA, 0x03, 0x54, 0xCC, 0xAD, 0xDC,
- 0x03, 0x54, 0xCC, 0xB1, 0xDC, 0x03, 0x55, 0xCC,
- 0x80, 0xE6, 0x03, 0x55, 0xCC, 0x81, 0xE6, 0x03,
- 0x55, 0xCC, 0x82, 0xE6, 0x03, 0x55, 0xCC, 0x86,
- 0xE6, 0x03, 0x55, 0xCC, 0x89, 0xE6, 0x03, 0x55,
- 0xCC, 0x8A, 0xE6, 0x03, 0x55, 0xCC, 0x8B, 0xE6,
- // Bytes 31c0 - 31ff
- 0x03, 0x55, 0xCC, 0x8C, 0xE6, 0x03, 0x55, 0xCC,
- 0x8F, 0xE6, 0x03, 0x55, 0xCC, 0x91, 0xE6, 0x03,
- 0x55, 0xCC, 0xA3, 0xDC, 0x03, 0x55, 0xCC, 0xA4,
- 0xDC, 0x03, 0x55, 0xCC, 0xA8, 0xCA, 0x03, 0x55,
- 0xCC, 0xAD, 0xDC, 0x03, 0x55, 0xCC, 0xB0, 0xDC,
- 0x03, 0x56, 0xCC, 0x83, 0xE6, 0x03, 0x56, 0xCC,
- 0xA3, 0xDC, 0x03, 0x57, 0xCC, 0x80, 0xE6, 0x03,
- 0x57, 0xCC, 0x81, 0xE6, 0x03, 0x57, 0xCC, 0x82,
- // Bytes 3200 - 323f
- 0xE6, 0x03, 0x57, 0xCC, 0x87, 0xE6, 0x03, 0x57,
- 0xCC, 0x88, 0xE6, 0x03, 0x57, 0xCC, 0xA3, 0xDC,
- 0x03, 0x58, 0xCC, 0x87, 0xE6, 0x03, 0x58, 0xCC,
- 0x88, 0xE6, 0x03, 0x59, 0xCC, 0x80, 0xE6, 0x03,
- 0x59, 0xCC, 0x81, 0xE6, 0x03, 0x59, 0xCC, 0x82,
- 0xE6, 0x03, 0x59, 0xCC, 0x83, 0xE6, 0x03, 0x59,
- 0xCC, 0x84, 0xE6, 0x03, 0x59, 0xCC, 0x87, 0xE6,
- 0x03, 0x59, 0xCC, 0x88, 0xE6, 0x03, 0x59, 0xCC,
- // Bytes 3240 - 327f
- 0x89, 0xE6, 0x03, 0x59, 0xCC, 0xA3, 0xDC, 0x03,
- 0x5A, 0xCC, 0x81, 0xE6, 0x03, 0x5A, 0xCC, 0x82,
- 0xE6, 0x03, 0x5A, 0xCC, 0x87, 0xE6, 0x03, 0x5A,
- 0xCC, 0x8C, 0xE6, 0x03, 0x5A, 0xCC, 0xA3, 0xDC,
- 0x03, 0x5A, 0xCC, 0xB1, 0xDC, 0x03, 0x61, 0xCC,
- 0x80, 0xE6, 0x03, 0x61, 0xCC, 0x81, 0xE6, 0x03,
- 0x61, 0xCC, 0x83, 0xE6, 0x03, 0x61, 0xCC, 0x84,
- 0xE6, 0x03, 0x61, 0xCC, 0x89, 0xE6, 0x03, 0x61,
- // Bytes 3280 - 32bf
- 0xCC, 0x8C, 0xE6, 0x03, 0x61, 0xCC, 0x8F, 0xE6,
- 0x03, 0x61, 0xCC, 0x91, 0xE6, 0x03, 0x61, 0xCC,
- 0xA5, 0xDC, 0x03, 0x61, 0xCC, 0xA8, 0xCA, 0x03,
- 0x62, 0xCC, 0x87, 0xE6, 0x03, 0x62, 0xCC, 0xA3,
- 0xDC, 0x03, 0x62, 0xCC, 0xB1, 0xDC, 0x03, 0x63,
- 0xCC, 0x81, 0xE6, 0x03, 0x63, 0xCC, 0x82, 0xE6,
- 0x03, 0x63, 0xCC, 0x87, 0xE6, 0x03, 0x63, 0xCC,
- 0x8C, 0xE6, 0x03, 0x64, 0xCC, 0x87, 0xE6, 0x03,
- // Bytes 32c0 - 32ff
- 0x64, 0xCC, 0x8C, 0xE6, 0x03, 0x64, 0xCC, 0xA3,
- 0xDC, 0x03, 0x64, 0xCC, 0xA7, 0xCA, 0x03, 0x64,
- 0xCC, 0xAD, 0xDC, 0x03, 0x64, 0xCC, 0xB1, 0xDC,
- 0x03, 0x65, 0xCC, 0x80, 0xE6, 0x03, 0x65, 0xCC,
- 0x81, 0xE6, 0x03, 0x65, 0xCC, 0x83, 0xE6, 0x03,
- 0x65, 0xCC, 0x86, 0xE6, 0x03, 0x65, 0xCC, 0x87,
- 0xE6, 0x03, 0x65, 0xCC, 0x88, 0xE6, 0x03, 0x65,
- 0xCC, 0x89, 0xE6, 0x03, 0x65, 0xCC, 0x8C, 0xE6,
- // Bytes 3300 - 333f
- 0x03, 0x65, 0xCC, 0x8F, 0xE6, 0x03, 0x65, 0xCC,
- 0x91, 0xE6, 0x03, 0x65, 0xCC, 0xA8, 0xCA, 0x03,
- 0x65, 0xCC, 0xAD, 0xDC, 0x03, 0x65, 0xCC, 0xB0,
- 0xDC, 0x03, 0x66, 0xCC, 0x87, 0xE6, 0x03, 0x67,
- 0xCC, 0x81, 0xE6, 0x03, 0x67, 0xCC, 0x82, 0xE6,
- 0x03, 0x67, 0xCC, 0x84, 0xE6, 0x03, 0x67, 0xCC,
- 0x86, 0xE6, 0x03, 0x67, 0xCC, 0x87, 0xE6, 0x03,
- 0x67, 0xCC, 0x8C, 0xE6, 0x03, 0x67, 0xCC, 0xA7,
- // Bytes 3340 - 337f
- 0xCA, 0x03, 0x68, 0xCC, 0x82, 0xE6, 0x03, 0x68,
- 0xCC, 0x87, 0xE6, 0x03, 0x68, 0xCC, 0x88, 0xE6,
- 0x03, 0x68, 0xCC, 0x8C, 0xE6, 0x03, 0x68, 0xCC,
- 0xA3, 0xDC, 0x03, 0x68, 0xCC, 0xA7, 0xCA, 0x03,
- 0x68, 0xCC, 0xAE, 0xDC, 0x03, 0x68, 0xCC, 0xB1,
- 0xDC, 0x03, 0x69, 0xCC, 0x80, 0xE6, 0x03, 0x69,
- 0xCC, 0x81, 0xE6, 0x03, 0x69, 0xCC, 0x82, 0xE6,
- 0x03, 0x69, 0xCC, 0x83, 0xE6, 0x03, 0x69, 0xCC,
- // Bytes 3380 - 33bf
- 0x84, 0xE6, 0x03, 0x69, 0xCC, 0x86, 0xE6, 0x03,
- 0x69, 0xCC, 0x89, 0xE6, 0x03, 0x69, 0xCC, 0x8C,
- 0xE6, 0x03, 0x69, 0xCC, 0x8F, 0xE6, 0x03, 0x69,
- 0xCC, 0x91, 0xE6, 0x03, 0x69, 0xCC, 0xA3, 0xDC,
- 0x03, 0x69, 0xCC, 0xA8, 0xCA, 0x03, 0x69, 0xCC,
- 0xB0, 0xDC, 0x03, 0x6A, 0xCC, 0x82, 0xE6, 0x03,
- 0x6A, 0xCC, 0x8C, 0xE6, 0x03, 0x6B, 0xCC, 0x81,
- 0xE6, 0x03, 0x6B, 0xCC, 0x8C, 0xE6, 0x03, 0x6B,
- // Bytes 33c0 - 33ff
- 0xCC, 0xA3, 0xDC, 0x03, 0x6B, 0xCC, 0xA7, 0xCA,
- 0x03, 0x6B, 0xCC, 0xB1, 0xDC, 0x03, 0x6C, 0xCC,
- 0x81, 0xE6, 0x03, 0x6C, 0xCC, 0x8C, 0xE6, 0x03,
- 0x6C, 0xCC, 0xA7, 0xCA, 0x03, 0x6C, 0xCC, 0xAD,
- 0xDC, 0x03, 0x6C, 0xCC, 0xB1, 0xDC, 0x03, 0x6D,
- 0xCC, 0x81, 0xE6, 0x03, 0x6D, 0xCC, 0x87, 0xE6,
- 0x03, 0x6D, 0xCC, 0xA3, 0xDC, 0x03, 0x6E, 0xCC,
- 0x80, 0xE6, 0x03, 0x6E, 0xCC, 0x81, 0xE6, 0x03,
- // Bytes 3400 - 343f
- 0x6E, 0xCC, 0x83, 0xE6, 0x03, 0x6E, 0xCC, 0x87,
- 0xE6, 0x03, 0x6E, 0xCC, 0x8C, 0xE6, 0x03, 0x6E,
- 0xCC, 0xA3, 0xDC, 0x03, 0x6E, 0xCC, 0xA7, 0xCA,
- 0x03, 0x6E, 0xCC, 0xAD, 0xDC, 0x03, 0x6E, 0xCC,
- 0xB1, 0xDC, 0x03, 0x6F, 0xCC, 0x80, 0xE6, 0x03,
- 0x6F, 0xCC, 0x81, 0xE6, 0x03, 0x6F, 0xCC, 0x86,
- 0xE6, 0x03, 0x6F, 0xCC, 0x89, 0xE6, 0x03, 0x6F,
- 0xCC, 0x8B, 0xE6, 0x03, 0x6F, 0xCC, 0x8C, 0xE6,
- // Bytes 3440 - 347f
- 0x03, 0x6F, 0xCC, 0x8F, 0xE6, 0x03, 0x6F, 0xCC,
- 0x91, 0xE6, 0x03, 0x70, 0xCC, 0x81, 0xE6, 0x03,
- 0x70, 0xCC, 0x87, 0xE6, 0x03, 0x72, 0xCC, 0x81,
- 0xE6, 0x03, 0x72, 0xCC, 0x87, 0xE6, 0x03, 0x72,
- 0xCC, 0x8C, 0xE6, 0x03, 0x72, 0xCC, 0x8F, 0xE6,
- 0x03, 0x72, 0xCC, 0x91, 0xE6, 0x03, 0x72, 0xCC,
- 0xA7, 0xCA, 0x03, 0x72, 0xCC, 0xB1, 0xDC, 0x03,
- 0x73, 0xCC, 0x82, 0xE6, 0x03, 0x73, 0xCC, 0x87,
- // Bytes 3480 - 34bf
- 0xE6, 0x03, 0x73, 0xCC, 0xA6, 0xDC, 0x03, 0x73,
- 0xCC, 0xA7, 0xCA, 0x03, 0x74, 0xCC, 0x87, 0xE6,
- 0x03, 0x74, 0xCC, 0x88, 0xE6, 0x03, 0x74, 0xCC,
- 0x8C, 0xE6, 0x03, 0x74, 0xCC, 0xA3, 0xDC, 0x03,
- 0x74, 0xCC, 0xA6, 0xDC, 0x03, 0x74, 0xCC, 0xA7,
- 0xCA, 0x03, 0x74, 0xCC, 0xAD, 0xDC, 0x03, 0x74,
- 0xCC, 0xB1, 0xDC, 0x03, 0x75, 0xCC, 0x80, 0xE6,
- 0x03, 0x75, 0xCC, 0x81, 0xE6, 0x03, 0x75, 0xCC,
- // Bytes 34c0 - 34ff
- 0x82, 0xE6, 0x03, 0x75, 0xCC, 0x86, 0xE6, 0x03,
- 0x75, 0xCC, 0x89, 0xE6, 0x03, 0x75, 0xCC, 0x8A,
- 0xE6, 0x03, 0x75, 0xCC, 0x8B, 0xE6, 0x03, 0x75,
- 0xCC, 0x8C, 0xE6, 0x03, 0x75, 0xCC, 0x8F, 0xE6,
- 0x03, 0x75, 0xCC, 0x91, 0xE6, 0x03, 0x75, 0xCC,
- 0xA3, 0xDC, 0x03, 0x75, 0xCC, 0xA4, 0xDC, 0x03,
- 0x75, 0xCC, 0xA8, 0xCA, 0x03, 0x75, 0xCC, 0xAD,
- 0xDC, 0x03, 0x75, 0xCC, 0xB0, 0xDC, 0x03, 0x76,
- // Bytes 3500 - 353f
- 0xCC, 0x83, 0xE6, 0x03, 0x76, 0xCC, 0xA3, 0xDC,
- 0x03, 0x77, 0xCC, 0x80, 0xE6, 0x03, 0x77, 0xCC,
- 0x81, 0xE6, 0x03, 0x77, 0xCC, 0x82, 0xE6, 0x03,
- 0x77, 0xCC, 0x87, 0xE6, 0x03, 0x77, 0xCC, 0x88,
- 0xE6, 0x03, 0x77, 0xCC, 0x8A, 0xE6, 0x03, 0x77,
- 0xCC, 0xA3, 0xDC, 0x03, 0x78, 0xCC, 0x87, 0xE6,
- 0x03, 0x78, 0xCC, 0x88, 0xE6, 0x03, 0x79, 0xCC,
- 0x80, 0xE6, 0x03, 0x79, 0xCC, 0x81, 0xE6, 0x03,
- // Bytes 3540 - 357f
- 0x79, 0xCC, 0x82, 0xE6, 0x03, 0x79, 0xCC, 0x83,
- 0xE6, 0x03, 0x79, 0xCC, 0x84, 0xE6, 0x03, 0x79,
- 0xCC, 0x87, 0xE6, 0x03, 0x79, 0xCC, 0x88, 0xE6,
- 0x03, 0x79, 0xCC, 0x89, 0xE6, 0x03, 0x79, 0xCC,
- 0x8A, 0xE6, 0x03, 0x79, 0xCC, 0xA3, 0xDC, 0x03,
- 0x7A, 0xCC, 0x81, 0xE6, 0x03, 0x7A, 0xCC, 0x82,
- 0xE6, 0x03, 0x7A, 0xCC, 0x87, 0xE6, 0x03, 0x7A,
- 0xCC, 0x8C, 0xE6, 0x03, 0x7A, 0xCC, 0xA3, 0xDC,
- // Bytes 3580 - 35bf
- 0x03, 0x7A, 0xCC, 0xB1, 0xDC, 0x04, 0xC2, 0xA8,
- 0xCC, 0x80, 0xE6, 0x04, 0xC2, 0xA8, 0xCC, 0x81,
- 0xE6, 0x04, 0xC2, 0xA8, 0xCD, 0x82, 0xE6, 0x04,
- 0xC3, 0x86, 0xCC, 0x81, 0xE6, 0x04, 0xC3, 0x86,
- 0xCC, 0x84, 0xE6, 0x04, 0xC3, 0x98, 0xCC, 0x81,
- 0xE6, 0x04, 0xC3, 0xA6, 0xCC, 0x81, 0xE6, 0x04,
- 0xC3, 0xA6, 0xCC, 0x84, 0xE6, 0x04, 0xC3, 0xB8,
- 0xCC, 0x81, 0xE6, 0x04, 0xC5, 0xBF, 0xCC, 0x87,
- // Bytes 35c0 - 35ff
- 0xE6, 0x04, 0xC6, 0xB7, 0xCC, 0x8C, 0xE6, 0x04,
- 0xCA, 0x92, 0xCC, 0x8C, 0xE6, 0x04, 0xCE, 0x91,
- 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0x91, 0xCC, 0x81,
- 0xE6, 0x04, 0xCE, 0x91, 0xCC, 0x84, 0xE6, 0x04,
- 0xCE, 0x91, 0xCC, 0x86, 0xE6, 0x04, 0xCE, 0x91,
- 0xCD, 0x85, 0xF0, 0x04, 0xCE, 0x95, 0xCC, 0x80,
- 0xE6, 0x04, 0xCE, 0x95, 0xCC, 0x81, 0xE6, 0x04,
- 0xCE, 0x97, 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0x97,
- // Bytes 3600 - 363f
- 0xCC, 0x81, 0xE6, 0x04, 0xCE, 0x97, 0xCD, 0x85,
- 0xF0, 0x04, 0xCE, 0x99, 0xCC, 0x80, 0xE6, 0x04,
- 0xCE, 0x99, 0xCC, 0x81, 0xE6, 0x04, 0xCE, 0x99,
- 0xCC, 0x84, 0xE6, 0x04, 0xCE, 0x99, 0xCC, 0x86,
- 0xE6, 0x04, 0xCE, 0x99, 0xCC, 0x88, 0xE6, 0x04,
- 0xCE, 0x9F, 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0x9F,
- 0xCC, 0x81, 0xE6, 0x04, 0xCE, 0xA1, 0xCC, 0x94,
- 0xE6, 0x04, 0xCE, 0xA5, 0xCC, 0x80, 0xE6, 0x04,
- // Bytes 3640 - 367f
- 0xCE, 0xA5, 0xCC, 0x81, 0xE6, 0x04, 0xCE, 0xA5,
- 0xCC, 0x84, 0xE6, 0x04, 0xCE, 0xA5, 0xCC, 0x86,
- 0xE6, 0x04, 0xCE, 0xA5, 0xCC, 0x88, 0xE6, 0x04,
- 0xCE, 0xA9, 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0xA9,
- 0xCC, 0x81, 0xE6, 0x04, 0xCE, 0xA9, 0xCD, 0x85,
- 0xF0, 0x04, 0xCE, 0xB1, 0xCC, 0x84, 0xE6, 0x04,
- 0xCE, 0xB1, 0xCC, 0x86, 0xE6, 0x04, 0xCE, 0xB1,
- 0xCD, 0x85, 0xF0, 0x04, 0xCE, 0xB5, 0xCC, 0x80,
- // Bytes 3680 - 36bf
- 0xE6, 0x04, 0xCE, 0xB5, 0xCC, 0x81, 0xE6, 0x04,
- 0xCE, 0xB7, 0xCD, 0x85, 0xF0, 0x04, 0xCE, 0xB9,
- 0xCC, 0x80, 0xE6, 0x04, 0xCE, 0xB9, 0xCC, 0x81,
- 0xE6, 0x04, 0xCE, 0xB9, 0xCC, 0x84, 0xE6, 0x04,
- 0xCE, 0xB9, 0xCC, 0x86, 0xE6, 0x04, 0xCE, 0xB9,
- 0xCD, 0x82, 0xE6, 0x04, 0xCE, 0xBF, 0xCC, 0x80,
- 0xE6, 0x04, 0xCE, 0xBF, 0xCC, 0x81, 0xE6, 0x04,
- 0xCF, 0x81, 0xCC, 0x93, 0xE6, 0x04, 0xCF, 0x81,
- // Bytes 36c0 - 36ff
- 0xCC, 0x94, 0xE6, 0x04, 0xCF, 0x85, 0xCC, 0x80,
- 0xE6, 0x04, 0xCF, 0x85, 0xCC, 0x81, 0xE6, 0x04,
- 0xCF, 0x85, 0xCC, 0x84, 0xE6, 0x04, 0xCF, 0x85,
- 0xCC, 0x86, 0xE6, 0x04, 0xCF, 0x85, 0xCD, 0x82,
- 0xE6, 0x04, 0xCF, 0x89, 0xCD, 0x85, 0xF0, 0x04,
- 0xCF, 0x92, 0xCC, 0x81, 0xE6, 0x04, 0xCF, 0x92,
- 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0x86, 0xCC, 0x88,
- 0xE6, 0x04, 0xD0, 0x90, 0xCC, 0x86, 0xE6, 0x04,
- // Bytes 3700 - 373f
- 0xD0, 0x90, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0x93,
- 0xCC, 0x81, 0xE6, 0x04, 0xD0, 0x95, 0xCC, 0x80,
- 0xE6, 0x04, 0xD0, 0x95, 0xCC, 0x86, 0xE6, 0x04,
- 0xD0, 0x95, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0x96,
- 0xCC, 0x86, 0xE6, 0x04, 0xD0, 0x96, 0xCC, 0x88,
- 0xE6, 0x04, 0xD0, 0x97, 0xCC, 0x88, 0xE6, 0x04,
- 0xD0, 0x98, 0xCC, 0x80, 0xE6, 0x04, 0xD0, 0x98,
- 0xCC, 0x84, 0xE6, 0x04, 0xD0, 0x98, 0xCC, 0x86,
- // Bytes 3740 - 377f
- 0xE6, 0x04, 0xD0, 0x98, 0xCC, 0x88, 0xE6, 0x04,
- 0xD0, 0x9A, 0xCC, 0x81, 0xE6, 0x04, 0xD0, 0x9E,
- 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xA3, 0xCC, 0x84,
- 0xE6, 0x04, 0xD0, 0xA3, 0xCC, 0x86, 0xE6, 0x04,
- 0xD0, 0xA3, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xA3,
- 0xCC, 0x8B, 0xE6, 0x04, 0xD0, 0xA7, 0xCC, 0x88,
- 0xE6, 0x04, 0xD0, 0xAB, 0xCC, 0x88, 0xE6, 0x04,
- 0xD0, 0xAD, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xB0,
- // Bytes 3780 - 37bf
- 0xCC, 0x86, 0xE6, 0x04, 0xD0, 0xB0, 0xCC, 0x88,
- 0xE6, 0x04, 0xD0, 0xB3, 0xCC, 0x81, 0xE6, 0x04,
- 0xD0, 0xB5, 0xCC, 0x80, 0xE6, 0x04, 0xD0, 0xB5,
- 0xCC, 0x86, 0xE6, 0x04, 0xD0, 0xB5, 0xCC, 0x88,
- 0xE6, 0x04, 0xD0, 0xB6, 0xCC, 0x86, 0xE6, 0x04,
- 0xD0, 0xB6, 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xB7,
- 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xB8, 0xCC, 0x80,
- 0xE6, 0x04, 0xD0, 0xB8, 0xCC, 0x84, 0xE6, 0x04,
- // Bytes 37c0 - 37ff
- 0xD0, 0xB8, 0xCC, 0x86, 0xE6, 0x04, 0xD0, 0xB8,
- 0xCC, 0x88, 0xE6, 0x04, 0xD0, 0xBA, 0xCC, 0x81,
- 0xE6, 0x04, 0xD0, 0xBE, 0xCC, 0x88, 0xE6, 0x04,
- 0xD1, 0x83, 0xCC, 0x84, 0xE6, 0x04, 0xD1, 0x83,
- 0xCC, 0x86, 0xE6, 0x04, 0xD1, 0x83, 0xCC, 0x88,
- 0xE6, 0x04, 0xD1, 0x83, 0xCC, 0x8B, 0xE6, 0x04,
- 0xD1, 0x87, 0xCC, 0x88, 0xE6, 0x04, 0xD1, 0x8B,
- 0xCC, 0x88, 0xE6, 0x04, 0xD1, 0x8D, 0xCC, 0x88,
- // Bytes 3800 - 383f
- 0xE6, 0x04, 0xD1, 0x96, 0xCC, 0x88, 0xE6, 0x04,
- 0xD1, 0xB4, 0xCC, 0x8F, 0xE6, 0x04, 0xD1, 0xB5,
- 0xCC, 0x8F, 0xE6, 0x04, 0xD3, 0x98, 0xCC, 0x88,
- 0xE6, 0x04, 0xD3, 0x99, 0xCC, 0x88, 0xE6, 0x04,
- 0xD3, 0xA8, 0xCC, 0x88, 0xE6, 0x04, 0xD3, 0xA9,
- 0xCC, 0x88, 0xE6, 0x04, 0xD8, 0xA7, 0xD9, 0x93,
- 0xE6, 0x04, 0xD8, 0xA7, 0xD9, 0x94, 0xE6, 0x04,
- 0xD8, 0xA7, 0xD9, 0x95, 0xDC, 0x04, 0xD9, 0x88,
- // Bytes 3840 - 387f
- 0xD9, 0x94, 0xE6, 0x04, 0xD9, 0x8A, 0xD9, 0x94,
- 0xE6, 0x04, 0xDB, 0x81, 0xD9, 0x94, 0xE6, 0x04,
- 0xDB, 0x92, 0xD9, 0x94, 0xE6, 0x04, 0xDB, 0x95,
- 0xD9, 0x94, 0xE6, 0x05, 0x41, 0xCC, 0x82, 0xCC,
- 0x80, 0xE6, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x81,
- 0xE6, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x83, 0xE6,
- 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05,
- 0x41, 0xCC, 0x86, 0xCC, 0x80, 0xE6, 0x05, 0x41,
- // Bytes 3880 - 38bf
- 0xCC, 0x86, 0xCC, 0x81, 0xE6, 0x05, 0x41, 0xCC,
- 0x86, 0xCC, 0x83, 0xE6, 0x05, 0x41, 0xCC, 0x86,
- 0xCC, 0x89, 0xE6, 0x05, 0x41, 0xCC, 0x87, 0xCC,
- 0x84, 0xE6, 0x05, 0x41, 0xCC, 0x88, 0xCC, 0x84,
- 0xE6, 0x05, 0x41, 0xCC, 0x8A, 0xCC, 0x81, 0xE6,
- 0x05, 0x41, 0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05,
- 0x41, 0xCC, 0xA3, 0xCC, 0x86, 0xE6, 0x05, 0x43,
- 0xCC, 0xA7, 0xCC, 0x81, 0xE6, 0x05, 0x45, 0xCC,
- // Bytes 38c0 - 38ff
- 0x82, 0xCC, 0x80, 0xE6, 0x05, 0x45, 0xCC, 0x82,
- 0xCC, 0x81, 0xE6, 0x05, 0x45, 0xCC, 0x82, 0xCC,
- 0x83, 0xE6, 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x89,
- 0xE6, 0x05, 0x45, 0xCC, 0x84, 0xCC, 0x80, 0xE6,
- 0x05, 0x45, 0xCC, 0x84, 0xCC, 0x81, 0xE6, 0x05,
- 0x45, 0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05, 0x45,
- 0xCC, 0xA7, 0xCC, 0x86, 0xE6, 0x05, 0x49, 0xCC,
- 0x88, 0xCC, 0x81, 0xE6, 0x05, 0x4C, 0xCC, 0xA3,
- // Bytes 3900 - 393f
- 0xCC, 0x84, 0xE6, 0x05, 0x4F, 0xCC, 0x82, 0xCC,
- 0x80, 0xE6, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x81,
- 0xE6, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x83, 0xE6,
- 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05,
- 0x4F, 0xCC, 0x83, 0xCC, 0x81, 0xE6, 0x05, 0x4F,
- 0xCC, 0x83, 0xCC, 0x84, 0xE6, 0x05, 0x4F, 0xCC,
- 0x83, 0xCC, 0x88, 0xE6, 0x05, 0x4F, 0xCC, 0x84,
- 0xCC, 0x80, 0xE6, 0x05, 0x4F, 0xCC, 0x84, 0xCC,
- // Bytes 3940 - 397f
- 0x81, 0xE6, 0x05, 0x4F, 0xCC, 0x87, 0xCC, 0x84,
- 0xE6, 0x05, 0x4F, 0xCC, 0x88, 0xCC, 0x84, 0xE6,
- 0x05, 0x4F, 0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05,
- 0x4F, 0xCC, 0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x4F,
- 0xCC, 0x9B, 0xCC, 0x83, 0xE6, 0x05, 0x4F, 0xCC,
- 0x9B, 0xCC, 0x89, 0xE6, 0x05, 0x4F, 0xCC, 0x9B,
- 0xCC, 0xA3, 0xDC, 0x05, 0x4F, 0xCC, 0xA3, 0xCC,
- 0x82, 0xE6, 0x05, 0x4F, 0xCC, 0xA8, 0xCC, 0x84,
- // Bytes 3980 - 39bf
- 0xE6, 0x05, 0x52, 0xCC, 0xA3, 0xCC, 0x84, 0xE6,
- 0x05, 0x53, 0xCC, 0x81, 0xCC, 0x87, 0xE6, 0x05,
- 0x53, 0xCC, 0x8C, 0xCC, 0x87, 0xE6, 0x05, 0x53,
- 0xCC, 0xA3, 0xCC, 0x87, 0xE6, 0x05, 0x55, 0xCC,
- 0x83, 0xCC, 0x81, 0xE6, 0x05, 0x55, 0xCC, 0x84,
- 0xCC, 0x88, 0xE6, 0x05, 0x55, 0xCC, 0x88, 0xCC,
- 0x80, 0xE6, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x81,
- 0xE6, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x84, 0xE6,
- // Bytes 39c0 - 39ff
- 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x8C, 0xE6, 0x05,
- 0x55, 0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05, 0x55,
- 0xCC, 0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x55, 0xCC,
- 0x9B, 0xCC, 0x83, 0xE6, 0x05, 0x55, 0xCC, 0x9B,
- 0xCC, 0x89, 0xE6, 0x05, 0x55, 0xCC, 0x9B, 0xCC,
- 0xA3, 0xDC, 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x80,
- 0xE6, 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x81, 0xE6,
- 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x83, 0xE6, 0x05,
- // Bytes 3a00 - 3a3f
- 0x61, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05, 0x61,
- 0xCC, 0x86, 0xCC, 0x80, 0xE6, 0x05, 0x61, 0xCC,
- 0x86, 0xCC, 0x81, 0xE6, 0x05, 0x61, 0xCC, 0x86,
- 0xCC, 0x83, 0xE6, 0x05, 0x61, 0xCC, 0x86, 0xCC,
- 0x89, 0xE6, 0x05, 0x61, 0xCC, 0x87, 0xCC, 0x84,
- 0xE6, 0x05, 0x61, 0xCC, 0x88, 0xCC, 0x84, 0xE6,
- 0x05, 0x61, 0xCC, 0x8A, 0xCC, 0x81, 0xE6, 0x05,
- 0x61, 0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05, 0x61,
- // Bytes 3a40 - 3a7f
- 0xCC, 0xA3, 0xCC, 0x86, 0xE6, 0x05, 0x63, 0xCC,
- 0xA7, 0xCC, 0x81, 0xE6, 0x05, 0x65, 0xCC, 0x82,
- 0xCC, 0x80, 0xE6, 0x05, 0x65, 0xCC, 0x82, 0xCC,
- 0x81, 0xE6, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x83,
- 0xE6, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x89, 0xE6,
- 0x05, 0x65, 0xCC, 0x84, 0xCC, 0x80, 0xE6, 0x05,
- 0x65, 0xCC, 0x84, 0xCC, 0x81, 0xE6, 0x05, 0x65,
- 0xCC, 0xA3, 0xCC, 0x82, 0xE6, 0x05, 0x65, 0xCC,
- // Bytes 3a80 - 3abf
- 0xA7, 0xCC, 0x86, 0xE6, 0x05, 0x69, 0xCC, 0x88,
- 0xCC, 0x81, 0xE6, 0x05, 0x6C, 0xCC, 0xA3, 0xCC,
- 0x84, 0xE6, 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x80,
- 0xE6, 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x81, 0xE6,
- 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x83, 0xE6, 0x05,
- 0x6F, 0xCC, 0x82, 0xCC, 0x89, 0xE6, 0x05, 0x6F,
- 0xCC, 0x83, 0xCC, 0x81, 0xE6, 0x05, 0x6F, 0xCC,
- 0x83, 0xCC, 0x84, 0xE6, 0x05, 0x6F, 0xCC, 0x83,
- // Bytes 3ac0 - 3aff
- 0xCC, 0x88, 0xE6, 0x05, 0x6F, 0xCC, 0x84, 0xCC,
- 0x80, 0xE6, 0x05, 0x6F, 0xCC, 0x84, 0xCC, 0x81,
- 0xE6, 0x05, 0x6F, 0xCC, 0x87, 0xCC, 0x84, 0xE6,
- 0x05, 0x6F, 0xCC, 0x88, 0xCC, 0x84, 0xE6, 0x05,
- 0x6F, 0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05, 0x6F,
- 0xCC, 0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x6F, 0xCC,
- 0x9B, 0xCC, 0x83, 0xE6, 0x05, 0x6F, 0xCC, 0x9B,
- 0xCC, 0x89, 0xE6, 0x05, 0x6F, 0xCC, 0x9B, 0xCC,
- // Bytes 3b00 - 3b3f
- 0xA3, 0xDC, 0x05, 0x6F, 0xCC, 0xA3, 0xCC, 0x82,
- 0xE6, 0x05, 0x6F, 0xCC, 0xA8, 0xCC, 0x84, 0xE6,
- 0x05, 0x72, 0xCC, 0xA3, 0xCC, 0x84, 0xE6, 0x05,
- 0x73, 0xCC, 0x81, 0xCC, 0x87, 0xE6, 0x05, 0x73,
- 0xCC, 0x8C, 0xCC, 0x87, 0xE6, 0x05, 0x73, 0xCC,
- 0xA3, 0xCC, 0x87, 0xE6, 0x05, 0x75, 0xCC, 0x83,
- 0xCC, 0x81, 0xE6, 0x05, 0x75, 0xCC, 0x84, 0xCC,
- 0x88, 0xE6, 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x80,
- // Bytes 3b40 - 3b7f
- 0xE6, 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x81, 0xE6,
- 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x84, 0xE6, 0x05,
- 0x75, 0xCC, 0x88, 0xCC, 0x8C, 0xE6, 0x05, 0x75,
- 0xCC, 0x9B, 0xCC, 0x80, 0xE6, 0x05, 0x75, 0xCC,
- 0x9B, 0xCC, 0x81, 0xE6, 0x05, 0x75, 0xCC, 0x9B,
- 0xCC, 0x83, 0xE6, 0x05, 0x75, 0xCC, 0x9B, 0xCC,
- 0x89, 0xE6, 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0xA3,
- 0xDC, 0x05, 0xE1, 0xBE, 0xBF, 0xCC, 0x80, 0xE6,
- // Bytes 3b80 - 3bbf
- 0x05, 0xE1, 0xBE, 0xBF, 0xCC, 0x81, 0xE6, 0x05,
- 0xE1, 0xBE, 0xBF, 0xCD, 0x82, 0xE6, 0x05, 0xE1,
- 0xBF, 0xBE, 0xCC, 0x80, 0xE6, 0x05, 0xE1, 0xBF,
- 0xBE, 0xCC, 0x81, 0xE6, 0x05, 0xE1, 0xBF, 0xBE,
- 0xCD, 0x82, 0xE6, 0x05, 0xE2, 0x86, 0x90, 0xCC,
- 0xB8, 0x01, 0x05, 0xE2, 0x86, 0x92, 0xCC, 0xB8,
- 0x01, 0x05, 0xE2, 0x86, 0x94, 0xCC, 0xB8, 0x01,
- 0x05, 0xE2, 0x87, 0x90, 0xCC, 0xB8, 0x01, 0x05,
- // Bytes 3bc0 - 3bff
- 0xE2, 0x87, 0x92, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
- 0x87, 0x94, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x88,
- 0x83, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x88, 0x88,
- 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x88, 0x8B, 0xCC,
- 0xB8, 0x01, 0x05, 0xE2, 0x88, 0xA3, 0xCC, 0xB8,
- 0x01, 0x05, 0xE2, 0x88, 0xA5, 0xCC, 0xB8, 0x01,
- 0x05, 0xE2, 0x88, 0xBC, 0xCC, 0xB8, 0x01, 0x05,
- 0xE2, 0x89, 0x83, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
- // Bytes 3c00 - 3c3f
- 0x89, 0x85, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89,
- 0x88, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0x8D,
- 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xA1, 0xCC,
- 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xA4, 0xCC, 0xB8,
- 0x01, 0x05, 0xE2, 0x89, 0xA5, 0xCC, 0xB8, 0x01,
- 0x05, 0xE2, 0x89, 0xB2, 0xCC, 0xB8, 0x01, 0x05,
- 0xE2, 0x89, 0xB3, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
- 0x89, 0xB6, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89,
- // Bytes 3c40 - 3c7f
- 0xB7, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xBA,
- 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xBB, 0xCC,
- 0xB8, 0x01, 0x05, 0xE2, 0x89, 0xBC, 0xCC, 0xB8,
- 0x01, 0x05, 0xE2, 0x89, 0xBD, 0xCC, 0xB8, 0x01,
- 0x05, 0xE2, 0x8A, 0x82, 0xCC, 0xB8, 0x01, 0x05,
- 0xE2, 0x8A, 0x83, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
- 0x8A, 0x86, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A,
- 0x87, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0x91,
- // Bytes 3c80 - 3cbf
- 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0x92, 0xCC,
- 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0xA2, 0xCC, 0xB8,
- 0x01, 0x05, 0xE2, 0x8A, 0xA8, 0xCC, 0xB8, 0x01,
- 0x05, 0xE2, 0x8A, 0xA9, 0xCC, 0xB8, 0x01, 0x05,
- 0xE2, 0x8A, 0xAB, 0xCC, 0xB8, 0x01, 0x05, 0xE2,
- 0x8A, 0xB2, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A,
- 0xB3, 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0xB4,
- 0xCC, 0xB8, 0x01, 0x05, 0xE2, 0x8A, 0xB5, 0xCC,
- // Bytes 3cc0 - 3cff
- 0xB8, 0x01, 0x06, 0xCE, 0x91, 0xCC, 0x93, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0x91, 0xCC, 0x94, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0x97, 0xCC, 0x93, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0x97, 0xCC, 0x94, 0xCD,
- // Bytes 3d00 - 3d3f
- 0x85, 0xF0, 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCD,
- 0x82, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCD,
- 0x82, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC,
- // Bytes 3d40 - 3d7f
- 0x81, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCD,
- 0x82, 0xE6, 0x06, 0xCE, 0xA9, 0xCC, 0x93, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xA9, 0xCC, 0x94, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x80, 0xCD,
- // Bytes 3d80 - 3dbf
- 0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x81, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x93, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCC, 0x94, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB1, 0xCD, 0x82, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC,
- // Bytes 3dc0 - 3dff
- 0x81, 0xE6, 0x06, 0xCE, 0xB7, 0xCC, 0x80, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCC, 0x81, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCC, 0x93, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCC, 0x94, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB7, 0xCD, 0x82, 0xCD,
- 0x85, 0xF0, 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCD,
- // Bytes 3e00 - 3e3f
- 0x82, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCD,
- 0x82, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCD,
- 0x82, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC,
- // Bytes 3e40 - 3e7f
- 0x81, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC,
- 0x80, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC,
- 0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCD,
- 0x82, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC,
- 0x80, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC,
- 0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCD,
- // Bytes 3e80 - 3ebf
- 0x82, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC,
- 0x80, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCD,
- 0x82, 0xE6, 0x06, 0xCF, 0x89, 0xCC, 0x80, 0xCD,
- 0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCC, 0x81, 0xCD,
- 0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCC, 0x93, 0xCD,
- 0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCC, 0x94, 0xCD,
- 0x85, 0xF0, 0x06, 0xCF, 0x89, 0xCD, 0x82, 0xCD,
- // Bytes 3ec0 - 3eff
- 0x85, 0xF0, 0x06, 0xE0, 0xA4, 0xA8, 0xE0, 0xA4,
- 0xBC, 0x07, 0x06, 0xE0, 0xA4, 0xB0, 0xE0, 0xA4,
- 0xBC, 0x07, 0x06, 0xE0, 0xA4, 0xB3, 0xE0, 0xA4,
- 0xBC, 0x07, 0x06, 0xE0, 0xB1, 0x86, 0xE0, 0xB1,
- 0x96, 0x5B, 0x06, 0xE0, 0xB7, 0x99, 0xE0, 0xB7,
- 0x8A, 0x09, 0x06, 0xE3, 0x81, 0x86, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x8B, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x8D, 0xE3, 0x82,
- // Bytes 3f00 - 3f3f
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x8F, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x91, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x93, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x95, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x97, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x99, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x9B, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x9D, 0xE3, 0x82,
- // Bytes 3f40 - 3f7f
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0x9F, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xA1, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xA4, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xA6, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xA8, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82,
- // Bytes 3f80 - 3fbf
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x82, 0x9D, 0xE3, 0x82,
- // Bytes 3fc0 - 3fff
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xA6, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xAD, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xAF, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xB1, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xB3, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xB5, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xB7, 0xE3, 0x82,
- // Bytes 4000 - 403f
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xB9, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xBB, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xBD, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x82, 0xBF, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x81, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x84, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x86, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x88, 0xE3, 0x82,
- // Bytes 4040 - 407f
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82,
- // Bytes 4080 - 40bf
- 0x9A, 0x08, 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
- 0x9A, 0x08, 0x06, 0xE3, 0x83, 0xAF, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0xB0, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0xB1, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0xB2, 0xE3, 0x82,
- 0x99, 0x08, 0x06, 0xE3, 0x83, 0xBD, 0xE3, 0x82,
- 0x99, 0x08, 0x08, 0xCE, 0x91, 0xCC, 0x93, 0xCC,
- // Bytes 40c0 - 40ff
- 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0x91, 0xCC,
- 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
- 0x91, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xF0,
- 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCC, 0x80, 0xCD,
- 0x85, 0xF0, 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCC,
- 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0x91, 0xCC,
- 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
- 0x97, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xF0,
- // Bytes 4100 - 413f
- 0x08, 0xCE, 0x97, 0xCC, 0x93, 0xCC, 0x81, 0xCD,
- 0x85, 0xF0, 0x08, 0xCE, 0x97, 0xCC, 0x93, 0xCD,
- 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0x97, 0xCC,
- 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
- 0x97, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xF0,
- 0x08, 0xCE, 0x97, 0xCC, 0x94, 0xCD, 0x82, 0xCD,
- 0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC, 0x93, 0xCC,
- 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC,
- // Bytes 4140 - 417f
- 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
- 0xA9, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xF0,
- 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCC, 0x80, 0xCD,
- 0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCC,
- 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xA9, 0xCC,
- 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
- 0xB1, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xF0,
- 0x08, 0xCE, 0xB1, 0xCC, 0x93, 0xCC, 0x81, 0xCD,
- // Bytes 4180 - 41bf
- 0x85, 0xF0, 0x08, 0xCE, 0xB1, 0xCC, 0x93, 0xCD,
- 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xB1, 0xCC,
- 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
- 0xB1, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xF0,
- 0x08, 0xCE, 0xB1, 0xCC, 0x94, 0xCD, 0x82, 0xCD,
- 0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC, 0x93, 0xCC,
- 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC,
- 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE,
- // Bytes 41c0 - 41ff
- 0xB7, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xF0,
- 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCC, 0x80, 0xCD,
- 0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCC,
- 0x81, 0xCD, 0x85, 0xF0, 0x08, 0xCE, 0xB7, 0xCC,
- 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCF,
- 0x89, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xF0,
- 0x08, 0xCF, 0x89, 0xCC, 0x93, 0xCC, 0x81, 0xCD,
- 0x85, 0xF0, 0x08, 0xCF, 0x89, 0xCC, 0x93, 0xCD,
- // Bytes 4200 - 423f
- 0x82, 0xCD, 0x85, 0xF0, 0x08, 0xCF, 0x89, 0xCC,
- 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xF0, 0x08, 0xCF,
- 0x89, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xF0,
- 0x08, 0xCF, 0x89, 0xCC, 0x94, 0xCD, 0x82, 0xCD,
- 0x85, 0xF0, 0x08, 0xF0, 0x91, 0x82, 0x99, 0xF0,
- 0x91, 0x82, 0xBA, 0x07, 0x08, 0xF0, 0x91, 0x82,
- 0x9B, 0xF0, 0x91, 0x82, 0xBA, 0x07, 0x08, 0xF0,
- 0x91, 0x82, 0xA5, 0xF0, 0x91, 0x82, 0xBA, 0x07,
- // Bytes 4240 - 427f
- 0x43, 0x20, 0xCC, 0x81, 0xE6, 0x43, 0x20, 0xCC,
- 0x83, 0xE6, 0x43, 0x20, 0xCC, 0x84, 0xE6, 0x43,
- 0x20, 0xCC, 0x85, 0xE6, 0x43, 0x20, 0xCC, 0x86,
- 0xE6, 0x43, 0x20, 0xCC, 0x87, 0xE6, 0x43, 0x20,
- 0xCC, 0x88, 0xE6, 0x43, 0x20, 0xCC, 0x8A, 0xE6,
- 0x43, 0x20, 0xCC, 0x8B, 0xE6, 0x43, 0x20, 0xCC,
- 0x93, 0xE6, 0x43, 0x20, 0xCC, 0x94, 0xE6, 0x43,
- 0x20, 0xCC, 0xA7, 0xCA, 0x43, 0x20, 0xCC, 0xA8,
- // Bytes 4280 - 42bf
- 0xCA, 0x43, 0x20, 0xCC, 0xB3, 0xDC, 0x43, 0x20,
- 0xCD, 0x82, 0xE6, 0x43, 0x20, 0xCD, 0x85, 0xF0,
- 0x43, 0x20, 0xD9, 0x8B, 0x1B, 0x43, 0x20, 0xD9,
- 0x8C, 0x1C, 0x43, 0x20, 0xD9, 0x8D, 0x1D, 0x43,
- 0x20, 0xD9, 0x8E, 0x1E, 0x43, 0x20, 0xD9, 0x8F,
- 0x1F, 0x43, 0x20, 0xD9, 0x90, 0x20, 0x43, 0x20,
- 0xD9, 0x91, 0x21, 0x43, 0x20, 0xD9, 0x92, 0x22,
- 0x43, 0x41, 0xCC, 0x8A, 0xE6, 0x43, 0x73, 0xCC,
- // Bytes 42c0 - 42ff
- 0x87, 0xE6, 0x44, 0x20, 0xE3, 0x82, 0x99, 0x08,
- 0x44, 0x20, 0xE3, 0x82, 0x9A, 0x08, 0x44, 0xC2,
- 0xA8, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0x91, 0xCC,
- 0x81, 0xE6, 0x44, 0xCE, 0x95, 0xCC, 0x81, 0xE6,
- 0x44, 0xCE, 0x97, 0xCC, 0x81, 0xE6, 0x44, 0xCE,
- 0x99, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0x9F, 0xCC,
- 0x81, 0xE6, 0x44, 0xCE, 0xA5, 0xCC, 0x81, 0xE6,
- 0x44, 0xCE, 0xA5, 0xCC, 0x88, 0xE6, 0x44, 0xCE,
- // Bytes 4300 - 433f
- 0xA9, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0xB1, 0xCC,
- 0x81, 0xE6, 0x44, 0xCE, 0xB5, 0xCC, 0x81, 0xE6,
- 0x44, 0xCE, 0xB7, 0xCC, 0x81, 0xE6, 0x44, 0xCE,
- 0xB9, 0xCC, 0x81, 0xE6, 0x44, 0xCE, 0xBF, 0xCC,
- 0x81, 0xE6, 0x44, 0xCF, 0x85, 0xCC, 0x81, 0xE6,
- 0x44, 0xCF, 0x89, 0xCC, 0x81, 0xE6, 0x44, 0xD7,
- 0x90, 0xD6, 0xB7, 0x11, 0x44, 0xD7, 0x90, 0xD6,
- 0xB8, 0x12, 0x44, 0xD7, 0x90, 0xD6, 0xBC, 0x15,
- // Bytes 4340 - 437f
- 0x44, 0xD7, 0x91, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
- 0x91, 0xD6, 0xBF, 0x17, 0x44, 0xD7, 0x92, 0xD6,
- 0xBC, 0x15, 0x44, 0xD7, 0x93, 0xD6, 0xBC, 0x15,
- 0x44, 0xD7, 0x94, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
- 0x95, 0xD6, 0xB9, 0x13, 0x44, 0xD7, 0x95, 0xD6,
- 0xBC, 0x15, 0x44, 0xD7, 0x96, 0xD6, 0xBC, 0x15,
- 0x44, 0xD7, 0x98, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
- 0x99, 0xD6, 0xB4, 0x0E, 0x44, 0xD7, 0x99, 0xD6,
- // Bytes 4380 - 43bf
- 0xBC, 0x15, 0x44, 0xD7, 0x9A, 0xD6, 0xBC, 0x15,
- 0x44, 0xD7, 0x9B, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
- 0x9B, 0xD6, 0xBF, 0x17, 0x44, 0xD7, 0x9C, 0xD6,
- 0xBC, 0x15, 0x44, 0xD7, 0x9E, 0xD6, 0xBC, 0x15,
- 0x44, 0xD7, 0xA0, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
- 0xA1, 0xD6, 0xBC, 0x15, 0x44, 0xD7, 0xA3, 0xD6,
- 0xBC, 0x15, 0x44, 0xD7, 0xA4, 0xD6, 0xBC, 0x15,
- 0x44, 0xD7, 0xA4, 0xD6, 0xBF, 0x17, 0x44, 0xD7,
- // Bytes 43c0 - 43ff
- 0xA6, 0xD6, 0xBC, 0x15, 0x44, 0xD7, 0xA7, 0xD6,
- 0xBC, 0x15, 0x44, 0xD7, 0xA8, 0xD6, 0xBC, 0x15,
- 0x44, 0xD7, 0xA9, 0xD6, 0xBC, 0x15, 0x44, 0xD7,
- 0xA9, 0xD7, 0x81, 0x18, 0x44, 0xD7, 0xA9, 0xD7,
- 0x82, 0x19, 0x44, 0xD7, 0xAA, 0xD6, 0xBC, 0x15,
- 0x44, 0xD7, 0xB2, 0xD6, 0xB7, 0x11, 0x44, 0xD8,
- 0xA7, 0xD9, 0x8B, 0x1B, 0x44, 0xD8, 0xA7, 0xD9,
- 0x93, 0xE6, 0x44, 0xD8, 0xA7, 0xD9, 0x94, 0xE6,
- // Bytes 4400 - 443f
- 0x44, 0xD8, 0xA7, 0xD9, 0x95, 0xDC, 0x44, 0xD8,
- 0xB0, 0xD9, 0xB0, 0x23, 0x44, 0xD8, 0xB1, 0xD9,
- 0xB0, 0x23, 0x44, 0xD9, 0x80, 0xD9, 0x8B, 0x1B,
- 0x44, 0xD9, 0x80, 0xD9, 0x8E, 0x1E, 0x44, 0xD9,
- 0x80, 0xD9, 0x8F, 0x1F, 0x44, 0xD9, 0x80, 0xD9,
- 0x90, 0x20, 0x44, 0xD9, 0x80, 0xD9, 0x91, 0x21,
- 0x44, 0xD9, 0x80, 0xD9, 0x92, 0x22, 0x44, 0xD9,
- 0x87, 0xD9, 0xB0, 0x23, 0x44, 0xD9, 0x88, 0xD9,
- // Bytes 4440 - 447f
- 0x94, 0xE6, 0x44, 0xD9, 0x89, 0xD9, 0xB0, 0x23,
- 0x44, 0xD9, 0x8A, 0xD9, 0x94, 0xE6, 0x44, 0xDB,
- 0x92, 0xD9, 0x94, 0xE6, 0x44, 0xDB, 0x95, 0xD9,
- 0x94, 0xE6, 0x45, 0x20, 0xCC, 0x88, 0xCC, 0x80,
- 0xE6, 0x45, 0x20, 0xCC, 0x88, 0xCC, 0x81, 0xE6,
- 0x45, 0x20, 0xCC, 0x88, 0xCD, 0x82, 0xE6, 0x45,
- 0x20, 0xCC, 0x93, 0xCC, 0x80, 0xE6, 0x45, 0x20,
- 0xCC, 0x93, 0xCC, 0x81, 0xE6, 0x45, 0x20, 0xCC,
- // Bytes 4480 - 44bf
- 0x93, 0xCD, 0x82, 0xE6, 0x45, 0x20, 0xCC, 0x94,
- 0xCC, 0x80, 0xE6, 0x45, 0x20, 0xCC, 0x94, 0xCC,
- 0x81, 0xE6, 0x45, 0x20, 0xCC, 0x94, 0xCD, 0x82,
- 0xE6, 0x45, 0x20, 0xD9, 0x8C, 0xD9, 0x91, 0x21,
- 0x45, 0x20, 0xD9, 0x8D, 0xD9, 0x91, 0x21, 0x45,
- 0x20, 0xD9, 0x8E, 0xD9, 0x91, 0x21, 0x45, 0x20,
- 0xD9, 0x8F, 0xD9, 0x91, 0x21, 0x45, 0x20, 0xD9,
- 0x90, 0xD9, 0x91, 0x21, 0x45, 0x20, 0xD9, 0x91,
- // Bytes 44c0 - 44ff
- 0xD9, 0xB0, 0x23, 0x45, 0xE2, 0xAB, 0x9D, 0xCC,
- 0xB8, 0x01, 0x46, 0xCE, 0xB9, 0xCC, 0x88, 0xCC,
- 0x81, 0xE6, 0x46, 0xCF, 0x85, 0xCC, 0x88, 0xCC,
- 0x81, 0xE6, 0x46, 0xD7, 0xA9, 0xD6, 0xBC, 0xD7,
- 0x81, 0x18, 0x46, 0xD7, 0xA9, 0xD6, 0xBC, 0xD7,
- 0x82, 0x19, 0x46, 0xD9, 0x80, 0xD9, 0x8E, 0xD9,
- 0x91, 0x21, 0x46, 0xD9, 0x80, 0xD9, 0x8F, 0xD9,
- 0x91, 0x21, 0x46, 0xD9, 0x80, 0xD9, 0x90, 0xD9,
- // Bytes 4500 - 453f
- 0x91, 0x21, 0x46, 0xE0, 0xA4, 0x95, 0xE0, 0xA4,
- 0xBC, 0x07, 0x46, 0xE0, 0xA4, 0x96, 0xE0, 0xA4,
- 0xBC, 0x07, 0x46, 0xE0, 0xA4, 0x97, 0xE0, 0xA4,
- 0xBC, 0x07, 0x46, 0xE0, 0xA4, 0x9C, 0xE0, 0xA4,
- 0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xA1, 0xE0, 0xA4,
- 0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xA2, 0xE0, 0xA4,
- 0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xAB, 0xE0, 0xA4,
- 0xBC, 0x07, 0x46, 0xE0, 0xA4, 0xAF, 0xE0, 0xA4,
- // Bytes 4540 - 457f
- 0xBC, 0x07, 0x46, 0xE0, 0xA6, 0xA1, 0xE0, 0xA6,
- 0xBC, 0x07, 0x46, 0xE0, 0xA6, 0xA2, 0xE0, 0xA6,
- 0xBC, 0x07, 0x46, 0xE0, 0xA6, 0xAF, 0xE0, 0xA6,
- 0xBC, 0x07, 0x46, 0xE0, 0xA8, 0x96, 0xE0, 0xA8,
- 0xBC, 0x07, 0x46, 0xE0, 0xA8, 0x97, 0xE0, 0xA8,
- 0xBC, 0x07, 0x46, 0xE0, 0xA8, 0x9C, 0xE0, 0xA8,
- 0xBC, 0x07, 0x46, 0xE0, 0xA8, 0xAB, 0xE0, 0xA8,
- 0xBC, 0x07, 0x46, 0xE0, 0xA8, 0xB2, 0xE0, 0xA8,
- // Bytes 4580 - 45bf
- 0xBC, 0x07, 0x46, 0xE0, 0xA8, 0xB8, 0xE0, 0xA8,
- 0xBC, 0x07, 0x46, 0xE0, 0xAC, 0xA1, 0xE0, 0xAC,
- 0xBC, 0x07, 0x46, 0xE0, 0xAC, 0xA2, 0xE0, 0xAC,
- 0xBC, 0x07, 0x46, 0xE0, 0xBE, 0xB2, 0xE0, 0xBE,
- 0x80, 0x82, 0x46, 0xE0, 0xBE, 0xB3, 0xE0, 0xBE,
- 0x80, 0x82, 0x46, 0xE3, 0x83, 0x86, 0xE3, 0x82,
- 0x99, 0x08, 0x48, 0xF0, 0x9D, 0x85, 0x97, 0xF0,
- 0x9D, 0x85, 0xA5, 0xD8, 0x48, 0xF0, 0x9D, 0x85,
- // Bytes 45c0 - 45ff
- 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xD8, 0x48, 0xF0,
- 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xD8,
- 0x48, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
- 0xA5, 0xD8, 0x49, 0xE0, 0xBE, 0xB2, 0xE0, 0xBD,
- 0xB1, 0xE0, 0xBE, 0x80, 0x82, 0x49, 0xE0, 0xBE,
- 0xB3, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x82,
- 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
- 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xD8, 0x4C, 0xF0,
- // Bytes 4600 - 463f
- 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
- 0x9D, 0x85, 0xAF, 0xD8, 0x4C, 0xF0, 0x9D, 0x85,
- 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
- 0xB0, 0xD8, 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0,
- 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xB1, 0xD8,
- 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
- 0xA5, 0xF0, 0x9D, 0x85, 0xB2, 0xD8, 0x4C, 0xF0,
- 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
- // Bytes 4640 - 467f
- 0x9D, 0x85, 0xAE, 0xD8, 0x4C, 0xF0, 0x9D, 0x86,
- 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
- 0xAF, 0xD8, 0x4C, 0xF0, 0x9D, 0x86, 0xBA, 0xF0,
- 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xD8,
- 0x4C, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
- 0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0xD8, 0x83, 0x41,
- 0xCC, 0x82, 0xE6, 0x83, 0x41, 0xCC, 0x86, 0xE6,
- 0x83, 0x41, 0xCC, 0x87, 0xE6, 0x83, 0x41, 0xCC,
- // Bytes 4680 - 46bf
- 0x88, 0xE6, 0x83, 0x41, 0xCC, 0x8A, 0xE6, 0x83,
- 0x41, 0xCC, 0xA3, 0xDC, 0x83, 0x43, 0xCC, 0xA7,
- 0xCA, 0x83, 0x45, 0xCC, 0x82, 0xE6, 0x83, 0x45,
- 0xCC, 0x84, 0xE6, 0x83, 0x45, 0xCC, 0xA3, 0xDC,
- 0x83, 0x45, 0xCC, 0xA7, 0xCA, 0x83, 0x49, 0xCC,
- 0x88, 0xE6, 0x83, 0x4C, 0xCC, 0xA3, 0xDC, 0x83,
- 0x4F, 0xCC, 0x82, 0xE6, 0x83, 0x4F, 0xCC, 0x83,
- 0xE6, 0x83, 0x4F, 0xCC, 0x84, 0xE6, 0x83, 0x4F,
- // Bytes 46c0 - 46ff
- 0xCC, 0x87, 0xE6, 0x83, 0x4F, 0xCC, 0x88, 0xE6,
- 0x83, 0x4F, 0xCC, 0x9B, 0xD8, 0x83, 0x4F, 0xCC,
- 0xA3, 0xDC, 0x83, 0x4F, 0xCC, 0xA8, 0xCA, 0x83,
- 0x52, 0xCC, 0xA3, 0xDC, 0x83, 0x53, 0xCC, 0x81,
- 0xE6, 0x83, 0x53, 0xCC, 0x8C, 0xE6, 0x83, 0x53,
- 0xCC, 0xA3, 0xDC, 0x83, 0x55, 0xCC, 0x83, 0xE6,
- 0x83, 0x55, 0xCC, 0x84, 0xE6, 0x83, 0x55, 0xCC,
- 0x88, 0xE6, 0x83, 0x55, 0xCC, 0x9B, 0xD8, 0x83,
- // Bytes 4700 - 473f
- 0x61, 0xCC, 0x82, 0xE6, 0x83, 0x61, 0xCC, 0x86,
- 0xE6, 0x83, 0x61, 0xCC, 0x87, 0xE6, 0x83, 0x61,
- 0xCC, 0x88, 0xE6, 0x83, 0x61, 0xCC, 0x8A, 0xE6,
- 0x83, 0x61, 0xCC, 0xA3, 0xDC, 0x83, 0x63, 0xCC,
- 0xA7, 0xCA, 0x83, 0x65, 0xCC, 0x82, 0xE6, 0x83,
- 0x65, 0xCC, 0x84, 0xE6, 0x83, 0x65, 0xCC, 0xA3,
- 0xDC, 0x83, 0x65, 0xCC, 0xA7, 0xCA, 0x83, 0x69,
- 0xCC, 0x88, 0xE6, 0x83, 0x6C, 0xCC, 0xA3, 0xDC,
- // Bytes 4740 - 477f
- 0x83, 0x6F, 0xCC, 0x82, 0xE6, 0x83, 0x6F, 0xCC,
- 0x83, 0xE6, 0x83, 0x6F, 0xCC, 0x84, 0xE6, 0x83,
- 0x6F, 0xCC, 0x87, 0xE6, 0x83, 0x6F, 0xCC, 0x88,
- 0xE6, 0x83, 0x6F, 0xCC, 0x9B, 0xD8, 0x83, 0x6F,
- 0xCC, 0xA3, 0xDC, 0x83, 0x6F, 0xCC, 0xA8, 0xCA,
- 0x83, 0x72, 0xCC, 0xA3, 0xDC, 0x83, 0x73, 0xCC,
- 0x81, 0xE6, 0x83, 0x73, 0xCC, 0x8C, 0xE6, 0x83,
- 0x73, 0xCC, 0xA3, 0xDC, 0x83, 0x75, 0xCC, 0x83,
- // Bytes 4780 - 47bf
- 0xE6, 0x83, 0x75, 0xCC, 0x84, 0xE6, 0x83, 0x75,
- 0xCC, 0x88, 0xE6, 0x83, 0x75, 0xCC, 0x9B, 0xD8,
- 0x84, 0xCE, 0x91, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
- 0x91, 0xCC, 0x94, 0xE6, 0x84, 0xCE, 0x95, 0xCC,
- 0x93, 0xE6, 0x84, 0xCE, 0x95, 0xCC, 0x94, 0xE6,
- 0x84, 0xCE, 0x97, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
- 0x97, 0xCC, 0x94, 0xE6, 0x84, 0xCE, 0x99, 0xCC,
- 0x93, 0xE6, 0x84, 0xCE, 0x99, 0xCC, 0x94, 0xE6,
- // Bytes 47c0 - 47ff
- 0x84, 0xCE, 0x9F, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
- 0x9F, 0xCC, 0x94, 0xE6, 0x84, 0xCE, 0xA5, 0xCC,
- 0x94, 0xE6, 0x84, 0xCE, 0xA9, 0xCC, 0x93, 0xE6,
- 0x84, 0xCE, 0xA9, 0xCC, 0x94, 0xE6, 0x84, 0xCE,
- 0xB1, 0xCC, 0x80, 0xE6, 0x84, 0xCE, 0xB1, 0xCC,
- 0x81, 0xE6, 0x84, 0xCE, 0xB1, 0xCC, 0x93, 0xE6,
- 0x84, 0xCE, 0xB1, 0xCC, 0x94, 0xE6, 0x84, 0xCE,
- 0xB1, 0xCD, 0x82, 0xE6, 0x84, 0xCE, 0xB5, 0xCC,
- // Bytes 4800 - 483f
- 0x93, 0xE6, 0x84, 0xCE, 0xB5, 0xCC, 0x94, 0xE6,
- 0x84, 0xCE, 0xB7, 0xCC, 0x80, 0xE6, 0x84, 0xCE,
- 0xB7, 0xCC, 0x81, 0xE6, 0x84, 0xCE, 0xB7, 0xCC,
- 0x93, 0xE6, 0x84, 0xCE, 0xB7, 0xCC, 0x94, 0xE6,
- 0x84, 0xCE, 0xB7, 0xCD, 0x82, 0xE6, 0x84, 0xCE,
- 0xB9, 0xCC, 0x88, 0xE6, 0x84, 0xCE, 0xB9, 0xCC,
- 0x93, 0xE6, 0x84, 0xCE, 0xB9, 0xCC, 0x94, 0xE6,
- 0x84, 0xCE, 0xBF, 0xCC, 0x93, 0xE6, 0x84, 0xCE,
- // Bytes 4840 - 487f
- 0xBF, 0xCC, 0x94, 0xE6, 0x84, 0xCF, 0x85, 0xCC,
- 0x88, 0xE6, 0x84, 0xCF, 0x85, 0xCC, 0x93, 0xE6,
- 0x84, 0xCF, 0x85, 0xCC, 0x94, 0xE6, 0x84, 0xCF,
- 0x89, 0xCC, 0x80, 0xE6, 0x84, 0xCF, 0x89, 0xCC,
- 0x81, 0xE6, 0x84, 0xCF, 0x89, 0xCC, 0x93, 0xE6,
- 0x84, 0xCF, 0x89, 0xCC, 0x94, 0xE6, 0x84, 0xCF,
- 0x89, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
- 0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
- // Bytes 4880 - 48bf
- 0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
- 0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
- 0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
- 0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x91, 0xCC,
- 0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
- 0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
- 0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
- 0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
- // Bytes 48c0 - 48ff
- 0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
- 0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0x97, 0xCC,
- 0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
- 0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
- 0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
- 0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
- 0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
- 0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xA9, 0xCC,
- // Bytes 4900 - 493f
- 0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
- 0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
- 0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
- 0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
- 0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
- 0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB1, 0xCC,
- 0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
- 0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
- // Bytes 4940 - 497f
- 0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
- 0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
- 0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
- 0x94, 0xCC, 0x81, 0xE6, 0x86, 0xCE, 0xB7, 0xCC,
- 0x94, 0xCD, 0x82, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
- 0x93, 0xCC, 0x80, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
- 0x93, 0xCC, 0x81, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
- 0x93, 0xCD, 0x82, 0xE6, 0x86, 0xCF, 0x89, 0xCC,
- // Bytes 4980 - 49bf
- 0x94, 0xCC, 0x80, 0xE6, 0x86, 0xCF, 0x89, 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, 0x44, 0xCC, 0x88, 0xCC, 0x81,
- 0xE6, 0xE6, 0x43, 0xE3, 0x82, 0x99, 0x08, 0x08,
- 0x43, 0xE3, 0x82, 0x9A, 0x08, 0x08, 0x46, 0xE0,
- 0xBD, 0xB1, 0xE0, 0xBD, 0xB2, 0x82, 0x81, 0x46,
- // Bytes 49c0 - 49ff
- 0xE0, 0xBD, 0xB1, 0xE0, 0xBD, 0xB4, 0x84, 0x81,
- 0x46, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x82,
- 0x81,
-}
-
-// nfcValues: 2944 entries, 5888 bytes
-// Block 2 is the null block.
-var nfcValues = [2944]uint16{
- // Block 0x0, offset 0x0
- 0x003c: 0x8800, 0x003d: 0x8800, 0x003e: 0x8800,
- // Block 0x1, offset 0x40
- 0x0041: 0x8800, 0x0042: 0x8800, 0x0043: 0x8800, 0x0044: 0x8800, 0x0045: 0x8800,
- 0x0046: 0x8800, 0x0047: 0x8800, 0x0048: 0x8800, 0x0049: 0x8800, 0x004a: 0x8800, 0x004b: 0x8800,
- 0x004c: 0x8800, 0x004d: 0x8800, 0x004e: 0x8800, 0x004f: 0x8800, 0x0050: 0x8800,
- 0x0052: 0x8800, 0x0053: 0x8800, 0x0054: 0x8800, 0x0055: 0x8800, 0x0056: 0x8800, 0x0057: 0x8800,
- 0x0058: 0x8800, 0x0059: 0x8800, 0x005a: 0x8800,
- 0x0061: 0x8800, 0x0062: 0x8800, 0x0063: 0x8800,
- 0x0064: 0x8800, 0x0065: 0x8800, 0x0066: 0x8800, 0x0067: 0x8800, 0x0068: 0x8800, 0x0069: 0x8800,
- 0x006a: 0x8800, 0x006b: 0x8800, 0x006c: 0x8800, 0x006d: 0x8800, 0x006e: 0x8800, 0x006f: 0x8800,
- 0x0070: 0x8800, 0x0072: 0x8800, 0x0073: 0x8800, 0x0074: 0x8800, 0x0075: 0x8800,
- 0x0076: 0x8800, 0x0077: 0x8800, 0x0078: 0x8800, 0x0079: 0x8800, 0x007a: 0x8800,
- // Block 0x2, offset 0x80
- // Block 0x3, offset 0xc0
- 0x00c0: 0x2f59, 0x00c1: 0x2f5e, 0x00c2: 0x466e, 0x00c3: 0x2f63, 0x00c4: 0x467d, 0x00c5: 0x4682,
- 0x00c6: 0x8800, 0x00c7: 0x468c, 0x00c8: 0x2fcc, 0x00c9: 0x2fd1, 0x00ca: 0x4691, 0x00cb: 0x2fe5,
- 0x00cc: 0x3058, 0x00cd: 0x305d, 0x00ce: 0x3062, 0x00cf: 0x46a5, 0x00d1: 0x30ee,
- 0x00d2: 0x3111, 0x00d3: 0x3116, 0x00d4: 0x46af, 0x00d5: 0x46b4, 0x00d6: 0x46c3,
- 0x00d8: 0x8800, 0x00d9: 0x319d, 0x00da: 0x31a2, 0x00db: 0x31a7, 0x00dc: 0x46f5, 0x00dd: 0x321f,
- 0x00e0: 0x3265, 0x00e1: 0x326a, 0x00e2: 0x46ff, 0x00e3: 0x326f,
- 0x00e4: 0x470e, 0x00e5: 0x4713, 0x00e6: 0x8800, 0x00e7: 0x471d, 0x00e8: 0x32d8, 0x00e9: 0x32dd,
- 0x00ea: 0x4722, 0x00eb: 0x32f1, 0x00ec: 0x3369, 0x00ed: 0x336e, 0x00ee: 0x3373, 0x00ef: 0x4736,
- 0x00f1: 0x33ff, 0x00f2: 0x3422, 0x00f3: 0x3427, 0x00f4: 0x4740, 0x00f5: 0x4745,
- 0x00f6: 0x4754, 0x00f8: 0x8800, 0x00f9: 0x34b3, 0x00fa: 0x34b8, 0x00fb: 0x34bd,
- 0x00fc: 0x4786, 0x00fd: 0x353a, 0x00ff: 0x3553,
- // Block 0x4, offset 0x100
- 0x0100: 0x2f68, 0x0101: 0x3274, 0x0102: 0x4673, 0x0103: 0x4704, 0x0104: 0x2f86, 0x0105: 0x3292,
- 0x0106: 0x2f9a, 0x0107: 0x32a6, 0x0108: 0x2f9f, 0x0109: 0x32ab, 0x010a: 0x2fa4, 0x010b: 0x32b0,
- 0x010c: 0x2fa9, 0x010d: 0x32b5, 0x010e: 0x2fb3, 0x010f: 0x32bf,
- 0x0112: 0x4696, 0x0113: 0x4727, 0x0114: 0x2fdb, 0x0115: 0x32e7, 0x0116: 0x2fe0, 0x0117: 0x32ec,
- 0x0118: 0x2ffe, 0x0119: 0x330a, 0x011a: 0x2fef, 0x011b: 0x32fb, 0x011c: 0x3017, 0x011d: 0x3323,
- 0x011e: 0x3021, 0x011f: 0x332d, 0x0120: 0x3026, 0x0121: 0x3332, 0x0122: 0x3030, 0x0123: 0x333c,
- 0x0124: 0x3035, 0x0125: 0x3341, 0x0128: 0x3067, 0x0129: 0x3378,
- 0x012a: 0x306c, 0x012b: 0x337d, 0x012c: 0x3071, 0x012d: 0x3382, 0x012e: 0x3094, 0x012f: 0x33a0,
- 0x0130: 0x3076, 0x0134: 0x309e, 0x0135: 0x33aa,
- 0x0136: 0x30b2, 0x0137: 0x33c3, 0x0139: 0x30bc, 0x013a: 0x33cd, 0x013b: 0x30c6,
- 0x013c: 0x33d7, 0x013d: 0x30c1, 0x013e: 0x33d2,
- // Block 0x5, offset 0x140
- 0x0143: 0x30e9, 0x0144: 0x33fa, 0x0145: 0x3102,
- 0x0146: 0x3413, 0x0147: 0x30f8, 0x0148: 0x3409,
- 0x014c: 0x46b9, 0x014d: 0x474a, 0x014e: 0x311b, 0x014f: 0x342c, 0x0150: 0x3125, 0x0151: 0x3436,
- 0x0154: 0x3143, 0x0155: 0x3454, 0x0156: 0x315c, 0x0157: 0x346d,
- 0x0158: 0x314d, 0x0159: 0x345e, 0x015a: 0x46dc, 0x015b: 0x476d, 0x015c: 0x3166, 0x015d: 0x3477,
- 0x015e: 0x3175, 0x015f: 0x3486, 0x0160: 0x46e1, 0x0161: 0x4772, 0x0162: 0x318e, 0x0163: 0x34a4,
- 0x0164: 0x317f, 0x0165: 0x3495, 0x0168: 0x46eb, 0x0169: 0x477c,
- 0x016a: 0x46f0, 0x016b: 0x4781, 0x016c: 0x31ac, 0x016d: 0x34c2, 0x016e: 0x31b6, 0x016f: 0x34cc,
- 0x0170: 0x31bb, 0x0171: 0x34d1, 0x0172: 0x31d9, 0x0173: 0x34ef, 0x0174: 0x31fc, 0x0175: 0x3512,
- 0x0176: 0x3224, 0x0177: 0x353f, 0x0178: 0x3238, 0x0179: 0x3247, 0x017a: 0x3567, 0x017b: 0x3251,
- 0x017c: 0x3571, 0x017d: 0x3256, 0x017e: 0x3576, 0x017f: 0x8800,
- // Block 0x6, offset 0x180
- 0x018d: 0x2f72, 0x018e: 0x327e, 0x018f: 0x3080, 0x0190: 0x338c, 0x0191: 0x312a,
- 0x0192: 0x343b, 0x0193: 0x31c0, 0x0194: 0x34d6, 0x0195: 0x39b9, 0x0196: 0x3b48, 0x0197: 0x39b2,
- 0x0198: 0x3b41, 0x0199: 0x39c0, 0x019a: 0x3b4f, 0x019b: 0x39ab, 0x019c: 0x3b3a,
- 0x019e: 0x389a, 0x019f: 0x3a29, 0x01a0: 0x3893, 0x01a1: 0x3a22, 0x01a2: 0x359d, 0x01a3: 0x35af,
- 0x01a6: 0x302b, 0x01a7: 0x3337, 0x01a8: 0x30a8, 0x01a9: 0x33b9,
- 0x01aa: 0x46d2, 0x01ab: 0x4763, 0x01ac: 0x397a, 0x01ad: 0x3b09, 0x01ae: 0x35c1, 0x01af: 0x35c7,
- 0x01b0: 0x33af, 0x01b4: 0x3012, 0x01b5: 0x331e,
- 0x01b8: 0x30e4, 0x01b9: 0x33f5, 0x01ba: 0x38a1, 0x01bb: 0x3a30,
- 0x01bc: 0x3597, 0x01bd: 0x35a9, 0x01be: 0x35a3, 0x01bf: 0x35b5,
- // Block 0x7, offset 0x1c0
- 0x01c0: 0x2f77, 0x01c1: 0x3283, 0x01c2: 0x2f7c, 0x01c3: 0x3288, 0x01c4: 0x2ff4, 0x01c5: 0x3300,
- 0x01c6: 0x2ff9, 0x01c7: 0x3305, 0x01c8: 0x3085, 0x01c9: 0x3391, 0x01ca: 0x308a, 0x01cb: 0x3396,
- 0x01cc: 0x312f, 0x01cd: 0x3440, 0x01ce: 0x3134, 0x01cf: 0x3445, 0x01d0: 0x3152, 0x01d1: 0x3463,
- 0x01d2: 0x3157, 0x01d3: 0x3468, 0x01d4: 0x31c5, 0x01d5: 0x34db, 0x01d6: 0x31ca, 0x01d7: 0x34e0,
- 0x01d8: 0x3170, 0x01d9: 0x3481, 0x01da: 0x3189, 0x01db: 0x349f,
- 0x01de: 0x3044, 0x01df: 0x3350,
- 0x01e6: 0x4678, 0x01e7: 0x4709, 0x01e8: 0x46a0, 0x01e9: 0x4731,
- 0x01ea: 0x3949, 0x01eb: 0x3ad8, 0x01ec: 0x3926, 0x01ed: 0x3ab5, 0x01ee: 0x46be, 0x01ef: 0x474f,
- 0x01f0: 0x3942, 0x01f1: 0x3ad1, 0x01f2: 0x322e, 0x01f3: 0x3549,
- // Block 0x8, offset 0x200
- 0x0200: 0x86e6, 0x0201: 0x86e6, 0x0202: 0x86e6, 0x0203: 0x86e6, 0x0204: 0x86e6, 0x0205: 0x80e6,
- 0x0206: 0x86e6, 0x0207: 0x86e6, 0x0208: 0x86e6, 0x0209: 0x86e6, 0x020a: 0x86e6, 0x020b: 0x86e6,
- 0x020c: 0x86e6, 0x020d: 0x80e6, 0x020e: 0x80e6, 0x020f: 0x86e6, 0x0210: 0x80e6, 0x0211: 0x86e6,
- 0x0212: 0x80e6, 0x0213: 0x86e6, 0x0214: 0x86e6, 0x0215: 0x80e8, 0x0216: 0x80dc, 0x0217: 0x80dc,
- 0x0218: 0x80dc, 0x0219: 0x80dc, 0x021a: 0x80e8, 0x021b: 0x86d8, 0x021c: 0x80dc, 0x021d: 0x80dc,
- 0x021e: 0x80dc, 0x021f: 0x80dc, 0x0220: 0x80dc, 0x0221: 0x80ca, 0x0222: 0x80ca, 0x0223: 0x86dc,
- 0x0224: 0x86dc, 0x0225: 0x86dc, 0x0226: 0x86dc, 0x0227: 0x86ca, 0x0228: 0x86ca, 0x0229: 0x80dc,
- 0x022a: 0x80dc, 0x022b: 0x80dc, 0x022c: 0x80dc, 0x022d: 0x86dc, 0x022e: 0x86dc, 0x022f: 0x80dc,
- 0x0230: 0x86dc, 0x0231: 0x86dc, 0x0232: 0x80dc, 0x0233: 0x80dc, 0x0234: 0x8001, 0x0235: 0x8001,
- 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: 0x4994, 0x0241: 0x4999, 0x0242: 0x86e6, 0x0243: 0x499e, 0x0244: 0x49a3, 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,
- 0x0258: 0x80e8, 0x0259: 0x80dc, 0x025a: 0x80dc, 0x025b: 0x80e6, 0x025c: 0x80e9, 0x025d: 0x80ea,
- 0x025e: 0x80ea, 0x025f: 0x80e9, 0x0260: 0x80ea, 0x0261: 0x80ea, 0x0262: 0x80e9, 0x0263: 0x80e6,
- 0x0264: 0x80e6, 0x0265: 0x80e6, 0x0266: 0x80e6, 0x0267: 0x80e6, 0x0268: 0x80e6, 0x0269: 0x80e6,
- 0x026a: 0x80e6, 0x026b: 0x80e6, 0x026c: 0x80e6, 0x026d: 0x80e6, 0x026e: 0x80e6, 0x026f: 0x80e6,
- 0x0274: 0x0170,
- 0x027e: 0x0037,
- // Block 0xa, offset 0x280
- 0x0285: 0x358b,
- 0x0286: 0x35d3, 0x0287: 0x00d1, 0x0288: 0x35f1, 0x0289: 0x35fd, 0x028a: 0x360f,
- 0x028c: 0x362d, 0x028e: 0x363f, 0x028f: 0x365d, 0x0290: 0x3df2, 0x0291: 0x8800,
- 0x0295: 0x8800, 0x0297: 0x8800,
- 0x0299: 0x8800,
- 0x029f: 0x8800, 0x02a1: 0x8800,
- 0x02a5: 0x8800, 0x02a9: 0x8800,
- 0x02aa: 0x3621, 0x02ab: 0x3651, 0x02ac: 0x47e4, 0x02ad: 0x3681, 0x02ae: 0x480e, 0x02af: 0x3693,
- 0x02b0: 0x3e5a, 0x02b1: 0x8800, 0x02b5: 0x8800,
- 0x02b7: 0x8800, 0x02b9: 0x8800,
- 0x02bf: 0x8800,
- // Block 0xb, offset 0x2c0
- 0x02c0: 0x370b, 0x02c1: 0x3717, 0x02c3: 0x3705,
- 0x02c6: 0x8800, 0x02c7: 0x36f3,
- 0x02cc: 0x3747, 0x02cd: 0x372f, 0x02ce: 0x3759, 0x02d0: 0x8800,
- 0x02d3: 0x8800, 0x02d5: 0x8800, 0x02d6: 0x8800, 0x02d7: 0x8800,
- 0x02d8: 0x8800, 0x02d9: 0x373b, 0x02da: 0x8800,
- 0x02de: 0x8800, 0x02e3: 0x8800,
- 0x02e7: 0x8800,
- 0x02eb: 0x8800, 0x02ed: 0x8800,
- 0x02f0: 0x8800, 0x02f3: 0x8800, 0x02f5: 0x8800,
- 0x02f6: 0x8800, 0x02f7: 0x8800, 0x02f8: 0x8800, 0x02f9: 0x37bf, 0x02fa: 0x8800,
- 0x02fe: 0x8800,
- // Block 0xc, offset 0x300
- 0x0301: 0x371d, 0x0302: 0x37a1,
- 0x0310: 0x36f9, 0x0311: 0x377d,
- 0x0312: 0x36ff, 0x0313: 0x3783, 0x0316: 0x3711, 0x0317: 0x3795,
- 0x0318: 0x8800, 0x0319: 0x8800, 0x031a: 0x3813, 0x031b: 0x3819, 0x031c: 0x3723, 0x031d: 0x37a7,
- 0x031e: 0x3729, 0x031f: 0x37ad, 0x0322: 0x3735, 0x0323: 0x37b9,
- 0x0324: 0x3741, 0x0325: 0x37c5, 0x0326: 0x374d, 0x0327: 0x37d1, 0x0328: 0x8800, 0x0329: 0x8800,
- 0x032a: 0x381f, 0x032b: 0x3825, 0x032c: 0x3777, 0x032d: 0x37fb, 0x032e: 0x3753, 0x032f: 0x37d7,
- 0x0330: 0x375f, 0x0331: 0x37e3, 0x0332: 0x3765, 0x0333: 0x37e9, 0x0334: 0x376b, 0x0335: 0x37ef,
- 0x0338: 0x3771, 0x0339: 0x37f5,
- // Block 0xd, offset 0x340
- 0x0351: 0x80dc,
- 0x0352: 0x80e6, 0x0353: 0x80e6, 0x0354: 0x80e6, 0x0355: 0x80e6, 0x0356: 0x80dc, 0x0357: 0x80e6,
- 0x0358: 0x80e6, 0x0359: 0x80e6, 0x035a: 0x80de, 0x035b: 0x80dc, 0x035c: 0x80e6, 0x035d: 0x80e6,
- 0x035e: 0x80e6, 0x035f: 0x80e6, 0x0360: 0x80e6, 0x0361: 0x80e6, 0x0362: 0x80dc, 0x0363: 0x80dc,
- 0x0364: 0x80dc, 0x0365: 0x80dc, 0x0366: 0x80dc, 0x0367: 0x80dc, 0x0368: 0x80e6, 0x0369: 0x80e6,
- 0x036a: 0x80dc, 0x036b: 0x80e6, 0x036c: 0x80e6, 0x036d: 0x80de, 0x036e: 0x80e4, 0x036f: 0x80e6,
- 0x0370: 0x800a, 0x0371: 0x800b, 0x0372: 0x800c, 0x0373: 0x800d, 0x0374: 0x800e, 0x0375: 0x800f,
- 0x0376: 0x8010, 0x0377: 0x8011, 0x0378: 0x8012, 0x0379: 0x8013, 0x037a: 0x8013, 0x037b: 0x8014,
- 0x037c: 0x8015, 0x037d: 0x8016, 0x037f: 0x8017,
- // Block 0xe, offset 0x380
- 0x0388: 0x8800, 0x038a: 0x8800, 0x038b: 0x801b,
- 0x038c: 0x801c, 0x038d: 0x801d, 0x038e: 0x801e, 0x038f: 0x801f, 0x0390: 0x8020, 0x0391: 0x8021,
- 0x0392: 0x8022, 0x0393: 0x86e6, 0x0394: 0x86e6, 0x0395: 0x86dc, 0x0396: 0x80dc, 0x0397: 0x80e6,
- 0x0398: 0x80e6, 0x0399: 0x80e6, 0x039a: 0x80e6, 0x039b: 0x80e6, 0x039c: 0x80dc, 0x039d: 0x80e6,
- 0x039e: 0x80e6, 0x039f: 0x80dc,
- 0x03b0: 0x8023,
- // Block 0xf, offset 0x3c0
- 0x03c5: 0x8800,
- 0x03c6: 0x1946, 0x03c7: 0x8800, 0x03c8: 0x194d, 0x03c9: 0x8800, 0x03ca: 0x1954, 0x03cb: 0x8800,
- 0x03cc: 0x195b, 0x03cd: 0x8800, 0x03ce: 0x1962, 0x03d1: 0x8800,
- 0x03d2: 0x1969,
- 0x03f4: 0x8007, 0x03f5: 0x8600,
- 0x03fa: 0x8800, 0x03fb: 0x1970,
- 0x03fc: 0x8800, 0x03fd: 0x1977, 0x03fe: 0x8800, 0x03ff: 0x8800,
- // Block 0x10, offset 0x400
- 0x0400: 0x2f81, 0x0401: 0x328d, 0x0402: 0x2f8b, 0x0403: 0x3297, 0x0404: 0x2f90, 0x0405: 0x329c,
- 0x0406: 0x2f95, 0x0407: 0x32a1, 0x0408: 0x38b6, 0x0409: 0x3a45, 0x040a: 0x2fae, 0x040b: 0x32ba,
- 0x040c: 0x2fb8, 0x040d: 0x32c4, 0x040e: 0x2fc7, 0x040f: 0x32d3, 0x0410: 0x2fbd, 0x0411: 0x32c9,
- 0x0412: 0x2fc2, 0x0413: 0x32ce, 0x0414: 0x38d9, 0x0415: 0x3a68, 0x0416: 0x38e0, 0x0417: 0x3a6f,
- 0x0418: 0x3003, 0x0419: 0x330f, 0x041a: 0x3008, 0x041b: 0x3314, 0x041c: 0x38ee, 0x041d: 0x3a7d,
- 0x041e: 0x300d, 0x041f: 0x3319, 0x0420: 0x301c, 0x0421: 0x3328, 0x0422: 0x303a, 0x0423: 0x3346,
- 0x0424: 0x3049, 0x0425: 0x3355, 0x0426: 0x303f, 0x0427: 0x334b, 0x0428: 0x304e, 0x0429: 0x335a,
- 0x042a: 0x3053, 0x042b: 0x335f, 0x042c: 0x3099, 0x042d: 0x33a5, 0x042e: 0x38f5, 0x042f: 0x3a84,
- 0x0430: 0x30a3, 0x0431: 0x33b4, 0x0432: 0x30ad, 0x0433: 0x33be, 0x0434: 0x30b7, 0x0435: 0x33c8,
- 0x0436: 0x46aa, 0x0437: 0x473b, 0x0438: 0x38fc, 0x0439: 0x3a8b, 0x043a: 0x30d0, 0x043b: 0x33e1,
- 0x043c: 0x30cb, 0x043d: 0x33dc, 0x043e: 0x30d5, 0x043f: 0x33e6,
- // Block 0x11, offset 0x440
- 0x0440: 0x30da, 0x0441: 0x33eb, 0x0442: 0x30df, 0x0443: 0x33f0, 0x0444: 0x30f3, 0x0445: 0x3404,
- 0x0446: 0x30fd, 0x0447: 0x340e, 0x0448: 0x310c, 0x0449: 0x341d, 0x044a: 0x3107, 0x044b: 0x3418,
- 0x044c: 0x391f, 0x044d: 0x3aae, 0x044e: 0x392d, 0x044f: 0x3abc, 0x0450: 0x3934, 0x0451: 0x3ac3,
- 0x0452: 0x393b, 0x0453: 0x3aca, 0x0454: 0x3139, 0x0455: 0x344a, 0x0456: 0x313e, 0x0457: 0x344f,
- 0x0458: 0x3148, 0x0459: 0x3459, 0x045a: 0x46d7, 0x045b: 0x4768, 0x045c: 0x3981, 0x045d: 0x3b10,
- 0x045e: 0x3161, 0x045f: 0x3472, 0x0460: 0x316b, 0x0461: 0x347c, 0x0462: 0x46e6, 0x0463: 0x4777,
- 0x0464: 0x3988, 0x0465: 0x3b17, 0x0466: 0x398f, 0x0467: 0x3b1e, 0x0468: 0x3996, 0x0469: 0x3b25,
- 0x046a: 0x317a, 0x046b: 0x348b, 0x046c: 0x3184, 0x046d: 0x349a, 0x046e: 0x3198, 0x046f: 0x34ae,
- 0x0470: 0x3193, 0x0471: 0x34a9, 0x0472: 0x31d4, 0x0473: 0x34ea, 0x0474: 0x31e3, 0x0475: 0x34f9,
- 0x0476: 0x31de, 0x0477: 0x34f4, 0x0478: 0x399d, 0x0479: 0x3b2c, 0x047a: 0x39a4, 0x047b: 0x3b33,
- 0x047c: 0x31e8, 0x047d: 0x34fe, 0x047e: 0x31ed, 0x047f: 0x3503,
- // Block 0x12, offset 0x480
- 0x0480: 0x31f2, 0x0481: 0x3508, 0x0482: 0x31f7, 0x0483: 0x350d, 0x0484: 0x3206, 0x0485: 0x351c,
- 0x0486: 0x3201, 0x0487: 0x3517, 0x0488: 0x320b, 0x0489: 0x3526, 0x048a: 0x3210, 0x048b: 0x352b,
- 0x048c: 0x3215, 0x048d: 0x3530, 0x048e: 0x3233, 0x048f: 0x354e, 0x0490: 0x324c, 0x0491: 0x356c,
- 0x0492: 0x325b, 0x0493: 0x357b, 0x0494: 0x3260, 0x0495: 0x3580, 0x0496: 0x3364, 0x0497: 0x3490,
- 0x0498: 0x3521, 0x0499: 0x355d, 0x049b: 0x35bb,
- 0x04a0: 0x4687, 0x04a1: 0x4718, 0x04a2: 0x2f6d, 0x04a3: 0x3279,
- 0x04a4: 0x3862, 0x04a5: 0x39f1, 0x04a6: 0x385b, 0x04a7: 0x39ea, 0x04a8: 0x3870, 0x04a9: 0x39ff,
- 0x04aa: 0x3869, 0x04ab: 0x39f8, 0x04ac: 0x38a8, 0x04ad: 0x3a37, 0x04ae: 0x387e, 0x04af: 0x3a0d,
- 0x04b0: 0x3877, 0x04b1: 0x3a06, 0x04b2: 0x388c, 0x04b3: 0x3a1b, 0x04b4: 0x3885, 0x04b5: 0x3a14,
- 0x04b6: 0x38af, 0x04b7: 0x3a3e, 0x04b8: 0x469b, 0x04b9: 0x472c, 0x04ba: 0x2fea, 0x04bb: 0x32f6,
- 0x04bc: 0x2fd6, 0x04bd: 0x32e2, 0x04be: 0x38c4, 0x04bf: 0x3a53,
- // Block 0x13, offset 0x4c0
- 0x04c0: 0x38bd, 0x04c1: 0x3a4c, 0x04c2: 0x38d2, 0x04c3: 0x3a61, 0x04c4: 0x38cb, 0x04c5: 0x3a5a,
- 0x04c6: 0x38e7, 0x04c7: 0x3a76, 0x04c8: 0x307b, 0x04c9: 0x3387, 0x04ca: 0x308f, 0x04cb: 0x339b,
- 0x04cc: 0x46cd, 0x04cd: 0x475e, 0x04ce: 0x3120, 0x04cf: 0x3431, 0x04d0: 0x390a, 0x04d1: 0x3a99,
- 0x04d2: 0x3903, 0x04d3: 0x3a92, 0x04d4: 0x3918, 0x04d5: 0x3aa7, 0x04d6: 0x3911, 0x04d7: 0x3aa0,
- 0x04d8: 0x3973, 0x04d9: 0x3b02, 0x04da: 0x3957, 0x04db: 0x3ae6, 0x04dc: 0x3950, 0x04dd: 0x3adf,
- 0x04de: 0x3965, 0x04df: 0x3af4, 0x04e0: 0x395e, 0x04e1: 0x3aed, 0x04e2: 0x396c, 0x04e3: 0x3afb,
- 0x04e4: 0x31cf, 0x04e5: 0x34e5, 0x04e6: 0x31b1, 0x04e7: 0x34c7, 0x04e8: 0x39ce, 0x04e9: 0x3b5d,
- 0x04ea: 0x39c7, 0x04eb: 0x3b56, 0x04ec: 0x39dc, 0x04ed: 0x3b6b, 0x04ee: 0x39d5, 0x04ef: 0x3b64,
- 0x04f0: 0x39e3, 0x04f1: 0x3b72, 0x04f2: 0x321a, 0x04f3: 0x3535, 0x04f4: 0x3242, 0x04f5: 0x3562,
- 0x04f6: 0x323d, 0x04f7: 0x3558, 0x04f8: 0x3229, 0x04f9: 0x3544,
- // Block 0x14, offset 0x500
- 0x0500: 0x47ea, 0x0501: 0x47f0, 0x0502: 0x4904, 0x0503: 0x491c, 0x0504: 0x490c, 0x0505: 0x4924,
- 0x0506: 0x4914, 0x0507: 0x492c, 0x0508: 0x4790, 0x0509: 0x4796, 0x050a: 0x4874, 0x050b: 0x488c,
- 0x050c: 0x487c, 0x050d: 0x4894, 0x050e: 0x4884, 0x050f: 0x489c, 0x0510: 0x47fc, 0x0511: 0x4802,
- 0x0512: 0x3da2, 0x0513: 0x3db2, 0x0514: 0x3daa, 0x0515: 0x3dba,
- 0x0518: 0x479c, 0x0519: 0x47a2, 0x051a: 0x3cd2, 0x051b: 0x3ce2, 0x051c: 0x3cda, 0x051d: 0x3cea,
- 0x0520: 0x4814, 0x0521: 0x481a, 0x0522: 0x4934, 0x0523: 0x494c,
- 0x0524: 0x493c, 0x0525: 0x4954, 0x0526: 0x4944, 0x0527: 0x495c, 0x0528: 0x47a8, 0x0529: 0x47ae,
- 0x052a: 0x48a4, 0x052b: 0x48bc, 0x052c: 0x48ac, 0x052d: 0x48c4, 0x052e: 0x48b4, 0x052f: 0x48cc,
- 0x0530: 0x482c, 0x0531: 0x4832, 0x0532: 0x3e02, 0x0533: 0x3e1a, 0x0534: 0x3e0a, 0x0535: 0x3e22,
- 0x0536: 0x3e12, 0x0537: 0x3e2a, 0x0538: 0x47b4, 0x0539: 0x47ba, 0x053a: 0x3d02, 0x053b: 0x3d1a,
- 0x053c: 0x3d0a, 0x053d: 0x3d22, 0x053e: 0x3d12, 0x053f: 0x3d2a,
- // Block 0x15, offset 0x540
- 0x0540: 0x4838, 0x0541: 0x483e, 0x0542: 0x3e32, 0x0543: 0x3e42, 0x0544: 0x3e3a, 0x0545: 0x3e4a,
- 0x0548: 0x47c0, 0x0549: 0x47c6, 0x054a: 0x3d32, 0x054b: 0x3d42,
- 0x054c: 0x3d3a, 0x054d: 0x3d4a, 0x0550: 0x484a, 0x0551: 0x4850,
- 0x0552: 0x3e6a, 0x0553: 0x3e82, 0x0554: 0x3e72, 0x0555: 0x3e8a, 0x0556: 0x3e7a, 0x0557: 0x3e92,
- 0x0559: 0x47cc, 0x055b: 0x3d52, 0x055d: 0x3d5a,
- 0x055f: 0x3d62, 0x0560: 0x4862, 0x0561: 0x4868, 0x0562: 0x4964, 0x0563: 0x497c,
- 0x0564: 0x496c, 0x0565: 0x4984, 0x0566: 0x4974, 0x0567: 0x498c, 0x0568: 0x47d2, 0x0569: 0x47d8,
- 0x056a: 0x48d4, 0x056b: 0x48ec, 0x056c: 0x48dc, 0x056d: 0x48f4, 0x056e: 0x48e4, 0x056f: 0x48fc,
- 0x0570: 0x47de, 0x0571: 0x4304, 0x0572: 0x367b, 0x0573: 0x430a, 0x0574: 0x4808, 0x0575: 0x4310,
- 0x0576: 0x368d, 0x0577: 0x4316, 0x0578: 0x36ab, 0x0579: 0x431c, 0x057a: 0x36c3, 0x057b: 0x4322,
- 0x057c: 0x4856, 0x057d: 0x4328,
- // Block 0x16, offset 0x580
- 0x0580: 0x3d8a, 0x0581: 0x3d92, 0x0582: 0x416e, 0x0583: 0x418c, 0x0584: 0x4178, 0x0585: 0x4196,
- 0x0586: 0x4182, 0x0587: 0x41a0, 0x0588: 0x3cc2, 0x0589: 0x3cca, 0x058a: 0x40ba, 0x058b: 0x40d8,
- 0x058c: 0x40c4, 0x058d: 0x40e2, 0x058e: 0x40ce, 0x058f: 0x40ec, 0x0590: 0x3dd2, 0x0591: 0x3dda,
- 0x0592: 0x41aa, 0x0593: 0x41c8, 0x0594: 0x41b4, 0x0595: 0x41d2, 0x0596: 0x41be, 0x0597: 0x41dc,
- 0x0598: 0x3cf2, 0x0599: 0x3cfa, 0x059a: 0x40f6, 0x059b: 0x4114, 0x059c: 0x4100, 0x059d: 0x411e,
- 0x059e: 0x410a, 0x059f: 0x4128, 0x05a0: 0x3eaa, 0x05a1: 0x3eb2, 0x05a2: 0x41e6, 0x05a3: 0x4204,
- 0x05a4: 0x41f0, 0x05a5: 0x420e, 0x05a6: 0x41fa, 0x05a7: 0x4218, 0x05a8: 0x3d6a, 0x05a9: 0x3d72,
- 0x05aa: 0x4132, 0x05ab: 0x4150, 0x05ac: 0x413c, 0x05ad: 0x415a, 0x05ae: 0x4146, 0x05af: 0x4164,
- 0x05b0: 0x366f, 0x05b1: 0x3669, 0x05b2: 0x3d7a, 0x05b3: 0x3675, 0x05b4: 0x3d82,
- 0x05b6: 0x47f6, 0x05b7: 0x3d9a, 0x05b8: 0x35df, 0x05b9: 0x35d9, 0x05ba: 0x35cd, 0x05bb: 0x42d4,
- 0x05bc: 0x35e5, 0x05be: 0x01d3, 0x05bf: 0x8800,
- // Block 0x17, offset 0x5c0
- 0x05c1: 0x3591, 0x05c2: 0x3dc2, 0x05c3: 0x3687, 0x05c4: 0x3dca,
- 0x05c6: 0x4820, 0x05c7: 0x3de2, 0x05c8: 0x35eb, 0x05c9: 0x42da, 0x05ca: 0x35f7, 0x05cb: 0x42e0,
- 0x05cc: 0x3603, 0x05cd: 0x3b79, 0x05ce: 0x3b80, 0x05cf: 0x3b87, 0x05d0: 0x369f, 0x05d1: 0x3699,
- 0x05d2: 0x3dea, 0x05d3: 0x44ca, 0x05d6: 0x36a5, 0x05d7: 0x3dfa,
- 0x05d8: 0x361b, 0x05d9: 0x3615, 0x05da: 0x3609, 0x05db: 0x42e6, 0x05dd: 0x3b8e,
- 0x05de: 0x3b95, 0x05df: 0x3b9c, 0x05e0: 0x36d5, 0x05e1: 0x36cf, 0x05e2: 0x3e52, 0x05e3: 0x44d2,
- 0x05e4: 0x36b7, 0x05e5: 0x36bd, 0x05e6: 0x36db, 0x05e7: 0x3e62, 0x05e8: 0x364b, 0x05e9: 0x3645,
- 0x05ea: 0x3639, 0x05eb: 0x42f2, 0x05ec: 0x3633, 0x05ed: 0x3585, 0x05ee: 0x42ce, 0x05ef: 0x0081,
- 0x05f2: 0x3e9a, 0x05f3: 0x36e1, 0x05f4: 0x3ea2,
- 0x05f6: 0x486e, 0x05f7: 0x3eba, 0x05f8: 0x3627, 0x05f9: 0x42ec, 0x05fa: 0x3657, 0x05fb: 0x42fe,
- 0x05fc: 0x3663, 0x05fd: 0x00ce, 0x05fe: 0x8800,
- // Block 0x18, offset 0x600
- 0x0601: 0x3bf0, 0x0603: 0x8800, 0x0604: 0x3bf7, 0x0605: 0x8800,
- 0x0607: 0x3bfe, 0x0608: 0x8800, 0x0609: 0x3c05,
- 0x060d: 0x8800,
- 0x0620: 0x2f4f, 0x0621: 0x8800, 0x0622: 0x3c13,
- 0x0624: 0x8800, 0x0625: 0x8800,
- 0x062d: 0x3c0c, 0x062e: 0x2f4a, 0x062f: 0x2f54,
- 0x0630: 0x3c1a, 0x0631: 0x3c21, 0x0632: 0x8800, 0x0633: 0x8800, 0x0634: 0x3c28, 0x0635: 0x3c2f,
- 0x0636: 0x8800, 0x0637: 0x8800, 0x0638: 0x3c36, 0x0639: 0x3c3d, 0x063a: 0x8800, 0x063b: 0x8800,
- 0x063c: 0x8800, 0x063d: 0x8800,
- // Block 0x19, offset 0x640
- 0x0640: 0x3c44, 0x0641: 0x3c4b, 0x0642: 0x8800, 0x0643: 0x8800, 0x0644: 0x3c60, 0x0645: 0x3c67,
- 0x0646: 0x8800, 0x0647: 0x8800, 0x0648: 0x3c6e, 0x0649: 0x3c75,
- 0x0651: 0x8800,
- 0x0652: 0x8800,
- 0x0662: 0x8800,
- 0x0668: 0x8800, 0x0669: 0x8800,
- 0x066b: 0x8800, 0x066c: 0x3c8a, 0x066d: 0x3c91, 0x066e: 0x3c98, 0x066f: 0x3c9f,
- 0x0672: 0x8800, 0x0673: 0x8800, 0x0674: 0x8800, 0x0675: 0x8800,
- // Block 0x1a, offset 0x680
- 0x0686: 0x8800, 0x068b: 0x8800,
- 0x068c: 0x3ef2, 0x068d: 0x8800, 0x068e: 0x3efa, 0x068f: 0x8800, 0x0690: 0x3f02, 0x0691: 0x8800,
- 0x0692: 0x3f0a, 0x0693: 0x8800, 0x0694: 0x3f12, 0x0695: 0x8800, 0x0696: 0x3f1a, 0x0697: 0x8800,
- 0x0698: 0x3f22, 0x0699: 0x8800, 0x069a: 0x3f2a, 0x069b: 0x8800, 0x069c: 0x3f32, 0x069d: 0x8800,
- 0x069e: 0x3f3a, 0x069f: 0x8800, 0x06a0: 0x3f42, 0x06a1: 0x8800, 0x06a2: 0x3f4a,
- 0x06a4: 0x8800, 0x06a5: 0x3f52, 0x06a6: 0x8800, 0x06a7: 0x3f5a, 0x06a8: 0x8800, 0x06a9: 0x3f62,
- 0x06af: 0x8800,
- 0x06b0: 0x3f6a, 0x06b1: 0x3f72, 0x06b2: 0x8800, 0x06b3: 0x3f7a, 0x06b4: 0x3f82, 0x06b5: 0x8800,
- 0x06b6: 0x3f8a, 0x06b7: 0x3f92, 0x06b8: 0x8800, 0x06b9: 0x3f9a, 0x06ba: 0x3fa2, 0x06bb: 0x8800,
- 0x06bc: 0x3faa, 0x06bd: 0x3fb2,
- // Block 0x1b, offset 0x6c0
- 0x06d4: 0x3eea,
- 0x06d9: 0x8608, 0x06da: 0x8608, 0x06dd: 0x8800,
- 0x06de: 0x3fba,
- 0x06e6: 0x8800,
- 0x06eb: 0x8800, 0x06ec: 0x3fca, 0x06ed: 0x8800, 0x06ee: 0x3fd2, 0x06ef: 0x8800,
- 0x06f0: 0x3fda, 0x06f1: 0x8800, 0x06f2: 0x3fe2, 0x06f3: 0x8800, 0x06f4: 0x3fea, 0x06f5: 0x8800,
- 0x06f6: 0x3ff2, 0x06f7: 0x8800, 0x06f8: 0x3ffa, 0x06f9: 0x8800, 0x06fa: 0x4002, 0x06fb: 0x8800,
- 0x06fc: 0x400a, 0x06fd: 0x8800, 0x06fe: 0x4012, 0x06ff: 0x8800,
- // Block 0x1c, offset 0x700
- 0x0700: 0x401a, 0x0701: 0x8800, 0x0702: 0x4022, 0x0704: 0x8800, 0x0705: 0x402a,
- 0x0706: 0x8800, 0x0707: 0x4032, 0x0708: 0x8800, 0x0709: 0x403a,
- 0x070f: 0x8800, 0x0710: 0x4042, 0x0711: 0x404a,
- 0x0712: 0x8800, 0x0713: 0x4052, 0x0714: 0x405a, 0x0715: 0x8800, 0x0716: 0x4062, 0x0717: 0x406a,
- 0x0718: 0x8800, 0x0719: 0x4072, 0x071a: 0x407a, 0x071b: 0x8800, 0x071c: 0x4082, 0x071d: 0x408a,
- 0x072f: 0x8800,
- 0x0730: 0x8800, 0x0731: 0x8800, 0x0732: 0x8800, 0x0734: 0x3fc2,
- 0x0737: 0x4092, 0x0738: 0x409a, 0x0739: 0x40a2, 0x073a: 0x40aa,
- 0x073d: 0x8800, 0x073e: 0x40b2,
- // Block 0x1d, offset 0x740
- 0x0740: 0x13e9, 0x0741: 0x0d6d, 0x0742: 0x1445, 0x0743: 0x1411, 0x0744: 0x0ec9, 0x0745: 0x075d,
- 0x0746: 0x0951, 0x0747: 0x1699, 0x0748: 0x1699, 0x0749: 0x0a7d, 0x074a: 0x14cd, 0x074b: 0x09b5,
- 0x074c: 0x0a79, 0x074d: 0x0c61, 0x074e: 0x1041, 0x074f: 0x11d1, 0x0750: 0x1309, 0x0751: 0x1345,
- 0x0752: 0x1379, 0x0753: 0x148d, 0x0754: 0x0de5, 0x0755: 0x0e71, 0x0756: 0x0f1d, 0x0757: 0x0fb5,
- 0x0758: 0x12d1, 0x0759: 0x14b5, 0x075a: 0x15e1, 0x075b: 0x0781, 0x075c: 0x0925, 0x075d: 0x0df9,
- 0x075e: 0x0f41, 0x075f: 0x1305, 0x0760: 0x1631, 0x0761: 0x0b25, 0x0762: 0x0ee9, 0x0763: 0x12f5,
- 0x0764: 0x1389, 0x0765: 0x0c95, 0x0766: 0x122d, 0x0767: 0x1351, 0x0768: 0x0b91, 0x0769: 0x0d81,
- 0x076a: 0x0e89, 0x076b: 0x0f8d, 0x076c: 0x1499, 0x076d: 0x07c1, 0x076e: 0x0859, 0x076f: 0x08c5,
- 0x0770: 0x0cfd, 0x0771: 0x0df1, 0x0772: 0x0f3d, 0x0773: 0x1061, 0x0774: 0x11e9, 0x0775: 0x12fd,
- 0x0776: 0x1315, 0x0777: 0x1439, 0x0778: 0x155d, 0x0779: 0x1611, 0x077a: 0x162d, 0x077b: 0x109d,
- 0x077c: 0x10dd, 0x077d: 0x1195, 0x077e: 0x12b5, 0x077f: 0x14e9,
- // Block 0x1e, offset 0x780
- 0x0780: 0x1639, 0x0781: 0x13bd, 0x0782: 0x0a39, 0x0783: 0x0bad, 0x0784: 0x114d, 0x0785: 0x120d,
- 0x0786: 0x0f71, 0x0787: 0x10a5, 0x0788: 0x1409, 0x0789: 0x1555, 0x078a: 0x0a35, 0x078b: 0x0b01,
- 0x078c: 0x0de9, 0x078d: 0x0e9d, 0x078e: 0x0ed1, 0x078f: 0x1185, 0x0790: 0x11ad, 0x0791: 0x1515,
- 0x0792: 0x08c1, 0x0793: 0x1219, 0x0794: 0x0865, 0x0795: 0x0861, 0x0796: 0x1109, 0x0797: 0x1199,
- 0x0798: 0x12cd, 0x0799: 0x151d, 0x079a: 0x13d9, 0x079b: 0x0c99, 0x079c: 0x0de5, 0x079d: 0x13c9,
- 0x079e: 0x0769, 0x079f: 0x0ad5, 0x07a0: 0x0c05, 0x07a1: 0x0fa1, 0x07a2: 0x1021, 0x07a3: 0x08e5,
- 0x07a4: 0x10ad, 0x07a5: 0x07d1, 0x07a6: 0x0be9, 0x07a7: 0x0749, 0x07a8: 0x0e5d, 0x07a9: 0x0d15,
- 0x07aa: 0x1181, 0x07ab: 0x0939, 0x07ac: 0x0a25, 0x07ad: 0x106d, 0x07ae: 0x12d5, 0x07af: 0x13ad,
- 0x07b0: 0x0e29, 0x07b1: 0x1469, 0x07b2: 0x0e55, 0x07b3: 0x0ca9, 0x07b4: 0x128d, 0x07b5: 0x0cc9,
- 0x07b6: 0x101d, 0x07b7: 0x079d, 0x07b8: 0x0819, 0x07b9: 0x085d, 0x07ba: 0x0dc5, 0x07bb: 0x116d,
- 0x07bc: 0x1265, 0x07bd: 0x13b9, 0x07be: 0x14c9, 0x07bf: 0x08cd,
- // Block 0x1f, offset 0x7c0
- 0x07c0: 0x0981, 0x07c1: 0x0a89, 0x07c2: 0x0ba1, 0x07c3: 0x0d31, 0x07c4: 0x0eed, 0x07c5: 0x10b1,
- 0x07c6: 0x1505, 0x07c7: 0x15e9, 0x07c8: 0x163d, 0x07c9: 0x1655, 0x07ca: 0x08a9, 0x07cb: 0x0d65,
- 0x07cc: 0x0e15, 0x07cd: 0x145d, 0x07ce: 0x0b6d, 0x07cf: 0x0c49, 0x07d0: 0x0c65, 0x07d1: 0x0cf5,
- 0x07d2: 0x0edd, 0x07d3: 0x0f29, 0x07d4: 0x0fd9, 0x07d5: 0x10fd, 0x07d6: 0x11a1, 0x07d7: 0x1205,
- 0x07d8: 0x144d, 0x07d9: 0x12dd, 0x07da: 0x1475, 0x07db: 0x14ed, 0x07dc: 0x0881, 0x07dd: 0x08ad,
- 0x07de: 0x0995, 0x07df: 0x0f19, 0x07e0: 0x1365, 0x07e1: 0x13ad, 0x07e2: 0x0b8d, 0x07e3: 0x0bfd,
- 0x07e4: 0x0cc1, 0x07e5: 0x0e21, 0x07e6: 0x1149, 0x07e7: 0x0f95, 0x07e8: 0x07ad, 0x07e9: 0x09f1,
- 0x07ea: 0x0ad5, 0x07eb: 0x0b39, 0x07ec: 0x0c09, 0x07ed: 0x0fb1, 0x07ee: 0x0fcd, 0x07ef: 0x11dd,
- 0x07f0: 0x11fd, 0x07f1: 0x14d1, 0x07f2: 0x1551, 0x07f3: 0x1561, 0x07f4: 0x159d, 0x07f5: 0x07c5,
- 0x07f6: 0x10f1, 0x07f7: 0x14bd, 0x07f8: 0x1539, 0x07f9: 0x0c21, 0x07fa: 0x0789, 0x07fb: 0x07e9,
- 0x07fc: 0x0ad9, 0x07fd: 0x0af9, 0x07fe: 0x0d21, 0x07ff: 0x0de5,
- // Block 0x20, offset 0x800
- 0x0800: 0x0f35, 0x0801: 0x103d, 0x0802: 0x12e9, 0x0803: 0x1489, 0x0804: 0x1691, 0x0805: 0x0d55,
- 0x0806: 0x1511, 0x0807: 0x08a5, 0x0808: 0x0da1, 0x0809: 0x0dad, 0x080a: 0x0e81, 0x080b: 0x0eb9,
- 0x080c: 0x0fbd, 0x080d: 0x1019, 0x080e: 0x1099, 0x080f: 0x117d, 0x0810: 0x15a9, 0x0811: 0x0821,
- 0x0812: 0x0c75, 0x0813: 0x1521, 0x0814: 0x07d9, 0x0815: 0x0b1d, 0x0816: 0x0ea1, 0x0817: 0x1451,
- 0x0818: 0x0bd9, 0x0819: 0x0c29, 0x081a: 0x0db5, 0x081b: 0x0fa1, 0x081c: 0x1529, 0x081d: 0x0889,
- 0x081e: 0x0971, 0x081f: 0x0b09, 0x0820: 0x0d45, 0x0821: 0x0d91, 0x0822: 0x0dd1, 0x0823: 0x0e65,
- 0x0824: 0x0fb9, 0x0825: 0x102d, 0x0826: 0x11c9, 0x0827: 0x1369, 0x0828: 0x1375, 0x0829: 0x14c5,
- 0x082a: 0x1545, 0x082b: 0x08f5, 0x082c: 0x0ebd, 0x082d: 0x0975, 0x082e: 0x0f39, 0x082f: 0x0fdd,
- 0x0830: 0x12f9, 0x0831: 0x152d, 0x0832: 0x1619, 0x0833: 0x1641, 0x0834: 0x0da9, 0x0835: 0x0e99,
- 0x0836: 0x1235, 0x0837: 0x1129, 0x0838: 0x1135, 0x0839: 0x1159, 0x083a: 0x0f89, 0x083b: 0x0f11,
- 0x083c: 0x13d5, 0x083d: 0x07a5, 0x083e: 0x129d, 0x083f: 0x088d,
- // Block 0x21, offset 0x840
- 0x0840: 0x087d, 0x0841: 0x0b7d, 0x0842: 0x0c9d, 0x0843: 0x1165, 0x0844: 0x0ac5, 0x0845: 0x0e75,
- 0x0846: 0x0d61, 0x0847: 0x1459, 0x0848: 0x1359, 0x0849: 0x1519, 0x084a: 0x1395, 0x084b: 0x0b99,
- 0x084c: 0x07f9, 0x084d: 0x09cd, 0x0850: 0x0a21,
- 0x0852: 0x0d51, 0x0855: 0x0869, 0x0856: 0x0f91, 0x0857: 0x1055,
- 0x0858: 0x10b9, 0x0859: 0x10d5, 0x085a: 0x10d9, 0x085b: 0x10ed, 0x085c: 0x1569, 0x085d: 0x115d,
- 0x085e: 0x11e1, 0x0860: 0x1301, 0x0862: 0x13c5,
- 0x0865: 0x1479, 0x0866: 0x14a5,
- 0x086a: 0x15bd, 0x086b: 0x15c1, 0x086c: 0x15c5, 0x086d: 0x1629, 0x086e: 0x149d, 0x086f: 0x1535,
- 0x0870: 0x07c9, 0x0871: 0x07ed, 0x0872: 0x0801, 0x0873: 0x08bd, 0x0874: 0x08c9, 0x0875: 0x0909,
- 0x0876: 0x09bd, 0x0877: 0x09d9, 0x0878: 0x09e1, 0x0879: 0x0a1d, 0x087a: 0x0a29, 0x087b: 0x0b05,
- 0x087c: 0x0b0d, 0x087d: 0x0c15, 0x087e: 0x0c3d, 0x087f: 0x0c45,
- // Block 0x22, offset 0x880
- 0x0880: 0x0c5d, 0x0881: 0x0d09, 0x0882: 0x0d39, 0x0883: 0x0d59, 0x0884: 0x0dc9, 0x0885: 0x0e8d,
- 0x0886: 0x0ea9, 0x0887: 0x0ed9, 0x0888: 0x0f2d, 0x0889: 0x0f4d, 0x088a: 0x0fc1, 0x088b: 0x10a1,
- 0x088c: 0x10bd, 0x088d: 0x10c5, 0x088e: 0x10c1, 0x088f: 0x10c9, 0x0890: 0x10cd, 0x0891: 0x10d1,
- 0x0892: 0x10e5, 0x0893: 0x10e9, 0x0894: 0x110d, 0x0895: 0x1121, 0x0896: 0x113d, 0x0897: 0x11a1,
- 0x0898: 0x11a9, 0x0899: 0x11b1, 0x089a: 0x11c5, 0x089b: 0x11ed, 0x089c: 0x123d, 0x089d: 0x1271,
- 0x089e: 0x1271, 0x089f: 0x12d9, 0x08a0: 0x1381, 0x08a1: 0x1399, 0x08a2: 0x13cd, 0x08a3: 0x13d1,
- 0x08a4: 0x1415, 0x08a5: 0x1419, 0x08a6: 0x1471, 0x08a7: 0x1479, 0x08a8: 0x1549, 0x08a9: 0x158d,
- 0x08aa: 0x15a5, 0x08ab: 0x0c0d, 0x08ac: 0x1780, 0x08ad: 0x1255,
- 0x08b0: 0x0751, 0x08b1: 0x0855, 0x08b2: 0x0815, 0x08b3: 0x07bd, 0x08b4: 0x07fd, 0x08b5: 0x0829,
- 0x08b6: 0x08b9, 0x08b7: 0x08d5, 0x08b8: 0x09bd, 0x08b9: 0x09a9, 0x08ba: 0x09b9, 0x08bb: 0x09d5,
- 0x08bc: 0x0a21, 0x08bd: 0x0a31, 0x08be: 0x0a75, 0x08bf: 0x0a81,
- // Block 0x23, offset 0x8c0
- 0x08c0: 0x0a9d, 0x08c1: 0x0aad, 0x08c2: 0x0b95, 0x08c3: 0x0b9d, 0x08c4: 0x0bcd, 0x08c5: 0x0bed,
- 0x08c6: 0x0c1d, 0x08c7: 0x0c35, 0x08c8: 0x0c25, 0x08c9: 0x0c45, 0x08ca: 0x0c39, 0x08cb: 0x0c5d,
- 0x08cc: 0x0c79, 0x08cd: 0x0cd1, 0x08ce: 0x0cdd, 0x08cf: 0x0ce5, 0x08d0: 0x0d0d, 0x08d1: 0x0d51,
- 0x08d2: 0x0d81, 0x08d3: 0x0d85, 0x08d4: 0x0d99, 0x08d5: 0x0e19, 0x08d6: 0x0e29, 0x08d7: 0x0e81,
- 0x08d8: 0x0ecd, 0x08d9: 0x0ec5, 0x08da: 0x0ed9, 0x08db: 0x0ef5, 0x08dc: 0x0f2d, 0x08dd: 0x1085,
- 0x08de: 0x0f51, 0x08df: 0x0f85, 0x08e0: 0x0f91, 0x08e1: 0x0fd1, 0x08e2: 0x0fed, 0x08e3: 0x1011,
- 0x08e4: 0x1035, 0x08e5: 0x1039, 0x08e6: 0x1055, 0x08e7: 0x1059, 0x08e8: 0x1069, 0x08e9: 0x107d,
- 0x08ea: 0x1079, 0x08eb: 0x10a9, 0x08ec: 0x1125, 0x08ed: 0x113d, 0x08ee: 0x1155, 0x08ef: 0x118d,
- 0x08f0: 0x11a1, 0x08f1: 0x11bd, 0x08f2: 0x11ed, 0x08f3: 0x12a1, 0x08f4: 0x12c9, 0x08f5: 0x133d,
- 0x08f6: 0x1385, 0x08f7: 0x1391, 0x08f8: 0x1399, 0x08f9: 0x13b1, 0x08fa: 0x13c5, 0x08fb: 0x13b5,
- 0x08fc: 0x13cd, 0x08fd: 0x13c9, 0x08fe: 0x13c1, 0x08ff: 0x13d1,
- // Block 0x24, offset 0x900
- 0x0900: 0x13dd, 0x0901: 0x1419, 0x0902: 0x1455, 0x0903: 0x1485, 0x0904: 0x14b9, 0x0905: 0x14d9,
- 0x0906: 0x1525, 0x0907: 0x1549, 0x0908: 0x1569, 0x0909: 0x157d, 0x090a: 0x158d, 0x090b: 0x1599,
- 0x090c: 0x15a5, 0x090d: 0x15f9, 0x090e: 0x1699, 0x090f: 0x1717, 0x0910: 0x1712, 0x0911: 0x1744,
- 0x0912: 0x0679, 0x0913: 0x06a1, 0x0914: 0x06a5, 0x0915: 0x17c6, 0x0916: 0x17f3, 0x0917: 0x186b,
- 0x0918: 0x1685, 0x0919: 0x1695,
- // Block 0x25, offset 0x940
- 0x0940: 0x076d, 0x0941: 0x0765, 0x0942: 0x0775, 0x0943: 0x16a9, 0x0944: 0x07b9, 0x0945: 0x07c9,
- 0x0946: 0x07cd, 0x0947: 0x07d5, 0x0948: 0x07dd, 0x0949: 0x07e1, 0x094a: 0x07ed, 0x094b: 0x07e5,
- 0x094c: 0x0625, 0x094d: 0x16bd, 0x094e: 0x0801, 0x094f: 0x0805, 0x0950: 0x0809, 0x0951: 0x0825,
- 0x0952: 0x16ae, 0x0953: 0x0629, 0x0954: 0x0811, 0x0955: 0x0831, 0x0956: 0x16b8, 0x0957: 0x0841,
- 0x0958: 0x0849, 0x0959: 0x07a9, 0x095a: 0x0851, 0x095b: 0x0855, 0x095c: 0x1893, 0x095d: 0x0871,
- 0x095e: 0x0879, 0x095f: 0x0631, 0x0960: 0x0891, 0x0961: 0x0895, 0x0962: 0x089d, 0x0963: 0x08a1,
- 0x0964: 0x0635, 0x0965: 0x08b9, 0x0966: 0x08bd, 0x0967: 0x08c9, 0x0968: 0x08d5, 0x0969: 0x08d9,
- 0x096a: 0x08dd, 0x096b: 0x08e5, 0x096c: 0x0905, 0x096d: 0x0909, 0x096e: 0x0911, 0x096f: 0x0921,
- 0x0970: 0x0929, 0x0971: 0x092d, 0x0972: 0x092d, 0x0973: 0x092d, 0x0974: 0x16cc, 0x0975: 0x0f05,
- 0x0976: 0x0941, 0x0977: 0x0949, 0x0978: 0x16d1, 0x0979: 0x0955, 0x097a: 0x095d, 0x097b: 0x0965,
- 0x097c: 0x098d, 0x097d: 0x0979, 0x097e: 0x0985, 0x097f: 0x0989,
- // Block 0x26, offset 0x980
- 0x0980: 0x0991, 0x0981: 0x0999, 0x0982: 0x099d, 0x0983: 0x09a5, 0x0984: 0x09ad, 0x0985: 0x09b1,
- 0x0986: 0x09b1, 0x0987: 0x09b9, 0x0988: 0x09c1, 0x0989: 0x09c5, 0x098a: 0x09d1, 0x098b: 0x09f5,
- 0x098c: 0x09d9, 0x098d: 0x09f9, 0x098e: 0x09dd, 0x098f: 0x09e5, 0x0990: 0x087d, 0x0991: 0x0a41,
- 0x0992: 0x0a09, 0x0993: 0x0a0d, 0x0994: 0x0a11, 0x0995: 0x0a05, 0x0996: 0x0a19, 0x0997: 0x0a15,
- 0x0998: 0x0a2d, 0x0999: 0x16d6, 0x099a: 0x0a49, 0x099b: 0x0a4d, 0x099c: 0x0a55, 0x099d: 0x0a61,
- 0x099e: 0x0a69, 0x099f: 0x0a85, 0x09a0: 0x16db, 0x09a1: 0x16e0, 0x09a2: 0x0a91, 0x09a3: 0x0a95,
- 0x09a4: 0x0a99, 0x09a5: 0x0a8d, 0x09a6: 0x0aa1, 0x09a7: 0x0639, 0x09a8: 0x063d, 0x09a9: 0x0aa9,
- 0x09aa: 0x0ab1, 0x09ab: 0x0ab1, 0x09ac: 0x16e5, 0x09ad: 0x0acd, 0x09ae: 0x0ad1, 0x09af: 0x0ad5,
- 0x09b0: 0x0add, 0x09b1: 0x16ea, 0x09b2: 0x0ae5, 0x09b3: 0x0ae9, 0x09b4: 0x0bc1, 0x09b5: 0x0af1,
- 0x09b6: 0x0641, 0x09b7: 0x0afd, 0x09b8: 0x0b0d, 0x09b9: 0x0b19, 0x09ba: 0x0b15, 0x09bb: 0x16f4,
- 0x09bc: 0x0b21, 0x09bd: 0x16f9, 0x09be: 0x0b2d, 0x09bf: 0x0b29,
- // Block 0x27, offset 0x9c0
- 0x09c0: 0x0b31, 0x09c1: 0x0b41, 0x09c2: 0x0b45, 0x09c3: 0x0645, 0x09c4: 0x0b55, 0x09c5: 0x0b5d,
- 0x09c6: 0x0b61, 0x09c7: 0x0b65, 0x09c8: 0x0649, 0x09c9: 0x16fe, 0x09ca: 0x064d, 0x09cb: 0x0b81,
- 0x09cc: 0x0b85, 0x09cd: 0x0b89, 0x09ce: 0x0b91, 0x09cf: 0x18c5, 0x09d0: 0x0ba9, 0x09d1: 0x1708,
- 0x09d2: 0x1708, 0x09d3: 0x1249, 0x09d4: 0x0bb9, 0x09d5: 0x0bb9, 0x09d6: 0x0651, 0x09d7: 0x172b,
- 0x09d8: 0x17fd, 0x09d9: 0x0bc9, 0x09da: 0x0bd1, 0x09db: 0x0655, 0x09dc: 0x0be5, 0x09dd: 0x0bf5,
- 0x09de: 0x0bf9, 0x09df: 0x0c01, 0x09e0: 0x0c11, 0x09e1: 0x065d, 0x09e2: 0x0659, 0x09e3: 0x0c15,
- 0x09e4: 0x170d, 0x09e5: 0x0c19, 0x09e6: 0x0c2d, 0x09e7: 0x0c31, 0x09e8: 0x0c35, 0x09e9: 0x0c31,
- 0x09ea: 0x0c41, 0x09eb: 0x0c45, 0x09ec: 0x0c55, 0x09ed: 0x0c4d, 0x09ee: 0x0c51, 0x09ef: 0x0c59,
- 0x09f0: 0x0c5d, 0x09f1: 0x0c61, 0x09f2: 0x0c6d, 0x09f3: 0x0c71, 0x09f4: 0x0c89, 0x09f5: 0x0c91,
- 0x09f6: 0x0ca1, 0x09f7: 0x0cb5, 0x09f8: 0x171c, 0x09f9: 0x0cb1, 0x09fa: 0x0ca5, 0x09fb: 0x0cbd,
- 0x09fc: 0x0cc5, 0x09fd: 0x0cd9, 0x09fe: 0x1721, 0x09ff: 0x0ce1,
- // Block 0x28, offset 0xa00
- 0x0a00: 0x0cd5, 0x0a01: 0x0ccd, 0x0a02: 0x0661, 0x0a03: 0x0ce9, 0x0a04: 0x0cf1, 0x0a05: 0x0cf9,
- 0x0a06: 0x0ced, 0x0a07: 0x0665, 0x0a08: 0x0d09, 0x0a09: 0x0d11, 0x0a0a: 0x1726, 0x0a0b: 0x0d3d,
- 0x0a0c: 0x0d71, 0x0a0d: 0x0d4d, 0x0a0e: 0x0671, 0x0a0f: 0x0d59, 0x0a10: 0x066d, 0x0a11: 0x0669,
- 0x0a12: 0x0835, 0x0a13: 0x0839, 0x0a14: 0x0d75, 0x0a15: 0x0d5d, 0x0a16: 0x121d, 0x0a17: 0x06d5,
- 0x0a18: 0x0d81, 0x0a19: 0x0d85, 0x0a1a: 0x0d89, 0x0a1b: 0x0d9d, 0x0a1c: 0x0d95, 0x0a1d: 0x173f,
- 0x0a1e: 0x0675, 0x0a1f: 0x0db1, 0x0a20: 0x0da5, 0x0a21: 0x0dc1, 0x0a22: 0x0dc9, 0x0a23: 0x1749,
- 0x0a24: 0x0dcd, 0x0a25: 0x0db9, 0x0a26: 0x0dd5, 0x0a27: 0x0679, 0x0a28: 0x0dd9, 0x0a29: 0x0ddd,
- 0x0a2a: 0x0de1, 0x0a2b: 0x0ded, 0x0a2c: 0x174e, 0x0a2d: 0x0df5, 0x0a2e: 0x067d, 0x0a2f: 0x0e01,
- 0x0a30: 0x1753, 0x0a31: 0x0e05, 0x0a32: 0x0681, 0x0a33: 0x0e11, 0x0a34: 0x0e1d, 0x0a35: 0x0e29,
- 0x0a36: 0x0e2d, 0x0a37: 0x1758, 0x0a38: 0x16ef, 0x0a39: 0x175d, 0x0a3a: 0x0e4d, 0x0a3b: 0x1762,
- 0x0a3c: 0x0e59, 0x0a3d: 0x0e61, 0x0a3e: 0x0e51, 0x0a3f: 0x0e6d,
- // Block 0x29, offset 0xa40
- 0x0a40: 0x0e7d, 0x0a41: 0x0e8d, 0x0a42: 0x0e81, 0x0a43: 0x0e85, 0x0a44: 0x0e91, 0x0a45: 0x0e95,
- 0x0a46: 0x1767, 0x0a47: 0x0e79, 0x0a48: 0x0ead, 0x0a49: 0x0eb1, 0x0a4a: 0x0685, 0x0a4b: 0x0ec5,
- 0x0a4c: 0x0ec1, 0x0a4d: 0x176c, 0x0a4e: 0x0ea5, 0x0a4f: 0x0ee1, 0x0a50: 0x1771, 0x0a51: 0x1776,
- 0x0a52: 0x0ee5, 0x0a53: 0x0ef9, 0x0a54: 0x0ef5, 0x0a55: 0x0ef1, 0x0a56: 0x0689, 0x0a57: 0x0efd,
- 0x0a58: 0x0f0d, 0x0a59: 0x0f09, 0x0a5a: 0x0f15, 0x0a5b: 0x16b3, 0x0a5c: 0x0f25, 0x0a5d: 0x177b,
- 0x0a5e: 0x0f31, 0x0a5f: 0x1785, 0x0a60: 0x0f45, 0x0a61: 0x0f51, 0x0a62: 0x0f65, 0x0a63: 0x178a,
- 0x0a64: 0x0f79, 0x0a65: 0x0f7d, 0x0a66: 0x178f, 0x0a67: 0x1794, 0x0a68: 0x0f99, 0x0a69: 0x0fa9,
- 0x0a6a: 0x068d, 0x0a6b: 0x0fad, 0x0a6c: 0x0691, 0x0a6d: 0x0691, 0x0a6e: 0x0fc5, 0x0a6f: 0x0fc9,
- 0x0a70: 0x0fd1, 0x0a71: 0x0fd5, 0x0a72: 0x0fe1, 0x0a73: 0x0695, 0x0a74: 0x0ff9, 0x0a75: 0x1799,
- 0x0a76: 0x1015, 0x0a77: 0x179e, 0x0a78: 0x1021, 0x0a79: 0x1703, 0x0a7a: 0x1031, 0x0a7b: 0x17a3,
- 0x0a7c: 0x17a8, 0x0a7d: 0x17ad, 0x0a7e: 0x0699, 0x0a7f: 0x069d,
- // Block 0x2a, offset 0xa80
- 0x0a80: 0x1069, 0x0a81: 0x17b7, 0x0a82: 0x17b2, 0x0a83: 0x17bc, 0x0a84: 0x17c1, 0x0a85: 0x1071,
- 0x0a86: 0x1075, 0x0a87: 0x1075, 0x0a88: 0x107d, 0x0a89: 0x06a5, 0x0a8a: 0x1081, 0x0a8b: 0x06a9,
- 0x0a8c: 0x06ad, 0x0a8d: 0x17cb, 0x0a8e: 0x1095, 0x0a8f: 0x109d, 0x0a90: 0x10a9, 0x0a91: 0x06b1,
- 0x0a92: 0x17d0, 0x0a93: 0x10cd, 0x0a94: 0x17d5, 0x0a95: 0x17da, 0x0a96: 0x10ed, 0x0a97: 0x1105,
- 0x0a98: 0x06b5, 0x0a99: 0x110d, 0x0a9a: 0x1111, 0x0a9b: 0x1115, 0x0a9c: 0x17df, 0x0a9d: 0x17e4,
- 0x0a9e: 0x17e4, 0x0a9f: 0x112d, 0x0aa0: 0x06b9, 0x0aa1: 0x17e9, 0x0aa2: 0x1141, 0x0aa3: 0x1145,
- 0x0aa4: 0x06bd, 0x0aa5: 0x17ee, 0x0aa6: 0x1161, 0x0aa7: 0x06c1, 0x0aa8: 0x1171, 0x0aa9: 0x1169,
- 0x0aaa: 0x1179, 0x0aab: 0x17f8, 0x0aac: 0x1191, 0x0aad: 0x06c5, 0x0aae: 0x119d, 0x0aaf: 0x11a5,
- 0x0ab0: 0x11b5, 0x0ab1: 0x06c9, 0x0ab2: 0x1802, 0x0ab3: 0x1807, 0x0ab4: 0x06cd, 0x0ab5: 0x180c,
- 0x0ab6: 0x11cd, 0x0ab7: 0x1811, 0x0ab8: 0x11d9, 0x0ab9: 0x11e5, 0x0aba: 0x11ed, 0x0abb: 0x1816,
- 0x0abc: 0x181b, 0x0abd: 0x1201, 0x0abe: 0x1820, 0x0abf: 0x1209,
- // Block 0x2b, offset 0xac0
- 0x0ac0: 0x1730, 0x0ac1: 0x06d1, 0x0ac2: 0x1221, 0x0ac3: 0x1225, 0x0ac4: 0x06d9, 0x0ac5: 0x1229,
- 0x0ac6: 0x0aa5, 0x0ac7: 0x1825, 0x0ac8: 0x182a, 0x0ac9: 0x1735, 0x0aca: 0x173a, 0x0acb: 0x1249,
- 0x0acc: 0x124d, 0x0acd: 0x1465, 0x0ace: 0x06dd, 0x0acf: 0x1279, 0x0ad0: 0x1275, 0x0ad1: 0x127d,
- 0x0ad2: 0x08b1, 0x0ad3: 0x1281, 0x0ad4: 0x1285, 0x0ad5: 0x1289, 0x0ad6: 0x1291, 0x0ad7: 0x182f,
- 0x0ad8: 0x128d, 0x0ad9: 0x1295, 0x0ada: 0x12a9, 0x0adb: 0x12ad, 0x0adc: 0x1299, 0x0add: 0x12b1,
- 0x0ade: 0x12c5, 0x0adf: 0x12d9, 0x0ae0: 0x12a5, 0x0ae1: 0x12b9, 0x0ae2: 0x12bd, 0x0ae3: 0x12c1,
- 0x0ae4: 0x1834, 0x0ae5: 0x183e, 0x0ae6: 0x1839, 0x0ae7: 0x06e1, 0x0ae8: 0x12e1, 0x0ae9: 0x12e5,
- 0x0aea: 0x12ed, 0x0aeb: 0x1852, 0x0aec: 0x12f1, 0x0aed: 0x1843, 0x0aee: 0x06e5, 0x0aef: 0x06e9,
- 0x0af0: 0x1848, 0x0af1: 0x184d, 0x0af2: 0x06ed, 0x0af3: 0x1311, 0x0af4: 0x1315, 0x0af5: 0x1319,
- 0x0af6: 0x131d, 0x0af7: 0x1329, 0x0af8: 0x1325, 0x0af9: 0x1331, 0x0afa: 0x132d, 0x0afb: 0x133d,
- 0x0afc: 0x1335, 0x0afd: 0x1339, 0x0afe: 0x1341, 0x0aff: 0x06f1,
- // Block 0x2c, offset 0xb00
- 0x0b00: 0x1349, 0x0b01: 0x134d, 0x0b02: 0x06f5, 0x0b03: 0x135d, 0x0b04: 0x1361, 0x0b05: 0x1857,
- 0x0b06: 0x136d, 0x0b07: 0x1371, 0x0b08: 0x06f9, 0x0b09: 0x137d, 0x0b0a: 0x062d, 0x0b0b: 0x185c,
- 0x0b0c: 0x1861, 0x0b0d: 0x06fd, 0x0b0e: 0x0701, 0x0b0f: 0x13a9, 0x0b10: 0x13c1, 0x0b11: 0x13dd,
- 0x0b12: 0x13ed, 0x0b13: 0x1866, 0x0b14: 0x1401, 0x0b15: 0x1405, 0x0b16: 0x141d, 0x0b17: 0x1429,
- 0x0b18: 0x1870, 0x0b19: 0x16c2, 0x0b1a: 0x1435, 0x0b1b: 0x1431, 0x0b1c: 0x143d, 0x0b1d: 0x16c7,
- 0x0b1e: 0x1449, 0x0b1f: 0x1455, 0x0b20: 0x1875, 0x0b21: 0x187a, 0x0b22: 0x1495, 0x0b23: 0x14a1,
- 0x0b24: 0x14a9, 0x0b25: 0x187f, 0x0b26: 0x14ad, 0x0b27: 0x14d5, 0x0b28: 0x14e1, 0x0b29: 0x14e5,
- 0x0b2a: 0x14dd, 0x0b2b: 0x14f1, 0x0b2c: 0x14f5, 0x0b2d: 0x1884, 0x0b2e: 0x1501, 0x0b2f: 0x0705,
- 0x0b30: 0x1509, 0x0b31: 0x1889, 0x0b32: 0x0709, 0x0b33: 0x1541, 0x0b34: 0x0b35, 0x0b35: 0x1559,
- 0x0b36: 0x188e, 0x0b37: 0x1898, 0x0b38: 0x070d, 0x0b39: 0x0711, 0x0b3a: 0x1581, 0x0b3b: 0x189d,
- 0x0b3c: 0x0715, 0x0b3d: 0x18a2, 0x0b3e: 0x1599, 0x0b3f: 0x1599,
- // Block 0x2d, offset 0xb40
- 0x0b40: 0x15a1, 0x0b41: 0x18a7, 0x0b42: 0x15b9, 0x0b43: 0x0719, 0x0b44: 0x15c9, 0x0b45: 0x15d5,
- 0x0b46: 0x15dd, 0x0b47: 0x15e5, 0x0b48: 0x071d, 0x0b49: 0x18ac, 0x0b4a: 0x15f9, 0x0b4b: 0x1615,
- 0x0b4c: 0x1621, 0x0b4d: 0x0721, 0x0b4e: 0x0725, 0x0b4f: 0x1625, 0x0b50: 0x18b1, 0x0b51: 0x0729,
- 0x0b52: 0x18b6, 0x0b53: 0x18bb, 0x0b54: 0x18c0, 0x0b55: 0x1649, 0x0b56: 0x072d, 0x0b57: 0x165d,
- 0x0b58: 0x1665, 0x0b59: 0x1669, 0x0b5a: 0x1671, 0x0b5b: 0x1679, 0x0b5c: 0x1681, 0x0b5d: 0x18ca,
-}
-
-// nfcSparseOffset: 98 entries, 196 bytes
-var nfcSparseOffset = []uint16{0x0, 0x2, 0x6, 0x8, 0x13, 0x23, 0x25, 0x2a, 0x35, 0x44, 0x51, 0x59, 0x5d, 0x62, 0x64, 0x73, 0x7b, 0x82, 0x85, 0x8d, 0x91, 0x95, 0x97, 0x99, 0xa2, 0xa6, 0xad, 0xb2, 0xb5, 0xbf, 0xc1, 0xc8, 0xd0, 0xd3, 0xd5, 0xd7, 0xd9, 0xde, 0xed, 0xf9, 0xfb, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10b, 0x10d, 0x110, 0x113, 0x115, 0x118, 0x11b, 0x11f, 0x128, 0x12a, 0x12d, 0x12f, 0x139, 0x148, 0x14a, 0x158, 0x15b, 0x161, 0x167, 0x172, 0x176, 0x178, 0x17a, 0x17c, 0x17e, 0x180, 0x186, 0x189, 0x18b, 0x18d, 0x18f, 0x192, 0x194, 0x196, 0x198, 0x19a, 0x1a0, 0x1a3, 0x1a5, 0x1a7, 0x1a9, 0x1b7, 0x1c0, 0x1c2, 0x1c4, 0x1ca, 0x1d2, 0x1d9, 0x1dc, 0x1e9, 0x1f3, 0x1f5}
-
-// nfcSparseValues: 503 entries, 2012 bytes
-var nfcSparseValues = [503]valueRange{
- // Block 0x0, offset 0x1
- {value: 0x0000, lo: 0x01},
- {value: 0x8800, lo: 0xa8, hi: 0xa8},
- // Block 0x1, offset 0x2
- {value: 0x0091, lo: 0x03},
- {value: 0x46c8, lo: 0xa0, hi: 0xa1},
- {value: 0x46fa, lo: 0xaf, hi: 0xb0},
- {value: 0x8800, lo: 0xb7, hi: 0xb7},
- // Block 0x2, offset 0x3
- {value: 0x0000, lo: 0x01},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- // Block 0x3, offset 0x4
- {value: 0x0006, lo: 0x0a},
- {value: 0x8800, lo: 0x81, hi: 0x81},
- {value: 0x8800, lo: 0x85, hi: 0x85},
- {value: 0x8800, lo: 0x89, hi: 0x89},
- {value: 0x4826, lo: 0x8a, hi: 0x8a},
- {value: 0x4844, lo: 0x8b, hi: 0x8b},
- {value: 0x36b1, lo: 0x8c, hi: 0x8c},
- {value: 0x36c9, lo: 0x8d, hi: 0x8d},
- {value: 0x485c, lo: 0x8e, hi: 0x8e},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x36e7, lo: 0x93, hi: 0x94},
- // Block 0x4, offset 0x5
- {value: 0x0000, lo: 0x0f},
- {value: 0x8800, lo: 0x83, hi: 0x83},
- {value: 0x8800, lo: 0x87, hi: 0x87},
- {value: 0x8800, lo: 0x8b, hi: 0x8b},
- {value: 0x8800, lo: 0x8d, hi: 0x8d},
- {value: 0x378f, lo: 0x90, hi: 0x90},
- {value: 0x379b, lo: 0x91, hi: 0x91},
- {value: 0x3789, lo: 0x93, hi: 0x93},
- {value: 0x8800, lo: 0x96, hi: 0x96},
- {value: 0x3801, lo: 0x97, hi: 0x97},
- {value: 0x37cb, lo: 0x9c, hi: 0x9c},
- {value: 0x37b3, lo: 0x9d, hi: 0x9d},
- {value: 0x37dd, lo: 0x9e, hi: 0x9e},
- {value: 0x8800, lo: 0xb4, hi: 0xb5},
- {value: 0x3807, lo: 0xb6, hi: 0xb6},
- {value: 0x380d, lo: 0xb7, hi: 0xb7},
- // Block 0x5, offset 0x6
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x83, hi: 0x87},
- // Block 0x6, offset 0x7
- {value: 0x0001, lo: 0x04},
- {value: 0x8018, lo: 0x81, hi: 0x82},
- {value: 0x80e6, lo: 0x84, hi: 0x84},
- {value: 0x80dc, lo: 0x85, hi: 0x85},
- {value: 0x8012, lo: 0x87, hi: 0x87},
- // Block 0x7, offset 0x8
- {value: 0x0000, lo: 0x0a},
- {value: 0x80e6, lo: 0x90, hi: 0x97},
- {value: 0x801e, lo: 0x98, hi: 0x98},
- {value: 0x801f, lo: 0x99, hi: 0x99},
- {value: 0x8020, lo: 0x9a, hi: 0x9a},
- {value: 0x382b, lo: 0xa2, hi: 0xa2},
- {value: 0x3831, lo: 0xa3, hi: 0xa3},
- {value: 0x383d, lo: 0xa4, hi: 0xa4},
- {value: 0x3837, lo: 0xa5, hi: 0xa5},
- {value: 0x3843, lo: 0xa6, hi: 0xa6},
- {value: 0x8800, lo: 0xa7, hi: 0xa7},
- // Block 0x8, offset 0x9
- {value: 0x0000, lo: 0x0e},
- {value: 0x3855, lo: 0x80, hi: 0x80},
- {value: 0x8800, lo: 0x81, hi: 0x81},
- {value: 0x3849, lo: 0x82, hi: 0x82},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x384f, lo: 0x93, hi: 0x93},
- {value: 0x8800, lo: 0x95, hi: 0x95},
- {value: 0x80e6, lo: 0x96, hi: 0x9c},
- {value: 0x80e6, lo: 0x9f, hi: 0xa2},
- {value: 0x80dc, lo: 0xa3, hi: 0xa3},
- {value: 0x80e6, lo: 0xa4, hi: 0xa4},
- {value: 0x80e6, lo: 0xa7, hi: 0xa8},
- {value: 0x80dc, lo: 0xaa, hi: 0xaa},
- {value: 0x80e6, lo: 0xab, hi: 0xac},
- {value: 0x80dc, lo: 0xad, hi: 0xad},
- // Block 0x9, offset 0xa
- {value: 0x0000, lo: 0x0c},
- {value: 0x8024, lo: 0x91, hi: 0x91},
- {value: 0x80e6, lo: 0xb0, hi: 0xb0},
- {value: 0x80dc, lo: 0xb1, hi: 0xb1},
- {value: 0x80e6, lo: 0xb2, hi: 0xb3},
- {value: 0x80dc, lo: 0xb4, hi: 0xb4},
- {value: 0x80e6, lo: 0xb5, hi: 0xb6},
- {value: 0x80dc, lo: 0xb7, hi: 0xb9},
- {value: 0x80e6, lo: 0xba, hi: 0xba},
- {value: 0x80dc, lo: 0xbb, hi: 0xbc},
- {value: 0x80e6, lo: 0xbd, hi: 0xbd},
- {value: 0x80dc, lo: 0xbe, hi: 0xbe},
- {value: 0x80e6, lo: 0xbf, hi: 0xbf},
- // Block 0xa, offset 0xb
- {value: 0x000a, lo: 0x07},
- {value: 0x80e6, lo: 0x80, hi: 0x80},
- {value: 0x80e6, lo: 0x81, hi: 0x81},
- {value: 0x80dc, lo: 0x82, hi: 0x83},
- {value: 0x80dc, lo: 0x84, hi: 0x85},
- {value: 0x80dc, lo: 0x86, hi: 0x87},
- {value: 0x80dc, lo: 0x88, hi: 0x89},
- {value: 0x80e6, lo: 0x8a, hi: 0x8a},
- // Block 0xb, offset 0xc
- {value: 0x0000, lo: 0x03},
- {value: 0x80e6, lo: 0xab, hi: 0xb1},
- {value: 0x80dc, lo: 0xb2, hi: 0xb2},
- {value: 0x80e6, lo: 0xb3, hi: 0xb3},
- // Block 0xc, offset 0xd
- {value: 0x0000, lo: 0x04},
- {value: 0x80e6, lo: 0x96, hi: 0x99},
- {value: 0x80e6, lo: 0x9b, hi: 0xa3},
- {value: 0x80e6, lo: 0xa5, hi: 0xa7},
- {value: 0x80e6, lo: 0xa9, hi: 0xad},
- // Block 0xd, offset 0xe
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0x99, hi: 0x9b},
- // Block 0xe, offset 0xf
- {value: 0x0000, lo: 0x0e},
- {value: 0x80e6, lo: 0xa4, hi: 0xa5},
- {value: 0x80dc, lo: 0xa6, hi: 0xa6},
- {value: 0x80e6, lo: 0xa7, hi: 0xa8},
- {value: 0x80dc, lo: 0xa9, hi: 0xa9},
- {value: 0x80e6, lo: 0xaa, hi: 0xac},
- {value: 0x80dc, lo: 0xad, hi: 0xaf},
- {value: 0x801b, lo: 0xb0, hi: 0xb0},
- {value: 0x801c, lo: 0xb1, hi: 0xb1},
- {value: 0x801d, lo: 0xb2, hi: 0xb2},
- {value: 0x80e6, lo: 0xb3, hi: 0xb5},
- {value: 0x80dc, lo: 0xb6, hi: 0xb6},
- {value: 0x80e6, lo: 0xb7, hi: 0xb8},
- {value: 0x80dc, lo: 0xb9, hi: 0xba},
- {value: 0x80e6, lo: 0xbb, hi: 0xbe},
- // Block 0xf, offset 0x10
- {value: 0x0000, lo: 0x07},
- {value: 0x8800, lo: 0xa8, hi: 0xa8},
- {value: 0x3ec2, lo: 0xa9, hi: 0xa9},
- {value: 0x8800, lo: 0xb0, hi: 0xb0},
- {value: 0x3eca, lo: 0xb1, hi: 0xb1},
- {value: 0x8800, lo: 0xb3, hi: 0xb3},
- {value: 0x3ed2, lo: 0xb4, hi: 0xb4},
- {value: 0x8607, lo: 0xbc, hi: 0xbc},
- // Block 0x10, offset 0x11
- {value: 0x0008, lo: 0x06},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x80e6, lo: 0x91, hi: 0x91},
- {value: 0x80dc, lo: 0x92, hi: 0x92},
- {value: 0x80e6, lo: 0x93, hi: 0x93},
- {value: 0x80e6, lo: 0x94, hi: 0x94},
- {value: 0x4502, lo: 0x98, hi: 0x9f},
- // Block 0x11, offset 0x12
- {value: 0x0000, lo: 0x02},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- {value: 0x8600, lo: 0xbe, hi: 0xbe},
- // Block 0x12, offset 0x13
- {value: 0x0007, lo: 0x07},
- {value: 0x8800, lo: 0x87, hi: 0x87},
- {value: 0x18cf, lo: 0x8b, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x97, hi: 0x97},
- {value: 0x4542, lo: 0x9c, hi: 0x9c},
- {value: 0x454a, lo: 0x9d, hi: 0x9d},
- {value: 0x4552, lo: 0x9f, hi: 0x9f},
- // Block 0x13, offset 0x14
- {value: 0x0000, lo: 0x03},
- {value: 0x457a, lo: 0xb3, hi: 0xb3},
- {value: 0x4582, lo: 0xb6, hi: 0xb6},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- // Block 0x14, offset 0x15
- {value: 0x0008, lo: 0x03},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x455a, lo: 0x99, hi: 0x9b},
- {value: 0x4572, lo: 0x9e, hi: 0x9e},
- // Block 0x15, offset 0x16
- {value: 0x0000, lo: 0x01},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- // Block 0x16, offset 0x17
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- // Block 0x17, offset 0x18
- {value: 0x0000, lo: 0x08},
- {value: 0x8800, lo: 0x87, hi: 0x87},
- {value: 0x18e4, lo: 0x88, hi: 0x88},
- {value: 0x18dd, lo: 0x8b, hi: 0x8b},
- {value: 0x18eb, lo: 0x8c, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x96, hi: 0x97},
- {value: 0x458a, lo: 0x9c, hi: 0x9c},
- {value: 0x4592, lo: 0x9d, hi: 0x9d},
- // Block 0x18, offset 0x19
- {value: 0x0000, lo: 0x03},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x18f2, lo: 0x94, hi: 0x94},
- {value: 0x8600, lo: 0xbe, hi: 0xbe},
- // Block 0x19, offset 0x1a
- {value: 0x0000, lo: 0x06},
- {value: 0x8800, lo: 0x86, hi: 0x87},
- {value: 0x18f9, lo: 0x8a, hi: 0x8a},
- {value: 0x1907, lo: 0x8b, hi: 0x8b},
- {value: 0x1900, lo: 0x8c, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x97, hi: 0x97},
- // Block 0x1a, offset 0x1b
- {value: 0x0607, lo: 0x04},
- {value: 0x8800, lo: 0x86, hi: 0x86},
- {value: 0x3eda, lo: 0x88, hi: 0x88},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8054, lo: 0x95, hi: 0x96},
- // Block 0x1b, offset 0x1c
- {value: 0x0000, lo: 0x02},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- {value: 0x8800, lo: 0xbf, hi: 0xbf},
- // Block 0x1c, offset 0x1d
- {value: 0x0000, lo: 0x09},
- {value: 0x190e, lo: 0x80, hi: 0x80},
- {value: 0x8600, lo: 0x82, hi: 0x82},
- {value: 0x8800, lo: 0x86, hi: 0x86},
- {value: 0x1915, lo: 0x87, hi: 0x87},
- {value: 0x191c, lo: 0x88, hi: 0x88},
- {value: 0x2e66, lo: 0x8a, hi: 0x8a},
- {value: 0x19a5, lo: 0x8b, hi: 0x8b},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x95, hi: 0x96},
- // Block 0x1d, offset 0x1e
- {value: 0x0000, lo: 0x01},
- {value: 0x8600, lo: 0xbe, hi: 0xbe},
- // Block 0x1e, offset 0x1f
- {value: 0x0000, lo: 0x06},
- {value: 0x8800, lo: 0x86, hi: 0x87},
- {value: 0x1923, lo: 0x8a, hi: 0x8a},
- {value: 0x1931, lo: 0x8b, hi: 0x8b},
- {value: 0x192a, lo: 0x8c, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x97, hi: 0x97},
- // Block 0x1f, offset 0x20
- {value: 0x0007, lo: 0x07},
- {value: 0x8609, lo: 0x8a, hi: 0x8a},
- {value: 0x8600, lo: 0x8f, hi: 0x8f},
- {value: 0x8800, lo: 0x99, hi: 0x99},
- {value: 0x3ee2, lo: 0x9a, hi: 0x9a},
- {value: 0x2e6d, lo: 0x9c, hi: 0x9d},
- {value: 0x1938, lo: 0x9e, hi: 0x9e},
- {value: 0x8600, lo: 0x9f, hi: 0x9f},
- // Block 0x20, offset 0x21
- {value: 0x0000, lo: 0x02},
- {value: 0x8067, lo: 0xb8, hi: 0xb9},
- {value: 0x8009, lo: 0xba, hi: 0xba},
- // Block 0x21, offset 0x22
- {value: 0x0000, lo: 0x01},
- {value: 0x806b, lo: 0x88, hi: 0x8b},
- // Block 0x22, offset 0x23
- {value: 0x0000, lo: 0x01},
- {value: 0x8076, lo: 0xb8, hi: 0xb9},
- // Block 0x23, offset 0x24
- {value: 0x0000, lo: 0x01},
- {value: 0x807a, lo: 0x88, hi: 0x8b},
- // Block 0x24, offset 0x25
- {value: 0x0000, lo: 0x04},
- {value: 0x80dc, lo: 0x98, hi: 0x99},
- {value: 0x80dc, lo: 0xb5, hi: 0xb5},
- {value: 0x80dc, lo: 0xb7, hi: 0xb7},
- {value: 0x80d8, lo: 0xb9, hi: 0xb9},
- // Block 0x25, offset 0x26
- {value: 0x0000, lo: 0x0e},
- {value: 0x2786, lo: 0x83, hi: 0x83},
- {value: 0x278d, lo: 0x8d, hi: 0x8d},
- {value: 0x2794, lo: 0x92, hi: 0x92},
- {value: 0x279b, lo: 0x97, hi: 0x97},
- {value: 0x27a2, lo: 0x9c, hi: 0x9c},
- {value: 0x277f, lo: 0xa9, hi: 0xa9},
- {value: 0x8081, lo: 0xb1, hi: 0xb1},
- {value: 0x8082, lo: 0xb2, hi: 0xb2},
- {value: 0x49b6, lo: 0xb3, hi: 0xb3},
- {value: 0x8084, lo: 0xb4, hi: 0xb4},
- {value: 0x49bf, lo: 0xb5, hi: 0xb5},
- {value: 0x459a, lo: 0xb6, hi: 0xb6},
- {value: 0x45a2, lo: 0xb8, hi: 0xb8},
- {value: 0x8082, lo: 0xba, hi: 0xbd},
- // Block 0x26, offset 0x27
- {value: 0x0000, lo: 0x0b},
- {value: 0x8082, lo: 0x80, hi: 0x80},
- {value: 0x49c8, lo: 0x81, hi: 0x81},
- {value: 0x80e6, lo: 0x82, hi: 0x83},
- {value: 0x8009, lo: 0x84, hi: 0x84},
- {value: 0x80e6, lo: 0x86, hi: 0x87},
- {value: 0x27b0, lo: 0x93, hi: 0x93},
- {value: 0x27b7, lo: 0x9d, hi: 0x9d},
- {value: 0x27be, lo: 0xa2, hi: 0xa2},
- {value: 0x27c5, lo: 0xa7, hi: 0xa7},
- {value: 0x27cc, lo: 0xac, hi: 0xac},
- {value: 0x27a9, lo: 0xb9, hi: 0xb9},
- // Block 0x27, offset 0x28
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0x86, hi: 0x86},
- // Block 0x28, offset 0x29
- {value: 0x0000, lo: 0x05},
- {value: 0x8800, lo: 0xa5, hi: 0xa5},
- {value: 0x193f, lo: 0xa6, hi: 0xa6},
- {value: 0x8600, lo: 0xae, hi: 0xae},
- {value: 0x8007, lo: 0xb7, hi: 0xb7},
- {value: 0x8009, lo: 0xb9, hi: 0xba},
- // Block 0x29, offset 0x2a
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0x8d, hi: 0x8d},
- // Block 0x2a, offset 0x2b
- {value: 0x0000, lo: 0x01},
- {value: 0x8800, lo: 0x80, hi: 0x92},
- // Block 0x2b, offset 0x2c
- {value: 0x0000, lo: 0x01},
- {value: 0x8e00, lo: 0xa1, hi: 0xb5},
- // Block 0x2c, offset 0x2d
- {value: 0x0000, lo: 0x01},
- {value: 0x8600, lo: 0xa8, hi: 0xbf},
- // Block 0x2d, offset 0x2e
- {value: 0x0000, lo: 0x01},
- {value: 0x8600, lo: 0x80, hi: 0x82},
- // Block 0x2e, offset 0x2f
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x9d, hi: 0x9f},
- // Block 0x2f, offset 0x30
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0x94, hi: 0x94},
- {value: 0x8009, lo: 0xb4, hi: 0xb4},
- // Block 0x30, offset 0x31
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0x92, hi: 0x92},
- {value: 0x80e6, lo: 0x9d, hi: 0x9d},
- // Block 0x31, offset 0x32
- {value: 0x0000, lo: 0x01},
- {value: 0x80e4, lo: 0xa9, hi: 0xa9},
- // Block 0x32, offset 0x33
- {value: 0x0008, lo: 0x02},
- {value: 0x80de, lo: 0xb9, hi: 0xba},
- {value: 0x80dc, lo: 0xbb, hi: 0xbb},
- // Block 0x33, offset 0x34
- {value: 0x0000, lo: 0x02},
- {value: 0x80e6, lo: 0x97, hi: 0x97},
- {value: 0x80dc, lo: 0x98, hi: 0x98},
- // Block 0x34, offset 0x35
- {value: 0x0000, lo: 0x03},
- {value: 0x8009, lo: 0xa0, hi: 0xa0},
- {value: 0x80e6, lo: 0xb5, hi: 0xbc},
- {value: 0x80dc, lo: 0xbf, hi: 0xbf},
- // Block 0x35, offset 0x36
- {value: 0x0000, lo: 0x08},
- {value: 0x197e, lo: 0x80, hi: 0x80},
- {value: 0x1985, lo: 0x81, hi: 0x81},
- {value: 0x8800, lo: 0x82, hi: 0x82},
- {value: 0x198c, lo: 0x83, hi: 0x83},
- {value: 0x8009, lo: 0x84, hi: 0x84},
- {value: 0x80e6, lo: 0xab, hi: 0xab},
- {value: 0x80dc, lo: 0xac, hi: 0xac},
- {value: 0x80e6, lo: 0xad, hi: 0xb3},
- // Block 0x36, offset 0x37
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0xaa, hi: 0xab},
- // Block 0x37, offset 0x38
- {value: 0x0000, lo: 0x02},
- {value: 0x8007, lo: 0xa6, hi: 0xa6},
- {value: 0x8009, lo: 0xb2, hi: 0xb3},
- // Block 0x38, offset 0x39
- {value: 0x0000, lo: 0x01},
- {value: 0x8007, lo: 0xb7, hi: 0xb7},
- // Block 0x39, offset 0x3a
- {value: 0x0000, lo: 0x09},
- {value: 0x80e6, lo: 0x90, hi: 0x92},
- {value: 0x8001, lo: 0x94, hi: 0x94},
- {value: 0x80dc, lo: 0x95, hi: 0x99},
- {value: 0x80e6, lo: 0x9a, hi: 0x9b},
- {value: 0x80dc, lo: 0x9c, hi: 0x9f},
- {value: 0x80e6, lo: 0xa0, hi: 0xa0},
- {value: 0x8001, lo: 0xa2, hi: 0xa8},
- {value: 0x80dc, lo: 0xad, hi: 0xad},
- {value: 0x80e6, lo: 0xb4, hi: 0xb4},
- // Block 0x3a, offset 0x3b
- {value: 0x0000, lo: 0x0e},
- {value: 0x80e6, lo: 0x80, hi: 0x81},
- {value: 0x80dc, lo: 0x82, hi: 0x82},
- {value: 0x80e6, lo: 0x83, hi: 0x89},
- {value: 0x80dc, lo: 0x8a, hi: 0x8a},
- {value: 0x80e6, lo: 0x8b, hi: 0x8c},
- {value: 0x80ea, lo: 0x8d, hi: 0x8d},
- {value: 0x80d6, lo: 0x8e, hi: 0x8e},
- {value: 0x80dc, lo: 0x8f, hi: 0x8f},
- {value: 0x80ca, lo: 0x90, hi: 0x90},
- {value: 0x80e6, lo: 0x91, hi: 0xa6},
- {value: 0x80e9, lo: 0xbc, hi: 0xbc},
- {value: 0x80dc, lo: 0xbd, hi: 0xbd},
- {value: 0x80e6, lo: 0xbe, hi: 0xbe},
- {value: 0x80dc, lo: 0xbf, hi: 0xbf},
- // Block 0x3b, offset 0x3c
- {value: 0x0004, lo: 0x01},
- {value: 0x04a5, lo: 0x80, hi: 0x81},
- // Block 0x3c, offset 0x3d
- {value: 0x0000, lo: 0x0d},
- {value: 0x80e6, lo: 0x90, hi: 0x91},
- {value: 0x8001, lo: 0x92, hi: 0x93},
- {value: 0x80e6, lo: 0x94, hi: 0x97},
- {value: 0x8001, lo: 0x98, hi: 0x9a},
- {value: 0x80e6, lo: 0x9b, hi: 0x9c},
- {value: 0x80e6, lo: 0xa1, hi: 0xa1},
- {value: 0x8001, lo: 0xa5, hi: 0xa6},
- {value: 0x80e6, lo: 0xa7, hi: 0xa7},
- {value: 0x80dc, lo: 0xa8, hi: 0xa8},
- {value: 0x80e6, lo: 0xa9, hi: 0xa9},
- {value: 0x8001, lo: 0xaa, hi: 0xab},
- {value: 0x80dc, lo: 0xac, hi: 0xaf},
- {value: 0x80e6, lo: 0xb0, hi: 0xb0},
- // Block 0x3d, offset 0x3e
- {value: 0x4261, lo: 0x02},
- {value: 0x01b8, lo: 0xa6, hi: 0xa6},
- {value: 0x0057, lo: 0xaa, hi: 0xab},
- // Block 0x3e, offset 0x3f
- {value: 0x0007, lo: 0x05},
- {value: 0x8800, lo: 0x90, hi: 0x90},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x8800, lo: 0x94, hi: 0x94},
- {value: 0x3ba3, lo: 0x9a, hi: 0x9b},
- {value: 0x3bb1, lo: 0xae, hi: 0xae},
- // Block 0x3f, offset 0x40
- {value: 0x000e, lo: 0x05},
- {value: 0x3bb8, lo: 0x8d, hi: 0x8e},
- {value: 0x3bbf, lo: 0x8f, hi: 0x8f},
- {value: 0x8800, lo: 0x90, hi: 0x90},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x8800, lo: 0x94, hi: 0x94},
- // Block 0x40, offset 0x41
- {value: 0x4c1e, lo: 0x0a},
- {value: 0x8800, lo: 0x83, hi: 0x83},
- {value: 0x3bcd, lo: 0x84, hi: 0x84},
- {value: 0x8800, lo: 0x88, hi: 0x88},
- {value: 0x3bd4, lo: 0x89, hi: 0x89},
- {value: 0x8800, lo: 0x8b, hi: 0x8b},
- {value: 0x3bdb, lo: 0x8c, hi: 0x8c},
- {value: 0x8800, lo: 0xa3, hi: 0xa3},
- {value: 0x3be2, lo: 0xa4, hi: 0xa5},
- {value: 0x3be9, lo: 0xa6, hi: 0xa6},
- {value: 0x8800, lo: 0xbc, hi: 0xbc},
- // Block 0x41, offset 0x42
- {value: 0x0007, lo: 0x03},
- {value: 0x3c52, lo: 0xa0, hi: 0xa1},
- {value: 0x3c7c, lo: 0xa2, hi: 0xa3},
- {value: 0x3ca6, lo: 0xaa, hi: 0xad},
- // Block 0x42, offset 0x43
- {value: 0x0004, lo: 0x01},
- {value: 0x04fd, lo: 0xa9, hi: 0xaa},
- // Block 0x43, offset 0x44
- {value: 0x0000, lo: 0x01},
- {value: 0x44c3, lo: 0x9c, hi: 0x9c},
- // Block 0x44, offset 0x45
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0xaf, hi: 0xb1},
- // Block 0x45, offset 0x46
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0xbf, hi: 0xbf},
- // Block 0x46, offset 0x47
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0xa0, hi: 0xbf},
- // Block 0x47, offset 0x48
- {value: 0x0000, lo: 0x05},
- {value: 0x80da, lo: 0xaa, hi: 0xaa},
- {value: 0x80e4, lo: 0xab, hi: 0xab},
- {value: 0x80e8, lo: 0xac, hi: 0xac},
- {value: 0x80de, lo: 0xad, hi: 0xad},
- {value: 0x80e0, lo: 0xae, hi: 0xaf},
- // Block 0x48, offset 0x49
- {value: 0x0000, lo: 0x02},
- {value: 0x80e6, lo: 0xaf, hi: 0xaf},
- {value: 0x80e6, lo: 0xb4, hi: 0xbd},
- // Block 0x49, offset 0x4a
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x9f, hi: 0x9f},
- // Block 0x4a, offset 0x4b
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0xb0, hi: 0xb1},
- // Block 0x4b, offset 0x4c
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x86, hi: 0x86},
- // Block 0x4c, offset 0x4d
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0x84, hi: 0x84},
- {value: 0x80e6, lo: 0xa0, hi: 0xb1},
- // Block 0x4d, offset 0x4e
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0xab, hi: 0xad},
- // Block 0x4e, offset 0x4f
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x93, hi: 0x93},
- // Block 0x4f, offset 0x50
- {value: 0x0000, lo: 0x01},
- {value: 0x8007, lo: 0xb3, hi: 0xb3},
- // Block 0x50, offset 0x51
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x80, hi: 0x80},
- // Block 0x51, offset 0x52
- {value: 0x0000, lo: 0x05},
- {value: 0x80e6, lo: 0xb0, hi: 0xb0},
- {value: 0x80e6, lo: 0xb2, hi: 0xb3},
- {value: 0x80dc, lo: 0xb4, hi: 0xb4},
- {value: 0x80e6, lo: 0xb7, hi: 0xb8},
- {value: 0x80e6, lo: 0xbe, hi: 0xbf},
- // Block 0x52, offset 0x53
- {value: 0x0000, lo: 0x02},
- {value: 0x80e6, lo: 0x81, hi: 0x81},
- {value: 0x8009, lo: 0xb6, hi: 0xb6},
- // Block 0x53, offset 0x54
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0xad, hi: 0xad},
- // Block 0x54, offset 0x55
- {value: 0x0000, lo: 0x01},
- {value: 0x8100, lo: 0x80, hi: 0xbf},
- // Block 0x55, offset 0x56
- {value: 0x0000, lo: 0x01},
- {value: 0x8100, lo: 0x80, hi: 0xa3},
- // Block 0x56, offset 0x57
- {value: 0x0006, lo: 0x0d},
- {value: 0x4376, lo: 0x9d, hi: 0x9d},
- {value: 0x801a, lo: 0x9e, hi: 0x9e},
- {value: 0x43e8, lo: 0x9f, hi: 0x9f},
- {value: 0x43d6, lo: 0xaa, hi: 0xab},
- {value: 0x44da, lo: 0xac, hi: 0xac},
- {value: 0x44e2, lo: 0xad, hi: 0xad},
- {value: 0x432e, lo: 0xae, hi: 0xb1},
- {value: 0x434c, lo: 0xb2, hi: 0xb4},
- {value: 0x4364, lo: 0xb5, hi: 0xb6},
- {value: 0x4370, lo: 0xb8, hi: 0xb8},
- {value: 0x437c, lo: 0xb9, hi: 0xbb},
- {value: 0x4394, lo: 0xbc, hi: 0xbc},
- {value: 0x439a, lo: 0xbe, hi: 0xbe},
- // Block 0x57, offset 0x58
- {value: 0x0006, lo: 0x08},
- {value: 0x43a0, lo: 0x80, hi: 0x81},
- {value: 0x43ac, lo: 0x83, hi: 0x84},
- {value: 0x43be, lo: 0x86, hi: 0x89},
- {value: 0x43e2, lo: 0x8a, hi: 0x8a},
- {value: 0x435e, lo: 0x8b, hi: 0x8b},
- {value: 0x4346, lo: 0x8c, hi: 0x8c},
- {value: 0x438e, lo: 0x8d, hi: 0x8d},
- {value: 0x43b8, lo: 0x8e, hi: 0x8e},
- // Block 0x58, offset 0x59
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0xa0, hi: 0xa6},
- // Block 0x59, offset 0x5a
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0xbd, hi: 0xbd},
- // Block 0x5a, offset 0x5b
- {value: 0x00db, lo: 0x05},
- {value: 0x80dc, lo: 0x8d, hi: 0x8d},
- {value: 0x80e6, lo: 0x8f, hi: 0x8f},
- {value: 0x80e6, lo: 0xb8, hi: 0xb8},
- {value: 0x8001, lo: 0xb9, hi: 0xba},
- {value: 0x8009, lo: 0xbf, hi: 0xbf},
- // Block 0x5b, offset 0x5c
- {value: 0x05fe, lo: 0x07},
- {value: 0x8800, lo: 0x99, hi: 0x99},
- {value: 0x4222, lo: 0x9a, hi: 0x9a},
- {value: 0x8800, lo: 0x9b, hi: 0x9b},
- {value: 0x422c, lo: 0x9c, hi: 0x9c},
- {value: 0x8800, lo: 0xa5, hi: 0xa5},
- {value: 0x4236, lo: 0xab, hi: 0xab},
- {value: 0x8009, lo: 0xb9, hi: 0xba},
- // Block 0x5c, offset 0x5d
- {value: 0x0000, lo: 0x06},
- {value: 0x80e6, lo: 0x80, hi: 0x82},
- {value: 0x8600, lo: 0xa7, hi: 0xa7},
- {value: 0x1993, lo: 0xae, hi: 0xae},
- {value: 0x199c, lo: 0xaf, hi: 0xaf},
- {value: 0x8800, lo: 0xb1, hi: 0xb2},
- {value: 0x8009, lo: 0xb3, hi: 0xb4},
- // Block 0x5d, offset 0x5e
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0xb6, hi: 0xb6},
- {value: 0x8007, lo: 0xb7, hi: 0xb7},
- // Block 0x5e, offset 0x5f
- {value: 0x0000, lo: 0x0c},
- {value: 0x45b2, lo: 0x9e, hi: 0x9e},
- {value: 0x45bc, lo: 0x9f, hi: 0x9f},
- {value: 0x45f0, lo: 0xa0, hi: 0xa0},
- {value: 0x45fe, lo: 0xa1, hi: 0xa1},
- {value: 0x460c, lo: 0xa2, hi: 0xa2},
- {value: 0x461a, lo: 0xa3, hi: 0xa3},
- {value: 0x4628, lo: 0xa4, hi: 0xa4},
- {value: 0x80d8, lo: 0xa5, hi: 0xa6},
- {value: 0x8001, lo: 0xa7, hi: 0xa9},
- {value: 0x80e2, lo: 0xad, hi: 0xad},
- {value: 0x80d8, lo: 0xae, hi: 0xb2},
- {value: 0x80dc, lo: 0xbb, hi: 0xbf},
- // Block 0x5f, offset 0x60
- {value: 0x0000, lo: 0x09},
- {value: 0x80dc, lo: 0x80, hi: 0x82},
- {value: 0x80e6, lo: 0x85, hi: 0x89},
- {value: 0x80dc, lo: 0x8a, hi: 0x8b},
- {value: 0x80e6, lo: 0xaa, hi: 0xad},
- {value: 0x45c6, lo: 0xbb, hi: 0xbb},
- {value: 0x45d0, lo: 0xbc, hi: 0xbc},
- {value: 0x4636, lo: 0xbd, hi: 0xbd},
- {value: 0x4652, lo: 0xbe, hi: 0xbe},
- {value: 0x4644, lo: 0xbf, hi: 0xbf},
- // Block 0x60, offset 0x61
- {value: 0x0000, lo: 0x01},
- {value: 0x4660, lo: 0x80, hi: 0x80},
- // Block 0x61, offset 0x62
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x82, hi: 0x84},
-}
-
-// nfcLookup: 1088 bytes
-// Block 0 is the null block.
-var nfcLookup = [1088]uint8{
- // Block 0x0, offset 0x0
- // Block 0x1, offset 0x40
- // Block 0x2, offset 0x80
- // Block 0x3, offset 0xc0
- 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: 0x38, 0x121: 0x39, 0x123: 0x3a, 0x124: 0x3b, 0x125: 0x3c, 0x126: 0x3d, 0x127: 0x3e,
- 0x128: 0x3f, 0x129: 0x40, 0x12a: 0x41, 0x12b: 0x42, 0x12c: 0x3d, 0x12d: 0x43, 0x12e: 0x44, 0x12f: 0x45,
- 0x131: 0x46, 0x132: 0x47, 0x133: 0x48, 0x134: 0x49, 0x135: 0x4a, 0x137: 0x4b,
- 0x138: 0x4c, 0x139: 0x4d, 0x13a: 0x4e, 0x13b: 0x4f, 0x13c: 0x50, 0x13d: 0x51, 0x13e: 0x52, 0x13f: 0x53,
- // Block 0x5, offset 0x140
- 0x140: 0x54, 0x142: 0x55, 0x144: 0x56, 0x145: 0x57, 0x146: 0x58, 0x147: 0x59,
- 0x14d: 0x5a,
- 0x15c: 0x5b, 0x15f: 0x5c,
- 0x162: 0x5d, 0x164: 0x5e,
- 0x168: 0x5f, 0x169: 0x60, 0x16c: 0x0d, 0x16d: 0x61, 0x16e: 0x62, 0x16f: 0x63,
- 0x170: 0x64, 0x173: 0x65, 0x177: 0x66,
- 0x178: 0x0e, 0x179: 0x0f, 0x17a: 0x10, 0x17b: 0x11, 0x17c: 0x12, 0x17d: 0x13, 0x17e: 0x14, 0x17f: 0x15,
- // Block 0x6, offset 0x180
- 0x180: 0x67, 0x183: 0x68, 0x184: 0x69, 0x186: 0x6a, 0x187: 0x6b,
- 0x188: 0x6c, 0x189: 0x16, 0x18a: 0x17, 0x18b: 0x6d, 0x18c: 0x6e,
- 0x1ab: 0x6f,
- 0x1b3: 0x70, 0x1b5: 0x71, 0x1b7: 0x72,
- // Block 0x7, offset 0x1c0
- 0x1c0: 0x73, 0x1c1: 0x18, 0x1c2: 0x19, 0x1c3: 0x1a,
- // Block 0x8, offset 0x200
- 0x219: 0x74, 0x21a: 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,
- // 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,
- // 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,
- // Block 0xb, offset 0x2c0
- 0x2e4: 0x1b, 0x2e5: 0x1c, 0x2e6: 0x1d, 0x2e7: 0x1e,
- 0x2e8: 0x1f, 0x2e9: 0x20, 0x2ea: 0x21, 0x2eb: 0x22, 0x2ec: 0x82, 0x2ed: 0x83,
- 0x2f8: 0x84,
- // Block 0xc, offset 0x300
- 0x307: 0x85,
- 0x328: 0x86,
- // Block 0xd, offset 0x340
- 0x341: 0x77, 0x342: 0x87, 0x344: 0x88, 0x347: 0x7c,
- 0x35a: 0x89,
- // Block 0xe, offset 0x380
- 0x385: 0x8a, 0x386: 0x8b, 0x387: 0x8c,
- 0x389: 0x8d,
- // Block 0xf, offset 0x3c0
- 0x3e0: 0x23, 0x3e1: 0x24, 0x3e2: 0x25, 0x3e3: 0x26, 0x3e4: 0x27, 0x3e5: 0x28, 0x3e6: 0x29, 0x3e7: 0x2a,
- 0x3e8: 0x2b,
- // Block 0x10, offset 0x400
- 0x410: 0x0a, 0x411: 0x0b,
- 0x41d: 0x0c,
- 0x42f: 0x0d,
-}
-
-var nfcTrie = trie{nfcLookup[:], nfcValues[:], nfcSparseValues[:], nfcSparseOffset[:], 44}
-
-// nfkcValues: 5760 entries, 11520 bytes
-// Block 2 is the null block.
-var nfkcValues = [5760]uint16{
- // Block 0x0, offset 0x0
- 0x003c: 0x8800, 0x003d: 0x8800, 0x003e: 0x8800,
- // Block 0x1, offset 0x40
- 0x0041: 0x8800, 0x0042: 0x8800, 0x0043: 0x8800, 0x0044: 0x8800, 0x0045: 0x8800,
- 0x0046: 0x8800, 0x0047: 0x8800, 0x0048: 0x8800, 0x0049: 0x8800, 0x004a: 0x8800, 0x004b: 0x8800,
- 0x004c: 0x8800, 0x004d: 0x8800, 0x004e: 0x8800, 0x004f: 0x8800, 0x0050: 0x8800,
- 0x0052: 0x8800, 0x0053: 0x8800, 0x0054: 0x8800, 0x0055: 0x8800, 0x0056: 0x8800, 0x0057: 0x8800,
- 0x0058: 0x8800, 0x0059: 0x8800, 0x005a: 0x8800,
- 0x0061: 0x8800, 0x0062: 0x8800, 0x0063: 0x8800,
- 0x0064: 0x8800, 0x0065: 0x8800, 0x0066: 0x8800, 0x0067: 0x8800, 0x0068: 0x8800, 0x0069: 0x8800,
- 0x006a: 0x8800, 0x006b: 0x8800, 0x006c: 0x8800, 0x006d: 0x8800, 0x006e: 0x8800, 0x006f: 0x8800,
- 0x0070: 0x8800, 0x0072: 0x8800, 0x0073: 0x8800, 0x0074: 0x8800, 0x0075: 0x8800,
- 0x0076: 0x8800, 0x0077: 0x8800, 0x0078: 0x8800, 0x0079: 0x8800, 0x007a: 0x8800,
- // Block 0x2, offset 0x80
- // Block 0x3, offset 0xc0
- 0x00c0: 0x2f59, 0x00c1: 0x2f5e, 0x00c2: 0x466e, 0x00c3: 0x2f63, 0x00c4: 0x467d, 0x00c5: 0x4682,
- 0x00c6: 0x8800, 0x00c7: 0x468c, 0x00c8: 0x2fcc, 0x00c9: 0x2fd1, 0x00ca: 0x4691, 0x00cb: 0x2fe5,
- 0x00cc: 0x3058, 0x00cd: 0x305d, 0x00ce: 0x3062, 0x00cf: 0x46a5, 0x00d1: 0x30ee,
- 0x00d2: 0x3111, 0x00d3: 0x3116, 0x00d4: 0x46af, 0x00d5: 0x46b4, 0x00d6: 0x46c3,
- 0x00d8: 0x8800, 0x00d9: 0x319d, 0x00da: 0x31a2, 0x00db: 0x31a7, 0x00dc: 0x46f5, 0x00dd: 0x321f,
- 0x00e0: 0x3265, 0x00e1: 0x326a, 0x00e2: 0x46ff, 0x00e3: 0x326f,
- 0x00e4: 0x470e, 0x00e5: 0x4713, 0x00e6: 0x8800, 0x00e7: 0x471d, 0x00e8: 0x32d8, 0x00e9: 0x32dd,
- 0x00ea: 0x4722, 0x00eb: 0x32f1, 0x00ec: 0x3369, 0x00ed: 0x336e, 0x00ee: 0x3373, 0x00ef: 0x4736,
- 0x00f1: 0x33ff, 0x00f2: 0x3422, 0x00f3: 0x3427, 0x00f4: 0x4740, 0x00f5: 0x4745,
- 0x00f6: 0x4754, 0x00f8: 0x8800, 0x00f9: 0x34b3, 0x00fa: 0x34b8, 0x00fb: 0x34bd,
- 0x00fc: 0x4786, 0x00fd: 0x353a, 0x00ff: 0x3553,
- // Block 0x4, offset 0x100
- 0x0100: 0x2f68, 0x0101: 0x3274, 0x0102: 0x4673, 0x0103: 0x4704, 0x0104: 0x2f86, 0x0105: 0x3292,
- 0x0106: 0x2f9a, 0x0107: 0x32a6, 0x0108: 0x2f9f, 0x0109: 0x32ab, 0x010a: 0x2fa4, 0x010b: 0x32b0,
- 0x010c: 0x2fa9, 0x010d: 0x32b5, 0x010e: 0x2fb3, 0x010f: 0x32bf,
- 0x0112: 0x4696, 0x0113: 0x4727, 0x0114: 0x2fdb, 0x0115: 0x32e7, 0x0116: 0x2fe0, 0x0117: 0x32ec,
- 0x0118: 0x2ffe, 0x0119: 0x330a, 0x011a: 0x2fef, 0x011b: 0x32fb, 0x011c: 0x3017, 0x011d: 0x3323,
- 0x011e: 0x3021, 0x011f: 0x332d, 0x0120: 0x3026, 0x0121: 0x3332, 0x0122: 0x3030, 0x0123: 0x333c,
- 0x0124: 0x3035, 0x0125: 0x3341, 0x0128: 0x3067, 0x0129: 0x3378,
- 0x012a: 0x306c, 0x012b: 0x337d, 0x012c: 0x3071, 0x012d: 0x3382, 0x012e: 0x3094, 0x012f: 0x33a0,
- 0x0130: 0x3076, 0x0132: 0x1a9f, 0x0133: 0x1b29, 0x0134: 0x309e, 0x0135: 0x33aa,
- 0x0136: 0x30b2, 0x0137: 0x33c3, 0x0139: 0x30bc, 0x013a: 0x33cd, 0x013b: 0x30c6,
- 0x013c: 0x33d7, 0x013d: 0x30c1, 0x013e: 0x33d2, 0x013f: 0x1cee,
- // Block 0x5, offset 0x140
- 0x0140: 0x1d76, 0x0143: 0x30e9, 0x0144: 0x33fa, 0x0145: 0x3102,
- 0x0146: 0x3413, 0x0147: 0x30f8, 0x0148: 0x3409, 0x0149: 0x1d9e,
- 0x014c: 0x46b9, 0x014d: 0x474a, 0x014e: 0x311b, 0x014f: 0x342c, 0x0150: 0x3125, 0x0151: 0x3436,
- 0x0154: 0x3143, 0x0155: 0x3454, 0x0156: 0x315c, 0x0157: 0x346d,
- 0x0158: 0x314d, 0x0159: 0x345e, 0x015a: 0x46dc, 0x015b: 0x476d, 0x015c: 0x3166, 0x015d: 0x3477,
- 0x015e: 0x3175, 0x015f: 0x3486, 0x0160: 0x46e1, 0x0161: 0x4772, 0x0162: 0x318e, 0x0163: 0x34a4,
- 0x0164: 0x317f, 0x0165: 0x3495, 0x0168: 0x46eb, 0x0169: 0x477c,
- 0x016a: 0x46f0, 0x016b: 0x4781, 0x016c: 0x31ac, 0x016d: 0x34c2, 0x016e: 0x31b6, 0x016f: 0x34cc,
- 0x0170: 0x31bb, 0x0171: 0x34d1, 0x0172: 0x31d9, 0x0173: 0x34ef, 0x0174: 0x31fc, 0x0175: 0x3512,
- 0x0176: 0x3224, 0x0177: 0x353f, 0x0178: 0x3238, 0x0179: 0x3247, 0x017a: 0x3567, 0x017b: 0x3251,
- 0x017c: 0x3571, 0x017d: 0x3256, 0x017e: 0x3576, 0x017f: 0x00a7,
- // Block 0x6, offset 0x180
- 0x0184: 0x2e7f, 0x0185: 0x2e85,
- 0x0186: 0x2e8b, 0x0187: 0x1ab4, 0x0188: 0x1ab7, 0x0189: 0x1b4a, 0x018a: 0x1ac9, 0x018b: 0x1acc,
- 0x018c: 0x1b80, 0x018d: 0x2f72, 0x018e: 0x327e, 0x018f: 0x3080, 0x0190: 0x338c, 0x0191: 0x312a,
- 0x0192: 0x343b, 0x0193: 0x31c0, 0x0194: 0x34d6, 0x0195: 0x39b9, 0x0196: 0x3b48, 0x0197: 0x39b2,
- 0x0198: 0x3b41, 0x0199: 0x39c0, 0x019a: 0x3b4f, 0x019b: 0x39ab, 0x019c: 0x3b3a,
- 0x019e: 0x389a, 0x019f: 0x3a29, 0x01a0: 0x3893, 0x01a1: 0x3a22, 0x01a2: 0x359d, 0x01a3: 0x35af,
- 0x01a6: 0x302b, 0x01a7: 0x3337, 0x01a8: 0x30a8, 0x01a9: 0x33b9,
- 0x01aa: 0x46d2, 0x01ab: 0x4763, 0x01ac: 0x397a, 0x01ad: 0x3b09, 0x01ae: 0x35c1, 0x01af: 0x35c7,
- 0x01b0: 0x33af, 0x01b1: 0x1a84, 0x01b2: 0x1a87, 0x01b3: 0x1b11, 0x01b4: 0x3012, 0x01b5: 0x331e,
- 0x01b8: 0x30e4, 0x01b9: 0x33f5, 0x01ba: 0x38a1, 0x01bb: 0x3a30,
- 0x01bc: 0x3597, 0x01bd: 0x35a9, 0x01be: 0x35a3, 0x01bf: 0x35b5,
- // Block 0x7, offset 0x1c0
- 0x01c0: 0x2f77, 0x01c1: 0x3283, 0x01c2: 0x2f7c, 0x01c3: 0x3288, 0x01c4: 0x2ff4, 0x01c5: 0x3300,
- 0x01c6: 0x2ff9, 0x01c7: 0x3305, 0x01c8: 0x3085, 0x01c9: 0x3391, 0x01ca: 0x308a, 0x01cb: 0x3396,
- 0x01cc: 0x312f, 0x01cd: 0x3440, 0x01ce: 0x3134, 0x01cf: 0x3445, 0x01d0: 0x3152, 0x01d1: 0x3463,
- 0x01d2: 0x3157, 0x01d3: 0x3468, 0x01d4: 0x31c5, 0x01d5: 0x34db, 0x01d6: 0x31ca, 0x01d7: 0x34e0,
- 0x01d8: 0x3170, 0x01d9: 0x3481, 0x01da: 0x3189, 0x01db: 0x349f,
- 0x01de: 0x3044, 0x01df: 0x3350,
- 0x01e6: 0x4678, 0x01e7: 0x4709, 0x01e8: 0x46a0, 0x01e9: 0x4731,
- 0x01ea: 0x3949, 0x01eb: 0x3ad8, 0x01ec: 0x3926, 0x01ed: 0x3ab5, 0x01ee: 0x46be, 0x01ef: 0x474f,
- 0x01f0: 0x3942, 0x01f1: 0x3ad1, 0x01f2: 0x322e, 0x01f3: 0x3549,
- // Block 0x8, offset 0x200
- 0x0200: 0x86e6, 0x0201: 0x86e6, 0x0202: 0x86e6, 0x0203: 0x86e6, 0x0204: 0x86e6, 0x0205: 0x80e6,
- 0x0206: 0x86e6, 0x0207: 0x86e6, 0x0208: 0x86e6, 0x0209: 0x86e6, 0x020a: 0x86e6, 0x020b: 0x86e6,
- 0x020c: 0x86e6, 0x020d: 0x80e6, 0x020e: 0x80e6, 0x020f: 0x86e6, 0x0210: 0x80e6, 0x0211: 0x86e6,
- 0x0212: 0x80e6, 0x0213: 0x86e6, 0x0214: 0x86e6, 0x0215: 0x80e8, 0x0216: 0x80dc, 0x0217: 0x80dc,
- 0x0218: 0x80dc, 0x0219: 0x80dc, 0x021a: 0x80e8, 0x021b: 0x86d8, 0x021c: 0x80dc, 0x021d: 0x80dc,
- 0x021e: 0x80dc, 0x021f: 0x80dc, 0x0220: 0x80dc, 0x0221: 0x80ca, 0x0222: 0x80ca, 0x0223: 0x86dc,
- 0x0224: 0x86dc, 0x0225: 0x86dc, 0x0226: 0x86dc, 0x0227: 0x86ca, 0x0228: 0x86ca, 0x0229: 0x80dc,
- 0x022a: 0x80dc, 0x022b: 0x80dc, 0x022c: 0x80dc, 0x022d: 0x86dc, 0x022e: 0x86dc, 0x022f: 0x80dc,
- 0x0230: 0x86dc, 0x0231: 0x86dc, 0x0232: 0x80dc, 0x0233: 0x80dc, 0x0234: 0x8001, 0x0235: 0x8001,
- 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: 0x4994, 0x0241: 0x4999, 0x0242: 0x86e6, 0x0243: 0x499e, 0x0244: 0x49a3, 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,
- 0x0258: 0x80e8, 0x0259: 0x80dc, 0x025a: 0x80dc, 0x025b: 0x80e6, 0x025c: 0x80e9, 0x025d: 0x80ea,
- 0x025e: 0x80ea, 0x025f: 0x80e9, 0x0260: 0x80ea, 0x0261: 0x80ea, 0x0262: 0x80e9, 0x0263: 0x80e6,
- 0x0264: 0x80e6, 0x0265: 0x80e6, 0x0266: 0x80e6, 0x0267: 0x80e6, 0x0268: 0x80e6, 0x0269: 0x80e6,
- 0x026a: 0x80e6, 0x026b: 0x80e6, 0x026c: 0x80e6, 0x026d: 0x80e6, 0x026e: 0x80e6, 0x026f: 0x80e6,
- 0x0274: 0x0170,
- 0x027a: 0x428b,
- 0x027e: 0x0037,
- // Block 0xa, offset 0x280
- 0x0284: 0x4240, 0x0285: 0x4461,
- 0x0286: 0x35d3, 0x0287: 0x00d1, 0x0288: 0x35f1, 0x0289: 0x35fd, 0x028a: 0x360f,
- 0x028c: 0x362d, 0x028e: 0x363f, 0x028f: 0x365d, 0x0290: 0x3df2, 0x0291: 0x8800,
- 0x0295: 0x8800, 0x0297: 0x8800,
- 0x0299: 0x8800,
- 0x029f: 0x8800, 0x02a1: 0x8800,
- 0x02a5: 0x8800, 0x02a9: 0x8800,
- 0x02aa: 0x3621, 0x02ab: 0x3651, 0x02ac: 0x47e4, 0x02ad: 0x3681, 0x02ae: 0x480e, 0x02af: 0x3693,
- 0x02b0: 0x3e5a, 0x02b1: 0x8800, 0x02b5: 0x8800,
- 0x02b7: 0x8800, 0x02b9: 0x8800,
- 0x02bf: 0x8800,
- // Block 0xb, offset 0x2c0
- 0x02c1: 0x8800, 0x02c5: 0x8800,
- 0x02c9: 0x8800, 0x02ca: 0x4826, 0x02cb: 0x4844,
- 0x02cc: 0x36b1, 0x02cd: 0x36c9, 0x02ce: 0x485c, 0x02d0: 0x01be, 0x02d1: 0x01d0,
- 0x02d2: 0x01ac, 0x02d3: 0x42f2, 0x02d4: 0x42f8, 0x02d5: 0x01fa, 0x02d6: 0x01e8,
- 0x02f0: 0x01d6, 0x02f1: 0x01eb, 0x02f2: 0x01ee, 0x02f4: 0x0188, 0x02f5: 0x01c7,
- 0x02f9: 0x01a6,
- // Block 0xc, offset 0x300
- 0x0300: 0x370b, 0x0301: 0x3717, 0x0303: 0x3705,
- 0x0306: 0x8800, 0x0307: 0x36f3,
- 0x030c: 0x3747, 0x030d: 0x372f, 0x030e: 0x3759, 0x0310: 0x8800,
- 0x0313: 0x8800, 0x0315: 0x8800, 0x0316: 0x8800, 0x0317: 0x8800,
- 0x0318: 0x8800, 0x0319: 0x373b, 0x031a: 0x8800,
- 0x031e: 0x8800, 0x0323: 0x8800,
- 0x0327: 0x8800,
- 0x032b: 0x8800, 0x032d: 0x8800,
- 0x0330: 0x8800, 0x0333: 0x8800, 0x0335: 0x8800,
- 0x0336: 0x8800, 0x0337: 0x8800, 0x0338: 0x8800, 0x0339: 0x37bf, 0x033a: 0x8800,
- 0x033e: 0x8800,
- // Block 0xd, offset 0x340
- 0x0341: 0x371d, 0x0342: 0x37a1,
- 0x0350: 0x36f9, 0x0351: 0x377d,
- 0x0352: 0x36ff, 0x0353: 0x3783, 0x0356: 0x3711, 0x0357: 0x3795,
- 0x0358: 0x8800, 0x0359: 0x8800, 0x035a: 0x3813, 0x035b: 0x3819, 0x035c: 0x3723, 0x035d: 0x37a7,
- 0x035e: 0x3729, 0x035f: 0x37ad, 0x0362: 0x3735, 0x0363: 0x37b9,
- 0x0364: 0x3741, 0x0365: 0x37c5, 0x0366: 0x374d, 0x0367: 0x37d1, 0x0368: 0x8800, 0x0369: 0x8800,
- 0x036a: 0x381f, 0x036b: 0x3825, 0x036c: 0x3777, 0x036d: 0x37fb, 0x036e: 0x3753, 0x036f: 0x37d7,
- 0x0370: 0x375f, 0x0371: 0x37e3, 0x0372: 0x3765, 0x0373: 0x37e9, 0x0374: 0x376b, 0x0375: 0x37ef,
- 0x0378: 0x3771, 0x0379: 0x37f5,
- // Block 0xe, offset 0x380
- 0x0387: 0x1ea3,
- 0x0391: 0x80dc,
- 0x0392: 0x80e6, 0x0393: 0x80e6, 0x0394: 0x80e6, 0x0395: 0x80e6, 0x0396: 0x80dc, 0x0397: 0x80e6,
- 0x0398: 0x80e6, 0x0399: 0x80e6, 0x039a: 0x80de, 0x039b: 0x80dc, 0x039c: 0x80e6, 0x039d: 0x80e6,
- 0x039e: 0x80e6, 0x039f: 0x80e6, 0x03a0: 0x80e6, 0x03a1: 0x80e6, 0x03a2: 0x80dc, 0x03a3: 0x80dc,
- 0x03a4: 0x80dc, 0x03a5: 0x80dc, 0x03a6: 0x80dc, 0x03a7: 0x80dc, 0x03a8: 0x80e6, 0x03a9: 0x80e6,
- 0x03aa: 0x80dc, 0x03ab: 0x80e6, 0x03ac: 0x80e6, 0x03ad: 0x80de, 0x03ae: 0x80e4, 0x03af: 0x80e6,
- 0x03b0: 0x800a, 0x03b1: 0x800b, 0x03b2: 0x800c, 0x03b3: 0x800d, 0x03b4: 0x800e, 0x03b5: 0x800f,
- 0x03b6: 0x8010, 0x03b7: 0x8011, 0x03b8: 0x8012, 0x03b9: 0x8013, 0x03ba: 0x8013, 0x03bb: 0x8014,
- 0x03bc: 0x8015, 0x03bd: 0x8016, 0x03bf: 0x8017,
- // Block 0xf, offset 0x3c0
- 0x03c8: 0x8800, 0x03ca: 0x8800, 0x03cb: 0x801b,
- 0x03cc: 0x801c, 0x03cd: 0x801d, 0x03ce: 0x801e, 0x03cf: 0x801f, 0x03d0: 0x8020, 0x03d1: 0x8021,
- 0x03d2: 0x8022, 0x03d3: 0x86e6, 0x03d4: 0x86e6, 0x03d5: 0x86dc, 0x03d6: 0x80dc, 0x03d7: 0x80e6,
- 0x03d8: 0x80e6, 0x03d9: 0x80e6, 0x03da: 0x80e6, 0x03db: 0x80e6, 0x03dc: 0x80dc, 0x03dd: 0x80e6,
- 0x03de: 0x80e6, 0x03df: 0x80dc,
- 0x03f0: 0x8023, 0x03f5: 0x1ec6,
- 0x03f6: 0x2155, 0x03f7: 0x2191, 0x03f8: 0x218c,
- // Block 0x10, offset 0x400
- 0x0405: 0x8800,
- 0x0406: 0x1946, 0x0407: 0x8800, 0x0408: 0x194d, 0x0409: 0x8800, 0x040a: 0x1954, 0x040b: 0x8800,
- 0x040c: 0x195b, 0x040d: 0x8800, 0x040e: 0x1962, 0x0411: 0x8800,
- 0x0412: 0x1969,
- 0x0434: 0x8007, 0x0435: 0x8600,
- 0x043a: 0x8800, 0x043b: 0x1970,
- 0x043c: 0x8800, 0x043d: 0x1977, 0x043e: 0x8800, 0x043f: 0x8800,
- // Block 0x11, offset 0x440
- 0x0440: 0x0069, 0x0441: 0x006b, 0x0442: 0x006f, 0x0443: 0x0083, 0x0444: 0x00f8, 0x0445: 0x00fb,
- 0x0446: 0x0485, 0x0447: 0x0085, 0x0448: 0x0089, 0x0449: 0x008b, 0x044a: 0x0107, 0x044b: 0x010a,
- 0x044c: 0x010d, 0x044d: 0x008f, 0x044f: 0x0097, 0x0450: 0x009b, 0x0451: 0x00e3,
- 0x0452: 0x009f, 0x0453: 0x0101, 0x0454: 0x0489, 0x0455: 0x048d, 0x0456: 0x00a1, 0x0457: 0x00a9,
- 0x0458: 0x00ab, 0x0459: 0x0495, 0x045a: 0x012b, 0x045b: 0x00ad, 0x045c: 0x0499, 0x045d: 0x01be,
- 0x045e: 0x01c1, 0x045f: 0x01c4, 0x0460: 0x01fa, 0x0461: 0x01fd, 0x0462: 0x0093, 0x0463: 0x00a5,
- 0x0464: 0x00ab, 0x0465: 0x00ad, 0x0466: 0x01be, 0x0467: 0x01c1, 0x0468: 0x01eb, 0x0469: 0x01fa,
- 0x046a: 0x01fd,
- 0x0478: 0x020c,
- // Block 0x12, offset 0x480
- 0x049b: 0x00fe, 0x049c: 0x0087, 0x049d: 0x0104,
- 0x049e: 0x00d7, 0x049f: 0x010d, 0x04a0: 0x008d, 0x04a1: 0x0110, 0x04a2: 0x0113, 0x04a3: 0x0119,
- 0x04a4: 0x011f, 0x04a5: 0x0122, 0x04a6: 0x0125, 0x04a7: 0x049d, 0x04a8: 0x016a, 0x04a9: 0x0128,
- 0x04aa: 0x04a1, 0x04ab: 0x016d, 0x04ac: 0x0131, 0x04ad: 0x012e, 0x04ae: 0x0134, 0x04af: 0x0137,
- 0x04b0: 0x013a, 0x04b1: 0x013d, 0x04b2: 0x0140, 0x04b3: 0x014c, 0x04b4: 0x014f, 0x04b5: 0x00ef,
- 0x04b6: 0x0152, 0x04b7: 0x0155, 0x04b8: 0x0491, 0x04b9: 0x0158, 0x04ba: 0x015b, 0x04bb: 0x00b5,
- 0x04bc: 0x015e, 0x04bd: 0x0161, 0x04be: 0x0164, 0x04bf: 0x01d0,
- // Block 0x13, offset 0x4c0
- 0x04c0: 0x2f81, 0x04c1: 0x328d, 0x04c2: 0x2f8b, 0x04c3: 0x3297, 0x04c4: 0x2f90, 0x04c5: 0x329c,
- 0x04c6: 0x2f95, 0x04c7: 0x32a1, 0x04c8: 0x38b6, 0x04c9: 0x3a45, 0x04ca: 0x2fae, 0x04cb: 0x32ba,
- 0x04cc: 0x2fb8, 0x04cd: 0x32c4, 0x04ce: 0x2fc7, 0x04cf: 0x32d3, 0x04d0: 0x2fbd, 0x04d1: 0x32c9,
- 0x04d2: 0x2fc2, 0x04d3: 0x32ce, 0x04d4: 0x38d9, 0x04d5: 0x3a68, 0x04d6: 0x38e0, 0x04d7: 0x3a6f,
- 0x04d8: 0x3003, 0x04d9: 0x330f, 0x04da: 0x3008, 0x04db: 0x3314, 0x04dc: 0x38ee, 0x04dd: 0x3a7d,
- 0x04de: 0x300d, 0x04df: 0x3319, 0x04e0: 0x301c, 0x04e1: 0x3328, 0x04e2: 0x303a, 0x04e3: 0x3346,
- 0x04e4: 0x3049, 0x04e5: 0x3355, 0x04e6: 0x303f, 0x04e7: 0x334b, 0x04e8: 0x304e, 0x04e9: 0x335a,
- 0x04ea: 0x3053, 0x04eb: 0x335f, 0x04ec: 0x3099, 0x04ed: 0x33a5, 0x04ee: 0x38f5, 0x04ef: 0x3a84,
- 0x04f0: 0x30a3, 0x04f1: 0x33b4, 0x04f2: 0x30ad, 0x04f3: 0x33be, 0x04f4: 0x30b7, 0x04f5: 0x33c8,
- 0x04f6: 0x46aa, 0x04f7: 0x473b, 0x04f8: 0x38fc, 0x04f9: 0x3a8b, 0x04fa: 0x30d0, 0x04fb: 0x33e1,
- 0x04fc: 0x30cb, 0x04fd: 0x33dc, 0x04fe: 0x30d5, 0x04ff: 0x33e6,
- // Block 0x14, offset 0x500
- 0x0500: 0x30da, 0x0501: 0x33eb, 0x0502: 0x30df, 0x0503: 0x33f0, 0x0504: 0x30f3, 0x0505: 0x3404,
- 0x0506: 0x30fd, 0x0507: 0x340e, 0x0508: 0x310c, 0x0509: 0x341d, 0x050a: 0x3107, 0x050b: 0x3418,
- 0x050c: 0x391f, 0x050d: 0x3aae, 0x050e: 0x392d, 0x050f: 0x3abc, 0x0510: 0x3934, 0x0511: 0x3ac3,
- 0x0512: 0x393b, 0x0513: 0x3aca, 0x0514: 0x3139, 0x0515: 0x344a, 0x0516: 0x313e, 0x0517: 0x344f,
- 0x0518: 0x3148, 0x0519: 0x3459, 0x051a: 0x46d7, 0x051b: 0x4768, 0x051c: 0x3981, 0x051d: 0x3b10,
- 0x051e: 0x3161, 0x051f: 0x3472, 0x0520: 0x316b, 0x0521: 0x347c, 0x0522: 0x46e6, 0x0523: 0x4777,
- 0x0524: 0x3988, 0x0525: 0x3b17, 0x0526: 0x398f, 0x0527: 0x3b1e, 0x0528: 0x3996, 0x0529: 0x3b25,
- 0x052a: 0x317a, 0x052b: 0x348b, 0x052c: 0x3184, 0x052d: 0x349a, 0x052e: 0x3198, 0x052f: 0x34ae,
- 0x0530: 0x3193, 0x0531: 0x34a9, 0x0532: 0x31d4, 0x0533: 0x34ea, 0x0534: 0x31e3, 0x0535: 0x34f9,
- 0x0536: 0x31de, 0x0537: 0x34f4, 0x0538: 0x399d, 0x0539: 0x3b2c, 0x053a: 0x39a4, 0x053b: 0x3b33,
- 0x053c: 0x31e8, 0x053d: 0x34fe, 0x053e: 0x31ed, 0x053f: 0x3503,
- // Block 0x15, offset 0x540
- 0x0540: 0x31f2, 0x0541: 0x3508, 0x0542: 0x31f7, 0x0543: 0x350d, 0x0544: 0x3206, 0x0545: 0x351c,
- 0x0546: 0x3201, 0x0547: 0x3517, 0x0548: 0x320b, 0x0549: 0x3526, 0x054a: 0x3210, 0x054b: 0x352b,
- 0x054c: 0x3215, 0x054d: 0x3530, 0x054e: 0x3233, 0x054f: 0x354e, 0x0550: 0x324c, 0x0551: 0x356c,
- 0x0552: 0x325b, 0x0553: 0x357b, 0x0554: 0x3260, 0x0555: 0x3580, 0x0556: 0x3364, 0x0557: 0x3490,
- 0x0558: 0x3521, 0x0559: 0x355d, 0x055a: 0x1d22, 0x055b: 0x42bd,
- 0x0560: 0x4687, 0x0561: 0x4718, 0x0562: 0x2f6d, 0x0563: 0x3279,
- 0x0564: 0x3862, 0x0565: 0x39f1, 0x0566: 0x385b, 0x0567: 0x39ea, 0x0568: 0x3870, 0x0569: 0x39ff,
- 0x056a: 0x3869, 0x056b: 0x39f8, 0x056c: 0x38a8, 0x056d: 0x3a37, 0x056e: 0x387e, 0x056f: 0x3a0d,
- 0x0570: 0x3877, 0x0571: 0x3a06, 0x0572: 0x388c, 0x0573: 0x3a1b, 0x0574: 0x3885, 0x0575: 0x3a14,
- 0x0576: 0x38af, 0x0577: 0x3a3e, 0x0578: 0x469b, 0x0579: 0x472c, 0x057a: 0x2fea, 0x057b: 0x32f6,
- 0x057c: 0x2fd6, 0x057d: 0x32e2, 0x057e: 0x38c4, 0x057f: 0x3a53,
- // Block 0x16, offset 0x580
- 0x0580: 0x38bd, 0x0581: 0x3a4c, 0x0582: 0x38d2, 0x0583: 0x3a61, 0x0584: 0x38cb, 0x0585: 0x3a5a,
- 0x0586: 0x38e7, 0x0587: 0x3a76, 0x0588: 0x307b, 0x0589: 0x3387, 0x058a: 0x308f, 0x058b: 0x339b,
- 0x058c: 0x46cd, 0x058d: 0x475e, 0x058e: 0x3120, 0x058f: 0x3431, 0x0590: 0x390a, 0x0591: 0x3a99,
- 0x0592: 0x3903, 0x0593: 0x3a92, 0x0594: 0x3918, 0x0595: 0x3aa7, 0x0596: 0x3911, 0x0597: 0x3aa0,
- 0x0598: 0x3973, 0x0599: 0x3b02, 0x059a: 0x3957, 0x059b: 0x3ae6, 0x059c: 0x3950, 0x059d: 0x3adf,
- 0x059e: 0x3965, 0x059f: 0x3af4, 0x05a0: 0x395e, 0x05a1: 0x3aed, 0x05a2: 0x396c, 0x05a3: 0x3afb,
- 0x05a4: 0x31cf, 0x05a5: 0x34e5, 0x05a6: 0x31b1, 0x05a7: 0x34c7, 0x05a8: 0x39ce, 0x05a9: 0x3b5d,
- 0x05aa: 0x39c7, 0x05ab: 0x3b56, 0x05ac: 0x39dc, 0x05ad: 0x3b6b, 0x05ae: 0x39d5, 0x05af: 0x3b64,
- 0x05b0: 0x39e3, 0x05b1: 0x3b72, 0x05b2: 0x321a, 0x05b3: 0x3535, 0x05b4: 0x3242, 0x05b5: 0x3562,
- 0x05b6: 0x323d, 0x05b7: 0x3558, 0x05b8: 0x3229, 0x05b9: 0x3544,
- // Block 0x17, offset 0x5c0
- 0x05c0: 0x47ea, 0x05c1: 0x47f0, 0x05c2: 0x4904, 0x05c3: 0x491c, 0x05c4: 0x490c, 0x05c5: 0x4924,
- 0x05c6: 0x4914, 0x05c7: 0x492c, 0x05c8: 0x4790, 0x05c9: 0x4796, 0x05ca: 0x4874, 0x05cb: 0x488c,
- 0x05cc: 0x487c, 0x05cd: 0x4894, 0x05ce: 0x4884, 0x05cf: 0x489c, 0x05d0: 0x47fc, 0x05d1: 0x4802,
- 0x05d2: 0x3da2, 0x05d3: 0x3db2, 0x05d4: 0x3daa, 0x05d5: 0x3dba,
- 0x05d8: 0x479c, 0x05d9: 0x47a2, 0x05da: 0x3cd2, 0x05db: 0x3ce2, 0x05dc: 0x3cda, 0x05dd: 0x3cea,
- 0x05e0: 0x4814, 0x05e1: 0x481a, 0x05e2: 0x4934, 0x05e3: 0x494c,
- 0x05e4: 0x493c, 0x05e5: 0x4954, 0x05e6: 0x4944, 0x05e7: 0x495c, 0x05e8: 0x47a8, 0x05e9: 0x47ae,
- 0x05ea: 0x48a4, 0x05eb: 0x48bc, 0x05ec: 0x48ac, 0x05ed: 0x48c4, 0x05ee: 0x48b4, 0x05ef: 0x48cc,
- 0x05f0: 0x482c, 0x05f1: 0x4832, 0x05f2: 0x3e02, 0x05f3: 0x3e1a, 0x05f4: 0x3e0a, 0x05f5: 0x3e22,
- 0x05f6: 0x3e12, 0x05f7: 0x3e2a, 0x05f8: 0x47b4, 0x05f9: 0x47ba, 0x05fa: 0x3d02, 0x05fb: 0x3d1a,
- 0x05fc: 0x3d0a, 0x05fd: 0x3d22, 0x05fe: 0x3d12, 0x05ff: 0x3d2a,
- // Block 0x18, offset 0x600
- 0x0600: 0x4838, 0x0601: 0x483e, 0x0602: 0x3e32, 0x0603: 0x3e42, 0x0604: 0x3e3a, 0x0605: 0x3e4a,
- 0x0608: 0x47c0, 0x0609: 0x47c6, 0x060a: 0x3d32, 0x060b: 0x3d42,
- 0x060c: 0x3d3a, 0x060d: 0x3d4a, 0x0610: 0x484a, 0x0611: 0x4850,
- 0x0612: 0x3e6a, 0x0613: 0x3e82, 0x0614: 0x3e72, 0x0615: 0x3e8a, 0x0616: 0x3e7a, 0x0617: 0x3e92,
- 0x0619: 0x47cc, 0x061b: 0x3d52, 0x061d: 0x3d5a,
- 0x061f: 0x3d62, 0x0620: 0x4862, 0x0621: 0x4868, 0x0622: 0x4964, 0x0623: 0x497c,
- 0x0624: 0x496c, 0x0625: 0x4984, 0x0626: 0x4974, 0x0627: 0x498c, 0x0628: 0x47d2, 0x0629: 0x47d8,
- 0x062a: 0x48d4, 0x062b: 0x48ec, 0x062c: 0x48dc, 0x062d: 0x48f4, 0x062e: 0x48e4, 0x062f: 0x48fc,
- 0x0630: 0x47de, 0x0631: 0x4304, 0x0632: 0x367b, 0x0633: 0x430a, 0x0634: 0x4808, 0x0635: 0x4310,
- 0x0636: 0x368d, 0x0637: 0x4316, 0x0638: 0x36ab, 0x0639: 0x431c, 0x063a: 0x36c3, 0x063b: 0x4322,
- 0x063c: 0x4856, 0x063d: 0x4328,
- // Block 0x19, offset 0x640
- 0x0640: 0x3d8a, 0x0641: 0x3d92, 0x0642: 0x416e, 0x0643: 0x418c, 0x0644: 0x4178, 0x0645: 0x4196,
- 0x0646: 0x4182, 0x0647: 0x41a0, 0x0648: 0x3cc2, 0x0649: 0x3cca, 0x064a: 0x40ba, 0x064b: 0x40d8,
- 0x064c: 0x40c4, 0x064d: 0x40e2, 0x064e: 0x40ce, 0x064f: 0x40ec, 0x0650: 0x3dd2, 0x0651: 0x3dda,
- 0x0652: 0x41aa, 0x0653: 0x41c8, 0x0654: 0x41b4, 0x0655: 0x41d2, 0x0656: 0x41be, 0x0657: 0x41dc,
- 0x0658: 0x3cf2, 0x0659: 0x3cfa, 0x065a: 0x40f6, 0x065b: 0x4114, 0x065c: 0x4100, 0x065d: 0x411e,
- 0x065e: 0x410a, 0x065f: 0x4128, 0x0660: 0x3eaa, 0x0661: 0x3eb2, 0x0662: 0x41e6, 0x0663: 0x4204,
- 0x0664: 0x41f0, 0x0665: 0x420e, 0x0666: 0x41fa, 0x0667: 0x4218, 0x0668: 0x3d6a, 0x0669: 0x3d72,
- 0x066a: 0x4132, 0x066b: 0x4150, 0x066c: 0x413c, 0x066d: 0x415a, 0x066e: 0x4146, 0x066f: 0x4164,
- 0x0670: 0x366f, 0x0671: 0x3669, 0x0672: 0x3d7a, 0x0673: 0x3675, 0x0674: 0x3d82,
- 0x0676: 0x47f6, 0x0677: 0x3d9a, 0x0678: 0x35df, 0x0679: 0x35d9, 0x067a: 0x35cd, 0x067b: 0x42d4,
- 0x067c: 0x35e5, 0x067d: 0x426d, 0x067e: 0x01d3, 0x067f: 0x426d,
- // Block 0x1a, offset 0x680
- 0x0680: 0x4286, 0x0681: 0x4468, 0x0682: 0x3dc2, 0x0683: 0x3687, 0x0684: 0x3dca,
- 0x0686: 0x4820, 0x0687: 0x3de2, 0x0688: 0x35eb, 0x0689: 0x42da, 0x068a: 0x35f7, 0x068b: 0x42e0,
- 0x068c: 0x3603, 0x068d: 0x446f, 0x068e: 0x4476, 0x068f: 0x447d, 0x0690: 0x369f, 0x0691: 0x3699,
- 0x0692: 0x3dea, 0x0693: 0x44ca, 0x0696: 0x36a5, 0x0697: 0x3dfa,
- 0x0698: 0x361b, 0x0699: 0x3615, 0x069a: 0x3609, 0x069b: 0x42e6, 0x069d: 0x4484,
- 0x069e: 0x448b, 0x069f: 0x4492, 0x06a0: 0x36d5, 0x06a1: 0x36cf, 0x06a2: 0x3e52, 0x06a3: 0x44d2,
- 0x06a4: 0x36b7, 0x06a5: 0x36bd, 0x06a6: 0x36db, 0x06a7: 0x3e62, 0x06a8: 0x364b, 0x06a9: 0x3645,
- 0x06aa: 0x3639, 0x06ab: 0x42f2, 0x06ac: 0x3633, 0x06ad: 0x445a, 0x06ae: 0x4461, 0x06af: 0x0081,
- 0x06b2: 0x3e9a, 0x06b3: 0x36e1, 0x06b4: 0x3ea2,
- 0x06b6: 0x486e, 0x06b7: 0x3eba, 0x06b8: 0x3627, 0x06b9: 0x42ec, 0x06ba: 0x3657, 0x06bb: 0x42fe,
- 0x06bc: 0x3663, 0x06bd: 0x4240, 0x06be: 0x4272,
- // Block 0x1b, offset 0x6c0
- 0x06c0: 0x1d1a, 0x06c1: 0x1d1e, 0x06c2: 0x0047, 0x06c3: 0x1d96, 0x06c5: 0x1d2a,
- 0x06c6: 0x1d2e, 0x06c7: 0x00ec, 0x06c9: 0x1d9a, 0x06ca: 0x008f, 0x06cb: 0x0051,
- 0x06cc: 0x0051, 0x06cd: 0x0051, 0x06ce: 0x0091, 0x06cf: 0x00dd, 0x06d0: 0x0053, 0x06d1: 0x0053,
- 0x06d2: 0x0059, 0x06d3: 0x0099, 0x06d5: 0x005d, 0x06d6: 0x1acf,
- 0x06d9: 0x0061, 0x06da: 0x0063, 0x06db: 0x0065, 0x06dc: 0x0065, 0x06dd: 0x0065,
- 0x06e0: 0x1ae1, 0x06e1: 0x1d0a, 0x06e2: 0x1aea,
- 0x06e4: 0x0075, 0x06e6: 0x01b8, 0x06e8: 0x0075,
- 0x06ea: 0x0057, 0x06eb: 0x42b8, 0x06ec: 0x0045, 0x06ed: 0x0047, 0x06ef: 0x008b,
- 0x06f0: 0x004b, 0x06f1: 0x004d, 0x06f3: 0x005b, 0x06f4: 0x009f, 0x06f5: 0x020f,
- 0x06f6: 0x0212, 0x06f7: 0x0215, 0x06f8: 0x0218, 0x06f9: 0x0093, 0x06fb: 0x1cda,
- 0x06fc: 0x01e8, 0x06fd: 0x01c1, 0x06fe: 0x0179, 0x06ff: 0x01a0,
- // Block 0x1c, offset 0x700
- 0x0700: 0x04d5, 0x0705: 0x0049,
- 0x0706: 0x0089, 0x0707: 0x008b, 0x0708: 0x0093, 0x0709: 0x0095,
- 0x0710: 0x2370, 0x0711: 0x237c,
- 0x0712: 0x2430, 0x0713: 0x2358, 0x0714: 0x23dc, 0x0715: 0x2364, 0x0716: 0x23e2, 0x0717: 0x23fa,
- 0x0718: 0x2406, 0x0719: 0x236a, 0x071a: 0x240c, 0x071b: 0x2376, 0x071c: 0x2400, 0x071d: 0x2412,
- 0x071e: 0x2418, 0x071f: 0x1dfe, 0x0720: 0x0053, 0x0721: 0x1a9c, 0x0722: 0x1ce6, 0x0723: 0x1aa5,
- 0x0724: 0x006d, 0x0725: 0x1aed, 0x0726: 0x1d12, 0x0727: 0x1e8a, 0x0728: 0x1aa8, 0x0729: 0x0071,
- 0x072a: 0x1af9, 0x072b: 0x1d16, 0x072c: 0x0059, 0x072d: 0x0047, 0x072e: 0x0049, 0x072f: 0x005b,
- 0x0730: 0x0093, 0x0731: 0x1b26, 0x0732: 0x1d5a, 0x0733: 0x1b2f, 0x0734: 0x00ad, 0x0735: 0x1ba4,
- 0x0736: 0x1d8e, 0x0737: 0x1e9e, 0x0738: 0x1b32, 0x0739: 0x00b1, 0x073a: 0x1ba7, 0x073b: 0x1d92,
- 0x073c: 0x0099, 0x073d: 0x0087, 0x073e: 0x0089, 0x073f: 0x009b,
- // Block 0x1d, offset 0x740
- 0x0741: 0x3bf0, 0x0743: 0x8800, 0x0744: 0x3bf7, 0x0745: 0x8800,
- 0x0747: 0x3bfe, 0x0748: 0x8800, 0x0749: 0x3c05,
- 0x074d: 0x8800,
- 0x0760: 0x2f4f, 0x0761: 0x8800, 0x0762: 0x3c13,
- 0x0764: 0x8800, 0x0765: 0x8800,
- 0x076d: 0x3c0c, 0x076e: 0x2f4a, 0x076f: 0x2f54,
- 0x0770: 0x3c1a, 0x0771: 0x3c21, 0x0772: 0x8800, 0x0773: 0x8800, 0x0774: 0x3c28, 0x0775: 0x3c2f,
- 0x0776: 0x8800, 0x0777: 0x8800, 0x0778: 0x3c36, 0x0779: 0x3c3d, 0x077a: 0x8800, 0x077b: 0x8800,
- 0x077c: 0x8800, 0x077d: 0x8800,
- // Block 0x1e, offset 0x780
- 0x0780: 0x3c44, 0x0781: 0x3c4b, 0x0782: 0x8800, 0x0783: 0x8800, 0x0784: 0x3c60, 0x0785: 0x3c67,
- 0x0786: 0x8800, 0x0787: 0x8800, 0x0788: 0x3c6e, 0x0789: 0x3c75,
- 0x0791: 0x8800,
- 0x0792: 0x8800,
- 0x07a2: 0x8800,
- 0x07a8: 0x8800, 0x07a9: 0x8800,
- 0x07ab: 0x8800, 0x07ac: 0x3c8a, 0x07ad: 0x3c91, 0x07ae: 0x3c98, 0x07af: 0x3c9f,
- 0x07b2: 0x8800, 0x07b3: 0x8800, 0x07b4: 0x8800, 0x07b5: 0x8800,
- // Block 0x1f, offset 0x7c0
- 0x07e0: 0x0023, 0x07e1: 0x0025, 0x07e2: 0x0027, 0x07e3: 0x0029,
- 0x07e4: 0x002b, 0x07e5: 0x002d, 0x07e6: 0x002f, 0x07e7: 0x0031, 0x07e8: 0x0033, 0x07e9: 0x19c4,
- 0x07ea: 0x19c7, 0x07eb: 0x19ca, 0x07ec: 0x19cd, 0x07ed: 0x19d0, 0x07ee: 0x19d3, 0x07ef: 0x19d6,
- 0x07f0: 0x19d9, 0x07f1: 0x19dc, 0x07f2: 0x19df, 0x07f3: 0x19e8, 0x07f4: 0x1baa, 0x07f5: 0x1bae,
- 0x07f6: 0x1bb2, 0x07f7: 0x1bb6, 0x07f8: 0x1bba, 0x07f9: 0x1bbe, 0x07fa: 0x1bc2, 0x07fb: 0x1bc6,
- 0x07fc: 0x1bca, 0x07fd: 0x1dc2, 0x07fe: 0x1dc7, 0x07ff: 0x1dcc,
- // Block 0x20, offset 0x800
- 0x0800: 0x1dd1, 0x0801: 0x1dd6, 0x0802: 0x1ddb, 0x0803: 0x1de0, 0x0804: 0x1de5, 0x0805: 0x1dea,
- 0x0806: 0x1def, 0x0807: 0x1df4, 0x0808: 0x19c1, 0x0809: 0x19e5, 0x080a: 0x1a09, 0x080b: 0x1a2d,
- 0x080c: 0x1a51, 0x080d: 0x1a5a, 0x080e: 0x1a60, 0x080f: 0x1a66, 0x0810: 0x1a6c, 0x0811: 0x1ca2,
- 0x0812: 0x1ca6, 0x0813: 0x1caa, 0x0814: 0x1cae, 0x0815: 0x1cb2, 0x0816: 0x1cb6, 0x0817: 0x1cba,
- 0x0818: 0x1cbe, 0x0819: 0x1cc2, 0x081a: 0x1cc6, 0x081b: 0x1cca, 0x081c: 0x1c36, 0x081d: 0x1c3a,
- 0x081e: 0x1c3e, 0x081f: 0x1c42, 0x0820: 0x1c46, 0x0821: 0x1c4a, 0x0822: 0x1c4e, 0x0823: 0x1c52,
- 0x0824: 0x1c56, 0x0825: 0x1c5a, 0x0826: 0x1c5e, 0x0827: 0x1c62, 0x0828: 0x1c66, 0x0829: 0x1c6a,
- 0x082a: 0x1c6e, 0x082b: 0x1c72, 0x082c: 0x1c76, 0x082d: 0x1c7a, 0x082e: 0x1c7e, 0x082f: 0x1c82,
- 0x0830: 0x1c86, 0x0831: 0x1c8a, 0x0832: 0x1c8e, 0x0833: 0x1c92, 0x0834: 0x1c96, 0x0835: 0x1c9a,
- 0x0836: 0x0043, 0x0837: 0x0045, 0x0838: 0x0047, 0x0839: 0x0049, 0x083a: 0x004b, 0x083b: 0x004d,
- 0x083c: 0x004f, 0x083d: 0x0051, 0x083e: 0x0053, 0x083f: 0x0055,
- // Block 0x21, offset 0x840
- 0x0840: 0x0731, 0x0841: 0x0755, 0x0842: 0x0761, 0x0843: 0x0771, 0x0844: 0x0779, 0x0845: 0x0785,
- 0x0846: 0x078d, 0x0847: 0x0795, 0x0848: 0x07a1, 0x0849: 0x07f5, 0x084a: 0x080d, 0x084b: 0x081d,
- 0x084c: 0x082d, 0x084d: 0x083d, 0x084e: 0x084d, 0x084f: 0x086d, 0x0850: 0x0871, 0x0851: 0x0875,
- 0x0852: 0x08a9, 0x0853: 0x08d1, 0x0854: 0x08e1, 0x0855: 0x08e9, 0x0856: 0x08ed, 0x0857: 0x08f9,
- 0x0858: 0x0915, 0x0859: 0x0919, 0x085a: 0x0931, 0x085b: 0x0935, 0x085c: 0x093d, 0x085d: 0x094d,
- 0x085e: 0x09e9, 0x085f: 0x09fd, 0x0860: 0x0a3d, 0x0861: 0x0a51, 0x0862: 0x0a59, 0x0863: 0x0a5d,
- 0x0864: 0x0a6d, 0x0865: 0x0a89, 0x0866: 0x0ab5, 0x0867: 0x0ac1, 0x0868: 0x0ae1, 0x0869: 0x0aed,
- 0x086a: 0x0af1, 0x086b: 0x0af5, 0x086c: 0x0b0d, 0x086d: 0x0b11, 0x086e: 0x0b3d, 0x086f: 0x0b49,
- 0x0870: 0x0b51, 0x0871: 0x0b59, 0x0872: 0x0b69, 0x0873: 0x0b71, 0x0874: 0x0b79, 0x0875: 0x0ba5,
- 0x0876: 0x0ba9, 0x0877: 0x0bb1, 0x0878: 0x0bb5, 0x0879: 0x0bbd, 0x087a: 0x0bc5, 0x087b: 0x0bd5,
- 0x087c: 0x0bf1, 0x087d: 0x0c69, 0x087e: 0x0c7d, 0x087f: 0x0c81,
- // Block 0x22, offset 0x880
- 0x0880: 0x0d01, 0x0881: 0x0d05, 0x0882: 0x0d19, 0x0883: 0x0d1d, 0x0884: 0x0d25, 0x0885: 0x0d2d,
- 0x0886: 0x0d35, 0x0887: 0x0d41, 0x0888: 0x0d69, 0x0889: 0x0d79, 0x088a: 0x0d8d, 0x088b: 0x0dfd,
- 0x088c: 0x0e09, 0x088d: 0x0e19, 0x088e: 0x0e25, 0x088f: 0x0e31, 0x0890: 0x0e39, 0x0891: 0x0e3d,
- 0x0892: 0x0e41, 0x0893: 0x0e45, 0x0894: 0x0e49, 0x0895: 0x0f01, 0x0896: 0x0f49, 0x0897: 0x0f55,
- 0x0898: 0x0f59, 0x0899: 0x0f5d, 0x089a: 0x0f61, 0x089b: 0x0f69, 0x089c: 0x0f6d, 0x089d: 0x0f81,
- 0x089e: 0x0f9d, 0x089f: 0x0fa5, 0x08a0: 0x0fe5, 0x08a1: 0x0fe9, 0x08a2: 0x0ff1, 0x08a3: 0x0ff5,
- 0x08a4: 0x0ffd, 0x08a5: 0x1001, 0x08a6: 0x1025, 0x08a7: 0x1029, 0x08a8: 0x1045, 0x08a9: 0x1049,
- 0x08aa: 0x104d, 0x08ab: 0x1051, 0x08ac: 0x1065, 0x08ad: 0x1089, 0x08ae: 0x108d, 0x08af: 0x1091,
- 0x08b0: 0x10b5, 0x08b1: 0x10f5, 0x08b2: 0x10f9, 0x08b3: 0x1119, 0x08b4: 0x1129, 0x08b5: 0x1131,
- 0x08b6: 0x1151, 0x08b7: 0x1175, 0x08b8: 0x11b9, 0x08b9: 0x11c1, 0x08ba: 0x11d5, 0x08bb: 0x11e1,
- 0x08bc: 0x11e9, 0x08bd: 0x11f1, 0x08be: 0x11f5, 0x08bf: 0x11f9,
- // Block 0x23, offset 0x8c0
- 0x08c0: 0x1211, 0x08c1: 0x1215, 0x08c2: 0x1231, 0x08c3: 0x1239, 0x08c4: 0x1241, 0x08c5: 0x1245,
- 0x08c6: 0x1251, 0x08c7: 0x1259, 0x08c8: 0x125d, 0x08c9: 0x1261, 0x08ca: 0x1269, 0x08cb: 0x126d,
- 0x08cc: 0x130d, 0x08cd: 0x1321, 0x08ce: 0x1355, 0x08cf: 0x1359, 0x08d0: 0x1361, 0x08d1: 0x138d,
- 0x08d2: 0x1395, 0x08d3: 0x139d, 0x08d4: 0x13a5, 0x08d5: 0x13e1, 0x08d6: 0x13e5, 0x08d7: 0x13ed,
- 0x08d8: 0x13f1, 0x08d9: 0x13f5, 0x08da: 0x1421, 0x08db: 0x1425, 0x08dc: 0x142d, 0x08dd: 0x1441,
- 0x08de: 0x1445, 0x08df: 0x1461, 0x08e0: 0x1469, 0x08e1: 0x146d, 0x08e2: 0x1491, 0x08e3: 0x14b1,
- 0x08e4: 0x14c1, 0x08e5: 0x14c5, 0x08e6: 0x14cd, 0x08e7: 0x14f9, 0x08e8: 0x14fd, 0x08e9: 0x150d,
- 0x08ea: 0x1531, 0x08eb: 0x153d, 0x08ec: 0x154d, 0x08ed: 0x1565, 0x08ee: 0x156d, 0x08ef: 0x1571,
- 0x08f0: 0x1575, 0x08f1: 0x1579, 0x08f2: 0x1585, 0x08f3: 0x1589, 0x08f4: 0x1591, 0x08f5: 0x15ad,
- 0x08f6: 0x15b1, 0x08f7: 0x15b5, 0x08f8: 0x15cd, 0x08f9: 0x15d1, 0x08fa: 0x15d9, 0x08fb: 0x15ed,
- 0x08fc: 0x15f1, 0x08fd: 0x15f5, 0x08fe: 0x15fd, 0x08ff: 0x1601,
- // Block 0x24, offset 0x900
- 0x0906: 0x8800, 0x090b: 0x8800,
- 0x090c: 0x3ef2, 0x090d: 0x8800, 0x090e: 0x3efa, 0x090f: 0x8800, 0x0910: 0x3f02, 0x0911: 0x8800,
- 0x0912: 0x3f0a, 0x0913: 0x8800, 0x0914: 0x3f12, 0x0915: 0x8800, 0x0916: 0x3f1a, 0x0917: 0x8800,
- 0x0918: 0x3f22, 0x0919: 0x8800, 0x091a: 0x3f2a, 0x091b: 0x8800, 0x091c: 0x3f32, 0x091d: 0x8800,
- 0x091e: 0x3f3a, 0x091f: 0x8800, 0x0920: 0x3f42, 0x0921: 0x8800, 0x0922: 0x3f4a,
- 0x0924: 0x8800, 0x0925: 0x3f52, 0x0926: 0x8800, 0x0927: 0x3f5a, 0x0928: 0x8800, 0x0929: 0x3f62,
- 0x092f: 0x8800,
- 0x0930: 0x3f6a, 0x0931: 0x3f72, 0x0932: 0x8800, 0x0933: 0x3f7a, 0x0934: 0x3f82, 0x0935: 0x8800,
- 0x0936: 0x3f8a, 0x0937: 0x3f92, 0x0938: 0x8800, 0x0939: 0x3f9a, 0x093a: 0x3fa2, 0x093b: 0x8800,
- 0x093c: 0x3faa, 0x093d: 0x3fb2,
- // Block 0x25, offset 0x940
- 0x0954: 0x3eea,
- 0x0959: 0x8608, 0x095a: 0x8608, 0x095b: 0x42c2, 0x095c: 0x42c8, 0x095d: 0x8800,
- 0x095e: 0x3fba, 0x095f: 0x285f,
- 0x0966: 0x8800,
- 0x096b: 0x8800, 0x096c: 0x3fca, 0x096d: 0x8800, 0x096e: 0x3fd2, 0x096f: 0x8800,
- 0x0970: 0x3fda, 0x0971: 0x8800, 0x0972: 0x3fe2, 0x0973: 0x8800, 0x0974: 0x3fea, 0x0975: 0x8800,
- 0x0976: 0x3ff2, 0x0977: 0x8800, 0x0978: 0x3ffa, 0x0979: 0x8800, 0x097a: 0x4002, 0x097b: 0x8800,
- 0x097c: 0x400a, 0x097d: 0x8800, 0x097e: 0x4012, 0x097f: 0x8800,
- // Block 0x26, offset 0x980
- 0x0980: 0x401a, 0x0981: 0x8800, 0x0982: 0x4022, 0x0984: 0x8800, 0x0985: 0x402a,
- 0x0986: 0x8800, 0x0987: 0x4032, 0x0988: 0x8800, 0x0989: 0x403a,
- 0x098f: 0x8800, 0x0990: 0x4042, 0x0991: 0x404a,
- 0x0992: 0x8800, 0x0993: 0x4052, 0x0994: 0x405a, 0x0995: 0x8800, 0x0996: 0x4062, 0x0997: 0x406a,
- 0x0998: 0x8800, 0x0999: 0x4072, 0x099a: 0x407a, 0x099b: 0x8800, 0x099c: 0x4082, 0x099d: 0x408a,
- 0x09af: 0x8800,
- 0x09b0: 0x8800, 0x09b1: 0x8800, 0x09b2: 0x8800, 0x09b4: 0x3fc2,
- 0x09b7: 0x4092, 0x09b8: 0x409a, 0x09b9: 0x40a2, 0x09ba: 0x40aa,
- 0x09bd: 0x8800, 0x09be: 0x40b2, 0x09bf: 0x2874,
- // Block 0x27, offset 0x9c0
- 0x09c0: 0x03a9, 0x09c1: 0x03ad, 0x09c2: 0x047d, 0x09c3: 0x0481, 0x09c4: 0x03b1, 0x09c5: 0x03b5,
- 0x09c6: 0x03b9, 0x09c7: 0x0415, 0x09c8: 0x0419, 0x09c9: 0x041d, 0x09ca: 0x0421, 0x09cb: 0x0425,
- 0x09cc: 0x0429, 0x09cd: 0x042d, 0x09ce: 0x0431,
- 0x09d2: 0x0731, 0x09d3: 0x078d, 0x09d4: 0x073d, 0x09d5: 0x09ed, 0x09d6: 0x0741, 0x09d7: 0x0759,
- 0x09d8: 0x0745, 0x09d9: 0x1005, 0x09da: 0x0779, 0x09db: 0x074d, 0x09dc: 0x0735, 0x09dd: 0x0a71,
- 0x09de: 0x0a01, 0x09df: 0x07a1,
- // Block 0x28, offset 0xa00
- 0x0a00: 0x2196, 0x0a01: 0x219c, 0x0a02: 0x21a2, 0x0a03: 0x21a8, 0x0a04: 0x21ae, 0x0a05: 0x21b4,
- 0x0a06: 0x21ba, 0x0a07: 0x21c0, 0x0a08: 0x21c6, 0x0a09: 0x21cc, 0x0a0a: 0x21d2, 0x0a0b: 0x21d8,
- 0x0a0c: 0x21de, 0x0a0d: 0x21e4, 0x0a0e: 0x28d1, 0x0a0f: 0x28da, 0x0a10: 0x28e3, 0x0a11: 0x28ec,
- 0x0a12: 0x28f5, 0x0a13: 0x28fe, 0x0a14: 0x2907, 0x0a15: 0x2910, 0x0a16: 0x2919, 0x0a17: 0x292b,
- 0x0a18: 0x2934, 0x0a19: 0x293d, 0x0a1a: 0x2946, 0x0a1b: 0x294f, 0x0a1c: 0x2922, 0x0a1d: 0x2d74,
- 0x0a1e: 0x2ca5, 0x0a20: 0x21ea, 0x0a21: 0x2202, 0x0a22: 0x21f6, 0x0a23: 0x224a,
- 0x0a24: 0x2208, 0x0a25: 0x2226, 0x0a26: 0x21f0, 0x0a27: 0x2220, 0x0a28: 0x21fc, 0x0a29: 0x2232,
- 0x0a2a: 0x2262, 0x0a2b: 0x2280, 0x0a2c: 0x227a, 0x0a2d: 0x226e, 0x0a2e: 0x22bc, 0x0a2f: 0x2250,
- 0x0a30: 0x225c, 0x0a31: 0x2274, 0x0a32: 0x2268, 0x0a33: 0x2292, 0x0a34: 0x223e, 0x0a35: 0x2286,
- 0x0a36: 0x22b0, 0x0a37: 0x2298, 0x0a38: 0x222c, 0x0a39: 0x220e, 0x0a3a: 0x2244, 0x0a3b: 0x2256,
- 0x0a3c: 0x228c, 0x0a3d: 0x2214, 0x0a3e: 0x22b6, 0x0a3f: 0x2238,
- // Block 0x29, offset 0xa40
- 0x0a40: 0x229e, 0x0a41: 0x221a, 0x0a42: 0x22a4, 0x0a43: 0x22aa, 0x0a44: 0x09a1, 0x0a45: 0x0b75,
- 0x0a46: 0x0d19, 0x0a47: 0x1139,
- 0x0a50: 0x1d06, 0x0a51: 0x19eb,
- 0x0a52: 0x19ee, 0x0a53: 0x19f1, 0x0a54: 0x19f4, 0x0a55: 0x19f7, 0x0a56: 0x19fa, 0x0a57: 0x19fd,
- 0x0a58: 0x1a00, 0x0a59: 0x1a03, 0x0a5a: 0x1a0c, 0x0a5b: 0x1a0f, 0x0a5c: 0x1a12, 0x0a5d: 0x1a15,
- 0x0a5e: 0x1a18, 0x0a5f: 0x1a1b, 0x0a60: 0x030d, 0x0a61: 0x0315, 0x0a62: 0x0319, 0x0a63: 0x0321,
- 0x0a64: 0x0325, 0x0a65: 0x0329, 0x0a66: 0x0331, 0x0a67: 0x0339, 0x0a68: 0x033d, 0x0a69: 0x0345,
- 0x0a6a: 0x0349, 0x0a6b: 0x034d, 0x0a6c: 0x0351, 0x0a6d: 0x0355, 0x0a6e: 0x27d3, 0x0a6f: 0x27da,
- 0x0a70: 0x27e1, 0x0a71: 0x27e8, 0x0a72: 0x27ef, 0x0a73: 0x27f6, 0x0a74: 0x27fd, 0x0a75: 0x2804,
- 0x0a76: 0x2812, 0x0a77: 0x2819, 0x0a78: 0x2820, 0x0a79: 0x2827, 0x0a7a: 0x282e, 0x0a7b: 0x2835,
- 0x0a7c: 0x2cc4, 0x0a7d: 0x2b39, 0x0a7e: 0x280b,
- // Block 0x2a, offset 0xa80
- 0x0a80: 0x0731, 0x0a81: 0x078d, 0x0a82: 0x073d, 0x0a83: 0x09ed, 0x0a84: 0x0791, 0x0a85: 0x0821,
- 0x0a86: 0x0739, 0x0a87: 0x081d, 0x0a88: 0x077d, 0x0a89: 0x08f9, 0x0a8a: 0x0d79, 0x0a8b: 0x0f01,
- 0x0a8c: 0x0e49, 0x0a8d: 0x0d8d, 0x0a8e: 0x14cd, 0x0a8f: 0x09fd, 0x0a90: 0x0d41, 0x0a91: 0x0dbd,
- 0x0a92: 0x0d7d, 0x0a93: 0x10bd, 0x0a94: 0x096d, 0x0a95: 0x0f75, 0x0a96: 0x13f9, 0x0a97: 0x10d1,
- 0x0a98: 0x08b5, 0x0a99: 0x1101, 0x0a9a: 0x100d, 0x0a9b: 0x0a89, 0x0a9c: 0x1481, 0x0a9d: 0x07f1,
- 0x0a9e: 0x091d, 0x0a9f: 0x0e69, 0x0aa0: 0x1595, 0x0aa1: 0x07b5, 0x0aa2: 0x0845, 0x0aa3: 0x0e0d,
- 0x0aa4: 0x0741, 0x0aa5: 0x0759, 0x0aa6: 0x0745, 0x0aa7: 0x0b4d, 0x0aa8: 0x0961, 0x0aa9: 0x08f1,
- 0x0aaa: 0x0ac9, 0x0aab: 0x0abd, 0x0aac: 0x105d, 0x0aad: 0x07b1, 0x0aae: 0x140d, 0x0aaf: 0x090d,
- 0x0ab0: 0x0a65, 0x0ab1: 0x1a1e, 0x0ab2: 0x1a21, 0x0ab3: 0x1a24, 0x0ab4: 0x1a27, 0x0ab5: 0x1a30,
- 0x0ab6: 0x1a33, 0x0ab7: 0x1a36, 0x0ab8: 0x1a39, 0x0ab9: 0x1a3c, 0x0aba: 0x1a3f, 0x0abb: 0x1a42,
- 0x0abc: 0x1a45, 0x0abd: 0x1a48, 0x0abe: 0x1a4b, 0x0abf: 0x1a54,
- // Block 0x2b, offset 0xac0
- 0x0ac0: 0x1e08, 0x0ac1: 0x1e17, 0x0ac2: 0x1e26, 0x0ac3: 0x1e35, 0x0ac4: 0x1e44, 0x0ac5: 0x1e53,
- 0x0ac6: 0x1e62, 0x0ac7: 0x1e71, 0x0ac8: 0x1e80, 0x0ac9: 0x22ce, 0x0aca: 0x22e0, 0x0acb: 0x22f2,
- 0x0acc: 0x1a96, 0x0acd: 0x1d46, 0x0ace: 0x1b14, 0x0acf: 0x1cea, 0x0ad0: 0x053d, 0x0ad1: 0x0545,
- 0x0ad2: 0x054d, 0x0ad3: 0x0555, 0x0ad4: 0x055d, 0x0ad5: 0x0561, 0x0ad6: 0x0565, 0x0ad7: 0x0569,
- 0x0ad8: 0x056d, 0x0ad9: 0x0571, 0x0ada: 0x0575, 0x0adb: 0x0579, 0x0adc: 0x057d, 0x0add: 0x0581,
- 0x0ade: 0x0585, 0x0adf: 0x0589, 0x0ae0: 0x058d, 0x0ae1: 0x0595, 0x0ae2: 0x0599, 0x0ae3: 0x059d,
- 0x0ae4: 0x05a1, 0x0ae5: 0x05a5, 0x0ae6: 0x05a9, 0x0ae7: 0x05ad, 0x0ae8: 0x05b1, 0x0ae9: 0x05b5,
- 0x0aea: 0x05b9, 0x0aeb: 0x05bd, 0x0aec: 0x05c1, 0x0aed: 0x05c5, 0x0aee: 0x05c9, 0x0aef: 0x05cd,
- 0x0af0: 0x05d1, 0x0af1: 0x05d5, 0x0af2: 0x05d9, 0x0af3: 0x05e1, 0x0af4: 0x05e9, 0x0af5: 0x05f1,
- 0x0af6: 0x05f5, 0x0af7: 0x05f9, 0x0af8: 0x05fd, 0x0af9: 0x0601, 0x0afa: 0x0605, 0x0afb: 0x0609,
- 0x0afc: 0x060d, 0x0afd: 0x0611, 0x0afe: 0x0615,
- // Block 0x2c, offset 0xb00
- 0x0b00: 0x2cd4, 0x0b01: 0x2b60, 0x0b02: 0x2ce4, 0x0b03: 0x2a2b, 0x0b04: 0x2ede, 0x0b05: 0x2a35,
- 0x0b06: 0x2a3f, 0x0b07: 0x2f22, 0x0b08: 0x2b6d, 0x0b09: 0x2a49, 0x0b0a: 0x2a53, 0x0b0b: 0x2a5d,
- 0x0b0c: 0x2b94, 0x0b0d: 0x2ba1, 0x0b0e: 0x2b7a, 0x0b0f: 0x2b87, 0x0b10: 0x2eb4, 0x0b11: 0x2bae,
- 0x0b12: 0x2bbb, 0x0b13: 0x2d86, 0x0b14: 0x2866, 0x0b15: 0x2d99, 0x0b16: 0x2dac, 0x0b17: 0x2cf4,
- 0x0b18: 0x2bc8, 0x0b19: 0x2dbf, 0x0b1a: 0x2dd2, 0x0b1b: 0x2bd5, 0x0b1c: 0x2a67, 0x0b1d: 0x2a71,
- 0x0b1e: 0x2ec2, 0x0b1f: 0x2be2, 0x0b20: 0x2d04, 0x0b21: 0x2eef, 0x0b22: 0x2a7b, 0x0b23: 0x2a85,
- 0x0b24: 0x2bef, 0x0b25: 0x2a8f, 0x0b26: 0x2a99, 0x0b27: 0x287b, 0x0b28: 0x2882, 0x0b29: 0x2aa3,
- 0x0b2a: 0x2aad, 0x0b2b: 0x2de5, 0x0b2c: 0x2bfc, 0x0b2d: 0x2d14, 0x0b2e: 0x2df8, 0x0b2f: 0x2c09,
- 0x0b30: 0x2ac1, 0x0b31: 0x2ab7, 0x0b32: 0x2f36, 0x0b33: 0x2c16, 0x0b34: 0x2e0b, 0x0b35: 0x2acb,
- 0x0b36: 0x2d24, 0x0b37: 0x2ad5, 0x0b38: 0x2c30, 0x0b39: 0x2adf, 0x0b3a: 0x2c3d, 0x0b3b: 0x2f00,
- 0x0b3c: 0x2c23, 0x0b3d: 0x2d34, 0x0b3e: 0x2c4a, 0x0b3f: 0x2889,
- // Block 0x2d, offset 0xb40
- 0x0b40: 0x2f11, 0x0b41: 0x2ae9, 0x0b42: 0x2af3, 0x0b43: 0x2c57, 0x0b44: 0x2afd, 0x0b45: 0x2b07,
- 0x0b46: 0x2b11, 0x0b47: 0x2d44, 0x0b48: 0x2c64, 0x0b49: 0x2890, 0x0b4a: 0x2e1e, 0x0b4b: 0x2ea9,
- 0x0b4c: 0x2d54, 0x0b4d: 0x2c71, 0x0b4e: 0x2ed0, 0x0b4f: 0x2b1b, 0x0b50: 0x2b25, 0x0b51: 0x2c7e,
- 0x0b52: 0x2897, 0x0b53: 0x2c8b, 0x0b54: 0x2d64, 0x0b55: 0x289e, 0x0b56: 0x2e31, 0x0b57: 0x2b2f,
- 0x0b58: 0x1df9, 0x0b59: 0x1e0d, 0x0b5a: 0x1e1c, 0x0b5b: 0x1e2b, 0x0b5c: 0x1e3a, 0x0b5d: 0x1e49,
- 0x0b5e: 0x1e58, 0x0b5f: 0x1e67, 0x0b60: 0x1e76, 0x0b61: 0x1e85, 0x0b62: 0x22d4, 0x0b63: 0x22e6,
- 0x0b64: 0x22f8, 0x0b65: 0x2304, 0x0b66: 0x2310, 0x0b67: 0x231c, 0x0b68: 0x2328, 0x0b69: 0x2334,
- 0x0b6a: 0x2340, 0x0b6b: 0x234c, 0x0b6c: 0x2388, 0x0b6d: 0x2394, 0x0b6e: 0x23a0, 0x0b6f: 0x23ac,
- 0x0b70: 0x23b8, 0x0b71: 0x1d56, 0x0b72: 0x1b08, 0x0b73: 0x1a78, 0x0b74: 0x1d26, 0x0b75: 0x1b89,
- 0x0b76: 0x1b98, 0x0b77: 0x1b0e, 0x0b78: 0x1d3e, 0x0b79: 0x1d42, 0x0b7a: 0x1aa2, 0x0b7b: 0x28ac,
- 0x0b7c: 0x28ba, 0x0b7d: 0x28a5, 0x0b7e: 0x28b3, 0x0b7f: 0x2c98,
- // Block 0x2e, offset 0xb80
- 0x0b80: 0x1b8c, 0x0b81: 0x1b74, 0x0b82: 0x1da2, 0x0b83: 0x1b5c, 0x0b84: 0x1b35, 0x0b85: 0x1aab,
- 0x0b86: 0x1aba, 0x0b87: 0x1a8a, 0x0b88: 0x1d32, 0x0b89: 0x1e94, 0x0b8a: 0x1b8f, 0x0b8b: 0x1b77,
- 0x0b8c: 0x1da6, 0x0b8d: 0x1db2, 0x0b8e: 0x1b68, 0x0b8f: 0x1b3e, 0x0b90: 0x1a99, 0x0b91: 0x1d5e,
- 0x0b92: 0x1cf2, 0x0b93: 0x1cde, 0x0b94: 0x1d0e, 0x0b95: 0x1db6, 0x0b96: 0x1b6b, 0x0b97: 0x1b0b,
- 0x0b98: 0x1b41, 0x0b99: 0x1b20, 0x0b9a: 0x1b83, 0x0b9b: 0x1dba, 0x0b9c: 0x1b6e, 0x0b9d: 0x1b02,
- 0x0b9e: 0x1b44, 0x0b9f: 0x1d7e, 0x0ba0: 0x1d36, 0x0ba1: 0x1b56, 0x0ba2: 0x1d66, 0x0ba3: 0x1d82,
- 0x0ba4: 0x1d3a, 0x0ba5: 0x1b59, 0x0ba6: 0x1d6a, 0x0ba7: 0x242a, 0x0ba8: 0x243e, 0x0ba9: 0x1ad8,
- 0x0baa: 0x1d62, 0x0bab: 0x1cf6, 0x0bac: 0x1ce2, 0x0bad: 0x1d8a, 0x0bae: 0x28c1, 0x0baf: 0x2958,
- 0x0bb0: 0x1b9b, 0x0bb1: 0x1b86, 0x0bb2: 0x1dbe, 0x0bb3: 0x1b71, 0x0bb4: 0x1b92, 0x0bb5: 0x1b7a,
- 0x0bb6: 0x1daa, 0x0bb7: 0x1b5f, 0x0bb8: 0x1b38, 0x0bb9: 0x1ac3, 0x0bba: 0x1b95, 0x0bbb: 0x1b7d,
- 0x0bbc: 0x1dae, 0x0bbd: 0x1b62, 0x0bbe: 0x1b3b, 0x0bbf: 0x1ac6,
- // Block 0x2f, offset 0xbc0
- 0x0bc0: 0x1d6e, 0x0bc1: 0x1cfa, 0x0bc2: 0x1e8f, 0x0bc3: 0x1a7b, 0x0bc4: 0x1afc, 0x0bc5: 0x1aff,
- 0x0bc6: 0x2437, 0x0bc7: 0x1cd6, 0x0bc8: 0x1b05, 0x0bc9: 0x1a8d, 0x0bca: 0x1b23, 0x0bcb: 0x1a90,
- 0x0bcc: 0x1b2c, 0x0bcd: 0x1aae, 0x0bce: 0x1ab1, 0x0bcf: 0x1b47, 0x0bd0: 0x1b4d, 0x0bd1: 0x1b50,
- 0x0bd2: 0x1d72, 0x0bd3: 0x1b53, 0x0bd4: 0x1b65, 0x0bd5: 0x1d7a, 0x0bd6: 0x1d86, 0x0bd7: 0x1ad2,
- 0x0bd8: 0x1e99, 0x0bd9: 0x1cfe, 0x0bda: 0x1ad5, 0x0bdb: 0x1b9e, 0x0bdc: 0x1ae7, 0x0bdd: 0x1af6,
- 0x0bde: 0x2424, 0x0bdf: 0x241e, 0x0be0: 0x1e03, 0x0be1: 0x1e12, 0x0be2: 0x1e21, 0x0be3: 0x1e30,
- 0x0be4: 0x1e3f, 0x0be5: 0x1e4e, 0x0be6: 0x1e5d, 0x0be7: 0x1e6c, 0x0be8: 0x1e7b, 0x0be9: 0x22c8,
- 0x0bea: 0x22da, 0x0beb: 0x22ec, 0x0bec: 0x22fe, 0x0bed: 0x230a, 0x0bee: 0x2316, 0x0bef: 0x2322,
- 0x0bf0: 0x232e, 0x0bf1: 0x233a, 0x0bf2: 0x2346, 0x0bf3: 0x2382, 0x0bf4: 0x238e, 0x0bf5: 0x239a,
- 0x0bf6: 0x23a6, 0x0bf7: 0x23b2, 0x0bf8: 0x23be, 0x0bf9: 0x23c4, 0x0bfa: 0x23ca, 0x0bfb: 0x23d0,
- 0x0bfc: 0x23d6, 0x0bfd: 0x23e8, 0x0bfe: 0x23ee, 0x0bff: 0x1d52,
- // Block 0x30, offset 0xc00
- 0x0c00: 0x13e9, 0x0c01: 0x0d6d, 0x0c02: 0x1445, 0x0c03: 0x1411, 0x0c04: 0x0ec9, 0x0c05: 0x075d,
- 0x0c06: 0x0951, 0x0c07: 0x1699, 0x0c08: 0x1699, 0x0c09: 0x0a7d, 0x0c0a: 0x14cd, 0x0c0b: 0x09b5,
- 0x0c0c: 0x0a79, 0x0c0d: 0x0c61, 0x0c0e: 0x1041, 0x0c0f: 0x11d1, 0x0c10: 0x1309, 0x0c11: 0x1345,
- 0x0c12: 0x1379, 0x0c13: 0x148d, 0x0c14: 0x0de5, 0x0c15: 0x0e71, 0x0c16: 0x0f1d, 0x0c17: 0x0fb5,
- 0x0c18: 0x12d1, 0x0c19: 0x14b5, 0x0c1a: 0x15e1, 0x0c1b: 0x0781, 0x0c1c: 0x0925, 0x0c1d: 0x0df9,
- 0x0c1e: 0x0f41, 0x0c1f: 0x1305, 0x0c20: 0x1631, 0x0c21: 0x0b25, 0x0c22: 0x0ee9, 0x0c23: 0x12f5,
- 0x0c24: 0x1389, 0x0c25: 0x0c95, 0x0c26: 0x122d, 0x0c27: 0x1351, 0x0c28: 0x0b91, 0x0c29: 0x0d81,
- 0x0c2a: 0x0e89, 0x0c2b: 0x0f8d, 0x0c2c: 0x1499, 0x0c2d: 0x07c1, 0x0c2e: 0x0859, 0x0c2f: 0x08c5,
- 0x0c30: 0x0cfd, 0x0c31: 0x0df1, 0x0c32: 0x0f3d, 0x0c33: 0x1061, 0x0c34: 0x11e9, 0x0c35: 0x12fd,
- 0x0c36: 0x1315, 0x0c37: 0x1439, 0x0c38: 0x155d, 0x0c39: 0x1611, 0x0c3a: 0x162d, 0x0c3b: 0x109d,
- 0x0c3c: 0x10dd, 0x0c3d: 0x1195, 0x0c3e: 0x12b5, 0x0c3f: 0x14e9,
- // Block 0x31, offset 0xc40
- 0x0c40: 0x1639, 0x0c41: 0x13bd, 0x0c42: 0x0a39, 0x0c43: 0x0bad, 0x0c44: 0x114d, 0x0c45: 0x120d,
- 0x0c46: 0x0f71, 0x0c47: 0x10a5, 0x0c48: 0x1409, 0x0c49: 0x1555, 0x0c4a: 0x0a35, 0x0c4b: 0x0b01,
- 0x0c4c: 0x0de9, 0x0c4d: 0x0e9d, 0x0c4e: 0x0ed1, 0x0c4f: 0x1185, 0x0c50: 0x11ad, 0x0c51: 0x1515,
- 0x0c52: 0x08c1, 0x0c53: 0x1219, 0x0c54: 0x0865, 0x0c55: 0x0861, 0x0c56: 0x1109, 0x0c57: 0x1199,
- 0x0c58: 0x12cd, 0x0c59: 0x151d, 0x0c5a: 0x13d9, 0x0c5b: 0x0c99, 0x0c5c: 0x0de5, 0x0c5d: 0x13c9,
- 0x0c5e: 0x0769, 0x0c5f: 0x0ad5, 0x0c60: 0x0c05, 0x0c61: 0x0fa1, 0x0c62: 0x1021, 0x0c63: 0x08e5,
- 0x0c64: 0x10ad, 0x0c65: 0x07d1, 0x0c66: 0x0be9, 0x0c67: 0x0749, 0x0c68: 0x0e5d, 0x0c69: 0x0d15,
- 0x0c6a: 0x1181, 0x0c6b: 0x0939, 0x0c6c: 0x0a25, 0x0c6d: 0x106d, 0x0c6e: 0x12d5, 0x0c6f: 0x13ad,
- 0x0c70: 0x0e29, 0x0c71: 0x1469, 0x0c72: 0x0e55, 0x0c73: 0x0ca9, 0x0c74: 0x128d, 0x0c75: 0x0cc9,
- 0x0c76: 0x101d, 0x0c77: 0x079d, 0x0c78: 0x0819, 0x0c79: 0x085d, 0x0c7a: 0x0dc5, 0x0c7b: 0x116d,
- 0x0c7c: 0x1265, 0x0c7d: 0x13b9, 0x0c7e: 0x14c9, 0x0c7f: 0x08cd,
- // Block 0x32, offset 0xc80
- 0x0c80: 0x0981, 0x0c81: 0x0a89, 0x0c82: 0x0ba1, 0x0c83: 0x0d31, 0x0c84: 0x0eed, 0x0c85: 0x10b1,
- 0x0c86: 0x1505, 0x0c87: 0x15e9, 0x0c88: 0x163d, 0x0c89: 0x1655, 0x0c8a: 0x08a9, 0x0c8b: 0x0d65,
- 0x0c8c: 0x0e15, 0x0c8d: 0x145d, 0x0c8e: 0x0b6d, 0x0c8f: 0x0c49, 0x0c90: 0x0c65, 0x0c91: 0x0cf5,
- 0x0c92: 0x0edd, 0x0c93: 0x0f29, 0x0c94: 0x0fd9, 0x0c95: 0x10fd, 0x0c96: 0x11a1, 0x0c97: 0x1205,
- 0x0c98: 0x144d, 0x0c99: 0x12dd, 0x0c9a: 0x1475, 0x0c9b: 0x14ed, 0x0c9c: 0x0881, 0x0c9d: 0x08ad,
- 0x0c9e: 0x0995, 0x0c9f: 0x0f19, 0x0ca0: 0x1365, 0x0ca1: 0x13ad, 0x0ca2: 0x0b8d, 0x0ca3: 0x0bfd,
- 0x0ca4: 0x0cc1, 0x0ca5: 0x0e21, 0x0ca6: 0x1149, 0x0ca7: 0x0f95, 0x0ca8: 0x07ad, 0x0ca9: 0x09f1,
- 0x0caa: 0x0ad5, 0x0cab: 0x0b39, 0x0cac: 0x0c09, 0x0cad: 0x0fb1, 0x0cae: 0x0fcd, 0x0caf: 0x11dd,
- 0x0cb0: 0x11fd, 0x0cb1: 0x14d1, 0x0cb2: 0x1551, 0x0cb3: 0x1561, 0x0cb4: 0x159d, 0x0cb5: 0x07c5,
- 0x0cb6: 0x10f1, 0x0cb7: 0x14bd, 0x0cb8: 0x1539, 0x0cb9: 0x0c21, 0x0cba: 0x0789, 0x0cbb: 0x07e9,
- 0x0cbc: 0x0ad9, 0x0cbd: 0x0af9, 0x0cbe: 0x0d21, 0x0cbf: 0x0de5,
- // Block 0x33, offset 0xcc0
- 0x0cc0: 0x0f35, 0x0cc1: 0x103d, 0x0cc2: 0x12e9, 0x0cc3: 0x1489, 0x0cc4: 0x1691, 0x0cc5: 0x0d55,
- 0x0cc6: 0x1511, 0x0cc7: 0x08a5, 0x0cc8: 0x0da1, 0x0cc9: 0x0dad, 0x0cca: 0x0e81, 0x0ccb: 0x0eb9,
- 0x0ccc: 0x0fbd, 0x0ccd: 0x1019, 0x0cce: 0x1099, 0x0ccf: 0x117d, 0x0cd0: 0x15a9, 0x0cd1: 0x0821,
- 0x0cd2: 0x0c75, 0x0cd3: 0x1521, 0x0cd4: 0x07d9, 0x0cd5: 0x0b1d, 0x0cd6: 0x0ea1, 0x0cd7: 0x1451,
- 0x0cd8: 0x0bd9, 0x0cd9: 0x0c29, 0x0cda: 0x0db5, 0x0cdb: 0x0fa1, 0x0cdc: 0x1529, 0x0cdd: 0x0889,
- 0x0cde: 0x0971, 0x0cdf: 0x0b09, 0x0ce0: 0x0d45, 0x0ce1: 0x0d91, 0x0ce2: 0x0dd1, 0x0ce3: 0x0e65,
- 0x0ce4: 0x0fb9, 0x0ce5: 0x102d, 0x0ce6: 0x11c9, 0x0ce7: 0x1369, 0x0ce8: 0x1375, 0x0ce9: 0x14c5,
- 0x0cea: 0x1545, 0x0ceb: 0x08f5, 0x0cec: 0x0ebd, 0x0ced: 0x0975, 0x0cee: 0x0f39, 0x0cef: 0x0fdd,
- 0x0cf0: 0x12f9, 0x0cf1: 0x152d, 0x0cf2: 0x1619, 0x0cf3: 0x1641, 0x0cf4: 0x0da9, 0x0cf5: 0x0e99,
- 0x0cf6: 0x1235, 0x0cf7: 0x1129, 0x0cf8: 0x1135, 0x0cf9: 0x1159, 0x0cfa: 0x0f89, 0x0cfb: 0x0f11,
- 0x0cfc: 0x13d5, 0x0cfd: 0x07a5, 0x0cfe: 0x129d, 0x0cff: 0x088d,
- // Block 0x34, offset 0xd00
- 0x0d00: 0x087d, 0x0d01: 0x0b7d, 0x0d02: 0x0c9d, 0x0d03: 0x1165, 0x0d04: 0x0ac5, 0x0d05: 0x0e75,
- 0x0d06: 0x0d61, 0x0d07: 0x1459, 0x0d08: 0x1359, 0x0d09: 0x1519, 0x0d0a: 0x1395, 0x0d0b: 0x0b99,
- 0x0d0c: 0x07f9, 0x0d0d: 0x09cd, 0x0d10: 0x0a21,
- 0x0d12: 0x0d51, 0x0d15: 0x0869, 0x0d16: 0x0f91, 0x0d17: 0x1055,
- 0x0d18: 0x10b9, 0x0d19: 0x10d5, 0x0d1a: 0x10d9, 0x0d1b: 0x10ed, 0x0d1c: 0x1569, 0x0d1d: 0x115d,
- 0x0d1e: 0x11e1, 0x0d20: 0x1301, 0x0d22: 0x13c5,
- 0x0d25: 0x1479, 0x0d26: 0x14a5,
- 0x0d2a: 0x15bd, 0x0d2b: 0x15c1, 0x0d2c: 0x15c5, 0x0d2d: 0x1629, 0x0d2e: 0x149d, 0x0d2f: 0x1535,
- 0x0d30: 0x07c9, 0x0d31: 0x07ed, 0x0d32: 0x0801, 0x0d33: 0x08bd, 0x0d34: 0x08c9, 0x0d35: 0x0909,
- 0x0d36: 0x09bd, 0x0d37: 0x09d9, 0x0d38: 0x09e1, 0x0d39: 0x0a1d, 0x0d3a: 0x0a29, 0x0d3b: 0x0b05,
- 0x0d3c: 0x0b0d, 0x0d3d: 0x0c15, 0x0d3e: 0x0c3d, 0x0d3f: 0x0c45,
- // Block 0x35, offset 0xd40
- 0x0d40: 0x0c5d, 0x0d41: 0x0d09, 0x0d42: 0x0d39, 0x0d43: 0x0d59, 0x0d44: 0x0dc9, 0x0d45: 0x0e8d,
- 0x0d46: 0x0ea9, 0x0d47: 0x0ed9, 0x0d48: 0x0f2d, 0x0d49: 0x0f4d, 0x0d4a: 0x0fc1, 0x0d4b: 0x10a1,
- 0x0d4c: 0x10bd, 0x0d4d: 0x10c5, 0x0d4e: 0x10c1, 0x0d4f: 0x10c9, 0x0d50: 0x10cd, 0x0d51: 0x10d1,
- 0x0d52: 0x10e5, 0x0d53: 0x10e9, 0x0d54: 0x110d, 0x0d55: 0x1121, 0x0d56: 0x113d, 0x0d57: 0x11a1,
- 0x0d58: 0x11a9, 0x0d59: 0x11b1, 0x0d5a: 0x11c5, 0x0d5b: 0x11ed, 0x0d5c: 0x123d, 0x0d5d: 0x1271,
- 0x0d5e: 0x1271, 0x0d5f: 0x12d9, 0x0d60: 0x1381, 0x0d61: 0x1399, 0x0d62: 0x13cd, 0x0d63: 0x13d1,
- 0x0d64: 0x1415, 0x0d65: 0x1419, 0x0d66: 0x1471, 0x0d67: 0x1479, 0x0d68: 0x1549, 0x0d69: 0x158d,
- 0x0d6a: 0x15a5, 0x0d6b: 0x0c0d, 0x0d6c: 0x1780, 0x0d6d: 0x1255,
- 0x0d70: 0x0751, 0x0d71: 0x0855, 0x0d72: 0x0815, 0x0d73: 0x07bd, 0x0d74: 0x07fd, 0x0d75: 0x0829,
- 0x0d76: 0x08b9, 0x0d77: 0x08d5, 0x0d78: 0x09bd, 0x0d79: 0x09a9, 0x0d7a: 0x09b9, 0x0d7b: 0x09d5,
- 0x0d7c: 0x0a21, 0x0d7d: 0x0a31, 0x0d7e: 0x0a75, 0x0d7f: 0x0a81,
- // Block 0x36, offset 0xd80
- 0x0d80: 0x0a9d, 0x0d81: 0x0aad, 0x0d82: 0x0b95, 0x0d83: 0x0b9d, 0x0d84: 0x0bcd, 0x0d85: 0x0bed,
- 0x0d86: 0x0c1d, 0x0d87: 0x0c35, 0x0d88: 0x0c25, 0x0d89: 0x0c45, 0x0d8a: 0x0c39, 0x0d8b: 0x0c5d,
- 0x0d8c: 0x0c79, 0x0d8d: 0x0cd1, 0x0d8e: 0x0cdd, 0x0d8f: 0x0ce5, 0x0d90: 0x0d0d, 0x0d91: 0x0d51,
- 0x0d92: 0x0d81, 0x0d93: 0x0d85, 0x0d94: 0x0d99, 0x0d95: 0x0e19, 0x0d96: 0x0e29, 0x0d97: 0x0e81,
- 0x0d98: 0x0ecd, 0x0d99: 0x0ec5, 0x0d9a: 0x0ed9, 0x0d9b: 0x0ef5, 0x0d9c: 0x0f2d, 0x0d9d: 0x1085,
- 0x0d9e: 0x0f51, 0x0d9f: 0x0f85, 0x0da0: 0x0f91, 0x0da1: 0x0fd1, 0x0da2: 0x0fed, 0x0da3: 0x1011,
- 0x0da4: 0x1035, 0x0da5: 0x1039, 0x0da6: 0x1055, 0x0da7: 0x1059, 0x0da8: 0x1069, 0x0da9: 0x107d,
- 0x0daa: 0x1079, 0x0dab: 0x10a9, 0x0dac: 0x1125, 0x0dad: 0x113d, 0x0dae: 0x1155, 0x0daf: 0x118d,
- 0x0db0: 0x11a1, 0x0db1: 0x11bd, 0x0db2: 0x11ed, 0x0db3: 0x12a1, 0x0db4: 0x12c9, 0x0db5: 0x133d,
- 0x0db6: 0x1385, 0x0db7: 0x1391, 0x0db8: 0x1399, 0x0db9: 0x13b1, 0x0dba: 0x13c5, 0x0dbb: 0x13b5,
- 0x0dbc: 0x13cd, 0x0dbd: 0x13c9, 0x0dbe: 0x13c1, 0x0dbf: 0x13d1,
- // Block 0x37, offset 0xdc0
- 0x0dc0: 0x13dd, 0x0dc1: 0x1419, 0x0dc2: 0x1455, 0x0dc3: 0x1485, 0x0dc4: 0x14b9, 0x0dc5: 0x14d9,
- 0x0dc6: 0x1525, 0x0dc7: 0x1549, 0x0dc8: 0x1569, 0x0dc9: 0x157d, 0x0dca: 0x158d, 0x0dcb: 0x1599,
- 0x0dcc: 0x15a5, 0x0dcd: 0x15f9, 0x0dce: 0x1699, 0x0dcf: 0x1717, 0x0dd0: 0x1712, 0x0dd1: 0x1744,
- 0x0dd2: 0x0679, 0x0dd3: 0x06a1, 0x0dd4: 0x06a5, 0x0dd5: 0x17c6, 0x0dd6: 0x17f3, 0x0dd7: 0x186b,
- 0x0dd8: 0x1685, 0x0dd9: 0x1695,
- // Block 0x38, offset 0xe00
- 0x0e00: 0x1b17, 0x0e01: 0x1b1a, 0x0e02: 0x1b1d, 0x0e03: 0x1d4a, 0x0e04: 0x1d4e, 0x0e05: 0x1ba1,
- 0x0e06: 0x1ba1,
- 0x0e13: 0x1eb7, 0x0e14: 0x1ea8, 0x0e15: 0x1ead, 0x0e16: 0x1ebc, 0x0e17: 0x1eb2,
- 0x0e1d: 0x4376,
- 0x0e1e: 0x801a, 0x0e1f: 0x43e8, 0x0e20: 0x0227, 0x0e21: 0x020f, 0x0e22: 0x0218, 0x0e23: 0x021b,
- 0x0e24: 0x021e, 0x0e25: 0x0221, 0x0e26: 0x0224, 0x0e27: 0x022a, 0x0e28: 0x022d, 0x0e29: 0x0017,
- 0x0e2a: 0x43d6, 0x0e2b: 0x43dc, 0x0e2c: 0x44da, 0x0e2d: 0x44e2, 0x0e2e: 0x432e, 0x0e2f: 0x4334,
- 0x0e30: 0x433a, 0x0e31: 0x4340, 0x0e32: 0x434c, 0x0e33: 0x4352, 0x0e34: 0x4358, 0x0e35: 0x4364,
- 0x0e36: 0x436a, 0x0e38: 0x4370, 0x0e39: 0x437c, 0x0e3a: 0x4382, 0x0e3b: 0x4388,
- 0x0e3c: 0x4394, 0x0e3e: 0x439a,
- // Block 0x39, offset 0xe40
- 0x0e40: 0x43a0, 0x0e41: 0x43a6, 0x0e43: 0x43ac, 0x0e44: 0x43b2,
- 0x0e46: 0x43be, 0x0e47: 0x43c4, 0x0e48: 0x43ca, 0x0e49: 0x43d0, 0x0e4a: 0x43e2, 0x0e4b: 0x435e,
- 0x0e4c: 0x4346, 0x0e4d: 0x438e, 0x0e4e: 0x43b8, 0x0e4f: 0x1ec1, 0x0e50: 0x0293, 0x0e51: 0x0293,
- 0x0e52: 0x029c, 0x0e53: 0x029c, 0x0e54: 0x029c, 0x0e55: 0x029c, 0x0e56: 0x029f, 0x0e57: 0x029f,
- 0x0e58: 0x029f, 0x0e59: 0x029f, 0x0e5a: 0x02a5, 0x0e5b: 0x02a5, 0x0e5c: 0x02a5, 0x0e5d: 0x02a5,
- 0x0e5e: 0x0299, 0x0e5f: 0x0299, 0x0e60: 0x0299, 0x0e61: 0x0299, 0x0e62: 0x02a2, 0x0e63: 0x02a2,
- 0x0e64: 0x02a2, 0x0e65: 0x02a2, 0x0e66: 0x0296, 0x0e67: 0x0296, 0x0e68: 0x0296, 0x0e69: 0x0296,
- 0x0e6a: 0x02c9, 0x0e6b: 0x02c9, 0x0e6c: 0x02c9, 0x0e6d: 0x02c9, 0x0e6e: 0x02cc, 0x0e6f: 0x02cc,
- 0x0e70: 0x02cc, 0x0e71: 0x02cc, 0x0e72: 0x02ab, 0x0e73: 0x02ab, 0x0e74: 0x02ab, 0x0e75: 0x02ab,
- 0x0e76: 0x02a8, 0x0e77: 0x02a8, 0x0e78: 0x02a8, 0x0e79: 0x02a8, 0x0e7a: 0x02ae, 0x0e7b: 0x02ae,
- 0x0e7c: 0x02ae, 0x0e7d: 0x02ae, 0x0e7e: 0x02b1, 0x0e7f: 0x02b1,
- // Block 0x3a, offset 0xe80
- 0x0e80: 0x02b1, 0x0e81: 0x02b1, 0x0e82: 0x02ba, 0x0e83: 0x02ba, 0x0e84: 0x02b7, 0x0e85: 0x02b7,
- 0x0e86: 0x02bd, 0x0e87: 0x02bd, 0x0e88: 0x02b4, 0x0e89: 0x02b4, 0x0e8a: 0x02c3, 0x0e8b: 0x02c3,
- 0x0e8c: 0x02c0, 0x0e8d: 0x02c0, 0x0e8e: 0x02cf, 0x0e8f: 0x02cf, 0x0e90: 0x02cf, 0x0e91: 0x02cf,
- 0x0e92: 0x02d5, 0x0e93: 0x02d5, 0x0e94: 0x02d5, 0x0e95: 0x02d5, 0x0e96: 0x02db, 0x0e97: 0x02db,
- 0x0e98: 0x02db, 0x0e99: 0x02db, 0x0e9a: 0x02d8, 0x0e9b: 0x02d8, 0x0e9c: 0x02d8, 0x0e9d: 0x02d8,
- 0x0e9e: 0x02de, 0x0e9f: 0x02de, 0x0ea0: 0x02e1, 0x0ea1: 0x02e1, 0x0ea2: 0x02e1, 0x0ea3: 0x02e1,
- 0x0ea4: 0x4454, 0x0ea5: 0x4454, 0x0ea6: 0x02e7, 0x0ea7: 0x02e7, 0x0ea8: 0x02e7, 0x0ea9: 0x02e7,
- 0x0eaa: 0x02e4, 0x0eab: 0x02e4, 0x0eac: 0x02e4, 0x0ead: 0x02e4, 0x0eae: 0x0302, 0x0eaf: 0x0302,
- 0x0eb0: 0x444e, 0x0eb1: 0x444e,
- // Block 0x3b, offset 0xec0
- 0x0ed3: 0x02d2, 0x0ed4: 0x02d2, 0x0ed5: 0x02d2, 0x0ed6: 0x02d2, 0x0ed7: 0x02f0,
- 0x0ed8: 0x02f0, 0x0ed9: 0x02ed, 0x0eda: 0x02ed, 0x0edb: 0x02f3, 0x0edc: 0x02f3, 0x0edd: 0x2191,
- 0x0ede: 0x02f9, 0x0edf: 0x02f9, 0x0ee0: 0x02ea, 0x0ee1: 0x02ea, 0x0ee2: 0x02f6, 0x0ee3: 0x02f6,
- 0x0ee4: 0x02ff, 0x0ee5: 0x02ff, 0x0ee6: 0x02ff, 0x0ee7: 0x02ff, 0x0ee8: 0x0287, 0x0ee9: 0x0287,
- 0x0eea: 0x26ec, 0x0eeb: 0x26ec, 0x0eec: 0x275c, 0x0eed: 0x275c, 0x0eee: 0x272b, 0x0eef: 0x272b,
- 0x0ef0: 0x2747, 0x0ef1: 0x2747, 0x0ef2: 0x2740, 0x0ef3: 0x2740, 0x0ef4: 0x274e, 0x0ef5: 0x274e,
- 0x0ef6: 0x2755, 0x0ef7: 0x2755, 0x0ef8: 0x2755, 0x0ef9: 0x2732, 0x0efa: 0x2732, 0x0efb: 0x2732,
- 0x0efc: 0x02fc, 0x0efd: 0x02fc, 0x0efe: 0x02fc, 0x0eff: 0x02fc,
- // Block 0x3c, offset 0xf00
- 0x0f00: 0x26f3, 0x0f01: 0x26fa, 0x0f02: 0x2716, 0x0f03: 0x2732, 0x0f04: 0x2739, 0x0f05: 0x1ecb,
- 0x0f06: 0x1ed0, 0x0f07: 0x1ed5, 0x0f08: 0x1ee4, 0x0f09: 0x1ef3, 0x0f0a: 0x1ef8, 0x0f0b: 0x1efd,
- 0x0f0c: 0x1f02, 0x0f0d: 0x1f07, 0x0f0e: 0x1f16, 0x0f0f: 0x1f25, 0x0f10: 0x1f2a, 0x0f11: 0x1f2f,
- 0x0f12: 0x1f3e, 0x0f13: 0x1f4d, 0x0f14: 0x1f52, 0x0f15: 0x1f57, 0x0f16: 0x1f5c, 0x0f17: 0x1f6b,
- 0x0f18: 0x1f70, 0x0f19: 0x1f7f, 0x0f1a: 0x1f84, 0x0f1b: 0x1f89, 0x0f1c: 0x1f98, 0x0f1d: 0x1f9d,
- 0x0f1e: 0x1fa2, 0x0f1f: 0x1fac, 0x0f20: 0x1fe8, 0x0f21: 0x1ff7, 0x0f22: 0x2006, 0x0f23: 0x200b,
- 0x0f24: 0x2010, 0x0f25: 0x201a, 0x0f26: 0x2029, 0x0f27: 0x202e, 0x0f28: 0x203d, 0x0f29: 0x2042,
- 0x0f2a: 0x2047, 0x0f2b: 0x2056, 0x0f2c: 0x205b, 0x0f2d: 0x206a, 0x0f2e: 0x206f, 0x0f2f: 0x2074,
- 0x0f30: 0x2079, 0x0f31: 0x207e, 0x0f32: 0x2083, 0x0f33: 0x2088, 0x0f34: 0x208d, 0x0f35: 0x2092,
- 0x0f36: 0x2097, 0x0f37: 0x209c, 0x0f38: 0x20a1, 0x0f39: 0x20a6, 0x0f3a: 0x20ab, 0x0f3b: 0x20b0,
- 0x0f3c: 0x20b5, 0x0f3d: 0x20ba, 0x0f3e: 0x20bf, 0x0f3f: 0x20c9,
- // Block 0x3d, offset 0xf40
- 0x0f40: 0x20ce, 0x0f41: 0x20d3, 0x0f42: 0x20d8, 0x0f43: 0x20e2, 0x0f44: 0x20e7, 0x0f45: 0x20f1,
- 0x0f46: 0x20f6, 0x0f47: 0x20fb, 0x0f48: 0x2100, 0x0f49: 0x2105, 0x0f4a: 0x210a, 0x0f4b: 0x210f,
- 0x0f4c: 0x2114, 0x0f4d: 0x2119, 0x0f4e: 0x2128, 0x0f4f: 0x2137, 0x0f50: 0x213c, 0x0f51: 0x2141,
- 0x0f52: 0x2146, 0x0f53: 0x214b, 0x0f54: 0x2150, 0x0f55: 0x215a, 0x0f56: 0x215f, 0x0f57: 0x2164,
- 0x0f58: 0x2173, 0x0f59: 0x2182, 0x0f5a: 0x2187, 0x0f5b: 0x4406, 0x0f5c: 0x440c, 0x0f5d: 0x4442,
- 0x0f5e: 0x4499, 0x0f5f: 0x44a0, 0x0f60: 0x44a7, 0x0f61: 0x44ae, 0x0f62: 0x44b5, 0x0f63: 0x44bc,
- 0x0f64: 0x2708, 0x0f65: 0x270f, 0x0f66: 0x2716, 0x0f67: 0x271d, 0x0f68: 0x2732, 0x0f69: 0x2739,
- 0x0f6a: 0x1eda, 0x0f6b: 0x1edf, 0x0f6c: 0x1ee4, 0x0f6d: 0x1ee9, 0x0f6e: 0x1ef3, 0x0f6f: 0x1ef8,
- 0x0f70: 0x1f0c, 0x0f71: 0x1f11, 0x0f72: 0x1f16, 0x0f73: 0x1f1b, 0x0f74: 0x1f25, 0x0f75: 0x1f2a,
- 0x0f76: 0x1f34, 0x0f77: 0x1f39, 0x0f78: 0x1f3e, 0x0f79: 0x1f43, 0x0f7a: 0x1f4d, 0x0f7b: 0x1f52,
- 0x0f7c: 0x207e, 0x0f7d: 0x2083, 0x0f7e: 0x2092, 0x0f7f: 0x2097,
- // Block 0x3e, offset 0xf80
- 0x0f80: 0x209c, 0x0f81: 0x20b0, 0x0f82: 0x20b5, 0x0f83: 0x20ba, 0x0f84: 0x20bf, 0x0f85: 0x20d8,
- 0x0f86: 0x20e2, 0x0f87: 0x20e7, 0x0f88: 0x20ec, 0x0f89: 0x2100, 0x0f8a: 0x211e, 0x0f8b: 0x2123,
- 0x0f8c: 0x2128, 0x0f8d: 0x212d, 0x0f8e: 0x2137, 0x0f8f: 0x213c, 0x0f90: 0x4442, 0x0f91: 0x2169,
- 0x0f92: 0x216e, 0x0f93: 0x2173, 0x0f94: 0x2178, 0x0f95: 0x2182, 0x0f96: 0x2187, 0x0f97: 0x26f3,
- 0x0f98: 0x26fa, 0x0f99: 0x2701, 0x0f9a: 0x2716, 0x0f9b: 0x2724, 0x0f9c: 0x1ecb, 0x0f9d: 0x1ed0,
- 0x0f9e: 0x1ed5, 0x0f9f: 0x1ee4, 0x0fa0: 0x1eee, 0x0fa1: 0x1efd, 0x0fa2: 0x1f02, 0x0fa3: 0x1f07,
- 0x0fa4: 0x1f16, 0x0fa5: 0x1f20, 0x0fa6: 0x1f3e, 0x0fa7: 0x1f57, 0x0fa8: 0x1f5c, 0x0fa9: 0x1f6b,
- 0x0faa: 0x1f70, 0x0fab: 0x1f7f, 0x0fac: 0x1f89, 0x0fad: 0x1f98, 0x0fae: 0x1f9d, 0x0faf: 0x1fa2,
- 0x0fb0: 0x1fac, 0x0fb1: 0x1fe8, 0x0fb2: 0x1fed, 0x0fb3: 0x1ff7, 0x0fb4: 0x2006, 0x0fb5: 0x200b,
- 0x0fb6: 0x2010, 0x0fb7: 0x201a, 0x0fb8: 0x2029, 0x0fb9: 0x203d, 0x0fba: 0x2042, 0x0fbb: 0x2047,
- 0x0fbc: 0x2056, 0x0fbd: 0x205b, 0x0fbe: 0x206a, 0x0fbf: 0x206f,
- // Block 0x3f, offset 0xfc0
- 0x0fc0: 0x2074, 0x0fc1: 0x2079, 0x0fc2: 0x2088, 0x0fc3: 0x208d, 0x0fc4: 0x20a1, 0x0fc5: 0x20a6,
- 0x0fc6: 0x20ab, 0x0fc7: 0x20b0, 0x0fc8: 0x20b5, 0x0fc9: 0x20c9, 0x0fca: 0x20ce, 0x0fcb: 0x20d3,
- 0x0fcc: 0x20d8, 0x0fcd: 0x20dd, 0x0fce: 0x20f1, 0x0fcf: 0x20f6, 0x0fd0: 0x20fb, 0x0fd1: 0x2100,
- 0x0fd2: 0x210f, 0x0fd3: 0x2114, 0x0fd4: 0x2119, 0x0fd5: 0x2128, 0x0fd6: 0x2132, 0x0fd7: 0x2141,
- 0x0fd8: 0x2146, 0x0fd9: 0x4436, 0x0fda: 0x215a, 0x0fdb: 0x215f, 0x0fdc: 0x2164, 0x0fdd: 0x2173,
- 0x0fde: 0x217d, 0x0fdf: 0x2716, 0x0fe0: 0x2724, 0x0fe1: 0x1ee4, 0x0fe2: 0x1eee, 0x0fe3: 0x1f16,
- 0x0fe4: 0x1f20, 0x0fe5: 0x1f3e, 0x0fe6: 0x1f48, 0x0fe7: 0x1fac, 0x0fe8: 0x1fb1, 0x0fe9: 0x1fd4,
- 0x0fea: 0x1fd9, 0x0feb: 0x20b0, 0x0fec: 0x20b5, 0x0fed: 0x20d8, 0x0fee: 0x2128, 0x0fef: 0x2132,
- 0x0ff0: 0x2173, 0x0ff1: 0x217d, 0x0ff2: 0x44ea, 0x0ff3: 0x44f2, 0x0ff4: 0x44fa, 0x0ff5: 0x2033,
- 0x0ff6: 0x2038, 0x0ff7: 0x204c, 0x0ff8: 0x2051, 0x0ff9: 0x2060, 0x0ffa: 0x2065, 0x0ffb: 0x1fb6,
- 0x0ffc: 0x1fbb, 0x0ffd: 0x1fde, 0x0ffe: 0x1fe3, 0x0fff: 0x1f75,
- // Block 0x40, offset 0x1000
- 0x1000: 0x1f7a, 0x1001: 0x1f61, 0x1002: 0x1f66, 0x1003: 0x1f8e, 0x1004: 0x1f93, 0x1005: 0x1ffc,
- 0x1006: 0x2001, 0x1007: 0x201f, 0x1008: 0x2024, 0x1009: 0x1fc0, 0x100a: 0x1fc5, 0x100b: 0x1fca,
- 0x100c: 0x1fd4, 0x100d: 0x1fcf, 0x100e: 0x1fa7, 0x100f: 0x1ff2, 0x1010: 0x2015, 0x1011: 0x2033,
- 0x1012: 0x2038, 0x1013: 0x204c, 0x1014: 0x2051, 0x1015: 0x2060, 0x1016: 0x2065, 0x1017: 0x1fb6,
- 0x1018: 0x1fbb, 0x1019: 0x1fde, 0x101a: 0x1fe3, 0x101b: 0x1f75, 0x101c: 0x1f7a, 0x101d: 0x1f61,
- 0x101e: 0x1f66, 0x101f: 0x1f8e, 0x1020: 0x1f93, 0x1021: 0x1ffc, 0x1022: 0x2001, 0x1023: 0x201f,
- 0x1024: 0x2024, 0x1025: 0x1fc0, 0x1026: 0x1fc5, 0x1027: 0x1fca, 0x1028: 0x1fd4, 0x1029: 0x1fcf,
- 0x102a: 0x1fa7, 0x102b: 0x1ff2, 0x102c: 0x2015, 0x102d: 0x1fc0, 0x102e: 0x1fc5, 0x102f: 0x1fca,
- 0x1030: 0x1fd4, 0x1031: 0x1fb1, 0x1032: 0x1fd9, 0x1033: 0x202e, 0x1034: 0x1f98, 0x1035: 0x1f9d,
- 0x1036: 0x1fa2, 0x1037: 0x1fc0, 0x1038: 0x1fc5, 0x1039: 0x1fca, 0x103a: 0x202e, 0x103b: 0x203d,
- 0x103c: 0x43ee, 0x103d: 0x43ee,
- // Block 0x41, offset 0x1040
- 0x1050: 0x2453, 0x1051: 0x2468,
- 0x1052: 0x2468, 0x1053: 0x246f, 0x1054: 0x2476, 0x1055: 0x248b, 0x1056: 0x2492, 0x1057: 0x2499,
- 0x1058: 0x24bc, 0x1059: 0x24bc, 0x105a: 0x24df, 0x105b: 0x24d8, 0x105c: 0x24f4, 0x105d: 0x24e6,
- 0x105e: 0x24ed, 0x105f: 0x2510, 0x1060: 0x2510, 0x1061: 0x2509, 0x1062: 0x2517, 0x1063: 0x2517,
- 0x1064: 0x2541, 0x1065: 0x2541, 0x1066: 0x255d, 0x1067: 0x2525, 0x1068: 0x2525, 0x1069: 0x251e,
- 0x106a: 0x2533, 0x106b: 0x2533, 0x106c: 0x253a, 0x106d: 0x253a, 0x106e: 0x2564, 0x106f: 0x2572,
- 0x1070: 0x2572, 0x1071: 0x2579, 0x1072: 0x2579, 0x1073: 0x2580, 0x1074: 0x2587, 0x1075: 0x258e,
- 0x1076: 0x2595, 0x1077: 0x2595, 0x1078: 0x259c, 0x1079: 0x25aa, 0x107a: 0x25b8, 0x107b: 0x25b1,
- 0x107c: 0x25bf, 0x107d: 0x25bf, 0x107e: 0x25d4, 0x107f: 0x25db,
- // Block 0x42, offset 0x1080
- 0x1080: 0x260c, 0x1081: 0x261a, 0x1082: 0x2613, 0x1083: 0x25f7, 0x1084: 0x25f7, 0x1085: 0x2621,
- 0x1086: 0x2621, 0x1087: 0x2628, 0x1088: 0x2628, 0x1089: 0x2652, 0x108a: 0x2659, 0x108b: 0x2660,
- 0x108c: 0x2636, 0x108d: 0x2644, 0x108e: 0x2667, 0x108f: 0x266e,
- 0x1092: 0x263d, 0x1093: 0x26c2, 0x1094: 0x26c9, 0x1095: 0x269f, 0x1096: 0x26a6, 0x1097: 0x268a,
- 0x1098: 0x268a, 0x1099: 0x2691, 0x109a: 0x26bb, 0x109b: 0x26b4, 0x109c: 0x26de, 0x109d: 0x26de,
- 0x109e: 0x244c, 0x109f: 0x2461, 0x10a0: 0x245a, 0x10a1: 0x2484, 0x10a2: 0x247d, 0x10a3: 0x24a7,
- 0x10a4: 0x24a0, 0x10a5: 0x24ca, 0x10a6: 0x24ae, 0x10a7: 0x24c3, 0x10a8: 0x24fb, 0x10a9: 0x2548,
- 0x10aa: 0x252c, 0x10ab: 0x256b, 0x10ac: 0x2605, 0x10ad: 0x262f, 0x10ae: 0x26d7, 0x10af: 0x26d0,
- 0x10b0: 0x26e5, 0x10b1: 0x267c, 0x10b2: 0x25e2, 0x10b3: 0x26ad, 0x10b4: 0x25d4, 0x10b5: 0x260c,
- 0x10b6: 0x25a3, 0x10b7: 0x25f0, 0x10b8: 0x2683, 0x10b9: 0x2675, 0x10ba: 0x25fe, 0x10bb: 0x25e9,
- 0x10bc: 0x25fe, 0x10bd: 0x2683, 0x10be: 0x24b5, 0x10bf: 0x24d1,
- // Block 0x43, offset 0x10c0
- 0x10c0: 0x264b, 0x10c1: 0x25c6, 0x10c2: 0x2445, 0x10c3: 0x25e9, 0x10c4: 0x258e, 0x10c5: 0x255d,
- 0x10c6: 0x2502, 0x10c7: 0x2698,
- 0x10f0: 0x2556, 0x10f1: 0x25cd, 0x10f2: 0x296a, 0x10f3: 0x2961, 0x10f4: 0x2997, 0x10f5: 0x2985,
- 0x10f6: 0x2973, 0x10f7: 0x298e, 0x10f8: 0x29a0, 0x10f9: 0x254f, 0x10fa: 0x2e44, 0x10fb: 0x2cb4,
- 0x10fc: 0x297c,
- // Block 0x44, offset 0x1100
- 0x1110: 0x0019, 0x1111: 0x04f5,
- 0x1112: 0x04f9, 0x1113: 0x0035, 0x1114: 0x0037, 0x1115: 0x0003, 0x1116: 0x003f, 0x1117: 0x0531,
- 0x1118: 0x0535, 0x1119: 0x1c9e,
- 0x1120: 0x80e6, 0x1121: 0x80e6, 0x1122: 0x80e6, 0x1123: 0x80e6,
- 0x1124: 0x80e6, 0x1125: 0x80e6, 0x1126: 0x80e6,
- 0x1130: 0x19b5, 0x1131: 0x04b5, 0x1132: 0x04b1, 0x1133: 0x007f, 0x1134: 0x007f, 0x1135: 0x0011,
- 0x1136: 0x0013, 0x1137: 0x00b7, 0x1138: 0x00bb, 0x1139: 0x0529, 0x113a: 0x052d, 0x113b: 0x051d,
- 0x113c: 0x0521, 0x113d: 0x0505, 0x113e: 0x0509, 0x113f: 0x04fd,
- // Block 0x45, offset 0x1140
- 0x1140: 0x0501, 0x1141: 0x050d, 0x1142: 0x0511, 0x1143: 0x0515, 0x1144: 0x0519,
- 0x1147: 0x0077, 0x1148: 0x007b, 0x1149: 0x424f, 0x114a: 0x424f, 0x114b: 0x424f,
- 0x114c: 0x424f, 0x114d: 0x007f, 0x114e: 0x007f, 0x114f: 0x007f, 0x1150: 0x0019, 0x1151: 0x04f5,
- 0x1152: 0x001d, 0x1154: 0x0037, 0x1155: 0x0035, 0x1156: 0x003f, 0x1157: 0x0003,
- 0x1158: 0x04b5, 0x1159: 0x0011, 0x115a: 0x0013, 0x115b: 0x00b7, 0x115c: 0x00bb, 0x115d: 0x0529,
- 0x115e: 0x052d, 0x115f: 0x0007, 0x1160: 0x000d, 0x1161: 0x0015, 0x1162: 0x0017, 0x1163: 0x001b,
- 0x1164: 0x0039, 0x1165: 0x003d, 0x1166: 0x003b, 0x1168: 0x0079, 0x1169: 0x0009,
- 0x116a: 0x000b, 0x116b: 0x0041,
- 0x1170: 0x4290, 0x1171: 0x4412, 0x1172: 0x4295, 0x1174: 0x429a,
- 0x1176: 0x429f, 0x1177: 0x4418, 0x1178: 0x42a4, 0x1179: 0x441e, 0x117a: 0x42a9, 0x117b: 0x4424,
- 0x117c: 0x42ae, 0x117d: 0x442a, 0x117e: 0x42b3, 0x117f: 0x4430,
- // Block 0x46, offset 0x1180
- 0x1180: 0x0230, 0x1181: 0x43f4, 0x1182: 0x43f4, 0x1183: 0x43fa, 0x1184: 0x43fa, 0x1185: 0x443c,
- 0x1186: 0x443c, 0x1187: 0x4400, 0x1188: 0x4400, 0x1189: 0x4448, 0x118a: 0x4448, 0x118b: 0x4448,
- 0x118c: 0x4448, 0x118d: 0x0233, 0x118e: 0x0233, 0x118f: 0x0236, 0x1190: 0x0236, 0x1191: 0x0236,
- 0x1192: 0x0236, 0x1193: 0x0239, 0x1194: 0x0239, 0x1195: 0x023c, 0x1196: 0x023c, 0x1197: 0x023c,
- 0x1198: 0x023c, 0x1199: 0x023f, 0x119a: 0x023f, 0x119b: 0x023f, 0x119c: 0x023f, 0x119d: 0x0242,
- 0x119e: 0x0242, 0x119f: 0x0242, 0x11a0: 0x0242, 0x11a1: 0x0245, 0x11a2: 0x0245, 0x11a3: 0x0245,
- 0x11a4: 0x0245, 0x11a5: 0x0248, 0x11a6: 0x0248, 0x11a7: 0x0248, 0x11a8: 0x0248, 0x11a9: 0x024b,
- 0x11aa: 0x024b, 0x11ab: 0x024e, 0x11ac: 0x024e, 0x11ad: 0x0251, 0x11ae: 0x0251, 0x11af: 0x0254,
- 0x11b0: 0x0254, 0x11b1: 0x0257, 0x11b2: 0x0257, 0x11b3: 0x0257, 0x11b4: 0x0257, 0x11b5: 0x025a,
- 0x11b6: 0x025a, 0x11b7: 0x025a, 0x11b8: 0x025a, 0x11b9: 0x025d, 0x11ba: 0x025d, 0x11bb: 0x025d,
- 0x11bc: 0x025d, 0x11bd: 0x0260, 0x11be: 0x0260, 0x11bf: 0x0260,
- // Block 0x47, offset 0x11c0
- 0x11c0: 0x0260, 0x11c1: 0x0263, 0x11c2: 0x0263, 0x11c3: 0x0263, 0x11c4: 0x0263, 0x11c5: 0x0266,
- 0x11c6: 0x0266, 0x11c7: 0x0266, 0x11c8: 0x0266, 0x11c9: 0x0269, 0x11ca: 0x0269, 0x11cb: 0x0269,
- 0x11cc: 0x0269, 0x11cd: 0x026c, 0x11ce: 0x026c, 0x11cf: 0x026c, 0x11d0: 0x026c, 0x11d1: 0x026f,
- 0x11d2: 0x026f, 0x11d3: 0x026f, 0x11d4: 0x026f, 0x11d5: 0x0272, 0x11d6: 0x0272, 0x11d7: 0x0272,
- 0x11d8: 0x0272, 0x11d9: 0x0275, 0x11da: 0x0275, 0x11db: 0x0275, 0x11dc: 0x0275, 0x11dd: 0x0278,
- 0x11de: 0x0278, 0x11df: 0x0278, 0x11e0: 0x0278, 0x11e1: 0x027b, 0x11e2: 0x027b, 0x11e3: 0x027b,
- 0x11e4: 0x027b, 0x11e5: 0x027e, 0x11e6: 0x027e, 0x11e7: 0x027e, 0x11e8: 0x027e, 0x11e9: 0x0281,
- 0x11ea: 0x0281, 0x11eb: 0x0281, 0x11ec: 0x0281, 0x11ed: 0x0284, 0x11ee: 0x0284, 0x11ef: 0x0287,
- 0x11f0: 0x0287, 0x11f1: 0x028a, 0x11f2: 0x028a, 0x11f3: 0x028a, 0x11f4: 0x028a, 0x11f5: 0x2e91,
- 0x11f6: 0x2e91, 0x11f7: 0x2e99, 0x11f8: 0x2e99, 0x11f9: 0x2ea1, 0x11fa: 0x2ea1, 0x11fb: 0x20c4,
- 0x11fc: 0x20c4,
- // Block 0x48, offset 0x1200
- 0x1200: 0x0081, 0x1201: 0x0083, 0x1202: 0x0085, 0x1203: 0x0087, 0x1204: 0x0089, 0x1205: 0x008b,
- 0x1206: 0x008d, 0x1207: 0x008f, 0x1208: 0x0091, 0x1209: 0x0093, 0x120a: 0x0095, 0x120b: 0x0097,
- 0x120c: 0x0099, 0x120d: 0x009b, 0x120e: 0x009d, 0x120f: 0x009f, 0x1210: 0x00a1, 0x1211: 0x00a3,
- 0x1212: 0x00a5, 0x1213: 0x00a7, 0x1214: 0x00a9, 0x1215: 0x00ab, 0x1216: 0x00ad, 0x1217: 0x00af,
- 0x1218: 0x00b1, 0x1219: 0x00b3, 0x121a: 0x00b5, 0x121b: 0x00b7, 0x121c: 0x00b9, 0x121d: 0x00bb,
- 0x121e: 0x00bd, 0x121f: 0x04e9, 0x1220: 0x04ed, 0x1221: 0x04f9, 0x1222: 0x050d, 0x1223: 0x0511,
- 0x1224: 0x04f5, 0x1225: 0x061d, 0x1226: 0x0615, 0x1227: 0x0539, 0x1228: 0x0541, 0x1229: 0x0549,
- 0x122a: 0x0551, 0x122b: 0x0559, 0x122c: 0x05dd, 0x122d: 0x05e5, 0x122e: 0x05ed, 0x122f: 0x0591,
- 0x1230: 0x0621, 0x1231: 0x053d, 0x1232: 0x0545, 0x1233: 0x054d, 0x1234: 0x0555, 0x1235: 0x055d,
- 0x1236: 0x0561, 0x1237: 0x0565, 0x1238: 0x0569, 0x1239: 0x056d, 0x123a: 0x0571, 0x123b: 0x0575,
- 0x123c: 0x0579, 0x123d: 0x057d, 0x123e: 0x0581, 0x123f: 0x0585,
- // Block 0x49, offset 0x1240
- 0x1240: 0x0589, 0x1241: 0x058d, 0x1242: 0x0595, 0x1243: 0x0599, 0x1244: 0x059d, 0x1245: 0x05a1,
- 0x1246: 0x05a5, 0x1247: 0x05a9, 0x1248: 0x05ad, 0x1249: 0x05b1, 0x124a: 0x05b5, 0x124b: 0x05b9,
- 0x124c: 0x05bd, 0x124d: 0x05c1, 0x124e: 0x05c5, 0x124f: 0x05c9, 0x1250: 0x05cd, 0x1251: 0x05d1,
- 0x1252: 0x05d5, 0x1253: 0x05d9, 0x1254: 0x05e1, 0x1255: 0x05e9, 0x1256: 0x05f1, 0x1257: 0x05f5,
- 0x1258: 0x05f9, 0x1259: 0x05fd, 0x125a: 0x0601, 0x125b: 0x0605, 0x125c: 0x0609, 0x125d: 0x0619,
- 0x125e: 0x49aa, 0x125f: 0x49b0, 0x1260: 0x03bd, 0x1261: 0x030d, 0x1262: 0x0311, 0x1263: 0x0435,
- 0x1264: 0x0315, 0x1265: 0x0439, 0x1266: 0x043d, 0x1267: 0x0319, 0x1268: 0x031d, 0x1269: 0x0321,
- 0x126a: 0x0441, 0x126b: 0x0445, 0x126c: 0x0449, 0x126d: 0x044d, 0x126e: 0x0451, 0x126f: 0x0455,
- 0x1270: 0x0361, 0x1271: 0x0325, 0x1272: 0x0329, 0x1273: 0x032d, 0x1274: 0x0375, 0x1275: 0x0331,
- 0x1276: 0x0335, 0x1277: 0x0339, 0x1278: 0x033d, 0x1279: 0x0341, 0x127a: 0x0345, 0x127b: 0x0349,
- 0x127c: 0x034d, 0x127d: 0x0351, 0x127e: 0x0355,
- // Block 0x4a, offset 0x1280
- 0x1280: 0x0063, 0x1281: 0x0065, 0x1282: 0x0067, 0x1283: 0x0069, 0x1284: 0x006b, 0x1285: 0x006d,
- 0x1286: 0x006f, 0x1287: 0x0071, 0x1288: 0x0073, 0x1289: 0x0075, 0x128a: 0x0083, 0x128b: 0x0085,
- 0x128c: 0x0087, 0x128d: 0x0089, 0x128e: 0x008b, 0x128f: 0x008d, 0x1290: 0x008f, 0x1291: 0x0091,
- 0x1292: 0x0093, 0x1293: 0x0095, 0x1294: 0x0097, 0x1295: 0x0099, 0x1296: 0x009b, 0x1297: 0x009d,
- 0x1298: 0x009f, 0x1299: 0x00a1, 0x129a: 0x00a3, 0x129b: 0x00a5, 0x129c: 0x00a7, 0x129d: 0x00a9,
- 0x129e: 0x00ab, 0x129f: 0x00ad, 0x12a0: 0x00af, 0x12a1: 0x00b1, 0x12a2: 0x00b3, 0x12a3: 0x00b5,
- 0x12a4: 0x00e0, 0x12a5: 0x00f5, 0x12a8: 0x0173, 0x12a9: 0x0176,
- 0x12aa: 0x0179, 0x12ab: 0x017c, 0x12ac: 0x017f, 0x12ad: 0x0182, 0x12ae: 0x0185, 0x12af: 0x0188,
- 0x12b0: 0x018b, 0x12b1: 0x018e, 0x12b2: 0x0191, 0x12b3: 0x0194, 0x12b4: 0x0197, 0x12b5: 0x019a,
- 0x12b6: 0x019d, 0x12b7: 0x01a0, 0x12b8: 0x01a3, 0x12b9: 0x0188, 0x12ba: 0x01a6, 0x12bb: 0x01a9,
- 0x12bc: 0x01ac, 0x12bd: 0x01af, 0x12be: 0x01b2, 0x12bf: 0x01b5,
- // Block 0x4b, offset 0x12c0
- 0x12c0: 0x01fd, 0x12c1: 0x0200, 0x12c2: 0x0203, 0x12c3: 0x04cd, 0x12c4: 0x01c7, 0x12c5: 0x01d0,
- 0x12c6: 0x01d6, 0x12c7: 0x01fa, 0x12c8: 0x01eb, 0x12c9: 0x01e8, 0x12ca: 0x0206, 0x12cb: 0x0209,
- 0x12ce: 0x0021, 0x12cf: 0x0023, 0x12d0: 0x0025, 0x12d1: 0x0027,
- 0x12d2: 0x0029, 0x12d3: 0x002b, 0x12d4: 0x002d, 0x12d5: 0x002f, 0x12d6: 0x0031, 0x12d7: 0x0033,
- 0x12d8: 0x0021, 0x12d9: 0x0023, 0x12da: 0x0025, 0x12db: 0x0027, 0x12dc: 0x0029, 0x12dd: 0x002b,
- 0x12de: 0x002d, 0x12df: 0x002f, 0x12e0: 0x0031, 0x12e1: 0x0033, 0x12e2: 0x0021, 0x12e3: 0x0023,
- 0x12e4: 0x0025, 0x12e5: 0x0027, 0x12e6: 0x0029, 0x12e7: 0x002b, 0x12e8: 0x002d, 0x12e9: 0x002f,
- 0x12ea: 0x0031, 0x12eb: 0x0033, 0x12ec: 0x0021, 0x12ed: 0x0023, 0x12ee: 0x0025, 0x12ef: 0x0027,
- 0x12f0: 0x0029, 0x12f1: 0x002b, 0x12f2: 0x002d, 0x12f3: 0x002f, 0x12f4: 0x0031, 0x12f5: 0x0033,
- 0x12f6: 0x0021, 0x12f7: 0x0023, 0x12f8: 0x0025, 0x12f9: 0x0027, 0x12fa: 0x0029, 0x12fb: 0x002b,
- 0x12fc: 0x002d, 0x12fd: 0x002f, 0x12fe: 0x0031, 0x12ff: 0x0033,
- // Block 0x4c, offset 0x1300
- 0x1300: 0x0233, 0x1301: 0x0236, 0x1302: 0x0242, 0x1303: 0x024b, 0x1305: 0x0284,
- 0x1306: 0x0254, 0x1307: 0x0245, 0x1308: 0x0263, 0x1309: 0x028a, 0x130a: 0x0275, 0x130b: 0x0278,
- 0x130c: 0x027b, 0x130d: 0x027e, 0x130e: 0x0257, 0x130f: 0x0269, 0x1310: 0x026f, 0x1311: 0x025d,
- 0x1312: 0x0272, 0x1313: 0x0251, 0x1314: 0x025a, 0x1315: 0x023c, 0x1316: 0x023f, 0x1317: 0x0248,
- 0x1318: 0x024e, 0x1319: 0x0260, 0x131a: 0x0266, 0x131b: 0x026c, 0x131c: 0x028d, 0x131d: 0x02de,
- 0x131e: 0x02c6, 0x131f: 0x0290, 0x1321: 0x0236, 0x1322: 0x0242,
- 0x1324: 0x0281, 0x1327: 0x0245, 0x1329: 0x028a,
- 0x132a: 0x0275, 0x132b: 0x0278, 0x132c: 0x027b, 0x132d: 0x027e, 0x132e: 0x0257, 0x132f: 0x0269,
- 0x1330: 0x026f, 0x1331: 0x025d, 0x1332: 0x0272, 0x1334: 0x025a, 0x1335: 0x023c,
- 0x1336: 0x023f, 0x1337: 0x0248, 0x1339: 0x0260, 0x133b: 0x026c,
- // Block 0x4d, offset 0x1340
- 0x1342: 0x0242,
- 0x1347: 0x0245, 0x1349: 0x028a, 0x134b: 0x0278,
- 0x134d: 0x027e, 0x134e: 0x0257, 0x134f: 0x0269, 0x1351: 0x025d,
- 0x1352: 0x0272, 0x1354: 0x025a, 0x1357: 0x0248,
- 0x1359: 0x0260, 0x135b: 0x026c, 0x135d: 0x02de,
- 0x135f: 0x0290, 0x1361: 0x0236, 0x1362: 0x0242,
- 0x1364: 0x0281, 0x1367: 0x0245, 0x1368: 0x0263, 0x1369: 0x028a,
- 0x136a: 0x0275, 0x136c: 0x027b, 0x136d: 0x027e, 0x136e: 0x0257, 0x136f: 0x0269,
- 0x1370: 0x026f, 0x1371: 0x025d, 0x1372: 0x0272, 0x1374: 0x025a, 0x1375: 0x023c,
- 0x1376: 0x023f, 0x1377: 0x0248, 0x1379: 0x0260, 0x137a: 0x0266, 0x137b: 0x026c,
- 0x137c: 0x028d, 0x137e: 0x02c6,
- // Block 0x4e, offset 0x1380
- 0x1380: 0x0233, 0x1381: 0x0236, 0x1382: 0x0242, 0x1383: 0x024b, 0x1384: 0x0281, 0x1385: 0x0284,
- 0x1386: 0x0254, 0x1387: 0x0245, 0x1388: 0x0263, 0x1389: 0x028a, 0x138b: 0x0278,
- 0x138c: 0x027b, 0x138d: 0x027e, 0x138e: 0x0257, 0x138f: 0x0269, 0x1390: 0x026f, 0x1391: 0x025d,
- 0x1392: 0x0272, 0x1393: 0x0251, 0x1394: 0x025a, 0x1395: 0x023c, 0x1396: 0x023f, 0x1397: 0x0248,
- 0x1398: 0x024e, 0x1399: 0x0260, 0x139a: 0x0266, 0x139b: 0x026c,
- 0x13a1: 0x0236, 0x13a2: 0x0242, 0x13a3: 0x024b,
- 0x13a5: 0x0284, 0x13a6: 0x0254, 0x13a7: 0x0245, 0x13a8: 0x0263, 0x13a9: 0x028a,
- 0x13ab: 0x0278, 0x13ac: 0x027b, 0x13ad: 0x027e, 0x13ae: 0x0257, 0x13af: 0x0269,
- 0x13b0: 0x026f, 0x13b1: 0x025d, 0x13b2: 0x0272, 0x13b3: 0x0251, 0x13b4: 0x025a, 0x13b5: 0x023c,
- 0x13b6: 0x023f, 0x13b7: 0x0248, 0x13b8: 0x024e, 0x13b9: 0x0260, 0x13ba: 0x0266, 0x13bb: 0x026c,
- // Block 0x4f, offset 0x13c0
- 0x13c0: 0x19bb, 0x13c1: 0x19b8, 0x13c2: 0x19be, 0x13c3: 0x19e2, 0x13c4: 0x1a06, 0x13c5: 0x1a2a,
- 0x13c6: 0x1a4e, 0x13c7: 0x1a57, 0x13c8: 0x1a5d, 0x13c9: 0x1a63, 0x13ca: 0x1a69,
- 0x13d0: 0x1bce, 0x13d1: 0x1bd2,
- 0x13d2: 0x1bd6, 0x13d3: 0x1bda, 0x13d4: 0x1bde, 0x13d5: 0x1be2, 0x13d6: 0x1be6, 0x13d7: 0x1bea,
- 0x13d8: 0x1bee, 0x13d9: 0x1bf2, 0x13da: 0x1bf6, 0x13db: 0x1bfa, 0x13dc: 0x1bfe, 0x13dd: 0x1c02,
- 0x13de: 0x1c06, 0x13df: 0x1c0a, 0x13e0: 0x1c0e, 0x13e1: 0x1c12, 0x13e2: 0x1c16, 0x13e3: 0x1c1a,
- 0x13e4: 0x1c1e, 0x13e5: 0x1c22, 0x13e6: 0x1c26, 0x13e7: 0x1c2a, 0x13e8: 0x1c2e, 0x13e9: 0x1c32,
- 0x13ea: 0x28c9, 0x13eb: 0x0047, 0x13ec: 0x0065, 0x13ed: 0x1a7e, 0x13ee: 0x1af3,
- 0x13f0: 0x0043, 0x13f1: 0x0045, 0x13f2: 0x0047, 0x13f3: 0x0049, 0x13f4: 0x004b, 0x13f5: 0x004d,
- 0x13f6: 0x004f, 0x13f7: 0x0051, 0x13f8: 0x0053, 0x13f9: 0x0055, 0x13fa: 0x0057, 0x13fb: 0x0059,
- 0x13fc: 0x005b, 0x13fd: 0x005d, 0x13fe: 0x005f, 0x13ff: 0x0061,
- // Block 0x50, offset 0x1400
- 0x1400: 0x2858, 0x1401: 0x286d, 0x1402: 0x0575,
- 0x1410: 0x0c81, 0x1411: 0x0ab9,
- 0x1412: 0x0945, 0x1413: 0x45aa, 0x1414: 0x078d, 0x1415: 0x0a61, 0x1416: 0x13a1, 0x1417: 0x0a71,
- 0x1418: 0x0799, 0x1419: 0x0d49, 0x141a: 0x0f21, 0x141b: 0x0d21, 0x141c: 0x0899, 0x141d: 0x0bdd,
- 0x141e: 0x0831, 0x141f: 0x0d29, 0x1420: 0x0885, 0x1421: 0x1189, 0x1422: 0x0ff5, 0x1423: 0x13fd,
- 0x1424: 0x0a45, 0x1425: 0x097d, 0x1426: 0x0ed5, 0x1427: 0x0c8d, 0x1428: 0x0cb9, 0x1429: 0x0731,
- 0x142a: 0x073d, 0x142b: 0x147d, 0x142c: 0x0b4d, 0x142d: 0x0759, 0x142e: 0x0961, 0x142f: 0x0cad,
- 0x1430: 0x1425, 0x1431: 0x0c85, 0x1432: 0x10e1, 0x1433: 0x111d, 0x1434: 0x0969, 0x1435: 0x0eb5,
- 0x1436: 0x0d7d, 0x1437: 0x0d79, 0x1438: 0x1009, 0x1439: 0x089d, 0x143a: 0x09c9,
- // Block 0x51, offset 0x1440
- 0x1440: 0x076d, 0x1441: 0x0765, 0x1442: 0x0775, 0x1443: 0x16a9, 0x1444: 0x07b9, 0x1445: 0x07c9,
- 0x1446: 0x07cd, 0x1447: 0x07d5, 0x1448: 0x07dd, 0x1449: 0x07e1, 0x144a: 0x07ed, 0x144b: 0x07e5,
- 0x144c: 0x0625, 0x144d: 0x16bd, 0x144e: 0x0801, 0x144f: 0x0805, 0x1450: 0x0809, 0x1451: 0x0825,
- 0x1452: 0x16ae, 0x1453: 0x0629, 0x1454: 0x0811, 0x1455: 0x0831, 0x1456: 0x16b8, 0x1457: 0x0841,
- 0x1458: 0x0849, 0x1459: 0x07a9, 0x145a: 0x0851, 0x145b: 0x0855, 0x145c: 0x1893, 0x145d: 0x0871,
- 0x145e: 0x0879, 0x145f: 0x0631, 0x1460: 0x0891, 0x1461: 0x0895, 0x1462: 0x089d, 0x1463: 0x08a1,
- 0x1464: 0x0635, 0x1465: 0x08b9, 0x1466: 0x08bd, 0x1467: 0x08c9, 0x1468: 0x08d5, 0x1469: 0x08d9,
- 0x146a: 0x08dd, 0x146b: 0x08e5, 0x146c: 0x0905, 0x146d: 0x0909, 0x146e: 0x0911, 0x146f: 0x0921,
- 0x1470: 0x0929, 0x1471: 0x092d, 0x1472: 0x092d, 0x1473: 0x092d, 0x1474: 0x16cc, 0x1475: 0x0f05,
- 0x1476: 0x0941, 0x1477: 0x0949, 0x1478: 0x16d1, 0x1479: 0x0955, 0x147a: 0x095d, 0x147b: 0x0965,
- 0x147c: 0x098d, 0x147d: 0x0979, 0x147e: 0x0985, 0x147f: 0x0989,
- // Block 0x52, offset 0x1480
- 0x1480: 0x0991, 0x1481: 0x0999, 0x1482: 0x099d, 0x1483: 0x09a5, 0x1484: 0x09ad, 0x1485: 0x09b1,
- 0x1486: 0x09b1, 0x1487: 0x09b9, 0x1488: 0x09c1, 0x1489: 0x09c5, 0x148a: 0x09d1, 0x148b: 0x09f5,
- 0x148c: 0x09d9, 0x148d: 0x09f9, 0x148e: 0x09dd, 0x148f: 0x09e5, 0x1490: 0x087d, 0x1491: 0x0a41,
- 0x1492: 0x0a09, 0x1493: 0x0a0d, 0x1494: 0x0a11, 0x1495: 0x0a05, 0x1496: 0x0a19, 0x1497: 0x0a15,
- 0x1498: 0x0a2d, 0x1499: 0x16d6, 0x149a: 0x0a49, 0x149b: 0x0a4d, 0x149c: 0x0a55, 0x149d: 0x0a61,
- 0x149e: 0x0a69, 0x149f: 0x0a85, 0x14a0: 0x16db, 0x14a1: 0x16e0, 0x14a2: 0x0a91, 0x14a3: 0x0a95,
- 0x14a4: 0x0a99, 0x14a5: 0x0a8d, 0x14a6: 0x0aa1, 0x14a7: 0x0639, 0x14a8: 0x063d, 0x14a9: 0x0aa9,
- 0x14aa: 0x0ab1, 0x14ab: 0x0ab1, 0x14ac: 0x16e5, 0x14ad: 0x0acd, 0x14ae: 0x0ad1, 0x14af: 0x0ad5,
- 0x14b0: 0x0add, 0x14b1: 0x16ea, 0x14b2: 0x0ae5, 0x14b3: 0x0ae9, 0x14b4: 0x0bc1, 0x14b5: 0x0af1,
- 0x14b6: 0x0641, 0x14b7: 0x0afd, 0x14b8: 0x0b0d, 0x14b9: 0x0b19, 0x14ba: 0x0b15, 0x14bb: 0x16f4,
- 0x14bc: 0x0b21, 0x14bd: 0x16f9, 0x14be: 0x0b2d, 0x14bf: 0x0b29,
- // Block 0x53, offset 0x14c0
- 0x14c0: 0x0b31, 0x14c1: 0x0b41, 0x14c2: 0x0b45, 0x14c3: 0x0645, 0x14c4: 0x0b55, 0x14c5: 0x0b5d,
- 0x14c6: 0x0b61, 0x14c7: 0x0b65, 0x14c8: 0x0649, 0x14c9: 0x16fe, 0x14ca: 0x064d, 0x14cb: 0x0b81,
- 0x14cc: 0x0b85, 0x14cd: 0x0b89, 0x14ce: 0x0b91, 0x14cf: 0x18c5, 0x14d0: 0x0ba9, 0x14d1: 0x1708,
- 0x14d2: 0x1708, 0x14d3: 0x1249, 0x14d4: 0x0bb9, 0x14d5: 0x0bb9, 0x14d6: 0x0651, 0x14d7: 0x172b,
- 0x14d8: 0x17fd, 0x14d9: 0x0bc9, 0x14da: 0x0bd1, 0x14db: 0x0655, 0x14dc: 0x0be5, 0x14dd: 0x0bf5,
- 0x14de: 0x0bf9, 0x14df: 0x0c01, 0x14e0: 0x0c11, 0x14e1: 0x065d, 0x14e2: 0x0659, 0x14e3: 0x0c15,
- 0x14e4: 0x170d, 0x14e5: 0x0c19, 0x14e6: 0x0c2d, 0x14e7: 0x0c31, 0x14e8: 0x0c35, 0x14e9: 0x0c31,
- 0x14ea: 0x0c41, 0x14eb: 0x0c45, 0x14ec: 0x0c55, 0x14ed: 0x0c4d, 0x14ee: 0x0c51, 0x14ef: 0x0c59,
- 0x14f0: 0x0c5d, 0x14f1: 0x0c61, 0x14f2: 0x0c6d, 0x14f3: 0x0c71, 0x14f4: 0x0c89, 0x14f5: 0x0c91,
- 0x14f6: 0x0ca1, 0x14f7: 0x0cb5, 0x14f8: 0x171c, 0x14f9: 0x0cb1, 0x14fa: 0x0ca5, 0x14fb: 0x0cbd,
- 0x14fc: 0x0cc5, 0x14fd: 0x0cd9, 0x14fe: 0x1721, 0x14ff: 0x0ce1,
- // Block 0x54, offset 0x1500
- 0x1500: 0x0cd5, 0x1501: 0x0ccd, 0x1502: 0x0661, 0x1503: 0x0ce9, 0x1504: 0x0cf1, 0x1505: 0x0cf9,
- 0x1506: 0x0ced, 0x1507: 0x0665, 0x1508: 0x0d09, 0x1509: 0x0d11, 0x150a: 0x1726, 0x150b: 0x0d3d,
- 0x150c: 0x0d71, 0x150d: 0x0d4d, 0x150e: 0x0671, 0x150f: 0x0d59, 0x1510: 0x066d, 0x1511: 0x0669,
- 0x1512: 0x0835, 0x1513: 0x0839, 0x1514: 0x0d75, 0x1515: 0x0d5d, 0x1516: 0x121d, 0x1517: 0x06d5,
- 0x1518: 0x0d81, 0x1519: 0x0d85, 0x151a: 0x0d89, 0x151b: 0x0d9d, 0x151c: 0x0d95, 0x151d: 0x173f,
- 0x151e: 0x0675, 0x151f: 0x0db1, 0x1520: 0x0da5, 0x1521: 0x0dc1, 0x1522: 0x0dc9, 0x1523: 0x1749,
- 0x1524: 0x0dcd, 0x1525: 0x0db9, 0x1526: 0x0dd5, 0x1527: 0x0679, 0x1528: 0x0dd9, 0x1529: 0x0ddd,
- 0x152a: 0x0de1, 0x152b: 0x0ded, 0x152c: 0x174e, 0x152d: 0x0df5, 0x152e: 0x067d, 0x152f: 0x0e01,
- 0x1530: 0x1753, 0x1531: 0x0e05, 0x1532: 0x0681, 0x1533: 0x0e11, 0x1534: 0x0e1d, 0x1535: 0x0e29,
- 0x1536: 0x0e2d, 0x1537: 0x1758, 0x1538: 0x16ef, 0x1539: 0x175d, 0x153a: 0x0e4d, 0x153b: 0x1762,
- 0x153c: 0x0e59, 0x153d: 0x0e61, 0x153e: 0x0e51, 0x153f: 0x0e6d,
- // Block 0x55, offset 0x1540
- 0x1540: 0x0e7d, 0x1541: 0x0e8d, 0x1542: 0x0e81, 0x1543: 0x0e85, 0x1544: 0x0e91, 0x1545: 0x0e95,
- 0x1546: 0x1767, 0x1547: 0x0e79, 0x1548: 0x0ead, 0x1549: 0x0eb1, 0x154a: 0x0685, 0x154b: 0x0ec5,
- 0x154c: 0x0ec1, 0x154d: 0x176c, 0x154e: 0x0ea5, 0x154f: 0x0ee1, 0x1550: 0x1771, 0x1551: 0x1776,
- 0x1552: 0x0ee5, 0x1553: 0x0ef9, 0x1554: 0x0ef5, 0x1555: 0x0ef1, 0x1556: 0x0689, 0x1557: 0x0efd,
- 0x1558: 0x0f0d, 0x1559: 0x0f09, 0x155a: 0x0f15, 0x155b: 0x16b3, 0x155c: 0x0f25, 0x155d: 0x177b,
- 0x155e: 0x0f31, 0x155f: 0x1785, 0x1560: 0x0f45, 0x1561: 0x0f51, 0x1562: 0x0f65, 0x1563: 0x178a,
- 0x1564: 0x0f79, 0x1565: 0x0f7d, 0x1566: 0x178f, 0x1567: 0x1794, 0x1568: 0x0f99, 0x1569: 0x0fa9,
- 0x156a: 0x068d, 0x156b: 0x0fad, 0x156c: 0x0691, 0x156d: 0x0691, 0x156e: 0x0fc5, 0x156f: 0x0fc9,
- 0x1570: 0x0fd1, 0x1571: 0x0fd5, 0x1572: 0x0fe1, 0x1573: 0x0695, 0x1574: 0x0ff9, 0x1575: 0x1799,
- 0x1576: 0x1015, 0x1577: 0x179e, 0x1578: 0x1021, 0x1579: 0x1703, 0x157a: 0x1031, 0x157b: 0x17a3,
- 0x157c: 0x17a8, 0x157d: 0x17ad, 0x157e: 0x0699, 0x157f: 0x069d,
- // Block 0x56, offset 0x1580
- 0x1580: 0x1069, 0x1581: 0x17b7, 0x1582: 0x17b2, 0x1583: 0x17bc, 0x1584: 0x17c1, 0x1585: 0x1071,
- 0x1586: 0x1075, 0x1587: 0x1075, 0x1588: 0x107d, 0x1589: 0x06a5, 0x158a: 0x1081, 0x158b: 0x06a9,
- 0x158c: 0x06ad, 0x158d: 0x17cb, 0x158e: 0x1095, 0x158f: 0x109d, 0x1590: 0x10a9, 0x1591: 0x06b1,
- 0x1592: 0x17d0, 0x1593: 0x10cd, 0x1594: 0x17d5, 0x1595: 0x17da, 0x1596: 0x10ed, 0x1597: 0x1105,
- 0x1598: 0x06b5, 0x1599: 0x110d, 0x159a: 0x1111, 0x159b: 0x1115, 0x159c: 0x17df, 0x159d: 0x17e4,
- 0x159e: 0x17e4, 0x159f: 0x112d, 0x15a0: 0x06b9, 0x15a1: 0x17e9, 0x15a2: 0x1141, 0x15a3: 0x1145,
- 0x15a4: 0x06bd, 0x15a5: 0x17ee, 0x15a6: 0x1161, 0x15a7: 0x06c1, 0x15a8: 0x1171, 0x15a9: 0x1169,
- 0x15aa: 0x1179, 0x15ab: 0x17f8, 0x15ac: 0x1191, 0x15ad: 0x06c5, 0x15ae: 0x119d, 0x15af: 0x11a5,
- 0x15b0: 0x11b5, 0x15b1: 0x06c9, 0x15b2: 0x1802, 0x15b3: 0x1807, 0x15b4: 0x06cd, 0x15b5: 0x180c,
- 0x15b6: 0x11cd, 0x15b7: 0x1811, 0x15b8: 0x11d9, 0x15b9: 0x11e5, 0x15ba: 0x11ed, 0x15bb: 0x1816,
- 0x15bc: 0x181b, 0x15bd: 0x1201, 0x15be: 0x1820, 0x15bf: 0x1209,
- // Block 0x57, offset 0x15c0
- 0x15c0: 0x1730, 0x15c1: 0x06d1, 0x15c2: 0x1221, 0x15c3: 0x1225, 0x15c4: 0x06d9, 0x15c5: 0x1229,
- 0x15c6: 0x0aa5, 0x15c7: 0x1825, 0x15c8: 0x182a, 0x15c9: 0x1735, 0x15ca: 0x173a, 0x15cb: 0x1249,
- 0x15cc: 0x124d, 0x15cd: 0x1465, 0x15ce: 0x06dd, 0x15cf: 0x1279, 0x15d0: 0x1275, 0x15d1: 0x127d,
- 0x15d2: 0x08b1, 0x15d3: 0x1281, 0x15d4: 0x1285, 0x15d5: 0x1289, 0x15d6: 0x1291, 0x15d7: 0x182f,
- 0x15d8: 0x128d, 0x15d9: 0x1295, 0x15da: 0x12a9, 0x15db: 0x12ad, 0x15dc: 0x1299, 0x15dd: 0x12b1,
- 0x15de: 0x12c5, 0x15df: 0x12d9, 0x15e0: 0x12a5, 0x15e1: 0x12b9, 0x15e2: 0x12bd, 0x15e3: 0x12c1,
- 0x15e4: 0x1834, 0x15e5: 0x183e, 0x15e6: 0x1839, 0x15e7: 0x06e1, 0x15e8: 0x12e1, 0x15e9: 0x12e5,
- 0x15ea: 0x12ed, 0x15eb: 0x1852, 0x15ec: 0x12f1, 0x15ed: 0x1843, 0x15ee: 0x06e5, 0x15ef: 0x06e9,
- 0x15f0: 0x1848, 0x15f1: 0x184d, 0x15f2: 0x06ed, 0x15f3: 0x1311, 0x15f4: 0x1315, 0x15f5: 0x1319,
- 0x15f6: 0x131d, 0x15f7: 0x1329, 0x15f8: 0x1325, 0x15f9: 0x1331, 0x15fa: 0x132d, 0x15fb: 0x133d,
- 0x15fc: 0x1335, 0x15fd: 0x1339, 0x15fe: 0x1341, 0x15ff: 0x06f1,
- // Block 0x58, offset 0x1600
- 0x1600: 0x1349, 0x1601: 0x134d, 0x1602: 0x06f5, 0x1603: 0x135d, 0x1604: 0x1361, 0x1605: 0x1857,
- 0x1606: 0x136d, 0x1607: 0x1371, 0x1608: 0x06f9, 0x1609: 0x137d, 0x160a: 0x062d, 0x160b: 0x185c,
- 0x160c: 0x1861, 0x160d: 0x06fd, 0x160e: 0x0701, 0x160f: 0x13a9, 0x1610: 0x13c1, 0x1611: 0x13dd,
- 0x1612: 0x13ed, 0x1613: 0x1866, 0x1614: 0x1401, 0x1615: 0x1405, 0x1616: 0x141d, 0x1617: 0x1429,
- 0x1618: 0x1870, 0x1619: 0x16c2, 0x161a: 0x1435, 0x161b: 0x1431, 0x161c: 0x143d, 0x161d: 0x16c7,
- 0x161e: 0x1449, 0x161f: 0x1455, 0x1620: 0x1875, 0x1621: 0x187a, 0x1622: 0x1495, 0x1623: 0x14a1,
- 0x1624: 0x14a9, 0x1625: 0x187f, 0x1626: 0x14ad, 0x1627: 0x14d5, 0x1628: 0x14e1, 0x1629: 0x14e5,
- 0x162a: 0x14dd, 0x162b: 0x14f1, 0x162c: 0x14f5, 0x162d: 0x1884, 0x162e: 0x1501, 0x162f: 0x0705,
- 0x1630: 0x1509, 0x1631: 0x1889, 0x1632: 0x0709, 0x1633: 0x1541, 0x1634: 0x0b35, 0x1635: 0x1559,
- 0x1636: 0x188e, 0x1637: 0x1898, 0x1638: 0x070d, 0x1639: 0x0711, 0x163a: 0x1581, 0x163b: 0x189d,
- 0x163c: 0x0715, 0x163d: 0x18a2, 0x163e: 0x1599, 0x163f: 0x1599,
- // Block 0x59, offset 0x1640
- 0x1640: 0x15a1, 0x1641: 0x18a7, 0x1642: 0x15b9, 0x1643: 0x0719, 0x1644: 0x15c9, 0x1645: 0x15d5,
- 0x1646: 0x15dd, 0x1647: 0x15e5, 0x1648: 0x071d, 0x1649: 0x18ac, 0x164a: 0x15f9, 0x164b: 0x1615,
- 0x164c: 0x1621, 0x164d: 0x0721, 0x164e: 0x0725, 0x164f: 0x1625, 0x1650: 0x18b1, 0x1651: 0x0729,
- 0x1652: 0x18b6, 0x1653: 0x18bb, 0x1654: 0x18c0, 0x1655: 0x1649, 0x1656: 0x072d, 0x1657: 0x165d,
- 0x1658: 0x1665, 0x1659: 0x1669, 0x165a: 0x1671, 0x165b: 0x1679, 0x165c: 0x1681, 0x165d: 0x18ca,
-}
-
-// nfkcSparseOffset: 128 entries, 256 bytes
-var nfkcSparseOffset = []uint16{0x0, 0xe, 0x12, 0x1b, 0x25, 0x35, 0x37, 0x3c, 0x47, 0x56, 0x63, 0x6b, 0x6f, 0x74, 0x76, 0x85, 0x8d, 0x94, 0x97, 0x9f, 0xa3, 0xa7, 0xa9, 0xab, 0xb4, 0xb8, 0xbf, 0xc4, 0xc7, 0xd1, 0xd3, 0xda, 0xe2, 0xe6, 0xe8, 0xeb, 0xef, 0xf5, 0x106, 0x112, 0x114, 0x11a, 0x11c, 0x11e, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12b, 0x12e, 0x130, 0x133, 0x136, 0x13a, 0x143, 0x145, 0x148, 0x14a, 0x154, 0x15f, 0x16e, 0x17c, 0x18a, 0x19a, 0x1a8, 0x1af, 0x1b5, 0x1c4, 0x1c8, 0x1ca, 0x1ce, 0x1d0, 0x1d3, 0x1d5, 0x1d8, 0x1da, 0x1dd, 0x1df, 0x1e1, 0x1e3, 0x1ef, 0x1f8, 0x1ff, 0x20c, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21c, 0x21e, 0x220, 0x222, 0x224, 0x22a, 0x22d, 0x22f, 0x231, 0x233, 0x235, 0x244, 0x246, 0x24c, 0x254, 0x25b, 0x25e, 0x26b, 0x275, 0x277, 0x279, 0x27d, 0x282, 0x28e, 0x293, 0x29c, 0x2a2, 0x2a7, 0x2ab, 0x2b0, 0x2b4, 0x2c4, 0x2d2, 0x2e0, 0x2ee, 0x2f8, 0x2fa}
-
-// nfkcSparseValues: 772 entries, 3088 bytes
-var nfkcSparseValues = [772]valueRange{
- // Block 0x0, offset 0x1
- {value: 0x0002, lo: 0x0d},
- {value: 0x0001, lo: 0xa0, hi: 0xa0},
- {value: 0x425e, lo: 0xa8, hi: 0xa8},
- {value: 0x0083, lo: 0xaa, hi: 0xaa},
- {value: 0x424a, lo: 0xaf, hi: 0xaf},
- {value: 0x0025, lo: 0xb2, hi: 0xb3},
- {value: 0x4240, lo: 0xb4, hi: 0xb4},
- {value: 0x01dc, lo: 0xb5, hi: 0xb5},
- {value: 0x4277, lo: 0xb8, hi: 0xb8},
- {value: 0x0023, lo: 0xb9, hi: 0xb9},
- {value: 0x009f, lo: 0xba, hi: 0xba},
- {value: 0x235e, lo: 0xbc, hi: 0xbc},
- {value: 0x2352, lo: 0xbd, hi: 0xbd},
- {value: 0x23f4, lo: 0xbe, hi: 0xbe},
- // Block 0x1, offset 0x2
- {value: 0x0091, lo: 0x03},
- {value: 0x46c8, lo: 0xa0, hi: 0xa1},
- {value: 0x46fa, lo: 0xaf, hi: 0xb0},
- {value: 0x8800, lo: 0xb7, hi: 0xb7},
- // Block 0x2, offset 0x3
- {value: 0x0003, lo: 0x08},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x0091, lo: 0xb0, hi: 0xb0},
- {value: 0x011c, lo: 0xb1, hi: 0xb1},
- {value: 0x0095, lo: 0xb2, hi: 0xb2},
- {value: 0x00a5, lo: 0xb3, hi: 0xb3},
- {value: 0x0143, lo: 0xb4, hi: 0xb6},
- {value: 0x00af, lo: 0xb7, hi: 0xb7},
- {value: 0x00b3, lo: 0xb8, hi: 0xb8},
- // Block 0x3, offset 0x4
- {value: 0x000a, lo: 0x09},
- {value: 0x4254, lo: 0x98, hi: 0x98},
- {value: 0x4259, lo: 0x99, hi: 0x9a},
- {value: 0x427c, lo: 0x9b, hi: 0x9b},
- {value: 0x4245, lo: 0x9c, hi: 0x9c},
- {value: 0x4268, lo: 0x9d, hi: 0x9d},
- {value: 0x0116, lo: 0xa0, hi: 0xa0},
- {value: 0x0099, lo: 0xa1, hi: 0xa1},
- {value: 0x00a7, lo: 0xa2, hi: 0xa3},
- {value: 0x0167, lo: 0xa4, hi: 0xa4},
- // Block 0x4, offset 0x5
- {value: 0x0000, lo: 0x0f},
- {value: 0x8800, lo: 0x83, hi: 0x83},
- {value: 0x8800, lo: 0x87, hi: 0x87},
- {value: 0x8800, lo: 0x8b, hi: 0x8b},
- {value: 0x8800, lo: 0x8d, hi: 0x8d},
- {value: 0x378f, lo: 0x90, hi: 0x90},
- {value: 0x379b, lo: 0x91, hi: 0x91},
- {value: 0x3789, lo: 0x93, hi: 0x93},
- {value: 0x8800, lo: 0x96, hi: 0x96},
- {value: 0x3801, lo: 0x97, hi: 0x97},
- {value: 0x37cb, lo: 0x9c, hi: 0x9c},
- {value: 0x37b3, lo: 0x9d, hi: 0x9d},
- {value: 0x37dd, lo: 0x9e, hi: 0x9e},
- {value: 0x8800, lo: 0xb4, hi: 0xb5},
- {value: 0x3807, lo: 0xb6, hi: 0xb6},
- {value: 0x380d, lo: 0xb7, hi: 0xb7},
- // Block 0x5, offset 0x6
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x83, hi: 0x87},
- // Block 0x6, offset 0x7
- {value: 0x0001, lo: 0x04},
- {value: 0x8018, lo: 0x81, hi: 0x82},
- {value: 0x80e6, lo: 0x84, hi: 0x84},
- {value: 0x80dc, lo: 0x85, hi: 0x85},
- {value: 0x8012, lo: 0x87, hi: 0x87},
- // Block 0x7, offset 0x8
- {value: 0x0000, lo: 0x0a},
- {value: 0x80e6, lo: 0x90, hi: 0x97},
- {value: 0x801e, lo: 0x98, hi: 0x98},
- {value: 0x801f, lo: 0x99, hi: 0x99},
- {value: 0x8020, lo: 0x9a, hi: 0x9a},
- {value: 0x382b, lo: 0xa2, hi: 0xa2},
- {value: 0x3831, lo: 0xa3, hi: 0xa3},
- {value: 0x383d, lo: 0xa4, hi: 0xa4},
- {value: 0x3837, lo: 0xa5, hi: 0xa5},
- {value: 0x3843, lo: 0xa6, hi: 0xa6},
- {value: 0x8800, lo: 0xa7, hi: 0xa7},
- // Block 0x8, offset 0x9
- {value: 0x0000, lo: 0x0e},
- {value: 0x3855, lo: 0x80, hi: 0x80},
- {value: 0x8800, lo: 0x81, hi: 0x81},
- {value: 0x3849, lo: 0x82, hi: 0x82},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x384f, lo: 0x93, hi: 0x93},
- {value: 0x8800, lo: 0x95, hi: 0x95},
- {value: 0x80e6, lo: 0x96, hi: 0x9c},
- {value: 0x80e6, lo: 0x9f, hi: 0xa2},
- {value: 0x80dc, lo: 0xa3, hi: 0xa3},
- {value: 0x80e6, lo: 0xa4, hi: 0xa4},
- {value: 0x80e6, lo: 0xa7, hi: 0xa8},
- {value: 0x80dc, lo: 0xaa, hi: 0xaa},
- {value: 0x80e6, lo: 0xab, hi: 0xac},
- {value: 0x80dc, lo: 0xad, hi: 0xad},
- // Block 0x9, offset 0xa
- {value: 0x0000, lo: 0x0c},
- {value: 0x8024, lo: 0x91, hi: 0x91},
- {value: 0x80e6, lo: 0xb0, hi: 0xb0},
- {value: 0x80dc, lo: 0xb1, hi: 0xb1},
- {value: 0x80e6, lo: 0xb2, hi: 0xb3},
- {value: 0x80dc, lo: 0xb4, hi: 0xb4},
- {value: 0x80e6, lo: 0xb5, hi: 0xb6},
- {value: 0x80dc, lo: 0xb7, hi: 0xb9},
- {value: 0x80e6, lo: 0xba, hi: 0xba},
- {value: 0x80dc, lo: 0xbb, hi: 0xbc},
- {value: 0x80e6, lo: 0xbd, hi: 0xbd},
- {value: 0x80dc, lo: 0xbe, hi: 0xbe},
- {value: 0x80e6, lo: 0xbf, hi: 0xbf},
- // Block 0xa, offset 0xb
- {value: 0x000a, lo: 0x07},
- {value: 0x80e6, lo: 0x80, hi: 0x80},
- {value: 0x80e6, lo: 0x81, hi: 0x81},
- {value: 0x80dc, lo: 0x82, hi: 0x83},
- {value: 0x80dc, lo: 0x84, hi: 0x85},
- {value: 0x80dc, lo: 0x86, hi: 0x87},
- {value: 0x80dc, lo: 0x88, hi: 0x89},
- {value: 0x80e6, lo: 0x8a, hi: 0x8a},
- // Block 0xb, offset 0xc
- {value: 0x0000, lo: 0x03},
- {value: 0x80e6, lo: 0xab, hi: 0xb1},
- {value: 0x80dc, lo: 0xb2, hi: 0xb2},
- {value: 0x80e6, lo: 0xb3, hi: 0xb3},
- // Block 0xc, offset 0xd
- {value: 0x0000, lo: 0x04},
- {value: 0x80e6, lo: 0x96, hi: 0x99},
- {value: 0x80e6, lo: 0x9b, hi: 0xa3},
- {value: 0x80e6, lo: 0xa5, hi: 0xa7},
- {value: 0x80e6, lo: 0xa9, hi: 0xad},
- // Block 0xd, offset 0xe
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0x99, hi: 0x9b},
- // Block 0xe, offset 0xf
- {value: 0x0000, lo: 0x0e},
- {value: 0x80e6, lo: 0xa4, hi: 0xa5},
- {value: 0x80dc, lo: 0xa6, hi: 0xa6},
- {value: 0x80e6, lo: 0xa7, hi: 0xa8},
- {value: 0x80dc, lo: 0xa9, hi: 0xa9},
- {value: 0x80e6, lo: 0xaa, hi: 0xac},
- {value: 0x80dc, lo: 0xad, hi: 0xaf},
- {value: 0x801b, lo: 0xb0, hi: 0xb0},
- {value: 0x801c, lo: 0xb1, hi: 0xb1},
- {value: 0x801d, lo: 0xb2, hi: 0xb2},
- {value: 0x80e6, lo: 0xb3, hi: 0xb5},
- {value: 0x80dc, lo: 0xb6, hi: 0xb6},
- {value: 0x80e6, lo: 0xb7, hi: 0xb8},
- {value: 0x80dc, lo: 0xb9, hi: 0xba},
- {value: 0x80e6, lo: 0xbb, hi: 0xbe},
- // Block 0xf, offset 0x10
- {value: 0x0000, lo: 0x07},
- {value: 0x8800, lo: 0xa8, hi: 0xa8},
- {value: 0x3ec2, lo: 0xa9, hi: 0xa9},
- {value: 0x8800, lo: 0xb0, hi: 0xb0},
- {value: 0x3eca, lo: 0xb1, hi: 0xb1},
- {value: 0x8800, lo: 0xb3, hi: 0xb3},
- {value: 0x3ed2, lo: 0xb4, hi: 0xb4},
- {value: 0x8607, lo: 0xbc, hi: 0xbc},
- // Block 0x10, offset 0x11
- {value: 0x0008, lo: 0x06},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x80e6, lo: 0x91, hi: 0x91},
- {value: 0x80dc, lo: 0x92, hi: 0x92},
- {value: 0x80e6, lo: 0x93, hi: 0x93},
- {value: 0x80e6, lo: 0x94, hi: 0x94},
- {value: 0x4502, lo: 0x98, hi: 0x9f},
- // Block 0x11, offset 0x12
- {value: 0x0000, lo: 0x02},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- {value: 0x8600, lo: 0xbe, hi: 0xbe},
- // Block 0x12, offset 0x13
- {value: 0x0007, lo: 0x07},
- {value: 0x8800, lo: 0x87, hi: 0x87},
- {value: 0x18cf, lo: 0x8b, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x97, hi: 0x97},
- {value: 0x4542, lo: 0x9c, hi: 0x9c},
- {value: 0x454a, lo: 0x9d, hi: 0x9d},
- {value: 0x4552, lo: 0x9f, hi: 0x9f},
- // Block 0x13, offset 0x14
- {value: 0x0000, lo: 0x03},
- {value: 0x457a, lo: 0xb3, hi: 0xb3},
- {value: 0x4582, lo: 0xb6, hi: 0xb6},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- // Block 0x14, offset 0x15
- {value: 0x0008, lo: 0x03},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x455a, lo: 0x99, hi: 0x9b},
- {value: 0x4572, lo: 0x9e, hi: 0x9e},
- // Block 0x15, offset 0x16
- {value: 0x0000, lo: 0x01},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- // Block 0x16, offset 0x17
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- // Block 0x17, offset 0x18
- {value: 0x0000, lo: 0x08},
- {value: 0x8800, lo: 0x87, hi: 0x87},
- {value: 0x18e4, lo: 0x88, hi: 0x88},
- {value: 0x18dd, lo: 0x8b, hi: 0x8b},
- {value: 0x18eb, lo: 0x8c, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x96, hi: 0x97},
- {value: 0x458a, lo: 0x9c, hi: 0x9c},
- {value: 0x4592, lo: 0x9d, hi: 0x9d},
- // Block 0x18, offset 0x19
- {value: 0x0000, lo: 0x03},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x18f2, lo: 0x94, hi: 0x94},
- {value: 0x8600, lo: 0xbe, hi: 0xbe},
- // Block 0x19, offset 0x1a
- {value: 0x0000, lo: 0x06},
- {value: 0x8800, lo: 0x86, hi: 0x87},
- {value: 0x18f9, lo: 0x8a, hi: 0x8a},
- {value: 0x1907, lo: 0x8b, hi: 0x8b},
- {value: 0x1900, lo: 0x8c, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x97, hi: 0x97},
- // Block 0x1a, offset 0x1b
- {value: 0x0607, lo: 0x04},
- {value: 0x8800, lo: 0x86, hi: 0x86},
- {value: 0x3eda, lo: 0x88, hi: 0x88},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8054, lo: 0x95, hi: 0x96},
- // Block 0x1b, offset 0x1c
- {value: 0x0000, lo: 0x02},
- {value: 0x8007, lo: 0xbc, hi: 0xbc},
- {value: 0x8800, lo: 0xbf, hi: 0xbf},
- // Block 0x1c, offset 0x1d
- {value: 0x0000, lo: 0x09},
- {value: 0x190e, lo: 0x80, hi: 0x80},
- {value: 0x8600, lo: 0x82, hi: 0x82},
- {value: 0x8800, lo: 0x86, hi: 0x86},
- {value: 0x1915, lo: 0x87, hi: 0x87},
- {value: 0x191c, lo: 0x88, hi: 0x88},
- {value: 0x2e66, lo: 0x8a, hi: 0x8a},
- {value: 0x19a5, lo: 0x8b, hi: 0x8b},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x95, hi: 0x96},
- // Block 0x1d, offset 0x1e
- {value: 0x0000, lo: 0x01},
- {value: 0x8600, lo: 0xbe, hi: 0xbe},
- // Block 0x1e, offset 0x1f
- {value: 0x0000, lo: 0x06},
- {value: 0x8800, lo: 0x86, hi: 0x87},
- {value: 0x1923, lo: 0x8a, hi: 0x8a},
- {value: 0x1931, lo: 0x8b, hi: 0x8b},
- {value: 0x192a, lo: 0x8c, hi: 0x8c},
- {value: 0x8009, lo: 0x8d, hi: 0x8d},
- {value: 0x8600, lo: 0x97, hi: 0x97},
- // Block 0x1f, offset 0x20
- {value: 0x0007, lo: 0x07},
- {value: 0x8609, lo: 0x8a, hi: 0x8a},
- {value: 0x8600, lo: 0x8f, hi: 0x8f},
- {value: 0x8800, lo: 0x99, hi: 0x99},
- {value: 0x3ee2, lo: 0x9a, hi: 0x9a},
- {value: 0x2e6d, lo: 0x9c, hi: 0x9d},
- {value: 0x1938, lo: 0x9e, hi: 0x9e},
- {value: 0x8600, lo: 0x9f, hi: 0x9f},
- // Block 0x20, offset 0x21
- {value: 0x0000, lo: 0x03},
- {value: 0x2763, lo: 0xb3, hi: 0xb3},
- {value: 0x8067, lo: 0xb8, hi: 0xb9},
- {value: 0x8009, lo: 0xba, hi: 0xba},
- // Block 0x21, offset 0x22
- {value: 0x0000, lo: 0x01},
- {value: 0x806b, lo: 0x88, hi: 0x8b},
- // Block 0x22, offset 0x23
- {value: 0x0000, lo: 0x02},
- {value: 0x2778, lo: 0xb3, hi: 0xb3},
- {value: 0x8076, lo: 0xb8, hi: 0xb9},
- // Block 0x23, offset 0x24
- {value: 0x0000, lo: 0x03},
- {value: 0x807a, lo: 0x88, hi: 0x8b},
- {value: 0x276a, lo: 0x9c, hi: 0x9c},
- {value: 0x2771, lo: 0x9d, hi: 0x9d},
- // Block 0x24, offset 0x25
- {value: 0x0000, lo: 0x05},
- {value: 0x0305, lo: 0x8c, hi: 0x8c},
- {value: 0x80dc, lo: 0x98, hi: 0x99},
- {value: 0x80dc, lo: 0xb5, hi: 0xb5},
- {value: 0x80dc, lo: 0xb7, hi: 0xb7},
- {value: 0x80d8, lo: 0xb9, hi: 0xb9},
- // Block 0x25, offset 0x26
- {value: 0x0000, lo: 0x10},
- {value: 0x2786, lo: 0x83, hi: 0x83},
- {value: 0x278d, lo: 0x8d, hi: 0x8d},
- {value: 0x2794, lo: 0x92, hi: 0x92},
- {value: 0x279b, lo: 0x97, hi: 0x97},
- {value: 0x27a2, lo: 0x9c, hi: 0x9c},
- {value: 0x277f, lo: 0xa9, hi: 0xa9},
- {value: 0x8081, lo: 0xb1, hi: 0xb1},
- {value: 0x8082, lo: 0xb2, hi: 0xb2},
- {value: 0x49b6, lo: 0xb3, hi: 0xb3},
- {value: 0x8084, lo: 0xb4, hi: 0xb4},
- {value: 0x49bf, lo: 0xb5, hi: 0xb5},
- {value: 0x459a, lo: 0xb6, hi: 0xb6},
- {value: 0x45da, lo: 0xb7, hi: 0xb7},
- {value: 0x45a2, lo: 0xb8, hi: 0xb8},
- {value: 0x45e5, lo: 0xb9, hi: 0xb9},
- {value: 0x8082, lo: 0xba, hi: 0xbd},
- // Block 0x26, offset 0x27
- {value: 0x0000, lo: 0x0b},
- {value: 0x8082, lo: 0x80, hi: 0x80},
- {value: 0x49c8, lo: 0x81, hi: 0x81},
- {value: 0x80e6, lo: 0x82, hi: 0x83},
- {value: 0x8009, lo: 0x84, hi: 0x84},
- {value: 0x80e6, lo: 0x86, hi: 0x87},
- {value: 0x27b0, lo: 0x93, hi: 0x93},
- {value: 0x27b7, lo: 0x9d, hi: 0x9d},
- {value: 0x27be, lo: 0xa2, hi: 0xa2},
- {value: 0x27c5, lo: 0xa7, hi: 0xa7},
- {value: 0x27cc, lo: 0xac, hi: 0xac},
- {value: 0x27a9, lo: 0xb9, hi: 0xb9},
- // Block 0x27, offset 0x28
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0x86, hi: 0x86},
- // Block 0x28, offset 0x29
- {value: 0x0000, lo: 0x05},
- {value: 0x8800, lo: 0xa5, hi: 0xa5},
- {value: 0x193f, lo: 0xa6, hi: 0xa6},
- {value: 0x8600, lo: 0xae, hi: 0xae},
- {value: 0x8007, lo: 0xb7, hi: 0xb7},
- {value: 0x8009, lo: 0xb9, hi: 0xba},
- // Block 0x29, offset 0x2a
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0x8d, hi: 0x8d},
- // Block 0x2a, offset 0x2b
- {value: 0x0000, lo: 0x01},
- {value: 0x0309, lo: 0xbc, hi: 0xbc},
- // Block 0x2b, offset 0x2c
- {value: 0x0000, lo: 0x01},
- {value: 0x8800, lo: 0x80, hi: 0x92},
- // Block 0x2c, offset 0x2d
- {value: 0x0000, lo: 0x01},
- {value: 0x8e00, lo: 0xa1, hi: 0xb5},
- // Block 0x2d, offset 0x2e
- {value: 0x0000, lo: 0x01},
- {value: 0x8600, lo: 0xa8, hi: 0xbf},
- // Block 0x2e, offset 0x2f
- {value: 0x0000, lo: 0x01},
- {value: 0x8600, lo: 0x80, hi: 0x82},
- // Block 0x2f, offset 0x30
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x9d, hi: 0x9f},
- // Block 0x30, offset 0x31
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0x94, hi: 0x94},
- {value: 0x8009, lo: 0xb4, hi: 0xb4},
- // Block 0x31, offset 0x32
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0x92, hi: 0x92},
- {value: 0x80e6, lo: 0x9d, hi: 0x9d},
- // Block 0x32, offset 0x33
- {value: 0x0000, lo: 0x01},
- {value: 0x80e4, lo: 0xa9, hi: 0xa9},
- // Block 0x33, offset 0x34
- {value: 0x0008, lo: 0x02},
- {value: 0x80de, lo: 0xb9, hi: 0xba},
- {value: 0x80dc, lo: 0xbb, hi: 0xbb},
- // Block 0x34, offset 0x35
- {value: 0x0000, lo: 0x02},
- {value: 0x80e6, lo: 0x97, hi: 0x97},
- {value: 0x80dc, lo: 0x98, hi: 0x98},
- // Block 0x35, offset 0x36
- {value: 0x0000, lo: 0x03},
- {value: 0x8009, lo: 0xa0, hi: 0xa0},
- {value: 0x80e6, lo: 0xb5, hi: 0xbc},
- {value: 0x80dc, lo: 0xbf, hi: 0xbf},
- // Block 0x36, offset 0x37
- {value: 0x0000, lo: 0x08},
- {value: 0x197e, lo: 0x80, hi: 0x80},
- {value: 0x1985, lo: 0x81, hi: 0x81},
- {value: 0x8800, lo: 0x82, hi: 0x82},
- {value: 0x198c, lo: 0x83, hi: 0x83},
- {value: 0x8009, lo: 0x84, hi: 0x84},
- {value: 0x80e6, lo: 0xab, hi: 0xab},
- {value: 0x80dc, lo: 0xac, hi: 0xac},
- {value: 0x80e6, lo: 0xad, hi: 0xb3},
- // Block 0x37, offset 0x38
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0xaa, hi: 0xab},
- // Block 0x38, offset 0x39
- {value: 0x0000, lo: 0x02},
- {value: 0x8007, lo: 0xa6, hi: 0xa6},
- {value: 0x8009, lo: 0xb2, hi: 0xb3},
- // Block 0x39, offset 0x3a
- {value: 0x0000, lo: 0x01},
- {value: 0x8007, lo: 0xb7, hi: 0xb7},
- // Block 0x3a, offset 0x3b
- {value: 0x0000, lo: 0x09},
- {value: 0x80e6, lo: 0x90, hi: 0x92},
- {value: 0x8001, lo: 0x94, hi: 0x94},
- {value: 0x80dc, lo: 0x95, hi: 0x99},
- {value: 0x80e6, lo: 0x9a, hi: 0x9b},
- {value: 0x80dc, lo: 0x9c, hi: 0x9f},
- {value: 0x80e6, lo: 0xa0, hi: 0xa0},
- {value: 0x8001, lo: 0xa2, hi: 0xa8},
- {value: 0x80dc, lo: 0xad, hi: 0xad},
- {value: 0x80e6, lo: 0xb4, hi: 0xb4},
- // Block 0x3b, offset 0x3c
- {value: 0x0002, lo: 0x0a},
- {value: 0x0043, lo: 0xac, hi: 0xac},
- {value: 0x00d4, lo: 0xad, hi: 0xad},
- {value: 0x0045, lo: 0xae, hi: 0xae},
- {value: 0x0049, lo: 0xb0, hi: 0xb1},
- {value: 0x00e9, lo: 0xb2, hi: 0xb2},
- {value: 0x004f, lo: 0xb3, hi: 0xba},
- {value: 0x005f, lo: 0xbc, hi: 0xbc},
- {value: 0x00f2, lo: 0xbd, hi: 0xbd},
- {value: 0x0061, lo: 0xbe, hi: 0xbe},
- {value: 0x0065, lo: 0xbf, hi: 0xbf},
- // Block 0x3c, offset 0x3d
- {value: 0x0000, lo: 0x0e},
- {value: 0x80e6, lo: 0x80, hi: 0x81},
- {value: 0x80dc, lo: 0x82, hi: 0x82},
- {value: 0x80e6, lo: 0x83, hi: 0x89},
- {value: 0x80dc, lo: 0x8a, hi: 0x8a},
- {value: 0x80e6, lo: 0x8b, hi: 0x8c},
- {value: 0x80ea, lo: 0x8d, hi: 0x8d},
- {value: 0x80d6, lo: 0x8e, hi: 0x8e},
- {value: 0x80dc, lo: 0x8f, hi: 0x8f},
- {value: 0x80ca, lo: 0x90, hi: 0x90},
- {value: 0x80e6, lo: 0x91, hi: 0xa6},
- {value: 0x80e9, lo: 0xbc, hi: 0xbc},
- {value: 0x80dc, lo: 0xbd, hi: 0xbd},
- {value: 0x80e6, lo: 0xbe, hi: 0xbe},
- {value: 0x80dc, lo: 0xbf, hi: 0xbf},
- // Block 0x3d, offset 0x3e
- {value: 0x0000, lo: 0x0d},
- {value: 0x0001, lo: 0x80, hi: 0x8a},
- {value: 0x04ad, lo: 0x91, hi: 0x91},
- {value: 0x4281, lo: 0x97, hi: 0x97},
- {value: 0x001d, lo: 0xa4, hi: 0xa4},
- {value: 0x19b5, lo: 0xa5, hi: 0xa5},
- {value: 0x1c9e, lo: 0xa6, hi: 0xa6},
- {value: 0x0001, lo: 0xaf, hi: 0xaf},
- {value: 0x283c, lo: 0xb3, hi: 0xb3},
- {value: 0x29a9, lo: 0xb4, hi: 0xb4},
- {value: 0x2843, lo: 0xb6, hi: 0xb6},
- {value: 0x29b3, lo: 0xb7, hi: 0xb7},
- {value: 0x19af, lo: 0xbc, hi: 0xbc},
- {value: 0x424f, lo: 0xbe, hi: 0xbe},
- // Block 0x3e, offset 0x3f
- {value: 0x0002, lo: 0x0d},
- {value: 0x1a75, lo: 0x87, hi: 0x87},
- {value: 0x1a72, lo: 0x88, hi: 0x88},
- {value: 0x19b2, lo: 0x89, hi: 0x89},
- {value: 0x2b46, lo: 0x97, hi: 0x97},
- {value: 0x0001, lo: 0x9f, hi: 0x9f},
- {value: 0x0021, lo: 0xb0, hi: 0xb0},
- {value: 0x0093, lo: 0xb1, hi: 0xb1},
- {value: 0x0029, lo: 0xb4, hi: 0xb9},
- {value: 0x0017, lo: 0xba, hi: 0xba},
- {value: 0x04d9, lo: 0xbb, hi: 0xbb},
- {value: 0x003b, lo: 0xbc, hi: 0xbc},
- {value: 0x0011, lo: 0xbd, hi: 0xbe},
- {value: 0x009d, lo: 0xbf, hi: 0xbf},
- // Block 0x3f, offset 0x40
- {value: 0x0002, lo: 0x0f},
- {value: 0x0021, lo: 0x80, hi: 0x89},
- {value: 0x0017, lo: 0x8a, hi: 0x8a},
- {value: 0x04d9, lo: 0x8b, hi: 0x8b},
- {value: 0x003b, lo: 0x8c, hi: 0x8c},
- {value: 0x0011, lo: 0x8d, hi: 0x8e},
- {value: 0x0083, lo: 0x90, hi: 0x90},
- {value: 0x008b, lo: 0x91, hi: 0x91},
- {value: 0x009f, lo: 0x92, hi: 0x92},
- {value: 0x00b1, lo: 0x93, hi: 0x93},
- {value: 0x0107, lo: 0x94, hi: 0x94},
- {value: 0x0091, lo: 0x95, hi: 0x95},
- {value: 0x0097, lo: 0x96, hi: 0x99},
- {value: 0x00a1, lo: 0x9a, hi: 0x9a},
- {value: 0x00a7, lo: 0x9b, hi: 0x9c},
- {value: 0x1adb, lo: 0xa8, hi: 0xa8},
- // Block 0x40, offset 0x41
- {value: 0x0000, lo: 0x0d},
- {value: 0x80e6, lo: 0x90, hi: 0x91},
- {value: 0x8001, lo: 0x92, hi: 0x93},
- {value: 0x80e6, lo: 0x94, hi: 0x97},
- {value: 0x8001, lo: 0x98, hi: 0x9a},
- {value: 0x80e6, lo: 0x9b, hi: 0x9c},
- {value: 0x80e6, lo: 0xa1, hi: 0xa1},
- {value: 0x8001, lo: 0xa5, hi: 0xa6},
- {value: 0x80e6, lo: 0xa7, hi: 0xa7},
- {value: 0x80dc, lo: 0xa8, hi: 0xa8},
- {value: 0x80e6, lo: 0xa9, hi: 0xa9},
- {value: 0x8001, lo: 0xaa, hi: 0xab},
- {value: 0x80dc, lo: 0xac, hi: 0xaf},
- {value: 0x80e6, lo: 0xb0, hi: 0xb0},
- // Block 0x41, offset 0x42
- {value: 0x0007, lo: 0x06},
- {value: 0x22c2, lo: 0x89, hi: 0x89},
- {value: 0x8800, lo: 0x90, hi: 0x90},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x8800, lo: 0x94, hi: 0x94},
- {value: 0x3ba3, lo: 0x9a, hi: 0x9b},
- {value: 0x3bb1, lo: 0xae, hi: 0xae},
- // Block 0x42, offset 0x43
- {value: 0x000e, lo: 0x05},
- {value: 0x3bb8, lo: 0x8d, hi: 0x8e},
- {value: 0x3bbf, lo: 0x8f, hi: 0x8f},
- {value: 0x8800, lo: 0x90, hi: 0x90},
- {value: 0x8800, lo: 0x92, hi: 0x92},
- {value: 0x8800, lo: 0x94, hi: 0x94},
- // Block 0x43, offset 0x44
- {value: 0x0173, lo: 0x0e},
- {value: 0x8800, lo: 0x83, hi: 0x83},
- {value: 0x3bcd, lo: 0x84, hi: 0x84},
- {value: 0x8800, lo: 0x88, hi: 0x88},
- {value: 0x3bd4, lo: 0x89, hi: 0x89},
- {value: 0x8800, lo: 0x8b, hi: 0x8b},
- {value: 0x3bdb, lo: 0x8c, hi: 0x8c},
- {value: 0x8800, lo: 0xa3, hi: 0xa3},
- {value: 0x3be2, lo: 0xa4, hi: 0xa4},
- {value: 0x8800, lo: 0xa5, hi: 0xa5},
- {value: 0x3be9, lo: 0xa6, hi: 0xa6},
- {value: 0x284a, lo: 0xac, hi: 0xad},
- {value: 0x2851, lo: 0xaf, hi: 0xaf},
- {value: 0x29c7, lo: 0xb0, hi: 0xb0},
- {value: 0x8800, lo: 0xbc, hi: 0xbc},
- // Block 0x44, offset 0x45
- {value: 0x0007, lo: 0x03},
- {value: 0x3c52, lo: 0xa0, hi: 0xa1},
- {value: 0x3c7c, lo: 0xa2, hi: 0xa3},
- {value: 0x3ca6, lo: 0xaa, hi: 0xad},
- // Block 0x45, offset 0x46
- {value: 0x0004, lo: 0x01},
- {value: 0x04fd, lo: 0xa9, hi: 0xaa},
- // Block 0x46, offset 0x47
- {value: 0x0002, lo: 0x03},
- {value: 0x0057, lo: 0x80, hi: 0x8f},
- {value: 0x0083, lo: 0x90, hi: 0xa9},
- {value: 0x0021, lo: 0xaa, hi: 0xaa},
- // Block 0x47, offset 0x48
- {value: 0x0000, lo: 0x01},
- {value: 0x2b53, lo: 0x8c, hi: 0x8c},
- // Block 0x48, offset 0x49
- {value: 0x0263, lo: 0x02},
- {value: 0x1cce, lo: 0xb4, hi: 0xb4},
- {value: 0x1a6f, lo: 0xb5, hi: 0xb6},
- // Block 0x49, offset 0x4a
- {value: 0x0000, lo: 0x01},
- {value: 0x44c3, lo: 0x9c, hi: 0x9c},
- // Block 0x4a, offset 0x4b
- {value: 0x0000, lo: 0x02},
- {value: 0x0095, lo: 0xbc, hi: 0xbc},
- {value: 0x006d, lo: 0xbd, hi: 0xbd},
- // Block 0x4b, offset 0x4c
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0xaf, hi: 0xb1},
- // Block 0x4c, offset 0x4d
- {value: 0x0000, lo: 0x02},
- {value: 0x04f1, lo: 0xaf, hi: 0xaf},
- {value: 0x8009, lo: 0xbf, hi: 0xbf},
- // Block 0x4d, offset 0x4e
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0xa0, hi: 0xbf},
- // Block 0x4e, offset 0x4f
- {value: 0x0000, lo: 0x01},
- {value: 0x0e35, lo: 0x9f, hi: 0x9f},
- // Block 0x4f, offset 0x50
- {value: 0x0000, lo: 0x01},
- {value: 0x169d, lo: 0xb3, hi: 0xb3},
- // Block 0x50, offset 0x51
- {value: 0x0004, lo: 0x0b},
- {value: 0x1605, lo: 0x80, hi: 0x82},
- {value: 0x161d, lo: 0x83, hi: 0x83},
- {value: 0x1635, lo: 0x84, hi: 0x85},
- {value: 0x1645, lo: 0x86, hi: 0x89},
- {value: 0x1659, lo: 0x8a, hi: 0x8c},
- {value: 0x166d, lo: 0x8d, hi: 0x8d},
- {value: 0x1675, lo: 0x8e, hi: 0x8e},
- {value: 0x167d, lo: 0x8f, hi: 0x90},
- {value: 0x1689, lo: 0x91, hi: 0x93},
- {value: 0x1699, lo: 0x94, hi: 0x94},
- {value: 0x16a1, lo: 0x95, hi: 0x95},
- // Block 0x51, offset 0x52
- {value: 0x0004, lo: 0x08},
- {value: 0x0001, lo: 0x80, hi: 0x80},
- {value: 0x80da, lo: 0xaa, hi: 0xaa},
- {value: 0x80e4, lo: 0xab, hi: 0xac},
- {value: 0x80de, lo: 0xad, hi: 0xad},
- {value: 0x80e0, lo: 0xae, hi: 0xae},
- {value: 0x80e0, lo: 0xaf, hi: 0xaf},
- {value: 0x0525, lo: 0xb6, hi: 0xb6},
- {value: 0x08f9, lo: 0xb8, hi: 0xba},
- // Block 0x52, offset 0x53
- {value: 0x0004, lo: 0x06},
- {value: 0x030d, lo: 0xb1, hi: 0xb2},
- {value: 0x0435, lo: 0xb3, hi: 0xb3},
- {value: 0x0315, lo: 0xb4, hi: 0xb4},
- {value: 0x0439, lo: 0xb5, hi: 0xb6},
- {value: 0x0319, lo: 0xb7, hi: 0xb9},
- {value: 0x0441, lo: 0xba, hi: 0xbf},
- // Block 0x53, offset 0x54
- {value: 0x0004, lo: 0x0c},
- {value: 0x0361, lo: 0x80, hi: 0x80},
- {value: 0x0325, lo: 0x81, hi: 0x83},
- {value: 0x0375, lo: 0x84, hi: 0x84},
- {value: 0x0331, lo: 0x85, hi: 0x8e},
- {value: 0x03c1, lo: 0x8f, hi: 0xa3},
- {value: 0x03bd, lo: 0xa4, hi: 0xa4},
- {value: 0x0359, lo: 0xa5, hi: 0xa6},
- {value: 0x0459, lo: 0xa7, hi: 0xad},
- {value: 0x0365, lo: 0xae, hi: 0xae},
- {value: 0x0475, lo: 0xaf, hi: 0xb0},
- {value: 0x0369, lo: 0xb1, hi: 0xb3},
- {value: 0x0379, lo: 0xb4, hi: 0xbf},
- // Block 0x54, offset 0x55
- {value: 0x0000, lo: 0x02},
- {value: 0x80e6, lo: 0xaf, hi: 0xaf},
- {value: 0x80e6, lo: 0xb4, hi: 0xbd},
- // Block 0x55, offset 0x56
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x9f, hi: 0x9f},
- // Block 0x56, offset 0x57
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0xb0, hi: 0xb1},
- // Block 0x57, offset 0x58
- {value: 0x0000, lo: 0x01},
- {value: 0x16a5, lo: 0xb0, hi: 0xb0},
- // Block 0x58, offset 0x59
- {value: 0x000c, lo: 0x01},
- {value: 0x00da, lo: 0xb8, hi: 0xb9},
- // Block 0x59, offset 0x5a
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x86, hi: 0x86},
- // Block 0x5a, offset 0x5b
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0x84, hi: 0x84},
- {value: 0x80e6, lo: 0xa0, hi: 0xb1},
- // Block 0x5b, offset 0x5c
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0xab, hi: 0xad},
- // Block 0x5c, offset 0x5d
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x93, hi: 0x93},
- // Block 0x5d, offset 0x5e
- {value: 0x0000, lo: 0x01},
- {value: 0x8007, lo: 0xb3, hi: 0xb3},
- // Block 0x5e, offset 0x5f
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0x80, hi: 0x80},
- // Block 0x5f, offset 0x60
- {value: 0x0000, lo: 0x05},
- {value: 0x80e6, lo: 0xb0, hi: 0xb0},
- {value: 0x80e6, lo: 0xb2, hi: 0xb3},
- {value: 0x80dc, lo: 0xb4, hi: 0xb4},
- {value: 0x80e6, lo: 0xb7, hi: 0xb8},
- {value: 0x80e6, lo: 0xbe, hi: 0xbf},
- // Block 0x60, offset 0x61
- {value: 0x0000, lo: 0x02},
- {value: 0x80e6, lo: 0x81, hi: 0x81},
- {value: 0x8009, lo: 0xb6, hi: 0xb6},
- // Block 0x61, offset 0x62
- {value: 0x0000, lo: 0x01},
- {value: 0x8009, lo: 0xad, hi: 0xad},
- // Block 0x62, offset 0x63
- {value: 0x0000, lo: 0x01},
- {value: 0x8100, lo: 0x80, hi: 0xbf},
- // Block 0x63, offset 0x64
- {value: 0x0000, lo: 0x01},
- {value: 0x8100, lo: 0x80, hi: 0xa3},
- // Block 0x64, offset 0x65
- {value: 0x0002, lo: 0x01},
- {value: 0x0003, lo: 0x81, hi: 0xbf},
- // Block 0x65, offset 0x66
- {value: 0x0004, lo: 0x0e},
- {value: 0x03c1, lo: 0x82, hi: 0x87},
- {value: 0x03d9, lo: 0x8a, hi: 0x8f},
- {value: 0x03f1, lo: 0x92, hi: 0x97},
- {value: 0x0409, lo: 0x9a, hi: 0x9c},
- {value: 0x00bf, lo: 0xa0, hi: 0xa0},
- {value: 0x00c2, lo: 0xa1, hi: 0xa1},
- {value: 0x00cb, lo: 0xa2, hi: 0xa2},
- {value: 0x424a, lo: 0xa3, hi: 0xa3},
- {value: 0x00c8, lo: 0xa4, hi: 0xa4},
- {value: 0x00c5, lo: 0xa5, hi: 0xa5},
- {value: 0x04b9, lo: 0xa6, hi: 0xa6},
- {value: 0x04dd, lo: 0xa8, hi: 0xa8},
- {value: 0x04bd, lo: 0xa9, hi: 0xac},
- {value: 0x04e1, lo: 0xad, hi: 0xae},
- // Block 0x66, offset 0x67
- {value: 0x0000, lo: 0x01},
- {value: 0x80dc, lo: 0xbd, hi: 0xbd},
- // Block 0x67, offset 0x68
- {value: 0x00db, lo: 0x05},
- {value: 0x80dc, lo: 0x8d, hi: 0x8d},
- {value: 0x80e6, lo: 0x8f, hi: 0x8f},
- {value: 0x80e6, lo: 0xb8, hi: 0xb8},
- {value: 0x8001, lo: 0xb9, hi: 0xba},
- {value: 0x8009, lo: 0xbf, hi: 0xbf},
- // Block 0x68, offset 0x69
- {value: 0x05fe, lo: 0x07},
- {value: 0x8800, lo: 0x99, hi: 0x99},
- {value: 0x4222, lo: 0x9a, hi: 0x9a},
- {value: 0x8800, lo: 0x9b, hi: 0x9b},
- {value: 0x422c, lo: 0x9c, hi: 0x9c},
- {value: 0x8800, lo: 0xa5, hi: 0xa5},
- {value: 0x4236, lo: 0xab, hi: 0xab},
- {value: 0x8009, lo: 0xb9, hi: 0xba},
- // Block 0x69, offset 0x6a
- {value: 0x0000, lo: 0x06},
- {value: 0x80e6, lo: 0x80, hi: 0x82},
- {value: 0x8600, lo: 0xa7, hi: 0xa7},
- {value: 0x1993, lo: 0xae, hi: 0xae},
- {value: 0x199c, lo: 0xaf, hi: 0xaf},
- {value: 0x8800, lo: 0xb1, hi: 0xb2},
- {value: 0x8009, lo: 0xb3, hi: 0xb4},
- // Block 0x6a, offset 0x6b
- {value: 0x0000, lo: 0x02},
- {value: 0x8009, lo: 0xb6, hi: 0xb6},
- {value: 0x8007, lo: 0xb7, hi: 0xb7},
- // Block 0x6b, offset 0x6c
- {value: 0x0000, lo: 0x0c},
- {value: 0x45b2, lo: 0x9e, hi: 0x9e},
- {value: 0x45bc, lo: 0x9f, hi: 0x9f},
- {value: 0x45f0, lo: 0xa0, hi: 0xa0},
- {value: 0x45fe, lo: 0xa1, hi: 0xa1},
- {value: 0x460c, lo: 0xa2, hi: 0xa2},
- {value: 0x461a, lo: 0xa3, hi: 0xa3},
- {value: 0x4628, lo: 0xa4, hi: 0xa4},
- {value: 0x80d8, lo: 0xa5, hi: 0xa6},
- {value: 0x8001, lo: 0xa7, hi: 0xa9},
- {value: 0x80e2, lo: 0xad, hi: 0xad},
- {value: 0x80d8, lo: 0xae, hi: 0xb2},
- {value: 0x80dc, lo: 0xbb, hi: 0xbf},
- // Block 0x6c, offset 0x6d
- {value: 0x0000, lo: 0x09},
- {value: 0x80dc, lo: 0x80, hi: 0x82},
- {value: 0x80e6, lo: 0x85, hi: 0x89},
- {value: 0x80dc, lo: 0x8a, hi: 0x8b},
- {value: 0x80e6, lo: 0xaa, hi: 0xad},
- {value: 0x45c6, lo: 0xbb, hi: 0xbb},
- {value: 0x45d0, lo: 0xbc, hi: 0xbc},
- {value: 0x4636, lo: 0xbd, hi: 0xbd},
- {value: 0x4652, lo: 0xbe, hi: 0xbe},
- {value: 0x4644, lo: 0xbf, hi: 0xbf},
- // Block 0x6d, offset 0x6e
- {value: 0x0000, lo: 0x01},
- {value: 0x4660, lo: 0x80, hi: 0x80},
- // Block 0x6e, offset 0x6f
- {value: 0x0000, lo: 0x01},
- {value: 0x80e6, lo: 0x82, hi: 0x84},
- // Block 0x6f, offset 0x70
- {value: 0x0002, lo: 0x03},
- {value: 0x0043, lo: 0x80, hi: 0x99},
- {value: 0x0083, lo: 0x9a, hi: 0xb3},
- {value: 0x0043, lo: 0xb4, hi: 0xbf},
- // Block 0x70, offset 0x71
- {value: 0x0002, lo: 0x04},
- {value: 0x005b, lo: 0x80, hi: 0x8d},
- {value: 0x0083, lo: 0x8e, hi: 0x94},
- {value: 0x0093, lo: 0x96, hi: 0xa7},
- {value: 0x0043, lo: 0xa8, hi: 0xbf},
- // Block 0x71, offset 0x72
- {value: 0x0002, lo: 0x0b},
- {value: 0x0073, lo: 0x80, hi: 0x81},
- {value: 0x0083, lo: 0x82, hi: 0x9b},
- {value: 0x0043, lo: 0x9c, hi: 0x9c},
- {value: 0x0047, lo: 0x9e, hi: 0x9f},
- {value: 0x004f, lo: 0xa2, hi: 0xa2},
- {value: 0x0055, lo: 0xa5, hi: 0xa6},
- {value: 0x005d, lo: 0xa9, hi: 0xac},
- {value: 0x0067, lo: 0xae, hi: 0xb5},
- {value: 0x0083, lo: 0xb6, hi: 0xb9},
- {value: 0x008d, lo: 0xbb, hi: 0xbb},
- {value: 0x0091, lo: 0xbd, hi: 0xbf},
- // Block 0x72, offset 0x73
- {value: 0x0002, lo: 0x04},
- {value: 0x0097, lo: 0x80, hi: 0x83},
- {value: 0x00a1, lo: 0x85, hi: 0x8f},
- {value: 0x0043, lo: 0x90, hi: 0xa9},
- {value: 0x0083, lo: 0xaa, hi: 0xbf},
- // Block 0x73, offset 0x74
- {value: 0x0002, lo: 0x08},
- {value: 0x00af, lo: 0x80, hi: 0x83},
- {value: 0x0043, lo: 0x84, hi: 0x85},
- {value: 0x0049, lo: 0x87, hi: 0x8a},
- {value: 0x0055, lo: 0x8d, hi: 0x94},
- {value: 0x0067, lo: 0x96, hi: 0x9c},
- {value: 0x0083, lo: 0x9e, hi: 0xb7},
- {value: 0x0043, lo: 0xb8, hi: 0xb9},
- {value: 0x0049, lo: 0xbb, hi: 0xbe},
- // Block 0x74, offset 0x75
- {value: 0x0002, lo: 0x05},
- {value: 0x0053, lo: 0x80, hi: 0x84},
- {value: 0x005f, lo: 0x86, hi: 0x86},
- {value: 0x0067, lo: 0x8a, hi: 0x90},
- {value: 0x0083, lo: 0x92, hi: 0xab},
- {value: 0x0043, lo: 0xac, hi: 0xbf},
- // Block 0x75, offset 0x76
- {value: 0x0002, lo: 0x04},
- {value: 0x006b, lo: 0x80, hi: 0x85},
- {value: 0x0083, lo: 0x86, hi: 0x9f},
- {value: 0x0043, lo: 0xa0, hi: 0xb9},
- {value: 0x0083, lo: 0xba, hi: 0xbf},
- // Block 0x76, offset 0x77
- {value: 0x0002, lo: 0x03},
- {value: 0x008f, lo: 0x80, hi: 0x93},
- {value: 0x0043, lo: 0x94, hi: 0xad},
- {value: 0x0083, lo: 0xae, hi: 0xbf},
- // Block 0x77, offset 0x78
- {value: 0x0002, lo: 0x04},
- {value: 0x00a7, lo: 0x80, hi: 0x87},
- {value: 0x0043, lo: 0x88, hi: 0xa1},
- {value: 0x0083, lo: 0xa2, hi: 0xbb},
- {value: 0x0043, lo: 0xbc, hi: 0xbf},
- // Block 0x78, offset 0x79
- {value: 0x0002, lo: 0x03},
- {value: 0x004b, lo: 0x80, hi: 0x95},
- {value: 0x0083, lo: 0x96, hi: 0xaf},
- {value: 0x0043, lo: 0xb0, hi: 0xbf},
- // Block 0x79, offset 0x7a
- {value: 0x0003, lo: 0x0f},
- {value: 0x01b8, lo: 0x80, hi: 0x80},
- {value: 0x04d1, lo: 0x81, hi: 0x81},
- {value: 0x01bb, lo: 0x82, hi: 0x9a},
- {value: 0x04cd, lo: 0x9b, hi: 0x9b},
- {value: 0x01c7, lo: 0x9c, hi: 0x9c},
- {value: 0x01d0, lo: 0x9d, hi: 0x9d},
- {value: 0x01d6, lo: 0x9e, hi: 0x9e},
- {value: 0x01fa, lo: 0x9f, hi: 0x9f},
- {value: 0x01eb, lo: 0xa0, hi: 0xa0},
- {value: 0x01e8, lo: 0xa1, hi: 0xa1},
- {value: 0x0173, lo: 0xa2, hi: 0xb2},
- {value: 0x0188, lo: 0xb3, hi: 0xb3},
- {value: 0x01a6, lo: 0xb4, hi: 0xba},
- {value: 0x04d1, lo: 0xbb, hi: 0xbb},
- {value: 0x01bb, lo: 0xbc, hi: 0xbf},
- // Block 0x7a, offset 0x7b
- {value: 0x0003, lo: 0x0d},
- {value: 0x01c7, lo: 0x80, hi: 0x94},
- {value: 0x04cd, lo: 0x95, hi: 0x95},
- {value: 0x01c7, lo: 0x96, hi: 0x96},
- {value: 0x01d0, lo: 0x97, hi: 0x97},
- {value: 0x01d6, lo: 0x98, hi: 0x98},
- {value: 0x01fa, lo: 0x99, hi: 0x99},
- {value: 0x01eb, lo: 0x9a, hi: 0x9a},
- {value: 0x01e8, lo: 0x9b, hi: 0x9b},
- {value: 0x0173, lo: 0x9c, hi: 0xac},
- {value: 0x0188, lo: 0xad, hi: 0xad},
- {value: 0x01a6, lo: 0xae, hi: 0xb4},
- {value: 0x04d1, lo: 0xb5, hi: 0xb5},
- {value: 0x01bb, lo: 0xb6, hi: 0xbf},
- // Block 0x7b, offset 0x7c
- {value: 0x0003, lo: 0x0d},
- {value: 0x01d9, lo: 0x80, hi: 0x8e},
- {value: 0x04cd, lo: 0x8f, hi: 0x8f},
- {value: 0x01c7, lo: 0x90, hi: 0x90},
- {value: 0x01d0, lo: 0x91, hi: 0x91},
- {value: 0x01d6, lo: 0x92, hi: 0x92},
- {value: 0x01fa, lo: 0x93, hi: 0x93},
- {value: 0x01eb, lo: 0x94, hi: 0x94},
- {value: 0x01e8, lo: 0x95, hi: 0x95},
- {value: 0x0173, lo: 0x96, hi: 0xa6},
- {value: 0x0188, lo: 0xa7, hi: 0xa7},
- {value: 0x01a6, lo: 0xa8, hi: 0xae},
- {value: 0x04d1, lo: 0xaf, hi: 0xaf},
- {value: 0x01bb, lo: 0xb0, hi: 0xbf},
- // Block 0x7c, offset 0x7d
- {value: 0x0003, lo: 0x0d},
- {value: 0x01eb, lo: 0x80, hi: 0x88},
- {value: 0x04cd, lo: 0x89, hi: 0x89},
- {value: 0x01c7, lo: 0x8a, hi: 0x8a},
- {value: 0x01d0, lo: 0x8b, hi: 0x8b},
- {value: 0x01d6, lo: 0x8c, hi: 0x8c},
- {value: 0x01fa, lo: 0x8d, hi: 0x8d},
- {value: 0x01eb, lo: 0x8e, hi: 0x8e},
- {value: 0x01e8, lo: 0x8f, hi: 0x8f},
- {value: 0x0173, lo: 0x90, hi: 0xa0},
- {value: 0x0188, lo: 0xa1, hi: 0xa1},
- {value: 0x01a6, lo: 0xa2, hi: 0xa8},
- {value: 0x04d1, lo: 0xa9, hi: 0xa9},
- {value: 0x01bb, lo: 0xaa, hi: 0xbf},
- // Block 0x7d, offset 0x7e
- {value: 0x0002, lo: 0x09},
- {value: 0x0063, lo: 0x80, hi: 0x89},
- {value: 0x1a93, lo: 0x8a, hi: 0x8a},
- {value: 0x1ac3, lo: 0x8b, hi: 0x8b},
- {value: 0x1ade, lo: 0x8c, hi: 0x8c},
- {value: 0x1ae4, lo: 0x8d, hi: 0x8d},
- {value: 0x1d02, lo: 0x8e, hi: 0x8e},
- {value: 0x1af0, lo: 0x8f, hi: 0x8f},
- {value: 0x1abd, lo: 0xaa, hi: 0xaa},
- {value: 0x1ac0, lo: 0xab, hi: 0xab},
- // Block 0x7e, offset 0x7f
- {value: 0x0000, lo: 0x01},
- {value: 0x1a81, lo: 0x90, hi: 0x90},
- // Block 0x7f, offset 0x80
- {value: 0x0028, lo: 0x09},
- {value: 0x2a0d, lo: 0x80, hi: 0x80},
- {value: 0x29d1, lo: 0x81, hi: 0x81},
- {value: 0x29db, lo: 0x82, hi: 0x82},
- {value: 0x29ef, lo: 0x83, hi: 0x84},
- {value: 0x29f9, lo: 0x85, hi: 0x86},
- {value: 0x29e5, lo: 0x87, hi: 0x87},
- {value: 0x2a03, lo: 0x88, hi: 0x88},
- {value: 0x0be1, lo: 0x90, hi: 0x90},
- {value: 0x0959, lo: 0x91, hi: 0x91},
-}
-
-// nfkcLookup: 1216 bytes
-// Block 0 is the null block.
-var nfkcLookup = [1216]uint8{
- // Block 0x0, offset 0x0
- // Block 0x1, offset 0x40
- // Block 0x2, offset 0x80
- // Block 0x3, offset 0xc0
- 0x0c2: 0x58, 0x0c3: 0x01, 0x0c4: 0x02, 0x0c5: 0x03, 0x0c6: 0x59, 0x0c7: 0x04,
- 0x0c8: 0x05, 0x0ca: 0x5a, 0x0cb: 0x5b, 0x0cc: 0x06, 0x0cd: 0x07, 0x0ce: 0x08, 0x0cf: 0x09,
- 0x0d0: 0x0a, 0x0d1: 0x5c, 0x0d2: 0x5d, 0x0d3: 0x0b, 0x0d6: 0x0c, 0x0d7: 0x5e,
- 0x0d8: 0x5f, 0x0d9: 0x0d, 0x0db: 0x60, 0x0dc: 0x61, 0x0dd: 0x62, 0x0df: 0x63,
- 0x0e0: 0x02, 0x0e1: 0x03, 0x0e2: 0x04, 0x0e3: 0x05,
- 0x0ea: 0x06, 0x0eb: 0x07, 0x0ec: 0x07, 0x0ed: 0x08, 0x0ef: 0x09,
- 0x0f0: 0x10,
- // Block 0x4, offset 0x100
- 0x120: 0x64, 0x121: 0x65, 0x123: 0x66, 0x124: 0x67, 0x125: 0x68, 0x126: 0x69, 0x127: 0x6a,
- 0x128: 0x6b, 0x129: 0x6c, 0x12a: 0x6d, 0x12b: 0x6e, 0x12c: 0x69, 0x12d: 0x6f, 0x12e: 0x70, 0x12f: 0x71,
- 0x131: 0x72, 0x132: 0x73, 0x133: 0x74, 0x134: 0x75, 0x135: 0x76, 0x137: 0x77,
- 0x138: 0x78, 0x139: 0x79, 0x13a: 0x7a, 0x13b: 0x7b, 0x13c: 0x7c, 0x13d: 0x7d, 0x13e: 0x7e, 0x13f: 0x7f,
- // Block 0x5, offset 0x140
- 0x140: 0x80, 0x142: 0x81, 0x143: 0x82, 0x144: 0x83, 0x145: 0x84, 0x146: 0x85, 0x147: 0x86,
- 0x14d: 0x87,
- 0x15c: 0x88, 0x15f: 0x89,
- 0x162: 0x8a, 0x164: 0x8b,
- 0x168: 0x8c, 0x169: 0x8d, 0x16c: 0x0e, 0x16d: 0x8e, 0x16e: 0x8f, 0x16f: 0x90,
- 0x170: 0x91, 0x173: 0x92, 0x174: 0x93, 0x175: 0x0f, 0x176: 0x10, 0x177: 0x94,
- 0x178: 0x11, 0x179: 0x12, 0x17a: 0x13, 0x17b: 0x14, 0x17c: 0x15, 0x17d: 0x16, 0x17e: 0x17, 0x17f: 0x18,
- // Block 0x6, offset 0x180
- 0x180: 0x95, 0x181: 0x96, 0x182: 0x97, 0x183: 0x98, 0x184: 0x19, 0x185: 0x1a, 0x186: 0x99, 0x187: 0x9a,
- 0x188: 0x9b, 0x189: 0x1b, 0x18a: 0x1c, 0x18b: 0x9c, 0x18c: 0x9d,
- 0x191: 0x1d, 0x192: 0x1e, 0x193: 0x9e,
- 0x1a8: 0x9f, 0x1a9: 0xa0, 0x1ab: 0xa1,
- 0x1b1: 0xa2, 0x1b3: 0xa3, 0x1b5: 0xa4, 0x1b7: 0xa5,
- 0x1ba: 0xa6, 0x1bb: 0xa7, 0x1bc: 0x1f, 0x1bd: 0x20, 0x1be: 0x21, 0x1bf: 0xa8,
- // Block 0x7, offset 0x1c0
- 0x1c0: 0xa9, 0x1c1: 0x22, 0x1c2: 0x23, 0x1c3: 0x24, 0x1c4: 0xaa, 0x1c5: 0xab, 0x1c6: 0x25,
- 0x1c8: 0x26, 0x1c9: 0x27, 0x1ca: 0x28, 0x1cb: 0x29, 0x1cc: 0x2a, 0x1cd: 0x2b, 0x1ce: 0x2c, 0x1cf: 0x2d,
- // Block 0x8, offset 0x200
- 0x219: 0xac, 0x21a: 0xad, 0x21b: 0xae, 0x21d: 0xaf, 0x21f: 0xb0,
- 0x220: 0xb1, 0x223: 0xb2, 0x224: 0xb3, 0x225: 0xb4, 0x226: 0xb5, 0x227: 0xb6,
- 0x22a: 0xb7, 0x22b: 0xb8, 0x22f: 0xb9,
- 0x230: 0xba, 0x231: 0xba, 0x232: 0xba, 0x233: 0xba, 0x234: 0xba, 0x235: 0xba, 0x236: 0xba, 0x237: 0xba,
- 0x238: 0xba, 0x239: 0xba, 0x23a: 0xba, 0x23b: 0xba, 0x23c: 0xba, 0x23d: 0xba, 0x23e: 0xba, 0x23f: 0xba,
- // Block 0x9, offset 0x240
- 0x240: 0xba, 0x241: 0xba, 0x242: 0xba, 0x243: 0xba, 0x244: 0xba, 0x245: 0xba, 0x246: 0xba, 0x247: 0xba,
- 0x248: 0xba, 0x249: 0xba, 0x24a: 0xba, 0x24b: 0xba, 0x24c: 0xba, 0x24d: 0xba, 0x24e: 0xba, 0x24f: 0xba,
- 0x250: 0xba, 0x251: 0xba, 0x252: 0xba, 0x253: 0xba, 0x254: 0xba, 0x255: 0xba, 0x256: 0xba, 0x257: 0xba,
- 0x258: 0xba, 0x259: 0xba, 0x25a: 0xba, 0x25b: 0xba, 0x25c: 0xba, 0x25d: 0xba, 0x25e: 0xba, 0x25f: 0xba,
- 0x260: 0xba, 0x261: 0xba, 0x262: 0xba, 0x263: 0xba, 0x264: 0xba, 0x265: 0xba, 0x266: 0xba, 0x267: 0xba,
- 0x268: 0xba, 0x269: 0xba, 0x26a: 0xba, 0x26b: 0xba, 0x26c: 0xba, 0x26d: 0xba, 0x26e: 0xba, 0x26f: 0xba,
- 0x270: 0xba, 0x271: 0xba, 0x272: 0xba, 0x273: 0xba, 0x274: 0xba, 0x275: 0xba, 0x276: 0xba, 0x277: 0xba,
- 0x278: 0xba, 0x279: 0xba, 0x27a: 0xba, 0x27b: 0xba, 0x27c: 0xba, 0x27d: 0xba, 0x27e: 0xba, 0x27f: 0xba,
- // Block 0xa, offset 0x280
- 0x280: 0xba, 0x281: 0xba, 0x282: 0xba, 0x283: 0xba, 0x284: 0xba, 0x285: 0xba, 0x286: 0xba, 0x287: 0xba,
- 0x288: 0xba, 0x289: 0xba, 0x28a: 0xba, 0x28b: 0xba, 0x28c: 0xba, 0x28d: 0xba, 0x28e: 0xba, 0x28f: 0xba,
- 0x290: 0xba, 0x291: 0xba, 0x292: 0xba, 0x293: 0xba, 0x294: 0xba, 0x295: 0xba, 0x296: 0xba, 0x297: 0xba,
- 0x298: 0xba, 0x299: 0xba, 0x29a: 0xba, 0x29b: 0xba, 0x29c: 0xba, 0x29d: 0xba, 0x29e: 0xbb,
- // Block 0xb, offset 0x2c0
- 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: 0xbc, 0x2fd: 0x46, 0x2fe: 0x47, 0x2ff: 0xbd,
- // Block 0xc, offset 0x300
- 0x307: 0xbe,
- 0x328: 0xbf,
- // Block 0xd, offset 0x340
- 0x341: 0xb1, 0x342: 0xc0, 0x344: 0xc1, 0x347: 0xb6,
- 0x35a: 0xc2,
- // Block 0xe, offset 0x380
- 0x385: 0xc3, 0x386: 0xc4, 0x387: 0xc5,
- 0x389: 0xc6,
- 0x390: 0xc7, 0x391: 0xc8, 0x392: 0xc9, 0x393: 0xca, 0x394: 0xcb, 0x395: 0xcc, 0x396: 0xcd, 0x397: 0xce,
- 0x398: 0xcf, 0x399: 0xd0, 0x39a: 0x48, 0x39b: 0xd1, 0x39c: 0xd2, 0x39d: 0xd3, 0x39e: 0xd4, 0x39f: 0x49,
- // Block 0xf, offset 0x3c0
- 0x3f8: 0x4a, 0x3f9: 0x4b, 0x3fa: 0x4c,
- // Block 0x10, offset 0x400
- 0x404: 0x4d, 0x405: 0xd5, 0x406: 0xd6,
- 0x408: 0x4e, 0x409: 0xd7,
- // Block 0x11, offset 0x440
- 0x460: 0x4f, 0x461: 0x50, 0x462: 0x51, 0x463: 0x52, 0x464: 0x53, 0x465: 0x54, 0x466: 0x55, 0x467: 0x56,
- 0x468: 0x57,
- // Block 0x12, offset 0x480
- 0x490: 0x0a, 0x491: 0x0b,
- 0x49d: 0x0c, 0x49e: 0x0d, 0x49f: 0x0e,
- 0x4af: 0x0f,
-}
-
-var nfkcTrie = trie{nfkcLookup[:], nfkcValues[:], nfkcSparseValues[:], nfkcSparseOffset[:], 88}
-
-// recompMap: 7464 bytes (entries only)
-var recompMap = map[uint32]rune{
- 0x00410300: 0x00C0,
- 0x00410301: 0x00C1,
- 0x00410302: 0x00C2,
- 0x00410303: 0x00C3,
- 0x00410308: 0x00C4,
- 0x0041030A: 0x00C5,
- 0x00430327: 0x00C7,
- 0x00450300: 0x00C8,
- 0x00450301: 0x00C9,
- 0x00450302: 0x00CA,
- 0x00450308: 0x00CB,
- 0x00490300: 0x00CC,
- 0x00490301: 0x00CD,
- 0x00490302: 0x00CE,
- 0x00490308: 0x00CF,
- 0x004E0303: 0x00D1,
- 0x004F0300: 0x00D2,
- 0x004F0301: 0x00D3,
- 0x004F0302: 0x00D4,
- 0x004F0303: 0x00D5,
- 0x004F0308: 0x00D6,
- 0x00550300: 0x00D9,
- 0x00550301: 0x00DA,
- 0x00550302: 0x00DB,
- 0x00550308: 0x00DC,
- 0x00590301: 0x00DD,
- 0x00610300: 0x00E0,
- 0x00610301: 0x00E1,
- 0x00610302: 0x00E2,
- 0x00610303: 0x00E3,
- 0x00610308: 0x00E4,
- 0x0061030A: 0x00E5,
- 0x00630327: 0x00E7,
- 0x00650300: 0x00E8,
- 0x00650301: 0x00E9,
- 0x00650302: 0x00EA,
- 0x00650308: 0x00EB,
- 0x00690300: 0x00EC,
- 0x00690301: 0x00ED,
- 0x00690302: 0x00EE,
- 0x00690308: 0x00EF,
- 0x006E0303: 0x00F1,
- 0x006F0300: 0x00F2,
- 0x006F0301: 0x00F3,
- 0x006F0302: 0x00F4,
- 0x006F0303: 0x00F5,
- 0x006F0308: 0x00F6,
- 0x00750300: 0x00F9,
- 0x00750301: 0x00FA,
- 0x00750302: 0x00FB,
- 0x00750308: 0x00FC,
- 0x00790301: 0x00FD,
- 0x00790308: 0x00FF,
- 0x00410304: 0x0100,
- 0x00610304: 0x0101,
- 0x00410306: 0x0102,
- 0x00610306: 0x0103,
- 0x00410328: 0x0104,
- 0x00610328: 0x0105,
- 0x00430301: 0x0106,
- 0x00630301: 0x0107,
- 0x00430302: 0x0108,
- 0x00630302: 0x0109,
- 0x00430307: 0x010A,
- 0x00630307: 0x010B,
- 0x0043030C: 0x010C,
- 0x0063030C: 0x010D,
- 0x0044030C: 0x010E,
- 0x0064030C: 0x010F,
- 0x00450304: 0x0112,
- 0x00650304: 0x0113,
- 0x00450306: 0x0114,
- 0x00650306: 0x0115,
- 0x00450307: 0x0116,
- 0x00650307: 0x0117,
- 0x00450328: 0x0118,
- 0x00650328: 0x0119,
- 0x0045030C: 0x011A,
- 0x0065030C: 0x011B,
- 0x00470302: 0x011C,
- 0x00670302: 0x011D,
- 0x00470306: 0x011E,
- 0x00670306: 0x011F,
- 0x00470307: 0x0120,
- 0x00670307: 0x0121,
- 0x00470327: 0x0122,
- 0x00670327: 0x0123,
- 0x00480302: 0x0124,
- 0x00680302: 0x0125,
- 0x00490303: 0x0128,
- 0x00690303: 0x0129,
- 0x00490304: 0x012A,
- 0x00690304: 0x012B,
- 0x00490306: 0x012C,
- 0x00690306: 0x012D,
- 0x00490328: 0x012E,
- 0x00690328: 0x012F,
- 0x00490307: 0x0130,
- 0x004A0302: 0x0134,
- 0x006A0302: 0x0135,
- 0x004B0327: 0x0136,
- 0x006B0327: 0x0137,
- 0x004C0301: 0x0139,
- 0x006C0301: 0x013A,
- 0x004C0327: 0x013B,
- 0x006C0327: 0x013C,
- 0x004C030C: 0x013D,
- 0x006C030C: 0x013E,
- 0x004E0301: 0x0143,
- 0x006E0301: 0x0144,
- 0x004E0327: 0x0145,
- 0x006E0327: 0x0146,
- 0x004E030C: 0x0147,
- 0x006E030C: 0x0148,
- 0x004F0304: 0x014C,
- 0x006F0304: 0x014D,
- 0x004F0306: 0x014E,
- 0x006F0306: 0x014F,
- 0x004F030B: 0x0150,
- 0x006F030B: 0x0151,
- 0x00520301: 0x0154,
- 0x00720301: 0x0155,
- 0x00520327: 0x0156,
- 0x00720327: 0x0157,
- 0x0052030C: 0x0158,
- 0x0072030C: 0x0159,
- 0x00530301: 0x015A,
- 0x00730301: 0x015B,
- 0x00530302: 0x015C,
- 0x00730302: 0x015D,
- 0x00530327: 0x015E,
- 0x00730327: 0x015F,
- 0x0053030C: 0x0160,
- 0x0073030C: 0x0161,
- 0x00540327: 0x0162,
- 0x00740327: 0x0163,
- 0x0054030C: 0x0164,
- 0x0074030C: 0x0165,
- 0x00550303: 0x0168,
- 0x00750303: 0x0169,
- 0x00550304: 0x016A,
- 0x00750304: 0x016B,
- 0x00550306: 0x016C,
- 0x00750306: 0x016D,
- 0x0055030A: 0x016E,
- 0x0075030A: 0x016F,
- 0x0055030B: 0x0170,
- 0x0075030B: 0x0171,
- 0x00550328: 0x0172,
- 0x00750328: 0x0173,
- 0x00570302: 0x0174,
- 0x00770302: 0x0175,
- 0x00590302: 0x0176,
- 0x00790302: 0x0177,
- 0x00590308: 0x0178,
- 0x005A0301: 0x0179,
- 0x007A0301: 0x017A,
- 0x005A0307: 0x017B,
- 0x007A0307: 0x017C,
- 0x005A030C: 0x017D,
- 0x007A030C: 0x017E,
- 0x004F031B: 0x01A0,
- 0x006F031B: 0x01A1,
- 0x0055031B: 0x01AF,
- 0x0075031B: 0x01B0,
- 0x0041030C: 0x01CD,
- 0x0061030C: 0x01CE,
- 0x0049030C: 0x01CF,
- 0x0069030C: 0x01D0,
- 0x004F030C: 0x01D1,
- 0x006F030C: 0x01D2,
- 0x0055030C: 0x01D3,
- 0x0075030C: 0x01D4,
- 0x00DC0304: 0x01D5,
- 0x00FC0304: 0x01D6,
- 0x00DC0301: 0x01D7,
- 0x00FC0301: 0x01D8,
- 0x00DC030C: 0x01D9,
- 0x00FC030C: 0x01DA,
- 0x00DC0300: 0x01DB,
- 0x00FC0300: 0x01DC,
- 0x00C40304: 0x01DE,
- 0x00E40304: 0x01DF,
- 0x02260304: 0x01E0,
- 0x02270304: 0x01E1,
- 0x00C60304: 0x01E2,
- 0x00E60304: 0x01E3,
- 0x0047030C: 0x01E6,
- 0x0067030C: 0x01E7,
- 0x004B030C: 0x01E8,
- 0x006B030C: 0x01E9,
- 0x004F0328: 0x01EA,
- 0x006F0328: 0x01EB,
- 0x01EA0304: 0x01EC,
- 0x01EB0304: 0x01ED,
- 0x01B7030C: 0x01EE,
- 0x0292030C: 0x01EF,
- 0x006A030C: 0x01F0,
- 0x00470301: 0x01F4,
- 0x00670301: 0x01F5,
- 0x004E0300: 0x01F8,
- 0x006E0300: 0x01F9,
- 0x00C50301: 0x01FA,
- 0x00E50301: 0x01FB,
- 0x00C60301: 0x01FC,
- 0x00E60301: 0x01FD,
- 0x00D80301: 0x01FE,
- 0x00F80301: 0x01FF,
- 0x0041030F: 0x0200,
- 0x0061030F: 0x0201,
- 0x00410311: 0x0202,
- 0x00610311: 0x0203,
- 0x0045030F: 0x0204,
- 0x0065030F: 0x0205,
- 0x00450311: 0x0206,
- 0x00650311: 0x0207,
- 0x0049030F: 0x0208,
- 0x0069030F: 0x0209,
- 0x00490311: 0x020A,
- 0x00690311: 0x020B,
- 0x004F030F: 0x020C,
- 0x006F030F: 0x020D,
- 0x004F0311: 0x020E,
- 0x006F0311: 0x020F,
- 0x0052030F: 0x0210,
- 0x0072030F: 0x0211,
- 0x00520311: 0x0212,
- 0x00720311: 0x0213,
- 0x0055030F: 0x0214,
- 0x0075030F: 0x0215,
- 0x00550311: 0x0216,
- 0x00750311: 0x0217,
- 0x00530326: 0x0218,
- 0x00730326: 0x0219,
- 0x00540326: 0x021A,
- 0x00740326: 0x021B,
- 0x0048030C: 0x021E,
- 0x0068030C: 0x021F,
- 0x00410307: 0x0226,
- 0x00610307: 0x0227,
- 0x00450327: 0x0228,
- 0x00650327: 0x0229,
- 0x00D60304: 0x022A,
- 0x00F60304: 0x022B,
- 0x00D50304: 0x022C,
- 0x00F50304: 0x022D,
- 0x004F0307: 0x022E,
- 0x006F0307: 0x022F,
- 0x022E0304: 0x0230,
- 0x022F0304: 0x0231,
- 0x00590304: 0x0232,
- 0x00790304: 0x0233,
- 0x00A80301: 0x0385,
- 0x03910301: 0x0386,
- 0x03950301: 0x0388,
- 0x03970301: 0x0389,
- 0x03990301: 0x038A,
- 0x039F0301: 0x038C,
- 0x03A50301: 0x038E,
- 0x03A90301: 0x038F,
- 0x03CA0301: 0x0390,
- 0x03990308: 0x03AA,
- 0x03A50308: 0x03AB,
- 0x03B10301: 0x03AC,
- 0x03B50301: 0x03AD,
- 0x03B70301: 0x03AE,
- 0x03B90301: 0x03AF,
- 0x03CB0301: 0x03B0,
- 0x03B90308: 0x03CA,
- 0x03C50308: 0x03CB,
- 0x03BF0301: 0x03CC,
- 0x03C50301: 0x03CD,
- 0x03C90301: 0x03CE,
- 0x03D20301: 0x03D3,
- 0x03D20308: 0x03D4,
- 0x04150300: 0x0400,
- 0x04150308: 0x0401,
- 0x04130301: 0x0403,
- 0x04060308: 0x0407,
- 0x041A0301: 0x040C,
- 0x04180300: 0x040D,
- 0x04230306: 0x040E,
- 0x04180306: 0x0419,
- 0x04380306: 0x0439,
- 0x04350300: 0x0450,
- 0x04350308: 0x0451,
- 0x04330301: 0x0453,
- 0x04560308: 0x0457,
- 0x043A0301: 0x045C,
- 0x04380300: 0x045D,
- 0x04430306: 0x045E,
- 0x0474030F: 0x0476,
- 0x0475030F: 0x0477,
- 0x04160306: 0x04C1,
- 0x04360306: 0x04C2,
- 0x04100306: 0x04D0,
- 0x04300306: 0x04D1,
- 0x04100308: 0x04D2,
- 0x04300308: 0x04D3,
- 0x04150306: 0x04D6,
- 0x04350306: 0x04D7,
- 0x04D80308: 0x04DA,
- 0x04D90308: 0x04DB,
- 0x04160308: 0x04DC,
- 0x04360308: 0x04DD,
- 0x04170308: 0x04DE,
- 0x04370308: 0x04DF,
- 0x04180304: 0x04E2,
- 0x04380304: 0x04E3,
- 0x04180308: 0x04E4,
- 0x04380308: 0x04E5,
- 0x041E0308: 0x04E6,
- 0x043E0308: 0x04E7,
- 0x04E80308: 0x04EA,
- 0x04E90308: 0x04EB,
- 0x042D0308: 0x04EC,
- 0x044D0308: 0x04ED,
- 0x04230304: 0x04EE,
- 0x04430304: 0x04EF,
- 0x04230308: 0x04F0,
- 0x04430308: 0x04F1,
- 0x0423030B: 0x04F2,
- 0x0443030B: 0x04F3,
- 0x04270308: 0x04F4,
- 0x04470308: 0x04F5,
- 0x042B0308: 0x04F8,
- 0x044B0308: 0x04F9,
- 0x06270653: 0x0622,
- 0x06270654: 0x0623,
- 0x06480654: 0x0624,
- 0x06270655: 0x0625,
- 0x064A0654: 0x0626,
- 0x06D50654: 0x06C0,
- 0x06C10654: 0x06C2,
- 0x06D20654: 0x06D3,
- 0x0928093C: 0x0929,
- 0x0930093C: 0x0931,
- 0x0933093C: 0x0934,
- 0x09C709BE: 0x09CB,
- 0x09C709D7: 0x09CC,
- 0x0B470B56: 0x0B48,
- 0x0B470B3E: 0x0B4B,
- 0x0B470B57: 0x0B4C,
- 0x0B920BD7: 0x0B94,
- 0x0BC60BBE: 0x0BCA,
- 0x0BC70BBE: 0x0BCB,
- 0x0BC60BD7: 0x0BCC,
- 0x0C460C56: 0x0C48,
- 0x0CBF0CD5: 0x0CC0,
- 0x0CC60CD5: 0x0CC7,
- 0x0CC60CD6: 0x0CC8,
- 0x0CC60CC2: 0x0CCA,
- 0x0CCA0CD5: 0x0CCB,
- 0x0D460D3E: 0x0D4A,
- 0x0D470D3E: 0x0D4B,
- 0x0D460D57: 0x0D4C,
- 0x0DD90DCA: 0x0DDA,
- 0x0DD90DCF: 0x0DDC,
- 0x0DDC0DCA: 0x0DDD,
- 0x0DD90DDF: 0x0DDE,
- 0x1025102E: 0x1026,
- 0x1B051B35: 0x1B06,
- 0x1B071B35: 0x1B08,
- 0x1B091B35: 0x1B0A,
- 0x1B0B1B35: 0x1B0C,
- 0x1B0D1B35: 0x1B0E,
- 0x1B111B35: 0x1B12,
- 0x1B3A1B35: 0x1B3B,
- 0x1B3C1B35: 0x1B3D,
- 0x1B3E1B35: 0x1B40,
- 0x1B3F1B35: 0x1B41,
- 0x1B421B35: 0x1B43,
- 0x00410325: 0x1E00,
- 0x00610325: 0x1E01,
- 0x00420307: 0x1E02,
- 0x00620307: 0x1E03,
- 0x00420323: 0x1E04,
- 0x00620323: 0x1E05,
- 0x00420331: 0x1E06,
- 0x00620331: 0x1E07,
- 0x00C70301: 0x1E08,
- 0x00E70301: 0x1E09,
- 0x00440307: 0x1E0A,
- 0x00640307: 0x1E0B,
- 0x00440323: 0x1E0C,
- 0x00640323: 0x1E0D,
- 0x00440331: 0x1E0E,
- 0x00640331: 0x1E0F,
- 0x00440327: 0x1E10,
- 0x00640327: 0x1E11,
- 0x0044032D: 0x1E12,
- 0x0064032D: 0x1E13,
- 0x01120300: 0x1E14,
- 0x01130300: 0x1E15,
- 0x01120301: 0x1E16,
- 0x01130301: 0x1E17,
- 0x0045032D: 0x1E18,
- 0x0065032D: 0x1E19,
- 0x00450330: 0x1E1A,
- 0x00650330: 0x1E1B,
- 0x02280306: 0x1E1C,
- 0x02290306: 0x1E1D,
- 0x00460307: 0x1E1E,
- 0x00660307: 0x1E1F,
- 0x00470304: 0x1E20,
- 0x00670304: 0x1E21,
- 0x00480307: 0x1E22,
- 0x00680307: 0x1E23,
- 0x00480323: 0x1E24,
- 0x00680323: 0x1E25,
- 0x00480308: 0x1E26,
- 0x00680308: 0x1E27,
- 0x00480327: 0x1E28,
- 0x00680327: 0x1E29,
- 0x0048032E: 0x1E2A,
- 0x0068032E: 0x1E2B,
- 0x00490330: 0x1E2C,
- 0x00690330: 0x1E2D,
- 0x00CF0301: 0x1E2E,
- 0x00EF0301: 0x1E2F,
- 0x004B0301: 0x1E30,
- 0x006B0301: 0x1E31,
- 0x004B0323: 0x1E32,
- 0x006B0323: 0x1E33,
- 0x004B0331: 0x1E34,
- 0x006B0331: 0x1E35,
- 0x004C0323: 0x1E36,
- 0x006C0323: 0x1E37,
- 0x1E360304: 0x1E38,
- 0x1E370304: 0x1E39,
- 0x004C0331: 0x1E3A,
- 0x006C0331: 0x1E3B,
- 0x004C032D: 0x1E3C,
- 0x006C032D: 0x1E3D,
- 0x004D0301: 0x1E3E,
- 0x006D0301: 0x1E3F,
- 0x004D0307: 0x1E40,
- 0x006D0307: 0x1E41,
- 0x004D0323: 0x1E42,
- 0x006D0323: 0x1E43,
- 0x004E0307: 0x1E44,
- 0x006E0307: 0x1E45,
- 0x004E0323: 0x1E46,
- 0x006E0323: 0x1E47,
- 0x004E0331: 0x1E48,
- 0x006E0331: 0x1E49,
- 0x004E032D: 0x1E4A,
- 0x006E032D: 0x1E4B,
- 0x00D50301: 0x1E4C,
- 0x00F50301: 0x1E4D,
- 0x00D50308: 0x1E4E,
- 0x00F50308: 0x1E4F,
- 0x014C0300: 0x1E50,
- 0x014D0300: 0x1E51,
- 0x014C0301: 0x1E52,
- 0x014D0301: 0x1E53,
- 0x00500301: 0x1E54,
- 0x00700301: 0x1E55,
- 0x00500307: 0x1E56,
- 0x00700307: 0x1E57,
- 0x00520307: 0x1E58,
- 0x00720307: 0x1E59,
- 0x00520323: 0x1E5A,
- 0x00720323: 0x1E5B,
- 0x1E5A0304: 0x1E5C,
- 0x1E5B0304: 0x1E5D,
- 0x00520331: 0x1E5E,
- 0x00720331: 0x1E5F,
- 0x00530307: 0x1E60,
- 0x00730307: 0x1E61,
- 0x00530323: 0x1E62,
- 0x00730323: 0x1E63,
- 0x015A0307: 0x1E64,
- 0x015B0307: 0x1E65,
- 0x01600307: 0x1E66,
- 0x01610307: 0x1E67,
- 0x1E620307: 0x1E68,
- 0x1E630307: 0x1E69,
- 0x00540307: 0x1E6A,
- 0x00740307: 0x1E6B,
- 0x00540323: 0x1E6C,
- 0x00740323: 0x1E6D,
- 0x00540331: 0x1E6E,
- 0x00740331: 0x1E6F,
- 0x0054032D: 0x1E70,
- 0x0074032D: 0x1E71,
- 0x00550324: 0x1E72,
- 0x00750324: 0x1E73,
- 0x00550330: 0x1E74,
- 0x00750330: 0x1E75,
- 0x0055032D: 0x1E76,
- 0x0075032D: 0x1E77,
- 0x01680301: 0x1E78,
- 0x01690301: 0x1E79,
- 0x016A0308: 0x1E7A,
- 0x016B0308: 0x1E7B,
- 0x00560303: 0x1E7C,
- 0x00760303: 0x1E7D,
- 0x00560323: 0x1E7E,
- 0x00760323: 0x1E7F,
- 0x00570300: 0x1E80,
- 0x00770300: 0x1E81,
- 0x00570301: 0x1E82,
- 0x00770301: 0x1E83,
- 0x00570308: 0x1E84,
- 0x00770308: 0x1E85,
- 0x00570307: 0x1E86,
- 0x00770307: 0x1E87,
- 0x00570323: 0x1E88,
- 0x00770323: 0x1E89,
- 0x00580307: 0x1E8A,
- 0x00780307: 0x1E8B,
- 0x00580308: 0x1E8C,
- 0x00780308: 0x1E8D,
- 0x00590307: 0x1E8E,
- 0x00790307: 0x1E8F,
- 0x005A0302: 0x1E90,
- 0x007A0302: 0x1E91,
- 0x005A0323: 0x1E92,
- 0x007A0323: 0x1E93,
- 0x005A0331: 0x1E94,
- 0x007A0331: 0x1E95,
- 0x00680331: 0x1E96,
- 0x00740308: 0x1E97,
- 0x0077030A: 0x1E98,
- 0x0079030A: 0x1E99,
- 0x017F0307: 0x1E9B,
- 0x00410323: 0x1EA0,
- 0x00610323: 0x1EA1,
- 0x00410309: 0x1EA2,
- 0x00610309: 0x1EA3,
- 0x00C20301: 0x1EA4,
- 0x00E20301: 0x1EA5,
- 0x00C20300: 0x1EA6,
- 0x00E20300: 0x1EA7,
- 0x00C20309: 0x1EA8,
- 0x00E20309: 0x1EA9,
- 0x00C20303: 0x1EAA,
- 0x00E20303: 0x1EAB,
- 0x1EA00302: 0x1EAC,
- 0x1EA10302: 0x1EAD,
- 0x01020301: 0x1EAE,
- 0x01030301: 0x1EAF,
- 0x01020300: 0x1EB0,
- 0x01030300: 0x1EB1,
- 0x01020309: 0x1EB2,
- 0x01030309: 0x1EB3,
- 0x01020303: 0x1EB4,
- 0x01030303: 0x1EB5,
- 0x1EA00306: 0x1EB6,
- 0x1EA10306: 0x1EB7,
- 0x00450323: 0x1EB8,
- 0x00650323: 0x1EB9,
- 0x00450309: 0x1EBA,
- 0x00650309: 0x1EBB,
- 0x00450303: 0x1EBC,
- 0x00650303: 0x1EBD,
- 0x00CA0301: 0x1EBE,
- 0x00EA0301: 0x1EBF,
- 0x00CA0300: 0x1EC0,
- 0x00EA0300: 0x1EC1,
- 0x00CA0309: 0x1EC2,
- 0x00EA0309: 0x1EC3,
- 0x00CA0303: 0x1EC4,
- 0x00EA0303: 0x1EC5,
- 0x1EB80302: 0x1EC6,
- 0x1EB90302: 0x1EC7,
- 0x00490309: 0x1EC8,
- 0x00690309: 0x1EC9,
- 0x00490323: 0x1ECA,
- 0x00690323: 0x1ECB,
- 0x004F0323: 0x1ECC,
- 0x006F0323: 0x1ECD,
- 0x004F0309: 0x1ECE,
- 0x006F0309: 0x1ECF,
- 0x00D40301: 0x1ED0,
- 0x00F40301: 0x1ED1,
- 0x00D40300: 0x1ED2,
- 0x00F40300: 0x1ED3,
- 0x00D40309: 0x1ED4,
- 0x00F40309: 0x1ED5,
- 0x00D40303: 0x1ED6,
- 0x00F40303: 0x1ED7,
- 0x1ECC0302: 0x1ED8,
- 0x1ECD0302: 0x1ED9,
- 0x01A00301: 0x1EDA,
- 0x01A10301: 0x1EDB,
- 0x01A00300: 0x1EDC,
- 0x01A10300: 0x1EDD,
- 0x01A00309: 0x1EDE,
- 0x01A10309: 0x1EDF,
- 0x01A00303: 0x1EE0,
- 0x01A10303: 0x1EE1,
- 0x01A00323: 0x1EE2,
- 0x01A10323: 0x1EE3,
- 0x00550323: 0x1EE4,
- 0x00750323: 0x1EE5,
- 0x00550309: 0x1EE6,
- 0x00750309: 0x1EE7,
- 0x01AF0301: 0x1EE8,
- 0x01B00301: 0x1EE9,
- 0x01AF0300: 0x1EEA,
- 0x01B00300: 0x1EEB,
- 0x01AF0309: 0x1EEC,
- 0x01B00309: 0x1EED,
- 0x01AF0303: 0x1EEE,
- 0x01B00303: 0x1EEF,
- 0x01AF0323: 0x1EF0,
- 0x01B00323: 0x1EF1,
- 0x00590300: 0x1EF2,
- 0x00790300: 0x1EF3,
- 0x00590323: 0x1EF4,
- 0x00790323: 0x1EF5,
- 0x00590309: 0x1EF6,
- 0x00790309: 0x1EF7,
- 0x00590303: 0x1EF8,
- 0x00790303: 0x1EF9,
- 0x03B10313: 0x1F00,
- 0x03B10314: 0x1F01,
- 0x1F000300: 0x1F02,
- 0x1F010300: 0x1F03,
- 0x1F000301: 0x1F04,
- 0x1F010301: 0x1F05,
- 0x1F000342: 0x1F06,
- 0x1F010342: 0x1F07,
- 0x03910313: 0x1F08,
- 0x03910314: 0x1F09,
- 0x1F080300: 0x1F0A,
- 0x1F090300: 0x1F0B,
- 0x1F080301: 0x1F0C,
- 0x1F090301: 0x1F0D,
- 0x1F080342: 0x1F0E,
- 0x1F090342: 0x1F0F,
- 0x03B50313: 0x1F10,
- 0x03B50314: 0x1F11,
- 0x1F100300: 0x1F12,
- 0x1F110300: 0x1F13,
- 0x1F100301: 0x1F14,
- 0x1F110301: 0x1F15,
- 0x03950313: 0x1F18,
- 0x03950314: 0x1F19,
- 0x1F180300: 0x1F1A,
- 0x1F190300: 0x1F1B,
- 0x1F180301: 0x1F1C,
- 0x1F190301: 0x1F1D,
- 0x03B70313: 0x1F20,
- 0x03B70314: 0x1F21,
- 0x1F200300: 0x1F22,
- 0x1F210300: 0x1F23,
- 0x1F200301: 0x1F24,
- 0x1F210301: 0x1F25,
- 0x1F200342: 0x1F26,
- 0x1F210342: 0x1F27,
- 0x03970313: 0x1F28,
- 0x03970314: 0x1F29,
- 0x1F280300: 0x1F2A,
- 0x1F290300: 0x1F2B,
- 0x1F280301: 0x1F2C,
- 0x1F290301: 0x1F2D,
- 0x1F280342: 0x1F2E,
- 0x1F290342: 0x1F2F,
- 0x03B90313: 0x1F30,
- 0x03B90314: 0x1F31,
- 0x1F300300: 0x1F32,
- 0x1F310300: 0x1F33,
- 0x1F300301: 0x1F34,
- 0x1F310301: 0x1F35,
- 0x1F300342: 0x1F36,
- 0x1F310342: 0x1F37,
- 0x03990313: 0x1F38,
- 0x03990314: 0x1F39,
- 0x1F380300: 0x1F3A,
- 0x1F390300: 0x1F3B,
- 0x1F380301: 0x1F3C,
- 0x1F390301: 0x1F3D,
- 0x1F380342: 0x1F3E,
- 0x1F390342: 0x1F3F,
- 0x03BF0313: 0x1F40,
- 0x03BF0314: 0x1F41,
- 0x1F400300: 0x1F42,
- 0x1F410300: 0x1F43,
- 0x1F400301: 0x1F44,
- 0x1F410301: 0x1F45,
- 0x039F0313: 0x1F48,
- 0x039F0314: 0x1F49,
- 0x1F480300: 0x1F4A,
- 0x1F490300: 0x1F4B,
- 0x1F480301: 0x1F4C,
- 0x1F490301: 0x1F4D,
- 0x03C50313: 0x1F50,
- 0x03C50314: 0x1F51,
- 0x1F500300: 0x1F52,
- 0x1F510300: 0x1F53,
- 0x1F500301: 0x1F54,
- 0x1F510301: 0x1F55,
- 0x1F500342: 0x1F56,
- 0x1F510342: 0x1F57,
- 0x03A50314: 0x1F59,
- 0x1F590300: 0x1F5B,
- 0x1F590301: 0x1F5D,
- 0x1F590342: 0x1F5F,
- 0x03C90313: 0x1F60,
- 0x03C90314: 0x1F61,
- 0x1F600300: 0x1F62,
- 0x1F610300: 0x1F63,
- 0x1F600301: 0x1F64,
- 0x1F610301: 0x1F65,
- 0x1F600342: 0x1F66,
- 0x1F610342: 0x1F67,
- 0x03A90313: 0x1F68,
- 0x03A90314: 0x1F69,
- 0x1F680300: 0x1F6A,
- 0x1F690300: 0x1F6B,
- 0x1F680301: 0x1F6C,
- 0x1F690301: 0x1F6D,
- 0x1F680342: 0x1F6E,
- 0x1F690342: 0x1F6F,
- 0x03B10300: 0x1F70,
- 0x03B50300: 0x1F72,
- 0x03B70300: 0x1F74,
- 0x03B90300: 0x1F76,
- 0x03BF0300: 0x1F78,
- 0x03C50300: 0x1F7A,
- 0x03C90300: 0x1F7C,
- 0x1F000345: 0x1F80,
- 0x1F010345: 0x1F81,
- 0x1F020345: 0x1F82,
- 0x1F030345: 0x1F83,
- 0x1F040345: 0x1F84,
- 0x1F050345: 0x1F85,
- 0x1F060345: 0x1F86,
- 0x1F070345: 0x1F87,
- 0x1F080345: 0x1F88,
- 0x1F090345: 0x1F89,
- 0x1F0A0345: 0x1F8A,
- 0x1F0B0345: 0x1F8B,
- 0x1F0C0345: 0x1F8C,
- 0x1F0D0345: 0x1F8D,
- 0x1F0E0345: 0x1F8E,
- 0x1F0F0345: 0x1F8F,
- 0x1F200345: 0x1F90,
- 0x1F210345: 0x1F91,
- 0x1F220345: 0x1F92,
- 0x1F230345: 0x1F93,
- 0x1F240345: 0x1F94,
- 0x1F250345: 0x1F95,
- 0x1F260345: 0x1F96,
- 0x1F270345: 0x1F97,
- 0x1F280345: 0x1F98,
- 0x1F290345: 0x1F99,
- 0x1F2A0345: 0x1F9A,
- 0x1F2B0345: 0x1F9B,
- 0x1F2C0345: 0x1F9C,
- 0x1F2D0345: 0x1F9D,
- 0x1F2E0345: 0x1F9E,
- 0x1F2F0345: 0x1F9F,
- 0x1F600345: 0x1FA0,
- 0x1F610345: 0x1FA1,
- 0x1F620345: 0x1FA2,
- 0x1F630345: 0x1FA3,
- 0x1F640345: 0x1FA4,
- 0x1F650345: 0x1FA5,
- 0x1F660345: 0x1FA6,
- 0x1F670345: 0x1FA7,
- 0x1F680345: 0x1FA8,
- 0x1F690345: 0x1FA9,
- 0x1F6A0345: 0x1FAA,
- 0x1F6B0345: 0x1FAB,
- 0x1F6C0345: 0x1FAC,
- 0x1F6D0345: 0x1FAD,
- 0x1F6E0345: 0x1FAE,
- 0x1F6F0345: 0x1FAF,
- 0x03B10306: 0x1FB0,
- 0x03B10304: 0x1FB1,
- 0x1F700345: 0x1FB2,
- 0x03B10345: 0x1FB3,
- 0x03AC0345: 0x1FB4,
- 0x03B10342: 0x1FB6,
- 0x1FB60345: 0x1FB7,
- 0x03910306: 0x1FB8,
- 0x03910304: 0x1FB9,
- 0x03910300: 0x1FBA,
- 0x03910345: 0x1FBC,
- 0x00A80342: 0x1FC1,
- 0x1F740345: 0x1FC2,
- 0x03B70345: 0x1FC3,
- 0x03AE0345: 0x1FC4,
- 0x03B70342: 0x1FC6,
- 0x1FC60345: 0x1FC7,
- 0x03950300: 0x1FC8,
- 0x03970300: 0x1FCA,
- 0x03970345: 0x1FCC,
- 0x1FBF0300: 0x1FCD,
- 0x1FBF0301: 0x1FCE,
- 0x1FBF0342: 0x1FCF,
- 0x03B90306: 0x1FD0,
- 0x03B90304: 0x1FD1,
- 0x03CA0300: 0x1FD2,
- 0x03B90342: 0x1FD6,
- 0x03CA0342: 0x1FD7,
- 0x03990306: 0x1FD8,
- 0x03990304: 0x1FD9,
- 0x03990300: 0x1FDA,
- 0x1FFE0300: 0x1FDD,
- 0x1FFE0301: 0x1FDE,
- 0x1FFE0342: 0x1FDF,
- 0x03C50306: 0x1FE0,
- 0x03C50304: 0x1FE1,
- 0x03CB0300: 0x1FE2,
- 0x03C10313: 0x1FE4,
- 0x03C10314: 0x1FE5,
- 0x03C50342: 0x1FE6,
- 0x03CB0342: 0x1FE7,
- 0x03A50306: 0x1FE8,
- 0x03A50304: 0x1FE9,
- 0x03A50300: 0x1FEA,
- 0x03A10314: 0x1FEC,
- 0x00A80300: 0x1FED,
- 0x1F7C0345: 0x1FF2,
- 0x03C90345: 0x1FF3,
- 0x03CE0345: 0x1FF4,
- 0x03C90342: 0x1FF6,
- 0x1FF60345: 0x1FF7,
- 0x039F0300: 0x1FF8,
- 0x03A90300: 0x1FFA,
- 0x03A90345: 0x1FFC,
- 0x21900338: 0x219A,
- 0x21920338: 0x219B,
- 0x21940338: 0x21AE,
- 0x21D00338: 0x21CD,
- 0x21D40338: 0x21CE,
- 0x21D20338: 0x21CF,
- 0x22030338: 0x2204,
- 0x22080338: 0x2209,
- 0x220B0338: 0x220C,
- 0x22230338: 0x2224,
- 0x22250338: 0x2226,
- 0x223C0338: 0x2241,
- 0x22430338: 0x2244,
- 0x22450338: 0x2247,
- 0x22480338: 0x2249,
- 0x003D0338: 0x2260,
- 0x22610338: 0x2262,
- 0x224D0338: 0x226D,
- 0x003C0338: 0x226E,
- 0x003E0338: 0x226F,
- 0x22640338: 0x2270,
- 0x22650338: 0x2271,
- 0x22720338: 0x2274,
- 0x22730338: 0x2275,
- 0x22760338: 0x2278,
- 0x22770338: 0x2279,
- 0x227A0338: 0x2280,
- 0x227B0338: 0x2281,
- 0x22820338: 0x2284,
- 0x22830338: 0x2285,
- 0x22860338: 0x2288,
- 0x22870338: 0x2289,
- 0x22A20338: 0x22AC,
- 0x22A80338: 0x22AD,
- 0x22A90338: 0x22AE,
- 0x22AB0338: 0x22AF,
- 0x227C0338: 0x22E0,
- 0x227D0338: 0x22E1,
- 0x22910338: 0x22E2,
- 0x22920338: 0x22E3,
- 0x22B20338: 0x22EA,
- 0x22B30338: 0x22EB,
- 0x22B40338: 0x22EC,
- 0x22B50338: 0x22ED,
- 0x304B3099: 0x304C,
- 0x304D3099: 0x304E,
- 0x304F3099: 0x3050,
- 0x30513099: 0x3052,
- 0x30533099: 0x3054,
- 0x30553099: 0x3056,
- 0x30573099: 0x3058,
- 0x30593099: 0x305A,
- 0x305B3099: 0x305C,
- 0x305D3099: 0x305E,
- 0x305F3099: 0x3060,
- 0x30613099: 0x3062,
- 0x30643099: 0x3065,
- 0x30663099: 0x3067,
- 0x30683099: 0x3069,
- 0x306F3099: 0x3070,
- 0x306F309A: 0x3071,
- 0x30723099: 0x3073,
- 0x3072309A: 0x3074,
- 0x30753099: 0x3076,
- 0x3075309A: 0x3077,
- 0x30783099: 0x3079,
- 0x3078309A: 0x307A,
- 0x307B3099: 0x307C,
- 0x307B309A: 0x307D,
- 0x30463099: 0x3094,
- 0x309D3099: 0x309E,
- 0x30AB3099: 0x30AC,
- 0x30AD3099: 0x30AE,
- 0x30AF3099: 0x30B0,
- 0x30B13099: 0x30B2,
- 0x30B33099: 0x30B4,
- 0x30B53099: 0x30B6,
- 0x30B73099: 0x30B8,
- 0x30B93099: 0x30BA,
- 0x30BB3099: 0x30BC,
- 0x30BD3099: 0x30BE,
- 0x30BF3099: 0x30C0,
- 0x30C13099: 0x30C2,
- 0x30C43099: 0x30C5,
- 0x30C63099: 0x30C7,
- 0x30C83099: 0x30C9,
- 0x30CF3099: 0x30D0,
- 0x30CF309A: 0x30D1,
- 0x30D23099: 0x30D3,
- 0x30D2309A: 0x30D4,
- 0x30D53099: 0x30D6,
- 0x30D5309A: 0x30D7,
- 0x30D83099: 0x30D9,
- 0x30D8309A: 0x30DA,
- 0x30DB3099: 0x30DC,
- 0x30DB309A: 0x30DD,
- 0x30A63099: 0x30F4,
- 0x30EF3099: 0x30F7,
- 0x30F03099: 0x30F8,
- 0x30F13099: 0x30F9,
- 0x30F23099: 0x30FA,
- 0x30FD3099: 0x30FE,
- 0x109910BA: 0x1109A,
- 0x109B10BA: 0x1109C,
- 0x10A510BA: 0x110AB,
- 0x11311127: 0x1112E,
- 0x11321127: 0x1112F,
-}
-
-// Total size of tables: 50KB (51625 bytes)
diff --git a/src/pkg/exp/norm/trie.go b/src/pkg/exp/norm/trie.go
deleted file mode 100644
index 82267a8d3..000000000
--- a/src/pkg/exp/norm/trie.go
+++ /dev/null
@@ -1,232 +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 norm
-
-type valueRange struct {
- value uint16 // header: value:stride
- lo, hi byte // header: lo:n
-}
-
-type trie struct {
- index []uint8
- values []uint16
- sparse []valueRange
- sparseOffset []uint16
- cutoff uint8 // indices >= cutoff are sparse
-}
-
-// lookupValue determines the type of block n and looks up the value for b.
-// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
-// is a list of ranges with an accompanying value. Given a matching range r,
-// the value for b is by r.value + (b - r.lo) * stride.
-func (t *trie) lookupValue(n uint8, b byte) uint16 {
- if n < t.cutoff {
- return t.values[uint16(n)<<6+uint16(b)]
- }
- offset := t.sparseOffset[n-t.cutoff]
- header := t.sparse[offset]
- lo := offset + 1
- hi := lo + uint16(header.lo)
- for lo < hi {
- m := lo + (hi-lo)/2
- r := t.sparse[m]
- if r.lo <= b && b <= r.hi {
- return r.value + uint16(b-r.lo)*header.value
- }
- if b < r.lo {
- hi = m
- } else {
- lo = m + 1
- }
- }
- return 0
-}
-
-const (
- 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
-)
-
-// 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 uint16, sz int) {
- c0 := s[0]
- switch {
- case c0 < tx:
- return t.values[c0], 1
- case c0 < t2:
- return 0, 1
- case c0 < t3:
- if len(s) < 2 {
- return 0, 0
- }
- i := t.index[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.index[c0]
- c1 := s[1]
- if c1 < tx || t2 <= c1 {
- return 0, 1
- }
- o := uint16(i)<<6 + uint16(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.index[c0]
- c1 := s[1]
- if c1 < tx || t2 <= c1 {
- return 0, 1
- }
- 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)
- 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
-}
-
-// lookupString 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) lookupString(s string) (v uint16, sz int) {
- c0 := s[0]
- switch {
- case c0 < tx:
- return t.values[c0], 1
- case c0 < t2:
- return 0, 1
- case c0 < t3:
- if len(s) < 2 {
- return 0, 0
- }
- i := t.index[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.index[c0]
- c1 := s[1]
- if c1 < tx || t2 <= c1 {
- return 0, 1
- }
- o := uint16(i)<<6 + uint16(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.index[c0]
- c1 := s[1]
- if c1 < tx || t2 <= c1 {
- return 0, 1
- }
- 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)
- 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
-}
-
-// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
-// s must hold a full encoding.
-func (t *trie) lookupUnsafe(s []byte) uint16 {
- c0 := s[0]
- if c0 < tx {
- return t.values[c0]
- }
- if c0 < t2 {
- return 0
- }
- i := t.index[c0]
- if c0 < t3 {
- return t.lookupValue(i, s[1])
- }
- 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])]
- if c0 < t5 {
- return t.lookupValue(i, s[3])
- }
- return 0
-}
-
-// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
-// s must hold a full encoding.
-func (t *trie) lookupStringUnsafe(s string) uint16 {
- c0 := s[0]
- if c0 < tx {
- return t.values[c0]
- }
- if c0 < t2 {
- return 0
- }
- i := t.index[c0]
- if c0 < t3 {
- return t.lookupValue(i, s[1])
- }
- 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])]
- if c0 < t5 {
- return t.lookupValue(i, s[3])
- }
- return 0
-}
diff --git a/src/pkg/exp/norm/trie_test.go b/src/pkg/exp/norm/trie_test.go
deleted file mode 100644
index 1a75cc705..000000000
--- a/src/pkg/exp/norm/trie_test.go
+++ /dev/null
@@ -1,152 +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 norm
-
-import (
- "testing"
- "unicode/utf8"
-)
-
-// Test data is located in triedata_test.go; generated by maketesttables.
-var testdata = testdataTrie
-
-type rangeTest struct {
- block uint8
- lookup byte
- result uint16
- table []valueRange
- offsets []uint16
-}
-
-var range1Off = []uint16{0, 2}
-var range1 = []valueRange{
- {0, 1, 0},
- {1, 0x80, 0x80},
- {0, 2, 0},
- {1, 0x80, 0x80},
- {9, 0xff, 0xff},
-}
-
-var rangeTests = []rangeTest{
- {10, 0x80, 1, range1, range1Off},
- {10, 0x00, 0, range1, range1Off},
- {11, 0x80, 1, range1, range1Off},
- {11, 0xff, 9, range1, range1Off},
- {11, 0x00, 0, range1, range1Off},
-}
-
-func TestLookupSparse(t *testing.T) {
- for i, test := range rangeTests {
- n := trie{sparse: test.table, sparseOffset: test.offsets, cutoff: 10}
- v := n.lookupValue(test.block, test.lookup)
- if v != test.result {
- t.Errorf("LookupSparse:%d: found %X; want %X", i, v, test.result)
- }
- }
-}
-
-// Test cases for illegal runes.
-type trietest struct {
- size int
- 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 mkUTF8(r rune) ([]byte, int) {
- var b [utf8.UTFMax]byte
- sz := utf8.EncodeRune(b[:], r)
- return b[:sz], sz
-}
-
-func TestLookup(t *testing.T) {
- for i, tt := range testRunes {
- b, szg := mkUTF8(tt)
- v, szt := testdata.lookup(b)
- if int(v) != i {
- t.Errorf("lookup(%U): found value %#x, expected %#x", tt, v, i)
- }
- if szt != szg {
- t.Errorf("lookup(%U): found size %d, expected %d", tt, szt, szg)
- }
- }
- for i, tt := range tests {
- v, sz := testdata.lookup(tt.bytes)
- 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) {
- for i, tt := range testRunes {
- b, _ := mkUTF8(tt)
- v := testdata.lookupUnsafe(b)
- if int(v) != i {
- t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i)
- }
- }
-}
-
-func TestLookupString(t *testing.T) {
- for i, tt := range testRunes {
- b, szg := mkUTF8(tt)
- v, szt := testdata.lookupString(string(b))
- if int(v) != i {
- t.Errorf("lookup(%U): found value %#x, expected %#x", i, v, i)
- }
- if szt != szg {
- t.Errorf("lookup(%U): found size %d, expected %d", i, szt, szg)
- }
- }
- for i, tt := range tests {
- v, sz := testdata.lookupString(string(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)
- }
- }
-}
-
-func TestLookupStringUnsafe(t *testing.T) {
- for i, tt := range testRunes {
- b, _ := mkUTF8(tt)
- v := testdata.lookupStringUnsafe(string(b))
- if int(v) != i {
- t.Errorf("lookupUnsafe(%U): found value %#x, expected %#x", i, v, i)
- }
- }
-}
diff --git a/src/pkg/exp/norm/triedata_test.go b/src/pkg/exp/norm/triedata_test.go
deleted file mode 100644
index d6c832d46..000000000
--- a/src/pkg/exp/norm/triedata_test.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Generated by running
-// maketesttables
-// DO NOT EDIT
-
-package norm
-
-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.
-var testdataValues = [192]uint16{
- // Block 0x0, offset 0x0
- 0x000c: 0x0001,
- // Block 0x1, offset 0x40
- 0x007f: 0x0002,
- // Block 0x2, offset 0x80
-}
-
-// testdataSparseOffset: 10 entries, 20 bytes
-var testdataSparseOffset = []uint16{0x0, 0x2, 0x4, 0x8, 0xa, 0xc, 0xe, 0x10, 0x12, 0x14}
-
-// testdataSparseValues: 22 entries, 88 bytes
-var testdataSparseValues = [22]valueRange{
- // Block 0x0, offset 0x1
- {value: 0x0000, lo: 0x01},
- {value: 0x0003, lo: 0x80, hi: 0x80},
- // Block 0x1, offset 0x2
- {value: 0x0000, lo: 0x01},
- {value: 0x0004, lo: 0x80, hi: 0x80},
- // Block 0x2, offset 0x3
- {value: 0x0001, lo: 0x03},
- {value: 0x000c, lo: 0x80, hi: 0x82},
- {value: 0x000f, lo: 0x90, hi: 0x90},
- {value: 0x0010, lo: 0x95, hi: 0x95},
- // Block 0x3, offset 0x4
- {value: 0x0000, lo: 0x01},
- {value: 0x0005, lo: 0xbf, hi: 0xbf},
- // Block 0x4, offset 0x5
- {value: 0x0000, lo: 0x01},
- {value: 0x0006, lo: 0x80, hi: 0x80},
- // Block 0x5, offset 0x6
- {value: 0x0000, lo: 0x01},
- {value: 0x0007, lo: 0x99, hi: 0x99},
- // Block 0x6, offset 0x7
- {value: 0x0000, lo: 0x01},
- {value: 0x0008, lo: 0xbf, hi: 0xbf},
- // Block 0x7, offset 0x8
- {value: 0x0000, lo: 0x01},
- {value: 0x0009, lo: 0x80, hi: 0x80},
- // Block 0x8, offset 0x9
- {value: 0x0000, lo: 0x01},
- {value: 0x000a, lo: 0x81, hi: 0x81},
- // Block 0x9, offset 0xa
- {value: 0x0000, lo: 0x01},
- {value: 0x000b, lo: 0xbf, hi: 0xbf},
-}
-
-// testdataLookup: 640 bytes
-// Block 0 is the null block.
-var testdataLookup = [640]uint8{
- // Block 0x0, offset 0x0
- // Block 0x1, offset 0x40
- // Block 0x2, offset 0x80
- // Block 0x3, offset 0xc0
- 0x0c2: 0x01, 0x0c4: 0x02,
- 0x0c8: 0x03,
- 0x0df: 0x04,
- 0x0e0: 0x02,
- 0x0ef: 0x03,
- 0x0f0: 0x05, 0x0f4: 0x07,
- // Block 0x4, offset 0x100
- 0x120: 0x05, 0x126: 0x06,
- // Block 0x5, offset 0x140
- 0x17f: 0x07,
- // Block 0x6, offset 0x180
- 0x180: 0x08, 0x184: 0x09,
- // Block 0x7, offset 0x1c0
- 0x1d0: 0x04,
- // Block 0x8, offset 0x200
- 0x23f: 0x0a,
- // Block 0x9, offset 0x240
- 0x24f: 0x06,
-}
-
-var testdataTrie = trie{testdataLookup[:], testdataValues[:], testdataSparseValues[:], testdataSparseOffset[:], 1}
diff --git a/src/pkg/exp/norm/triegen.go b/src/pkg/exp/norm/triegen.go
deleted file mode 100644
index 52c88b039..000000000
--- a/src/pkg/exp/norm/triegen.go
+++ /dev/null
@@ -1,317 +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 ignore
-
-// Trie table generator.
-// Used by make*tables tools to generate a go file with trie data structures
-// for mapping UTF-8 to a 16-bit value. 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 with 16-bit values.
-
-package main
-
-import (
- "fmt"
- "hash/crc32"
- "log"
- "unicode/utf8"
-)
-
-const (
- blockSize = 64
- blockOffset = 2 // Subtract two blocks to compensate for the 0x80 added to continuation bytes.
- maxSparseEntries = 16
-)
-
-// Intermediate trie structure
-type trieNode struct {
- table [256]*trieNode
- value int
- b byte
- leaf bool
-}
-
-func newNode() *trieNode {
- return new(trieNode)
-}
-
-func (n trieNode) String() string {
- s := fmt.Sprint("trieNode{table: { non-nil at index: ")
- for i, v := range n.table {
- if v != nil {
- s += fmt.Sprintf("%d, ", i)
- }
- }
- s += fmt.Sprintf("}, value:%#x, b:%#x leaf:%v}", n.value, n.b, n.leaf)
- return s
-}
-
-func (n trieNode) isInternal() bool {
- internal := true
- for i := 0; i < 256; i++ {
- if nn := n.table[i]; nn != nil {
- if !internal && !nn.leaf {
- log.Fatalf("triegen: isInternal: node contains both leaf and non-leaf children (%v)", n)
- }
- internal = internal && !nn.leaf
- }
- }
- return internal
-}
-
-func (n trieNode) mostFrequentStride() int {
- counts := make(map[int]int)
- v := 0
- for _, t := range n.table[0x80 : 0x80+blockSize] {
- if t != nil {
- if stride := t.value - v; v != 0 && stride >= 0 {
- counts[stride]++
- }
- v = t.value
- } else {
- v = 0
- }
- }
- var maxs, maxc int
- for stride, cnt := range counts {
- if cnt > maxc || (cnt == maxc && stride < maxs) {
- maxs, maxc = stride, cnt
- }
- }
- return maxs
-}
-
-func (n trieNode) countSparseEntries() int {
- stride := n.mostFrequentStride()
- var count, v int
- for _, t := range n.table[0x80 : 0x80+blockSize] {
- tv := 0
- if t != nil {
- tv = t.value
- }
- if tv-v != stride {
- if tv != 0 {
- count++
- }
- }
- v = tv
- }
- return count
-}
-
-func (n *trieNode) insert(r rune, value uint16) {
- var p [utf8.UTFMax]byte
- sz := utf8.EncodeRune(p[:], r)
-
- for i := 0; i < sz; i++ {
- if n.leaf {
- log.Fatalf("triegen: insert: node (%#v) should not be a leaf", n)
- }
- nn := n.table[p[i]]
- if nn == nil {
- nn = newNode()
- nn.b = p[i]
- n.table[p[i]] = nn
- }
- n = nn
- }
- n.value = int(value)
- n.leaf = true
-}
-
-type nodeIndex struct {
- lookupBlocks []*trieNode
- valueBlocks []*trieNode
- sparseBlocks []*trieNode
- sparseOffset []uint16
- sparseCount int
-
- lookupBlockIdx map[uint32]int
- valueBlockIdx map[uint32]int
-}
-
-func newIndex() *nodeIndex {
- index := &nodeIndex{}
- index.lookupBlocks = make([]*trieNode, 0)
- index.valueBlocks = make([]*trieNode, 0)
- index.sparseBlocks = make([]*trieNode, 0)
- index.sparseOffset = make([]uint16, 1)
- index.lookupBlockIdx = make(map[uint32]int)
- index.valueBlockIdx = make(map[uint32]int)
- return index
-}
-
-func computeOffsets(index *nodeIndex, n *trieNode) int {
- if n.leaf {
- return n.value
- }
- hasher := crc32.New(crc32.MakeTable(crc32.IEEE))
- // We only index continuation bytes.
- for i := 0; i < blockSize; i++ {
- v := 0
- if nn := n.table[0x80+i]; nn != nil {
- v = computeOffsets(index, nn)
- }
- hasher.Write([]byte{uint8(v >> 8), uint8(v)})
- }
- h := hasher.Sum32()
- if n.isInternal() {
- v, ok := index.lookupBlockIdx[h]
- if !ok {
- v = len(index.lookupBlocks) - blockOffset
- index.lookupBlocks = append(index.lookupBlocks, n)
- index.lookupBlockIdx[h] = v
- }
- n.value = v
- } else {
- v, ok := index.valueBlockIdx[h]
- if !ok {
- if c := n.countSparseEntries(); c > maxSparseEntries {
- v = len(index.valueBlocks) - blockOffset
- index.valueBlocks = append(index.valueBlocks, n)
- index.valueBlockIdx[h] = v
- } else {
- v = -len(index.sparseOffset)
- index.sparseBlocks = append(index.sparseBlocks, n)
- index.sparseOffset = append(index.sparseOffset, uint16(index.sparseCount))
- index.sparseCount += c + 1
- index.valueBlockIdx[h] = v
- }
- }
- n.value = v
- }
- return n.value
-}
-
-func printValueBlock(nr int, n *trieNode, offset int) {
- boff := nr * blockSize
- fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
- var printnewline bool
- for i := 0; i < blockSize; i++ {
- if i%6 == 0 {
- printnewline = true
- }
- v := 0
- if nn := n.table[i+offset]; nn != nil {
- v = nn.value
- }
- if v != 0 {
- if printnewline {
- fmt.Printf("\n")
- printnewline = false
- }
- fmt.Printf("%#04x:%#04x, ", boff+i, v)
- }
- }
-}
-
-func printSparseBlock(nr int, n *trieNode) {
- boff := -n.value
- fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
- v := 0
- //stride := f(n)
- stride := n.mostFrequentStride()
- c := n.countSparseEntries()
- fmt.Printf("\n{value:%#04x,lo:%#02x},", stride, uint8(c))
- for i, nn := range n.table[0x80 : 0x80+blockSize] {
- nv := 0
- if nn != nil {
- nv = nn.value
- }
- if nv-v != stride {
- if v != 0 {
- fmt.Printf(",hi:%#02x},", 0x80+i-1)
- }
- if nv != 0 {
- fmt.Printf("\n{value:%#04x,lo:%#02x", nv, nn.b)
- }
- }
- v = nv
- }
- if v != 0 {
- fmt.Printf(",hi:%#02x},", 0x80+blockSize-1)
- }
-}
-
-func printLookupBlock(nr int, n *trieNode, offset, cutoff int) {
- boff := nr * blockSize
- fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
- var printnewline bool
- for i := 0; i < blockSize; i++ {
- if i%8 == 0 {
- printnewline = true
- }
- v := 0
- if nn := n.table[i+offset]; nn != nil {
- v = nn.value
- }
- if v != 0 {
- if v < 0 {
- v = -v - 1 + cutoff
- }
- if printnewline {
- fmt.Printf("\n")
- printnewline = false
- }
- fmt.Printf("%#03x:%#02x, ", boff+i, v)
- }
- }
-}
-
-// printTables returns the size in bytes of the generated tables.
-func (t *trieNode) printTables(name string) int {
- index := newIndex()
- // Values for 7-bit ASCII are stored in first two block, followed by nil block.
- index.valueBlocks = append(index.valueBlocks, nil, nil, nil)
- // First byte of multi-byte UTF-8 codepoints are indexed in 4th block.
- index.lookupBlocks = append(index.lookupBlocks, nil, nil, nil, nil)
- // Index starter bytes of multi-byte UTF-8.
- for i := 0xC0; i < 0x100; i++ {
- if t.table[i] != nil {
- computeOffsets(index, t.table[i])
- }
- }
-
- nv := len(index.valueBlocks) * blockSize
- fmt.Printf("// %sValues: %d entries, %d bytes\n", name, nv, nv*2)
- fmt.Printf("// Block 2 is the null block.\n")
- fmt.Printf("var %sValues = [%d]uint16 {", name, nv)
- printValueBlock(0, t, 0)
- printValueBlock(1, t, 64)
- printValueBlock(2, newNode(), 0)
- for i := 3; i < len(index.valueBlocks); i++ {
- printValueBlock(i, index.valueBlocks[i], 0x80)
- }
- fmt.Print("\n}\n\n")
-
- ls := len(index.sparseBlocks)
- fmt.Printf("// %sSparseOffset: %d entries, %d bytes\n", name, ls, ls*2)
- fmt.Printf("var %sSparseOffset = %#v\n\n", name, index.sparseOffset[1:])
-
- ns := index.sparseCount
- fmt.Printf("// %sSparseValues: %d entries, %d bytes\n", name, ns, ns*4)
- fmt.Printf("var %sSparseValues = [%d]valueRange {", name, ns)
- for i, n := range index.sparseBlocks {
- printSparseBlock(i, n)
- }
- fmt.Print("\n}\n\n")
-
- cutoff := len(index.valueBlocks) - blockOffset
- ni := len(index.lookupBlocks) * blockSize
- fmt.Printf("// %sLookup: %d bytes\n", name, ni)
- fmt.Printf("// Block 0 is the null block.\n")
- fmt.Printf("var %sLookup = [%d]uint8 {", name, ni)
- printLookupBlock(0, newNode(), 0, cutoff)
- printLookupBlock(1, newNode(), 0, cutoff)
- printLookupBlock(2, newNode(), 0, cutoff)
- printLookupBlock(3, t, 0xC0, cutoff)
- for i := 4; i < len(index.lookupBlocks); i++ {
- printLookupBlock(i, index.lookupBlocks[i], 0x80, cutoff)
- }
- fmt.Print("\n}\n\n")
- fmt.Printf("var %sTrie = trie{ %sLookup[:], %sValues[:], %sSparseValues[:], %sSparseOffset[:], %d}\n\n",
- name, name, name, name, name, cutoff)
- return nv*2 + ns*4 + ni + ls*2
-}
diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go
index af4b5c8f8..552f76931 100644
--- a/src/pkg/fmt/fmt_test.go
+++ b/src/pkg/fmt/fmt_test.go
@@ -9,6 +9,7 @@ import (
. "fmt"
"io"
"math"
+ "runtime"
"strings"
"testing"
"time"
@@ -601,6 +602,9 @@ var mallocTest = []struct {
var _ bytes.Buffer
func TestCountMallocs(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
for _, mt := range mallocTest {
mallocs := testing.AllocsPerRun(100, mt.fn)
if got, max := mallocs, float64(mt.count); got > max {
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go
index 16c3da458..dc3669c1d 100644
--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -27,15 +27,31 @@ import (
// A Context specifies the supporting context for a build.
type Context struct {
- GOARCH string // target architecture
- GOOS string // target operating system
- GOROOT string // Go root
- 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
+ GOARCH string // target architecture
+ GOOS string // target operating system
+ GOROOT string // Go root
+ GOPATH string // Go path
+ CgoEnabled bool // whether cgo can be used
+ UseAllFiles bool // use files regardless of +build lines, file names
+ Compiler string // compiler to assume when computing target paths
+
+ // The build and release tags specify build constraints
+ // that should be considered satisfied when processing +build lines.
+ // Clients creating a new context may customize BuildTags, which
+ // defaults to empty, but it is usually an error to customize ReleaseTags,
+ // which defaults to the list of Go releases the current release is compatible with.
+ // In addition to the BuildTags and ReleaseTags, build constraints
+ // consider the values of GOARCH and GOOS as satisfied tags.
+ BuildTags []string
+ ReleaseTags []string
+
+ // The install suffix specifies a suffix to use in the name of the installation
+ // directory. By default it is empty, but custom builds that need to keep
+ // their outputs separate can set InstallSuffix to do so. For example, when
+ // using the race detector, the go command uses InstallSuffix = "race", so
+ // that on a Linux/386 system, packages are written to a directory named
+ // "linux_386_race" instead of the usual "linux_386".
+ InstallSuffix string
// By default, Import uses the operating system's file system calls
// to read directories and files. To read from other sources,
@@ -196,8 +212,8 @@ func (ctxt *Context) gopath() []string {
// Do not get confused by this common mistake.
continue
}
- if strings.Contains(p, "~") && runtime.GOOS != "windows" {
- // Path segments containing ~ on Unix are almost always
+ if strings.HasPrefix(p, "~") {
+ // Path segments starting with ~ on Unix are almost always
// users who have incorrectly quoted ~ while setting GOPATH,
// preventing it from expanding to $HOME.
// The situation is made more confusing by the fact that
@@ -246,6 +262,7 @@ var cgoEnabled = map[string]bool{
"darwin/amd64": true,
"freebsd/386": true,
"freebsd/amd64": true,
+ "freebsd/arm": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
@@ -267,6 +284,17 @@ func defaultContext() Context {
c.GOPATH = envOr("GOPATH", "")
c.Compiler = runtime.Compiler
+ // Each major Go release in the Go 1.x series should add a tag here.
+ // Old tags should not be removed. That is, the go1.x tag is present
+ // in all releases >= Go 1.x. Code that requires Go 1.x or later should
+ // say "+build go1.x", and code that should only be built before Go 1.x
+ // (perhaps it is the stub to use in that case) should say "+build !go1.x".
+ //
+ // When we reach Go 1.3 the line will read
+ // c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
+ // and so on.
+ c.ReleaseTags = []string{"go1.1"}
+
switch os.Getenv("CGO_ENABLED") {
case "1":
c.CgoEnabled = true
@@ -397,11 +425,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":
- tag := ""
- if ctxt.InstallTag != "" {
- tag = "_" + ctxt.InstallTag
+ suffix := ""
+ if ctxt.InstallSuffix != "" {
+ suffix = "_" + ctxt.InstallSuffix
}
- pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + tag + "/" + p.ImportPath + ".a"
+ pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix + "/" + p.ImportPath + ".a"
default:
// Save error for end of function.
pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
@@ -458,7 +486,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
return p, fmt.Errorf("import %q: cannot import absolute path", path)
}
- // tried records the location of unsucsessful package lookups
+ // tried records the location of unsuccessful package lookups
var tried struct {
goroot string
gopath []string
@@ -970,8 +998,8 @@ func splitQuoted(s string) (r []string, err error) {
// !cgo (if cgo is disabled)
// ctxt.Compiler
// !ctxt.Compiler
-// tag (if tag is listed in ctxt.BuildTags)
-// !tag (if tag is not listed in ctxt.BuildTags)
+// tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags)
+// !tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags)
// a comma-separated list of any of these
//
func (ctxt *Context) match(name string) bool {
@@ -989,10 +1017,10 @@ func (ctxt *Context) match(name string) bool {
return len(name) > 1 && !ctxt.match(name[1:])
}
- // Tags must be letters, digits, underscores.
+ // Tags must be letters, digits, underscores or dots.
// Unlike in Go identifiers, all digits are fine (e.g., "386").
for _, c := range name {
- if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
+ if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
return false
}
}
@@ -1011,6 +1039,11 @@ func (ctxt *Context) match(name string) bool {
return true
}
}
+ for _, tag := range ctxt.ReleaseTags {
+ if tag == name {
+ return true
+ }
+ }
return false
}
diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go
index 65b1b83eb..96d867cae 100644
--- a/src/pkg/go/doc/doc.go
+++ b/src/pkg/go/doc/doc.go
@@ -17,17 +17,11 @@ type Package struct {
ImportPath string
Imports []string
Filenames []string
+ Notes map[string][]*Note
// DEPRECATED. For backward compatibility Bugs is still populated,
// but all new code should use Notes instead.
Bugs []string
- // Notes such as TODO(userid): or SECURITY(userid):
- // along the lines of BUG(userid). Any marker with 2 or more upper
- // case [A-Z] letters is recognised.
- // BUG is explicitly not included in these notes but will
- // be in a subsequent change when the Bugs field above is removed.
- Notes map[string][]string
-
// declarations
Consts []*Value
Types []*Type
@@ -70,6 +64,16 @@ type Func struct {
Level int // embedding level; 0 means not embedded
}
+// A Note represents marked comments starting with "MARKER(uid): note body".
+// Any note with a marker of 2 or more upper case [A-Z] letters and a uid of
+// at least one character is recognized. The ":" following the uid is optional.
+// Notes are collected in the Package.Notes map indexed by the notes marker.
+type Note struct {
+ Pos token.Pos // position of the comment containing the marker
+ UID string // uid found with the marker
+ Body string // note body text
+}
+
// Mode values control the operation of New.
type Mode int
@@ -97,8 +101,8 @@ func New(pkg *ast.Package, importPath string, mode Mode) *Package {
ImportPath: importPath,
Imports: sortedKeys(r.imports),
Filenames: r.filenames,
- Bugs: r.bugs,
Notes: r.notes,
+ Bugs: noteBodies(r.notes["BUG"]),
Consts: sortedValues(r.values, token.CONST),
Types: sortedTypes(r.types, mode&AllMethods != 0),
Vars: sortedValues(r.values, token.VAR),
diff --git a/src/pkg/go/doc/filter.go b/src/pkg/go/doc/filter.go
index 02b66ccef..a6f243f33 100644
--- a/src/pkg/go/doc/filter.go
+++ b/src/pkg/go/doc/filter.go
@@ -94,7 +94,7 @@ func filterTypes(a []*Type, f Filter) []*Type {
}
// Filter eliminates documentation for names that don't pass through the filter f.
-// TODO: Recognize "Type.Method" as a name.
+// TODO(gri): Recognize "Type.Method" as a name.
//
func (p *Package) Filter(f Filter) {
p.Consts = filterValues(p.Consts, f)
diff --git a/src/pkg/go/doc/reader.go b/src/pkg/go/doc/reader.go
index dd6a57299..7e1422d0c 100644
--- a/src/pkg/go/doc/reader.go
+++ b/src/pkg/go/doc/reader.go
@@ -148,8 +148,7 @@ type reader struct {
// package properties
doc string // package documentation, if any
filenames []string
- bugs []string
- notes map[string][]string
+ notes map[string][]*Note
// declarations
imports map[string]int
@@ -401,21 +400,54 @@ func (r *reader) readFunc(fun *ast.FuncDecl) {
}
var (
- noteMarker = regexp.MustCompile(`^/[/*][ \t]*([A-Z][A-Z]+)\(.+\):[ \t]*(.*)`) // MARKER(uid)
- noteContent = regexp.MustCompile(`[^ \n\r\t]+`) // at least one non-whitespace char
+ noteMarker = `([A-Z][A-Z]+)\(([^)]+)\):?` // MARKER(uid), MARKER at least 2 chars, uid at least 1 char
+ noteMarkerRx = regexp.MustCompile(`^[ \t]*` + noteMarker) // MARKER(uid) at text start
+ noteCommentRx = regexp.MustCompile(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start
)
-func readNote(c *ast.CommentGroup) (marker, annotation string) {
- text := c.List[0].Text
- if m := noteMarker.FindStringSubmatch(text); m != nil {
- if btxt := m[2]; noteContent.MatchString(btxt) {
- // non-empty MARKER comment; collect comment without the MARKER prefix
- list := append([]*ast.Comment(nil), c.List...) // make a copy
- list[0].Text = m[2]
- return m[1], (&ast.CommentGroup{List: list}).Text()
+// readNote collects a single note from a sequence of comments.
+//
+func (r *reader) readNote(list []*ast.Comment) {
+ text := (&ast.CommentGroup{List: list}).Text()
+ if m := noteMarkerRx.FindStringSubmatchIndex(text); m != nil {
+ // The note body starts after the marker.
+ // We remove any formatting so that we don't
+ // get spurious line breaks/indentation when
+ // showing the TODO body.
+ body := clean(text[m[1]:])
+ if body != "" {
+ marker := text[m[2]:m[3]]
+ r.notes[marker] = append(r.notes[marker], &Note{
+ Pos: list[0].Pos(),
+ UID: text[m[4]:m[5]],
+ Body: body,
+ })
+ }
+ }
+}
+
+// readNotes extracts notes from comments.
+// A note must start at the beginning of a comment with "MARKER(uid):"
+// and is followed by the note body (e.g., "// BUG(gri): fix this").
+// The note ends at the end of the comment group or at the start of
+// another note in the same comment group, whichever comes first.
+//
+func (r *reader) readNotes(comments []*ast.CommentGroup) {
+ for _, group := range comments {
+ i := -1 // comment index of most recent note start, valid if >= 0
+ list := group.List
+ for j, c := range list {
+ if noteCommentRx.MatchString(c.Text) {
+ if i >= 0 {
+ r.readNote(list[i:j])
+ }
+ i = j
+ }
+ }
+ if i >= 0 {
+ r.readNote(list[i:])
}
}
- return "", ""
}
// readFile adds the AST for a source file to the reader.
@@ -484,14 +516,7 @@ func (r *reader) readFile(src *ast.File) {
}
// collect MARKER(...): annotations
- for _, c := range src.Comments {
- if marker, text := readNote(c); marker != "" {
- r.notes[marker] = append(r.notes[marker], text)
- if marker == "BUG" {
- r.bugs = append(r.bugs, text)
- }
- }
- }
+ r.readNotes(src.Comments)
src.Comments = nil // consumed unassociated comments - remove from AST
}
@@ -502,7 +527,7 @@ func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
r.mode = mode
r.types = make(map[string]*namedType)
r.funcs = make(methodSet)
- r.notes = make(map[string][]string)
+ r.notes = make(map[string][]*Note)
// sort package files before reading them so that the
// result does not depend on map iteration order
@@ -533,10 +558,13 @@ func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int)
// copy existing receiver field and set new type
newField := *f.Decl.Recv.List[0]
+ origPos := newField.Type.Pos()
_, origRecvIsPtr := newField.Type.(*ast.StarExpr)
- var typ ast.Expr = ast.NewIdent(recvTypeName)
+ newIdent := &ast.Ident{NamePos: origPos, Name: recvTypeName}
+ var typ ast.Expr = newIdent
if !embeddedIsPtr && origRecvIsPtr {
- typ = &ast.StarExpr{X: typ}
+ newIdent.NamePos++ // '*' is one character
+ typ = &ast.StarExpr{Star: origPos, X: newIdent}
}
newField.Type = typ
@@ -761,6 +789,17 @@ func sortedFuncs(m methodSet, allMethods bool) []*Func {
return list
}
+// noteBodies returns a list of note body strings given a list of notes.
+// This is only used to populate the deprecated Package.Bugs field.
+//
+func noteBodies(notes []*Note) []string {
+ var list []string
+ for _, n := range notes {
+ list = append(list, n.Body)
+ }
+ return list
+}
+
// ----------------------------------------------------------------------------
// Predeclared identifiers
diff --git a/src/pkg/go/doc/testdata/a.0.golden b/src/pkg/go/doc/testdata/a.0.golden
index ae3756c84..cd98f4e0e 100644
--- a/src/pkg/go/doc/testdata/a.0.golden
+++ b/src/pkg/go/doc/testdata/a.0.golden
@@ -9,16 +9,24 @@ FILENAMES
testdata/a1.go
BUGS .Bugs is now deprecated, please use .Notes instead
- // bug0
- // bug1
+ // bug0
+ // bug1
BUGS
- // bug0
- // bug1
+ // bug0 (uid: uid)
+ // bug1 (uid: uid)
+
+NOTES
+ // 1 of 4 - this is the first line of note 1 - note 1 continues on ... (uid: foo)
+ // 2 of 4 (uid: foo)
+ // 3 of 4 (uid: bar)
+ // 4 of 4 - this is the last line of note 4 (uid: bar)
+ // This note which contains a (parenthesized) subphrase must ... (uid: bam)
+ // The ':' after the marker and uid is optional. (uid: xxx)
SECBUGS
- // sec hole 0 need to fix asap
+ // sec hole 0 need to fix asap (uid: uid)
TODOS
- // todo0
- // todo1
+ // todo0 (uid: uid)
+ // todo1 (uid: uid)
diff --git a/src/pkg/go/doc/testdata/a.1.golden b/src/pkg/go/doc/testdata/a.1.golden
index ae3756c84..cd98f4e0e 100644
--- a/src/pkg/go/doc/testdata/a.1.golden
+++ b/src/pkg/go/doc/testdata/a.1.golden
@@ -9,16 +9,24 @@ FILENAMES
testdata/a1.go
BUGS .Bugs is now deprecated, please use .Notes instead
- // bug0
- // bug1
+ // bug0
+ // bug1
BUGS
- // bug0
- // bug1
+ // bug0 (uid: uid)
+ // bug1 (uid: uid)
+
+NOTES
+ // 1 of 4 - this is the first line of note 1 - note 1 continues on ... (uid: foo)
+ // 2 of 4 (uid: foo)
+ // 3 of 4 (uid: bar)
+ // 4 of 4 - this is the last line of note 4 (uid: bar)
+ // This note which contains a (parenthesized) subphrase must ... (uid: bam)
+ // The ':' after the marker and uid is optional. (uid: xxx)
SECBUGS
- // sec hole 0 need to fix asap
+ // sec hole 0 need to fix asap (uid: uid)
TODOS
- // todo0
- // todo1
+ // todo0 (uid: uid)
+ // todo1 (uid: uid)
diff --git a/src/pkg/go/doc/testdata/a.2.golden b/src/pkg/go/doc/testdata/a.2.golden
index ae3756c84..cd98f4e0e 100644
--- a/src/pkg/go/doc/testdata/a.2.golden
+++ b/src/pkg/go/doc/testdata/a.2.golden
@@ -9,16 +9,24 @@ FILENAMES
testdata/a1.go
BUGS .Bugs is now deprecated, please use .Notes instead
- // bug0
- // bug1
+ // bug0
+ // bug1
BUGS
- // bug0
- // bug1
+ // bug0 (uid: uid)
+ // bug1 (uid: uid)
+
+NOTES
+ // 1 of 4 - this is the first line of note 1 - note 1 continues on ... (uid: foo)
+ // 2 of 4 (uid: foo)
+ // 3 of 4 (uid: bar)
+ // 4 of 4 - this is the last line of note 4 (uid: bar)
+ // This note which contains a (parenthesized) subphrase must ... (uid: bam)
+ // The ':' after the marker and uid is optional. (uid: xxx)
SECBUGS
- // sec hole 0 need to fix asap
+ // sec hole 0 need to fix asap (uid: uid)
TODOS
- // todo0
- // todo1
+ // todo0 (uid: uid)
+ // todo1 (uid: uid)
diff --git a/src/pkg/go/doc/testdata/a0.go b/src/pkg/go/doc/testdata/a0.go
index 71af470ee..2420c8a48 100644
--- a/src/pkg/go/doc/testdata/a0.go
+++ b/src/pkg/go/doc/testdata/a0.go
@@ -15,3 +15,26 @@ package a
// SECBUG(uid): sec hole 0
// need to fix asap
+
+// Multiple notes may be in the same comment group and should be
+// recognized individually. Notes may start in the middle of a
+// comment group as long as they start at the beginning of an
+// individual comment.
+//
+// NOTE(foo): 1 of 4 - this is the first line of note 1
+// - note 1 continues on this 2nd line
+// - note 1 continues on this 3rd line
+// NOTE(foo): 2 of 4
+// NOTE(bar): 3 of 4
+/* NOTE(bar): 4 of 4 */
+// - this is the last line of note 4
+//
+//
+
+// NOTE(bam): This note which contains a (parenthesized) subphrase
+// must appear in its entirety.
+
+// NOTE(xxx) The ':' after the marker and uid is optional.
+
+// NOTE(): NO uid - should not show up.
+// NOTE() NO uid - should not show up.
diff --git a/src/pkg/go/doc/testdata/template.txt b/src/pkg/go/doc/testdata/template.txt
index d3882b6b9..26482f7c2 100644
--- a/src/pkg/go/doc/testdata/template.txt
+++ b/src/pkg/go/doc/testdata/template.txt
@@ -64,5 +64,5 @@ BUGS .Bugs is now deprecated, please use .Notes instead
{{range .}} {{synopsis .}}
{{end}}{{end}}{{with .Notes}}{{range $marker, $content := .}}
{{$marker}}S
-{{range $content}} {{synopsis .}}
+{{range $content}} {{synopsis .Body}} (uid: {{.UID}})
{{end}}{{end}}{{end}} \ No newline at end of file
diff --git a/src/pkg/go/format/format.go b/src/pkg/go/format/format.go
index 65b0e4e4b..3d00a645d 100644
--- a/src/pkg/go/format/format.go
+++ b/src/pkg/go/format/format.go
@@ -69,15 +69,14 @@ func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
return config.Fprint(dst, fset, node)
}
-// Source formats src in canonical gofmt style and writes the result to dst
-// or returns an I/O or syntax error. src is expected to be a syntactically
+// Source formats src in canonical gofmt style and returns the result
+// or an (I/O or syntax) error. src is expected to be a syntactically
// correct Go source file, or a list of Go declarations or statements.
//
// If src is a partial source file, the leading and trailing space of src
// is applied to the result (such that it has the same leading and trailing
-// space as src), and the formatted src is indented by the same amount as
-// the first line of src containing code. Imports are not sorted for partial
-// source files.
+// space as src), and the result is indented by the same amount as the first
+// line of src containing code. Imports are not sorted for partial source files.
//
func Source(src []byte) ([]byte, error) {
fset := token.NewFileSet()
diff --git a/src/pkg/go/parser/error_test.go b/src/pkg/go/parser/error_test.go
index b59fda11a..d4d4f909d 100644
--- a/src/pkg/go/parser/error_test.go
+++ b/src/pkg/go/parser/error_test.go
@@ -89,8 +89,6 @@ func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]str
prev = pos
}
}
-
- panic("unreachable")
}
// compareErrors compares the map of expected error messages with the list
diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go
index a021a5abe..f4a690a6f 100644
--- a/src/pkg/go/parser/parser.go
+++ b/src/pkg/go/parser/parser.go
@@ -48,7 +48,8 @@ type parser struct {
syncCnt int // number of calls to syncXXX without progress
// Non-syntactic parser control
- exprLev int // < 0: in control clause, >= 0: in expression
+ exprLev int // < 0: in control clause, >= 0: in expression
+ inRhs bool // if set, the parser is parsing a rhs expression
// Ordinary identifier scopes
pkgScope *ast.Scope // pkgScope.Outer == nil
@@ -539,6 +540,8 @@ func (p *parser) parseExprList(lhs bool) (list []ast.Expr) {
}
func (p *parser) parseLhsList() []ast.Expr {
+ old := p.inRhs
+ p.inRhs = false
list := p.parseExprList(true)
switch p.tok {
case token.DEFINE:
@@ -560,11 +563,16 @@ func (p *parser) parseLhsList() []ast.Expr {
p.resolve(x)
}
}
+ p.inRhs = old
return list
}
func (p *parser) parseRhsList() []ast.Expr {
- return p.parseExprList(false)
+ old := p.inRhs
+ p.inRhs = true
+ list := p.parseExprList(false)
+ p.inRhs = old
+ return list
}
// ----------------------------------------------------------------------------
@@ -1505,6 +1513,14 @@ func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
return p.parsePrimaryExpr(lhs)
}
+func (p *parser) tokPrec() (token.Token, int) {
+ tok := p.tok
+ if p.inRhs && tok == token.ASSIGN {
+ tok = token.EQL
+ }
+ return tok, tok.Precedence()
+}
+
// If lhs is set and the result is an identifier, it is not resolved.
func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
if p.trace {
@@ -1512,10 +1528,13 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
}
x := p.parseUnaryExpr(lhs)
- for prec := p.tok.Precedence(); prec >= prec1; prec-- {
- for p.tok.Precedence() == prec {
- pos, op := p.pos, p.tok
- p.next()
+ for _, prec := p.tokPrec(); prec >= prec1; prec-- {
+ for {
+ op, oprec := p.tokPrec()
+ if oprec != prec {
+ break
+ }
+ pos := p.expect(op)
if lhs {
p.resolve(x)
lhs = false
@@ -1541,11 +1560,19 @@ func (p *parser) parseExpr(lhs bool) ast.Expr {
}
func (p *parser) parseRhs() ast.Expr {
- return p.checkExpr(p.parseExpr(false))
+ old := p.inRhs
+ p.inRhs = true
+ x := p.checkExpr(p.parseExpr(false))
+ p.inRhs = old
+ return x
}
func (p *parser) parseRhsOrType() ast.Expr {
- return p.checkExprOrType(p.parseExpr(false))
+ old := p.inRhs
+ p.inRhs = true
+ x := p.checkExprOrType(p.parseExpr(false))
+ p.inRhs = old
+ return x
}
// ----------------------------------------------------------------------------
@@ -2091,7 +2118,7 @@ func (p *parser) parseStmt() (s ast.Stmt) {
// ----------------------------------------------------------------------------
// Declarations
-type parseSpecFunction func(p *parser, doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
+type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
func isValidImport(lit string) bool {
const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
@@ -2210,12 +2237,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, keyword, iota))
+ list = append(list, f(p.leadComment, keyword, iota))
}
rparen = p.expect(token.RPAREN)
p.expectSemi()
} else {
- list = append(list, f(p, nil, keyword, 0))
+ list = append(list, f(nil, keyword, 0))
}
return &ast.GenDecl{
@@ -2316,10 +2343,10 @@ func (p *parser) parseDecl(sync func(*parser)) ast.Decl {
var f parseSpecFunction
switch p.tok {
case token.CONST, token.VAR:
- f = (*parser).parseValueSpec
+ f = p.parseValueSpec
case token.TYPE:
- f = (*parser).parseTypeSpec
+ f = p.parseTypeSpec
case token.FUNC:
return p.parseFuncDecl()
@@ -2371,7 +2398,7 @@ func (p *parser) parseFile() *ast.File {
if p.mode&PackageClauseOnly == 0 {
// import decls
for p.tok == token.IMPORT {
- decls = append(decls, p.parseGenDecl(token.IMPORT, (*parser).parseImportSpec))
+ decls = append(decls, p.parseGenDecl(token.IMPORT, p.parseImportSpec))
}
if p.mode&ImportsOnly == 0 {
diff --git a/src/pkg/go/parser/short_test.go b/src/pkg/go/parser/short_test.go
index c62f7e050..62277c0d2 100644
--- a/src/pkg/go/parser/short_test.go
+++ b/src/pkg/go/parser/short_test.go
@@ -71,6 +71,9 @@ var invalids = []string{
`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) };`,
`package p; func f() { var t []int; t /* ERROR "expected identifier on left side of :=" */ [0] := 0 };`,
+ `package p; func f() { if x := g(); x = /* ERROR "expected '=='" */ 0 {}};`,
+ `package p; func f() { _ = x = /* ERROR "expected '=='" */ 0 {}};`,
+ `package p; func f() { _ = 1 == func()int { var x bool; x = x = /* ERROR "expected '=='" */ true; return x }() };`,
}
func TestInvalid(t *testing.T) {
diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go
index ee0bbf1ed..7cd068e22 100644
--- a/src/pkg/go/printer/nodes.go
+++ b/src/pkg/go/printer/nodes.go
@@ -271,12 +271,12 @@ func (p *printer) parameters(fields *ast.FieldList) {
// if there are multiple parameter names for this par
// or the type is on a separate line)
var parLineBeg int
- var parLineEnd = p.lineFor(par.Type.Pos())
if len(par.Names) > 0 {
parLineBeg = p.lineFor(par.Names[0].Pos())
} else {
- parLineBeg = parLineEnd
+ parLineBeg = p.lineFor(par.Type.Pos())
}
+ var parLineEnd = p.lineFor(par.Type.End())
// separating "," if needed
needsLinebreak := 0 < prevLine && prevLine < parLineBeg
if i > 0 {
diff --git a/src/pkg/go/printer/testdata/declarations.golden b/src/pkg/go/printer/testdata/declarations.golden
index 0ad72d349..0331615e5 100644
--- a/src/pkg/go/printer/testdata/declarations.golden
+++ b/src/pkg/go/printer/testdata/declarations.golden
@@ -912,3 +912,28 @@ func _(x chan (<-chan int))
func _(x chan<- (chan int))
func _(x chan<- (chan int))
func _(x chan<- (chan int))
+
+// don't introduce comma after last parameter if the closing ) is on the same line
+// even if the parameter type itself is multi-line (test cases from issue 4533)
+func _(...interface{})
+func _(...interface {
+ m()
+ n()
+}) // no extra comma between } and )
+
+func (t *T) _(...interface{})
+func (t *T) _(...interface {
+ m()
+ n()
+}) // no extra comma between } and )
+
+func _(interface{})
+func _(interface {
+ m()
+}) // no extra comma between } and )
+
+func _(struct{})
+func _(struct {
+ x int
+ y int
+}) // no extra comma between } and )
diff --git a/src/pkg/go/printer/testdata/declarations.input b/src/pkg/go/printer/testdata/declarations.input
index 455c0c6c1..dbdbdfe74 100644
--- a/src/pkg/go/printer/testdata/declarations.input
+++ b/src/pkg/go/printer/testdata/declarations.input
@@ -921,3 +921,28 @@ func _(x ((((chan(<-chan int))))))
func _(x chan<-(chan int))
func _(x (chan<-(chan int)))
func _(x ((((chan<-(chan int))))))
+
+// don't introduce comma after last parameter if the closing ) is on the same line
+// even if the parameter type itself is multi-line (test cases from issue 4533)
+func _(...interface{})
+func _(...interface {
+ m()
+ n()
+}) // no extra comma between } and )
+
+func (t *T) _(...interface{})
+func (t *T) _(...interface {
+ m()
+ n()
+}) // no extra comma between } and )
+
+func _(interface{})
+func _(interface {
+ m()
+}) // no extra comma between } and )
+
+func _(struct{})
+func _(struct {
+ x int
+ y int
+}) // no extra comma between } and )
diff --git a/src/pkg/go/types/api.go b/src/pkg/go/types/api.go
deleted file mode 100644
index 13b453faa..000000000
--- a/src/pkg/go/types/api.go
+++ /dev/null
@@ -1,105 +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.
-
-// Package types declares the data structures for representing
-// Go types and implements typechecking of package files.
-//
-// WARNING: THE TYPES API IS SUBJECT TO CHANGE.
-//
-package types
-
-import (
- "go/ast"
- "go/token"
-)
-
-// A Context specifies the supporting context for type checking.
-// An empty Context is a ready-to-use default context.
-type Context struct {
- // If Error != nil, it is called with each error found
- // during type checking. The error strings of errors with
- // detailed position information are formatted as follows:
- // filename:line:column: message
- Error func(err error)
-
- // If Ident != nil, it is called for each identifier id
- // denoting an Object in the files provided to Check, and
- // obj is the denoted object.
- // Ident is not called for fields and methods in struct or
- // interface types or composite literals, or for blank (_)
- // or dot (.) identifiers in dot-imports.
- // TODO(gri) Consider making Fields and Methods ordinary
- // Objects - than we could lift this restriction.
- Ident func(id *ast.Ident, obj Object)
-
- // If Expr != nil, it is called exactly once for each expression x
- // that is type-checked: typ is the expression type, and val is the
- // value if x is constant, val is nil otherwise.
- //
- // If x is a literal value (constant, composite literal), typ is always
- // the dynamic type of x (never an interface type). Otherwise, typ is x's
- // static type (possibly an interface type).
- //
- // Constants are represented as follows:
- //
- // bool -> bool
- // numeric -> int64, *big.Int, *big.Rat, Complex
- // string -> string
- // nil -> NilType
- //
- // Constant values are normalized, that is, they are represented
- // using the "smallest" possible type that can represent the value.
- // For instance, 1.0 is represented as an int64 because it can be
- // represented accurately as an int64.
- Expr func(x ast.Expr, typ Type, val interface{})
-
- // If Import != nil, it is called for each imported package.
- // Otherwise, GcImporter is called.
- Import Importer
-
- // If Alignof != nil, it is called to determine the alignment
- // of the given type. Otherwise DefaultAlignmentof is called.
- // Alignof must implement the alignment guarantees required by
- // the spec.
- Alignof func(Type) int64
-
- // If Offsetsof != nil, it is called to determine the offsets
- // of the given struct fields, in bytes. Otherwise DefaultOffsetsof
- // is called. Offsetsof must implement the offset guarantees
- // required by the spec.
- Offsetsof func(fields []*Field) []int64
-
- // If Sizeof != nil, it is called to determine the size of the
- // given type. Otherwise, DefaultSizeof is called. Sizeof must
- // implement the size guarantees required by the spec.
- Sizeof func(Type) int64
-}
-
-// An Importer resolves import paths to Package objects.
-// The imports map records the packages already imported,
-// indexed by package id (canonical import path).
-// An Importer must determine the canonical import path and
-// check the map to see if it is already present in the imports map.
-// If so, the Importer can return the map entry. Otherwise, the
-// Importer should load the package data for the given path into
-// a new *Package, record pkg in the imports map, and then
-// return pkg.
-type Importer func(imports map[string]*Package, path string) (pkg *Package, err error)
-
-// Check resolves and typechecks a set of package files within the given
-// context. It returns the package and the first error encountered, if
-// any. If the context's Error handler is nil, Check terminates as soon
-// as the first error is encountered; otherwise it continues until the
-// entire package is checked. If there are errors, the package may be
-// only partially type-checked, and the resulting package may be incomplete
-// (missing objects, imports, etc.).
-func (ctxt *Context) Check(fset *token.FileSet, files []*ast.File) (*Package, error) {
- return check(ctxt, fset, files)
-}
-
-// Check is shorthand for ctxt.Check where ctxt is a default (empty) context.
-func Check(fset *token.FileSet, files []*ast.File) (*Package, error) {
- var ctxt Context
- return ctxt.Check(fset, files)
-}
diff --git a/src/pkg/go/types/builtins.go b/src/pkg/go/types/builtins.go
deleted file mode 100644
index ad9259118..000000000
--- a/src/pkg/go/types/builtins.go
+++ /dev/null
@@ -1,455 +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.
-
-// 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 // first argument, if present
-
- // 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, _Print, _Println, _Offsetof, _Trace:
- // respective cases below do the work
- default:
- // argument must be an expression
- check.expr(x, arg0, nil, iota)
- if x.mode == invalid {
- goto Error
- }
- }
- }
-
- switch id {
- case _Append:
- if _, ok := underlying(x.typ).(*Slice); !ok {
- check.invalidArg(x.pos(), "%s is not a typed slice", x)
- goto Error
- }
- resultTyp := x.typ
- 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 = resultTyp
-
- case _Cap, _Len:
- mode := invalid
- var val interface{}
- switch typ := implicitArrayDeref(underlying(x.typ)).(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
- // spec: "The expressions len(s) and cap(s) are constants
- // if the type of s is an array or pointer to an array and
- // the expression s does not contain channel receives or
- // function calls; in this case s is not evaluated."
- if !check.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 := underlying(x.typ).(*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:
- if !check.complexArg(x) {
- goto Error
- }
-
- var y operand
- check.expr(&y, args[1], nil, iota)
- if y.mode == invalid {
- goto Error
- }
- if !check.complexArg(&y) {
- goto Error
- }
-
- check.convertUntyped(x, y.typ)
- if x.mode == invalid {
- goto Error
- }
- check.convertUntyped(&y, x.typ)
- if y.mode == invalid {
- goto Error
- }
-
- if !IsIdentical(x.typ, y.typ) {
- check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
- goto Error
- }
-
- typ := underlying(x.typ).(*Basic)
- if x.mode == constant && y.mode == constant {
- x.val = binaryOpConst(x.val, toImagConst(y.val), token.ADD, typ)
- } else {
- x.mode = value
- }
-
- switch typ.Kind {
- case Float32:
- x.typ = Typ[Complex64]
- case Float64:
- x.typ = Typ[Complex128]
- case UntypedInt, UntypedRune, UntypedFloat:
- x.typ = Typ[UntypedComplex]
- default:
- check.invalidArg(x.pos(), "float32 or float64 arguments expected")
- goto Error
- }
-
- case _Copy:
- var y operand
- check.expr(&y, args[1], nil, iota)
- if y.mode == invalid {
- goto Error
- }
-
- var dst, src Type
- if t, ok := underlying(x.typ).(*Slice); ok {
- dst = t.Elt
- }
- switch t := underlying(y.typ).(type) {
- case *Basic:
- if isString(y.typ) {
- src = Typ[Byte]
- }
- case *Slice:
- src = t.Elt
- }
-
- if dst == nil || src == nil {
- check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y)
- goto Error
- }
-
- if !IsIdentical(dst, src) {
- check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
- goto Error
- }
-
- x.mode = value
- x.typ = Typ[Int]
-
- case _Delete:
- m, ok := underlying(x.typ).(*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(check.ctxt, 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(x.typ) {
- 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 underlying(x.typ).(*Basic).Kind {
- case Complex64:
- k = Float32
- case Complex128:
- k = Float64
- case UntypedComplex:
- k = UntypedFloat
- default:
- unreachable()
- }
- x.typ = Typ[k]
-
- case _Make:
- resultTyp := check.typ(arg0, false)
- if resultTyp == Typ[Invalid] {
- goto Error
- }
- var min int // minimum number of arguments
- switch underlying(resultTyp).(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
- }
- var sizes []interface{} // constant integer arguments, if any
- for _, arg := range args[1:] {
- check.expr(x, arg, nil, iota)
- if x.isInteger(check.ctxt) {
- if x.mode == constant {
- if isNegConst(x.val) {
- check.invalidArg(x.pos(), "%s must not be negative", x)
- // safe to continue
- } else {
- sizes = append(sizes, x.val) // x.val >= 0
- }
- }
- } else {
- check.invalidArg(x.pos(), "%s must be an integer", x)
- // safe to continue
- }
- }
- if len(sizes) == 2 && compareConst(sizes[0], sizes[1], token.GTR) {
- check.invalidArg(args[1].Pos(), "length and capacity swapped")
- // safe to continue
- }
- x.mode = variable
- x.typ = resultTyp
-
- case _New:
- resultTyp := check.typ(arg0, false)
- if resultTyp == Typ[Invalid] {
- goto Error
- }
- x.mode = variable
- x.typ = &Pointer{Base: resultTyp}
-
- case _Panic:
- x.mode = novalue
-
- case _Print, _Println:
- for _, arg := range args {
- check.expr(x, arg, nil, -1)
- if x.mode == invalid {
- goto Error
- }
- }
- x.mode = novalue
-
- case _Recover:
- x.mode = value
- x.typ = new(Interface)
-
- case _Alignof:
- x.mode = constant
- x.val = check.ctxt.alignof(x.typ)
- x.typ = Typ[Uintptr]
-
- case _Offsetof:
- arg, ok := unparen(arg0).(*ast.SelectorExpr)
- if !ok {
- check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
- goto Error
- }
- check.expr(x, arg.X, nil, -1)
- if x.mode == invalid {
- goto Error
- }
- sel := arg.Sel.Name
- res := lookupField(x.typ, QualifiedName{check.pkg, arg.Sel.Name})
- if res.index == nil {
- check.invalidArg(x.pos(), "%s has no single field %s", x, sel)
- goto Error
- }
- offs := check.ctxt.offsetof(deref(x.typ), res.index)
- if offs < 0 {
- check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, x)
- goto Error
- }
- x.mode = constant
- x.val = offs
- x.typ = Typ[Uintptr]
-
- case _Sizeof:
- x.mode = constant
- x.val = check.ctxt.sizeof(x.typ)
- x.typ = Typ[Uintptr]
-
- 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(x.typ) {
- 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.rawExpr(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
-}
-
-// implicitArrayDeref returns A if typ is of the form *A and A is an array;
-// otherwise it returns typ.
-//
-func implicitArrayDeref(typ Type) Type {
- if p, ok := typ.(*Pointer); ok {
- if a, ok := underlying(p.Base).(*Array); ok {
- return a
- }
- }
- return typ
-}
-
-// containsCallsOrReceives reports if x contains function calls or channel receives.
-// Expects that x was type-checked already.
-//
-func (check *checker) containsCallsOrReceives(x ast.Expr) (found bool) {
- ast.Inspect(x, func(x ast.Node) bool {
- switch x := x.(type) {
- case *ast.CallExpr:
- // calls and conversions look the same
- if !check.conversions[x] {
- found = true
- }
- case *ast.UnaryExpr:
- if x.Op == token.ARROW {
- found = true
- }
- }
- return !found // no need to continue if found
- })
- return
-}
-
-// 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
-}
-
-func (check *checker) complexArg(x *operand) bool {
- t, _ := underlying(x.typ).(*Basic)
- if t != nil && (t.Info&IsFloat != 0 || t.Kind == UntypedInt || t.Kind == UntypedRune) {
- return true
- }
- check.invalidArg(x.pos(), "%s must be a float32, float64, or an untyped non-complex numeric constant", x)
- return false
-}
diff --git a/src/pkg/go/types/check.go b/src/pkg/go/types/check.go
deleted file mode 100644
index f7b87e30c..000000000
--- a/src/pkg/go/types/check.go
+++ /dev/null
@@ -1,507 +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.
-
-// This file implements the Check function, which typechecks a package.
-
-package types
-
-import (
- "fmt"
- "go/ast"
- "go/token"
-)
-
-// debugging support
-const (
- debug = true // leave on during development
- trace = false // turn on for detailed type resolution traces
-)
-
-type checker struct {
- ctxt *Context
- fset *token.FileSet
- files []*ast.File
-
- // lazily initialized
- pkg *Package // current package
- firsterr error // first error encountered
- idents map[*ast.Ident]Object // maps identifiers to their unique object
- objects map[*ast.Object]Object // maps *ast.Objects to their unique object
- initspecs map[*ast.ValueSpec]*ast.ValueSpec // "inherited" type and initialization expressions for constant declarations
- methods map[*TypeName]*Scope // maps type names to associated methods
- conversions map[*ast.CallExpr]bool // set of type-checked conversions (to distinguish from calls)
-
- // untyped expressions
- // TODO(gri): Consider merging the untyped and constants map. Should measure
- // the ratio between untyped non-constant and untyped constant expressions
- // to make an informed decision.
- untyped map[ast.Expr]*Basic // map of expressions of untyped type
- constants map[ast.Expr]interface{} // map of untyped constant expressions; each key also appears in untyped
- shiftOps map[ast.Expr]bool // map of lhs shift operands with delayed type-checking
-
- // functions
- funclist []function // list of functions/methods with correct signatures and non-empty bodies
- funcsig *Signature // signature of currently typechecked function
- pos []token.Pos // stack of expr positions; debugging support, used if trace is set
-}
-
-func (check *checker) register(id *ast.Ident, obj Object) {
- // When an expression is evaluated more than once (happens
- // in rare cases, e.g. for statement expressions, see
- // comment in stmt.go), the object has been registered
- // before. Don't do anything in that case.
- if alt := check.idents[id]; alt != nil {
- assert(alt == obj)
- return
- }
- check.idents[id] = obj
- if f := check.ctxt.Ident; f != nil {
- f(id, obj)
- }
-}
-
-// lookup returns the unique Object denoted by the identifier.
-// For identifiers without assigned *ast.Object, it uses the
-// checker.idents map; for identifiers with an *ast.Object it
-// uses the checker.objects map.
-//
-// TODO(gri) Once identifier resolution is done entirely by
-// the typechecker, only the idents map is needed.
-//
-func (check *checker) lookup(ident *ast.Ident) Object {
- obj := check.idents[ident]
- astObj := ident.Obj
-
- if obj != nil {
- assert(astObj == nil || check.objects[astObj] == nil || check.objects[astObj] == obj)
- return obj
- }
-
- if astObj == nil {
- return nil
- }
-
- if obj = check.objects[astObj]; obj == nil {
- obj = newObj(check.pkg, astObj)
- check.objects[astObj] = obj
- }
- check.register(ident, obj)
-
- return obj
-}
-
-type function struct {
- obj *Func // for debugging/tracing only
- sig *Signature
- body *ast.BlockStmt
-}
-
-// later adds a function with non-empty body to the list of functions
-// that need to be processed after all package-level declarations
-// are typechecked.
-//
-func (check *checker) later(f *Func, sig *Signature, body *ast.BlockStmt) {
- // functions implemented elsewhere (say in assembly) have no body
- if body != nil {
- check.funclist = append(check.funclist, function{f, sig, body})
- }
-}
-
-func (check *checker) declareIdent(scope *Scope, ident *ast.Ident, obj Object) {
- assert(check.lookup(ident) == nil) // identifier already declared or resolved
- check.register(ident, obj)
- if ident.Name != "_" {
- if alt := scope.Insert(obj); alt != nil {
- prevDecl := ""
- if pos := alt.GetPos(); 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 Object, lhs []*ast.Ident, spec *ast.ValueSpec, iota int) {
- if len(lhs) == 0 {
- check.invalidAST(pos, "missing lhs in declaration")
- return
- }
-
- // determine type for all of lhs, if any
- // (but only set it for the object we typecheck!)
- var typ Type
- if spec.Type != nil {
- typ = check.typ(spec.Type, false)
- }
-
- // len(lhs) > 0
- rhs := spec.Values
- if len(lhs) == len(rhs) {
- // check only lhs and rhs corresponding to obj
- var l, r ast.Expr
- for i, name := range lhs {
- if check.lookup(name) == obj {
- l = lhs[i]
- r = rhs[i]
- break
- }
- }
- assert(l != nil)
- switch obj := obj.(type) {
- case *Const:
- obj.Type = typ
- case *Var:
- obj.Type = typ
- default:
- unreachable()
- }
- check.assign1to1(l, r, nil, true, iota)
- return
- }
-
- // there must be a type or initialization expressions
- if typ == nil && len(rhs) == 0 {
- check.invalidAST(pos, "missing type or initialization expression")
- typ = Typ[Invalid]
- }
-
- // if we have a type, mark all of lhs
- if typ != nil {
- for _, name := range lhs {
- switch obj := check.lookup(name).(type) {
- case *Const:
- obj.Type = typ
- case *Var:
- obj.Type = typ
- default:
- unreachable()
- }
- }
- }
-
- // 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)
- }
-}
-
-// object typechecks an object by assigning it a type.
-//
-func (check *checker) object(obj Object, cycleOk bool) {
- switch obj := obj.(type) {
- case *Package:
- // nothing to do
- case *Const:
- if obj.Type != nil {
- return // already checked
- }
- // The obj.Val field for constants is initialized to its respective
- // iota value by the parser.
- // The object's fields can be in one of the following states:
- // Type != nil => the constant value is Val
- // Type == nil => the constant is not typechecked yet, and Val can be:
- // Val is int => Val is the value of iota for this declaration
- // Val == nil => the object's expression is being evaluated
- if obj.Val == nil {
- check.errorf(obj.GetPos(), "illegal cycle in initialization of %s", obj.Name)
- obj.Type = Typ[Invalid]
- return
- }
- spec := obj.spec
- iota := obj.Val.(int)
- obj.Val = nil // mark obj as "visited" for cycle detection
- // determine spec for type and initialization expressions
- init := spec
- if len(init.Values) == 0 {
- init = check.initspecs[spec]
- }
- check.valueSpec(spec.Pos(), obj, spec.Names, init, iota)
-
- case *Var:
- if obj.Type != nil {
- return // already checked
- }
- if obj.visited {
- check.errorf(obj.GetPos(), "illegal cycle in initialization of %s", obj.Name)
- obj.Type = Typ[Invalid]
- return
- }
- switch d := obj.decl.(type) {
- case *ast.Field:
- unreachable() // function parameters are always typed when collected
- case *ast.ValueSpec:
- obj.visited = true
- check.valueSpec(d.Pos(), obj, d.Names, d, 0)
- case *ast.AssignStmt:
- // If we reach here, we have a short variable declaration
- // where the rhs didn't typecheck and thus the lhs has no
- // types.
- obj.visited = true
- obj.Type = Typ[Invalid]
- default:
- unreachable() // see also function newObj
- }
-
- case *TypeName:
- if obj.Type != nil {
- return // already checked
- }
- typ := &NamedType{Obj: obj}
- obj.Type = typ // "mark" object so recursion terminates
- typ.Underlying = underlying(check.typ(obj.spec.Type, cycleOk))
- // typecheck associated method signatures
- if scope := check.methods[obj]; scope != nil {
- switch t := typ.Underlying.(type) {
- case *Struct:
- // struct fields must not conflict with methods
- for _, f := range t.Fields {
- if m := scope.Lookup(f.Name); m != nil {
- check.errorf(m.GetPos(), "type %s has both field and method named %s", obj.Name, f.Name)
- // ok to continue
- }
- }
- case *Interface:
- // methods cannot be associated with an interface type
- for _, m := range scope.Entries {
- recv := m.(*Func).decl.Recv.List[0].Type
- check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
- // ok to continue
- }
- }
- // typecheck method signatures
- var methods []*Method
- for _, obj := range scope.Entries {
- m := obj.(*Func)
- sig := check.typ(m.decl.Type, cycleOk).(*Signature)
- params, _ := check.collectParams(m.decl.Recv, false)
- sig.Recv = params[0] // the parser/assocMethod ensure there is exactly one parameter
- m.Type = sig
- methods = append(methods, &Method{QualifiedName{check.pkg, m.Name}, sig})
- check.later(m, sig, m.decl.Body)
- }
- typ.Methods = methods
- delete(check.methods, obj) // we don't need this scope anymore
- }
-
- case *Func:
- if obj.Type != nil {
- return // already checked
- }
- fdecl := obj.decl
- // methods are typechecked when their receivers are typechecked
- if fdecl.Recv == nil {
- sig := check.typ(fdecl.Type, cycleOk).(*Signature)
- if obj.Name == "init" && (len(sig.Params) != 0 || len(sig.Results) != 0) {
- check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
- // ok to continue
- }
- obj.Type = sig
- check.later(obj, sig, fdecl.Body)
- }
-
- default:
- unreachable()
- }
-}
-
-// assocInitvals associates "inherited" initialization expressions
-// with the corresponding *ast.ValueSpec in the check.initspecs map
-// for constant declarations without explicit initialization expressions.
-//
-func (check *checker) assocInitvals(decl *ast.GenDecl) {
- var last *ast.ValueSpec
- for _, s := range decl.Specs {
- if s, ok := s.(*ast.ValueSpec); ok {
- if len(s.Values) > 0 {
- last = s
- } else {
- check.initspecs[s] = last
- }
- }
- }
- if last == nil {
- 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 name
- ident, ok := typ.(*ast.Ident)
- if !ok {
- // not an identifier - parser reported error already
- return // ignore this method
- }
- // determine receiver base type object
- var tname *TypeName
- if obj := check.lookup(ident); obj != nil {
- obj, ok := obj.(*TypeName)
- if !ok {
- check.errorf(ident.Pos(), "%s is not a type", ident.Name)
- return // ignore this method
- }
- if obj.spec == nil {
- check.errorf(ident.Pos(), "cannot define method on non-local type %s", ident.Name)
- return // ignore this method
- }
- tname = obj
- } else {
- // identifier not declared/resolved - parser reported error already
- return // ignore this method
- }
- // declare method in receiver base type scope
- scope := check.methods[tname]
- if scope == nil {
- scope = new(Scope)
- check.methods[tname] = scope
- }
- check.declareIdent(scope, meth.Name, &Func{Pkg: check.pkg, Name: meth.Name.Name, decl: meth})
-}
-
-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 check.resolve)
- case *ast.ValueSpec:
- for _, name := range s.Names {
- check.object(check.lookup(name), false)
- }
- case *ast.TypeSpec:
- check.object(check.lookup(s.Name), false)
- default:
- check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
- }
- }
- case *ast.FuncDecl:
- // methods are checked when their respective base types are checked
- if d.Recv != nil {
- return
- }
- obj := check.lookup(d.Name)
- // Initialization functions don't have an object associated with them
- // since they are not in any scope. Create a dummy object for them.
- if d.Name.Name == "init" {
- assert(obj == nil) // all other functions should have an object
- obj = &Func{Pkg: check.pkg, Name: d.Name.Name, decl: d}
- check.register(d.Name, obj)
- }
- check.object(obj, false)
- default:
- check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
- }
-}
-
-// A bailout panic is raised to indicate early termination.
-type bailout struct{}
-
-func check(ctxt *Context, fset *token.FileSet, files []*ast.File) (pkg *Package, err error) {
- // initialize checker
- check := checker{
- ctxt: ctxt,
- fset: fset,
- files: files,
- idents: make(map[*ast.Ident]Object),
- objects: make(map[*ast.Object]Object),
- initspecs: make(map[*ast.ValueSpec]*ast.ValueSpec),
- methods: make(map[*TypeName]*Scope),
- conversions: make(map[*ast.CallExpr]bool),
- untyped: make(map[ast.Expr]*Basic),
- constants: make(map[ast.Expr]interface{}),
- shiftOps: make(map[ast.Expr]bool),
- }
-
- // set results and handle panics
- defer func() {
- pkg = check.pkg
- switch p := recover().(type) {
- case nil, bailout:
- // normal return or early exit
- err = check.firsterr
- default:
- // unexpected panic: don't crash clients
- if debug {
- check.dump("INTERNAL PANIC: %v", p)
- panic(p)
- }
- // TODO(gri) add a test case for this scenario
- err = fmt.Errorf("types internal error: %v", p)
- }
- }()
-
- // resolve identifiers
- imp := ctxt.Import
- if imp == nil {
- imp = GcImport
- }
- methods := check.resolve(imp)
-
- // associate methods with types
- for _, m := range methods {
- check.assocMethod(m)
- }
-
- // typecheck all declarations
- for _, f := range check.files {
- for _, d := range f.Decls {
- check.decl(d)
- }
- }
-
- // typecheck all function/method bodies
- // (funclist may grow when checking statements - do not use range clause!)
- for i := 0; i < len(check.funclist); i++ {
- f := check.funclist[i]
- if trace {
- s := "<function literal>"
- if f.obj != nil {
- s = f.obj.Name
- }
- fmt.Println("---", s)
- }
- check.funcsig = f.sig
- check.stmtList(f.body.List)
- }
-
- // remaining untyped expressions must indeed be untyped
- if debug {
- for x, typ := range check.untyped {
- if !isUntyped(typ) {
- check.dump("%s: %s (type %s) is not untyped", x.Pos(), x, typ)
- panic(0)
- }
- }
- }
-
- // notify client of any untyped types left
- // TODO(gri) Consider doing this before and
- // after function body checking for smaller
- // map size and more immediate feedback.
- if ctxt.Expr != nil {
- for x, typ := range check.untyped {
- ctxt.Expr(x, typ, check.constants[x])
- }
- }
-
- return
-}
diff --git a/src/pkg/go/types/check_test.go b/src/pkg/go/types/check_test.go
deleted file mode 100644
index 470f3a1a9..000000000
--- a/src/pkg/go/types/check_test.go
+++ /dev/null
@@ -1,259 +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.
-
-// 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")
-
-// 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"}},
- {"decls3", []string{"testdata/decls3.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
-}
-
-// Positioned errors are of the form filename:line:column: message .
-var posMsgRx = regexp.MustCompile(`^(.*:[0-9]+:[0-9]+): *(.*)`)
-
-// splitError splits an error's error message into a position string
-// and the actual error message. If there's no position information,
-// pos is the empty string, and msg is the entire error message.
-//
-func splitError(err error) (pos, msg string) {
- msg = err.Error()
- if m := posMsgRx.FindStringSubmatch(msg); len(m) == 3 {
- pos = m[1]
- msg = m[2]
- }
- return
-}
-
-func parseFiles(t *testing.T, testname string, filenames []string) ([]*ast.File, []error) {
- var files []*ast.File
- var errlist []error
- for _, filename := range filenames {
- file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors|parser.AllErrors)
- if file == nil {
- t.Fatalf("%s: could not parse file %s", testname, filename)
- }
- files = append(files, file)
- if err != nil {
- if list, _ := err.(scanner.ErrorList); len(list) > 0 {
- for _, err := range list {
- errlist = append(errlist, err)
- }
- } else {
- errlist = append(errlist, err)
- }
- }
- }
- return files, errlist
-}
-
-// 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 *"([^"]*)" *\*/$`)
-
-// errMap collects the regular expressions of ERROR comments found
-// in files and returns them as a map of error positions to error messages.
-//
-func errMap(t *testing.T, testname string, files []*ast.File) map[string][]string {
- errmap := make(map[string][]string)
-
- for _, file := range files {
- filename := fset.Position(file.Package).Filename
- 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 string // position string 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 {
- errmap[prev] = append(errmap[prev], string(s[1]))
- }
- case token.SEMICOLON:
- // ignore automatically inserted semicolon
- if lit == "\n" {
- continue scanFile
- }
- fallthrough
- default:
- prev = fset.Position(pos).String()
- }
- }
- }
-
- return errmap
-}
-
-func eliminate(t *testing.T, errmap map[string][]string, errlist []error) {
- for _, err := range errlist {
- pos, msg := splitError(err)
- list := errmap[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", pos, err)
- continue
- }
- if rx.MatchString(msg) {
- index = i
- break
- }
- }
- if index >= 0 {
- // eliminate from list
- if n := len(list) - 1; n > 0 {
- // not the last entry - swap in last element and shorten list by 1
- list[index] = list[n]
- errmap[pos] = list[:n]
- } else {
- // last entry - remove list from map
- delete(errmap, pos)
- }
- } else {
- t.Errorf("%s: no error expected: %q", pos, msg)
- }
-
- }
-}
-
-func checkFiles(t *testing.T, testname string, testfiles []string) {
- // parse files and collect parser errors
- files, errlist := parseFiles(t, testname, testfiles)
-
- // typecheck and collect typechecker errors
- var ctxt Context
- ctxt.Error = func(err error) { errlist = append(errlist, err) }
- ctxt.Check(fset, files)
-
- if *listErrors {
- t.Errorf("--- %s: %d errors found:", testname, len(errlist))
- for _, err := range errlist {
- t.Error(err)
- }
- return
- }
-
- // match and eliminate errors
- // we are expecting the following errors
- // (collect these after parsing the files so that
- // they are found in the file set)
- errmap := errMap(t, testname, files)
- eliminate(t, errmap, errlist)
-
- // there should be no expected errors left
- if len(errmap) > 0 {
- t.Errorf("--- %s: %d source positions with expected (but not reported) errors:", testname, len(errmap))
- for pos, list := range errmap {
- for _, rx := range list {
- t.Errorf("%s: %q", pos, rx)
- }
- }
- }
-}
-
-var testBuiltinsDeclared = false
-
-func TestCheck(t *testing.T) {
- // Declare builtins for testing.
- // Not done in an init func to avoid an init race with
- // the construction of the Universe var.
- if !testBuiltinsDeclared {
- testBuiltinsDeclared = true
- // Pkg == nil for Universe objects
- def(&Func{Name: "assert", Type: &builtin{_Assert, "assert", 1, false, true}})
- def(&Func{Name: "trace", Type: &builtin{_Trace, "trace", 0, true, true}})
- }
-
- // 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/src/pkg/go/types/const.go b/src/pkg/go/types/const.go
deleted file mode 100644
index 503652e75..000000000
--- a/src/pkg/go/types/const.go
+++ /dev/null
@@ -1,718 +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.
-
-// 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. Introduce a Const
-// interface 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 values.
-var (
- nilConst = NilType{}
- zeroConst = int64(0)
-)
-
-// 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,
-// or *big.Rat value.
-//
-func normalizeRatConst(x *big.Rat) interface{} {
- if x.IsInt() {
- return normalizeIntConst(x.Num())
- }
- return x
-}
-
-// newComplex returns the smallest constant representation
-// for the specific value re + im*i; either an int64, *big.Int,
-// *big.Rat, or complex value.
-//
-func newComplex(re, im *big.Rat) interface{} {
- if im.Sign() == 0 {
- return normalizeRatConst(re)
- }
- return Complex{re, im}
-}
-
-// 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 newComplex(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
-}
-
-// toImagConst returns the constant Complex(0, x) for a non-complex x.
-func toImagConst(x interface{}) interface{} {
- var im *big.Rat
- switch x := x.(type) {
- case int64:
- im = big.NewRat(x, 1)
- case *big.Int:
- im = new(big.Rat).SetFrac(x, int1)
- case *big.Rat:
- im = x
- default:
- unreachable()
- }
- return Complex{rat0, im}
-}
-
-// 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{}, ctxt *Context, as BasicKind) bool {
- switch x := x.(type) {
- case bool:
- return as == Bool || as == UntypedBool
-
- case int64:
- switch as {
- case Int:
- var s = uint(ctxt.sizeof(Typ[as])) * 8
- return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
- case Int8:
- const s = 8
- return -1<<(s-1) <= x && x <= 1<<(s-1)-1
- case Int16:
- const s = 16
- return -1<<(s-1) <= x && x <= 1<<(s-1)-1
- case Int32:
- const s = 32
- return -1<<(s-1) <= x && x <= 1<<(s-1)-1
- case Int64:
- return true
- case Uint, Uintptr:
- var s = uint(ctxt.sizeof(Typ[as])) * 8
- return 0 <= x && x <= int64(1)<<(s-1)-1
- case Uint8:
- const s = 8
- return 0 <= x && x <= 1<<s-1
- case Uint16:
- const s = 16
- return 0 <= x && x <= 1<<s-1
- case Uint32:
- const s = 32
- return 0 <= x && x <= 1<<s-1
- case Uint64:
- 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, Uintptr:
- var s = uint(ctxt.sizeof(Typ[as])) * 8
- return x.Sign() >= 0 && x.BitLen() <= int(s)
- case Uint64:
- return x.Sign() >= 0 && x.BitLen() <= 64
- 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 || as == UnsafePointer
-
- 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
-}
-
-// unaryOpConst returns the result of the constant evaluation op x where x is of the given type.
-func unaryOpConst(x interface{}, ctxt *Context, op token.Token, typ *Basic) interface{} {
- switch op {
- case token.ADD:
- return x // nothing to do
- case token.SUB:
- switch x := x.(type) {
- case int64:
- if z := -x; z != x {
- return z // no overflow
- }
- // overflow - need to convert to big.Int
- return normalizeIntConst(new(big.Int).Neg(big.NewInt(x)))
- case *big.Int:
- return normalizeIntConst(new(big.Int).Neg(x))
- case *big.Rat:
- return normalizeRatConst(new(big.Rat).Neg(x))
- case Complex:
- return newComplex(new(big.Rat).Neg(x.Re), new(big.Rat).Neg(x.Im))
- }
- case token.XOR:
- var z big.Int
- switch x := x.(type) {
- case int64:
- z.Not(big.NewInt(x))
- case *big.Int:
- z.Not(x)
- default:
- unreachable()
- }
- // For unsigned types, the result will be negative and
- // thus "too large": We must limit the result size to
- // the type's size.
- if typ.Info&IsUnsigned != 0 {
- s := uint(ctxt.sizeof(typ)) * 8
- z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z &^= (-1)<<s
- }
- return normalizeIntConst(&z)
- case token.NOT:
- return !x.(bool)
- }
- unreachable()
- return nil
-}
-
-// binaryOpConst returns the result of the constant evaluation x op y;
-// both operands must be of the same constant "kind" (boolean, numeric, or string).
-// If typ is an integer type, 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, typ *Basic) 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
- }
-
- 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 typ.Info&IsInteger != 0 {
- 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
- }
-
- 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 typ.Info&IsInteger != 0 {
- 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 newComplex(&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/src/pkg/go/types/conversions.go b/src/pkg/go/types/conversions.go
deleted file mode 100644
index fcbaf7717..000000000
--- a/src/pkg/go/types/conversions.go
+++ /dev/null
@@ -1,129 +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.
-
-// 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
- }
-
- if x.mode == constant && isConstType(typ) {
- // constant conversion
- // TODO(gri) implement this
- } else {
- // non-constant conversion
- if !x.isConvertible(check.ctxt, typ) {
- check.invalidOp(conv.Pos(), "cannot convert %s to %s", x, typ)
- goto Error
- }
- x.mode = value
- }
-
- check.conversions[conv] = true // for cap/len checking
- x.expr = conv
- x.typ = typ
- return
-
-Error:
- x.mode = invalid
-}
-
-func (x *operand) isConvertible(ctxt *Context, T Type) bool {
- // "x is assignable to T"
- if x.isAssignable(ctxt, T) {
- return true
- }
-
- // "x's type and T have identical underlying types"
- V := x.typ
- Vu := underlying(V)
- Tu := underlying(T)
- if IsIdentical(Vu, Tu) {
- return true
- }
-
- // "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
- if V, ok := V.(*Pointer); ok {
- if T, ok := T.(*Pointer); ok {
- if IsIdentical(underlying(V.Base), underlying(T.Base)) {
- return true
- }
- }
- }
-
- // "x's type and T are both integer or floating point types"
- if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
- return true
- }
-
- // "x's type and T are both complex types"
- if isComplex(V) && isComplex(T) {
- return true
- }
-
- // "x is an integer or a slice of bytes or runes and T is a string type"
- if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
- return true
- }
-
- // "x is a string and T is a slice of bytes or runes"
- if isString(V) && isBytesOrRunes(Tu) {
- return true
- }
-
- // package unsafe:
- // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
- if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
- return true
- }
- // "and vice versa"
- if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
- return true
- }
-
- return false
-}
-
-func isUintptr(typ Type) bool {
- t, ok := typ.(*Basic)
- return ok && t.Kind == Uintptr
-}
-
-func isUnsafePointer(typ Type) bool {
- t, ok := typ.(*Basic)
- return ok && t.Kind == UnsafePointer
-}
-
-func isPointer(typ Type) bool {
- _, ok := typ.(*Pointer)
- return ok
-}
-
-func isBytesOrRunes(typ Type) bool {
- if s, ok := typ.(*Slice); ok {
- t, ok := underlying(s.Elt).(*Basic)
- return ok && (t.Kind == Byte || t.Kind == Rune)
- }
- return false
-}
diff --git a/src/pkg/go/types/errors.go b/src/pkg/go/types/errors.go
deleted file mode 100644
index 62ee54791..000000000
--- a/src/pkg/go/types/errors.go
+++ /dev/null
@@ -1,335 +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.
-
-// This file implements various error reporters.
-
-package types
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/token"
-)
-
-// TODO(gri) eventually assert and unimplemented should disappear.
-func assert(p bool) {
- if !p {
- panic("assertion failed")
- }
-}
-
-func unreachable() {
- panic("unreachable")
-}
-
-func (check *checker) printTrace(format string, args []interface{}) {
- const dots = ". . . . . . . . . . . . . . . . . . . . "
- n := len(check.pos) - 1
- i := 3 * n
- for i > len(dots) {
- fmt.Print(dots)
- i -= len(dots)
- }
- // i <= len(dots)
- fmt.Printf("%s:\t", check.fset.Position(check.pos[n]))
- fmt.Print(dots[0:i])
- fmt.Println(check.formatMsg(format, args))
-}
-
-func (check *checker) trace(pos token.Pos, format string, args ...interface{}) {
- check.pos = append(check.pos, pos)
- check.printTrace(format, args)
-}
-
-func (check *checker) untrace(format string, args ...interface{}) {
- if len(format) > 0 {
- check.printTrace(format, args)
- }
- check.pos = check.pos[:len(check.pos)-1]
-}
-
-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).String()
- 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) err(err error) {
- if check.firsterr == nil {
- check.firsterr = err
- }
- f := check.ctxt.Error
- if f == nil {
- panic(bailout{}) // report only first error
- }
- f(err)
-}
-
-func (check *checker) errorf(pos token.Pos, format string, args ...interface{}) {
- check.err(fmt.Errorf("%s: %s", check.fset.Position(pos), check.formatMsg(format, args)))
-}
-
-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 []*Var, 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)
- }
- 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 *Result:
- writeParams(buf, t.Values, false)
-
- 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)
- }
- 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:
- s := "<NamedType w/o object>"
- if obj := t.Obj; obj != nil {
- if obj.Pkg != nil && obj.Pkg.Path != "" {
- buf.WriteString(obj.Pkg.Path)
- buf.WriteString(".")
- }
- s = t.Obj.GetName()
- }
- buf.WriteString(s)
-
- default:
- fmt.Fprintf(buf, "<type %T>", t)
- }
-}
-
-func (t *Array) String() string { return typeString(t) }
-func (t *Basic) String() string { return typeString(t) }
-func (t *Chan) String() string { return typeString(t) }
-func (t *Interface) String() string { return typeString(t) }
-func (t *Map) String() string { return typeString(t) }
-func (t *NamedType) String() string { return typeString(t) }
-func (t *Pointer) String() string { return typeString(t) }
-func (t *Result) String() string { return typeString(t) }
-func (t *Signature) String() string { return typeString(t) }
-func (t *Slice) String() string { return typeString(t) }
-func (t *Struct) String() string { return typeString(t) }
-func (t *builtin) String() string { return typeString(t) }
diff --git a/src/pkg/go/types/exportdata.go b/src/pkg/go/types/exportdata.go
deleted file mode 100644
index 1f6a3c725..000000000
--- a/src/pkg/go/types/exportdata.go
+++ /dev/null
@@ -1,111 +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.
-
-// 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
- }
- // leave for debugging
- if false {
- 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/src/pkg/go/types/expr.go b/src/pkg/go/types/expr.go
deleted file mode 100644
index 86d782d48..000000000
--- a/src/pkg/go/types/expr.go
+++ /dev/null
@@ -1,1520 +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.
-
-// This file implements typechecking of expressions.
-
-package types
-
-import (
- "go/ast"
- "go/token"
- "strconv"
-)
-
-// TODO(gri) Cleanups
-// - 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?
-// - rethink error handling: should all callers check if x.mode == valid after making a call?
-// - at the moment, iota is passed around almost everywhere - in many places we know it cannot be used
-// - use "" or "_" consistently for anonymous identifiers? (e.g. reeceivers that have no name)
-// - consider storing error messages in invalid operands for better error messages/debugging output
-
-// TODO(gri) API issues
-// - clients need access to builtins type information
-// - API tests are missing (e.g., identifiers should be handled as expressions in callbacks)
-
-func (check *checker) collectParams(list *ast.FieldList, variadicOk bool) (params []*Var, isVariadic bool) {
- if list == nil {
- return
- }
- var last *Var
- for i, field := range list.List {
- ftype := field.Type
- if t, _ := ftype.(*ast.Ellipsis); t != nil {
- ftype = t.Elt
- if variadicOk && i == len(list.List)-1 {
- isVariadic = true
- } else {
- check.invalidAST(field.Pos(), "... not permitted")
- // ok to continue
- }
- }
- // the parser ensures that f.Tag is nil and we don't
- // care if a constructed AST contains a non-nil tag
- typ := check.typ(ftype, true)
- if len(field.Names) > 0 {
- // named parameter
- for _, name := range field.Names {
- par := check.lookup(name).(*Var)
- par.Type = typ
- last = par
- copy := *par
- params = append(params, &copy)
- }
- } else {
- // anonymous parameter
- par := &Var{Type: typ}
- last = nil // not accessible inside function
- params = append(params, par)
- }
- }
- // For a variadic function, change the last parameter's object type
- // from T to []T (this is the type used inside the function), but
- // keep the params list unchanged (this is the externally visible type).
- if isVariadic && last != nil {
- last.Type = &Slice{Elt: last.Type}
- }
- return
-}
-
-func (check *checker) collectMethods(list *ast.FieldList) (methods []*Method) {
- if list == nil {
- return
- }
- for _, f := range list.List {
- typ := check.typ(f.Type, len(f.Names) > 0) // cycles are not ok for embedded interfaces
- // the parser ensures that f.Tag is nil and we don't
- // care if a constructed AST contains a non-nil tag
- if len(f.Names) > 0 {
- // methods (the parser ensures that there's only one
- // and we don't care if a constructed AST has more)
- sig, ok := typ.(*Signature)
- if !ok {
- check.invalidAST(f.Type.Pos(), "%s is not a method signature", typ)
- continue
- }
- for _, name := range f.Names {
- methods = append(methods, &Method{QualifiedName{check.pkg, name.Name}, sig})
- }
- } else {
- // embedded interface
- utyp := underlying(typ)
- if ityp, ok := utyp.(*Interface); ok {
- methods = append(methods, ityp.Methods...)
- } else if utyp != Typ[Invalid] {
- // if utyp is invalid, don't complain (the root cause was reported before)
- check.errorf(f.Type.Pos(), "%s is not an interface type", typ)
- }
- }
- }
- // Check for double declarations.
- // The parser inserts methods into an interface-local scope, so local
- // double declarations are reported by the parser already. We need to
- // check again for conflicts due to embedded interfaces. This will lead
- // to a 2nd error message if the double declaration was reported before
- // by the parser.
- // TODO(gri) clean this up a bit
- seen := make(map[string]bool)
- for _, m := range methods {
- if seen[m.Name] {
- check.errorf(list.Pos(), "multiple methods named %s", m.Name)
- return // keep multiple entries, lookup will only return the first entry
- }
- seen[m.Name] = true
- }
- return
-}
-
-func (check *checker) tag(t *ast.BasicLit) string {
- if t != nil {
- if t.Kind == token.STRING {
- if val, err := strconv.Unquote(t.Value); err == nil {
- return val
- }
- }
- check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
- }
- return ""
-}
-
-func (check *checker) collectFields(list *ast.FieldList, cycleOk bool) (fields []*Field) {
- if list == nil {
- return
- }
-
- var typ Type // current field typ
- var tag string // current field tag
- add := func(name string, isAnonymous bool) {
- fields = append(fields, &Field{QualifiedName{check.pkg, name}, typ, tag, isAnonymous})
- }
-
- for _, f := range list.List {
- typ = check.typ(f.Type, cycleOk)
- tag = check.tag(f.Tag)
- if len(f.Names) > 0 {
- // named fields
- for _, name := range f.Names {
- add(name.Name, false)
- }
- } else {
- // anonymous field
- switch t := deref(typ).(type) {
- case *Basic:
- add(t.Name, true)
- case *NamedType:
- add(t.Obj.GetName(), true)
- default:
- if typ != Typ[Invalid] {
- check.invalidAST(f.Type.Pos(), "anonymous field type %s must be named", 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,
-}
-
-func (check *checker) op(m opPredicates, x *operand, op token.Token) bool {
- if pred := m[op]; pred != nil {
- if !pred(x.typ) {
- 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) {
- switch op {
- case token.AND:
- // spec: "As an exception to the addressability
- // requirement x may also be a composite literal."
- if _, ok := unparen(x.expr).(*ast.CompositeLit); ok {
- x.mode = variable
- }
- if x.mode != variable {
- check.invalidOp(x.pos(), "cannot take address of %s", x)
- goto Error
- }
- x.typ = &Pointer{Base: x.typ}
- return
-
- case token.ARROW:
- typ, ok := underlying(x.typ).(*Chan)
- if !ok {
- check.invalidOp(x.pos(), "cannot receive from non-channel %s", x)
- goto Error
- }
- if typ.Dir&ast.RECV == 0 {
- check.invalidOp(x.pos(), "cannot receive from send-only channel %s", x)
- goto Error
- }
- x.mode = valueok
- x.typ = typ.Elt
- return
- }
-
- if !check.op(unaryOpPredicates, x, op) {
- goto Error
- }
-
- if x.mode == constant {
- typ := underlying(x.typ).(*Basic)
- x.val = unaryOpConst(x.val, check.ctxt, op, typ)
- // Typed constants must be representable in
- // their type after each constant operation.
- check.isRepresentable(x, typ)
- return
- }
-
- x.mode = value
- // x.typ remains unchanged
- return
-
-Error:
- x.mode = invalid
-}
-
-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, check.ctxt, 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
- }
-}
-
-// updateExprType updates the type of all untyped nodes in the
-// expression tree of x to typ. If shiftOp is set, x is the lhs
-// of a shift expression. In that case, and if x is in the set
-// of shift operands with delayed type checking, and typ is not
-// an untyped type, updateExprType will check if typ is an
-// integer type.
-// If Context.Expr != nil, it is called for all nodes that are
-// now assigned their final (not untyped) type.
-func (check *checker) updateExprType(x ast.Expr, typ Type, shiftOp bool) {
- switch x := x.(type) {
- case *ast.BadExpr,
- *ast.FuncLit,
- *ast.CompositeLit,
- *ast.SelectorExpr,
- *ast.IndexExpr,
- *ast.SliceExpr,
- *ast.TypeAssertExpr,
- *ast.CallExpr,
- *ast.StarExpr,
- *ast.KeyValueExpr,
- *ast.ArrayType,
- *ast.StructType,
- *ast.FuncType,
- *ast.InterfaceType,
- *ast.MapType,
- *ast.ChanType:
- // these expression are never untyped - nothing to do
- return
-
- case *ast.Ident, *ast.BasicLit:
- // update type
-
- case *ast.ParenExpr:
- check.updateExprType(x.X, typ, false)
-
- case *ast.UnaryExpr:
- check.updateExprType(x.X, typ, false)
-
- case *ast.BinaryExpr:
- if isComparison(x.Op) {
- // result type is independent of operand types
- } else if isShift(x.Op) {
- // result type depends only on lhs operand
- check.updateExprType(x.X, typ, true)
- } else {
- // operand types match result type
- check.updateExprType(x.X, typ, false)
- check.updateExprType(x.Y, typ, false)
- }
-
- case *ast.Ellipsis:
- unreachable()
- default:
- unreachable()
- }
-
- // TODO(gri) t should always exist, shouldn't it?
- if t := check.untyped[x]; t != nil {
- if isUntyped(typ) {
- check.untyped[x] = typ.(*Basic)
- } else {
- // notify clients of final type for x
- if f := check.ctxt.Expr; f != nil {
- f(x, typ, check.constants[x])
- }
- delete(check.untyped, x)
- delete(check.constants, x)
- // check delayed shift
- // Note: Using shiftOp is an optimization: it prevents
- // map lookups when we know x is not a shiftOp in the
- // first place.
- if shiftOp && check.shiftOps[x] {
- if !isInteger(typ) {
- check.invalidOp(x.Pos(), "shifted operand %s (type %s) must be integer", x, typ)
- }
- delete(check.shiftOps, x)
- }
- }
- }
-}
-
-// 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
- check.updateExprType(x.expr, target, false)
- }
- } else if xkind != tkind {
- goto Error
- }
- return
- }
-
- // typed target
- switch t := underlying(target).(type) {
- case nil:
- // We may reach here due to previous type errors.
- // Be conservative and don't crash.
- x.mode = invalid
- return
- case *Basic:
- check.isRepresentable(x, t)
- if x.mode == invalid {
- return // error already reported
- }
- case *Interface:
- if !x.isNil() && len(t.Methods) > 0 /* empty interfaces are ok */ {
- goto Error
- }
- // Update operand types to the default type rather then
- // the target (interface) type: values must have concrete
- // dynamic types. If the value is nil, keep it untyped
- // (this is important for tools such as go vet which need
- // the dynamic type for argument checking of say, print
- // functions)
- if x.isNil() {
- target = Typ[UntypedNil]
- } else {
- // cannot assign untyped values to non-empty interfaces
- if len(t.Methods) > 0 {
- goto Error
- }
- target = defaultType(x.typ)
- }
- case *Pointer, *Signature, *Slice, *Map, *Chan:
- if !x.isNil() {
- goto Error
- }
- // keep nil untyped - see comment for interfaces, above
- target = Typ[UntypedNil]
- default:
- if debug {
- check.dump("convertUntyped(x = %v, target = %v)", x, target)
- }
- unreachable()
- }
-
- x.typ = target
- check.updateExprType(x.expr, target, false)
- return
-
-Error:
- check.errorf(x.pos(), "cannot convert %s to %s", x, target)
- x.mode = invalid
-}
-
-func (check *checker) comparison(x, y *operand, op token.Token) {
- // TODO(gri) deal with interface vs non-interface comparison
-
- valid := false
- if x.isAssignable(check.ctxt, y.typ) || y.isAssignable(check.ctxt, x.typ) {
- switch op {
- case token.EQL, token.NEQ:
- valid = isComparable(x.typ) ||
- x.isNil() && hasNil(y.typ) ||
- y.isNil() && hasNil(x.typ)
- case token.LSS, token.LEQ, token.GTR, token.GEQ:
- valid = isOrdered(x.typ)
- default:
- unreachable()
- }
- }
-
- if !valid {
- check.invalidOp(x.pos(), "cannot compare %s %s %s", x, op, 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]
-}
-
-func (check *checker) shift(x, y *operand, op token.Token) {
- // spec: "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."
- switch {
- case isInteger(y.typ) && isUnsigned(y.typ):
- // nothing to do
- case y.mode == constant && isUntyped(y.typ):
- check.convertUntyped(x, Typ[UntypedInt])
- default:
- check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
- x.mode = invalid
- return
- }
-
- if x.mode == constant {
- if y.mode == constant {
- // constant shift - lhs must be (representable as) an integer
- if isUntyped(x.typ) {
- if !isRepresentableConst(x.val, check.ctxt, UntypedInt) {
- check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
- x.mode = invalid
- return
- }
- x.typ = Typ[UntypedInt]
- }
- assert(x.isInteger(check.ctxt))
-
- // rhs must be within reasonable bounds
- 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
- }
-
- // everything's ok
- x.val = shiftConst(x.val, uint(s), op)
- return
- }
-
- // non-constant shift with constant lhs
- if isUntyped(x.typ) {
- // spec: "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)".
-
- // delay operand checking until we know the type
- check.shiftOps[x.expr] = true
- x.mode = value
- return
- }
- }
-
- // non-constant shift - lhs must be an integer
- if !isInteger(x.typ) {
- check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
- x.mode = invalid
- return
- }
-
- // non-constant shift
- x.mode = value
-}
-
-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 *operand, lhs, rhs ast.Expr, op token.Token, iota int) {
- var y operand
-
- check.expr(x, lhs, nil, iota)
- check.expr(&y, rhs, nil, iota)
-
- if x.mode == invalid {
- return
- }
- if y.mode == invalid {
- x.mode = invalid
- x.expr = y.expr
- return
- }
-
- if isShift(op) {
- check.shift(x, &y, op)
- 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 {
- typ := underlying(x.typ).(*Basic)
- x.val = binaryOpConst(x.val, y.val, op, typ)
- // Typed constants must be representable in
- // their type after each constant operation.
- check.isRepresentable(x, typ)
- 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 index >= 0, or a negative value.
-//
-func (check *checker) index(index ast.Expr, length int64, iota int) int64 {
- var x operand
-
- check.expr(&x, index, nil, iota)
- if !x.isInteger(check.ctxt) {
- check.errorf(x.pos(), "index %s must be integer", &x)
- return -1
- }
- if x.mode != constant {
- return -1 // we cannot check more
- }
- // The spec doesn't require int64 indices, but perhaps it should.
- i, ok := x.val.(int64)
- if !ok {
- check.errorf(x.pos(), "stupid index %s", &x)
- return -1
- }
- if i < 0 {
- check.errorf(x.pos(), "index %s must not be negative", &x)
- return -1
- }
- if length >= 0 && i >= length {
- check.errorf(x.pos(), "index %s is out of bounds (>= %d)", &x, length)
- return -1
- }
-
- return i
-}
-
-// compositeLitKey resolves unresolved composite literal keys.
-// For details, see comment in go/parser/parser.go, method parseElement.
-func (check *checker) compositeLitKey(key ast.Expr) {
- if ident, ok := key.(*ast.Ident); ok && ident.Obj == nil {
- if obj := check.pkg.Scope.Lookup(ident.Name); obj != nil {
- check.register(ident, obj)
- } else if obj := Universe.Lookup(ident.Name); obj != nil {
- check.register(ident, obj)
- } else {
- check.errorf(ident.Pos(), "undeclared name: %s", ident.Name)
- }
- }
-}
-
-// indexElts checks the elements (elts) of an array or slice composite literal
-// against the literal's element type (typ), and the element indices against
-// the literal length if known (length >= 0). It returns the length of the
-// literal (maximum index value + 1).
-//
-func (check *checker) indexedElts(elts []ast.Expr, typ Type, length int64, iota int) int64 {
- visited := make(map[int64]bool, len(elts))
- var index, max int64
- for _, e := range elts {
- // determine and check index
- validIndex := false
- eval := e
- if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
- check.compositeLitKey(kv.Key)
- if i := check.index(kv.Key, length, iota); i >= 0 {
- index = i
- validIndex = true
- }
- eval = kv.Value
- } else if length >= 0 && index >= length {
- check.errorf(e.Pos(), "index %d is out of bounds (>= %d)", index, length)
- } else {
- validIndex = true
- }
-
- // if we have a valid index, check for duplicate entries
- if validIndex {
- if visited[index] {
- check.errorf(e.Pos(), "duplicate index %d in array or slice literal", index)
- }
- visited[index] = true
- }
- index++
- if index > max {
- max = index
- }
-
- // check element against composite literal element type
- var x operand
- check.expr(&x, eval, typ, iota)
- if !check.assignment(&x, typ) && x.mode != invalid {
- check.errorf(x.pos(), "cannot use %s as %s value in array or slice literal", &x, typ)
- }
- }
- return max
-}
-
-// argument typechecks passing an argument arg (if arg != nil) or
-// x (if arg == nil) to the i'th parameter of the given signature.
-// If passSlice is set, the argument is followed by ... in the call.
-//
-func (check *checker) argument(sig *Signature, i int, arg ast.Expr, x *operand, passSlice bool) {
- // determine parameter
- var par *Var
- n := len(sig.Params)
- if i < n {
- par = sig.Params[i]
- } else if sig.IsVariadic {
- par = sig.Params[n-1]
- } else {
- check.errorf(arg.Pos(), "too many arguments")
- return
- }
-
- // determine argument
- var z operand
- z.mode = variable
- z.expr = nil // TODO(gri) can we do better here? (for good error messages)
- z.typ = par.Type
-
- if arg != nil {
- check.expr(x, arg, z.typ, -1)
- }
- if x.mode == invalid {
- return // ignore this argument
- }
-
- // check last argument of the form x...
- if passSlice {
- if i+1 != n {
- check.errorf(x.pos(), "can only use ... with matching parameter")
- return // ignore this argument
- }
- // spec: "If the final argument is assignable to a slice type []T,
- // it may be passed unchanged as the value for a ...T parameter if
- // the argument is followed by ..."
- z.typ = &Slice{Elt: z.typ} // change final parameter type to []T
- }
-
- if !check.assignment(x, z.typ) && x.mode != invalid {
- check.errorf(x.pos(), "cannot pass argument %s to %s", x, &z)
- }
-}
-
-var emptyResult Result
-
-func (check *checker) callExpr(x *operand) {
- var typ Type
- var val interface{}
- switch x.mode {
- case invalid:
- return // nothing to do
- case novalue:
- typ = &emptyResult
- case constant:
- typ = x.typ
- val = x.val
- default:
- typ = x.typ
- }
-
- // if the operand is untyped, delay notification
- // until it becomes typed or until the end of
- // type checking
- if isUntyped(typ) {
- check.untyped[x.expr] = typ.(*Basic)
- if val != nil {
- check.constants[x.expr] = val
- }
- return
- }
-
- // TODO(gri) ensure that literals always report
- // their dynamic (never interface) type.
- // This is not the case yet.
-
- if check.ctxt.Expr != nil {
- check.ctxt.Expr(x.expr, typ, val)
- }
-}
-
-// rawExpr typechecks expression e and initializes x with the expression
-// value or type. If an error occurred, x.mode is set to invalid.
-// If hint != nil, it is the type of a composite literal element.
-// 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) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycleOk bool) {
- if trace {
- c := ""
- if cycleOk {
- c = " ⨁"
- }
- check.trace(e.Pos(), "%s (%s, %d%s)", e, typeString(hint), iota, c)
- defer check.untrace("=> %s", x)
- }
-
- defer check.callExpr(x)
-
- switch e := e.(type) {
- case *ast.BadExpr:
- goto Error // error was reported before
-
- case *ast.Ident:
- if e.Name == "_" {
- check.invalidOp(e.Pos(), "cannot use _ as value or type")
- goto Error
- }
- obj := check.lookup(e)
- if obj == nil {
- goto Error // error was reported before
- }
- check.object(obj, cycleOk)
- switch obj := obj.(type) {
- case *Package:
- check.errorf(e.Pos(), "use of package %s not in selector", obj.Name)
- goto Error
- case *Const:
- if obj.Val == 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.Val
- }
- case *TypeName:
- x.mode = typexpr
- if !cycleOk && underlying(obj.Type) == nil {
- check.errorf(obj.spec.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 *Var:
- x.mode = variable
- case *Func:
- x.mode = value
- default:
- unreachable()
- }
- x.typ = obj.GetType()
-
- case *ast.Ellipsis:
- // ellipses are handled explicitly where they are legal
- // (array composite literals and parameter lists)
- check.errorf(e.Pos(), "invalid use of '...'")
- goto Error
-
- 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:
- if sig, ok := check.typ(e.Type, false).(*Signature); ok {
- x.mode = value
- x.typ = sig
- check.later(nil, sig, e.Body)
- } else {
- check.invalidAST(e.Pos(), "invalid function literal %s", e)
- goto Error
- }
-
- case *ast.CompositeLit:
- typ := hint
- openArray := false
- if e.Type != nil {
- // [...]T array types may only appear with composite literals.
- // Check for them here so we don't have to handle ... in general.
- typ = nil
- if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
- if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
- // We have an "open" [...]T array type.
- // Create a new ArrayType with unknown length (-1)
- // and finish setting it up after analyzing the literal.
- typ = &Array{Len: -1, Elt: check.typ(atyp.Elt, cycleOk)}
- openArray = true
- }
- }
- if typ == nil {
- typ = check.typ(e.Type, false)
- }
- }
- if typ == nil {
- check.errorf(e.Pos(), "missing type in composite literal")
- goto Error
- }
-
- switch utyp := underlying(deref(typ)).(type) {
- case *Struct:
- if len(e.Elts) == 0 {
- break
- }
- fields := utyp.Fields
- if _, ok := e.Elts[0].(*ast.KeyValueExpr); ok {
- // all elements must have keys
- visited := make([]bool, len(fields))
- for _, e := range e.Elts {
- kv, _ := e.(*ast.KeyValueExpr)
- if kv == nil {
- check.errorf(e.Pos(), "mixture of field:value and value elements in struct literal")
- continue
- }
- key, _ := kv.Key.(*ast.Ident)
- if key == nil {
- check.errorf(kv.Pos(), "invalid field name %s in struct literal", kv.Key)
- continue
- }
- i := utyp.fieldIndex(QualifiedName{check.pkg, key.Name})
- if i < 0 {
- check.errorf(kv.Pos(), "unknown field %s in struct literal", key.Name)
- continue
- }
- // 0 <= i < len(fields)
- if visited[i] {
- check.errorf(kv.Pos(), "duplicate field name %s in struct literal", key.Name)
- continue
- }
- visited[i] = true
- check.expr(x, kv.Value, nil, iota)
- etyp := fields[i].Type
- if !check.assignment(x, etyp) {
- if x.mode != invalid {
- check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
- }
- continue
- }
- }
- } else {
- // no element must have a key
- for i, e := range e.Elts {
- if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
- check.errorf(kv.Pos(), "mixture of field:value and value elements in struct literal")
- continue
- }
- check.expr(x, e, nil, iota)
- if i >= len(fields) {
- check.errorf(x.pos(), "too many values in struct literal")
- break // cannot continue
- }
- // i < len(fields)
- etyp := fields[i].Type
- if !check.assignment(x, etyp) {
- if x.mode != invalid {
- check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
- }
- continue
- }
- }
- if len(e.Elts) < len(fields) {
- check.errorf(e.Rbrace, "too few values in struct literal")
- // ok to continue
- }
- }
-
- case *Array:
- n := check.indexedElts(e.Elts, utyp.Elt, utyp.Len, iota)
- // if we have an "open" [...]T array, set the length now that we know it
- if openArray {
- utyp.Len = n
- }
-
- case *Slice:
- check.indexedElts(e.Elts, utyp.Elt, -1, iota)
-
- case *Map:
- visited := make(map[interface{}]bool, len(e.Elts))
- for _, e := range e.Elts {
- kv, _ := e.(*ast.KeyValueExpr)
- if kv == nil {
- check.errorf(e.Pos(), "missing key in map literal")
- continue
- }
- check.compositeLitKey(kv.Key)
- check.expr(x, kv.Key, nil, iota)
- if !check.assignment(x, utyp.Key) {
- if x.mode != invalid {
- check.errorf(x.pos(), "cannot use %s as %s key in map literal", x, utyp.Key)
- }
- continue
- }
- if x.mode == constant {
- if visited[x.val] {
- check.errorf(x.pos(), "duplicate key %s in map literal", x.val)
- continue
- }
- visited[x.val] = true
- }
- check.expr(x, kv.Value, utyp.Elt, iota)
- if !check.assignment(x, utyp.Elt) {
- if x.mode != invalid {
- check.errorf(x.pos(), "cannot use %s as %s value in map literal", x, utyp.Elt)
- }
- continue
- }
- }
-
- default:
- check.errorf(e.Pos(), "%s is not a valid composite literal type", typ)
- goto Error
- }
-
- x.mode = value
- x.typ = typ
-
- case *ast.ParenExpr:
- check.rawExpr(x, e.X, nil, iota, cycleOk)
-
- case *ast.SelectorExpr:
- sel := e.Sel.Name
- // 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 pkg, ok := check.lookup(ident).(*Package); ok {
- exp := pkg.Scope.Lookup(sel)
- // gcimported package scopes contain non-exported
- // objects such as types used in partially exported
- // objects - do not accept them
- if exp == nil || !ast.IsExported(exp.GetName()) {
- check.errorf(e.Pos(), "cannot refer to unexported %s", e)
- goto Error
- }
- check.register(e.Sel, exp)
- // Simplified version of the code for *ast.Idents:
- // - imported packages use types.Scope and types.Objects
- // - imported objects are always fully initialized
- switch exp := exp.(type) {
- case *Const:
- assert(exp.Val != nil)
- x.mode = constant
- x.typ = exp.Type
- x.val = exp.Val
- case *TypeName:
- x.mode = typexpr
- x.typ = exp.Type
- case *Var:
- x.mode = variable
- x.typ = exp.Type
- case *Func:
- x.mode = value
- x.typ = exp.Type
- default:
- unreachable()
- }
- x.expr = e
- return
- }
- }
-
- check.exprOrType(x, e.X, iota, false)
- if x.mode == invalid {
- goto Error
- }
- res := lookupField(x.typ, QualifiedName{check.pkg, sel})
- if res.mode == invalid {
- check.invalidOp(e.Pos(), "%s has no single field or method %s", x, sel)
- goto Error
- }
- if x.mode == typexpr {
- // method expression
- sig, ok := res.typ.(*Signature)
- if !ok {
- check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
- goto Error
- }
- // the receiver type becomes the type of the first function
- // argument of the method expression's function type
- // TODO(gri) at the moment, method sets don't correctly track
- // pointer vs non-pointer receivers => typechecker is too lenient
- x.mode = value
- x.typ = &Signature{
- Params: append([]*Var{{Type: x.typ}}, sig.Params...),
- Results: sig.Results,
- IsVariadic: sig.IsVariadic,
- }
- } else {
- // regular selector
- x.mode = res.mode
- x.typ = res.typ
- }
-
- case *ast.IndexExpr:
- check.expr(x, e.X, nil, iota)
- if x.mode == invalid {
- goto Error
- }
-
- 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 *Pointer:
- if typ, _ := underlying(typ.Base).(*Array); typ != nil {
- valid = true
- length = typ.Len
- x.mode = variable
- x.typ = typ.Elt
- }
-
- case *Slice:
- valid = true
- x.mode = variable
- x.typ = typ.Elt
-
- case *Map:
- var key operand
- check.expr(&key, e.Index, nil, iota)
- if !check.assignment(&key, typ.Key) {
- if key.mode != invalid {
- check.invalidOp(key.pos(), "cannot use %s as map index of type %s", &key, typ.Key)
- }
- goto Error
- }
- x.mode = valueok
- x.typ = typ.Elt
- x.expr = e
- 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, nil, iota)
- if x.mode == invalid {
- goto Error
- }
-
- 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 indices
- // are constant
- x.mode = value
- // x.typ doesn't change, but if it is an untyped
- // string it becomes string (see also issue 4913).
- if typ.Kind == UntypedString {
- x.typ = Typ[String]
- }
- }
-
- 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 *Pointer:
- if typ, _ := underlying(typ.Base).(*Array); typ != nil {
- valid = true
- length = typ.Len + 1 // +1 for slice
- x.mode = variable
- 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
- }
-
- lo := int64(0)
- if e.Low != nil {
- lo = check.index(e.Low, length, iota)
- }
-
- hi := int64(-1)
- if e.High != nil {
- hi = check.index(e.High, length, iota)
- } else if length >= 0 {
- hi = length
- }
-
- if lo >= 0 && 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, nil, iota)
- if x.mode == invalid {
- goto Error
- }
- var T *Interface
- if T, _ = underlying(x.typ).(*Interface); T == nil {
- check.invalidOp(x.pos(), "%s is not an interface", x)
- goto Error
- }
- // x.(type) expressions are handled explicitly in type switches
- if e.Type == nil {
- check.errorf(e.Pos(), "use of .(type) outside type switch")
- goto Error
- }
- typ := check.typ(e.Type, false)
- if typ == Typ[Invalid] {
- goto Error
- }
- if method, wrongType := missingMethod(typ, T); method != nil {
- var msg string
- if wrongType {
- msg = "%s cannot have dynamic type %s (wrong type for method %s)"
- } else {
- msg = "%s cannot have dynamic type %s (missing method %s)"
- }
- check.errorf(e.Type.Pos(), msg, x, typ, method.Name)
- // ok to continue
- }
- x.mode = valueok
- x.expr = e
- x.typ = typ
-
- case *ast.CallExpr:
- check.exprOrType(x, e.Fun, iota, false)
- if x.mode == invalid {
- goto Error
- } else if x.mode == typexpr {
- check.conversion(x, e, x.typ, iota)
- } else if sig, ok := underlying(x.typ).(*Signature); ok {
- // check parameters
-
- // If we have a trailing ... at the end of the parameter
- // list, the last argument must match the parameter type
- // []T of a variadic function parameter x ...T.
- passSlice := false
- if e.Ellipsis.IsValid() {
- if sig.IsVariadic {
- passSlice = true
- } else {
- check.errorf(e.Ellipsis, "cannot use ... in call to %s", e.Fun)
- // ok to continue
- }
- }
-
- // If we have a single argument that is a function call
- // we need to handle it separately. Determine if this
- // is the case without checking the argument.
- var call *ast.CallExpr
- if len(e.Args) == 1 {
- call, _ = unparen(e.Args[0]).(*ast.CallExpr)
- }
-
- n := 0 // parameter count
- if call != nil {
- // We have a single argument that is a function call.
- check.expr(x, call, nil, -1)
- if x.mode == invalid {
- goto Error // TODO(gri): we can do better
- }
- if t, _ := x.typ.(*Result); t != nil {
- // multiple result values
- n = len(t.Values)
- for i, obj := range t.Values {
- x.mode = value
- x.expr = nil // TODO(gri) can we do better here? (for good error messages)
- x.typ = obj.Type
- check.argument(sig, i, nil, x, passSlice && i+1 == n)
- }
- } else {
- // single result value
- n = 1
- check.argument(sig, 0, nil, x, passSlice)
- }
-
- } else {
- // We don't have a single argument or it is not a function call.
- n = len(e.Args)
- for i, arg := range e.Args {
- check.argument(sig, i, arg, x, passSlice && i+1 == n)
- }
- }
-
- // determine if we have enough arguments
- if sig.IsVariadic {
- // a variadic function accepts an "empty"
- // last argument: count one extra
- n++
- }
- if n < len(sig.Params) {
- check.errorf(e.Fun.Pos(), "too few arguments in call to %s", e.Fun)
- // ok to continue
- }
-
- // determine result
- switch len(sig.Results) {
- case 0:
- x.mode = novalue
- case 1:
- x.mode = value
- x.typ = sig.Results[0].Type
- default:
- x.mode = value
- x.typ = &Result{Values: sig.Results}
- }
-
- } 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, iota, true)
- switch x.mode {
- case invalid:
- goto Error
- case typexpr:
- x.typ = &Pointer{Base: x.typ}
- default:
- if typ, ok := underlying(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, nil, iota)
- if x.mode == invalid {
- goto Error
- }
- check.unary(x, e.Op)
- if x.mode == invalid {
- goto Error
- }
-
- case *ast.BinaryExpr:
- check.binary(x, e.X, e.Y, e.Op, iota)
- if x.mode == invalid {
- goto Error
- }
-
- case *ast.KeyValueExpr:
- // key:value expressions are handled in composite literals
- check.invalidAST(e.Pos(), "no key:value expected")
- goto Error
-
- case *ast.ArrayType:
- if e.Len != nil {
- check.expr(x, e.Len, nil, iota)
- if x.mode == invalid {
- goto Error
- }
- if x.mode != constant {
- if x.mode != invalid {
- check.errorf(x.pos(), "array length %s must be constant", x)
- }
- goto Error
- }
- n, ok := x.val.(int64)
- if !ok || n < 0 {
- check.errorf(x.pos(), "invalid array length %s", x)
- goto Error
- }
- 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.collectFields(e.Fields, cycleOk)}
-
- case *ast.FuncType:
- params, isVariadic := check.collectParams(e.Params, true)
- results, _ := check.collectParams(e.Results, false)
- x.mode = typexpr
- x.typ = &Signature{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
-
- case *ast.InterfaceType:
- x.mode = typexpr
- x.typ = &Interface{Methods: check.collectMethods(e.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:
- if debug {
- check.dump("expr = %v (%T)", e, e)
- }
- unreachable()
- }
-
- // everything went well
- x.expr = e
- return
-
-Error:
- x.mode = invalid
- x.expr = e
-}
-
-// exprOrType is like rawExpr but reports an error if e doesn't represents a value or type.
-func (check *checker) exprOrType(x *operand, e ast.Expr, iota int, cycleOk bool) {
- check.rawExpr(x, e, nil, iota, cycleOk)
- if x.mode == novalue {
- check.errorf(x.pos(), "%s used as value or type", x)
- x.mode = invalid
- }
-}
-
-// expr is like rawExpr but reports an error if e doesn't represents a value.
-func (check *checker) expr(x *operand, e ast.Expr, hint Type, iota int) {
- check.rawExpr(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
- }
-}
-
-func (check *checker) rawTyp(e ast.Expr, cycleOk, nilOk bool) Type {
- var x operand
- check.rawExpr(&x, e, nil, -1, cycleOk)
- switch x.mode {
- case invalid:
- // ignore - error reported before
- case novalue:
- check.errorf(x.pos(), "%s used as type", &x)
- case typexpr:
- return x.typ
- case constant:
- if nilOk && x.isNil() {
- return nil
- }
- fallthrough
- default:
- check.errorf(x.pos(), "%s is not a type", &x)
- }
- return Typ[Invalid]
-}
-
-// typOrNil is like rawExpr but reports an error if e doesn't represents a type or the predeclared value nil.
-// It returns e's type, nil, or Typ[Invalid] if an error occurred.
-//
-func (check *checker) typOrNil(e ast.Expr, cycleOk bool) Type {
- return check.rawTyp(e, cycleOk, true)
-}
-
-// typ is like rawExpr but reports an error if e doesn't represents a type.
-// It returns e's type, or Typ[Invalid] if an error occurred.
-//
-func (check *checker) typ(e ast.Expr, cycleOk bool) Type {
- return check.rawTyp(e, cycleOk, false)
-}
diff --git a/src/pkg/go/types/gcimporter.go b/src/pkg/go/types/gcimporter.go
deleted file mode 100644
index 7f968eb8d..000000000
--- a/src/pkg/go/types/gcimporter.go
+++ /dev/null
@@ -1,950 +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.
-
-// This file implements an Importer for gc-generated object files.
-
-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 = strings.TrimSuffix(bp.PkgObj, ".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. The data
-// reader position must be the beginning of the export data section. The
-// filename is only used in error messages.
-//
-// If imports[id] contains the completely imported package, that package
-// can be used directly, and there is no need to call this function (but
-// there is also no harm but for extra time used).
-//
-func GcImportData(imports map[string]*Package, filename, id string, data *bufio.Reader) (pkg *Package, err error) {
- // 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]*Package, path string) (pkg *Package, err error) {
- if path == "unsafe" {
- return Unsafe, nil
- }
-
- srcDir := "."
- if build.IsLocalImport(path) {
- srcDir, err = os.Getwd()
- if err != nil {
- return
- }
- }
-
- filename, id := FindPkg(path, srcDir)
- if filename == "" {
- err = errors.New("can't find import: " + id)
- return
- }
-
- // no need to re-import if the package was imported completely before
- if pkg = imports[id]; pkg != nil && pkg.Complete {
- return
- }
-
- // 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]*Package // package id -> package object
-}
-
-func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*Package) {
- 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
- // leave for debugging
- if false {
- // check consistency of imports map
- for _, pkg := range imports {
- if pkg.Name == "" {
- fmt.Printf("no package name for %s\n", pkg.Path)
- }
- }
- }
-}
-
-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 = ""
- }
- // leave for debugging
- if false {
- fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
- }
-}
-
-func declConst(pkg *Package, name string) *Const {
- // the constant may have been imported before - if it exists
- // already in the respective scope, return that constant
- scope := pkg.Scope
- if obj := scope.Lookup(name); obj != nil {
- return obj.(*Const)
- }
- // otherwise create a new constant and insert it into the scope
- obj := &Const{Pkg: pkg, Name: name}
- scope.Insert(obj)
- return obj
-}
-
-func declTypeName(pkg *Package, name string) *TypeName {
- scope := pkg.Scope
- if obj := scope.Lookup(name); obj != nil {
- return obj.(*TypeName)
- }
- obj := &TypeName{Pkg: pkg, Name: name}
- // a named type may be referred to before the underlying type
- // is known - set it up
- obj.Type = &NamedType{Obj: obj}
- scope.Insert(obj)
- return obj
-}
-
-func declVar(pkg *Package, name string) *Var {
- scope := pkg.Scope
- if obj := scope.Lookup(name); obj != nil {
- return obj.(*Var)
- }
- obj := &Var{Pkg: pkg, Name: name}
- scope.Insert(obj)
- return obj
-}
-
-func declFunc(pkg *Package, name string) *Func {
- scope := pkg.Scope
- if obj := scope.Lookup(name); obj != nil {
- return obj.(*Func)
- }
- obj := &Func{Pkg: pkg, Name: name}
- scope.Insert(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)
- }
-}
-
-// ----------------------------------------------------------------------------
-// Qualified and unqualified names
-
-// PackageId = string_lit .
-//
-func (p *gcParser) parsePackageId() string {
- id, err := strconv.Unquote(p.expect(scanner.String))
- if err != nil {
- p.error(err)
- }
- // id == "" stands for the imported package id
- // (only known at time of package installation)
- if id == "" {
- id = p.id
- }
- return id
-}
-
-// PackageName = ident .
-//
-func (p *gcParser) parsePackageName() string {
- return p.expect(scanner.Ident)
-}
-
-// 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
-}
-
-// QualifiedName = "@" PackageId "." dotIdentifier .
-//
-func (p *gcParser) parseQualifiedName() (id, name string) {
- p.expect('@')
- id = p.parsePackageId()
- p.expect('.')
- name = p.parseDotIdent()
- return
-}
-
-// getPkg returns the package for a given id. If the package is
-// not found but we have a package name, create the package and
-// add it to the p.imports map.
-//
-func (p *gcParser) getPkg(id, name string) *Package {
- // package unsafe is not in the imports map - handle explicitly
- if id == "unsafe" {
- return Unsafe
- }
- pkg := p.imports[id]
- if pkg == nil && name != "" {
- pkg = &Package{Name: name, Path: id, Scope: new(Scope)}
- p.imports[id] = pkg
- }
- return pkg
-}
-
-// parseExportedName is like parseQualifiedName, but
-// the package id is resolved to an imported *Package.
-//
-func (p *gcParser) parseExportedName() (pkg *Package, name string) {
- id, name := p.parseQualifiedName()
- pkg = p.getPkg(id, "")
- if pkg == nil {
- p.errorf("%s package not found", id)
- }
- return
-}
-
-// ----------------------------------------------------------------------------
-// Types
-
-// BasicType = identifier .
-//
-func (p *gcParser) parseBasicType() Type {
- id := p.expect(scanner.Ident)
- obj := Universe.Lookup(id)
- if obj, ok := obj.(*TypeName); ok {
- return obj.Type
- }
- p.errorf("not a basic type: %s", id)
- return nil
-}
-
-// 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 | "?" | QualifiedName .
-//
-// If materializePkg is set, a package is returned for fully qualified names.
-// That package may be a fake package (without name, scope, and not in the
-// p.imports map), created for the sole purpose of providing a package path
-// for QualifiedNames. Fake packages are created when the package id is not
-// found in the p.imports map; we cannot create a real package in that case
-// because we don't have a package name.
-//
-// TODO(gri): consider changing QualifiedIdents to (path, name) pairs to
-// simplify this code.
-//
-func (p *gcParser) parseName(materializePkg bool) (pkg *Package, name string) {
- switch p.tok {
- case scanner.Ident:
- name = p.lit
- p.next()
- case '?':
- // anonymous
- p.next()
- case '@':
- // exported name prefixed with package path
- var id string
- id, name = p.parseQualifiedName()
- if materializePkg {
- // we don't have a package name - if the package
- // doesn't exist yet, create a fake package instead
- pkg = p.getPkg(id, "")
- if pkg == nil {
- pkg = &Package{Path: id}
- }
- }
- default:
- p.error("name expected")
- }
- return
-}
-
-// Field = Name Type [ string_lit ] .
-//
-func (p *gcParser) parseField() *Field {
- var f Field
- f.Pkg, f.Name = p.parseName(true)
- 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.GetName()
- f.IsAnonymous = true
- } else {
- p.errorf("anonymous field expected")
- }
- }
- return &f
-}
-
-// StructType = "struct" "{" [ FieldList ] "}" .
-// FieldList = Field { ";" Field } .
-//
-func (p *gcParser) parseStructType() Type {
- var fields []*Field
-
- p.expectKeyword("struct")
- p.expect('{')
- for p.tok != '}' {
- if len(fields) > 0 {
- p.expect(';')
- }
- fields = append(fields, p.parseField())
- }
- p.expect('}')
-
- return &Struct{Fields: fields}
-}
-
-// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
-//
-func (p *gcParser) parseParameter() (par *Var, isVariadic bool) {
- _, name := p.parseName(false)
- if name == "" {
- name = "_" // cannot access unnamed identifiers
- }
- if p.tok == '.' {
- p.expectSpecial("...")
- isVariadic = true
- }
- typ := p.parseType()
- // ignore argument tag (e.g. "noescape")
- if p.tok == scanner.String {
- p.next()
- }
- par = &Var{Name: name, Type: typ} // Pkg == nil
- return
-}
-
-// Parameters = "(" [ ParameterList ] ")" .
-// ParameterList = { Parameter "," } Parameter .
-//
-func (p *gcParser) parseParameters() (list []*Var, isVariadic bool) {
- p.expect('(')
- for p.tok != ')' {
- if len(list) > 0 {
- p.expect(',')
- }
- par, variadic := p.parseParameter()
- list = append(list, par)
- if variadic {
- if isVariadic {
- p.error("... not on final argument")
- }
- isVariadic = true
- }
- }
- p.expect(')')
-
- return
-}
-
-// Signature = Parameters [ Result ] .
-// Result = Type | Parameters .
-//
-func (p *gcParser) parseSignature() *Signature {
- params, isVariadic := p.parseParameters()
-
- // optional result type
- var results []*Var
- if p.tok == '(' {
- 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 []*Method
-
- p.expectKeyword("interface")
- p.expect('{')
- for p.tok != '}' {
- if len(methods) > 0 {
- p.expect(';')
- }
- pkg, name := p.parseName(true)
- typ := p.parseSignature()
- methods = append(methods, &Method{QualifiedName{pkg, name}, typ})
- }
- p.expect('}')
-
- 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 declTypeName(pkg, name).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" PackageName PackageId .
-//
-func (p *gcParser) parseImportDecl() {
- p.expectKeyword("import")
- name := p.parsePackageName()
- p.getPkg(p.parsePackageId(), 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 := declConst(pkg, 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.Val = x.val
-}
-
-// TypeDecl = "type" ExportedName Type .
-//
-func (p *gcParser) parseTypeDecl() {
- p.expectKeyword("type")
- pkg, name := p.parseExportedName()
- obj := declTypeName(pkg, 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 := declVar(pkg, name)
- obj.Type = p.parseType()
-}
-
-// Func = Signature [ Body ] .
-// Body = "{" ... "}" .
-//
-func (p *gcParser) parseFunc() *Signature {
- sig := p.parseSignature()
- if p.tok == '{' {
- p.next()
- for i := 1; i > 0; p.next() {
- switch p.tok {
- case '{':
- i++
- case '}':
- i--
- }
- }
- }
- return sig
-}
-
-// MethodDecl = "func" Receiver Name Func .
-// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
-//
-func (p *gcParser) parseMethodDecl() {
- // "func" already consumed
- p.expect('(')
- recv, _ := p.parseParameter() // receiver
- p.expect(')')
-
- // determine receiver base type object
- typ := recv.Type
- if ptr, ok := typ.(*Pointer); ok {
- typ = ptr.Base
- }
- base := typ.(*NamedType)
-
- // parse method name, signature, and possibly inlined body
- pkg, name := p.parseName(true) // unexported method names in imports are qualified with their package.
- sig := p.parseFunc()
- sig.Recv = recv
-
- // add method to type unless type was imported before
- // and method exists already
- // TODO(gri) investigate if this can be avoided
- for _, m := range base.Methods {
- if m.Name == name {
- return // method was added before
- }
- }
- base.Methods = append(base.Methods, &Method{QualifiedName{pkg, name}, sig})
-}
-
-// FuncDecl = "func" ExportedName Func .
-//
-func (p *gcParser) parseFuncDecl() {
- // "func" already consumed
- pkg, name := p.parseExportedName()
- typ := p.parseFunc()
- declFunc(pkg, name).Type = typ
-}
-
-// 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" PackageName [ "safe" ] "\n" .
-//
-func (p *gcParser) parseExport() *Package {
- p.expectKeyword("package")
- name := p.parsePackageName()
- 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.getPkg(p.id, name)
-
- 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)
- }
-
- // package was imported completely and without errors
- pkg.Complete = true
-
- return pkg
-}
diff --git a/src/pkg/go/types/gcimporter_test.go b/src/pkg/go/types/gcimporter_test.go
deleted file mode 100644
index b793eb4cb..000000000
--- a/src/pkg/go/types/gcimporter_test.go
+++ /dev/null
@@ -1,180 +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 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]*Package)
-
-func testPath(t *testing.T, path string) bool {
- t0 := time.Now()
- _, err := GcImport(imports, path)
- if err != nil {
- t.Errorf("testPath(%s): %s", path, err)
- return false
- }
- t.Logf("testPath(%s): %v", path, time.Since(t0))
- return true
-}
-
-const maxTime = 30 * 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.Fatalf("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.Skipf("skipping test: %v", err)
- }
-
- 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·2 float64) (_ float64)"},
- // TODO(gri) add more tests
-}
-
-func TestGcImportedTypes(t *testing.T) {
- // This package does not yet know how to read gccgo export data.
- if runtime.Compiler == "gccgo" {
- return
- }
- 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.Scope.Lookup(objName)
-
- // TODO(gri) should define an accessor on Object
- var kind ast.ObjKind
- var typ Type
- switch obj := obj.(type) {
- case *Const:
- kind = ast.Con
- typ = obj.Type
- case *TypeName:
- kind = ast.Typ
- typ = obj.Type
- case *Var:
- kind = ast.Var
- typ = obj.Type
- case *Func:
- kind = ast.Fun
- typ = obj.Type
- default:
- unreachable()
- }
-
- if kind != test.kind {
- t.Errorf("%s: got kind = %q; want %q", test.name, kind, test.kind)
- }
-
- str := typeString(underlying(typ))
- if str != test.typ {
- t.Errorf("%s: got type = %q; want %q", test.name, typ, test.typ)
- }
- }
-}
diff --git a/src/pkg/go/types/objects.go b/src/pkg/go/types/objects.go
deleted file mode 100644
index 02291d34c..000000000
--- a/src/pkg/go/types/objects.go
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package types
-
-import (
- "go/ast"
- "go/token"
-)
-
-// An Object describes a named language entity such as a package,
-// constant, type, variable, function (incl. methods), or label.
-// All objects implement the Object interface.
-//
-type Object interface {
- GetPkg() *Package
- GetName() string
- GetType() Type
- GetPos() token.Pos
-
- anObject()
-}
-
-// A Package represents the contents (objects) of a Go package.
-type Package struct {
- Name string
- Path string // import path, "" for current (non-imported) package
- Scope *Scope // package-level scope
- Imports map[string]*Package // map of import paths to imported packages
- Complete bool // if set, this package was imported completely
-
- spec *ast.ImportSpec
-}
-
-// A Const represents a declared constant.
-type Const struct {
- Pkg *Package
- Name string
- Type Type
- Val interface{}
-
- spec *ast.ValueSpec
-}
-
-// A TypeName represents a declared type.
-type TypeName struct {
- Pkg *Package
- Name string
- Type Type // *NamedType or *Basic
-
- spec *ast.TypeSpec
-}
-
-// A Variable represents a declared variable (including function parameters and results).
-type Var struct {
- Pkg *Package // nil for parameters
- Name string
- Type Type
-
- visited bool // for initialization cycle detection
- decl interface{}
-}
-
-// A Func represents a declared function.
-type Func struct {
- Pkg *Package
- Name string
- Type Type // *Signature or *Builtin
-
- decl *ast.FuncDecl
-}
-
-func (obj *Package) GetPkg() *Package { return obj }
-func (obj *Const) GetPkg() *Package { return obj.Pkg }
-func (obj *TypeName) GetPkg() *Package { return obj.Pkg }
-func (obj *Var) GetPkg() *Package { return obj.Pkg }
-func (obj *Func) GetPkg() *Package { return obj.Pkg }
-
-func (obj *Package) GetName() string { return obj.Name }
-func (obj *Const) GetName() string { return obj.Name }
-func (obj *TypeName) GetName() string { return obj.Name }
-func (obj *Var) GetName() string { return obj.Name }
-func (obj *Func) GetName() string { return obj.Name }
-
-func (obj *Package) GetType() Type { return Typ[Invalid] }
-func (obj *Const) GetType() Type { return obj.Type }
-func (obj *TypeName) GetType() Type { return obj.Type }
-func (obj *Var) GetType() Type { return obj.Type }
-func (obj *Func) GetType() Type { return obj.Type }
-
-func (obj *Package) GetPos() token.Pos {
- if obj.spec != nil {
- return obj.spec.Pos()
- }
- return token.NoPos
-}
-
-func (obj *Const) GetPos() token.Pos {
- for _, n := range obj.spec.Names {
- if n.Name == obj.Name {
- return n.Pos()
- }
- }
- return token.NoPos
-}
-func (obj *TypeName) GetPos() token.Pos {
- if obj.spec != nil {
- return obj.spec.Pos()
- }
- return token.NoPos
-}
-
-func (obj *Var) GetPos() token.Pos {
- switch d := obj.decl.(type) {
- case *ast.Field:
- for _, n := range d.Names {
- if n.Name == obj.Name {
- return n.Pos()
- }
- }
- case *ast.ValueSpec:
- for _, n := range d.Names {
- if n.Name == obj.Name {
- return n.Pos()
- }
- }
- case *ast.AssignStmt:
- for _, x := range d.Lhs {
- if ident, isIdent := x.(*ast.Ident); isIdent && ident.Name == obj.Name {
- return ident.Pos()
- }
- }
- }
- return token.NoPos
-}
-func (obj *Func) GetPos() token.Pos {
- if obj.decl != nil && obj.decl.Name != nil {
- return obj.decl.Name.Pos()
- }
- return token.NoPos
-}
-
-func (*Package) anObject() {}
-func (*Const) anObject() {}
-func (*TypeName) anObject() {}
-func (*Var) anObject() {}
-func (*Func) anObject() {}
-
-// newObj returns a new Object for a given *ast.Object.
-// It does not canonicalize them (it always returns a new one).
-// For canonicalization, see check.lookup.
-//
-// TODO(gri) Once we do identifier resolution completely in
-// in the typechecker, this functionality can go.
-//
-func newObj(pkg *Package, astObj *ast.Object) Object {
- assert(pkg != nil)
- name := astObj.Name
- typ, _ := astObj.Type.(Type)
- switch astObj.Kind {
- case ast.Bad:
- // ignore
- case ast.Pkg:
- unreachable()
- case ast.Con:
- return &Const{Pkg: pkg, Name: name, Type: typ, Val: astObj.Data, spec: astObj.Decl.(*ast.ValueSpec)}
- case ast.Typ:
- return &TypeName{Pkg: pkg, Name: name, Type: typ, spec: astObj.Decl.(*ast.TypeSpec)}
- case ast.Var:
- switch astObj.Decl.(type) {
- case *ast.Field: // function parameters
- case *ast.ValueSpec: // proper variable declarations
- case *ast.AssignStmt: // short variable declarations
- default:
- unreachable() // everything else is not ok
- }
- return &Var{Pkg: pkg, Name: name, Type: typ, decl: astObj.Decl}
- case ast.Fun:
- return &Func{Pkg: pkg, Name: name, Type: typ, decl: astObj.Decl.(*ast.FuncDecl)}
- case ast.Lbl:
- unreachable() // for now
- }
- unreachable()
- return nil
-}
diff --git a/src/pkg/go/types/operand.go b/src/pkg/go/types/operand.go
deleted file mode 100644
index 982ffef8d..000000000
--- a/src/pkg/go/types/operand.go
+++ /dev/null
@@ -1,411 +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.
-
-// 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 {
- format := " %v"
- if isString(x.typ) {
- format = " %q"
- }
- fmt.Fprintf(&buf, format, 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
- }
-}
-
-// isNil reports whether x is the predeclared nil constant.
-func (x *operand) isNil() bool {
- return x.mode == constant && x.val == nilConst
-}
-
-// TODO(gri) The functions operand.isAssignable, checker.convertUntyped,
-// checker.isRepresentable, and checker.assignOperand are
-// overlapping in functionality. Need to simplify and clean up.
-
-// isAssignable reports whether x is assignable to a variable of type T.
-func (x *operand) isAssignable(ctxt *Context, 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 {
- if m, _ := missingMethod(x.typ, Ti); m == nil {
- 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.isNil() {
- switch t := Tu.(type) {
- case *Basic:
- if t.Kind == UnsafePointer {
- return true
- }
- case *Pointer, *Signature, *Slice, *Map, *Chan, *Interface:
- return true
- }
- return false
- }
-
- // x is an untyped constant representable by a value of type T
- // TODO(gri) This is borrowing from checker.convertUntyped and
- // checker.isRepresentable. Need to clean up.
- if isUntyped(Vu) {
- switch t := Tu.(type) {
- case *Basic:
- if x.mode == constant {
- return isRepresentableConst(x.val, ctxt, t.Kind)
- }
- // The result of a comparison is an untyped boolean,
- // but may not be a constant.
- if Vb, _ := Vu.(*Basic); Vb != nil {
- return Vb.Kind == UntypedBool && isBoolean(Tu)
- }
- case *Interface:
- return x.isNil() || len(t.Methods) == 0
- case *Pointer, *Signature, *Slice, *Map, *Chan:
- return x.isNil()
- }
- }
-
- return false
-}
-
-// isInteger reports whether x is a (typed or untyped) integer value.
-func (x *operand) isInteger(ctxt *Context) bool {
- return x.mode == invalid ||
- isInteger(x.typ) ||
- x.mode == constant && isRepresentableConst(x.val, ctxt, UntypedInt)
-}
-
-// lookupResult represents the result of a struct field/method lookup.
-type lookupResult struct {
- mode operandMode
- typ Type
- index []int // field index sequence; nil for methods
-}
-
-type embeddedType struct {
- typ *NamedType
- index []int // field index sequence
- multiples bool // if set, typ is embedded multiple times at the same level
-}
-
-// lookupFieldBreadthFirst searches all types in list for a single entry (field
-// or method) of the given name from the given package. If such a field is found,
-// the result describes the field mode and type; otherwise the result mode is invalid.
-// (This function is similar in structure to FieldByNameFunc in reflect/type.go)
-//
-func lookupFieldBreadthFirst(list []embeddedType, name QualifiedName) (res lookupResult) {
- // visited records the types that have been searched already.
- visited := make(map[*NamedType]bool)
-
- // embedded types of the next lower level
- var next []embeddedType
-
- // potentialMatch is invoked every time a match is found.
- potentialMatch := func(multiples bool, mode operandMode, typ Type) bool {
- if multiples || res.mode != invalid {
- // name appeared already at this level - annihilate
- res.mode = invalid
- return false
- }
- // first appearance of name
- res.mode = mode
- res.typ = typ
- res.index = nil
- return true
- }
-
- // Search the current level if there is any work to do and collect
- // embedded types of the next lower level in the next list.
- for len(list) > 0 {
- // The res.mode indicates whether we have found a match already
- // on this level (mode != invalid), or not (mode == invalid).
- assert(res.mode == invalid)
-
- // start with empty next list (don't waste underlying array)
- next = next[:0]
-
- // look for name in all types at this level
- for _, e := range list {
- typ := e.typ
- if visited[typ] {
- continue
- }
- visited[typ] = true
-
- // look for a matching attached method
- for _, m := range typ.Methods {
- if name.IsSame(m.QualifiedName) {
- assert(m.Type != nil)
- if !potentialMatch(e.multiples, value, m.Type) {
- return // name collision
- }
- }
- }
-
- switch t := typ.Underlying.(type) {
- case *Struct:
- // look for a matching field and collect embedded types
- for i, f := range t.Fields {
- if name.IsSame(f.QualifiedName) {
- assert(f.Type != nil)
- if !potentialMatch(e.multiples, variable, f.Type) {
- return // name collision
- }
- var index []int
- index = append(index, e.index...) // copy e.index
- index = append(index, i)
- res.index = index
- continue
- }
- // Collect embedded struct fields for searching the next
- // lower level, but only if we have not seen a match yet
- // (if we have a match it is either the desired field or
- // we have a name collision on the same level; in either
- // case we don't need to look further).
- // Embedded fields are always of the form T or *T where
- // T is a named type. If typ appeared multiple times at
- // this level, f.Type appears multiple times at the next
- // level.
- if f.IsAnonymous && res.mode == invalid {
- // Ignore embedded basic types - only user-defined
- // named types can have methods or have struct fields.
- if t, _ := deref(f.Type).(*NamedType); t != nil {
- var index []int
- index = append(index, e.index...) // copy e.index
- index = append(index, i)
- next = append(next, embeddedType{t, index, e.multiples})
- }
- }
- }
-
- case *Interface:
- // look for a matching method
- for _, m := range t.Methods {
- if name.IsSame(m.QualifiedName) {
- assert(m.Type != nil)
- if !potentialMatch(e.multiples, value, m.Type) {
- return // name collision
- }
- }
- }
- }
- }
-
- if res.mode != invalid {
- // we found a single match on this level
- return
- }
-
- // No match and no collision so far.
- // Compute the list to search for the next level.
- list = list[:0] // don't waste underlying array
- for _, e := range next {
- // Instead of adding the same type multiple times, look for
- // it in the list and mark it as multiple if it was added
- // before.
- // We use a sequential search (instead of a map for next)
- // because the lists tend to be small, can easily be reused,
- // and explicit search appears to be faster in this case.
- if alt := findType(list, e.typ); alt != nil {
- alt.multiples = true
- } else {
- list = append(list, e)
- }
- }
-
- }
-
- return
-}
-
-func findType(list []embeddedType, typ *NamedType) *embeddedType {
- for i := range list {
- if p := &list[i]; p.typ == typ {
- return p
- }
- }
- return nil
-}
-
-func lookupField(typ Type, name QualifiedName) lookupResult {
- typ = deref(typ)
-
- if t, ok := typ.(*NamedType); ok {
- for _, m := range t.Methods {
- if name.IsSame(m.QualifiedName) {
- assert(m.Type != nil)
- return lookupResult{value, m.Type, nil}
- }
- }
- typ = t.Underlying
- }
-
- switch t := typ.(type) {
- case *Struct:
- var next []embeddedType
- for i, f := range t.Fields {
- if name.IsSame(f.QualifiedName) {
- return lookupResult{variable, f.Type, []int{i}}
- }
- if f.IsAnonymous {
- // Possible optimization: If the embedded type
- // is a pointer to the current type we could
- // ignore it.
- // Ignore embedded basic types - only user-defined
- // named types can have methods or have struct fields.
- if t, _ := deref(f.Type).(*NamedType); t != nil {
- next = append(next, embeddedType{t, []int{i}, false})
- }
- }
- }
- if len(next) > 0 {
- return lookupFieldBreadthFirst(next, name)
- }
-
- case *Interface:
- for _, m := range t.Methods {
- if name.IsSame(m.QualifiedName) {
- return lookupResult{value, m.Type, nil}
- }
- }
- }
-
- // not found
- return lookupResult{mode: invalid}
-}
diff --git a/src/pkg/go/types/predicates.go b/src/pkg/go/types/predicates.go
deleted file mode 100644
index a99c91a4e..000000000
--- a/src/pkg/go/types/predicates.go
+++ /dev/null
@@ -1,303 +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.
-
-// 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 isConstType(typ Type) bool {
- t, ok := underlying(typ).(*Basic)
- return ok && t.Info&IsConstType != 0
-}
-
-func isComparable(typ Type) bool {
- switch t := underlying(typ).(type) {
- case *Basic:
- return t.Kind != Invalid && t.Kind != UntypedNil
- case *Pointer, *Interface, *Chan:
- // 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
-}
-
-func hasNil(typ Type) bool {
- switch underlying(typ).(type) {
- case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
- return true
- }
- return false
-}
-
-// IsIdentical 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 {
- if len(x.Fields) == len(y.Fields) {
- for i, f := range x.Fields {
- g := y.Fields[i]
- if !f.QualifiedName.IsSame(g.QualifiedName) ||
- !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 identicalMethods(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 []*Var) bool {
- if len(a) != len(b) {
- return false
- }
- for i, x := range a {
- y := b[i]
- if !IsIdentical(x.Type, y.Type) {
- return false
- }
- }
- return true
-}
-
-// identicalMethods returns true if both lists a and b have the
-// same length and corresponding methods have identical types.
-// TODO(gri) make this more efficient
-func identicalMethods(a, b []*Method) bool {
- if len(a) != len(b) {
- return false
- }
- m := make(map[QualifiedName]*Method)
- for _, x := range a {
- assert(m[x.QualifiedName] == nil) // method list must not have duplicate entries
- m[x.QualifiedName] = x
- }
- for _, y := range b {
- if x := m[y.QualifiedName]; x == nil || !IsIdentical(x.Type, y.Type) {
- return false
- }
- }
- return true
-}
-
-// 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 incoming type for all other types. If there is no
-// corresponding untyped type, the result is Typ[Invalid].
-//
-func defaultType(typ Type) Type {
- if t, ok := typ.(*Basic); ok {
- k := Invalid
- switch t.Kind {
- // case UntypedNil:
- // There is no default type for nil. For a good error message,
- // catch this case before calling this function.
- case UntypedBool:
- k = Bool
- case UntypedInt:
- k = Int
- case UntypedRune:
- k = Rune
- case UntypedFloat:
- k = Float64
- case UntypedComplex:
- k = Complex128
- case UntypedString:
- k = String
- }
- typ = Typ[k]
- }
- return typ
-}
-
-// missingMethod returns (nil, false) if typ implements T, otherwise
-// it returns the first missing method required by T and whether it
-// is missing or simply has the wrong type.
-//
-func missingMethod(typ Type, T *Interface) (method *Method, wrongType bool) {
- // TODO(gri): this needs to correctly compare method names (taking package into account)
- // TODO(gri): distinguish pointer and non-pointer receivers
- // an interface type implements T if it has no methods with conflicting signatures
- // Note: This is stronger than the current spec. Should the spec require this?
- if ityp, _ := underlying(typ).(*Interface); ityp != nil {
- for _, m := range T.Methods {
- res := lookupField(ityp, m.QualifiedName) // TODO(gri) no need to go via lookupField
- if res.mode != invalid && !IsIdentical(res.typ, m.Type) {
- return m, true
- }
- }
- return
- }
-
- // a concrete type implements T if it implements all methods of T.
- for _, m := range T.Methods {
- res := lookupField(typ, m.QualifiedName)
- if res.mode == invalid {
- return m, false
- }
- if !IsIdentical(res.typ, m.Type) {
- return m, true
- }
- }
- return
-}
diff --git a/src/pkg/go/types/resolve.go b/src/pkg/go/types/resolve.go
deleted file mode 100644
index 43db60708..000000000
--- a/src/pkg/go/types/resolve.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package types
-
-import (
- "fmt"
- "go/ast"
- "go/token"
- "strconv"
-)
-
-func (check *checker) declareObj(scope, altScope *Scope, obj Object, dotImport token.Pos) {
- alt := scope.Insert(obj)
- if alt == nil && altScope != nil {
- // see if there is a conflicting declaration in altScope
- alt = altScope.Lookup(obj.GetName())
- }
- if alt != nil {
- prevDecl := ""
-
- // for dot-imports, local declarations are declared first - swap messages
- if dotImport.IsValid() {
- if pos := alt.GetPos(); pos.IsValid() {
- check.errorf(pos, fmt.Sprintf("%s redeclared in this block by dot-import at %s",
- obj.GetName(), check.fset.Position(dotImport)))
- return
- }
-
- // get by w/o other position
- check.errorf(dotImport, fmt.Sprintf("dot-import redeclares %s", obj.GetName()))
- return
- }
-
- if pos := alt.GetPos(); pos.IsValid() {
- prevDecl = fmt.Sprintf("\n\tother declaration at %s", check.fset.Position(pos))
- }
- check.errorf(obj.GetPos(), fmt.Sprintf("%s redeclared in this block%s", obj.GetName(), prevDecl))
- }
-}
-
-func (check *checker) resolveIdent(scope *Scope, ident *ast.Ident) bool {
- for ; scope != nil; scope = scope.Outer {
- if obj := scope.Lookup(ident.Name); obj != nil {
- check.register(ident, obj)
- return true
- }
- }
- return false
-}
-
-func (check *checker) resolve(importer Importer) (methods []*ast.FuncDecl) {
- pkg := &Package{Scope: &Scope{Outer: Universe}, Imports: make(map[string]*Package)}
- check.pkg = pkg
-
- // complete package scope
- i := 0
- for _, file := range check.files {
- // package names must match
- switch name := file.Name.Name; {
- case pkg.Name == "":
- pkg.Name = name
- case name != pkg.Name:
- check.errorf(file.Package, "package %s; expected %s", name, pkg.Name)
- continue // ignore this file
- }
-
- // keep this file
- check.files[i] = file
- i++
-
- // the package identifier denotes the current package
- check.register(file.Name, pkg)
-
- // insert top-level file objects in package scope
- // (the parser took care of declaration errors)
- for _, decl := range file.Decls {
- switch d := decl.(type) {
- case *ast.BadDecl:
- // ignore
- case *ast.GenDecl:
- if d.Tok == token.CONST {
- check.assocInitvals(d)
- }
- for _, spec := range d.Specs {
- switch s := spec.(type) {
- case *ast.ImportSpec:
- // handled separately below
- case *ast.ValueSpec:
- for _, name := range s.Names {
- if name.Name == "_" {
- continue
- }
- pkg.Scope.Insert(check.lookup(name))
- }
- case *ast.TypeSpec:
- if s.Name.Name == "_" {
- continue
- }
- pkg.Scope.Insert(check.lookup(s.Name))
- default:
- check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
- }
- }
- case *ast.FuncDecl:
- if d.Recv != nil {
- // collect method
- methods = append(methods, d)
- continue
- }
- if d.Name.Name == "_" || d.Name.Name == "init" {
- continue // blank (_) and init functions are inaccessible
- }
- pkg.Scope.Insert(check.lookup(d.Name))
- default:
- check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
- }
- }
- }
- check.files = check.files[0:i]
-
- // complete file scopes with imports and resolve identifiers
- for _, file := range check.files {
- // build file scope by processing all imports
- importErrors := false
- fileScope := &Scope{Outer: pkg.Scope}
- for _, spec := range file.Imports {
- if importer == nil {
- importErrors = true
- continue
- }
- path, _ := strconv.Unquote(spec.Path.Value)
- imp, err := importer(pkg.Imports, path)
- if err != nil {
- check.errorf(spec.Path.Pos(), "could not import %s (%s)", path, err)
- importErrors = true
- continue
- }
- // TODO(gri) If a local package name != "." is provided,
- // global identifier resolution could proceed even if the
- // import failed. Consider adjusting the logic here a bit.
-
- // local name overrides imported package name
- name := imp.Name
- if spec.Name != nil {
- name = spec.Name.Name
- }
-
- // add import to file scope
- if name == "." {
- // merge imported scope with file scope
- for _, obj := range imp.Scope.Entries {
- // gcimported package scopes contain non-exported
- // objects such as types used in partially exported
- // objects - do not accept them
- if ast.IsExported(obj.GetName()) {
- check.declareObj(fileScope, pkg.Scope, obj, spec.Pos())
- }
- }
- // TODO(gri) consider registering the "." identifier
- // if we have Context.Ident callbacks for say blank
- // (_) identifiers
- // check.register(spec.Name, pkg)
- } else if name != "_" {
- // declare imported package object in file scope
- // (do not re-use imp in the file scope but create
- // a new object instead; the Decl field is different
- // for different files)
- obj := &Package{Name: name, Scope: imp.Scope, spec: spec}
- check.declareObj(fileScope, pkg.Scope, obj, token.NoPos)
- }
- }
-
- // resolve identifiers
- if importErrors {
- // don't use the universe scope without correct imports
- // (objects in the universe may be shadowed by imports;
- // with missing imports, identifiers might get resolved
- // incorrectly to universe objects)
- pkg.Scope.Outer = nil
- }
- i := 0
- for _, ident := range file.Unresolved {
- if !check.resolveIdent(fileScope, ident) {
- check.errorf(ident.Pos(), "undeclared name: %s", ident.Name)
- file.Unresolved[i] = ident
- i++
- }
-
- }
- file.Unresolved = file.Unresolved[0:i]
- pkg.Scope.Outer = Universe // reset outer scope (is nil if there were importErrors)
- }
-
- return
-}
diff --git a/src/pkg/go/types/resolver_test.go b/src/pkg/go/types/resolver_test.go
deleted file mode 100644
index d4e364451..000000000
--- a/src/pkg/go/types/resolver_test.go
+++ /dev/null
@@ -1,167 +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 types
-
-import (
- "go/ast"
- "go/parser"
- "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 {
- _ = "foo"
- return fmt.Sprintf("%d", g())
- }
- func g() (x int) { return }
- `,
- `
- package p
- import . "go/parser"
- import "sync"
- func g() Mode { return ImportsOnly }
- var _, x int = 1, 2
- func init() {}
- type T struct{ sync.Mutex; a, b, c int}
- type I interface{ m() }
- var _ = T{a: 1, b: 2, c: 3}
- func (_ T) m() {}
- `,
-}
-
-var pkgnames = []string{
- "fmt",
- "math",
-}
-
-func TestResolveQualifiedIdents(t *testing.T) {
- // parse package files
- fset := token.NewFileSet()
- var files []*ast.File
- for _, src := range sources {
- f, err := parser.ParseFile(fset, "", src, parser.DeclarationErrors)
- if err != nil {
- t.Fatal(err)
- }
- files = append(files, f)
- }
-
- // resolve and type-check package AST
- idents := make(map[*ast.Ident]Object)
- var ctxt Context
- ctxt.Ident = func(id *ast.Ident, obj Object) { idents[id] = obj }
- pkg, err := ctxt.Check(fset, files)
- 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 files {
- for _, x := range f.Unresolved {
- t.Errorf("%s: unresolved global identifier %s", fset.Position(x.Pos()), x.Name)
- }
- }
-
- // check that qualified identifiers are resolved
- for _, f := range files {
- ast.Inspect(f, func(n ast.Node) bool {
- if s, ok := n.(*ast.SelectorExpr); ok {
- if x, ok := s.X.(*ast.Ident); ok {
- obj := idents[x]
- if obj == nil {
- t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
- return false
- }
- if _, ok := obj.(*Package); ok && idents[s.Sel] == nil {
- t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
- return false
- }
- return false
- }
- return false
- }
- return true
- })
- }
-
- // Currently, the Check API doesn't call Ident for fields, methods, and composite literal keys.
- // Introduce them artifically so that we can run the check below.
- for _, f := range files {
- ast.Inspect(f, func(n ast.Node) bool {
- switch x := n.(type) {
- case *ast.StructType:
- for _, list := range x.Fields.List {
- for _, f := range list.Names {
- assert(idents[f] == nil)
- idents[f] = &Var{Pkg: pkg, Name: f.Name}
- }
- }
- case *ast.InterfaceType:
- for _, list := range x.Methods.List {
- for _, f := range list.Names {
- assert(idents[f] == nil)
- idents[f] = &Func{Pkg: pkg, Name: f.Name}
- }
- }
- case *ast.CompositeLit:
- for _, e := range x.Elts {
- if kv, ok := e.(*ast.KeyValueExpr); ok {
- if k, ok := kv.Key.(*ast.Ident); ok {
- assert(idents[k] == nil)
- idents[k] = &Var{Pkg: pkg, Name: k.Name}
- }
- }
- }
- }
- return true
- })
- }
-
- // check that each identifier in the source is enumerated by the Context.Ident callback
- for _, f := range files {
- ast.Inspect(f, func(n ast.Node) bool {
- if x, ok := n.(*ast.Ident); ok && x.Name != "_" && x.Name != "." {
- obj := idents[x]
- if obj == nil {
- t.Errorf("%s: unresolved identifier %s", fset.Position(x.Pos()), x.Name)
- } else {
- delete(idents, x)
- }
- return false
- }
- return true
- })
- }
-
- // TODO(gri) enable code below
- // At the moment, the type checker introduces artifical identifiers which are not
- // present in the source. Once it doesn't do that anymore, enable the checks below.
- /*
- for x := range idents {
- t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
- }
- */
-}
diff --git a/src/pkg/go/types/scope.go b/src/pkg/go/types/scope.go
deleted file mode 100644
index 463ee40c5..000000000
--- a/src/pkg/go/types/scope.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package types
-
-import (
- "bytes"
- "fmt"
-)
-
-// A Scope maintains the set of named language entities declared
-// in the scope and a link to the immediately surrounding (outer)
-// scope.
-//
-type Scope struct {
- Outer *Scope
- Entries []Object // scope entries in insertion order
- large map[string]Object // for fast lookup - only used for larger scopes
-}
-
-// Lookup returns the object with the given name if it is
-// found in scope s, otherwise it returns nil. Outer scopes
-// are ignored.
-//
-func (s *Scope) Lookup(name string) Object {
- if s.large != nil {
- return s.large[name]
- }
- for _, obj := range s.Entries {
- if obj.GetName() == name {
- return obj
- }
- }
- return nil
-}
-
-// Insert attempts to insert an object obj into scope s.
-// If s already contains an object with the same name,
-// Insert leaves s unchanged and returns that object.
-// Otherwise it inserts obj and returns nil.
-//
-func (s *Scope) Insert(obj Object) Object {
- name := obj.GetName()
- if alt := s.Lookup(name); alt != nil {
- return alt
- }
- s.Entries = append(s.Entries, obj)
-
- // If the scope size reaches a threshold, use a map for faster lookups.
- const threshold = 20
- if len(s.Entries) > threshold {
- if s.large == nil {
- m := make(map[string]Object, len(s.Entries))
- for _, obj := range s.Entries {
- m[obj.GetName()] = obj
- }
- s.large = m
- }
- s.large[name] = obj
- }
-
- return nil
-}
-
-// Debugging support
-func (s *Scope) String() string {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "scope %p {", s)
- if s != nil && len(s.Entries) > 0 {
- fmt.Fprintln(&buf)
- for _, obj := range s.Entries {
- fmt.Fprintf(&buf, "\t%s\t%T\n", obj.GetName(), obj)
- }
- }
- fmt.Fprintf(&buf, "}\n")
- return buf.String()
-}
diff --git a/src/pkg/go/types/sizes.go b/src/pkg/go/types/sizes.go
deleted file mode 100644
index ef6499ba4..000000000
--- a/src/pkg/go/types/sizes.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file implements support for (unsafe) Alignof, Offsetof, and Sizeof.
-
-package types
-
-func (ctxt *Context) alignof(typ Type) int64 {
- if f := ctxt.Alignof; f != nil {
- if a := f(typ); a >= 1 {
- return a
- }
- panic("Context.Alignof returned an alignment < 1")
- }
- return DefaultAlignof(typ)
-}
-
-func (ctxt *Context) offsetsof(s *Struct) []int64 {
- offsets := s.offsets
- if offsets == nil {
- // compute offsets on demand
- if f := ctxt.Offsetsof; f != nil {
- offsets = f(s.Fields)
- // sanity checks
- if len(offsets) != len(s.Fields) {
- panic("Context.Offsetsof returned the wrong number of offsets")
- }
- for _, o := range offsets {
- if o < 0 {
- panic("Context.Offsetsof returned an offset < 0")
- }
- }
- } else {
- offsets = DefaultOffsetsof(s.Fields)
- }
- s.offsets = offsets
- }
- return offsets
-}
-
-// offsetof returns the offset of the field specified via
-// the index sequence relative to typ. It returns a value
-// < 0 if the field is in an embedded pointer type.
-func (ctxt *Context) offsetof(typ Type, index []int) int64 {
- var o int64
- for _, i := range index {
- s, _ := underlying(typ).(*Struct)
- if s == nil {
- return -1
- }
- o += ctxt.offsetsof(s)[i]
- typ = s.Fields[i].Type
- }
- return o
-}
-
-func (ctxt *Context) sizeof(typ Type) int64 {
- if f := ctxt.Sizeof; f != nil {
- if s := f(typ); s >= 0 {
- return s
- }
- panic("Context.Sizeof returned a size < 0")
- }
- return DefaultSizeof(typ)
-}
-
-// DefaultMaxAlign is the default maximum alignment, in bytes,
-// used by DefaultAlignof.
-const DefaultMaxAlign = 8
-
-// DefaultAlignof implements the default alignment computation
-// for unsafe.Alignof. It is used if Context.Alignof == nil.
-func DefaultAlignof(typ Type) int64 {
- // For arrays and structs, alignment is defined in terms
- // of alignment of the elements and fields, respectively.
- switch t := underlying(typ).(type) {
- case *Array:
- // spec: "For a variable x of array type: unsafe.Alignof(x)
- // is the same as unsafe.Alignof(x[0]), but at least 1."
- return DefaultAlignof(t.Elt)
- case *Struct:
- // spec: "For a variable x of struct type: unsafe.Alignof(x)
- // is the largest of the values unsafe.Alignof(x.f) for each
- // field f of x, but at least 1."
- max := int64(1)
- for _, f := range t.Fields {
- if a := DefaultAlignof(f.Type); a > max {
- max = a
- }
- }
- return max
- }
- a := DefaultSizeof(typ) // may be 0
- // spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
- if a < 1 {
- return 1
- }
- if a > DefaultMaxAlign {
- return DefaultMaxAlign
- }
- return a
-}
-
-// align returns the smallest y >= x such that y % a == 0.
-func align(x, a int64) int64 {
- y := x + a - 1
- return y - y%a
-}
-
-// DefaultOffsetsof implements the default field offset computation
-// for unsafe.Offsetof. It is used if Context.Offsetsof == nil.
-func DefaultOffsetsof(fields []*Field) []int64 {
- offsets := make([]int64, len(fields))
- var o int64
- for i, f := range fields {
- a := DefaultAlignof(f.Type)
- o = align(o, a)
- offsets[i] = o
- o += DefaultSizeof(f.Type)
- }
- return offsets
-}
-
-// DefaultPtrSize is the default size of ints, uint, and pointers, in bytes,
-// used by DefaultSizeof.
-const DefaultPtrSize = 8
-
-// DefaultSizeof implements the default size computation
-// for unsafe.Sizeof. It is used if Context.Sizeof == nil.
-func DefaultSizeof(typ Type) int64 {
- switch t := underlying(typ).(type) {
- case *Basic:
- if s := t.size; s > 0 {
- return s
- }
- if t.Kind == String {
- return DefaultPtrSize * 2
- }
- case *Array:
- a := DefaultAlignof(t.Elt)
- s := DefaultSizeof(t.Elt)
- return align(s, a) * t.Len // may be 0
- case *Slice:
- return DefaultPtrSize * 3
- case *Struct:
- n := len(t.Fields)
- if n == 0 {
- return 0
- }
- offsets := t.offsets
- if t.offsets == nil {
- // compute offsets on demand
- offsets = DefaultOffsetsof(t.Fields)
- t.offsets = offsets
- }
- return offsets[n-1] + DefaultSizeof(t.Fields[n-1].Type)
- case *Signature:
- return DefaultPtrSize * 2
- }
- return DefaultPtrSize // catch-all
-}
diff --git a/src/pkg/go/types/stmt.go b/src/pkg/go/types/stmt.go
deleted file mode 100644
index 53c46a167..000000000
--- a/src/pkg/go/types/stmt.go
+++ /dev/null
@@ -1,743 +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.
-
-// This file implements typechecking of statements.
-
-package types
-
-import (
- "go/ast"
- "go/token"
-)
-
-// assigment reports whether x can be assigned to a variable of type 'to',
-// if necessary by attempting to convert untyped values to the appropriate
-// type. If x.mode == invalid upon return, then assignment has already
-// issued an error message and the caller doesn't have to report another.
-// TODO(gri) This latter behavior is for historic reasons and complicates
-// callers. Needs to be cleaned up.
-func (check *checker) assignment(x *operand, to Type) bool {
- if x.mode == invalid {
- return false
- }
-
- if t, ok := x.typ.(*Result); ok {
- // TODO(gri) elsewhere we use "assignment count mismatch" (consolidate)
- check.errorf(x.pos(), "%d-valued expression %s used as single value", len(t.Values), x)
- x.mode = invalid
- return false
- }
-
- check.convertUntyped(x, to)
-
- return x.mode != invalid && x.isAssignable(check.ctxt, to)
-}
-
-// assign1to1 typechecks a single assignment of the form lhs = rhs (if rhs != nil),
-// or lhs = x (if rhs == nil). 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. If lhs has a
-// type it is used as a hint when evaluating rhs, if present.
-//
-func (check *checker) assign1to1(lhs, rhs ast.Expr, x *operand, decl bool, iota int) {
- ident, _ := lhs.(*ast.Ident)
- if x == nil {
- assert(rhs != nil)
- x = new(operand)
- }
-
- if ident != nil && ident.Name == "_" {
- // anything can be assigned to a blank identifier - check rhs only, if present
- if rhs != nil {
- check.expr(x, rhs, nil, iota)
- }
- return
- }
-
- if !decl {
- // regular assignment - start with lhs to obtain a type hint
- // TODO(gri) clean this up - we don't need type hints anymore
- var z operand
- check.expr(&z, lhs, nil, -1)
- if z.mode == invalid {
- z.typ = nil // so we can proceed with rhs
- }
-
- if rhs != nil {
- check.expr(x, rhs, z.typ, -1)
- if x.mode == invalid {
- return
- }
- }
-
- if x.mode == invalid || z.mode == invalid {
- return
- }
-
- if !check.assignment(x, z.typ) {
- if x.mode != invalid {
- check.errorf(x.pos(), "cannot assign %s to %s", x, &z)
- }
- return
- }
- if z.mode == constant {
- check.errorf(x.pos(), "cannot assign %s to %s", x, &z)
- }
- return
- }
-
- // declaration - lhs must be an identifier
- if ident == nil {
- check.errorf(lhs.Pos(), "cannot declare %s", lhs)
- return
- }
-
- // lhs may or may not be typed yet
- obj := check.lookup(ident)
- var typ Type
- if t := obj.GetType(); t != nil {
- typ = t
- }
-
- if rhs != nil {
- check.expr(x, rhs, typ, iota)
- // continue even if x.mode == invalid
- }
-
- if typ == nil {
- // determine lhs type from rhs expression;
- // for variables, convert untyped types to
- // default types
- typ = Typ[Invalid]
- if x.mode != invalid {
- typ = x.typ
- if _, ok := obj.(*Var); ok && isUntyped(typ) {
- if x.isNil() {
- check.errorf(x.pos(), "use of untyped nil")
- x.mode = invalid
- } else {
- typ = defaultType(typ)
- }
- }
- }
- switch obj := obj.(type) {
- case *Const:
- obj.Type = typ
- case *Var:
- obj.Type = typ
- default:
- unreachable()
- }
- }
-
- if x.mode != invalid {
- if !check.assignment(x, typ) {
- if x.mode != invalid {
- switch obj.(type) {
- case *Const:
- check.errorf(x.pos(), "cannot assign %s to variable of type %s", x, typ)
- case *Var:
- check.errorf(x.pos(), "cannot initialize constant of type %s with %s", typ, x)
- default:
- unreachable()
- }
- x.mode = invalid
- }
- }
- }
-
- // for constants, set their value
- if obj, ok := obj.(*Const); ok {
- assert(obj.Val == nil)
- if x.mode != invalid {
- if x.mode == constant {
- if isConstType(x.typ) {
- obj.Val = x.val
- } else {
- check.errorf(x.pos(), "%s has invalid constant type", x)
- }
- } else {
- check.errorf(x.pos(), "%s is not constant", x)
- }
- }
- if obj.Val == nil {
- // set the constant to its type's zero value to reduce spurious errors
- switch typ := underlying(obj.Type); {
- case typ == Typ[Invalid]:
- // ignore
- case isBoolean(typ):
- obj.Val = false
- case isNumeric(typ):
- obj.Val = int64(0)
- case isString(typ):
- obj.Val = ""
- case hasNil(typ):
- obj.Val = nilConst
- default:
- // in all other cases just prevent use of the constant
- // TODO(gri) re-evaluate this code
- obj.Val = nilConst
- }
- }
- }
-}
-
-// 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/variable declaration.
-// Precondition: len(lhs) > 0 .
-//
-func (check *checker) assignNtoM(lhs, rhs []ast.Expr, decl bool, iota int) {
- assert(len(lhs) > 0)
-
- if len(lhs) == len(rhs) {
- for i, e := range rhs {
- check.assign1to1(lhs[i], e, nil, decl, iota)
- }
- return
- }
-
- if len(rhs) == 1 {
- // len(lhs) > 1, 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 {
- // If decl is set, this leaves the lhs identifiers
- // untyped. We catch this when looking up the respective
- // object.
- return
- }
-
- if t, ok := x.typ.(*Result); ok && len(lhs) == len(t.Values) {
- // function result
- x.mode = value
- for i, obj := range t.Values {
- x.expr = nil // TODO(gri) should do better here
- x.typ = obj.Type
- check.assign1to1(lhs[i], nil, &x, decl, iota)
- }
- return
- }
-
- if x.mode == valueok && len(lhs) == 2 {
- // comma-ok expression
- x.mode = value
- check.assign1to1(lhs[0], nil, &x, decl, iota)
-
- x.mode = value
- x.typ = Typ[UntypedBool]
- check.assign1to1(lhs[1], nil, &x, decl, iota)
- 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 name, ok := e.(*ast.Ident); ok {
- switch obj := check.lookup(name).(type) {
- case *Const:
- obj.Type = Typ[Invalid]
- case *Var:
- obj.Type = Typ[Invalid]
- default:
- unreachable()
- }
- }
- }
- }
-}
-
-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)
- }
-}
-
-func (check *checker) call(call *ast.CallExpr) {
- var x operand
- check.rawExpr(&x, call, nil, -1, false) // don't check if value is used
- // TODO(gri) If a builtin is called, the builtin must be valid in statement context.
-}
-
-func (check *checker) multipleDefaults(list []ast.Stmt) {
- var first ast.Stmt
- for _, s := range list {
- var d ast.Stmt
- switch c := s.(type) {
- case *ast.CaseClause:
- if len(c.List) == 0 {
- d = s
- }
- case *ast.CommClause:
- if c.Comm == nil {
- d = s
- }
- default:
- check.invalidAST(s.Pos(), "case/communication clause expected")
- }
- if d != nil {
- if first != nil {
- check.errorf(d.Pos(), "multiple defaults (first at %s)", first.Pos())
- } else {
- first = d
- }
- }
- }
-}
-
-// stmt typechecks statement s.
-func (check *checker) stmt(s ast.Stmt) {
- switch s := s.(type) {
- case *ast.BadStmt, *ast.EmptyStmt:
- // ignore
-
- case *ast.DeclStmt:
- d, _ := s.Decl.(*ast.GenDecl)
- if d == nil || (d.Tok != token.CONST && d.Tok != token.TYPE && d.Tok != token.VAR) {
- check.invalidAST(token.NoPos, "const, type, or var declaration expected")
- return
- }
- if d.Tok == token.CONST {
- check.assocInitvals(d)
- }
- check.decl(d)
-
- case *ast.LabeledStmt:
- // TODO(gri) anything to do with label itself?
- check.stmt(s.Stmt)
-
- 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
- // (Caution: This evaluates e.Fun twice, once here and once
- // below as part of s.X. This has consequences for
- // check.register. Perhaps this can be avoided.)
- 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.rawExpr(&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 || !check.assignment(&x, tch.Elt) {
- if x.mode != invalid {
- check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
- }
- }
-
- case *ast.IncDecStmt:
- var op token.Token
- switch s.Tok {
- case token.INC:
- op = token.ADD
- case token.DEC:
- op = token.SUB
- default:
- check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
- return
- }
- var x operand
- Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
- check.binary(&x, s.X, Y, op, -1)
- if x.mode == invalid {
- return
- }
- check.assign1to1(s.X, nil, &x, false, -1)
-
- 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
- default:
- check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
- return
- }
- var x operand
- check.binary(&x, s.Lhs[0], s.Rhs[0], op, -1)
- if x.mode == invalid {
- return
- }
- check.assign1to1(s.Lhs[0], nil, &x, false, -1)
- }
-
- case *ast.GoStmt:
- check.call(s.Call)
-
- case *ast.DeferStmt:
- check.call(s.Call)
-
- case *ast.ReturnStmt:
- sig := check.funcsig
- if n := len(sig.Results); n > 0 {
- // TODO(gri) should not have to compute lhs, named every single time - clean this up
- lhs := make([]ast.Expr, n)
- named := false // if set, function has named results
- for i, res := range sig.Results {
- if len(res.Name) > 0 {
- // a blank (_) result parameter is a named result
- named = true
- }
- name := ast.NewIdent(res.Name)
- name.NamePos = s.Pos()
- check.register(name, &Var{Name: res.Name, Type: res.Type}) // Pkg == nil
- lhs[i] = name
- }
- if len(s.Results) > 0 || !named {
- // TODO(gri) assignNtoM should perhaps not require len(lhs) > 0
- check.assignNtoM(lhs, s.Results, false, -1)
- }
- } else if len(s.Results) > 0 {
- check.errorf(s.Pos(), "no result values expected")
- }
-
- case *ast.BranchStmt:
- // TODO(gri) implement this
-
- 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 x.mode != invalid && !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
- tag := s.Tag
- if tag == nil {
- // use fake true tag value and position it at the opening { of the switch
- ident := &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
- check.register(ident, Universe.Lookup("true"))
- tag = ident
- }
- check.expr(&x, tag, nil, -1)
-
- check.multipleDefaults(s.Body.List)
- seen := make(map[interface{}]token.Pos)
- for _, s := range s.Body.List {
- clause, _ := s.(*ast.CaseClause)
- if clause == nil {
- continue // error reported before
- }
- if x.mode != invalid {
- for _, expr := range clause.List {
- x := x // copy of x (don't modify original)
- var y operand
- check.expr(&y, expr, nil, -1)
- if y.mode == invalid {
- continue // error reported before
- }
- // If we have a constant case value, it must appear only
- // once in the switch statement. Determine if there is a
- // duplicate entry, but only report an error if there are
- // no other errors.
- var dupl token.Pos
- var yy operand
- if y.mode == constant {
- // TODO(gri) This code doesn't work correctly for
- // large integer, floating point, or
- // complex values - the respective struct
- // comparisons are shallow. Need to use a
- // hash function to index the map.
- dupl = seen[y.val]
- seen[y.val] = y.pos()
- yy = y // remember y
- }
- // TODO(gri) The convertUntyped call pair below appears in other places. Factor!
- // Order matters: By comparing y against x, error positions are at the case values.
- check.convertUntyped(&y, x.typ)
- if y.mode == invalid {
- continue // error reported before
- }
- check.convertUntyped(&x, y.typ)
- if x.mode == invalid {
- continue // error reported before
- }
- check.comparison(&y, &x, token.EQL)
- if y.mode != invalid && dupl.IsValid() {
- check.errorf(yy.pos(), "%s is duplicate case (previous at %s)",
- &yy, check.fset.Position(dupl))
- }
- }
- }
- check.stmtList(clause.Body)
- }
-
- case *ast.TypeSwitchStmt:
- check.optionalStmt(s.Init)
-
- // A type switch guard must be of the form:
- //
- // TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
- //
- // The parser is checking syntactic correctness;
- // remaining syntactic errors are considered AST errors here.
- // TODO(gri) better factoring of error handling (invalid ASTs)
- //
- var lhs *Var // lhs variable or nil
- var rhs ast.Expr
- switch guard := s.Assign.(type) {
- case *ast.ExprStmt:
- rhs = guard.X
- case *ast.AssignStmt:
- if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
- check.invalidAST(s.Pos(), "incorrect form of type switch guard")
- return
- }
- ident, _ := guard.Lhs[0].(*ast.Ident)
- if ident == nil {
- check.invalidAST(s.Pos(), "incorrect form of type switch guard")
- return
- }
- lhs = check.lookup(ident).(*Var)
- rhs = guard.Rhs[0]
- default:
- check.invalidAST(s.Pos(), "incorrect form of type switch guard")
- return
- }
-
- // rhs must be of the form: expr.(type) and expr must be an interface
- expr, _ := rhs.(*ast.TypeAssertExpr)
- if expr == nil || expr.Type != nil {
- check.invalidAST(s.Pos(), "incorrect form of type switch guard")
- return
- }
- var x operand
- check.expr(&x, expr.X, nil, -1)
- if x.mode == invalid {
- return
- }
- var T *Interface
- if T, _ = underlying(x.typ).(*Interface); T == nil {
- check.errorf(x.pos(), "%s is not an interface", &x)
- return
- }
-
- check.multipleDefaults(s.Body.List)
- for _, s := range s.Body.List {
- clause, _ := s.(*ast.CaseClause)
- if clause == nil {
- continue // error reported before
- }
- // Check each type in this type switch case.
- var typ Type
- for _, expr := range clause.List {
- typ = check.typOrNil(expr, false)
- if typ != nil && typ != Typ[Invalid] {
- if method, wrongType := missingMethod(typ, T); method != nil {
- var msg string
- if wrongType {
- msg = "%s cannot have dynamic type %s (wrong type for method %s)"
- } else {
- msg = "%s cannot have dynamic type %s (missing method %s)"
- }
- check.errorf(expr.Pos(), msg, &x, typ, method.Name)
- // ok to continue
- }
- }
- }
- // If lhs exists, set its type for each clause.
- if lhs != nil {
- // In clauses with a case listing exactly one type, the variable has that type;
- // otherwise, the variable has the type of the expression in the TypeSwitchGuard.
- if len(clause.List) != 1 || typ == nil {
- typ = x.typ
- }
- lhs.Type = typ
- }
- check.stmtList(clause.Body)
- }
-
- // There is only one object (lhs) associated with a lhs identifier, but that object
- // assumes different types for different clauses. Set it back to the type of the
- // TypeSwitchGuard expression so that that variable always has a valid type.
- if lhs != nil {
- lhs.Type = x.typ
- }
-
- case *ast.SelectStmt:
- check.multipleDefaults(s.Body.List)
- for _, s := range s.Body.List {
- clause, _ := s.(*ast.CommClause)
- if clause == nil {
- continue // error reported before
- }
- check.optionalStmt(clause.Comm) // TODO(gri) check correctness of c.Comm (must be Send/RecvStmt)
- check.stmtList(clause.Body)
- }
-
- case *ast.ForStmt:
- check.optionalStmt(s.Init)
- if s.Cond != nil {
- var x operand
- check.expr(&x, s.Cond, nil, -1)
- if x.mode != invalid && !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:
- // check expression to iterate over
- decl := s.Tok == token.DEFINE
- var x operand
- check.expr(&x, s.X, nil, -1)
- if x.mode == invalid {
- // if we don't have a declaration, we can still check the loop's body
- if !decl {
- check.stmt(s.Body)
- }
- return
- }
-
- // determine key/value types
- var key, val Type
- switch typ := underlying(x.typ).(type) {
- case *Basic:
- if isString(typ) {
- key = Typ[UntypedInt]
- val = Typ[UntypedRune]
- }
- case *Array:
- key = Typ[UntypedInt]
- val = typ.Elt
- case *Slice:
- key = Typ[UntypedInt]
- val = typ.Elt
- case *Pointer:
- if typ, _ := underlying(typ.Base).(*Array); typ != nil {
- key = Typ[UntypedInt]
- val = typ.Elt
- }
- case *Map:
- key = typ.Key
- val = typ.Elt
- case *Chan:
- key = typ.Elt
- if typ.Dir&ast.RECV == 0 {
- check.errorf(x.pos(), "cannot range over send-only channel %s", &x)
- // ok to continue
- }
- if s.Value != nil {
- check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x)
- // ok to continue
- }
- }
-
- if key == nil {
- check.errorf(x.pos(), "cannot range over %s", &x)
- // if we don't have a declaration, we can still check the loop's body
- if !decl {
- check.stmt(s.Body)
- }
- return
- }
-
- // check assignment to/declaration of iteration variables
- // TODO(gri) The error messages/positions are not great here,
- // they refer to the expression in the range clause.
- // Should give better messages w/o too much code
- // duplication (assignment checking).
- x.mode = value
- if s.Key != nil {
- x.typ = key
- x.expr = s.Key
- check.assign1to1(s.Key, nil, &x, decl, -1)
- } else {
- check.invalidAST(s.Pos(), "range clause requires index iteration variable")
- // ok to continue
- }
- if s.Value != nil {
- x.typ = val
- x.expr = s.Value
- check.assign1to1(s.Value, nil, &x, decl, -1)
- }
-
- check.stmt(s.Body)
-
- default:
- check.errorf(s.Pos(), "invalid statement")
- }
-}
diff --git a/src/pkg/go/types/testdata/builtins.src b/src/pkg/go/types/testdata/builtins.src
deleted file mode 100644
index c08c442ce..000000000
--- a/src/pkg/go/types/testdata/builtins.src
+++ /dev/null
@@ -1,401 +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.
-
-// 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)
-
- // issue 4744
- type T struct{ a [10]int }
- const _ = cap(((*T)(nil)).a)
-}
-
-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() {
- var i32 int32
- var f32 float32
- var f64 float64
- var c64 complex64
- _ = complex /* ERROR "argument" */ ()
- _ = complex /* ERROR "argument" */ (1)
- _ = complex(true /* ERROR "invalid argument" */ , 0)
- _ = complex(i32 /* ERROR "invalid argument" */ , 0)
- _ = complex("foo" /* ERROR "invalid argument" */ , 0)
- _ = complex(c64 /* ERROR "invalid argument" */ , 0)
- _ = complex(0, true /* ERROR "invalid argument" */ )
- _ = complex(0, i32 /* ERROR "invalid argument" */ )
- _ = complex(0, "foo" /* ERROR "invalid argument" */ )
- _ = complex(0, c64 /* ERROR "invalid argument" */ )
- _ = complex(f32, f32)
- _ = complex(f32, 1)
- _ = complex(f32, 1.0)
- _ = complex(f32, 'a')
- _ = complex(f64, f64)
- _ = complex(f64, 1)
- _ = complex(f64, 1.0)
- _ = complex(f64, 'a')
- _ = complex(f32 /* ERROR "mismatched types" */, f64)
- _ = complex(f64 /* ERROR "mismatched types" */, f32)
- _ = complex(1, 1)
- _ = complex(1, 1.1)
- _ = complex(1, 'a')
- complex /* ERROR "not used" */ (1, 2)
-}
-
-func _copy() {
- copy /* ERROR "not enough arguments" */ ()
- copy /* ERROR "not enough arguments" */ ("foo")
- copy([ /* ERROR "copy expects slice arguments" */ ...]int{}, []int{})
- copy([ /* ERROR "copy expects slice arguments" */ ]int{}, [...]int{})
- copy([ /* ERROR "different element types" */ ]int8{}, "foo")
-
- // spec examples
- var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
- var s = make([]int, 6)
- var b = make([]byte, 5)
- n1 := copy(s, a[0:]) // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
- n2 := copy(s, s[2:]) // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
- n3 := copy(b, "Hello, World!") // n3 == 5, b == []byte("Hello")
-}
-
-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
- _ = imag /* ERROR "argument" */ ()
- _ = imag /* ERROR "argument" */ (1, 2)
- _ = imag(10 /* ERROR "must be a complex number" */)
- _ = imag(2.7182818 /* ERROR "must be a complex number" */)
- _ = 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
- _ = len /* ERROR "argument" */ ()
- _ = len /* ERROR "argument" */ (1, 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)
- _ = 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)])
- _ = nn // TODO(gri) remove this once unused constants get type-checked
-
- // issue 4744
- type T struct{ a [10]int }
- const _ = len(((*T)(nil)).a)
-}
-
-func _make() {
- n := 0
-
- _ = make /* ERROR "argument" */ ()
- _ = make(1 /* ERROR "not a type" */)
- _ = make(int /* ERROR "cannot make" */)
-
- // slices
- _ = make/* ERROR "arguments" */ ([]int)
- _ = make/* ERROR "arguments" */ ([]int, 2, 3, 4)
- _ = make([]int, int /* ERROR "not an expression" */)
- _ = make([]int, 10, float32 /* ERROR "not an expression" */)
- _ = make([]int, "foo" /* ERROR "must be an integer" */)
- _ = make([]int, 10, 2.3 /* ERROR "must be an integer" */)
- _ = make([]int, 5, 10.0)
- _ = make([]int, 0i)
- _ = make([]int, - /* ERROR "must not be negative" */ 1, 10)
- _ = make([]int, 0, - /* ERROR "must not be negative" */ 1)
- _ = make([]int, - /* ERROR "must not be negative" */ 1, - /* ERROR "must not be negative" */ 1)
- _ = make([]int, 1<<100, 1<<100) // run-time panic
- _ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100 + 1, 1<<100)
- _ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100, 12345)
-
- // maps
- _ = make /* ERROR "arguments" */ (map[int]string, 10, 20)
- _ = make(map[int]float32, int /* ERROR "not an expression" */)
- _ = make(map[int]float32, "foo" /* ERROR "must be an integer" */)
- _ = make(map[int]float32, 10)
- _ = make(map[int]float32, n)
- _ = make(map[int]float32, int64(n))
-
- // channels
- _ = make /* ERROR "arguments" */ (chan int, 10, 20)
- _ = make(chan int, int /* ERROR "not an expression" */)
- _ = make(chan<- int, "foo" /* ERROR "must be an integer" */)
- _ = make(<-chan float64, 10)
- _ = make(chan chan int, n)
- _ = make(chan string, int64(n))
-
- make /* ERROR "not used" */ ([]int, 10)
-}
-
-func _new() {
- _ = new /* ERROR "argument" */ ()
- _ = new /* ERROR "argument" */ (1, 2)
- _ = new("foo" /* ERROR "not a type" */)
- p := new(float64)
- _ = new(struct{ x, y int })
- q := new(*float64)
- _ = *p == **q
- new /* ERROR "not used" */ (int)
-}
-
-func _panic() {
- panic /* ERROR "arguments" */ ()
- panic /* ERROR "arguments" */ (1, 2)
- panic(0)
- panic("foo")
- panic(false)
-}
-
-func _print() {
- print()
- print(1)
- print(1, 2)
- print("foo")
- print(2.718281828)
- print(false)
-}
-
-func _println() {
- println()
- println(1)
- println(1, 2)
- println("foo")
- println(2.718281828)
- println(false)
-}
-
-func _real() {
- var f32 float32
- var f64 float64
- var c64 complex64
- var c128 complex128
- _ = real /* ERROR "argument" */ ()
- _ = real /* ERROR "argument" */ (1, 2)
- _ = real(10 /* ERROR "must be a complex number" */)
- _ = real(2.7182818 /* ERROR "must be a complex number" */)
- _ = 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() {
- _ = recover()
- _ = recover /* ERROR "argument" */ (10)
- recover()
-}
-
-// assuming types.DefaultPtrSize == 8
-type S0 struct{ // offset
- a bool // 0
- b rune // 4
- c *int // 8
- d bool // 16
- e complex128 // 24
-} // 40
-
-type S1 struct{ // offset
- x float32 // 0
- y string // 8
- z *S1 // 24
- S0 // 32
-} // 72
-
-type S2 struct{ // offset
- *S1 // 0
-} // 8
-
-func _Alignof() {
- var x int
- _ = unsafe /* ERROR "argument" */ .Alignof()
- _ = unsafe /* ERROR "argument" */ .Alignof(1, 2)
- _ = unsafe.Alignof(int /* ERROR "not an expression" */)
- _ = unsafe.Alignof(42)
- _ = unsafe.Alignof(new(struct{}))
- unsafe /* ERROR "not used" */ .Alignof(x)
-
- var y S0
- assert(unsafe.Alignof(y.a) == 1)
- assert(unsafe.Alignof(y.b) == 4)
- assert(unsafe.Alignof(y.c) == 8)
- assert(unsafe.Alignof(y.d) == 1)
- assert(unsafe.Alignof(y.e) == 8)
-}
-
-func _Offsetof() {
- var x struct{ f int }
- _ = unsafe /* ERROR "argument" */ .Offsetof()
- _ = unsafe /* ERROR "argument" */ .Offsetof(1, 2)
- _ = unsafe.Offsetof(int /* ERROR "not an expression" */)
- _ = unsafe.Offsetof(x /* ERROR "not a selector" */)
- _ = unsafe.Offsetof(x.f)
- _ = unsafe.Offsetof((x.f))
- _ = unsafe.Offsetof((((((((x))).f)))))
- unsafe /* ERROR "not used" */ .Offsetof(x.f)
-
- var y0 S0
- assert(unsafe.Offsetof(y0.a) == 0)
- assert(unsafe.Offsetof(y0.b) == 4)
- assert(unsafe.Offsetof(y0.c) == 8)
- assert(unsafe.Offsetof(y0.d) == 16)
- assert(unsafe.Offsetof(y0.e) == 24)
-
- var y1 S1
- assert(unsafe.Offsetof(y1.x) == 0)
- assert(unsafe.Offsetof(y1.y) == 8)
- assert(unsafe.Offsetof(y1.z) == 24)
- assert(unsafe.Offsetof(y1.S0) == 32)
-
- assert(unsafe.Offsetof(y1.S0.a) == 0) // relative to S0
- assert(unsafe.Offsetof(y1.a) == 32) // relative to S1
- assert(unsafe.Offsetof(y1.b) == 36) // relative to S1
- assert(unsafe.Offsetof(y1.c) == 40) // relative to S1
- assert(unsafe.Offsetof(y1.d) == 48) // relative to S1
- assert(unsafe.Offsetof(y1.e) == 56) // relative to S1
-
- var y2 S2
- assert(unsafe.Offsetof(y2.S1) == 0)
- _ = unsafe.Offsetof(y2 /* ERROR "embedded via pointer" */ .x)
-}
-
-func _Sizeof() {
- var x int
- _ = unsafe /* ERROR "argument" */ .Sizeof()
- _ = unsafe /* ERROR "argument" */ .Sizeof(1, 2)
- _ = unsafe.Sizeof(int /* ERROR "not an expression" */)
- _ = unsafe.Sizeof(42)
- _ = 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)
-
- var y0 S0
- assert(unsafe.Sizeof(y0.a) == 1)
- assert(unsafe.Sizeof(y0.b) == 4)
- assert(unsafe.Sizeof(y0.c) == 8)
- assert(unsafe.Sizeof(y0.d) == 1)
- assert(unsafe.Sizeof(y0.e) == 16)
- assert(unsafe.Sizeof(y0) == 40)
-
- var y1 S1
- assert(unsafe.Sizeof(y1) == 72)
-
- var y2 S2
- assert(unsafe.Sizeof(y2) == 8)
-}
-
-// 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
- // _ = trace /* ERROR "no value" */ ()
- // _ = trace(1)
- // _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar")
-}
diff --git a/src/pkg/go/types/testdata/const0.src b/src/pkg/go/types/testdata/const0.src
deleted file mode 100644
index a2ca344c7..000000000
--- a/src/pkg/go/types/testdata/const0.src
+++ /dev/null
@@ -1,215 +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.
-
-// 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)
-)
-
-// special cases
-const (
- _n0 = nil /* ERROR "invalid constant type" */
- _n1 = [ /* ERROR "not constant" */ ]int{}
-) \ No newline at end of file
diff --git a/src/pkg/go/types/testdata/conversions.src b/src/pkg/go/types/testdata/conversions.src
deleted file mode 100644
index 1b1518366..000000000
--- a/src/pkg/go/types/testdata/conversions.src
+++ /dev/null
@@ -1,18 +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.
-
-// 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/src/pkg/go/types/testdata/decls0.src b/src/pkg/go/types/testdata/decls0.src
deleted file mode 100644
index f0115bd9d..000000000
--- a/src/pkg/go/types/testdata/decls0.src
+++ /dev/null
@@ -1,187 +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.
-
-// type declarations
-
-package decls0
-
-import (
- "unsafe"
- // we can have multiple blank imports (was bug)
- _ "math"
- _ "net/rpc"
- // reflect defines a type "flag" which shows up in the gc export data
- "reflect"
- . "reflect"
-)
-
-// reflect.flag must not be visible in this package
-type flag int
-type _ reflect /* ERROR "cannot refer to unexported" */ .flag
-
-// dot-imported exported objects may conflict with local objects
-type Value /* ERROR "redeclared in this block by dot-import" */ struct{}
-
-const pi = 3.1415
-
-type (
- N undeclared /* ERROR "undeclared" */
- 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" */ }
-)
-
-
-// invalid array types
-type (
- iA0 [... /* ERROR "invalid use of '...'" */ ]byte
- iA1 [1 /* ERROR "invalid array length" */ <<100]int
- iA2 [- /* ERROR "invalid array length" */ 1]complex128
- iA3 ["foo" /* ERROR "invalid array length" */ ]string
-)
-
-
-type (
- p1 pi /* ERROR "no single field or method foo" */ .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 { /* ERROR "multiple methods named m1" */
- 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 "not an 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/src/pkg/go/types/testdata/decls1.src b/src/pkg/go/types/testdata/decls1.src
deleted file mode 100644
index 2251f457f..000000000
--- a/src/pkg/go/types/testdata/decls1.src
+++ /dev/null
@@ -1,132 +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.
-
-// 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 _" */
-)
-
-// 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 "no 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" */
- t16 math /* ERROR "unexported" */ .xxx
- t17 math /* ERROR "not a type" */ .Pi
- t18 float64 = math.Pi * 10.0
- t19 int = t1 /* ERROR "cannot call" */ ()
- t20 int = f0 /* ERROR "no value" */ ()
-)
-
-// Various more complex expressions
-var (
- u1 = x /* ERROR "not an interface" */ .(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 + 9223372036854775807
- v8 = v6 + 9223372036854775808 /* ERROR "overflows" */
- v9 = i + 1 << 10
- v10 byte = 1024 /* ERROR "overflows" */
- v11 = xx/yy*yy - xx
- v12 = true && false
- v13 = nil /* ERROR "use of untyped nil" */
-)
-
-// 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() {}
-
-
-// Initialization functions
-func init() {}
-func /* ERROR "no arguments and no return values" */ init(int) {}
-func /* ERROR "no arguments and no return values" */ init() int { return 0 }
-func /* ERROR "no arguments and no return values" */ init(int) int {}
-func (T) init(int) int { return 0 }
diff --git a/src/pkg/go/types/testdata/decls2a.src b/src/pkg/go/types/testdata/decls2a.src
deleted file mode 100644
index 3867be737..000000000
--- a/src/pkg/go/types/testdata/decls2a.src
+++ /dev/null
@@ -1,67 +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.
-
-// 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() {}
-
-// TODO(gri) try to get rid of double error reporting here
-func (pi /* ERROR "not a type" */) m1() {}
-func (x pi /* ERROR "not a type" */) m2() {}
-func (x *pi /* ERROR "not a type" */ ) m3() {} // TODO(gri) not closing the last /* comment crashes the system
-
-// 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 /* ERROR "non-local type" */ ) m() {}
-func ([ /* ERROR "expected" */ ]int) m() {}
-func (time /* ERROR "expected" */ .Time) m() {}
-func (x interface /* ERROR "expected" */ {}) m() {}
diff --git a/src/pkg/go/types/testdata/decls2b.src b/src/pkg/go/types/testdata/decls2b.src
deleted file mode 100644
index c7f9ddf01..000000000
--- a/src/pkg/go/types/testdata/decls2b.src
+++ /dev/null
@@ -1,28 +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.
-
-// method declarations
-
-package decls2
-
-const pi = 3.1415
-
-func (T1) m /* ERROR "redeclared" */ () {}
-
-type T3 struct {
- f *T3
-}
-
-type T6 struct {
- x int
-}
-
-func (t *T6) m1() int {
- return t.x
-}
-
-func f() {
- var t *T6
- t.m1()
-} \ No newline at end of file
diff --git a/src/pkg/go/types/testdata/decls3.src b/src/pkg/go/types/testdata/decls3.src
deleted file mode 100644
index 6aa9f90e9..000000000
--- a/src/pkg/go/types/testdata/decls3.src
+++ /dev/null
@@ -1,253 +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.
-
-// embedded types
-
-package decls3
-
-// fields with the same name at the same level cancel each other out
-
-func _() {
- type (
- T1 struct { X int }
- T2 struct { X int }
- T3 struct { T1; T2 } // X is embedded twice at the same level via T1->X, T2->X
- )
-
- var t T3
- _ = t /* ERROR "no single field or method" */ .X
-}
-
-func _() {
- type (
- T1 struct { X int }
- T2 struct { T1 }
- T3 struct { T1 }
- T4 struct { T2; T3 } // X is embedded twice at the same level via T2->T1->X, T3->T1->X
- )
-
- var t T4
- _ = t /* ERROR "no single field or method" */ .X
-}
-
-func issue4355() {
- type (
- T1 struct {X int}
- T2 struct {T1}
- T3 struct {T2}
- T4 struct {T2}
- T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X
- )
-
- var t T5
- _ = t /* ERROR "no single field or method" */ .X
-}
-
-// Embedded fields can be predeclared types.
-
-func _() {
- type T0 struct{
- int
- float32
- f int
- }
- var x T0
- _ = x.int
- _ = x.float32
- _ = x.f
-
- type T1 struct{
- T0
- }
- var y T1
- _ = y.int
- _ = y.float32
- _ = y.f
-}
-
-// Borrowed from the FieldByName test cases in reflect/all_test.go.
-
-type D1 struct {
- d int
-}
-type D2 struct {
- d int
-}
-
-type S0 struct {
- A, B, C int
- D1
- D2
-}
-
-type S1 struct {
- B int
- S0
-}
-
-type S2 struct {
- A int
- *S1
-}
-
-type S1x struct {
- S1
-}
-
-type S1y struct {
- S1
-}
-
-type S3 struct {
- S1x
- S2
- D, E int
- *S1y
-}
-
-type S4 struct {
- *S4
- 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
-}
-
-func _() {
- _ = struct /* ERROR "no single field or method" */ {}{}.Foo
- _ = S0{}.A
- _ = S0 /* ERROR "no single field or method" */ {}.D
- _ = S1{}.A
- _ = S1{}.B
- _ = S1{}.S0
- _ = S1{}.C
- _ = S2{}.A
- _ = S2{}.S1
- _ = S2{}.B
- _ = S2{}.C
- _ = S2 /* ERROR "no single field or method" */ {}.D
- _ = S3 /* ERROR "no single field or method" */ {}.S1
- _ = S3{}.A
- _ = S3 /* ERROR "no single field or method" */ {}.B
- _ = S3{}.D
- _ = S3{}.E
- _ = S4{}.A
- _ = S4 /* ERROR "no single field or method" */ {}.B
- _ = S5 /* ERROR "no single field or method" */ {}.X
- _ = S5{}.Y
- _ = S10 /* ERROR "no single field or method" */ {}.X
- _ = S10{}.Y
-}
-
-// Borrowed from the FieldByName benchmark in reflect/all_test.go.
-
-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
-
-var _ = R0 /* ERROR "no single field or method" */ {}.X \ No newline at end of file
diff --git a/src/pkg/go/types/testdata/exports.go b/src/pkg/go/types/testdata/exports.go
deleted file mode 100644
index 8ee28b094..000000000
--- a/src/pkg/go/types/testdata/exports.go
+++ /dev/null
@@ -1,89 +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.
-
-// 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/src/pkg/go/types/testdata/expr0.src b/src/pkg/go/types/testdata/expr0.src
deleted file mode 100644
index 8d057f63c..000000000
--- a/src/pkg/go/types/testdata/expr0.src
+++ /dev/null
@@ -1,161 +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.
-
-// 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 "cannot receive" */
-
- // 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 "cannot receive" */
-
- // 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 "cannot receive" */
- u19 = ^uint(0)
-
- // 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 "cannot receive" */
-
- // 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 "cannot receive" */
-
- // 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 "cannot receive" */
-
- // 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 "cannot receive" */
-)
-
-// address of composite literals
-type T struct{x, y int}
-
-func f() T { return T{} }
-
-var (
- _ = &T{1, 2}
- _ = &[...]int{}
- _ = &[]int{}
- _ = &[]int{}
- _ = &map[string]T{}
- _ = &(T{1, 2})
- _ = &((((T{1, 2}))))
- _ = &f /* ERROR "cannot take address" */ ()
-)
-
-// recursive pointer types
-type P *P
-
-var (
- p1 P = new(P)
- p2 P = *p1
- p3 P = &p2
-)
-
diff --git a/src/pkg/go/types/testdata/expr1.src b/src/pkg/go/types/testdata/expr1.src
deleted file mode 100644
index 8ef0aed6d..000000000
--- a/src/pkg/go/types/testdata/expr1.src
+++ /dev/null
@@ -1,7 +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.
-
-// binary expressions
-
-package expr1
diff --git a/src/pkg/go/types/testdata/expr2.src b/src/pkg/go/types/testdata/expr2.src
deleted file mode 100644
index 674be4005..000000000
--- a/src/pkg/go/types/testdata/expr2.src
+++ /dev/null
@@ -1,23 +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.
-
-// comparisons
-
-package expr2
-
-func _bool() {
- const t = true == true
- const f = true == false
- _ = t /* ERROR "cannot compare" */ < f
- _ = 0 /* ERROR "cannot convert" */ == t
- var b bool
- var x, y float32
- b = x < y
- _ = struct{b bool}{x < y}
-}
-
-// corner cases
-var (
- v0 = nil /* ERROR "cannot compare" */ == nil
-) \ No newline at end of file
diff --git a/src/pkg/go/types/testdata/expr3.src b/src/pkg/go/types/testdata/expr3.src
deleted file mode 100644
index ff17f2eee..000000000
--- a/src/pkg/go/types/testdata/expr3.src
+++ /dev/null
@@ -1,463 +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.
-
-// various expressions
-
-package expr3
-
-func shifts1() {
- 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
- )
-}
-
-func shifts2() {
- // 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<<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
- )
-}
-
-func shifts3(a int16, b float32) {
- var (
- s uint = 11
- u = 1 /* ERROR "must be integer" */ <<s + 1.0
- v complex128 = 1 /* ERROR "must be integer" */ << s + 1.0 /* ERROR "must be integer" */ << s + 1
- )
- x := 1.0 /* ERROR "must be integer" */ <<s + 1
- shifts3(1.0 << s, 1 /* ERROR "must be integer" */ >> s)
- // TODO(gri) add more tests (systematically)
-}
-
-func shifts4() {
- // from src/pkg/compress/lzw/reader.go:90
- {
- var d struct {
- bits uint32
- width uint
- }
- _ = uint16(d.bits & (1<<d.width - 1))
- }
-
- // from src/pkg/debug/dwarf/buf.go:116
- {
- var ux uint64
- var bits uint
- x := int64(ux)
- if x&(1<<(bits-1)) != 0 {}
- }
-
- // from src/pkg/encoding/asn1/asn1.go:160
- {
- var bytes []byte
- if bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {}
- }
-
- // from src/pkg/math/big/rat.go:140
- {
- var exp int
- var mantissa uint64
- shift := uint64(-1022 - (exp - 1)) // [1..53)
- _ = mantissa & (1<<shift - 1)
- }
-
- // from src/pkg/net/interface.go:51
- {
- type Flags uint
- var f Flags
- var i int
- if f&(1<<uint(i)) != 0 {}
- }
-
- // from src/pkg/runtime/softfloat64.go:234
- {
- var gm uint64
- var shift uint
- _ = gm & (1<<shift - 1)
- }
-
- // from src/pkg/strconv/atof.go:326
- {
- var mant uint64
- var mantbits uint
- if mant == 2<<mantbits {}
- }
-
- // from src/pkg/syscall/route_bsd.go:82
- {
- var Addrs int32
- const rtaRtMask = 1
- var i uint
- if Addrs&rtaRtMask&(1<<i) == 0 {}
- }
-
- // from src/pkg/text/scanner/scanner.go:540
- {
- var s struct { Whitespace uint64 }
- var ch rune
- for s.Whitespace&(1<<uint(ch)) != 0 {}
- }
-}
-
-// 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[1 /* ERROR "stupid index" */ <<100]
- _ = a[10:]
- _ = a[:10]
- _ = a[10:10]
- _ = a[11 /* ERROR "index .* out of bounds" */ :]
- _ = a[: 11 /* ERROR "index .* out of bounds" */ ]
- _ = a[: 1 /* ERROR "stupid index" */ <<100]
-
- pa := &a
- _ = pa[9]
- _ = pa[10 /* ERROR "index .* out of bounds" */ ]
- _ = pa[1 /* ERROR "stupid index" */ <<100]
- _ = pa[10:]
- _ = pa[:10]
- _ = pa[10:10]
- _ = pa[11 /* ERROR "index .* out of bounds" */ :]
- _ = pa[: 11 /* ERROR "index .* out of bounds" */ ]
- _ = pa[: 1 /* ERROR "stupid index" */ <<100]
-
- 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 :]
- _ = s[: 1 /* ERROR "stupid index" */ <<100]
- _ = s[1 /* ERROR "stupid index" */ <<100 :]
- _ = s[1 /* ERROR "stupid index" */ <<100 : 1 /* ERROR "stupid index" */ <<100]
-
- 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
-
- // issue 4913
- type mystring string
- var ss string
- var ms mystring
- var i, j int
- ss = "foo"[1:2]
- ss = "foo"[i:j]
- ms = "foo" /* ERROR "cannot assign" */ [1:2]
- ms = "foo" /* ERROR "cannot assign" */ [i:j]
-}
-
-type T struct {
- x int
-}
-
-func (*T) m() {}
-
-func method_expressions() {
- _ = T /* ERROR "no single field or method" */ .a
- _ = T /* ERROR "has no method" */ .x
- _ = T.m
- var f func(*T) = (*T).m
- var g func(*T) = ( /* ERROR "cannot assign" */ T).m
-}
-
-func struct_literals() {
- type T0 struct {
- a, b, c int
- }
-
- type T1 struct {
- T0
- a, b int
- u float64
- s string
- }
-
- // keyed elements
- _ = T1{}
- _ = T1{a: 0, 1 /* ERROR "mixture of .* elements" */ }
- _ = T1{aa /* ERROR "unknown field" */ : 0}
- _ = T1{1 /* ERROR "invalid field name" */ : 0}
- _ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10}
- _ = T1{a: "foo" /* ERROR "cannot use" */ }
- _ = T1{c /* ERROR "unknown field" */ : 0}
- _ = T1{T0: { /* ERROR "missing type" */ }}
- _ = T1{T0: T0{}}
- _ = T1{T0 /* ERROR "invalid field name" */ .a: 0}
-
- // unkeyed elements
- _ = T0{1, 2, 3}
- _ = T0{1, b /* ERROR "mixture" */ : 2, 3}
- _ = T0{1, 2} /* ERROR "too few values" */
- _ = T0{1, 2, 3, 4 /* ERROR "too many values" */ }
- _ = T0{1, "foo" /* ERROR "cannot use" */, 3.4 /* ERROR "cannot use" */}
-}
-
-func array_literals() {
- type A0 [0]int
- _ = A0{}
- _ = A0{0 /* ERROR "index .* out of bounds" */}
- _ = A0{0 /* ERROR "index .* out of bounds" */ : 0}
-
- type A1 [10]int
- _ = A1{}
- _ = A1{0, 1, 2}
- _ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
- _ = A1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /* ERROR "index .* out of bounds" */ }
- _ = A1{- /* ERROR "index .* negative" */ 1: 0}
- _ = A1{8: 8, 9}
- _ = A1{8: 8, 9, 10 /* ERROR "index .* out of bounds" */ }
- _ = A1{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
- _ = A1{5: 5, 6, 7, 3: 3, 4}
- _ = A1{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
- _ = A1{10 /* ERROR "index .* out of bounds" */ : 10, 10 /* ERROR "index .* out of bounds" */ : 10}
- _ = A1{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
- _ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
- _ = A1{2.0}
- _ = A1{2.1 /* ERROR "cannot use" */ }
- _ = A1{"foo" /* ERROR "cannot use" */ }
-
- a0 := [...]int{}
- assert(len(a0) == 0)
-
- a1 := [...]int{0, 1, 2}
- assert(len(a1) == 3)
- var a13 [3]int
- var a14 [4]int
- a13 = a1
- a14 = a1 /* ERROR "cannot assign" */
-
- a2 := [...]int{- /* ERROR "index .* negative" */ 1: 0}
-
- a3 := [...]int{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
- assert(len(a3) == 5) // somewhat arbitrary
-
- a4 := [...]complex128{0, 1, 2, 1<<10-2: -1i, 1i, 400: 10, 12, 14}
- assert(len(a4) == 1024)
-
- // from the spec
- type Point struct { x, y float32 }
- _ = [...]Point{Point{1.5, -3.5}, Point{0, 0}}
- _ = [...]Point{{1.5, -3.5}, {0, 0}}
- _ = [][]int{[]int{1, 2, 3}, []int{4, 5}}
- _ = [][]int{{1, 2, 3}, {4, 5}}
- _ = [...]*Point{&Point{1.5, -3.5}, &Point{0, 0}}
- _ = [...]*Point{{1.5, -3.5}, {0, 0}}
-}
-
-func slice_literals() {
- type S0 []int
- _ = S0{}
- _ = S0{0, 1, 2}
- _ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
- _ = S0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
- _ = S0{- /* ERROR "index .* negative" */ 1: 0}
- _ = S0{8: 8, 9}
- _ = S0{8: 8, 9, 10}
- _ = S0{0, 1, 2, 0 /* ERROR "duplicate index" */ : 0, 3: 3, 4}
- _ = S0{5: 5, 6, 7, 3: 3, 4}
- _ = S0{5: 5, 6, 7, 3: 3, 4, 5 /* ERROR "duplicate index" */ }
- _ = S0{10: 10, 10 /* ERROR "duplicate index" */ : 10}
- _ = S0{5: 5, 6, 7, 3: 3, 1 /* ERROR "stupid index" */ <<100: 4, 5 /* ERROR "duplicate index" */ }
- _ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "stupid index" */ <<100: 4}
- _ = S0{2.0}
- _ = S0{2.1 /* ERROR "cannot use" */ }
- _ = S0{"foo" /* ERROR "cannot use" */ }
-
- // indices must be resolved correctly
- // (for details, see comment in go/parser/parser.go, method parseElement)
- index1 := 1
- _ = S0{index1: 1}
- _ = S0{index2: 2}
- _ = S0{index3 /* ERROR "undeclared name" */ : 3}
-}
-
-var index2 int = 2
-
-func map_literals() {
- type M0 map[string]int
- type M1 map[bool]int
- type M2 map[*int]int
-
- _ = M0{}
- _ = M0{1 /* ERROR "missing key" */ }
- _ = M0{1 /* ERROR "cannot use .* as string key" */ : 2}
- _ = M0{"foo": "bar" /* ERROR "cannot use .* as int value" */ }
- _ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
-
- // map keys must be resolved correctly
- // (for details, see comment in go/parser/parser.go, method parseElement)
- key1 := "foo"
- _ = M0{key1: 1}
- _ = M0{key2: 2}
- _ = M0{key3 /* ERROR "undeclared name" */ : 2}
-
- _ = M1{true: 1, false: 0}
- _ = M2{nil: 0, &index2: 1}
-}
-
-var key2 string = "bar"
-
-type I interface {
- m()
-}
-
-type I2 interface {
- m(int)
-}
-
-type T1 struct{}
-type T2 struct{}
-
-func (T2) m(int) {}
-
-func type_asserts() {
- var x int
- _ = x /* ERROR "not an interface" */ .(int)
-
- var e interface{}
- var ok bool
- x, ok = e.(int)
-
- var t I
- _ = t /* ERROR "use of .* outside type switch" */ .(type)
- _ = t.(T)
- _ = t.(T1 /* ERROR "missing method m" */ )
- _ = t.(T2 /* ERROR "wrong type for method m" */ )
- _ = t.(I2 /* ERROR "wrong type for method m" */ )
-}
-
-func f0() {}
-func f1(x int) {}
-func f2(u float32, s string) {}
-func fs(s []byte) {}
-func fv(x ...int) {}
-func fi(x ... interface{}) {}
-
-func g0() {}
-func g1() int { return 0}
-func g2() (u float32, s string) { return }
-func gs() []byte { return nil }
-
-func _calls() {
- var x int
- var y float32
- var s []int
-
- f0()
- _ = f0 /* ERROR "used as value" */ ()
- f0(g0 /* ERROR "too many arguments" */ )
-
- f1(0)
- f1(x)
- f1(10.0)
- f1 /* ERROR "too few arguments" */ ()
- f1(x, y /* ERROR "too many arguments" */ )
- f1(s /* ERROR "cannot assign" */ )
- f1(x ... /* ERROR "cannot use ..." */ )
- f1(g0 /* ERROR "used as value" */ ())
- f1(g1())
- // f1(g2()) // TODO(gri) missing position in error message
-
- f2 /* ERROR "too few arguments" */ ()
- f2 /* ERROR "too few arguments" */ (3.14)
- f2(3.14, "foo")
- f2(x /* ERROR "cannot assign" */ , "foo")
- f2(g0 /* ERROR "used as value" */ ())
- f2 /* ERROR "too few arguments" */ (g1 /* ERROR "cannot assign" */ ())
- f2(g2())
-
- fs /* ERROR "too few arguments" */ ()
- fs(g0 /* ERROR "used as value" */ ())
- fs(g1 /* ERROR "cannot assign" */ ())
- // fs(g2()) // TODO(gri) missing position in error message
- fs(gs())
-
- fv()
- fv(1, 2.0, x)
- fv(s /* ERROR "cannot assign" */ )
- fv(s...)
- fv(1, s /* ERROR "can only use ... with matching parameter" */ ...)
- fv(gs /* ERROR "cannot assign" */ ())
- fv(gs /* ERROR "cannot assign" */ ()...)
-
- fi()
- fi(1, 2.0, x, 3.14, "foo")
- fi(g2())
- fi(0, g2)
- fi(0, g2 /* ERROR "2-valued expression" */ ())
-}
diff --git a/src/pkg/go/types/testdata/stmt0.src b/src/pkg/go/types/testdata/stmt0.src
deleted file mode 100644
index 9d85de3bb..000000000
--- a/src/pkg/go/types/testdata/stmt0.src
+++ /dev/null
@@ -1,288 +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.
-
-// 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" */
-
- var u64 uint64
- u64 += 1<<u64
-
- undeclared /* ERROR "undeclared" */ = 991
-}
-
-func incdecs() {
- const c = 3.14
- c /* ERROR "cannot assign" */ ++
- s := "foo"
- s /* ERROR "cannot convert" */ --
- 3.14 /* ERROR "cannot assign" */ ++
- var (
- x int
- y float32
- z complex128
- )
- x++
- y--
- z++
-}
-
-func sends() {
- var ch chan int
- var rch <-chan int
- var x int
- x /* ERROR "cannot send" */ <- x
- rch /* ERROR "cannot send" */ <- x
- ch <- "foo" /* ERROR "cannot convert" */
- ch <- x
-}
-
-func selects() {
- select {}
- var (
- ch chan int
- sc chan <- bool
- x int
- )
- select {
- case <-ch:
- ch <- x
- case t, ok := <-ch:
- x = t
- case <-sc /* ERROR "cannot receive from send-only channel" */ :
- }
- select {
- default:
- default /* ERROR "multiple defaults" */ :
- }
-}
-
-func gos() {
- go 1 /* ERROR "expected function/method call" */
- go gos()
- var c chan int
- go close(c)
- go len(c) // TODO(gri) this should not be legal
-}
-
-func defers() {
- defer 1 /* ERROR "expected function/method call" */
- defer defers()
- var c chan int
- defer close(c)
- defer len(c) // TODO(gri) this should not be legal
-}
-
-func switches() {
- var x int
-
- switch x {
- default:
- default /* ERROR "multiple defaults" */ :
- }
-
- switch {
- case 1 /* ERROR "cannot convert" */ :
- }
-
- switch int32(x) {
- case 1, 2:
- case x /* ERROR "cannot compare" */ :
- }
-
- switch x {
- case 1 /* ERROR "overflows int" */ << 100:
- }
-
- switch x {
- case 1:
- case 1 /* ERROR "duplicate case" */ :
- case 2, 3, 4:
- case 1 /* ERROR "duplicate case" */ :
- }
-
- // TODO(gri) duplicate 64bit values that don't fit into an int64 are not yet detected
- switch uint64(x) {
- case 1<<64-1:
- case 1<<64-1:
- }
-}
-
-type I interface {
- m()
-}
-
-type I2 interface {
- m(int)
-}
-
-type T struct{}
-type T1 struct{}
-type T2 struct{}
-
-func (T) m() {}
-func (T2) m(int) {}
-
-func typeswitches() {
- var i int
- var x interface{}
-
- switch x.(type) {}
- switch (x /* ERROR "outside type switch" */ .(type)) {}
-
- switch x.(type) {
- default:
- default /* ERROR "multiple defaults" */ :
- }
-
- switch x := x.(type) {}
-
- switch x := x.(type) {
- case int:
- var y int = x
- }
-
- switch x := i /* ERROR "not an interface" */ .(type) {}
-
- switch t := x.(type) {
- case nil:
- var v bool = t /* ERROR "cannot assign" */
- case int:
- var v int = t
- case float32, complex64:
- var v float32 = t /* ERROR "cannot assign" */
- default:
- var v float32 = t /* ERROR "cannot assign" */
- }
-
- var t I
- switch t.(type) {
- case T:
- case T1 /* ERROR "missing method m" */ :
- case T2 /* ERROR "wrong type for method m" */ :
- case I2 /* ERROR "wrong type for method m" */ :
- }
-}
-
-func typeswitch0() {
- switch y := interface{}(nil).(type) {
- case int:
- // TODO(gri) y has the wrong type here (type-checking
- // of captured variable is delayed)
- // func() int { return y + 0 }()
- }
-}
-
-func rangeloops() {
- var (
- x int
- a [10]float32
- b []string
- p *[10]complex128
- pp **[10]complex128
- s string
- m map[int]bool
- c chan int
- sc chan<- int
- rc <-chan int
- )
-
- for _ = range x /* ERROR "cannot range over" */ {}
- for i := range x /* ERROR "cannot range over" */ {}
-
- for i := range a {
- var ii int
- ii = i
- }
- for i, x := range a {
- var ii int
- ii = i
- var xx float64
- xx = x /* ERROR "cannot assign" */
- }
- var ii int
- var xx float32
- for ii, xx := range a {}
-
- for i := range b {
- var ii int
- ii = i
- }
- for i, x := range b {
- var ii int
- ii = i
- var xx string
- xx = x
- }
-
- for i := range s {
- var ii int
- ii = i
- }
- for i, x := range s {
- var ii int
- ii = i
- var xx rune
- xx = x
- }
-
- for _, x := range p {
- var xx complex128
- xx = x
- }
-
- for _, x := range pp /* ERROR "cannot range over" */ {}
-
- for k := range m {
- var kk int32
- kk = k /* ERROR "cannot assign" */
- }
- for k, v := range m {
- var kk int
- kk = k
- if v {}
- }
-
- for _, _ /* ERROR "only one iteration variable" */ = range c {}
- for e := range c {
- var ee int
- ee = e
- }
- for _ = range sc /* ERROR "cannot range over send-only channel" */ {}
- for _ = range rc {}
-
- // constant strings
- const cs = "foo"
- for i, x := range cs {}
- for i, x := range "" {
- var ii int
- ii = i
- var xx rune
- xx = x
- }
-}
diff --git a/src/pkg/go/types/types.go b/src/pkg/go/types/types.go
deleted file mode 100644
index 2f2e579bd..000000000
--- a/src/pkg/go/types/types.go
+++ /dev/null
@@ -1,236 +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 types
-
-import "go/ast"
-
-// All types implement the Type interface.
-type Type interface {
- String() string
- 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
- IsConstType = IsBoolean | IsNumeric | IsString
-)
-
-// A Basic represents a basic type.
-type Basic struct {
- Kind BasicKind
- Info BasicInfo
- size int64 // use DefaultSizeof to get size
- Name string
-}
-
-// An Array represents an array type [Len]Elt.
-type Array struct {
- Len int64
- Elt Type
-}
-
-// A Slice represents a slice type []Elt.
-type Slice struct {
- Elt Type
-}
-
-// A QualifiedName is a name qualified with the package that declared the name.
-// Note: Pkg may be a fake package (no name, no scope) because the GC compiler's
-// export information doesn't provide full information in some cases.
-// TODO(gri): Should change Pkg to PkgPath since it's the only thing we care about.
-type QualifiedName struct {
- Pkg *Package // nil only for predeclared error.Error (exported)
- Name string // unqualified type name for anonymous fields
-}
-
-// IsSame reports whether p and q are the same.
-func (p QualifiedName) IsSame(q QualifiedName) bool {
- // spec:
- // "Two identifiers are different if they are spelled differently,
- // or if they appear in different packages and are not exported.
- // Otherwise, they are the same."
- if p.Name != q.Name {
- return false
- }
- // p.Name == q.Name
- return ast.IsExported(p.Name) || p.Pkg.Path == q.Pkg.Path
-}
-
-// A Field represents a field of a struct.
-type Field struct {
- QualifiedName
- Type Type
- Tag string
- IsAnonymous bool
-}
-
-// A Struct represents a struct type struct{...}.
-type Struct struct {
- Fields []*Field
- offsets []int64 // field offsets in bytes, lazily computed
-}
-
-func (typ *Struct) fieldIndex(name QualifiedName) int {
- for i, f := range typ.Fields {
- if f.QualifiedName.IsSame(name) {
- return i
- }
- }
- return -1
-}
-
-// A Pointer represents a pointer type *Base.
-type Pointer struct {
- Base Type
-}
-
-// A Result represents a (multi-value) function call result.
-type Result struct {
- Values []*Var // Signature.Results of the function called
-}
-
-// A Signature represents a user-defined function type func(...) (...).
-type Signature struct {
- Recv *Var // nil if not a method
- Params []*Var // (incoming) parameters from left to right; or nil
- Results []*Var // (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 {
- 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
-}
-
-// A Method represents a method.
-type Method struct {
- QualifiedName
- Type *Signature
-}
-
-// An Interface represents an interface type interface{...}.
-type Interface struct {
- Methods []*Method // TODO(gri) consider keeping them in sorted order
-}
-
-// A Map represents a map type map[Key]Elt.
-type Map struct {
- Key, Elt Type
-}
-
-// A Chan represents a channel type chan Elt, <-chan Elt, or chan<-Elt.
-type Chan struct {
- Dir ast.ChanDir
- Elt Type
-}
-
-// A NamedType represents a named type as declared in a type declaration.
-type NamedType struct {
- Obj *TypeName // corresponding declared object
- Underlying Type // nil if not fully declared yet; never a *NamedType
- Methods []*Method // TODO(gri) consider keeping them in sorted order
-}
-
-func (*Basic) aType() {}
-func (*Array) aType() {}
-func (*Slice) aType() {}
-func (*Struct) aType() {}
-func (*Pointer) aType() {}
-func (*Result) aType() {}
-func (*Signature) aType() {}
-func (*builtin) aType() {}
-func (*Interface) aType() {}
-func (*Map) aType() {}
-func (*Chan) aType() {}
-func (*NamedType) aType() {}
diff --git a/src/pkg/go/types/types_test.go b/src/pkg/go/types/types_test.go
deleted file mode 100644
index 8e228fa67..000000000
--- a/src/pkg/go/types/types_test.go
+++ /dev/null
@@ -1,171 +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.
-
-// 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) (*Package, error) {
- file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
- if err != nil {
- return nil, err
- }
- pkg, err := Check(fset, []*ast.File{file})
- return pkg, err
-}
-
-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()}"),
- dup(`interface{m(int) float32; String() string}`),
- // 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").GetType())
- 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("t.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 {}(1, 2)[x]", "(func literal)(1, 2)[x]"},
- {"[]int{1, 2, 3}", "(composite literal)"},
- {"[]int{1, 2, 3}[x:]", "(composite literal)[x:]"},
- {"i.([]string)", "i.(...)"},
-}
-
-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) int; i interface{}; t interface { foo() })"
- file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
- 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 := file.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/src/pkg/go/types/universe.go b/src/pkg/go/types/universe.go
deleted file mode 100644
index b218525c1..000000000
--- a/src/pkg/go/types/universe.go
+++ /dev/null
@@ -1,146 +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.
-
-// This file implements the universe and unsafe package scopes.
-
-package types
-
-import (
- "go/ast"
- "strings"
-)
-
-var (
- Universe *Scope
- Unsafe *Package
- universeIota *Const
-)
-
-// Predeclared types, indexed by BasicKind.
-var Typ = [...]*Basic{
- Invalid: {Invalid, 0, 0, "invalid type"},
-
- Bool: {Bool, IsBoolean, 1, "bool"},
- Int: {Int, IsInteger, 0, "int"},
- Int8: {Int8, IsInteger, 1, "int8"},
- Int16: {Int16, IsInteger, 2, "int16"},
- Int32: {Int32, IsInteger, 4, "int32"},
- Int64: {Int64, IsInteger, 8, "int64"},
- Uint: {Uint, IsInteger | IsUnsigned, 0, "uint"},
- Uint8: {Uint8, IsInteger | IsUnsigned, 1, "uint8"},
- Uint16: {Uint16, IsInteger | IsUnsigned, 2, "uint16"},
- Uint32: {Uint32, IsInteger | IsUnsigned, 4, "uint32"},
- Uint64: {Uint64, IsInteger | IsUnsigned, 8, "uint64"},
- Uintptr: {Uintptr, IsInteger | IsUnsigned, 0, "uintptr"},
- Float32: {Float32, IsFloat, 4, "float32"},
- Float64: {Float64, IsFloat, 8, "float64"},
- Complex64: {Complex64, IsComplex, 8, "complex64"},
- Complex128: {Complex128, IsComplex, 16, "complex128"},
- String: {String, IsString, 0, "string"},
- UnsafePointer: {UnsafePointer, 0, 0, "Pointer"},
-
- UntypedBool: {UntypedBool, IsBoolean | IsUntyped, 0, "untyped boolean"},
- UntypedInt: {UntypedInt, IsInteger | IsUntyped, 0, "untyped integer"},
- UntypedRune: {UntypedRune, IsInteger | IsUntyped, 0, "untyped rune"},
- UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, 0, "untyped float"},
- UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, 0, "untyped complex"},
- UntypedString: {UntypedString, IsString | IsUntyped, 0, "untyped string"},
- UntypedNil: {UntypedNil, IsUntyped, 0, "untyped nil"},
-}
-
-var aliases = [...]*Basic{
- {Byte, IsInteger | IsUnsigned, 1, "byte"},
- {Rune, IsInteger, 4, "rune"},
-}
-
-var predeclaredConstants = [...]*Const{
- {nil, "true", Typ[UntypedBool], true, nil},
- {nil, "false", Typ[UntypedBool], false, nil},
- {nil, "iota", Typ[UntypedInt], zeroConst, nil},
- {nil, "nil", Typ[UntypedNil], nilConst, nil},
-}
-
-var predeclaredFunctions = [...]*builtin{
- {_Append, "append", 1, true, false},
- {_Cap, "cap", 1, false, false},
- {_Close, "close", 1, false, true},
- {_Complex, "complex", 2, false, false},
- {_Copy, "copy", 2, false, true},
- {_Delete, "delete", 2, false, true},
- {_Imag, "imag", 1, false, false},
- {_Len, "len", 1, false, false},
- {_Make, "make", 1, true, false},
- {_New, "new", 1, false, false},
- {_Panic, "panic", 1, false, true},
- {_Print, "print", 0, true, true},
- {_Println, "println", 0, true, true},
- {_Real, "real", 1, false, false},
- {_Recover, "recover", 0, false, true},
-
- {_Alignof, "Alignof", 1, false, false},
- {_Offsetof, "Offsetof", 1, false, false},
- {_Sizeof, "Sizeof", 1, false, false},
-}
-
-func init() {
- Universe = new(Scope)
- Unsafe = &Package{Name: "unsafe", Scope: new(Scope)}
-
- // predeclared types
- for _, t := range Typ {
- def(&TypeName{Name: t.Name, Type: t})
- }
- for _, t := range aliases {
- def(&TypeName{Name: t.Name, Type: t})
- }
-
- // error type
- {
- // Error has a nil package in its qualified name since it is in no package
- err := &Method{QualifiedName{nil, "Error"}, &Signature{Results: []*Var{{Name: "", Type: Typ[String]}}}}
- def(&TypeName{Name: "error", Type: &NamedType{Underlying: &Interface{Methods: []*Method{err}}}})
- }
-
- for _, c := range predeclaredConstants {
- def(c)
- }
-
- for _, f := range predeclaredFunctions {
- def(&Func{Name: f.name, Type: f})
- }
-
- universeIota = Universe.Lookup("iota").(*Const)
-}
-
-// 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(obj Object) {
- name := obj.GetName()
- if strings.Index(name, " ") >= 0 {
- return // nothing to do
- }
- // fix Obj link for named types
- if typ, ok := obj.GetType().(*NamedType); ok {
- typ.Obj = obj.(*TypeName)
- }
- // exported identifiers go into package unsafe
- scope := Universe
- if ast.IsExported(name) {
- scope = Unsafe.Scope
- // set Pkg field
- switch obj := obj.(type) {
- case *TypeName:
- obj.Pkg = Unsafe
- case *Func:
- obj.Pkg = Unsafe
- default:
- unreachable()
- }
- }
- if scope.Insert(obj) != nil {
- panic("internal error: double declaration")
- }
-}
diff --git a/src/pkg/hash/crc32/crc32_amd64.s b/src/pkg/hash/crc32/crc32_amd64.s
index 6e6a364ee..826306a3e 100644
--- a/src/pkg/hash/crc32/crc32_amd64.s
+++ b/src/pkg/hash/crc32/crc32_amd64.s
@@ -6,7 +6,7 @@
TEXT ·castagnoliSSE42(SB),7,$0
MOVL crc+0(FP), AX // CRC value
MOVQ p+8(FP), SI // data pointer
- MOVQ p+16(FP), CX // len(p)
+ MOVQ p_len+16(FP), CX // len(p)
NOTL AX
@@ -47,7 +47,7 @@ cleanup:
done:
NOTL AX
- MOVL AX, r+32(FP)
+ MOVL AX, ret+32(FP)
RET
// func haveSSE42() bool
@@ -57,6 +57,6 @@ TEXT ·haveSSE42(SB),7,$0
CPUID
SHRQ $20, CX
ANDQ $1, CX
- MOVB CX, r+0(FP)
+ MOVB CX, ret+0(FP)
RET
diff --git a/src/pkg/html/template/template.go b/src/pkg/html/template/template.go
index 768cee7d5..e183898d5 100644
--- a/src/pkg/html/template/template.go
+++ b/src/pkg/html/template/template.go
@@ -45,18 +45,24 @@ func (t *Template) Templates() []*Template {
return m
}
-// Execute applies a parsed template to the specified data object,
-// writing the output to wr.
-func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
+// escape escapes all associated templates.
+func (t *Template) escape() error {
t.nameSpace.mu.Lock()
+ defer t.nameSpace.mu.Unlock()
if !t.escaped {
- if err = escapeTemplates(t, t.Name()); err != nil {
- t.escaped = true
+ if err := escapeTemplates(t, t.Name()); err != nil {
+ return err
}
+ t.escaped = true
}
- t.nameSpace.mu.Unlock()
- if err != nil {
- return
+ return nil
+}
+
+// Execute applies a parsed template to the specified data object,
+// writing the output to wr.
+func (t *Template) Execute(wr io.Writer, data interface{}) error {
+ if err := t.escape(); err != nil {
+ return err
}
return t.text.Execute(wr, data)
}
diff --git a/src/pkg/html/template/transition.go b/src/pkg/html/template/transition.go
index 96a4f6678..564eb2020 100644
--- a/src/pkg/html/template/transition.go
+++ b/src/pkg/html/template/transition.go
@@ -71,7 +71,6 @@ func tText(c context, s []byte) (context, int) {
}
k = j
}
- panic("unreachable")
}
var elementContentType = [...]state{
@@ -430,7 +429,6 @@ func tCSS(c context, s []byte) (context, int) {
}
k = i + 1
}
- panic("unreachable")
}
// tCSSStr is the context transition function for the CSS string and URL states.
@@ -471,7 +469,6 @@ func tCSSStr(c context, s []byte) (context, int) {
c, _ = tURL(c, decodeCSS(s[:i+1]))
k = i + 1
}
- panic("unreachable")
}
// tError is the context transition function for the error state.
diff --git a/src/pkg/image/gif/reader.go b/src/pkg/image/gif/reader.go
index 8b36948d6..8e8531f9b 100644
--- a/src/pkg/image/gif/reader.go
+++ b/src/pkg/image/gif/reader.go
@@ -17,6 +17,11 @@ import (
"io"
)
+var (
+ errNotEnough = errors.New("gif: not enough image data")
+ errTooMuch = errors.New("gif: too much image data")
+)
+
// If the io.Reader does not also have ReadByte, then decode will introduce its own buffering.
type reader interface {
io.Reader
@@ -89,29 +94,35 @@ type decoder struct {
// comprises (n, (n bytes)) blocks, with 1 <= n <= 255. It is the
// reader given to the LZW decoder, which is thus immune to the
// blocking. After the LZW decoder completes, there will be a 0-byte
-// block remaining (0, ()), but under normal execution blockReader
-// doesn't consume it, so it is handled in decode.
+// block remaining (0, ()), which is consumed when checking that the
+// blockReader is exhausted.
type blockReader struct {
r reader
slice []byte
+ err error
tmp [256]byte
}
func (b *blockReader) Read(p []byte) (int, error) {
+ if b.err != nil {
+ return 0, b.err
+ }
if len(p) == 0 {
return 0, nil
}
if len(b.slice) == 0 {
- blockLen, err := b.r.ReadByte()
- if err != nil {
- return 0, err
+ var blockLen uint8
+ blockLen, b.err = b.r.ReadByte()
+ if b.err != nil {
+ return 0, b.err
}
if blockLen == 0 {
- return 0, io.EOF
+ b.err = io.EOF
+ return 0, b.err
}
b.slice = b.tmp[0:blockLen]
- if _, err = io.ReadFull(b.r, b.slice); err != nil {
- return 0, err
+ if _, b.err = io.ReadFull(b.r, b.slice); b.err != nil {
+ return 0, b.err
}
}
n := copy(p, b.slice)
@@ -142,35 +153,33 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
}
}
-Loop:
- for err == nil {
- var c byte
- c, err = d.r.ReadByte()
- if err == io.EOF {
- break
+ for {
+ c, err := d.r.ReadByte()
+ if err != nil {
+ return err
}
switch c {
case sExtension:
- err = d.readExtension()
+ if err = d.readExtension(); err != nil {
+ return err
+ }
case sImageDescriptor:
- var m *image.Paletted
- m, err = d.newImageFromDescriptor()
+ m, err := d.newImageFromDescriptor()
if err != nil {
- break
+ return err
}
if d.imageFields&fColorMapFollows != 0 {
m.Palette, err = d.readColorMap()
if err != nil {
- break
+ return err
}
// TODO: do we set transparency in this map too? That would be
// d.setTransparency(m.Palette)
} else {
m.Palette = d.globalColorMap
}
- var litWidth uint8
- litWidth, err = d.r.ReadByte()
+ litWidth, err := d.r.ReadByte()
if err != nil {
return err
}
@@ -178,18 +187,27 @@ Loop:
return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
}
// A wonderfully Go-like piece of magic.
- lzwr := lzw.NewReader(&blockReader{r: d.r}, lzw.LSB, int(litWidth))
+ br := &blockReader{r: d.r}
+ lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
- break
+ if err != io.ErrUnexpectedEOF {
+ return err
+ }
+ return errNotEnough
}
-
- // There should be a "0" block remaining; drain that.
- c, err = d.r.ReadByte()
- if err != nil {
- return err
+ // Both lzwr and br should be exhausted. Reading from them
+ // should yield (0, io.EOF).
+ if n, err := lzwr.Read(d.tmp[:1]); n != 0 || err != io.EOF {
+ if err != nil {
+ return err
+ }
+ return errTooMuch
}
- if c != 0 {
- return errors.New("gif: extra data after image")
+ if n, err := br.Read(d.tmp[:1]); n != 0 || err != io.EOF {
+ if err != nil {
+ return err
+ }
+ return errTooMuch
}
// Undo the interlacing if necessary.
@@ -202,19 +220,15 @@ Loop:
d.delayTime = 0 // TODO: is this correct, or should we hold on to the value?
case sTrailer:
- break Loop
+ if len(d.image) == 0 {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
default:
- err = fmt.Errorf("gif: unknown block type: 0x%.2x", c)
+ return fmt.Errorf("gif: unknown block type: 0x%.2x", c)
}
}
- if err != nil {
- return err
- }
- if len(d.image) == 0 {
- return io.ErrUnexpectedEOF
- }
- return nil
}
func (d *decoder) readHeaderAndScreenDescriptor() error {
@@ -304,7 +318,6 @@ func (d *decoder) readExtension() error {
return err
}
}
- panic("unreachable")
}
func (d *decoder) readGraphicControl() error {
@@ -335,7 +348,15 @@ func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
width := int(d.tmp[4]) + int(d.tmp[5])<<8
height := int(d.tmp[6]) + int(d.tmp[7])<<8
d.imageFields = d.tmp[8]
- return image.NewPaletted(image.Rect(left, top, left+width, top+height), nil), nil
+
+ // The GIF89a spec, Section 20 (Image Descriptor) says:
+ // "Each image must fit within the boundaries of the Logical
+ // Screen, as defined in the Logical Screen Descriptor."
+ bounds := image.Rect(left, top, left+width, top+height)
+ if bounds != bounds.Intersect(image.Rect(0, 0, d.width, d.height)) {
+ return nil, errors.New("gif: frame bounds larger than image bounds")
+ }
+ return image.NewPaletted(bounds, nil), nil
}
func (d *decoder) readBlock() (int, error) {
diff --git a/src/pkg/image/gif/reader_test.go b/src/pkg/image/gif/reader_test.go
new file mode 100644
index 000000000..a035ef1ea
--- /dev/null
+++ b/src/pkg/image/gif/reader_test.go
@@ -0,0 +1,135 @@
+package gif
+
+import (
+ "bytes"
+ "compress/lzw"
+ "image"
+ "image/color"
+ "reflect"
+ "testing"
+)
+
+func TestDecode(t *testing.T) {
+ // header and trailer are parts of a valid 2x1 GIF image.
+ const (
+ header = "GIF89a" +
+ "\x02\x00\x01\x00" + // width=2, height=1
+ "\x80\x00\x00" + // headerFields=(a color map of 2 pixels), backgroundIndex, aspect
+ "\x10\x20\x30\x40\x50\x60" // the color map, also known as a palette
+ trailer = "\x3b"
+ )
+
+ // lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
+ lzwEncode := func(n int) []byte {
+ b := &bytes.Buffer{}
+ w := lzw.NewWriter(b, lzw.LSB, 2)
+ w.Write(make([]byte, n))
+ w.Close()
+ return b.Bytes()
+ }
+
+ testCases := []struct {
+ nPix int // The number of pixels in the image data.
+ extra bool // Whether to write an extra block after the LZW-encoded data.
+ wantErr error
+ }{
+ {0, false, errNotEnough},
+ {1, false, errNotEnough},
+ {2, false, nil},
+ {2, true, errTooMuch},
+ {3, false, errTooMuch},
+ }
+ for _, tc := range testCases {
+ b := &bytes.Buffer{}
+ b.WriteString(header)
+ // Write an image with bounds 2x1 but tc.nPix pixels. If tc.nPix != 2
+ // then this should result in an invalid GIF image. First, write a
+ // magic 0x2c (image descriptor) byte, bounds=(0,0)-(2,1), a flags
+ // byte, and 2-bit LZW literals.
+ b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
+ if tc.nPix > 0 {
+ enc := lzwEncode(tc.nPix)
+ if len(enc) > 0xff {
+ t.Errorf("nPix=%d, extra=%t: compressed length %d is too large", tc.nPix, tc.extra, len(enc))
+ continue
+ }
+ b.WriteByte(byte(len(enc)))
+ b.Write(enc)
+ }
+ if tc.extra {
+ b.WriteString("\x01\x02") // A 1-byte payload with an 0x02 byte.
+ }
+ b.WriteByte(0x00) // An empty block signifies the end of the image data.
+ b.WriteString(trailer)
+
+ got, err := Decode(b)
+ if err != tc.wantErr {
+ t.Errorf("nPix=%d, extra=%t\ngot %v\nwant %v", tc.nPix, tc.extra, err, tc.wantErr)
+ }
+
+ if tc.wantErr != nil {
+ continue
+ }
+ want := &image.Paletted{
+ Pix: []uint8{0, 0},
+ Stride: 2,
+ Rect: image.Rect(0, 0, 2, 1),
+ Palette: color.Palette{
+ color.RGBA{0x10, 0x20, 0x30, 0xff},
+ color.RGBA{0x40, 0x50, 0x60, 0xff},
+ },
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("nPix=%d, extra=%t\ngot %v\nwant %v", tc.nPix, tc.extra, got, want)
+ }
+ }
+}
+
+// testGIF is a simple GIF that we can modify to test different scenarios.
+var testGIF = []byte{
+ 'G', 'I', 'F', '8', '9', 'a',
+ 1, 0, 1, 0, // w=1, h=1 (6)
+ 128, 0, 0, // headerFields, bg, aspect (10)
+ 0, 0, 0, 1, 1, 1, // color map and graphics control (13)
+ 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0xff, 0x00, // (19)
+ // frame 1 (0,0 - 1,1)
+ 0x2c,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x00, // (32)
+ 0x00,
+ 0x02, 0x02, 0x4c, 0x01, 0x00, // lzw pixels
+ // trailer
+ 0x3b,
+}
+
+func try(t *testing.T, b []byte, want string) {
+ _, err := DecodeAll(bytes.NewReader(b))
+ var got string
+ if err != nil {
+ got = err.Error()
+ }
+ if got != want {
+ t.Fatalf("got %v, want %v", got, want)
+ }
+}
+
+func TestBounds(t *testing.T) {
+ // Make the bounds too big, just by one.
+ testGIF[32] = 2
+ want := "gif: frame bounds larger than image bounds"
+ try(t, testGIF, want)
+
+ // Make the bounds too small; does not trigger bounds
+ // check, but now there's too much data.
+ testGIF[32] = 0
+ want = "gif: too much image data"
+ try(t, testGIF, want)
+ testGIF[32] = 1
+
+ // Make the bounds really big, expect an error.
+ want = "gif: frame bounds larger than image bounds"
+ for i := 0; i < 4; i++ {
+ testGIF[32+i] = 0xff
+ }
+ try(t, testGIF, want)
+}
diff --git a/src/pkg/image/jpeg/reader.go b/src/pkg/image/jpeg/reader.go
index 1ee6bbcd1..862d8dc1b 100644
--- a/src/pkg/image/jpeg/reader.go
+++ b/src/pkg/image/jpeg/reader.go
@@ -245,10 +245,38 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
if err != nil {
return nil, err
}
- if d.tmp[0] != 0xff {
- return nil, FormatError("missing 0xff marker start")
+ for d.tmp[0] != 0xff {
+ // Strictly speaking, this is a format error. However, libjpeg is
+ // liberal in what it accepts. As of version 9, next_marker in
+ // jdmarker.c treats this as a warning (JWRN_EXTRANEOUS_DATA) and
+ // continues to decode the stream. Even before next_marker sees
+ // extraneous data, jpeg_fill_bit_buffer in jdhuff.c reads as many
+ // bytes as it can, possibly past the end of a scan's data. It
+ // effectively puts back any markers that it overscanned (e.g. an
+ // "\xff\xd9" EOI marker), but it does not put back non-marker data,
+ // and thus it can silently ignore a small number of extraneous
+ // non-marker bytes before next_marker has a chance to see them (and
+ // print a warning).
+ //
+ // We are therefore also liberal in what we accept. Extraneous data
+ // is silently ignored.
+ //
+ // This is similar to, but not exactly the same as, the restart
+ // mechanism within a scan (the RST[0-7] markers).
+ //
+ // Note that extraneous 0xff bytes in e.g. SOS data are escaped as
+ // "\xff\x00", and so are detected a little further down below.
+ d.tmp[0] = d.tmp[1]
+ d.tmp[1], err = d.r.ReadByte()
+ if err != nil {
+ return nil, err
+ }
}
marker := d.tmp[1]
+ if marker == 0 {
+ // Treat "\xff\x00" as extraneous data.
+ continue
+ }
for marker == 0xff {
// Section B.1.1.2 says, "Any marker may optionally be preceded by any
// number of fill bytes, which are bytes assigned code X'FF'".
diff --git a/src/pkg/image/jpeg/reader_test.go b/src/pkg/image/jpeg/reader_test.go
index b520a8ab1..e951e038c 100644
--- a/src/pkg/image/jpeg/reader_test.go
+++ b/src/pkg/image/jpeg/reader_test.go
@@ -8,8 +8,11 @@ import (
"bytes"
"fmt"
"image"
+ "image/color"
"io/ioutil"
+ "math/rand"
"os"
+ "strings"
"testing"
)
@@ -131,6 +134,66 @@ func pixString(pix []byte, stride, x, y int) string {
return s.String()
}
+func TestExtraneousData(t *testing.T) {
+ // Encode a 1x1 red image.
+ src := image.NewRGBA(image.Rect(0, 0, 1, 1))
+ src.Set(0, 0, color.RGBA{0xff, 0x00, 0x00, 0xff})
+ buf := new(bytes.Buffer)
+ if err := Encode(buf, src, nil); err != nil {
+ t.Fatalf("encode: %v", err)
+ }
+ enc := buf.String()
+ // Sanity check that the encoded JPEG is long enough, that it ends in a
+ // "\xff\xd9" EOI marker, and that it contains a "\xff\xda" SOS marker
+ // somewhere in the final 64 bytes.
+ if len(enc) < 64 {
+ t.Fatalf("encoded JPEG is too short: %d bytes", len(enc))
+ }
+ if got, want := enc[len(enc)-2:], "\xff\xd9"; got != want {
+ t.Fatalf("encoded JPEG ends with %q, want %q", got, want)
+ }
+ if s := enc[len(enc)-64:]; !strings.Contains(s, "\xff\xda") {
+ t.Fatalf("encoded JPEG does not contain a SOS marker (ff da) near the end: % x", s)
+ }
+ // Test that adding some random junk between the SOS marker and the
+ // EOI marker does not affect the decoding.
+ rnd := rand.New(rand.NewSource(1))
+ for i, nerr := 0, 0; i < 1000 && nerr < 10; i++ {
+ buf.Reset()
+ // Write all but the trailing "\xff\xd9" EOI marker.
+ buf.WriteString(enc[:len(enc)-2])
+ // Write some random extraneous data.
+ for n := rnd.Intn(10); n > 0; n-- {
+ if x := byte(rnd.Intn(256)); x != 0xff {
+ buf.WriteByte(x)
+ } else {
+ // The JPEG format escapes a SOS 0xff data byte as "\xff\x00".
+ buf.WriteString("\xff\x00")
+ }
+ }
+ // Write the "\xff\xd9" EOI marker.
+ buf.WriteString("\xff\xd9")
+
+ // Check that we can still decode the resultant image.
+ got, err := Decode(buf)
+ if err != nil {
+ t.Errorf("could not decode image #%d: %v", i, err)
+ nerr++
+ continue
+ }
+ if got.Bounds() != src.Bounds() {
+ t.Errorf("image #%d, bounds differ: %v and %v", i, got.Bounds(), src.Bounds())
+ nerr++
+ continue
+ }
+ if averageDelta(got, src) > 2<<8 {
+ t.Errorf("image #%d changed too much after a round trip", i)
+ nerr++
+ continue
+ }
+ }
+}
+
func benchmarkDecode(b *testing.B, filename string) {
b.StopTimer()
data, err := ioutil.ReadFile(filename)
diff --git a/src/pkg/image/jpeg/scan.go b/src/pkg/image/jpeg/scan.go
index e3ae8ae44..a69ed1748 100644
--- a/src/pkg/image/jpeg/scan.go
+++ b/src/pkg/image/jpeg/scan.go
@@ -109,9 +109,11 @@ func (d *decoder) processSOS(n int) error {
myy := (d.height + 8*v0 - 1) / (8 * v0)
if d.img1 == nil && d.img3 == nil {
d.makeImg(h0, v0, mxx, myy)
- if d.progressive {
- for i := 0; i < nComp; i++ {
- compIndex := scan[i].compIndex
+ }
+ if d.progressive {
+ for i := 0; i < nComp; i++ {
+ compIndex := scan[i].compIndex
+ if d.progCoeffs[compIndex] == nil {
d.progCoeffs[compIndex] = make([]block, mxx*myy*d.comp[compIndex].h*d.comp[compIndex].v)
}
}
diff --git a/src/pkg/image/jpeg/writer_test.go b/src/pkg/image/jpeg/writer_test.go
index 0b2143f5b..514b455dc 100644
--- a/src/pkg/image/jpeg/writer_test.go
+++ b/src/pkg/image/jpeg/writer_test.go
@@ -148,29 +148,38 @@ func TestWriter(t *testing.T) {
t.Error(tc.filename, err)
continue
}
- // Compute the average delta in RGB space.
- b := m0.Bounds()
- var sum, n int64
- for y := b.Min.Y; y < b.Max.Y; y++ {
- for x := b.Min.X; x < b.Max.X; x++ {
- c0 := m0.At(x, y)
- c1 := m1.At(x, y)
- r0, g0, b0, _ := c0.RGBA()
- r1, g1, b1, _ := c1.RGBA()
- sum += delta(r0, r1)
- sum += delta(g0, g1)
- sum += delta(b0, b1)
- n += 3
- }
+ if m0.Bounds() != m1.Bounds() {
+ t.Errorf("%s, bounds differ: %v and %v", tc.filename, m0.Bounds(), m1.Bounds())
+ continue
}
// Compare the average delta to the tolerance level.
- if sum/n > tc.tolerance {
+ if averageDelta(m0, m1) > tc.tolerance {
t.Errorf("%s, quality=%d: average delta is too high", tc.filename, tc.quality)
continue
}
}
}
+// averageDelta returns the average delta in RGB space. The two images must
+// have the same bounds.
+func averageDelta(m0, m1 image.Image) int64 {
+ b := m0.Bounds()
+ var sum, n int64
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ c0 := m0.At(x, y)
+ c1 := m1.At(x, y)
+ r0, g0, b0, _ := c0.RGBA()
+ r1, g1, b1, _ := c1.RGBA()
+ sum += delta(r0, r1)
+ sum += delta(g0, g1)
+ sum += delta(b0, b1)
+ n += 3
+ }
+ }
+ return sum / n
+}
+
func BenchmarkEncode(b *testing.B) {
b.StopTimer()
img := image.NewRGBA(image.Rect(0, 0, 640, 480))
diff --git a/src/pkg/io/ioutil/ioutil.go b/src/pkg/io/ioutil/ioutil.go
index 0eb146c0a..6b395c69b 100644
--- a/src/pkg/io/ioutil/ioutil.go
+++ b/src/pkg/io/ioutil/ioutil.go
@@ -144,7 +144,6 @@ func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
return
}
}
- panic("unreachable")
}
// Discard is an io.Writer on which all Write calls succeed
diff --git a/src/pkg/math/abs_386.s b/src/pkg/math/abs_386.s
index 889e80181..574676475 100644
--- a/src/pkg/math/abs_386.s
+++ b/src/pkg/math/abs_386.s
@@ -6,5 +6,5 @@
TEXT ·Abs(SB),7,$0
FMOVD x+0(FP), F0 // F0=x
FABS // F0=|x|
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/abs_amd64.s b/src/pkg/math/abs_amd64.s
index 32b78539a..119346045 100644
--- a/src/pkg/math/abs_amd64.s
+++ b/src/pkg/math/abs_amd64.s
@@ -8,5 +8,5 @@ TEXT ·Abs(SB),7,$0
MOVQ BX, X0 // movsd $(-0.0), x0
MOVSD x+0(FP), X1
ANDNPD X1, X0
- MOVSD X0, r+8(FP)
+ MOVSD X0, ret+8(FP)
RET
diff --git a/src/pkg/math/abs_arm.s b/src/pkg/math/abs_arm.s
index 37a1459fe..929e1ce67 100644
--- a/src/pkg/math/abs_arm.s
+++ b/src/pkg/math/abs_arm.s
@@ -3,9 +3,9 @@
// license that can be found in the LICENSE file.
TEXT ·Abs(SB),7,$0
- MOVW x+0(FP), R0
- MOVW x+4(FP), R1
+ MOVW x_lo+0(FP), R0
+ MOVW x_hi+4(FP), R1
AND $((1<<31)-1), R1
- MOVW R0, r+8(FP)
- MOVW R1, r+12(FP)
+ MOVW R0, ret_lo+8(FP)
+ MOVW R1, ret_hi+12(FP)
RET
diff --git a/src/pkg/math/asin_386.s b/src/pkg/math/asin_386.s
index 93df552dc..cd3f9cd9b 100644
--- a/src/pkg/math/asin_386.s
+++ b/src/pkg/math/asin_386.s
@@ -11,7 +11,7 @@ TEXT ·Asin(SB),7,$0
FSUBRDP F0, F1 // F0=1-sin(x)*sin(x) (=cos(x)*cos(x)), F1=sin(x)
FSQRT // F0=cos(x), F1=sin(x)
FPATAN // F0=arcsin(sin(x))=x
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
// func Acos(x float64) float64
@@ -24,5 +24,5 @@ TEXT ·Acos(SB),7,$0
FSQRT // F0=sin(x), F1=cos(x)
FXCHD F0, F1 // F0=cos(x), F1=sin(x)
FPATAN // F0=arccos(cos(x))=x
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/atan2_386.s b/src/pkg/math/atan2_386.s
index 9a664926a..1bf301c4c 100644
--- a/src/pkg/math/atan2_386.s
+++ b/src/pkg/math/atan2_386.s
@@ -7,5 +7,5 @@ TEXT ·Atan2(SB),7,$0
FMOVD y+0(FP), F0 // F0=y
FMOVD x+8(FP), F0 // F0=x, F1=y
FPATAN // F0=atan(F1/F0)
- FMOVDP F0, r+16(FP)
+ FMOVDP F0, ret+16(FP)
RET
diff --git a/src/pkg/math/atan_386.s b/src/pkg/math/atan_386.s
index 245437a78..c988705be 100644
--- a/src/pkg/math/atan_386.s
+++ b/src/pkg/math/atan_386.s
@@ -7,5 +7,5 @@ TEXT ·Atan(SB),7,$0
FMOVD x+0(FP), F0 // F0=x
FLD1 // F0=1, F1=x
FPATAN // F0=atan(F1/F0)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/big/arith_386.s b/src/pkg/math/big/arith_386.s
index c62483317..f0118ec0d 100644
--- a/src/pkg/math/big/arith_386.s
+++ b/src/pkg/math/big/arith_386.s
@@ -29,7 +29,7 @@ TEXT ·addVV(SB),7,$0
MOVL z+0(FP), DI
MOVL x+12(FP), SI
MOVL y+24(FP), CX
- MOVL z+4(FP), BP
+ MOVL z_len+4(FP), BP
MOVL $0, BX // i = 0
MOVL $0, DX // c = 0
JMP E1
@@ -54,7 +54,7 @@ TEXT ·subVV(SB),7,$0
MOVL z+0(FP), DI
MOVL x+12(FP), SI
MOVL y+24(FP), CX
- MOVL z+4(FP), BP
+ MOVL z_len+4(FP), BP
MOVL $0, BX // i = 0
MOVL $0, DX // c = 0
JMP E2
@@ -78,7 +78,7 @@ TEXT ·addVW(SB),7,$0
MOVL z+0(FP), DI
MOVL x+12(FP), SI
MOVL y+24(FP), AX // c = y
- MOVL z+4(FP), BP
+ MOVL z_len+4(FP), BP
MOVL $0, BX // i = 0
JMP E3
@@ -100,7 +100,7 @@ TEXT ·subVW(SB),7,$0
MOVL z+0(FP), DI
MOVL x+12(FP), SI
MOVL y+24(FP), AX // c = y
- MOVL z+4(FP), BP
+ MOVL z_len+4(FP), BP
MOVL $0, BX // i = 0
JMP E4
@@ -120,7 +120,7 @@ E4: CMPL BX, BP // i < n
// func shlVU(z, x []Word, s uint) (c Word)
TEXT ·shlVU(SB),7,$0
- MOVL z+4(FP), BX // i = z
+ MOVL z_len+4(FP), BX // i = z
SUBL $1, BX // i--
JL X8b // i < 0 (n <= 0)
@@ -155,7 +155,7 @@ X8b: MOVL $0, c+28(FP)
// func shrVU(z, x []Word, s uint) (c Word)
TEXT ·shrVU(SB),7,$0
- MOVL z+4(FP), BP
+ MOVL z_len+4(FP), BP
SUBL $1, BP // n--
JL X9b // n < 0 (n <= 0)
@@ -196,7 +196,7 @@ TEXT ·mulAddVWW(SB),7,$0
MOVL x+12(FP), SI
MOVL y+24(FP), BP
MOVL r+28(FP), CX // c = r
- MOVL z+4(FP), BX
+ MOVL z_len+4(FP), BX
LEAL (DI)(BX*4), DI
LEAL (SI)(BX*4), SI
NEGL BX // i = -n
@@ -222,7 +222,7 @@ TEXT ·addMulVVW(SB),7,$0
MOVL z+0(FP), DI
MOVL x+12(FP), SI
MOVL y+24(FP), BP
- MOVL z+4(FP), BX
+ MOVL z_len+4(FP), BX
LEAL (DI)(BX*4), DI
LEAL (SI)(BX*4), SI
NEGL BX // i = -n
@@ -251,7 +251,7 @@ TEXT ·divWVW(SB),7,$0
MOVL xn+12(FP), DX // r = xn
MOVL x+16(FP), SI
MOVL y+28(FP), CX
- MOVL z+4(FP), BX // i = z
+ MOVL z_len+4(FP), BX // i = z
JMP E7
L7: MOVL (SI)(BX*4), AX
diff --git a/src/pkg/math/big/arith_amd64.s b/src/pkg/math/big/arith_amd64.s
index d85964502..62da65030 100644
--- a/src/pkg/math/big/arith_amd64.s
+++ b/src/pkg/math/big/arith_amd64.s
@@ -36,7 +36,7 @@ TEXT ·divWW(SB),7,$0
// func addVV(z, x, y []Word) (c Word)
TEXT ·addVV(SB),7,$0
- MOVQ z+8(FP), DI
+ MOVQ z_len+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
MOVQ z+0(FP), R10
@@ -90,7 +90,7 @@ E1: MOVQ CX, c+72(FP) // return c
// func subVV(z, x, y []Word) (c Word)
// (same as addVV except for SBBQ instead of ADCQ and label names)
TEXT ·subVV(SB),7,$0
- MOVQ z+8(FP), DI
+ MOVQ z_len+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
MOVQ z+0(FP), R10
@@ -143,7 +143,7 @@ E2: MOVQ CX, c+72(FP) // return c
// func addVW(z, x []Word, y Word) (c Word)
TEXT ·addVW(SB),7,$0
- MOVQ z+8(FP), DI
+ MOVQ z_len+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), CX // c = y
MOVQ z+0(FP), R10
@@ -195,7 +195,7 @@ E3: MOVQ CX, c+56(FP) // return c
// func subVW(z, x []Word, y Word) (c Word)
// (same as addVW except for SUBQ/SBBQ instead of ADDQ/ADCQ and label names)
TEXT ·subVW(SB),7,$0
- MOVQ z+8(FP), DI
+ MOVQ z_len+8(FP), DI
MOVQ x+24(FP), R8
MOVQ y+48(FP), CX // c = y
MOVQ z+0(FP), R10
@@ -247,7 +247,7 @@ E4: MOVQ CX, c+56(FP) // return c
// func shlVU(z, x []Word, s uint) (c Word)
TEXT ·shlVU(SB),7,$0
- MOVQ z+8(FP), BX // i = z
+ MOVQ z_len+8(FP), BX // i = z
SUBQ $1, BX // i--
JL X8b // i < 0 (n <= 0)
@@ -282,7 +282,7 @@ X8b: MOVQ $0, c+56(FP)
// func shrVU(z, x []Word, s uint) (c Word)
TEXT ·shrVU(SB),7,$0
- MOVQ z+8(FP), R11
+ MOVQ z_len+8(FP), R11
SUBQ $1, R11 // n--
JL X9b // n < 0 (n <= 0)
@@ -323,7 +323,7 @@ TEXT ·mulAddVWW(SB),7,$0
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
MOVQ r+56(FP), CX // c = r
- MOVQ z+8(FP), R11
+ MOVQ z_len+8(FP), R11
MOVQ $0, BX // i = 0
JMP E5
@@ -347,7 +347,7 @@ TEXT ·addMulVVW(SB),7,$0
MOVQ z+0(FP), R10
MOVQ x+24(FP), R8
MOVQ y+48(FP), R9
- MOVQ z+8(FP), R11
+ MOVQ z_len+8(FP), R11
MOVQ $0, BX // i = 0
MOVQ $0, CX // c = 0
JMP E6
@@ -374,7 +374,7 @@ TEXT ·divWVW(SB),7,$0
MOVQ xn+24(FP), DX // r = xn
MOVQ x+32(FP), R8
MOVQ y+56(FP), R9
- MOVQ z+8(FP), BX // i = z
+ MOVQ z_len+8(FP), BX // i = z
JMP E7
L7: MOVQ (R8)(BX*8), AX
diff --git a/src/pkg/math/big/arith_arm.s b/src/pkg/math/big/arith_arm.s
index 64610f915..6e2d23d33 100644
--- a/src/pkg/math/big/arith_arm.s
+++ b/src/pkg/math/big/arith_arm.s
@@ -13,7 +13,7 @@ TEXT ·addVV(SB),7,$0
MOVW z+0(FP), R1
MOVW x+12(FP), R2
MOVW y+24(FP), R3
- MOVW z+4(FP), R4
+ MOVW z_len+4(FP), R4
MOVW R4<<2, R4
ADD R1, R4
B E1
@@ -41,7 +41,7 @@ TEXT ·subVV(SB),7,$0
MOVW z+0(FP), R1
MOVW x+12(FP), R2
MOVW y+24(FP), R3
- MOVW z+4(FP), R4
+ MOVW z_len+4(FP), R4
MOVW R4<<2, R4
ADD R1, R4
B E2
@@ -68,7 +68,7 @@ TEXT ·addVW(SB),7,$0
MOVW z+0(FP), R1
MOVW x+12(FP), R2
MOVW y+24(FP), R3
- MOVW z+4(FP), R4
+ MOVW z_len+4(FP), R4
MOVW R4<<2, R4
ADD R1, R4
CMP R1, R4
@@ -102,7 +102,7 @@ TEXT ·subVW(SB),7,$0
MOVW z+0(FP), R1
MOVW x+12(FP), R2
MOVW y+24(FP), R3
- MOVW z+4(FP), R4
+ MOVW z_len+4(FP), R4
MOVW R4<<2, R4
ADD R1, R4
CMP R1, R4
@@ -134,7 +134,7 @@ E4:
// func shlVU(z, x []Word, s uint) (c Word)
TEXT ·shlVU(SB),7,$0
- MOVW z+4(FP), R5
+ MOVW z_len+4(FP), R5
CMP $0, R5
BEQ X7
@@ -183,7 +183,7 @@ X7:
// func shrVU(z, x []Word, s uint) (c Word)
TEXT ·shrVU(SB),7,$0
- MOVW z+4(FP), R5
+ MOVW z_len+4(FP), R5
CMP $0, R5
BEQ X6
@@ -238,7 +238,7 @@ TEXT ·mulAddVWW(SB),7,$0
MOVW x+12(FP), R2
MOVW y+24(FP), R3
MOVW r+28(FP), R4
- MOVW z+4(FP), R5
+ MOVW z_len+4(FP), R5
MOVW R5<<2, R5
ADD R1, R5
B E8
@@ -265,7 +265,7 @@ TEXT ·addMulVVW(SB),7,$0
MOVW z+0(FP), R1
MOVW x+12(FP), R2
MOVW y+24(FP), R3
- MOVW z+4(FP), R5
+ MOVW z_len+4(FP), R5
MOVW R5<<2, R5
ADD R1, R5
MOVW $0, R4
diff --git a/src/pkg/math/big/int.go b/src/pkg/math/big/int.go
index bf2fd2009..fd7f005c2 100644
--- a/src/pkg/math/big/int.go
+++ b/src/pkg/math/big/int.go
@@ -795,8 +795,8 @@ func (x *Int) Bit(i int) uint {
}
// SetBit sets z to x, with x's i'th bit set to b (0 or 1).
-// That is, if bit is 1 SetBit sets z = x | (1 << i);
-// if bit is 0 it sets z = x &^ (1 << i). If bit is not 0 or 1,
+// That is, if b is 1 SetBit sets z = x | (1 << i);
+// if b is 0 SetBit sets z = x &^ (1 << i). If b is not 0 or 1,
// SetBit will panic.
func (z *Int) SetBit(x *Int, i int, b uint) *Int {
if i < 0 {
diff --git a/src/pkg/math/big/nat.go b/src/pkg/math/big/nat.go
index 9d09f97b7..6874900d0 100644
--- a/src/pkg/math/big/nat.go
+++ b/src/pkg/math/big/nat.go
@@ -1021,8 +1021,6 @@ func trailingZeroBits(x Word) uint {
default:
panic("unknown word size")
}
-
- return 0
}
// trailingZeroBits returns the number of consecutive least significant zero
diff --git a/src/pkg/math/dim_amd64.s b/src/pkg/math/dim_amd64.s
index a1505ce44..0ae8ad196 100644
--- a/src/pkg/math/dim_amd64.s
+++ b/src/pkg/math/dim_amd64.s
@@ -36,12 +36,12 @@ dim3: // (NaN, x) or (x, NaN)
SUBSD y+8(FP), X0
MOVSD $(0.0), X1
MAXSD X1, X0
- MOVSD X0, r+16(FP)
+ MOVSD X0, ret+16(FP)
RET
bothInf: // Dim(-Inf, -Inf) or Dim(+Inf, +Inf)
MOVQ $NaN, AX
isDimNaN:
- MOVQ AX, r+16(FP)
+ MOVQ AX, ret+16(FP)
RET
// func ·Max(x, y float64) float64
@@ -72,28 +72,28 @@ TEXT ·Max(SB),7,$0
MOVQ R8, X0
MOVQ R9, X1
MAXSD X1, X0
- MOVSD X0, r+16(FP)
+ MOVSD X0, ret+16(FP)
RET
isMaxNaN: // return NaN
isPosInf: // return +Inf
- MOVQ AX, r+16(FP)
+ MOVQ AX, ret+16(FP)
RET
isMaxZero:
MOVQ $(1<<63), AX // -0.0
CMPQ AX, R8
JEQ +3(PC)
- MOVQ R8, r+16(FP) // return 0
+ MOVQ R8, ret+16(FP) // return 0
RET
- MOVQ R9, r+16(FP) // return other 0
+ MOVQ R9, ret+16(FP) // return other 0
RET
/*
MOVQ $0, AX
CMPQ AX, R8
JNE +3(PC)
- MOVQ R8, r+16(FP) // return 0
+ MOVQ R8, ret+16(FP) // return 0
RET
- MOVQ R9, r+16(FP) // return other 0
+ MOVQ R9, ret+16(FP) // return other 0
RET
*/
@@ -125,18 +125,18 @@ TEXT ·Min(SB),7,$0
MOVQ R8, X0
MOVQ R9, X1
MINSD X1, X0
- MOVSD X0, r+16(FP)
+ MOVSD X0, ret+16(FP)
RET
isMinNaN: // return NaN
isNegInf: // return -Inf
- MOVQ AX, r+16(FP)
+ MOVQ AX, ret+16(FP)
RET
isMinZero:
MOVQ $(1<<63), AX // -0.0
CMPQ AX, R8
JEQ +3(PC)
- MOVQ R9, r+16(FP) // return other 0
+ MOVQ R9, ret+16(FP) // return other 0
RET
- MOVQ R8, r+16(FP) // return -0
+ MOVQ R8, ret+16(FP) // return -0
RET
diff --git a/src/pkg/math/exp2_386.s b/src/pkg/math/exp2_386.s
index ed82a4dd3..153762631 100644
--- a/src/pkg/math/exp2_386.s
+++ b/src/pkg/math/exp2_386.s
@@ -5,7 +5,7 @@
// func Exp2(x float64) float64
TEXT ·Exp2(SB),7,$0
// test bits for not-finite
- MOVL x+4(FP), AX
+ MOVL x_hi+4(FP), AX
ANDL $0x7ff00000, AX
CMPL AX, $0x7ff00000
JEQ not_finite
@@ -19,20 +19,20 @@ TEXT ·Exp2(SB),7,$0
FADDDP F0, F1 // F0=2**(x-int(x)), F1=int(x)
FSCALE // F0=2**x, F1=int(x)
FMOVDP F0, F1 // F0=2**x
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
not_finite:
// test bits for -Inf
- MOVL x+4(FP), BX
- MOVL x+0(FP), CX
+ MOVL x_hi+4(FP), BX
+ MOVL x_lo+0(FP), CX
CMPL BX, $0xfff00000
JNE not_neginf
CMPL CX, $0
JNE not_neginf
- MOVL $0, r+8(FP)
- MOVL $0, r+12(FP)
+ MOVL $0, ret_lo+8(FP)
+ MOVL $0, ret_hi+12(FP)
RET
not_neginf:
- MOVL CX, r+8(FP)
- MOVL BX, r+12(FP)
+ MOVL CX, ret_lo+8(FP)
+ MOVL BX, ret_hi+12(FP)
RET
diff --git a/src/pkg/math/exp_386.s b/src/pkg/math/exp_386.s
index e0743e72a..aeceb3cad 100644
--- a/src/pkg/math/exp_386.s
+++ b/src/pkg/math/exp_386.s
@@ -5,7 +5,7 @@
// func Exp(x float64) float64
TEXT ·Exp(SB),7,$0
// test bits for not-finite
- MOVL x+4(FP), AX
+ MOVL x_hi+4(FP), AX
ANDL $0x7ff00000, AX
CMPL AX, $0x7ff00000
JEQ not_finite
@@ -20,20 +20,20 @@ TEXT ·Exp(SB),7,$0
FADDDP F0, F1 // F0=2**(x*log2(e)-int(x*log2(e))), F1=int(x*log2(e))
FSCALE // F0=e**x, F1=int(x*log2(e))
FMOVDP F0, F1 // F0=e**x
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
not_finite:
// test bits for -Inf
- MOVL x+4(FP), BX
- MOVL x+0(FP), CX
+ MOVL x_hi+4(FP), BX
+ MOVL x_lo+0(FP), CX
CMPL BX, $0xfff00000
JNE not_neginf
CMPL CX, $0
JNE not_neginf
FLDZ // F0=0
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
not_neginf:
- MOVL CX, r+8(FP)
- MOVL BX, r+12(FP)
+ MOVL CX, ret_lo+8(FP)
+ MOVL BX, ret_hi+12(FP)
RET
diff --git a/src/pkg/math/exp_amd64.s b/src/pkg/math/exp_amd64.s
index 74c9c876a..eb6fb0432 100644
--- a/src/pkg/math/exp_amd64.s
+++ b/src/pkg/math/exp_amd64.s
@@ -93,7 +93,7 @@ TEXT ·Exp(SB),7,$0
SHLQ CX, BX
MOVQ BX, X1
MULSD X1, X0
- MOVSD X0, r+8(FP)
+ MOVSD X0, ret+8(FP)
RET
notFinite:
// test bits for -Inf
@@ -103,10 +103,10 @@ notFinite:
// -Inf, return 0
underflow: // return 0
MOVQ $0, AX
- MOVQ AX, r+8(FP)
+ MOVQ AX, ret+8(FP)
RET
overflow: // return +Inf
MOVQ $PosInf, BX
notNegInf: // NaN or +Inf, return x
- MOVQ BX, r+8(FP)
+ MOVQ BX, ret+8(FP)
RET
diff --git a/src/pkg/math/expm1_386.s b/src/pkg/math/expm1_386.s
index 8185f49a4..0ff9c4ab0 100644
--- a/src/pkg/math/expm1_386.s
+++ b/src/pkg/math/expm1_386.s
@@ -14,11 +14,11 @@ TEXT ·Expm1(SB),7,$0
FLDL2E // F0=log2(e)
FMULD x+0(FP), F0 // F0=x*log2(e) (-1<F0<1)
F2XM1 // F0=e**x-1 = 2**(x*log2(e))-1
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
use_exp:
// test bits for not-finite
- MOVL x+4(FP), AX
+ MOVL x_hi+4(FP), AX
ANDL $0x7ff00000, AX
CMPL AX, $0x7ff00000
JEQ not_finite
@@ -35,21 +35,21 @@ use_exp:
FMOVDP F0, F1 // F0=e**x
FLD1 // F0=1, F1=e**x
FSUBDP F0, F1 // F0=e**x-1
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
not_finite:
// test bits for -Inf
- MOVL x+4(FP), BX
- MOVL x+0(FP), CX
+ MOVL x_hi+4(FP), BX
+ MOVL x_lo+0(FP), CX
CMPL BX, $0xfff00000
JNE not_neginf
CMPL CX, $0
JNE not_neginf
FLD1 // F0=1
FCHS // F0=-1
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
not_neginf:
- MOVL CX, r+8(FP)
- MOVL BX, r+12(FP)
+ MOVL CX, ret_lo+8(FP)
+ MOVL BX, ret_hi+12(FP)
RET
diff --git a/src/pkg/math/floor_386.s b/src/pkg/math/floor_386.s
index a4ae9d2eb..9aa71c043 100644
--- a/src/pkg/math/floor_386.s
+++ b/src/pkg/math/floor_386.s
@@ -13,7 +13,7 @@ TEXT ·Ceil(SB),7,$0
FLDCW -4(SP) // load new Control Word
FRNDINT // F0=Ceil(x)
FLDCW -2(SP) // load old Control Word
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
// func Floor(x float64) float64
@@ -27,7 +27,7 @@ TEXT ·Floor(SB),7,$0
FLDCW -4(SP) // load new Control Word
FRNDINT // F0=Floor(x)
FLDCW -2(SP) // load old Control Word
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
// func Trunc(x float64) float64
@@ -40,5 +40,5 @@ TEXT ·Trunc(SB),7,$0
FLDCW -4(SP) // load new Control Word
FRNDINT // F0=Trunc(x)
FLDCW -2(SP) // load old Control Word
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/floor_amd64.s b/src/pkg/math/floor_amd64.s
index e72cc3cf9..bb1a2fd22 100644
--- a/src/pkg/math/floor_amd64.s
+++ b/src/pkg/math/floor_amd64.s
@@ -20,10 +20,10 @@ TEXT ·Floor(SB),7,$0
MOVSD $(-1.0), X2
ANDPD X2, X0 // if x < float(int(x)) {X0 = -1} else {X0 = 0}
ADDSD X1, X0
- MOVSD X0, r+8(FP)
+ MOVSD X0, ret+8(FP)
RET
isBig_floor:
- MOVQ AX, r+8(FP) // return x
+ MOVQ AX, ret+8(FP) // return x
RET
// func Ceil(x float64) float64
@@ -46,10 +46,10 @@ TEXT ·Ceil(SB),7,$0
ANDNPD X3, X0
ORPD X2, X0 // if float(int(x)) <= x {X0 = 1} else {X0 = -0}
ADDSD X1, X0
- MOVSD X0, r+8(FP)
+ MOVSD X0, ret+8(FP)
RET
isBig_ceil:
- MOVQ AX, r+8(FP)
+ MOVQ AX, ret+8(FP)
RET
// func Trunc(x float64) float64
@@ -67,8 +67,8 @@ TEXT ·Trunc(SB),7,$0
ANDNPD X0, X2 // X2 = sign
CVTSQ2SD AX, X0 // X0 = float(int(x))
ORPD X2, X0 // if X0 = 0.0, incorporate sign
- MOVSD X0, r+8(FP)
+ MOVSD X0, ret+8(FP)
RET
isBig_trunc:
- MOVQ AX, r+8(FP) // return x
+ MOVQ AX, ret+8(FP) // return x
RET
diff --git a/src/pkg/math/hypot_386.s b/src/pkg/math/hypot_386.s
index 51cd90419..8edfe064f 100644
--- a/src/pkg/math/hypot_386.s
+++ b/src/pkg/math/hypot_386.s
@@ -5,11 +5,11 @@
// func Hypot(p, q float64) float64
TEXT ·Hypot(SB),7,$0
// test bits for not-finite
- MOVL p+4(FP), AX // high word p
+ MOVL p_hi+4(FP), AX // high word p
ANDL $0x7ff00000, AX
CMPL AX, $0x7ff00000
JEQ not_finite
- MOVL q+12(FP), AX // high word q
+ MOVL q_hi+12(FP), AX // high word q
ANDL $0x7ff00000, AX
CMPL AX, $0x7ff00000
JEQ not_finite
@@ -31,27 +31,27 @@ TEXT ·Hypot(SB),7,$0
FADDDP F0, F1 // F0=1+q*q, F1=p
FSQRT // F0=sqrt(1+q*q), F1=p
FMULDP F0, F1 // F0=p*sqrt(1+q*q)
- FMOVDP F0, r+16(FP)
+ FMOVDP F0, ret+16(FP)
RET
FMOVDP F0, F1 // F0=0
- FMOVDP F0, r+16(FP)
+ FMOVDP F0, ret+16(FP)
RET
not_finite:
// test bits for -Inf or +Inf
- MOVL p+4(FP), AX // high word p
- ORL p+0(FP), AX // low word p
+ MOVL p_hi+4(FP), AX // high word p
+ ORL p_lo+0(FP), AX // low word p
ANDL $0x7fffffff, AX
CMPL AX, $0x7ff00000
JEQ is_inf
- MOVL q+12(FP), AX // high word q
- ORL q+8(FP), AX // low word q
+ MOVL q_hi+12(FP), AX // high word q
+ ORL q_lo+8(FP), AX // low word q
ANDL $0x7fffffff, AX
CMPL AX, $0x7ff00000
JEQ is_inf
- MOVL $0x7ff80000, r+20(FP) // return NaN = 0x7FF8000000000001
- MOVL $0x00000001, r+16(FP)
+ MOVL $0x7ff80000, ret_hi+20(FP) // return NaN = 0x7FF8000000000001
+ MOVL $0x00000001, ret_lo+16(FP)
RET
is_inf:
- MOVL AX, r+20(FP) // return +Inf = 0x7FF0000000000000
- MOVL $0x00000000, r+16(FP)
+ MOVL AX, ret_hi+20(FP) // return +Inf = 0x7FF0000000000000
+ MOVL $0x00000000, ret_lo+16(FP)
RET
diff --git a/src/pkg/math/hypot_amd64.s b/src/pkg/math/hypot_amd64.s
index 02fff5b92..40ba6f41d 100644
--- a/src/pkg/math/hypot_amd64.s
+++ b/src/pkg/math/hypot_amd64.s
@@ -31,7 +31,7 @@ TEXT ·Hypot(SB),7,$0
ADDSD $1.0, X1
SQRTSD X1, X1
MULSD X1, X0
- MOVSD X0, r+16(FP)
+ MOVSD X0, ret+16(FP)
RET
isInfOrNaN:
CMPQ AX, BX
@@ -39,12 +39,12 @@ isInfOrNaN:
CMPQ AX, CX
JEQ isInf
MOVQ $NaN, AX
- MOVQ AX, r+16(FP) // return NaN
+ MOVQ AX, ret+16(FP) // return NaN
RET
isInf:
- MOVQ AX, r+16(FP) // return +Inf
+ MOVQ AX, ret+16(FP) // return +Inf
RET
isZero:
MOVQ $0, AX
- MOVQ AX, r+16(FP) // return 0
+ MOVQ AX, ret+16(FP) // return 0
RET
diff --git a/src/pkg/math/ldexp_386.s b/src/pkg/math/ldexp_386.s
index 3a65629d2..566245dc2 100644
--- a/src/pkg/math/ldexp_386.s
+++ b/src/pkg/math/ldexp_386.s
@@ -8,5 +8,5 @@ TEXT ·Ldexp(SB),7,$0
FMOVD frac+0(FP), F0 // F0=frac, F1=e
FSCALE // F0=x*2**e, F1=e
FMOVDP F0, F1 // F0=x*2**e
- FMOVDP F0, r+12(FP)
+ FMOVDP F0, ret+12(FP)
RET
diff --git a/src/pkg/math/log10_386.s b/src/pkg/math/log10_386.s
index cc473b424..d4f94235e 100644
--- a/src/pkg/math/log10_386.s
+++ b/src/pkg/math/log10_386.s
@@ -7,7 +7,7 @@ TEXT ·Log10(SB),7,$0
FLDLG2 // F0=log10(2)
FMOVD x+0(FP), F0 // F0=x, F1=log10(2)
FYL2X // F0=log10(x)=log2(x)*log10(2)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
// func Log2(x float64) float64
@@ -15,5 +15,5 @@ TEXT ·Log2(SB),7,$0
FLD1 // F0=1
FMOVD x+0(FP), F0 // F0=x, F1=1
FYL2X // F0=log2(x)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/log1p_386.s b/src/pkg/math/log1p_386.s
index 30df88e1f..30dc8033d 100644
--- a/src/pkg/math/log1p_386.s
+++ b/src/pkg/math/log1p_386.s
@@ -14,12 +14,12 @@ TEXT ·Log1p(SB),7,$0
JEQ use_fyl2x // jump if F0 >= F1
FMOVD x+0(FP), F0 // F0=x, F1=log(2)
FYL2XP1 // F0=log(1+x)=log2(1+x)*log(2)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
use_fyl2x:
FLD1 // F0=1, F2=log(2)
FADDD x+0(FP), F0 // F0=1+x, F1=log(2)
FYL2X // F0=log(1+x)=log2(1+x)*log(2)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/log_386.s b/src/pkg/math/log_386.s
index 6cfbc7605..7a6f2c052 100644
--- a/src/pkg/math/log_386.s
+++ b/src/pkg/math/log_386.s
@@ -7,5 +7,5 @@ TEXT ·Log(SB),7,$0
FLDLN2 // F0=log(2)
FMOVD x+0(FP), F0 // F0=x, F1=log(2)
FYL2X // F0=log(x)=log2(x)*log(2)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/log_amd64.s b/src/pkg/math/log_amd64.s
index 75bc55764..6ae5fbc95 100644
--- a/src/pkg/math/log_amd64.s
+++ b/src/pkg/math/log_amd64.s
@@ -94,16 +94,16 @@ TEXT ·Log(SB),7,$0
SUBSD X2, X0 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k
MULSD $Ln2Hi, X1 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k*Ln2Hi
SUBSD X0, X1 // x1= k*Ln2Hi-((hfsq-(s*(hfsq+R)+k*Ln2Lo))-f)
- MOVSD X1, r+8(FP)
+ MOVSD X1, ret+8(FP)
RET
isInfOrNaN:
- MOVQ BX, r+8(FP) // +Inf or NaN, return x
+ MOVQ BX, ret+8(FP) // +Inf or NaN, return x
RET
isNegative:
MOVQ $NaN, AX
- MOVQ AX, r+8(FP) // return NaN
+ MOVQ AX, ret+8(FP) // return NaN
RET
isZero:
MOVQ $NegInf, AX
- MOVQ AX, r+8(FP) // return -Inf
+ MOVQ AX, ret+8(FP) // return -Inf
RET
diff --git a/src/pkg/math/mod_386.s b/src/pkg/math/mod_386.s
index 6b9c28d4f..bcb451b5d 100644
--- a/src/pkg/math/mod_386.s
+++ b/src/pkg/math/mod_386.s
@@ -11,5 +11,5 @@ TEXT ·Mod(SB),7,$0
ANDW $0x0400, AX
JNE -3(PC) // jump if reduction incomplete
FMOVDP F0, F1 // F0=x-q*y
- FMOVDP F0, r+16(FP)
+ FMOVDP F0, ret+16(FP)
RET
diff --git a/src/pkg/math/rand/exp.go b/src/pkg/math/rand/exp.go
index 85da49521..4bc110f91 100644
--- a/src/pkg/math/rand/exp.go
+++ b/src/pkg/math/rand/exp.go
@@ -43,7 +43,6 @@ func (r *Rand) ExpFloat64() float64 {
return x
}
}
- panic("unreachable")
}
var ke = [256]uint32{
diff --git a/src/pkg/math/rand/normal.go b/src/pkg/math/rand/normal.go
index 9ab46db9f..ba4ea54ca 100644
--- a/src/pkg/math/rand/normal.go
+++ b/src/pkg/math/rand/normal.go
@@ -63,7 +63,6 @@ func (r *Rand) NormFloat64() float64 {
return x
}
}
- panic("unreachable")
}
var kn = [128]uint32{
diff --git a/src/pkg/math/remainder_386.s b/src/pkg/math/remainder_386.s
index 4cb98233a..2238aba49 100644
--- a/src/pkg/math/remainder_386.s
+++ b/src/pkg/math/remainder_386.s
@@ -11,5 +11,5 @@ TEXT ·Remainder(SB),7,$0
ANDW $0x0400, AX
JNE -3(PC) // jump if reduction incomplete
FMOVDP F0, F1 // F0=x-q*y
- FMOVDP F0, r+16(FP)
+ FMOVDP F0, ret+16(FP)
RET
diff --git a/src/pkg/math/sin_386.s b/src/pkg/math/sin_386.s
index 9d00bd92b..b2a836eb1 100644
--- a/src/pkg/math/sin_386.s
+++ b/src/pkg/math/sin_386.s
@@ -9,7 +9,7 @@ TEXT ·Cos(SB),7,$0
FSTSW AX // AX=status word
ANDW $0x0400, AX
JNE 3(PC) // jump if x outside range
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
FLDPI // F0=Pi, F1=x
FADDD F0, F0 // F0=2*Pi, F1=x
@@ -20,7 +20,7 @@ TEXT ·Cos(SB),7,$0
JNE -3(PC) // jump if reduction incomplete
FMOVDP F0, F1 // F0=reduced_x
FCOS // F0=cos(reduced_x)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
// func Sin(x float64) float64
@@ -30,7 +30,7 @@ TEXT ·Sin(SB),7,$0
FSTSW AX // AX=status word
ANDW $0x0400, AX
JNE 3(PC) // jump if x outside range
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
FLDPI // F0=Pi, F1=x
FADDD F0, F0 // F0=2*Pi, F1=x
@@ -41,5 +41,5 @@ TEXT ·Sin(SB),7,$0
JNE -3(PC) // jump if reduction incomplete
FMOVDP F0, F1 // F0=reduced_x
FSIN // F0=sin(reduced_x)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/math/sqrt.go b/src/pkg/math/sqrt.go
index 21336df2a..1bd4437f1 100644
--- a/src/pkg/math/sqrt.go
+++ b/src/pkg/math/sqrt.go
@@ -4,15 +4,6 @@
package math
-// Sqrt returns the square root of x.
-//
-// Special cases are:
-// Sqrt(+Inf) = +Inf
-// Sqrt(±0) = ±0
-// Sqrt(x < 0) = NaN
-// Sqrt(NaN) = NaN
-func Sqrt(x float64) float64
-
// The original C code and the long comment below are
// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and
// came with this notice. The go code is a simplified
@@ -98,6 +89,8 @@ func Sqrt(x float64) float64
// Sqrt(±0) = ±0
// Sqrt(x < 0) = NaN
// Sqrt(NaN) = NaN
+func Sqrt(x float64) float64
+
func sqrt(x float64) float64 {
// special cases
switch {
diff --git a/src/pkg/math/sqrt_386.s b/src/pkg/math/sqrt_386.s
index d0a428d52..824fa634c 100644
--- a/src/pkg/math/sqrt_386.s
+++ b/src/pkg/math/sqrt_386.s
@@ -6,5 +6,5 @@
TEXT ·Sqrt(SB),7,$0
FMOVD x+0(FP),F0
FSQRT
- FMOVDP F0,r+8(FP)
+ FMOVDP F0,ret+8(FP)
RET
diff --git a/src/pkg/math/sqrt_amd64.s b/src/pkg/math/sqrt_amd64.s
index f5b329e70..553c4e01b 100644
--- a/src/pkg/math/sqrt_amd64.s
+++ b/src/pkg/math/sqrt_amd64.s
@@ -5,5 +5,5 @@
// func Sqrt(x float64) float64
TEXT ·Sqrt(SB),7,$0
SQRTSD x+0(FP), X0
- MOVSD X0, r+8(FP)
+ MOVSD X0, ret+8(FP)
RET
diff --git a/src/pkg/math/sqrt_arm.s b/src/pkg/math/sqrt_arm.s
index befbb8a89..b965b4845 100644
--- a/src/pkg/math/sqrt_arm.s
+++ b/src/pkg/math/sqrt_arm.s
@@ -6,5 +6,5 @@
TEXT ·Sqrt(SB),7,$0
MOVD x+0(FP),F0
SQRTD F0,F0
- MOVD F0,r+8(FP)
+ MOVD F0,ret+8(FP)
RET
diff --git a/src/pkg/math/tan_386.s b/src/pkg/math/tan_386.s
index ebb9e798b..f3ad33907 100644
--- a/src/pkg/math/tan_386.s
+++ b/src/pkg/math/tan_386.s
@@ -10,7 +10,7 @@ TEXT ·Tan(SB),7,$0
ANDW $0x0400, AX
JNE 4(PC) // jump if x outside range
FMOVDP F0, F0 // F0=tan(x)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
FLDPI // F0=Pi, F1=x
FADDD F0, F0 // F0=2*Pi, F1=x
@@ -22,5 +22,5 @@ TEXT ·Tan(SB),7,$0
FMOVDP F0, F1 // F0=reduced_x
FPTAN // F0=1, F1=tan(reduced_x)
FMOVDP F0, F0 // F0=tan(reduced_x)
- FMOVDP F0, r+8(FP)
+ FMOVDP F0, ret+8(FP)
RET
diff --git a/src/pkg/mime/multipart/multipart.go b/src/pkg/mime/multipart/multipart.go
index 77e969b41..a6204d7bd 100644
--- a/src/pkg/mime/multipart/multipart.go
+++ b/src/pkg/mime/multipart/multipart.go
@@ -265,11 +265,10 @@ func (r *Reader) NextPart() (*Part, error) {
return nil, fmt.Errorf("multipart: unexpected line in Next(): %q", line)
}
- panic("unreachable")
}
// isFinalBoundary returns whether line is the final boundary line
-// indiciating that all parts are over.
+// indicating that all parts are over.
// It matches `^--boundary--[ \t]*(\r\n)?$`
func (mr *Reader) isFinalBoundary(line []byte) bool {
if !bytes.HasPrefix(line, mr.dashBoundaryDash) {
diff --git a/src/pkg/net/conn_test.go b/src/pkg/net/conn_test.go
index fdb90862f..98bd69549 100644
--- a/src/pkg/net/conn_test.go
+++ b/src/pkg/net/conn_test.go
@@ -16,11 +16,11 @@ import (
var connTests = []struct {
net string
- addr string
+ addr func() string
}{
- {"tcp", "127.0.0.1:0"},
- {"unix", testUnixAddr()},
- {"unixpacket", testUnixAddr()},
+ {"tcp", func() string { return "127.0.0.1:0" }},
+ {"unix", testUnixAddr},
+ {"unixpacket", testUnixAddr},
}
// someTimeout is used just to test that net.Conn implementations
@@ -41,7 +41,8 @@ func TestConnAndListener(t *testing.T) {
}
}
- ln, err := Listen(tt.net, tt.addr)
+ addr := tt.addr()
+ ln, err := Listen(tt.net, addr)
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
@@ -51,7 +52,7 @@ func TestConnAndListener(t *testing.T) {
case "unix", "unixpacket":
os.Remove(addr)
}
- }(ln, tt.net, tt.addr)
+ }(ln, tt.net, addr)
ln.Addr()
done := make(chan int)
diff --git a/src/pkg/net/dial.go b/src/pkg/net/dial.go
index 22e1e7dd8..da5f7e302 100644
--- a/src/pkg/net/dial.go
+++ b/src/pkg/net/dial.go
@@ -11,7 +11,27 @@ import (
// A DialOption modifies a DialOpt call.
type DialOption interface {
- dialOption()
+ setDialOpt(*dialOpts)
+}
+
+var noLocalAddr Addr // nil
+
+// dialOpts holds all the dial options, populated by a DialOption's
+// setDialOpt.
+//
+// All fields may be their zero value.
+type dialOpts struct {
+ deadline time.Time
+ localAddr Addr
+ network string // if empty, "tcp"
+ deferredConnect bool
+}
+
+func (o *dialOpts) net() string {
+ if o.network == "" {
+ return "tcp"
+ }
+ return o.network
}
var (
@@ -38,7 +58,9 @@ func Network(net string) DialOption {
type dialNetwork string
-func (dialNetwork) dialOption() {}
+func (s dialNetwork) setDialOpt(o *dialOpts) {
+ o.network = string(s)
+}
// Deadline returns a DialOption to fail a dial that doesn't
// complete before t.
@@ -46,19 +68,29 @@ func Deadline(t time.Time) DialOption {
return dialDeadline(t)
}
+type dialDeadline time.Time
+
+func (t dialDeadline) setDialOpt(o *dialOpts) {
+ o.deadline = time.Time(t)
+}
+
// Timeout returns a DialOption to fail a dial that doesn't
// complete within the provided duration.
func Timeout(d time.Duration) DialOption {
- return dialDeadline(time.Now().Add(d))
+ return dialTimeoutOpt(d)
}
-type dialDeadline time.Time
+type dialTimeoutOpt time.Duration
-func (dialDeadline) dialOption() {}
+func (d dialTimeoutOpt) setDialOpt(o *dialOpts) {
+ o.deadline = time.Now().Add(time.Duration(d))
+}
type tcpFastOpen struct{}
-func (tcpFastOpen) dialOption() {}
+func (tcpFastOpen) setDialOpt(o *dialOpts) {
+ o.deferredConnect = true
+}
// TODO(bradfitz): implement this (golang.org/issue/4842) and unexport this.
//
@@ -74,7 +106,9 @@ type localAddrOption struct {
la Addr
}
-func (localAddrOption) dialOption() {}
+func (a localAddrOption) setDialOpt(o *dialOpts) {
+ o.localAddr = a.la
+}
// LocalAddress returns a dial option to perform a dial with the
// provided local address. The address must be of a compatible type
@@ -135,67 +169,44 @@ func resolveAddr(op, net, addr string, deadline time.Time) (Addr, error) {
// "unixpacket".
//
// For TCP and UDP networks, addresses have the form host:port.
-// If host is a literal IPv6 address, it must be enclosed
-// in square brackets. The functions JoinHostPort and SplitHostPort
-// manipulate addresses in this form.
+// If host is a literal IPv6 address or host name, it must be enclosed
+// in square brackets as in "[::1]:80", "[ipv6-host]:http" or
+// "[ipv6-host%zone]:80".
+// The functions JoinHostPort and SplitHostPort manipulate addresses
+// in this form.
//
// Examples:
// Dial("tcp", "12.34.56.78:80")
-// Dial("tcp", "google.com:80")
-// Dial("tcp", "[de:ad:be:ef::ca:fe]:80")
+// Dial("tcp", "google.com:http")
+// Dial("tcp", "[2001:db8::1]:http")
+// Dial("tcp", "[fe80::1%lo0]:80")
//
-// For IP networks, net must be "ip", "ip4" or "ip6" followed
-// by a colon and a protocol number or name.
+// For IP networks, the net must be "ip", "ip4" or "ip6" followed by a
+// colon and a protocol number or name and the addr must be a literal
+// IP address.
//
// Examples:
// Dial("ip4:1", "127.0.0.1")
// Dial("ip6:ospf", "::1")
//
+// For Unix networks, the addr must be a file system path.
func Dial(net, addr string) (Conn, error) {
return DialOpt(addr, dialNetwork(net))
}
-func netFromOptions(opts []DialOption) string {
- for _, opt := range opts {
- if p, ok := opt.(dialNetwork); ok {
- return string(p)
- }
- }
- return "tcp"
-}
-
-func deadlineFromOptions(opts []DialOption) time.Time {
- for _, opt := range opts {
- if d, ok := opt.(dialDeadline); ok {
- return time.Time(d)
- }
- }
- return noDeadline
-}
-
-var noLocalAddr Addr // nil
-
-func localAddrFromOptions(opts []DialOption) Addr {
- for _, opt := range opts {
- if o, ok := opt.(localAddrOption); ok {
- return o.la
- }
- }
- return noLocalAddr
-}
-
// DialOpt dials addr using the provided options.
// If no options are provided, DialOpt(addr) is equivalent
// to Dial("tcp", addr). See Dial for the syntax of addr.
func DialOpt(addr string, opts ...DialOption) (Conn, error) {
- net := netFromOptions(opts)
- deadline := deadlineFromOptions(opts)
- la := localAddrFromOptions(opts)
- ra, err := resolveAddr("dial", net, addr, deadline)
+ var o dialOpts
+ for _, opt := range opts {
+ opt.setDialOpt(&o)
+ }
+ ra, err := resolveAddr("dial", o.net(), addr, o.deadline)
if err != nil {
return nil, err
}
- return dial(net, addr, la, ra, deadline)
+ return dial(o.net(), addr, o.localAddr, ra, o.deadline)
}
func dial(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
@@ -274,7 +285,6 @@ func dialTimeoutRace(net, addr string, timeout time.Duration) (Conn, error) {
case p := <-ch:
return p.Conn, p.error
}
- panic("unreachable")
}
type stringAddr struct {
@@ -285,8 +295,9 @@ func (a stringAddr) Network() string { return a.net }
func (a stringAddr) String() string { return a.addr }
// Listen announces on the local network address laddr.
-// The network string net must be a stream-oriented network:
-// "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
+// The network net must be a stream-oriented network: "tcp", "tcp4",
+// "tcp6", "unix" or "unixpacket".
+// See Dial for the syntax of laddr.
func Listen(net, laddr string) (Listener, error) {
la, err := resolveAddr("listen", net, laddr, noDeadline)
if err != nil {
@@ -302,8 +313,9 @@ func Listen(net, laddr string) (Listener, error) {
}
// ListenPacket announces on the local network address laddr.
-// The network string net must be a packet-oriented network:
-// "udp", "udp4", "udp6", "ip", "ip4", "ip6" or "unixgram".
+// The network net must be a packet-oriented network: "udp", "udp4",
+// "udp6", "ip", "ip4", "ip6" or "unixgram".
+// See Dial for the syntax of laddr.
func ListenPacket(net, laddr string) (PacketConn, error) {
la, err := resolveAddr("listen", net, laddr, noDeadline)
if err != nil {
diff --git a/src/pkg/net/dial_test.go b/src/pkg/net/dial_test.go
index 2303e8fa4..098df738b 100644
--- a/src/pkg/net/dial_test.go
+++ b/src/pkg/net/dial_test.go
@@ -28,12 +28,18 @@ func newLocalListener(t *testing.T) Listener {
}
func TestDialTimeout(t *testing.T) {
+ origBacklog := listenerBacklog
+ defer func() {
+ listenerBacklog = origBacklog
+ }()
+ listenerBacklog = 1
+
ln := newLocalListener(t)
defer ln.Close()
errc := make(chan error)
- numConns := listenerBacklog + 10
+ numConns := listenerBacklog + 100
// TODO(bradfitz): It's hard to test this in a portable
// way. This is unfortunate, but works for now.
diff --git a/src/pkg/net/empty.c b/src/pkg/net/empty.c
new file mode 100644
index 000000000..a515c2fe2
--- /dev/null
+++ b/src/pkg/net/empty.c
@@ -0,0 +1,8 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is required to prevent compiler errors
+// when the package built with CGO_ENABLED=0.
+// Otherwise the compiler says:
+// pkg/net/fd_poll_runtime.go:15: missing function body
diff --git a/src/pkg/net/fd_darwin.go b/src/pkg/net/fd_darwin.go
deleted file mode 100644
index 382465ba6..000000000
--- a/src/pkg/net/fd_darwin.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// 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.
-
-// Waiting for FDs via kqueue/kevent.
-
-package net
-
-import (
- "errors"
- "os"
- "syscall"
-)
-
-type pollster struct {
- kq int
- eventbuf [10]syscall.Kevent_t
- events []syscall.Kevent_t
-
- // An event buffer for AddFD/DelFD.
- // Must hold pollServer lock.
- kbuf [1]syscall.Kevent_t
-}
-
-func newpollster() (p *pollster, err error) {
- p = new(pollster)
- if p.kq, err = syscall.Kqueue(); err != nil {
- return nil, os.NewSyscallError("kqueue", err)
- }
- syscall.CloseOnExec(p.kq)
- p.events = p.eventbuf[0:0]
- return p, nil
-}
-
-// First return value is whether the pollServer should be woken up.
-// This version always returns false.
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
- // pollServer is locked.
-
- var kmode int
- if mode == 'r' {
- kmode = syscall.EVFILT_READ
- } else {
- kmode = syscall.EVFILT_WRITE
- }
- ev := &p.kbuf[0]
- // EV_ADD - add event to kqueue list
- // EV_RECEIPT - generate fake EV_ERROR as result of add,
- // rather than waiting for real event
- // EV_ONESHOT - delete the event the first time it triggers
- flags := syscall.EV_ADD | syscall.EV_RECEIPT
- if !repeat {
- flags |= syscall.EV_ONESHOT
- }
- syscall.SetKevent(ev, fd, kmode, flags)
-
- n, err := syscall.Kevent(p.kq, p.kbuf[:], p.kbuf[:], nil)
- if err != nil {
- return false, os.NewSyscallError("kevent", err)
- }
- if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
- return false, errors.New("kqueue phase error")
- }
- if ev.Data != 0 {
- return false, syscall.Errno(ev.Data)
- }
- return false, nil
-}
-
-// Return value is whether the pollServer should be woken up.
-// This version always returns false.
-func (p *pollster) DelFD(fd int, mode int) bool {
- // pollServer is locked.
-
- var kmode int
- if mode == 'r' {
- kmode = syscall.EVFILT_READ
- } else {
- kmode = syscall.EVFILT_WRITE
- }
- ev := &p.kbuf[0]
- // EV_DELETE - delete event from kqueue list
- // EV_RECEIPT - generate fake EV_ERROR as result of add,
- // rather than waiting for real event
- syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE|syscall.EV_RECEIPT)
- syscall.Kevent(p.kq, p.kbuf[0:], p.kbuf[0:], nil)
- return false
-}
-
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
- var t *syscall.Timespec
- for len(p.events) == 0 {
- if nsec > 0 {
- if t == nil {
- t = new(syscall.Timespec)
- }
- *t = syscall.NsecToTimespec(nsec)
- }
-
- s.Unlock()
- n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
- s.Lock()
-
- if err != nil {
- if err == syscall.EINTR {
- continue
- }
- return -1, 0, os.NewSyscallError("kevent", nil)
- }
- if n == 0 {
- return -1, 0, nil
- }
- p.events = p.eventbuf[:n]
- }
- ev := &p.events[0]
- p.events = p.events[1:]
- fd = int(ev.Ident)
- if ev.Filter == syscall.EVFILT_READ {
- mode = 'r'
- } else {
- mode = 'w'
- }
- return fd, mode, nil
-}
-
-func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/src/pkg/net/fd_linux.go b/src/pkg/net/fd_linux.go
deleted file mode 100644
index 03679196d..000000000
--- a/src/pkg/net/fd_linux.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// 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.
-
-// Waiting for FDs via epoll(7).
-
-package net
-
-import (
- "os"
- "syscall"
-)
-
-const (
- readFlags = syscall.EPOLLIN | syscall.EPOLLRDHUP
- writeFlags = syscall.EPOLLOUT
-)
-
-type pollster struct {
- epfd int
-
- // Events we're already waiting for
- // Must hold pollServer lock
- events map[int]uint32
-
- // An event buffer for EpollWait.
- // Used without a lock, may only be used by WaitFD.
- waitEventBuf [10]syscall.EpollEvent
- waitEvents []syscall.EpollEvent
-
- // An event buffer for EpollCtl, to avoid a malloc.
- // Must hold pollServer lock.
- ctlEvent syscall.EpollEvent
-}
-
-func newpollster() (p *pollster, err error) {
- p = new(pollster)
- if p.epfd, err = syscall.EpollCreate1(syscall.EPOLL_CLOEXEC); err != nil {
- if err != syscall.ENOSYS {
- return nil, os.NewSyscallError("epoll_create1", err)
- }
- // The arg to epoll_create is a hint to the kernel
- // about the number of FDs we will care about.
- // We don't know, and since 2.6.8 the kernel ignores it anyhow.
- if p.epfd, err = syscall.EpollCreate(16); err != nil {
- return nil, os.NewSyscallError("epoll_create", err)
- }
- syscall.CloseOnExec(p.epfd)
- }
- p.events = make(map[int]uint32)
- return p, nil
-}
-
-// First return value is whether the pollServer should be woken up.
-// This version always returns false.
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
- // pollServer is locked.
-
- var already bool
- p.ctlEvent.Fd = int32(fd)
- p.ctlEvent.Events, already = p.events[fd]
- if !repeat {
- p.ctlEvent.Events |= syscall.EPOLLONESHOT
- }
- if mode == 'r' {
- p.ctlEvent.Events |= readFlags
- } else {
- p.ctlEvent.Events |= writeFlags
- }
-
- var op int
- if already {
- op = syscall.EPOLL_CTL_MOD
- } else {
- op = syscall.EPOLL_CTL_ADD
- }
- if err := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); err != nil {
- return false, os.NewSyscallError("epoll_ctl", err)
- }
- p.events[fd] = p.ctlEvent.Events
- return false, nil
-}
-
-func (p *pollster) StopWaiting(fd int, bits uint) {
- // pollServer is locked.
-
- events, already := p.events[fd]
- if !already {
- // The fd returned by the kernel may have been
- // cancelled already; return silently.
- return
- }
-
- // If syscall.EPOLLONESHOT is not set, the wait
- // is a repeating wait, so don't change it.
- if events&syscall.EPOLLONESHOT == 0 {
- return
- }
-
- // Disable the given bits.
- // If we're still waiting for other events, modify the fd
- // event in the kernel. Otherwise, delete it.
- events &= ^uint32(bits)
- if int32(events)&^syscall.EPOLLONESHOT != 0 {
- p.ctlEvent.Fd = int32(fd)
- p.ctlEvent.Events = events
- if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); err != nil {
- print("Epoll modify fd=", fd, ": ", err.Error(), "\n")
- }
- p.events[fd] = events
- } else {
- if err := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); err != nil {
- print("Epoll delete fd=", fd, ": ", err.Error(), "\n")
- }
- delete(p.events, fd)
- }
-}
-
-// Return value is whether the pollServer should be woken up.
-// This version always returns false.
-func (p *pollster) DelFD(fd int, mode int) bool {
- // pollServer is locked.
-
- if mode == 'r' {
- p.StopWaiting(fd, readFlags)
- } else {
- p.StopWaiting(fd, writeFlags)
- }
-
- // Discard any queued up events.
- i := 0
- for i < len(p.waitEvents) {
- if fd == int(p.waitEvents[i].Fd) {
- copy(p.waitEvents[i:], p.waitEvents[i+1:])
- p.waitEvents = p.waitEvents[:len(p.waitEvents)-1]
- } else {
- i++
- }
- }
- return false
-}
-
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
- for len(p.waitEvents) == 0 {
- var msec int = -1
- if nsec > 0 {
- msec = int((nsec + 1e6 - 1) / 1e6)
- }
-
- s.Unlock()
- n, err := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
- s.Lock()
-
- if err != nil {
- if err == syscall.EAGAIN || err == syscall.EINTR {
- continue
- }
- return -1, 0, os.NewSyscallError("epoll_wait", err)
- }
- if n == 0 {
- return -1, 0, nil
- }
- p.waitEvents = p.waitEventBuf[0:n]
- }
-
- ev := &p.waitEvents[0]
- p.waitEvents = p.waitEvents[1:]
-
- fd = int(ev.Fd)
-
- if ev.Events&writeFlags != 0 {
- p.StopWaiting(fd, writeFlags)
- return fd, 'w', nil
- }
- if ev.Events&readFlags != 0 {
- p.StopWaiting(fd, readFlags)
- return fd, 'r', nil
- }
-
- // Other events are error conditions - wake whoever is waiting.
- events, _ := p.events[fd]
- if events&writeFlags != 0 {
- p.StopWaiting(fd, writeFlags)
- return fd, 'w', nil
- }
- p.StopWaiting(fd, readFlags)
- return fd, 'r', nil
-}
-
-func (p *pollster) Close() error {
- return os.NewSyscallError("close", syscall.Close(p.epfd))
-}
diff --git a/src/pkg/net/fd_poll_runtime.go b/src/pkg/net/fd_poll_runtime.go
new file mode 100644
index 000000000..e3b4f7e46
--- /dev/null
+++ b/src/pkg/net/fd_poll_runtime.go
@@ -0,0 +1,119 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin linux
+
+package net
+
+import (
+ "sync"
+ "syscall"
+ "time"
+)
+
+func runtime_pollServerInit()
+func runtime_pollOpen(fd int) (uintptr, int)
+func runtime_pollClose(ctx uintptr)
+func runtime_pollWait(ctx uintptr, mode int) int
+func runtime_pollReset(ctx uintptr, mode int) int
+func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
+func runtime_pollUnblock(ctx uintptr)
+
+var canCancelIO = true // used for testing current package
+
+type pollDesc struct {
+ runtimeCtx uintptr
+}
+
+var serverInit sync.Once
+
+func sysInit() {
+}
+
+func (pd *pollDesc) Init(fd *netFD) error {
+ serverInit.Do(runtime_pollServerInit)
+ ctx, errno := runtime_pollOpen(fd.sysfd)
+ if errno != 0 {
+ return syscall.Errno(errno)
+ }
+ pd.runtimeCtx = ctx
+ return nil
+}
+
+func (pd *pollDesc) Close() {
+ runtime_pollClose(pd.runtimeCtx)
+}
+
+func (pd *pollDesc) Lock() {
+}
+
+func (pd *pollDesc) Unlock() {
+}
+
+func (pd *pollDesc) Wakeup() {
+}
+
+// Evict evicts fd from the pending list, unblocking any I/O running on fd.
+// Return value is whether the pollServer should be woken up.
+func (pd *pollDesc) Evict() bool {
+ runtime_pollUnblock(pd.runtimeCtx)
+ return false
+}
+
+func (pd *pollDesc) PrepareRead() error {
+ res := runtime_pollReset(pd.runtimeCtx, 'r')
+ return convertErr(res)
+}
+
+func (pd *pollDesc) PrepareWrite() error {
+ res := runtime_pollReset(pd.runtimeCtx, 'w')
+ return convertErr(res)
+}
+
+func (pd *pollDesc) WaitRead() error {
+ res := runtime_pollWait(pd.runtimeCtx, 'r')
+ return convertErr(res)
+}
+
+func (pd *pollDesc) WaitWrite() error {
+ res := runtime_pollWait(pd.runtimeCtx, 'w')
+ return convertErr(res)
+}
+
+func convertErr(res int) error {
+ switch res {
+ case 0:
+ return nil
+ case 1:
+ return errClosing
+ case 2:
+ return errTimeout
+ }
+ panic("unreachable")
+}
+
+func setReadDeadline(fd *netFD, t time.Time) error {
+ return setDeadlineImpl(fd, t, 'r')
+}
+
+func setWriteDeadline(fd *netFD, t time.Time) error {
+ return setDeadlineImpl(fd, t, 'w')
+}
+
+func setDeadline(fd *netFD, t time.Time) error {
+ return setDeadlineImpl(fd, t, 'r'+'w')
+}
+
+func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
+ d := t.UnixNano()
+ if t.IsZero() {
+ d = 0
+ }
+ if err := fd.incref(false); err != nil {
+ return err
+ }
+ runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
+ fd.decref()
+ return nil
+}
diff --git a/src/pkg/net/fd_poll_unix.go b/src/pkg/net/fd_poll_unix.go
new file mode 100644
index 000000000..307e577e9
--- /dev/null
+++ b/src/pkg/net/fd_poll_unix.go
@@ -0,0 +1,360 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd netbsd openbsd
+
+package net
+
+import (
+ "os"
+ "runtime"
+ "sync"
+ "syscall"
+ "time"
+)
+
+// A pollServer helps FDs determine when to retry a non-blocking
+// read or write after they get EAGAIN. When an FD needs to wait,
+// 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 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
+// and sets a closing flag. Only when the last reference is removed
+// will the fd be closed.
+
+type pollServer struct {
+ pr, pw *os.File
+ poll *pollster // low-level OS hooks
+ sync.Mutex // controls pending and deadline
+ pending map[int]*pollDesc
+ deadline int64 // next deadline (nsec since 1970)
+}
+
+// A pollDesc contains netFD state related to pollServer.
+type pollDesc struct {
+ // immutable after Init()
+ pollServer *pollServer
+ sysfd int
+ cr, cw chan error
+
+ // mutable, protected by pollServer mutex
+ closing bool
+ ncr, ncw int
+
+ // mutable, safe for concurrent access
+ rdeadline, wdeadline deadline
+}
+
+func newPollServer() (s *pollServer, err error) {
+ s = new(pollServer)
+ if s.pr, s.pw, err = os.Pipe(); err != nil {
+ return nil, err
+ }
+ if err = syscall.SetNonblock(int(s.pr.Fd()), true); err != nil {
+ goto Errno
+ }
+ if err = syscall.SetNonblock(int(s.pw.Fd()), true); err != nil {
+ goto Errno
+ }
+ if s.poll, err = newpollster(); err != nil {
+ goto Error
+ }
+ if _, err = s.poll.AddFD(int(s.pr.Fd()), 'r', true); err != nil {
+ s.poll.Close()
+ goto Error
+ }
+ s.pending = make(map[int]*pollDesc)
+ go s.Run()
+ return s, nil
+
+Errno:
+ err = &os.PathError{
+ Op: "setnonblock",
+ Path: s.pr.Name(),
+ Err: err,
+ }
+Error:
+ s.pr.Close()
+ s.pw.Close()
+ return nil, err
+}
+
+func (s *pollServer) AddFD(pd *pollDesc, mode int) error {
+ s.Lock()
+ intfd := pd.sysfd
+ if intfd < 0 || pd.closing {
+ // fd closed underfoot
+ s.Unlock()
+ return errClosing
+ }
+
+ var t int64
+ key := intfd << 1
+ if mode == 'r' {
+ pd.ncr++
+ t = pd.rdeadline.value()
+ } else {
+ pd.ncw++
+ key++
+ t = pd.wdeadline.value()
+ }
+ s.pending[key] = pd
+ doWakeup := false
+ if t > 0 && (s.deadline == 0 || t < s.deadline) {
+ s.deadline = t
+ doWakeup = true
+ }
+
+ wake, err := s.poll.AddFD(intfd, mode, false)
+ s.Unlock()
+ if err != nil {
+ return err
+ }
+ if wake || doWakeup {
+ s.Wakeup()
+ }
+ return nil
+}
+
+// Evict evicts pd from the pending list, unblocking
+// any I/O running on pd. The caller must have locked
+// pollserver.
+// Return value is whether the pollServer should be woken up.
+func (s *pollServer) Evict(pd *pollDesc) bool {
+ pd.closing = true
+ doWakeup := false
+ if s.pending[pd.sysfd<<1] == pd {
+ s.WakeFD(pd, 'r', errClosing)
+ if s.poll.DelFD(pd.sysfd, 'r') {
+ doWakeup = true
+ }
+ delete(s.pending, pd.sysfd<<1)
+ }
+ if s.pending[pd.sysfd<<1|1] == pd {
+ s.WakeFD(pd, 'w', errClosing)
+ if s.poll.DelFD(pd.sysfd, 'w') {
+ doWakeup = true
+ }
+ delete(s.pending, pd.sysfd<<1|1)
+ }
+ return doWakeup
+}
+
+var wakeupbuf [1]byte
+
+func (s *pollServer) Wakeup() { s.pw.Write(wakeupbuf[0:]) }
+
+func (s *pollServer) LookupFD(fd int, mode int) *pollDesc {
+ key := fd << 1
+ if mode == 'w' {
+ key++
+ }
+ netfd, ok := s.pending[key]
+ if !ok {
+ return nil
+ }
+ delete(s.pending, key)
+ return netfd
+}
+
+func (s *pollServer) WakeFD(pd *pollDesc, mode int, err error) {
+ if mode == 'r' {
+ for pd.ncr > 0 {
+ pd.ncr--
+ pd.cr <- err
+ }
+ } else {
+ for pd.ncw > 0 {
+ pd.ncw--
+ pd.cw <- err
+ }
+ }
+}
+
+func (s *pollServer) CheckDeadlines() {
+ now := time.Now().UnixNano()
+ // TODO(rsc): This will need to be handled more efficiently,
+ // probably with a heap indexed by wakeup time.
+
+ var nextDeadline int64
+ for key, pd := range s.pending {
+ var t int64
+ var mode int
+ if key&1 == 0 {
+ mode = 'r'
+ } else {
+ mode = 'w'
+ }
+ if mode == 'r' {
+ t = pd.rdeadline.value()
+ } else {
+ t = pd.wdeadline.value()
+ }
+ if t > 0 {
+ if t <= now {
+ delete(s.pending, key)
+ s.poll.DelFD(pd.sysfd, mode)
+ s.WakeFD(pd, mode, errTimeout)
+ } else if nextDeadline == 0 || t < nextDeadline {
+ nextDeadline = t
+ }
+ }
+ }
+ s.deadline = nextDeadline
+}
+
+func (s *pollServer) Run() {
+ var scratch [100]byte
+ s.Lock()
+ defer s.Unlock()
+ for {
+ var timeout int64 // nsec to wait for or 0 for none
+ if s.deadline > 0 {
+ timeout = s.deadline - time.Now().UnixNano()
+ if timeout <= 0 {
+ s.CheckDeadlines()
+ continue
+ }
+ }
+ fd, mode, err := s.poll.WaitFD(s, timeout)
+ if err != nil {
+ print("pollServer WaitFD: ", err.Error(), "\n")
+ return
+ }
+ if fd < 0 {
+ // Timeout happened.
+ s.CheckDeadlines()
+ continue
+ }
+ if fd == int(s.pr.Fd()) {
+ // Drain our wakeup pipe (we could loop here,
+ // but it's unlikely that there are more than
+ // len(scratch) wakeup calls).
+ s.pr.Read(scratch[0:])
+ s.CheckDeadlines()
+ } else {
+ pd := s.LookupFD(fd, mode)
+ if pd == nil {
+ // This can happen because the WaitFD runs without
+ // holding s's lock, so there might be a pending wakeup
+ // for an fd that has been evicted. No harm done.
+ continue
+ }
+ s.WakeFD(pd, mode, nil)
+ }
+ }
+}
+
+func (pd *pollDesc) Close() {
+}
+
+func (pd *pollDesc) Lock() {
+ pd.pollServer.Lock()
+}
+
+func (pd *pollDesc) Unlock() {
+ pd.pollServer.Unlock()
+}
+
+func (pd *pollDesc) Wakeup() {
+ pd.pollServer.Wakeup()
+}
+
+func (pd *pollDesc) PrepareRead() error {
+ if pd.rdeadline.expired() {
+ return errTimeout
+ }
+ return nil
+}
+
+func (pd *pollDesc) PrepareWrite() error {
+ if pd.wdeadline.expired() {
+ return errTimeout
+ }
+ return nil
+}
+
+func (pd *pollDesc) WaitRead() error {
+ err := pd.pollServer.AddFD(pd, 'r')
+ if err == nil {
+ err = <-pd.cr
+ }
+ return err
+}
+
+func (pd *pollDesc) WaitWrite() error {
+ err := pd.pollServer.AddFD(pd, 'w')
+ if err == nil {
+ err = <-pd.cw
+ }
+ return err
+}
+
+func (pd *pollDesc) Evict() bool {
+ return pd.pollServer.Evict(pd)
+}
+
+// Spread network FDs over several pollServers.
+
+var pollMaxN int
+var pollservers []*pollServer
+var startServersOnce []func()
+
+var canCancelIO = true // used for testing current package
+
+func sysInit() {
+ 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(k int) {
+ p, err := newPollServer()
+ if err != nil {
+ panic(err)
+ }
+ pollservers[k] = p
+}
+
+func (pd *pollDesc) Init(fd *netFD) error {
+ pollN := runtime.GOMAXPROCS(0)
+ if pollN > pollMaxN {
+ pollN = pollMaxN
+ }
+ k := fd.sysfd % pollN
+ startServersOnce[k]()
+ pd.sysfd = fd.sysfd
+ pd.pollServer = pollservers[k]
+ pd.cr = make(chan error, 1)
+ pd.cw = make(chan error, 1)
+ return nil
+}
+
+// TODO(dfc) these unused error returns could be removed
+
+func setReadDeadline(fd *netFD, t time.Time) error {
+ fd.pd.rdeadline.setTime(t)
+ return nil
+}
+
+func setWriteDeadline(fd *netFD, t time.Time) error {
+ fd.pd.wdeadline.setTime(t)
+ return nil
+}
+
+func setDeadline(fd *netFD, t time.Time) error {
+ setReadDeadline(fd, t)
+ setWriteDeadline(fd, t)
+ return nil
+}
diff --git a/src/pkg/net/fd_unix.go b/src/pkg/net/fd_unix.go
index 0540df825..2b418a868 100644
--- a/src/pkg/net/fd_unix.go
+++ b/src/pkg/net/fd_unix.go
@@ -9,7 +9,6 @@ package net
import (
"io"
"os"
- "runtime"
"sync"
"syscall"
"time"
@@ -21,7 +20,7 @@ type netFD struct {
sysmu sync.Mutex
sysref int
- // must lock both sysmu and pollserver to write
+ // must lock both sysmu and pollDesc to write
// can lock either to read
closing bool
@@ -31,8 +30,6 @@ type netFD struct {
sotype int
isConnected bool
sysfile *os.File
- cr chan error
- cw chan error
net string
laddr Addr
raddr Addr
@@ -40,255 +37,8 @@ type netFD struct {
// serialize access to Read and Write methods
rio, wio sync.Mutex
- // read and write deadlines
- rdeadline, wdeadline deadline
-
- // 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,
-// 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 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
-// and sets a closing flag. Only when the last reference is removed
-// will the fd be closed.
-
-type pollServer struct {
- pr, pw *os.File
- poll *pollster // low-level OS hooks
- sync.Mutex // controls pending and deadline
- pending map[int]*netFD
- deadline int64 // next deadline (nsec since 1970)
-}
-
-func (s *pollServer) AddFD(fd *netFD, mode int) error {
- s.Lock()
- intfd := fd.sysfd
- if intfd < 0 || fd.closing {
- // fd closed underfoot
- s.Unlock()
- return errClosing
- }
-
- var t int64
- key := intfd << 1
- if mode == 'r' {
- fd.ncr++
- t = fd.rdeadline.value()
- } else {
- fd.ncw++
- key++
- t = fd.wdeadline.value()
- }
- s.pending[key] = fd
- doWakeup := false
- if t > 0 && (s.deadline == 0 || t < s.deadline) {
- s.deadline = t
- doWakeup = true
- }
-
- wake, err := s.poll.AddFD(intfd, mode, false)
- s.Unlock()
- if err != nil {
- return &OpError{"addfd", fd.net, fd.laddr, err}
- }
- if wake || doWakeup {
- s.Wakeup()
- }
- return nil
-}
-
-// Evict evicts fd from the pending list, unblocking
-// any I/O running on fd. The caller must have locked
-// pollserver.
-// Return value is whether the pollServer should be woken up.
-func (s *pollServer) Evict(fd *netFD) bool {
- doWakeup := false
- if s.pending[fd.sysfd<<1] == fd {
- s.WakeFD(fd, 'r', errClosing)
- if s.poll.DelFD(fd.sysfd, 'r') {
- doWakeup = true
- }
- delete(s.pending, fd.sysfd<<1)
- }
- if s.pending[fd.sysfd<<1|1] == fd {
- s.WakeFD(fd, 'w', errClosing)
- if s.poll.DelFD(fd.sysfd, 'w') {
- doWakeup = true
- }
- delete(s.pending, fd.sysfd<<1|1)
- }
- return doWakeup
-}
-
-var wakeupbuf [1]byte
-
-func (s *pollServer) Wakeup() { s.pw.Write(wakeupbuf[0:]) }
-
-func (s *pollServer) LookupFD(fd int, mode int) *netFD {
- key := fd << 1
- if mode == 'w' {
- key++
- }
- netfd, ok := s.pending[key]
- if !ok {
- return nil
- }
- delete(s.pending, key)
- return netfd
-}
-
-func (s *pollServer) WakeFD(fd *netFD, mode int, err error) {
- if mode == 'r' {
- for fd.ncr > 0 {
- fd.ncr--
- fd.cr <- err
- }
- } else {
- for fd.ncw > 0 {
- fd.ncw--
- fd.cw <- err
- }
- }
-}
-
-func (s *pollServer) CheckDeadlines() {
- now := time.Now().UnixNano()
- // TODO(rsc): This will need to be handled more efficiently,
- // probably with a heap indexed by wakeup time.
-
- var nextDeadline int64
- for key, fd := range s.pending {
- var t int64
- var mode int
- if key&1 == 0 {
- mode = 'r'
- } else {
- mode = 'w'
- }
- if mode == 'r' {
- t = fd.rdeadline.value()
- } else {
- t = fd.wdeadline.value()
- }
- if t > 0 {
- if t <= now {
- delete(s.pending, key)
- s.poll.DelFD(fd.sysfd, mode)
- s.WakeFD(fd, mode, errTimeout)
- } else if nextDeadline == 0 || t < nextDeadline {
- nextDeadline = t
- }
- }
- }
- s.deadline = nextDeadline
-}
-
-func (s *pollServer) Run() {
- var scratch [100]byte
- s.Lock()
- defer s.Unlock()
- for {
- var timeout int64 // nsec to wait for or 0 for none
- if s.deadline > 0 {
- timeout = s.deadline - time.Now().UnixNano()
- if timeout <= 0 {
- s.CheckDeadlines()
- continue
- }
- }
- fd, mode, err := s.poll.WaitFD(s, timeout)
- if err != nil {
- print("pollServer WaitFD: ", err.Error(), "\n")
- return
- }
- if fd < 0 {
- // Timeout happened.
- s.CheckDeadlines()
- continue
- }
- if fd == int(s.pr.Fd()) {
- // Drain our wakeup pipe (we could loop here,
- // but it's unlikely that there are more than
- // len(scratch) wakeup calls).
- s.pr.Read(scratch[0:])
- s.CheckDeadlines()
- } else {
- netfd := s.LookupFD(fd, mode)
- if netfd == nil {
- // This can happen because the WaitFD runs without
- // holding s's lock, so there might be a pending wakeup
- // for an fd that has been evicted. No harm done.
- continue
- }
- s.WakeFD(netfd, mode, nil)
- }
- }
-}
-
-func (s *pollServer) WaitRead(fd *netFD) error {
- err := s.AddFD(fd, 'r')
- if err == nil {
- err = <-fd.cr
- }
- return err
-}
-
-func (s *pollServer) WaitWrite(fd *netFD) error {
- err := s.AddFD(fd, 'w')
- if err == nil {
- err = <-fd.cw
- }
- return err
-}
-
-// Network FD methods.
-// Spread network FDs over several pollServers.
-
-var pollMaxN int
-var pollservers []*pollServer
-var startServersOnce []func()
-
-var canCancelIO = true // used for testing current package
-
-func sysInit() {
- 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(k int) {
- p, err := newPollServer()
- if err != nil {
- panic(err)
- }
- pollservers[k] = p
-}
-
-func server(fd int) *pollServer {
- pollN := runtime.GOMAXPROCS(0)
- if pollN > pollMaxN {
- pollN = pollMaxN
- }
- k := fd % pollN
- startServersOnce[k]()
- return pollservers[k]
+ pd pollDesc
}
func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
@@ -307,9 +57,9 @@ func newFD(fd, family, sotype int, net string) (*netFD, error) {
sotype: sotype,
net: net,
}
- netfd.cr = make(chan error, 1)
- netfd.cw = make(chan error, 1)
- netfd.pollServer = server(fd)
+ if err := netfd.pd.Init(netfd); err != nil {
+ return nil, err
+ }
return netfd, nil
}
@@ -331,25 +81,28 @@ func (fd *netFD) name() string {
}
func (fd *netFD) connect(ra syscall.Sockaddr) error {
- err := syscall.Connect(fd.sysfd, ra)
- if err == syscall.EINPROGRESS {
- if err = fd.pollServer.WaitWrite(fd); err != nil {
- return err
+ fd.wio.Lock()
+ defer fd.wio.Unlock()
+ if err := fd.pd.PrepareWrite(); err != nil {
+ return err
+ }
+ for {
+ err := syscall.Connect(fd.sysfd, ra)
+ if err == nil || err == syscall.EISCONN {
+ break
}
- var e int
- e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
- if err != nil {
- return os.NewSyscallError("getsockopt", err)
+ if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR {
+ return err
}
- if e != 0 {
- err = syscall.Errno(e)
+ if err = fd.pd.WaitWrite(); err != nil {
+ return err
}
}
- return err
+ return nil
}
// Add a reference to this fd.
-// If closing==true, pollserver must be locked; mark the fd as closing.
+// If closing==true, pollDesc must be locked; mark the fd as closing.
// Returns an error if the fd cannot be used.
func (fd *netFD) incref(closing bool) error {
fd.sysmu.Lock()
@@ -371,6 +124,9 @@ func (fd *netFD) decref() {
fd.sysmu.Lock()
fd.sysref--
if fd.closing && fd.sysref == 0 && fd.sysfile != nil {
+ // Poller may want to unregister fd in readiness notification mechanism,
+ // so this must be executed before sysfile.Close().
+ fd.pd.Close()
fd.sysfile.Close()
fd.sysfile = nil
fd.sysfd = -1
@@ -379,21 +135,21 @@ func (fd *netFD) decref() {
}
func (fd *netFD) Close() error {
- fd.pollServer.Lock() // needed for both fd.incref(true) and pollserver.Evict
+ fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
if err := fd.incref(true); err != nil {
- fd.pollServer.Unlock()
+ fd.pd.Unlock()
return err
}
// Unblock any I/O. Once it all unblocks and returns,
// so that it cannot be referring to fd.sysfd anymore,
// 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.
- doWakeup := fd.pollServer.Evict(fd)
- fd.pollServer.Unlock()
+ // attempts to block in the pollDesc will return errClosing.
+ doWakeup := fd.pd.Evict()
+ fd.pd.Unlock()
fd.decref()
if doWakeup {
- fd.pollServer.Wakeup()
+ fd.pd.Wakeup()
}
return nil
}
@@ -425,16 +181,15 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
return 0, err
}
defer fd.decref()
+ if err := fd.pd.PrepareRead(); err != nil {
+ return 0, &OpError{"read", fd.net, fd.raddr, err}
+ }
for {
- if fd.rdeadline.expired() {
- err = errTimeout
- break
- }
n, err = syscall.Read(int(fd.sysfd), p)
if err != nil {
n = 0
if err == syscall.EAGAIN {
- if err = fd.pollServer.WaitRead(fd); err == nil {
+ if err = fd.pd.WaitRead(); err == nil {
continue
}
}
@@ -455,16 +210,15 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
return 0, nil, err
}
defer fd.decref()
+ if err := fd.pd.PrepareRead(); err != nil {
+ return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
+ }
for {
- if fd.rdeadline.expired() {
- err = errTimeout
- break
- }
n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
if err != nil {
n = 0
if err == syscall.EAGAIN {
- if err = fd.pollServer.WaitRead(fd); err == nil {
+ if err = fd.pd.WaitRead(); err == nil {
continue
}
}
@@ -485,16 +239,15 @@ func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
return 0, 0, 0, nil, err
}
defer fd.decref()
+ if err := fd.pd.PrepareRead(); err != nil {
+ return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
+ }
for {
- if fd.rdeadline.expired() {
- err = errTimeout
- break
- }
n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
if err != nil {
// TODO(dfc) should n and oobn be set to 0
if err == syscall.EAGAIN {
- if err = fd.pollServer.WaitRead(fd); err == nil {
+ if err = fd.pd.WaitRead(); err == nil {
continue
}
}
@@ -522,11 +275,10 @@ func (fd *netFD) Write(p []byte) (nn int, err error) {
return 0, err
}
defer fd.decref()
+ if err := fd.pd.PrepareWrite(); err != nil {
+ return 0, &OpError{"write", fd.net, fd.raddr, err}
+ }
for {
- if fd.wdeadline.expired() {
- err = errTimeout
- break
- }
var n int
n, err = syscall.Write(int(fd.sysfd), p[nn:])
if n > 0 {
@@ -536,7 +288,7 @@ func (fd *netFD) Write(p []byte) (nn int, err error) {
break
}
if err == syscall.EAGAIN {
- if err = fd.pollServer.WaitWrite(fd); err == nil {
+ if err = fd.pd.WaitWrite(); err == nil {
continue
}
}
@@ -562,14 +314,13 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
return 0, err
}
defer fd.decref()
+ if err := fd.pd.PrepareWrite(); err != nil {
+ return 0, &OpError{"write", fd.net, fd.raddr, err}
+ }
for {
- if fd.wdeadline.expired() {
- err = errTimeout
- break
- }
err = syscall.Sendto(fd.sysfd, p, 0, sa)
if err == syscall.EAGAIN {
- if err = fd.pollServer.WaitWrite(fd); err == nil {
+ if err = fd.pd.WaitWrite(); err == nil {
continue
}
}
@@ -590,14 +341,13 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
return 0, 0, err
}
defer fd.decref()
+ if err := fd.pd.PrepareWrite(); err != nil {
+ return 0, 0, &OpError{"write", fd.net, fd.raddr, err}
+ }
for {
- if fd.wdeadline.expired() {
- err = errTimeout
- break
- }
err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
if err == syscall.EAGAIN {
- if err = fd.pollServer.WaitWrite(fd); err == nil {
+ if err = fd.pd.WaitWrite(); err == nil {
continue
}
}
@@ -613,6 +363,8 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
}
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
+ fd.rio.Lock()
+ defer fd.rio.Unlock()
if err := fd.incref(false); err != nil {
return nil, err
}
@@ -620,11 +372,14 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
var s int
var rsa syscall.Sockaddr
+ if err = fd.pd.PrepareRead(); err != nil {
+ return nil, &OpError{"accept", fd.net, fd.laddr, err}
+ }
for {
s, rsa, err = accept(fd.sysfd)
if err != nil {
if err == syscall.EAGAIN {
- if err = fd.pollServer.WaitRead(fd); err == nil {
+ if err = fd.pd.WaitRead(); err == nil {
continue
}
} else if err == syscall.ECONNABORTED {
diff --git a/src/pkg/net/http/client.go b/src/pkg/net/http/client.go
index 5ee0804c7..a34d47be1 100644
--- a/src/pkg/net/http/client.go
+++ b/src/pkg/net/http/client.go
@@ -19,12 +19,16 @@ import (
"strings"
)
-// A Client is an HTTP client. Its zero value (DefaultClient) is a usable client
-// that uses DefaultTransport.
+// A Client is an HTTP client. Its zero value (DefaultClient) is a
+// usable client that uses DefaultTransport.
//
-// The Client's Transport typically has internal state (cached
-// TCP connections), so Clients should be reused instead of created as
+// The Client's Transport typically has internal state (cached TCP
+// connections), so Clients should be reused instead of created as
// needed. Clients are safe for concurrent use by multiple goroutines.
+//
+// A Client is higher-level than a RoundTripper (such as Transport)
+// and additionally handles HTTP details such as cookies and
+// redirects.
type Client struct {
// Transport specifies the mechanism by which individual
// HTTP requests are made.
diff --git a/src/pkg/net/http/client_test.go b/src/pkg/net/http/client_test.go
index 88649bb16..d7d2c1879 100644
--- a/src/pkg/net/http/client_test.go
+++ b/src/pkg/net/http/client_test.go
@@ -51,11 +51,10 @@ func pedanticReadAll(r io.Reader) (b []byte, err error) {
return b, err
}
}
- panic("unreachable")
}
func TestClient(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(robotsTxtHandler)
defer ts.Close()
@@ -73,7 +72,7 @@ func TestClient(t *testing.T) {
}
func TestClientHead(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(robotsTxtHandler)
defer ts.Close()
@@ -96,7 +95,7 @@ func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err error)
}
func TestGetRequestFormat(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
tr := &recordingTransport{}
client := &Client{Transport: tr}
url := "http://dummy.faketld/"
@@ -113,7 +112,7 @@ func TestGetRequestFormat(t *testing.T) {
}
func TestPostRequestFormat(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
tr := &recordingTransport{}
client := &Client{Transport: tr}
@@ -140,7 +139,7 @@ func TestPostRequestFormat(t *testing.T) {
}
func TestPostFormRequestFormat(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
tr := &recordingTransport{}
client := &Client{Transport: tr}
@@ -182,7 +181,7 @@ func TestPostFormRequestFormat(t *testing.T) {
}
func TestRedirects(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
var ts *httptest.Server
ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
n, _ := strconv.Atoi(r.FormValue("n"))
@@ -256,7 +255,7 @@ func TestRedirects(t *testing.T) {
}
func TestPostRedirects(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
var log struct {
sync.Mutex
bytes.Buffer
@@ -374,7 +373,7 @@ func (j *TestJar) Cookies(u *url.URL) []*Cookie {
}
func TestRedirectCookiesOnRequest(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
var ts *httptest.Server
ts = httptest.NewServer(echoCookiesRedirectHandler)
defer ts.Close()
@@ -392,7 +391,7 @@ func TestRedirectCookiesOnRequest(t *testing.T) {
}
func TestRedirectCookiesJar(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
var ts *httptest.Server
ts = httptest.NewServer(echoCookiesRedirectHandler)
defer ts.Close()
@@ -429,7 +428,7 @@ func matchReturnedCookies(t *testing.T, expected, given []*Cookie) {
}
func TestJarCalls(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
pathSuffix := r.RequestURI[1:]
if r.RequestURI == "/nosetcookie" {
@@ -493,7 +492,7 @@ func (j *RecordingJar) logf(format string, args ...interface{}) {
}
func TestStreamingGet(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
say := make(chan string)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.(Flusher).Flush()
@@ -544,7 +543,7 @@ func (c *writeCountingConn) Write(p []byte) (int, error) {
// TestClientWrites verifies that client requests are buffered and we
// don't send a TCP packet per line of the http request + body.
func TestClientWrites(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
}))
defer ts.Close()
@@ -578,7 +577,7 @@ func TestClientWrites(t *testing.T) {
}
func TestClientInsecureTransport(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Write([]byte("Hello"))
}))
@@ -606,7 +605,7 @@ func TestClientInsecureTransport(t *testing.T) {
}
func TestClientErrorWithRequestURI(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
req, _ := NewRequest("GET", "http://localhost:1234/", nil)
req.RequestURI = "/this/field/is/illegal/and/should/error/"
_, err := DefaultClient.Do(req)
@@ -635,7 +634,7 @@ func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport {
}
func TestClientWithCorrectTLSServerName(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.TLS.ServerName != "127.0.0.1" {
t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName)
@@ -650,7 +649,7 @@ func TestClientWithCorrectTLSServerName(t *testing.T) {
}
func TestClientWithIncorrectTLSServerName(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
defer ts.Close()
@@ -668,7 +667,7 @@ func TestClientWithIncorrectTLSServerName(t *testing.T) {
// Verify Response.ContentLength is populated. http://golang.org/issue/4126
func TestClientHeadContentLength(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if v := r.FormValue("cl"); v != "" {
w.Header().Set("Content-Length", v)
diff --git a/src/pkg/net/http/example_test.go b/src/pkg/net/http/example_test.go
index 22073eaf7..eed3beeea 100644
--- a/src/pkg/net/http/example_test.go
+++ b/src/pkg/net/http/example_test.go
@@ -54,3 +54,8 @@ func ExampleFileServer() {
// we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}
+
+func ExampleStripPrefix() {
+ // we use StripPrefix so that /tmpfiles/somefile will access /tmp/somefile
+ http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
+}
diff --git a/src/pkg/net/http/export_test.go b/src/pkg/net/http/export_test.go
index a7bca20a0..3fc245326 100644
--- a/src/pkg/net/http/export_test.go
+++ b/src/pkg/net/http/export_test.go
@@ -54,3 +54,5 @@ func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
}
return &timeoutHandler{handler, f, ""}
}
+
+var DefaultUserAgent = defaultUserAgent
diff --git a/src/pkg/net/http/fcgi/child.go b/src/pkg/net/http/fcgi/child.go
index c8b9a33c8..60b794e07 100644
--- a/src/pkg/net/http/fcgi/child.go
+++ b/src/pkg/net/http/fcgi/child.go
@@ -10,10 +10,12 @@ import (
"errors"
"fmt"
"io"
+ "io/ioutil"
"net"
"net/http"
"net/http/cgi"
"os"
+ "strings"
"time"
)
@@ -152,20 +154,23 @@ func (c *child) serve() {
var errCloseConn = errors.New("fcgi: connection should be closed")
+var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+
func (c *child) handleRecord(rec *record) error {
req, ok := c.requests[rec.h.Id]
if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
// The spec says to ignore unknown request IDs.
return nil
}
- if ok && rec.h.Type == typeBeginRequest {
- // The server is trying to begin a request with the same ID
- // as an in-progress request. This is an error.
- return errors.New("fcgi: received ID that is already in-flight")
- }
switch rec.h.Type {
case typeBeginRequest:
+ if req != nil {
+ // The server is trying to begin a request with the same ID
+ // as an in-progress request. This is an error.
+ return errors.New("fcgi: received ID that is already in-flight")
+ }
+
var br beginRequest
if err := br.read(rec.content()); err != nil {
return err
@@ -175,6 +180,7 @@ func (c *child) handleRecord(rec *record) error {
return nil
}
c.requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
+ return nil
case typeParams:
// NOTE(eds): Technically a key-value pair can straddle the boundary
// between two packets. We buffer until we've received all parameters.
@@ -183,6 +189,7 @@ func (c *child) handleRecord(rec *record) error {
return nil
}
req.parseParams()
+ return nil
case typeStdin:
content := rec.content()
if req.pw == nil {
@@ -191,6 +198,8 @@ func (c *child) handleRecord(rec *record) error {
// body could be an io.LimitReader, but it shouldn't matter
// as long as both sides are behaving.
body, req.pw = io.Pipe()
+ } else {
+ body = emptyBody
}
go c.serveRequest(req, body)
}
@@ -201,24 +210,29 @@ func (c *child) handleRecord(rec *record) error {
} else if req.pw != nil {
req.pw.Close()
}
+ return nil
case typeGetValues:
values := map[string]string{"FCGI_MPXS_CONNS": "1"}
c.conn.writePairs(typeGetValuesResult, 0, values)
+ return nil
case typeData:
// If the filter role is implemented, read the data stream here.
+ return nil
case typeAbortRequest:
+ println("abort")
delete(c.requests, rec.h.Id)
c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
if !req.keepConn {
// connection will close upon return
return errCloseConn
}
+ return nil
default:
b := make([]byte, 8)
b[0] = byte(rec.h.Type)
c.conn.writeRecord(typeUnknownType, 0, b)
+ return nil
}
- return nil
}
func (c *child) serveRequest(req *request, body io.ReadCloser) {
@@ -232,11 +246,19 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) {
httpReq.Body = body
c.handler.ServeHTTP(r, httpReq)
}
- if body != nil {
- body.Close()
- }
r.Close()
c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
+
+ // Consume the entire body, so the host isn't still writing to
+ // us when we close the socket below in the !keepConn case,
+ // otherwise we'd send a RST. (golang.org/issue/4183)
+ // TODO(bradfitz): also bound this copy in time. Or send
+ // some sort of abort request to the host, so the host
+ // can properly cut off the client sending all the data.
+ // For now just bound it a little and
+ io.CopyN(ioutil.Discard, body, 100<<20)
+ body.Close()
+
if !req.keepConn {
c.conn.Close()
}
@@ -267,5 +289,4 @@ func Serve(l net.Listener, handler http.Handler) error {
c := newChild(rw, handler)
go c.serve()
}
- panic("unreachable")
}
diff --git a/src/pkg/net/http/fs_test.go b/src/pkg/net/http/fs_test.go
index 0dd6d0df9..2c3737653 100644
--- a/src/pkg/net/http/fs_test.go
+++ b/src/pkg/net/http/fs_test.go
@@ -54,7 +54,7 @@ var ServeFileRangeTests = []struct {
}
func TestServeFile(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
ServeFile(w, r, "testdata/file")
}))
@@ -170,7 +170,7 @@ var fsRedirectTestData = []struct {
}
func TestFSRedirect(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(StripPrefix("/test", FileServer(Dir("."))))
defer ts.Close()
@@ -195,7 +195,7 @@ func (fs *testFileSystem) Open(name string) (File, error) {
}
func TestFileServerCleans(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ch := make(chan string, 1)
fs := FileServer(&testFileSystem{func(name string) (File, error) {
ch <- name
@@ -227,7 +227,7 @@ func mustRemoveAll(dir string) {
}
func TestFileServerImplicitLeadingSlash(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
tempDir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("TempDir: %v", err)
@@ -306,7 +306,7 @@ func TestEmptyDirOpenCWD(t *testing.T) {
}
func TestServeFileContentType(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const ctype = "icecream/chocolate"
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.FormValue("override") == "1" {
@@ -330,7 +330,7 @@ func TestServeFileContentType(t *testing.T) {
}
func TestServeFileMimeType(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
ServeFile(w, r, "testdata/style.css")
}))
@@ -347,7 +347,7 @@ func TestServeFileMimeType(t *testing.T) {
}
func TestServeFileFromCWD(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
ServeFile(w, r, "fs_test.go")
}))
@@ -363,7 +363,7 @@ func TestServeFileFromCWD(t *testing.T) {
}
func TestServeFileWithContentEncoding(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Content-Encoding", "foo")
ServeFile(w, r, "testdata/file")
@@ -380,7 +380,7 @@ func TestServeFileWithContentEncoding(t *testing.T) {
}
func TestServeIndexHtml(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const want = "index.html says hello\n"
ts := httptest.NewServer(FileServer(Dir(".")))
defer ts.Close()
@@ -402,7 +402,7 @@ func TestServeIndexHtml(t *testing.T) {
}
func TestFileServerZeroByte(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(FileServer(Dir(".")))
defer ts.Close()
@@ -471,7 +471,7 @@ func (fs fakeFS) Open(name string) (File, error) {
}
func TestDirectoryIfNotModified(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const indexContents = "I am a fake index.html file"
fileMod := time.Unix(1000000000, 0).UTC()
fileModStr := fileMod.Format(TimeFormat)
@@ -545,7 +545,7 @@ func mustStat(t *testing.T, fileName string) os.FileInfo {
}
func TestServeContent(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
type serveParam struct {
name string
modtime time.Time
@@ -678,7 +678,7 @@ func TestServeContent(t *testing.T) {
// verifies that sendfile is being used on Linux
func TestLinuxSendfile(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
if runtime.GOOS != "linux" {
t.Skip("skipping; linux-only test")
}
@@ -697,7 +697,7 @@ func TestLinuxSendfile(t *testing.T) {
defer ln.Close()
var buf bytes.Buffer
- child := exec.Command("strace", "-f", os.Args[0], "-test.run=TestLinuxSendfileChild")
+ child := exec.Command("strace", "-f", "-q", "-e", "trace=sendfile,sendfile64", os.Args[0], "-test.run=TestLinuxSendfileChild")
child.ExtraFiles = append(child.ExtraFiles, lnf)
child.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
child.Stdout = &buf
diff --git a/src/pkg/net/http/header.go b/src/pkg/net/http/header.go
index f479b7b4e..6374237fb 100644
--- a/src/pkg/net/http/header.go
+++ b/src/pkg/net/http/header.go
@@ -103,21 +103,41 @@ type keyValues struct {
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))
+// A headerSorter implements sort.Interface by sorting a []keyValues
+// by key. It's used as a pointer, so it can fit in a sort.Interface
+// interface value without allocation.
+type headerSorter struct {
+ kvs []keyValues
+}
+
+func (s *headerSorter) Len() int { return len(s.kvs) }
+func (s *headerSorter) Swap(i, j int) { s.kvs[i], s.kvs[j] = s.kvs[j], s.kvs[i] }
+func (s *headerSorter) Less(i, j int) bool { return s.kvs[i].key < s.kvs[j].key }
+
+// TODO: convert this to a sync.Cache (issue 4720)
+var headerSorterCache = make(chan *headerSorter, 8)
+
+// sortedKeyValues returns h's keys sorted in the returned kvs
+// slice. The headerSorter used to sort is also returned, for possible
+// return to headerSorterCache.
+func (h Header) sortedKeyValues(exclude map[string]bool) (kvs []keyValues, hs *headerSorter) {
+ select {
+ case hs = <-headerSorterCache:
+ default:
+ hs = new(headerSorter)
+ }
+ if cap(hs.kvs) < len(h) {
+ hs.kvs = make([]keyValues, 0, len(h))
+ }
+ kvs = hs.kvs[:0]
for k, vv := range h {
if !exclude[k] {
kvs = append(kvs, keyValues{k, vv})
}
}
- sort.Sort(byKey(kvs))
- return kvs
+ hs.kvs = kvs
+ sort.Sort(hs)
+ return kvs, hs
}
// WriteSubset writes a header in wire format.
@@ -127,7 +147,8 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
if !ok {
ws = stringWriter{w}
}
- for _, kv := range h.sortedKeyValues(exclude) {
+ kvs, sorter := h.sortedKeyValues(exclude)
+ for _, kv := range kvs {
for _, v := range kv.values {
v = headerNewlineToSpace.Replace(v)
v = textproto.TrimString(v)
@@ -138,6 +159,10 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
}
}
}
+ select {
+ case headerSorterCache <- sorter:
+ default:
+ }
return nil
}
diff --git a/src/pkg/net/http/header_test.go b/src/pkg/net/http/header_test.go
index 2313b5549..a2b82a701 100644
--- a/src/pkg/net/http/header_test.go
+++ b/src/pkg/net/http/header_test.go
@@ -6,6 +6,7 @@ package http
import (
"bytes"
+ "runtime"
"testing"
"time"
)
@@ -178,7 +179,7 @@ var testHeader = Header{
"Content-Length": {"123"},
"Content-Type": {"text/plain"},
"Date": {"some date at some time Z"},
- "Server": {"Go http package"},
+ "Server": {DefaultUserAgent},
}
var buf bytes.Buffer
@@ -192,13 +193,14 @@ func BenchmarkHeaderWriteSubset(b *testing.B) {
}
func TestHeaderWriteSubsetMallocs(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
n := testing.AllocsPerRun(100, func() {
buf.Reset()
testHeader.WriteSubset(&buf, nil)
})
- if n > 1 {
- // TODO(bradfitz,rsc): once we can sort without allocating,
- // make this an error. See http://golang.org/issue/3761
- // t.Errorf("got %v allocs, want <= %v", n, 1)
+ if n > 0 {
+ t.Errorf("mallocs = %d; want 0", n)
}
}
diff --git a/src/pkg/net/http/httputil/dump_test.go b/src/pkg/net/http/httputil/dump_test.go
index 5afe9ba74..3e87c27bc 100644
--- a/src/pkg/net/http/httputil/dump_test.go
+++ b/src/pkg/net/http/httputil/dump_test.go
@@ -68,7 +68,7 @@ var dumpTests = []dumpTest{
WantDumpOut: "GET /foo HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Accept-Encoding: gzip\r\n\r\n",
},
@@ -80,7 +80,7 @@ var dumpTests = []dumpTest{
WantDumpOut: "GET /foo HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Accept-Encoding: gzip\r\n\r\n",
},
}
diff --git a/src/pkg/net/http/httputil/reverseproxy.go b/src/pkg/net/http/httputil/reverseproxy.go
index 134c45299..1990f64db 100644
--- a/src/pkg/net/http/httputil/reverseproxy.go
+++ b/src/pkg/net/http/httputil/reverseproxy.go
@@ -81,6 +81,19 @@ func copyHeader(dst, src http.Header) {
}
}
+// Hop-by-hop headers. These are removed when sent to the backend.
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
+var hopHeaders = []string{
+ "Connection",
+ "Keep-Alive",
+ "Proxy-Authenticate",
+ "Proxy-Authorization",
+ "Te", // canonicalized version of "TE"
+ "Trailers",
+ "Transfer-Encoding",
+ "Upgrade",
+}
+
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
transport := p.Transport
if transport == nil {
@@ -96,14 +109,21 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
outreq.ProtoMinor = 1
outreq.Close = false
- // Remove the connection header to the backend. We want a
- // persistent connection, regardless of what the client sent
- // to us. This is modifying the same underlying map from req
- // (shallow copied above) so we only copy it if necessary.
- if outreq.Header.Get("Connection") != "" {
- outreq.Header = make(http.Header)
- copyHeader(outreq.Header, req.Header)
- outreq.Header.Del("Connection")
+ // Remove hop-by-hop headers to the backend. Especially
+ // important is "Connection" because we want a persistent
+ // connection, regardless of what the client sent to us. This
+ // is modifying the same underlying map from req (shallow
+ // copied above) so we only copy it if necessary.
+ copiedHeaders := false
+ for _, h := range hopHeaders {
+ if outreq.Header.Get(h) != "" {
+ if !copiedHeaders {
+ outreq.Header = make(http.Header)
+ copyHeader(outreq.Header, req.Header)
+ copiedHeaders = true
+ }
+ outreq.Header.Del(h)
+ }
}
if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
@@ -182,7 +202,6 @@ func (m *maxLatencyWriter) flushLoop() {
m.lk.Unlock()
}
}
- panic("unreached")
}
func (m *maxLatencyWriter) stop() { m.done <- true }
diff --git a/src/pkg/net/http/httputil/reverseproxy_test.go b/src/pkg/net/http/httputil/reverseproxy_test.go
index 863927162..1c0444ec4 100644
--- a/src/pkg/net/http/httputil/reverseproxy_test.go
+++ b/src/pkg/net/http/httputil/reverseproxy_test.go
@@ -29,6 +29,9 @@ func TestReverseProxy(t *testing.T) {
if c := r.Header.Get("Connection"); c != "" {
t.Errorf("handler got Connection header value %q", c)
}
+ if c := r.Header.Get("Upgrade"); c != "" {
+ t.Errorf("handler got Upgrade header value %q", c)
+ }
if g, e := r.Host, "some-name"; g != e {
t.Errorf("backend got Host header %q, want %q", g, e)
}
@@ -49,6 +52,7 @@ func TestReverseProxy(t *testing.T) {
getReq, _ := http.NewRequest("GET", frontend.URL, nil)
getReq.Host = "some-name"
getReq.Header.Set("Connection", "close")
+ getReq.Header.Set("Upgrade", "foo")
getReq.Close = true
res, err := http.DefaultClient.Do(getReq)
if err != nil {
diff --git a/src/pkg/net/http/request.go b/src/pkg/net/http/request.go
index 217f35b48..dabb169d1 100644
--- a/src/pkg/net/http/request.go
+++ b/src/pkg/net/http/request.go
@@ -283,7 +283,7 @@ func valueOrDefault(value, def string) string {
return def
}
-const defaultUserAgent = "Go http package"
+const defaultUserAgent = "Go 1.1 package http"
// Write writes an HTTP/1.1 request -- header and body -- in wire format.
// This method consults the following fields of the request:
diff --git a/src/pkg/net/http/request_test.go b/src/pkg/net/http/request_test.go
index 00ad791de..692485c49 100644
--- a/src/pkg/net/http/request_test.go
+++ b/src/pkg/net/http/request_test.go
@@ -267,6 +267,38 @@ func TestNewRequestContentLength(t *testing.T) {
}
}
+var parseHTTPVersionTests = []struct {
+ vers string
+ major, minor int
+ ok bool
+}{
+ {"HTTP/0.9", 0, 9, true},
+ {"HTTP/1.0", 1, 0, true},
+ {"HTTP/1.1", 1, 1, true},
+ {"HTTP/3.14", 3, 14, true},
+
+ {"HTTP", 0, 0, false},
+ {"HTTP/one.one", 0, 0, false},
+ {"HTTP/1.1/", 0, 0, false},
+ {"HTTP/-1,0", 0, 0, false},
+ {"HTTP/0,-1", 0, 0, false},
+ {"HTTP/", 0, 0, false},
+ {"HTTP/1,1", 0, 0, false},
+}
+
+func TestParseHTTPVersion(t *testing.T) {
+ for _, tt := range parseHTTPVersionTests {
+ major, minor, ok := ParseHTTPVersion(tt.vers)
+ if ok != tt.ok || major != tt.major || minor != tt.minor {
+ type version struct {
+ major, minor int
+ ok bool
+ }
+ t.Errorf("failed to parse %q, expected: %#v, got %#v", tt.vers, version{tt.major, tt.minor, tt.ok}, version{major, minor, ok})
+ }
+ }
+}
+
type logWrites struct {
t *testing.T
dst *[]string
@@ -289,7 +321,7 @@ func TestRequestWriteBufferedWriter(t *testing.T) {
want := []string{
"GET / HTTP/1.1\r\n",
"Host: foo.com\r\n",
- "User-Agent: Go http package\r\n",
+ "User-Agent: " + DefaultUserAgent + "\r\n",
"\r\n",
}
if !reflect.DeepEqual(got, want) {
diff --git a/src/pkg/net/http/requestwrite_test.go b/src/pkg/net/http/requestwrite_test.go
index bc637f18b..b27b1f7ce 100644
--- a/src/pkg/net/http/requestwrite_test.go
+++ b/src/pkg/net/http/requestwrite_test.go
@@ -93,13 +93,13 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "GET /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("abcdef") + chunk(""),
WantProxy: "GET http://www.google.com/search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("abcdef") + chunk(""),
},
@@ -123,14 +123,14 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "POST /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Connection: close\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("abcdef") + chunk(""),
WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Connection: close\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("abcdef") + chunk(""),
@@ -156,7 +156,7 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "POST /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Connection: close\r\n" +
"Content-Length: 6\r\n" +
"\r\n" +
@@ -164,7 +164,7 @@ var reqWriteTests = []reqWriteTest{
WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Connection: close\r\n" +
"Content-Length: 6\r\n" +
"\r\n" +
@@ -187,14 +187,14 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Content-Length: 6\r\n" +
"\r\n" +
"abcdef",
WantProxy: "POST http://example.com/ HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Content-Length: 6\r\n" +
"\r\n" +
"abcdef",
@@ -210,7 +210,7 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "GET /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"\r\n",
},
@@ -232,13 +232,13 @@ var reqWriteTests = []reqWriteTest{
// Also, nginx expects it for POST and PUT.
WantWrite: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Content-Length: 0\r\n" +
"\r\n",
WantProxy: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Content-Length: 0\r\n" +
"\r\n",
},
@@ -258,13 +258,13 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("x") + chunk(""),
WantProxy: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("x") + chunk(""),
},
@@ -325,7 +325,7 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "GET /foo HTTP/1.1\r\n" +
"Host: \r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"X-Foo: X-Bar\r\n\r\n",
},
@@ -351,7 +351,7 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "GET /search HTTP/1.1\r\n" +
"Host: \r\n" +
- "User-Agent: Go http package\r\n\r\n",
+ "User-Agent: Go 1.1 package http\r\n\r\n",
},
// Opaque test #1 from golang.org/issue/4860
@@ -370,7 +370,7 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "GET /%2F/%2F/ HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n\r\n",
+ "User-Agent: Go 1.1 package http\r\n\r\n",
},
// Opaque test #2 from golang.org/issue/4860
@@ -389,7 +389,31 @@ var reqWriteTests = []reqWriteTest{
WantWrite: "GET http://y.google.com/%2F/%2F/ HTTP/1.1\r\n" +
"Host: x.google.com\r\n" +
- "User-Agent: Go http package\r\n\r\n",
+ "User-Agent: Go 1.1 package http\r\n\r\n",
+ },
+
+ // Testing custom case in header keys. Issue 5022.
+ {
+ Req: Request{
+ Method: "GET",
+ URL: &url.URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/",
+ },
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: Header{
+ "ALL-CAPS": {"x"},
+ },
+ },
+
+ WantWrite: "GET / HTTP/1.1\r\n" +
+ "Host: www.google.com\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
+ "ALL-CAPS: x\r\n" +
+ "\r\n",
},
}
@@ -474,7 +498,7 @@ func TestRequestWriteClosesBody(t *testing.T) {
}
expected := "POST / HTTP/1.1\r\n" +
"Host: foo.com\r\n" +
- "User-Agent: Go http package\r\n" +
+ "User-Agent: Go 1.1 package http\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
// TODO: currently we don't buffer before chunking, so we get a
// single "m" chunk before the other chunks, as this was the 1-byte
diff --git a/src/pkg/net/http/response.go b/src/pkg/net/http/response.go
index 391ebbf6d..9a7e4e319 100644
--- a/src/pkg/net/http/response.go
+++ b/src/pkg/net/http/response.go
@@ -46,6 +46,9 @@ type Response struct {
// The http Client and Transport guarantee that Body is always
// non-nil, even on responses without a body or responses with
// a zero-lengthed body.
+ //
+ // The Body is automatically dechunked if the server replied
+ // with a "chunked" Transfer-Encoding.
Body io.ReadCloser
// ContentLength records the length of the associated content. The
diff --git a/src/pkg/net/http/response_test.go b/src/pkg/net/http/response_test.go
index 2f5f77369..49836ce2c 100644
--- a/src/pkg/net/http/response_test.go
+++ b/src/pkg/net/http/response_test.go
@@ -466,7 +466,7 @@ func TestReadResponseCloseInMiddle(t *testing.T) {
if test.compressed {
gzReader, err := gzip.NewReader(resp.Body)
checkErr(err, "gzip.NewReader")
- resp.Body = &readFirstCloseBoth{gzReader, resp.Body}
+ resp.Body = &readerAndCloser{gzReader, resp.Body}
}
rbuf := make([]byte, 2500)
diff --git a/src/pkg/net/http/serve_test.go b/src/pkg/net/http/serve_test.go
index 3300fef59..5adde545f 100644
--- a/src/pkg/net/http/serve_test.go
+++ b/src/pkg/net/http/serve_test.go
@@ -184,7 +184,7 @@ var vtests = []struct {
}
func TestHostHandlers(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
mux := NewServeMux()
for _, h := range handlers {
mux.Handle(h.pattern, stringHandler(h.msg))
@@ -257,7 +257,7 @@ func TestMuxRedirectLeadingSlashes(t *testing.T) {
}
func TestServerTimeouts(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
reqNum := 0
ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {
reqNum++
@@ -333,7 +333,7 @@ func TestServerTimeouts(t *testing.T) {
// shouldn't cause a handler to block forever on reads (next HTTP
// request) that will never happen.
func TestOnlyWriteTimeout(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
var conn net.Conn
var afterTimeoutErrc = make(chan error, 1)
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, req *Request) {
@@ -392,7 +392,7 @@ func (l trackLastConnListener) Accept() (c net.Conn, err error) {
// TestIdentityResponse verifies that a handler can unset
func TestIdentityResponse(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
rw.Header().Set("Content-Length", "3")
rw.Header().Set("Transfer-Encoding", req.FormValue("te"))
@@ -468,7 +468,7 @@ func TestIdentityResponse(t *testing.T) {
}
func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
s := httptest.NewServer(h)
defer s.Close()
@@ -539,7 +539,7 @@ func TestHandlersCanSetConnectionClose10(t *testing.T) {
}
func TestSetsRemoteAddr(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "%s", r.RemoteAddr)
}))
@@ -560,7 +560,7 @@ func TestSetsRemoteAddr(t *testing.T) {
}
func TestChunkedResponseHeaders(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
log.SetOutput(ioutil.Discard) // is noisy otherwise
defer log.SetOutput(os.Stderr)
@@ -591,7 +591,7 @@ func TestChunkedResponseHeaders(t *testing.T) {
// chunking in their response headers and aren't allowed to produce
// output.
func Test304Responses(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.WriteHeader(StatusNotModified)
_, err := w.Write([]byte("illegal body"))
@@ -621,7 +621,7 @@ func Test304Responses(t *testing.T) {
// allowed to produce output, and don't set a Content-Type since
// the real type of the body data cannot be inferred.
func TestHeadResponses(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
_, err := w.Write([]byte("Ignored body"))
if err != ErrBodyNotAllowed {
@@ -656,7 +656,7 @@ func TestHeadResponses(t *testing.T) {
}
func TestTLSHandshakeTimeout(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
ts.Config.ReadTimeout = 250 * time.Millisecond
ts.StartTLS()
@@ -676,7 +676,7 @@ func TestTLSHandshakeTimeout(t *testing.T) {
}
func TestTLSServer(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.TLS != nil {
w.Header().Set("X-TLS-Set", "true")
@@ -759,7 +759,7 @@ var serverExpectTests = []serverExpectTest{
// Tests that the server responds to the "Expect" request header
// correctly.
func TestServerExpect(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
// Note using r.FormValue("readbody") because for POST
// requests that would read from r.Body, which we only
@@ -897,7 +897,7 @@ func TestServerUnreadRequestBodyLarge(t *testing.T) {
}
func TestTimeoutHandler(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
sendHi := make(chan bool, 1)
writeErrors := make(chan error, 1)
sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -972,7 +972,7 @@ func TestRedirectMunging(t *testing.T) {
// the previous request's body, which is not optimal for zero-lengthed bodies,
// as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF.
func TestZeroLengthPostAndResponse(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
all, err := ioutil.ReadAll(r.Body)
if err != nil {
@@ -1023,7 +1023,7 @@ func TestHandlerPanicWithHijack(t *testing.T) {
}
func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
// Unlike the other tests that set the log output to ioutil.Discard
// to quiet the output, this test uses a pipe. The pipe serves three
// purposes:
@@ -1089,7 +1089,7 @@ func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
}
func TestNoDate(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header()["Date"] = nil
}))
@@ -1105,7 +1105,7 @@ func TestNoDate(t *testing.T) {
}
func TestStripPrefix(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
h := HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("X-Path", r.URL.Path)
})
@@ -1132,7 +1132,7 @@ func TestStripPrefix(t *testing.T) {
}
func TestRequestLimit(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
t.Fatalf("didn't expect to get request in Handler")
}))
@@ -1176,7 +1176,7 @@ func (cr countReader) Read(p []byte) (n int, err error) {
}
func TestRequestBodyLimit(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const limit = 1 << 20
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
r.Body = MaxBytesReader(w, r.Body, limit)
@@ -1213,7 +1213,7 @@ func TestRequestBodyLimit(t *testing.T) {
// TestClientWriteShutdown tests that if the client shuts down the write
// side of their TCP connection, the server doesn't send a 400 Bad Request.
func TestClientWriteShutdown(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
defer ts.Close()
conn, err := net.Dial("tcp", ts.Listener.Addr().String())
@@ -1268,7 +1268,7 @@ func TestServerBufferedChunking(t *testing.T) {
// closing the TCP connection, causing the client to get a RST.
// See http://golang.org/issue/3595
func TestServerGracefulClose(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
Error(w, "bye", StatusUnauthorized)
}))
@@ -1311,7 +1311,7 @@ func TestServerGracefulClose(t *testing.T) {
}
func TestCaseSensitiveMethod(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.Method != "get" {
t.Errorf(`Got method %q; want "get"`, r.Method)
@@ -1620,3 +1620,34 @@ func BenchmarkServer(b *testing.B) {
b.Errorf("Test failure: %v, with output: %s", err, out)
}
}
+
+func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
+ b.ReportAllocs()
+ req := []byte(strings.Replace(`GET / HTTP/1.0
+Host: golang.org
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+
+`, "\n", "\r\n", -1))
+ res := []byte("Hello world!\n")
+
+ conn := &testConn{
+ closec: make(chan bool),
+ }
+ handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+ rw.Header().Set("Content-Type", "text/html; charset=utf-8")
+ rw.Write(res)
+ })
+ ln := new(oneConnListener)
+ for i := 0; i < b.N; i++ {
+ conn.readBuf.Reset()
+ conn.writeBuf.Reset()
+ conn.readBuf.Write(req)
+ ln.conn = conn
+ Serve(ln, handler)
+ <-conn.closec
+ }
+}
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go
index b6ab78228..aee3229d3 100644
--- a/src/pkg/net/http/server.go
+++ b/src/pkg/net/http/server.go
@@ -109,9 +109,11 @@ type conn struct {
remoteAddr string // network address of remote side
server *Server // the Server on which the connection arrived
rwc net.Conn // i/o connection
- sr switchReader // where the LimitReader reads from; usually the rwc
+ sr liveSwitchReader // where the LimitReader reads from; usually the rwc
lr *io.LimitedReader // io.LimitReader(sr)
buf *bufio.ReadWriter // buffered(lr,rwc), reading from bufio->limitReader->sr->rwc
+ bufswr *switchReader // the *switchReader io.Reader source of buf
+ bufsww *switchWriter // the *switchWriter io.Writer dest of buf
tlsState *tls.ConnectionState // or nil when not using TLS
mu sync.Mutex // guards the following
@@ -180,12 +182,26 @@ func (c *conn) noteClientGone() {
c.clientGone = true
}
+// A switchReader can have its Reader changed at runtime.
+// It's not safe for concurrent Reads and switches.
type switchReader struct {
+ io.Reader
+}
+
+// A switchWriter can have its Writer changed at runtime.
+// It's not safe for concurrent Writes and switches.
+type switchWriter struct {
+ io.Writer
+}
+
+// A liveSwitchReader is a switchReader that's safe for concurrent
+// reads and switches, if its mutex is held.
+type liveSwitchReader struct {
sync.Mutex
r io.Reader
}
-func (sr *switchReader) Read(p []byte) (n int, err error) {
+func (sr *liveSwitchReader) Read(p []byte) (n int, err error) {
sr.Lock()
r := sr.r
sr.Unlock()
@@ -362,14 +378,87 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
if debugServerConnections {
c.rwc = newLoggingConn("server", c.rwc)
}
- c.sr = switchReader{r: c.rwc}
+ c.sr = liveSwitchReader{r: c.rwc}
c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
- br := bufio.NewReader(c.lr)
- bw := bufio.NewWriter(c.rwc)
+ br, sr := newBufioReader(c.lr)
+ bw, sw := newBufioWriter(c.rwc)
c.buf = bufio.NewReadWriter(br, bw)
+ c.bufswr = sr
+ c.bufsww = sw
return c, nil
}
+// TODO: remove this, if issue 5100 is fixed
+type bufioReaderPair struct {
+ br *bufio.Reader
+ sr *switchReader // from which the bufio.Reader is reading
+}
+
+// TODO: remove this, if issue 5100 is fixed
+type bufioWriterPair struct {
+ bw *bufio.Writer
+ sw *switchWriter // to which the bufio.Writer is writing
+}
+
+// TODO: use a sync.Cache instead
+var (
+ bufioReaderCache = make(chan bufioReaderPair, 4)
+ bufioWriterCache = make(chan bufioWriterPair, 4)
+)
+
+func newBufioReader(r io.Reader) (*bufio.Reader, *switchReader) {
+ select {
+ case p := <-bufioReaderCache:
+ p.sr.Reader = r
+ return p.br, p.sr
+ default:
+ sr := &switchReader{r}
+ return bufio.NewReader(sr), sr
+ }
+}
+
+func putBufioReader(br *bufio.Reader, sr *switchReader) {
+ if n := br.Buffered(); n > 0 {
+ io.CopyN(ioutil.Discard, br, int64(n))
+ }
+ br.Read(nil) // clears br.err
+ sr.Reader = nil
+ select {
+ case bufioReaderCache <- bufioReaderPair{br, sr}:
+ default:
+ }
+}
+
+func newBufioWriter(w io.Writer) (*bufio.Writer, *switchWriter) {
+ select {
+ case p := <-bufioWriterCache:
+ p.sw.Writer = w
+ return p.bw, p.sw
+ default:
+ sw := &switchWriter{w}
+ return bufio.NewWriter(sw), sw
+ }
+}
+
+func putBufioWriter(bw *bufio.Writer, sw *switchWriter) {
+ if bw.Buffered() > 0 {
+ // It must have failed to flush to its target
+ // earlier. We can't reuse this bufio.Writer.
+ return
+ }
+ if err := bw.Flush(); err != nil {
+ // Its sticky error field is set, which is returned by
+ // Flush even when there's no data buffered. This
+ // bufio Writer is dead to us. Don't reuse it.
+ return
+ }
+ sw.Writer = nil
+ select {
+ case bufioWriterCache <- bufioWriterPair{bw, sw}:
+ default:
+ }
+}
+
// DefaultMaxHeaderBytes is the maximum permitted size of the headers
// in an HTTP request.
// This can be overridden by setting Server.MaxHeaderBytes.
@@ -655,7 +744,7 @@ func (w *response) bodyAllowed() bool {
//
// Handler starts. No header has been sent. The handler can either
// write a header, or just start writing. Writing before sending a header
-// sends an implicity empty 200 OK header.
+// sends an implicitly empty 200 OK header.
//
// If the handler didn't declare a Content-Length up front, we either
// go into chunking mode or, if the handler finishes running before
@@ -742,6 +831,15 @@ func (w *response) Flush() {
func (c *conn) finalFlush() {
if c.buf != nil {
c.buf.Flush()
+
+ // Steal the bufio.Reader (~4KB worth of memory) and its associated
+ // reader for a future connection.
+ putBufioReader(c.buf.Reader, c.bufswr)
+
+ // Steal the bufio.Writer (~4KB worth of memory) and its associated
+ // writer for a future connection.
+ putBufioWriter(c.buf.Writer, c.bufsww)
+
c.buf = nil
}
}
@@ -948,13 +1046,16 @@ func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
// request for a path that doesn't begin with prefix by
// replying with an HTTP 404 not found error.
func StripPrefix(prefix string, h Handler) Handler {
+ if prefix == "" {
+ return h
+ }
return HandlerFunc(func(w ResponseWriter, r *Request) {
- if !strings.HasPrefix(r.URL.Path, prefix) {
+ if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
+ r.URL.Path = p
+ h.ServeHTTP(w, r)
+ } else {
NotFound(w, r)
- return
}
- r.URL.Path = r.URL.Path[len(prefix):]
- h.ServeHTTP(w, r)
})
}
@@ -1337,7 +1438,6 @@ func (srv *Server) Serve(l net.Listener) error {
}
go c.serve()
}
- panic("not reached")
}
// ListenAndServe listens on the TCP network address addr
diff --git a/src/pkg/net/http/sniff_test.go b/src/pkg/net/http/sniff_test.go
index 8ab72ac23..106d94ec1 100644
--- a/src/pkg/net/http/sniff_test.go
+++ b/src/pkg/net/http/sniff_test.go
@@ -54,6 +54,7 @@ func TestDetectContentType(t *testing.T) {
}
func TestServerContentType(t *testing.T) {
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
i, _ := strconv.Atoi(r.FormValue("i"))
tt := sniffTests[i]
@@ -84,6 +85,8 @@ func TestServerContentType(t *testing.T) {
}
func TestContentTypeWithCopy(t *testing.T) {
+ defer afterTest(t)
+
const (
input = "\n<html>\n\t<head>\n"
expected = "text/html; charset=utf-8"
@@ -116,6 +119,7 @@ func TestContentTypeWithCopy(t *testing.T) {
}
func TestSniffWriteSize(t *testing.T) {
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
size, _ := strconv.Atoi(r.FormValue("size"))
written, err := io.WriteString(w, strings.Repeat("a", size))
@@ -133,6 +137,11 @@ func TestSniffWriteSize(t *testing.T) {
if err != nil {
t.Fatalf("size %d: %v", size, err)
}
- res.Body.Close()
+ if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+ t.Fatalf("size %d: io.Copy of body = %v", size, err)
+ }
+ if err := res.Body.Close(); err != nil {
+ t.Fatalf("size %d: body Close = %v", size, err)
+ }
}
}
diff --git a/src/pkg/net/http/status.go b/src/pkg/net/http/status.go
index 5af0b77c4..d253bd5cb 100644
--- a/src/pkg/net/http/status.go
+++ b/src/pkg/net/http/status.go
@@ -51,6 +51,13 @@ const (
StatusServiceUnavailable = 503
StatusGatewayTimeout = 504
StatusHTTPVersionNotSupported = 505
+
+ // New HTTP status codes from RFC 6585. Not exported yet in Go 1.1.
+ // See discussion at https://codereview.appspot.com/7678043/
+ statusPreconditionRequired = 428
+ statusTooManyRequests = 429
+ statusRequestHeaderFieldsTooLarge = 431
+ statusNetworkAuthenticationRequired = 511
)
var statusText = map[int]string{
@@ -99,6 +106,11 @@ var statusText = map[int]string{
StatusServiceUnavailable: "Service Unavailable",
StatusGatewayTimeout: "Gateway Timeout",
StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
+
+ statusPreconditionRequired: "Precondition Required",
+ statusTooManyRequests: "Too Many Requests",
+ statusRequestHeaderFieldsTooLarge: "Request Header Fields Too Large",
+ statusNetworkAuthenticationRequired: "Network Authentication Required",
}
// StatusText returns a text for the HTTP status code. It returns the empty
diff --git a/src/pkg/net/http/transport.go b/src/pkg/net/http/transport.go
index 685d7d56c..08ced2c3d 100644
--- a/src/pkg/net/http/transport.go
+++ b/src/pkg/net/http/transport.go
@@ -17,7 +17,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"log"
"net"
"net/url"
@@ -42,16 +41,13 @@ const DefaultMaxIdleConnsPerHost = 2
// https, and http proxies (for either http or https with CONNECT).
// Transport can also cache connections for future re-use.
type Transport struct {
- idleMu sync.Mutex
- idleConn map[string][]*persistConn
- reqMu sync.Mutex
- reqConn map[*Request]*persistConn
- altMu sync.RWMutex
- altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
-
- // TODO: tunable on global max cached connections
- // TODO: tunable on timeout on cached connections
- // TODO: optional pipelining
+ idleMu sync.Mutex
+ idleConn map[string][]*persistConn
+ idleConnCh map[string]chan *persistConn
+ reqMu sync.Mutex
+ reqConn map[*Request]*persistConn
+ altMu sync.RWMutex
+ altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
// Proxy specifies a function to return a proxy for a given
// Request. If the function returns a non-nil error, the
@@ -68,7 +64,18 @@ type Transport struct {
// tls.Client. If nil, the default configuration is used.
TLSClientConfig *tls.Config
- DisableKeepAlives bool
+ // DisableKeepAlives, if true, prevents re-use of TCP connections
+ // between different HTTP requests.
+ DisableKeepAlives bool
+
+ // DisableCompression, if true, prevents the Transport from
+ // requesting compression with an "Accept-Encoding: gzip"
+ // request header when the Request contains no existing
+ // Accept-Encoding value. If the Transport requests gzip on
+ // its own and gets a gzipped response, it's transparently
+ // decoded in the Response.Body. However, if the user
+ // explicitly requested gzip it is not automatically
+ // uncompressed.
DisableCompression bool
// MaxIdleConnsPerHost, if non-zero, controls the maximum idle
@@ -81,6 +88,9 @@ type Transport struct {
// writing the request (including its body, if any). This
// time does not include the time to read the response body.
ResponseHeaderTimeout time.Duration
+
+ // TODO: tunable on global max cached connections
+ // TODO: tunable on timeout on cached connections
}
// ProxyFromEnvironment returns the URL of the proxy to use for a
@@ -133,6 +143,9 @@ func (tr *transportRequest) extraHeaders() Header {
}
// RoundTrip implements the RoundTripper interface.
+//
+// For higher-level HTTP client support (such as handling of cookies
+// and redirects), see Get, Post, and the Client type.
func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
if req.URL == nil {
return nil, errors.New("http: nil Request.URL")
@@ -280,6 +293,17 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
max = DefaultMaxIdleConnsPerHost
}
t.idleMu.Lock()
+ select {
+ case t.idleConnCh[key] <- pconn:
+ // We're done with this pconn and somebody else is
+ // currently waiting for a conn of this type (they're
+ // actively dialing, but this conn is ready
+ // first). Chrome calls this socket late binding. See
+ // https://insouciant.org/tech/connection-management-in-chromium/
+ t.idleMu.Unlock()
+ return true
+ default:
+ }
if t.idleConn == nil {
t.idleConn = make(map[string][]*persistConn)
}
@@ -298,8 +322,23 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
return true
}
+func (t *Transport) getIdleConnCh(cm *connectMethod) chan *persistConn {
+ key := cm.key()
+ t.idleMu.Lock()
+ defer t.idleMu.Unlock()
+ if t.idleConnCh == nil {
+ t.idleConnCh = make(map[string]chan *persistConn)
+ }
+ ch, ok := t.idleConnCh[key]
+ if !ok {
+ ch = make(chan *persistConn)
+ t.idleConnCh[key] = ch
+ }
+ return ch
+}
+
func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
- key := cm.String()
+ key := cm.key()
t.idleMu.Lock()
defer t.idleMu.Unlock()
if t.idleConn == nil {
@@ -323,7 +362,6 @@ func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
return
}
}
- panic("unreachable")
}
func (t *Transport) setReqConn(r *Request, pc *persistConn) {
@@ -355,6 +393,37 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
return pc, nil
}
+ type dialRes struct {
+ pc *persistConn
+ err error
+ }
+ dialc := make(chan dialRes)
+ go func() {
+ pc, err := t.dialConn(cm)
+ dialc <- dialRes{pc, err}
+ }()
+
+ idleConnCh := t.getIdleConnCh(cm)
+ select {
+ case v := <-dialc:
+ // Our dial finished.
+ return v.pc, v.err
+ case pc := <-idleConnCh:
+ // Another request finished first and its net.Conn
+ // became available before our dial. Or somebody
+ // else's dial that they didn't use.
+ // But our dial is still going, so give it away
+ // when it finishes:
+ go func() {
+ if v := <-dialc; v.err == nil {
+ t.putIdleConn(v.pc)
+ }
+ }()
+ return pc, nil
+ }
+}
+
+func (t *Transport) dialConn(cm *connectMethod) (*persistConn, error) {
conn, err := t.dial("tcp", cm.addr())
if err != nil {
if cm.proxyURL != nil {
@@ -367,7 +436,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
pconn := &persistConn{
t: t,
- cacheKey: cm.String(),
+ cacheKey: cm.key(),
conn: conn,
reqch: make(chan requestAndChan, 50),
writech: make(chan writeRequest, 50),
@@ -517,6 +586,10 @@ type connectMethod struct {
targetAddr string // Not used if proxy + http targetScheme (4th example in table)
}
+func (ck *connectMethod) key() string {
+ return ck.String() // TODO: use a struct type instead
+}
+
func (ck *connectMethod) String() string {
proxyStr := ""
targetAddr := ck.targetAddr
@@ -592,7 +665,6 @@ 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
for alive {
pb, err := pc.br.Peek(1)
@@ -611,13 +683,6 @@ func (pc *persistConn) readLoop() {
rc := <-pc.reqch
- // Advance past the previous response's body, if the
- // caller hasn't done so.
- if lastbody != nil {
- lastbody.Close() // assumed idempotent
- lastbody = nil
- }
-
var resp *Response
if err == nil {
resp, err = ReadResponse(pc.br, rc.req)
@@ -636,7 +701,7 @@ func (pc *persistConn) readLoop() {
pc.close()
err = zerr
} else {
- resp.Body = &readFirstCloseBoth{&discardOnCloseReadCloser{gzReader}, resp.Body}
+ resp.Body = &readerAndCloser{gzReader, resp.Body}
}
}
resp.Body = &bodyEOFSignal{body: resp.Body}
@@ -648,8 +713,14 @@ func (pc *persistConn) readLoop() {
var waitForBodyRead chan bool
if hasBody {
- lastbody = resp.Body
- waitForBodyRead = make(chan bool, 1)
+ waitForBodyRead = make(chan bool, 2)
+ resp.Body.(*bodyEOFSignal).earlyCloseFn = func() error {
+ // Sending false here sets alive to
+ // false and closes the connection
+ // below.
+ waitForBodyRead <- false
+ return nil
+ }
resp.Body.(*bodyEOFSignal).fn = func(err error) {
alive1 := alive
if err != nil {
@@ -666,15 +737,6 @@ func (pc *persistConn) readLoop() {
}
if alive && !hasBody {
- // When there's no response body, we immediately
- // reuse the TCP connection (putIdleConn), but
- // we need to prevent ClientConn.Read from
- // closing the Response.Body on the next
- // loop, otherwise it might close the body
- // before the client code has had a chance to
- // read it (even though it'll just be 0, EOF).
- lastbody = nil
-
if !pc.t.putIdleConn(pc) {
alive = false
}
@@ -868,13 +930,16 @@ func canonicalAddr(url *url.URL) string {
// bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
// once, right before its final (error-producing) Read or Close call
-// returns.
+// returns. If earlyCloseFn is non-nil and Close is called before
+// io.EOF is seen, earlyCloseFn is called instead of fn, and its
+// return value is the return value from Close.
type bodyEOFSignal struct {
- body io.ReadCloser
- mu sync.Mutex // guards closed, rerr and fn
- closed bool // whether Close has been called
- rerr error // sticky Read error
- fn func(error) // error will be nil on Read io.EOF
+ body io.ReadCloser
+ mu sync.Mutex // guards following 4 fields
+ closed bool // whether Close has been called
+ rerr error // sticky Read error
+ fn func(error) // error will be nil on Read io.EOF
+ earlyCloseFn func() error // optional alt Close func used if io.EOF not seen
}
func (es *bodyEOFSignal) Read(p []byte) (n int, err error) {
@@ -907,6 +972,9 @@ func (es *bodyEOFSignal) Close() error {
return nil
}
es.closed = true
+ if es.earlyCloseFn != nil && es.rerr != io.EOF {
+ return es.earlyCloseFn()
+ }
err := es.body.Close()
es.condfn(err)
return err
@@ -924,28 +992,7 @@ func (es *bodyEOFSignal) condfn(err error) {
es.fn = nil
}
-type readFirstCloseBoth struct {
- io.ReadCloser
+type readerAndCloser struct {
+ io.Reader
io.Closer
}
-
-func (r *readFirstCloseBoth) Close() error {
- if err := r.ReadCloser.Close(); err != nil {
- r.Closer.Close()
- return err
- }
- if err := r.Closer.Close(); err != nil {
- return err
- }
- return nil
-}
-
-// discardOnCloseReadCloser consumes all its input on Close.
-type discardOnCloseReadCloser struct {
- io.ReadCloser
-}
-
-func (d *discardOnCloseReadCloser) Close() error {
- io.Copy(ioutil.Discard, d.ReadCloser) // ignore errors; likely invalid or already closed
- return d.ReadCloser.Close()
-}
diff --git a/src/pkg/net/http/transport_test.go b/src/pkg/net/http/transport_test.go
index 68010e68b..4bb711b17 100644
--- a/src/pkg/net/http/transport_test.go
+++ b/src/pkg/net/http/transport_test.go
@@ -102,7 +102,7 @@ func (tcs *testConnSet) check(t *testing.T) {
// Two subsequent requests and verify their response is the same.
// The response from the server is our own IP:port
func TestTransportKeepAlives(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
@@ -135,7 +135,7 @@ func TestTransportKeepAlives(t *testing.T) {
}
func TestTransportConnectionCloseOnResponse(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
@@ -186,7 +186,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
}
func TestTransportConnectionCloseOnRequest(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
@@ -237,7 +237,7 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) {
}
func TestTransportIdleCacheKeys(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
@@ -270,7 +270,7 @@ func TestTransportIdleCacheKeys(t *testing.T) {
}
func TestTransportMaxPerHostIdleConns(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
resch := make(chan string)
gotReq := make(chan bool)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -339,7 +339,7 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
}
func TestTransportServerClosingUnexpectedly(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
@@ -396,7 +396,7 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
// Test for http://golang.org/issue/2616 (appropriate issue number)
// This fails pretty reliably with GOMAXPROCS=100 or something high.
func TestStressSurpriseServerCloses(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
if testing.Short() {
t.Skip("skipping test in short mode")
}
@@ -452,7 +452,7 @@ func TestStressSurpriseServerCloses(t *testing.T) {
// TestTransportHeadResponses verifies that we deal with Content-Lengths
// with no bodies properly
func TestTransportHeadResponses(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.Method != "HEAD" {
panic("expected HEAD; got " + r.Method)
@@ -481,7 +481,7 @@ func TestTransportHeadResponses(t *testing.T) {
// TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
// on responses to HEAD requests.
func TestTransportHeadChunkedResponse(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.Method != "HEAD" {
panic("expected HEAD; got " + r.Method)
@@ -523,7 +523,7 @@ var roundTripTests = []struct {
// Test that the modification made to the Request by the RoundTripper is cleaned up
func TestRoundTripGzip(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const responseBody = "test response body"
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
accept := req.Header.Get("Accept-Encoding")
@@ -580,7 +580,7 @@ func TestRoundTripGzip(t *testing.T) {
}
func TestTransportGzip(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
const nRandBytes = 1024 * 1024
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
@@ -673,7 +673,7 @@ func TestTransportGzip(t *testing.T) {
}
func TestTransportProxy(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ch := make(chan string, 1)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
ch <- "real server"
@@ -702,7 +702,7 @@ func TestTransportProxy(t *testing.T) {
// but checks that we don't recurse forever, and checks that
// Content-Encoding is removed.
func TestTransportGzipRecursive(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Content-Encoding", "gzip")
w.Write(rgz)
@@ -729,7 +729,7 @@ func TestTransportGzipRecursive(t *testing.T) {
// tests that persistent goroutine connections shut down when no longer desired.
func TestTransportPersistConnLeak(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
gotReqCh := make(chan bool)
unblockCh := make(chan bool)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -795,7 +795,7 @@ func TestTransportPersistConnLeak(t *testing.T) {
// golang.org/issue/4531: Transport leaks goroutines when
// request.ContentLength is explicitly short
func TestTransportPersistConnLeakShortBody(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
}))
defer ts.Close()
@@ -834,7 +834,7 @@ func TestTransportPersistConnLeakShortBody(t *testing.T) {
// This used to crash; http://golang.org/issue/3266
func TestTransportIdleConnCrash(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
tr := &Transport{}
c := &Client{Transport: tr}
@@ -864,7 +864,7 @@ func TestTransportIdleConnCrash(t *testing.T) {
// which sadly lacked a triggering test. The large response body made
// the old race easier to trigger.
func TestIssue3644(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const numFoos = 5000
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Connection", "close")
@@ -892,7 +892,7 @@ 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) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const deniedMsg = "sorry, denied."
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
Error(w, deniedMsg, StatusUnauthorized)
@@ -917,7 +917,7 @@ func TestIssue3595(t *testing.T) {
// From http://golang.org/issue/4454 ,
// "client fails to handle requests with no body and chunked encoding"
func TestChunkedNoContent(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.WriteHeader(StatusNoContent)
}))
@@ -940,15 +940,18 @@ func TestChunkedNoContent(t *testing.T) {
}
func TestTransportConcurrency(t *testing.T) {
- defer checkLeakedTransports(t)
- const maxProcs = 16
- const numReqs = 500
+ defer afterTest(t)
+ maxProcs, numReqs := 16, 500
+ if testing.Short() {
+ maxProcs, numReqs = 4, 50
+ }
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{}
+ defer tr.CloseIdleConnections()
c := &Client{Transport: tr}
reqs := make(chan string)
defer close(reqs)
@@ -973,8 +976,8 @@ func TestTransportConcurrency(t *testing.T) {
if string(all) != req {
t.Errorf("body of req %s = %q; want %q", req, all, req)
}
- wg.Done()
res.Body.Close()
+ wg.Done()
}
}()
}
@@ -985,7 +988,7 @@ func TestTransportConcurrency(t *testing.T) {
}
func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const debug = false
mux := NewServeMux()
mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
@@ -1046,7 +1049,7 @@ func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
}
func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
const debug = false
mux := NewServeMux()
mux.HandleFunc("/get", func(w ResponseWriter, r *Request) {
@@ -1114,7 +1117,7 @@ func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
}
func TestTransportResponseHeaderTimeout(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
if testing.Short() {
t.Skip("skipping timeout test in -short mode")
}
@@ -1161,7 +1164,7 @@ func TestTransportResponseHeaderTimeout(t *testing.T) {
}
func TestTransportCancelRequest(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
if testing.Short() {
t.Skip("skipping test in -short mode")
}
@@ -1214,6 +1217,70 @@ func TestTransportCancelRequest(t *testing.T) {
}
}
+// golang.org/issue/3672 -- Client can't close HTTP stream
+// Calling Close on a Response.Body used to just read until EOF.
+// Now it actually closes the TCP connection.
+func TestTransportCloseResponseBody(t *testing.T) {
+ defer afterTest(t)
+ writeErr := make(chan error, 1)
+ msg := []byte("young\n")
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ for {
+ _, err := w.Write(msg)
+ if err != nil {
+ writeErr <- err
+ return
+ }
+ w.(Flusher).Flush()
+ }
+ }))
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+
+ req, _ := NewRequest("GET", ts.URL, nil)
+ defer tr.CancelRequest(req)
+
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ const repeats = 3
+ buf := make([]byte, len(msg)*repeats)
+ want := bytes.Repeat(msg, repeats)
+
+ _, err = io.ReadFull(res.Body, buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(buf, want) {
+ t.Errorf("read %q; want %q", buf, want)
+ }
+ didClose := make(chan error, 1)
+ go func() {
+ didClose <- res.Body.Close()
+ }()
+ select {
+ case err := <-didClose:
+ if err != nil {
+ t.Errorf("Close = %v", err)
+ }
+ case <-time.After(10 * time.Second):
+ t.Fatal("too long waiting for close")
+ }
+ select {
+ case err := <-writeErr:
+ if err == nil {
+ t.Errorf("expected non-nil write error")
+ }
+ case <-time.After(10 * time.Second):
+ t.Fatal("too long waiting for write error")
+ }
+}
+
type fooProto struct{}
func (fooProto) RoundTrip(req *Request) (*Response, error) {
@@ -1227,7 +1294,7 @@ func (fooProto) RoundTrip(req *Request) (*Response, error) {
}
func TestTransportAltProto(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
tr := &Transport{}
c := &Client{Transport: tr}
tr.RegisterProtocol("foo", fooProto{})
@@ -1246,7 +1313,7 @@ func TestTransportAltProto(t *testing.T) {
}
func TestTransportNoHost(t *testing.T) {
- defer checkLeakedTransports(t)
+ defer afterTest(t)
tr := &Transport{}
_, err := tr.RoundTrip(&Request{
Header: make(Header),
@@ -1260,6 +1327,64 @@ func TestTransportNoHost(t *testing.T) {
}
}
+func TestTransportSocketLateBinding(t *testing.T) {
+ defer afterTest(t)
+
+ mux := NewServeMux()
+ fooGate := make(chan bool, 1)
+ mux.HandleFunc("/foo", func(w ResponseWriter, r *Request) {
+ w.Header().Set("foo-ipport", r.RemoteAddr)
+ w.(Flusher).Flush()
+ <-fooGate
+ })
+ mux.HandleFunc("/bar", func(w ResponseWriter, r *Request) {
+ w.Header().Set("bar-ipport", r.RemoteAddr)
+ })
+ ts := httptest.NewServer(mux)
+ defer ts.Close()
+
+ dialGate := make(chan bool, 1)
+ tr := &Transport{
+ Dial: func(n, addr string) (net.Conn, error) {
+ <-dialGate
+ return net.Dial(n, addr)
+ },
+ DisableKeepAlives: false,
+ }
+ defer tr.CloseIdleConnections()
+ c := &Client{
+ Transport: tr,
+ }
+
+ dialGate <- true // only allow one dial
+ fooRes, err := c.Get(ts.URL + "/foo")
+ if err != nil {
+ t.Fatal(err)
+ }
+ fooAddr := fooRes.Header.Get("foo-ipport")
+ if fooAddr == "" {
+ t.Fatal("No addr on /foo request")
+ }
+ time.AfterFunc(200*time.Millisecond, func() {
+ // let the foo response finish so we can use its
+ // connection for /bar
+ fooGate <- true
+ io.Copy(ioutil.Discard, fooRes.Body)
+ fooRes.Body.Close()
+ })
+
+ barRes, err := c.Get(ts.URL + "/bar")
+ if err != nil {
+ t.Fatal(err)
+ }
+ barAddr := barRes.Header.Get("bar-ipport")
+ if barAddr != fooAddr {
+ t.Fatalf("/foo came from conn %q; /bar came from %q instead", fooAddr, barAddr)
+ }
+ barRes.Body.Close()
+ dialGate <- true
+}
+
type proxyFromEnvTest struct {
req string // URL to fetch; blank means "http://example.com"
env string
diff --git a/src/pkg/net/http/z_last_test.go b/src/pkg/net/http/z_last_test.go
index 44095a8d9..a80fb01d0 100644
--- a/src/pkg/net/http/z_last_test.go
+++ b/src/pkg/net/http/z_last_test.go
@@ -7,27 +7,60 @@ package http_test
import (
"net/http"
"runtime"
+ "sort"
"strings"
"testing"
"time"
)
+func interestingGoroutines() (gs []string) {
+ buf := make([]byte, 2<<20)
+ buf = buf[:runtime.Stack(buf, true)]
+ for _, g := range strings.Split(string(buf), "\n\n") {
+ sl := strings.SplitN(g, "\n", 2)
+ if len(sl) != 2 {
+ continue
+ }
+ stack := strings.TrimSpace(sl[1])
+ if stack == "" ||
+ strings.Contains(stack, "created by net.newPollServer") ||
+ strings.Contains(stack, "created by net.startServer") ||
+ strings.Contains(stack, "created by testing.RunTests") ||
+ strings.Contains(stack, "closeWriteAndWait") ||
+ strings.Contains(stack, "testing.Main(") {
+ continue
+ }
+ gs = append(gs, stack)
+ }
+ sort.Strings(gs)
+ return
+}
+
// Verify the other tests didn't leave any goroutines running.
// This is in a file named z_last_test.go so it sorts at the end.
func TestGoroutinesRunning(t *testing.T) {
- n := runtime.NumGoroutine()
+ if testing.Short() {
+ t.Skip("not counting goroutines for leakage in -short mode")
+ }
+ gs := interestingGoroutines()
+
+ n := 0
+ stackCount := make(map[string]int)
+ for _, g := range gs {
+ stackCount[g]++
+ n++
+ }
+
t.Logf("num goroutines = %d", n)
- if n > 20 {
- // Currently 14 on Linux (blocked in epoll_wait,
- // waiting for on fds that are closed?), but give some
- // slop for now.
- buf := make([]byte, 1<<20)
- buf = buf[:runtime.Stack(buf, true)]
- t.Errorf("Too many goroutines:\n%s", buf)
+ if n > 0 {
+ t.Error("Too many goroutines.")
+ for stack, count := range stackCount {
+ t.Logf("%d instances of:\n%s", count, stack)
+ }
}
}
-func checkLeakedTransports(t *testing.T) {
+func afterTest(t *testing.T) {
http.DefaultTransport.(*http.Transport).CloseIdleConnections()
if testing.Short() {
return
@@ -40,6 +73,7 @@ func checkLeakedTransports(t *testing.T) {
").writeLoop(": "a Transport",
"created by net/http/httptest.(*Server).Start": "an httptest.Server",
"timeoutHandler": "a TimeoutHandler",
+ "net.(*netFD).connect(": "a timing out dial",
}
for i := 0; i < 4; i++ {
bad = ""
@@ -56,5 +90,6 @@ func checkLeakedTransports(t *testing.T) {
// shutting down, so give it some time.
time.Sleep(250 * time.Millisecond)
}
- t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
+ gs := interestingGoroutines()
+ t.Errorf("Test appears to have leaked %s:\n%s", bad, strings.Join(gs, "\n\n"))
}
diff --git a/src/pkg/net/interface_bsd.go b/src/pkg/net/interface_bsd.go
index f58065a85..716b60a97 100644
--- a/src/pkg/net/interface_bsd.go
+++ b/src/pkg/net/interface_bsd.go
@@ -171,7 +171,6 @@ func newAddr(ifi *Interface, m *syscall.InterfaceAddrMessage) (Addr, error) {
// the interface index in the interface-local or link-
// local address as the kernel-internal form.
if ifa.IP.IsLinkLocalUnicast() {
- ifa.Zone = ifi.Name
ifa.IP[2], ifa.IP[3] = 0, 0
}
}
diff --git a/src/pkg/net/interface_darwin.go b/src/pkg/net/interface_darwin.go
index 83e483ba2..ad0937db0 100644
--- a/src/pkg/net/interface_darwin.go
+++ b/src/pkg/net/interface_darwin.go
@@ -50,11 +50,10 @@ func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage)
case *syscall.SockaddrInet6:
ifma := &IPAddr{IP: make(IP, IPv6len)}
copy(ifma.IP, sa.Addr[:])
- // NOTE: KAME based IPv6 protcol stack usually embeds
+ // NOTE: KAME based IPv6 protocol stack usually embeds
// the interface index in the interface-local or link-
// local address as the kernel-internal form.
if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
- ifma.Zone = ifi.Name
ifma.IP[2], ifma.IP[3] = 0, 0
}
ifmat = append(ifmat, ifma.toAddr())
diff --git a/src/pkg/net/interface_freebsd.go b/src/pkg/net/interface_freebsd.go
index 1bf5ae72b..5df767910 100644
--- a/src/pkg/net/interface_freebsd.go
+++ b/src/pkg/net/interface_freebsd.go
@@ -50,11 +50,10 @@ func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage)
case *syscall.SockaddrInet6:
ifma := &IPAddr{IP: make(IP, IPv6len)}
copy(ifma.IP, sa.Addr[:])
- // NOTE: KAME based IPv6 protcol stack usually embeds
+ // NOTE: KAME based IPv6 protocol stack usually embeds
// the interface index in the interface-local or link-
// local address as the kernel-internal form.
if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
- ifma.Zone = ifi.Name
ifma.IP[2], ifma.IP[3] = 0, 0
}
ifmat = append(ifmat, ifma.toAddr())
diff --git a/src/pkg/net/interface_linux.go b/src/pkg/net/interface_linux.go
index e66daef06..1207c0f26 100644
--- a/src/pkg/net/interface_linux.go
+++ b/src/pkg/net/interface_linux.go
@@ -156,9 +156,6 @@ func newAddr(ifi *Interface, ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRou
case syscall.AF_INET6:
ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)}
copy(ifa.IP, a.Value[:])
- if ifam.Scope == syscall.RT_SCOPE_HOST || ifam.Scope == syscall.RT_SCOPE_LINK {
- ifa.Zone = ifi.Name
- }
return ifa
}
}
@@ -229,9 +226,6 @@ func parseProcNetIGMP6(path string, ifi *Interface) []Addr {
b[i/2], _ = xtoi2(f[2][i:i+2], 0)
}
ifma := IPAddr{IP: IP{b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]}}
- if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
- ifma.Zone = ifi.Name
- }
ifmat = append(ifmat, ifma.toAddr())
}
}
diff --git a/src/pkg/net/interface_test.go b/src/pkg/net/interface_test.go
index 7fb342818..e31894abf 100644
--- a/src/pkg/net/interface_test.go
+++ b/src/pkg/net/interface_test.go
@@ -25,6 +25,32 @@ func loopbackInterface() *Interface {
return nil
}
+// ipv6LinkLocalUnicastAddr returns an IPv6 link-local unicast address
+// on the given network interface for tests. It returns "" if no
+// suitable address is found.
+func ipv6LinkLocalUnicastAddr(ifi *Interface) string {
+ if ifi == nil {
+ return ""
+ }
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ return ""
+ }
+ for _, ifa := range ifat {
+ switch ifa := ifa.(type) {
+ case *IPAddr:
+ if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
+ return ifa.IP.String()
+ }
+ case *IPNet:
+ if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
+ return ifa.IP.String()
+ }
+ }
+ }
+ return ""
+}
+
func TestInterfaces(t *testing.T) {
ift, err := Interfaces()
if err != nil {
@@ -81,9 +107,9 @@ func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
func testAddrs(t *testing.T, ifat []Addr) {
for _, ifa := range ifat {
- switch v := ifa.(type) {
+ switch ifa := ifa.(type) {
case *IPAddr, *IPNet:
- if v == nil {
+ if ifa == nil {
t.Errorf("\tunexpected value: %v", ifa)
} else {
t.Logf("\tinterface address %q", ifa.String())
@@ -96,9 +122,9 @@ func testAddrs(t *testing.T, ifat []Addr) {
func testMulticastAddrs(t *testing.T, ifmat []Addr) {
for _, ifma := range ifmat {
- switch v := ifma.(type) {
+ switch ifma := ifma.(type) {
case *IPAddr:
- if v == nil {
+ if ifma == nil {
t.Errorf("\tunexpected value: %v", ifma)
} else {
t.Logf("\tjoined group address %q", ifma.String())
diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go
index d588e3a42..0e42da216 100644
--- a/src/pkg/net/ip.go
+++ b/src/pkg/net/ip.go
@@ -36,7 +36,6 @@ type IPMask []byte
type IPNet struct {
IP IP // network number
Mask IPMask // network mask
- Zone string // IPv6 scoped addressing zone
}
// IPv4 returns the IP address (in 16-byte form) of the
@@ -223,7 +222,6 @@ func (ip IP) DefaultMask() IPMask {
default:
return classCMask
}
- return nil // not reached
}
func allFF(b []byte) bool {
@@ -433,6 +431,9 @@ func (n *IPNet) Contains(ip IP) bool {
return true
}
+// Network returns the address's network name, "ip+net".
+func (n *IPNet) Network() string { return "ip+net" }
+
// String returns the CIDR notation of n like "192.168.100.1/24"
// or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291.
// If the mask is not in the canonical form, it returns the
@@ -451,9 +452,6 @@ func (n *IPNet) String() string {
return nn.String() + "/" + itod(uint(l))
}
-// Network returns the address's network name, "ip+net".
-func (n *IPNet) Network() string { return "ip+net" }
-
// Parse IPv4 address (d.d.d.d).
func parseIPv4(s string) IP {
var p [IPv4len]byte
@@ -485,26 +483,26 @@ func parseIPv4(s string) IP {
return IPv4(p[0], p[1], p[2], p[3])
}
-// Parse IPv6 address. Many forms.
-// The basic form is a sequence of eight colon-separated
-// 16-bit hex numbers separated by colons,
-// as in 0123:4567:89ab:cdef:0123:4567:89ab:cdef.
-// Two exceptions:
-// * A run of zeros can be replaced with "::".
-// * The last 32 bits can be in IPv4 form.
-// Thus, ::ffff:1.2.3.4 is the IPv4 address 1.2.3.4.
-func parseIPv6(s string) IP {
- p := make(IP, IPv6len)
+// parseIPv6 parses s as a literal IPv6 address described in RFC 4291
+// and RFC 5952. It can also parse a literal scoped IPv6 address with
+// zone identifier which is described in RFC 4007 when zoneAllowed is
+// true.
+func parseIPv6(s string, zoneAllowed bool) (ip IP, zone string) {
+ ip = make(IP, IPv6len)
ellipsis := -1 // position of ellipsis in p
i := 0 // index in string s
+ if zoneAllowed {
+ s, zone = splitHostZone(s)
+ }
+
// Might have leading ellipsis
if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
ellipsis = 0
i = 2
// Might be only ellipsis
if i == len(s) {
- return p
+ return ip, zone
}
}
@@ -514,35 +512,35 @@ func parseIPv6(s string) IP {
// Hex number.
n, i1, ok := xtoi(s, i)
if !ok || n > 0xFFFF {
- return nil
+ return nil, zone
}
// If followed by dot, might be in trailing IPv4.
if i1 < len(s) && s[i1] == '.' {
if ellipsis < 0 && j != IPv6len-IPv4len {
// Not the right place.
- return nil
+ return nil, zone
}
if j+IPv4len > IPv6len {
// Not enough room.
- return nil
+ return nil, zone
}
- p4 := parseIPv4(s[i:])
- if p4 == nil {
- return nil
+ ip4 := parseIPv4(s[i:])
+ if ip4 == nil {
+ return nil, zone
}
- p[j] = p4[12]
- p[j+1] = p4[13]
- p[j+2] = p4[14]
- p[j+3] = p4[15]
+ ip[j] = ip4[12]
+ ip[j+1] = ip4[13]
+ ip[j+2] = ip4[14]
+ ip[j+3] = ip4[15]
i = len(s)
j += IPv4len
break
}
// Save this 16-bit chunk.
- p[j] = byte(n >> 8)
- p[j+1] = byte(n)
+ ip[j] = byte(n >> 8)
+ ip[j+1] = byte(n)
j += 2
// Stop at end of string.
@@ -553,14 +551,14 @@ func parseIPv6(s string) IP {
// Otherwise must be followed by colon and more.
if s[i] != ':' || i+1 == len(s) {
- return nil
+ return nil, zone
}
i++
// Look for ellipsis.
if s[i] == ':' {
if ellipsis >= 0 { // already have one
- return nil
+ return nil, zone
}
ellipsis = j
if i++; i == len(s) { // can be at end
@@ -571,23 +569,23 @@ func parseIPv6(s string) IP {
// Must have used entire string.
if i != len(s) {
- return nil
+ return nil, zone
}
// If didn't parse enough, expand ellipsis.
if j < IPv6len {
if ellipsis < 0 {
- return nil
+ return nil, zone
}
n := IPv6len - j
for k := j - 1; k >= ellipsis; k-- {
- p[k+n] = p[k]
+ ip[k+n] = ip[k]
}
for k := ellipsis + n - 1; k >= ellipsis; k-- {
- p[k] = 0
+ ip[k] = 0
}
}
- return p
+ return ip, zone
}
// A ParseError represents a malformed text string and the type of string that was expected.
@@ -600,26 +598,17 @@ func (e *ParseError) Error() string {
return "invalid " + e.Type + ": " + e.Text
}
-func parseIP(s string) IP {
- if p := parseIPv4(s); p != nil {
- return p
- }
- if p := parseIPv6(s); p != nil {
- return p
- }
- return nil
-}
-
// ParseIP parses s as an IP address, returning the result.
// The string s can be in dotted decimal ("74.125.19.99")
// or IPv6 ("2001:4860:0:2001::68") form.
// If s is not a valid textual representation of an IP address,
// ParseIP returns nil.
func ParseIP(s string) IP {
- if p := parseIPv4(s); p != nil {
- return p
+ if ip := parseIPv4(s); ip != nil {
+ return ip
}
- return parseIPv6(s)
+ ip, _ := parseIPv6(s, false)
+ return ip
}
// ParseCIDR parses s as a CIDR notation IP address and mask,
@@ -634,15 +623,15 @@ func ParseCIDR(s string) (IP, *IPNet, error) {
if i < 0 {
return nil, nil, &ParseError{"CIDR address", s}
}
- ipstr, maskstr := s[:i], s[i+1:]
+ addr, mask := s[:i], s[i+1:]
iplen := IPv4len
- ip := parseIPv4(ipstr)
+ ip := parseIPv4(addr)
if ip == nil {
iplen = IPv6len
- ip = parseIPv6(ipstr)
+ ip, _ = parseIPv6(addr, false)
}
- n, i, ok := dtoi(maskstr, 0)
- if ip == nil || !ok || i != len(maskstr) || n < 0 || n > 8*iplen {
+ n, i, ok := dtoi(mask, 0)
+ if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
return nil, nil, &ParseError{"CIDR address", s}
}
m := CIDRMask(n, 8*iplen)
diff --git a/src/pkg/net/ip_test.go b/src/pkg/net/ip_test.go
index f8b7f067f..16f30d446 100644
--- a/src/pkg/net/ip_test.go
+++ b/src/pkg/net/ip_test.go
@@ -5,23 +5,12 @@
package net
import (
- "bytes"
"reflect"
"runtime"
"testing"
)
-func isEqual(a, b []byte) bool {
- if a == nil && b == nil {
- return true
- }
- if a == nil || b == nil {
- return false
- }
- return bytes.Equal(a, b)
-}
-
-var parseiptests = []struct {
+var parseIPTests = []struct {
in string
out IP
}{
@@ -33,22 +22,23 @@ var parseiptests = []struct {
{"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
{"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
{"::ffff:4a7d:1363", IPv4(74, 125, 19, 99)},
+ {"fe80::1%lo0", nil},
+ {"fe80::1%911", nil},
{"", nil},
}
func TestParseIP(t *testing.T) {
- for _, tt := range parseiptests {
- if out := ParseIP(tt.in); !isEqual(out, tt.out) {
+ for _, tt := range parseIPTests {
+ if out := ParseIP(tt.in); !reflect.DeepEqual(out, tt.out) {
t.Errorf("ParseIP(%q) = %v, want %v", tt.in, out, tt.out)
}
}
}
-var ipstringtests = []struct {
+var ipStringTests = []struct {
in IP
- out string
+ out string // see RFC 5952
}{
- // cf. RFC 5952 (A Recommendation for IPv6 Address Text Representation)
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, "2001:db8::123:12:1"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1}, "2001:db8:0:1:0:1:0:1"},
@@ -61,14 +51,14 @@ var ipstringtests = []struct {
}
func TestIPString(t *testing.T) {
- for _, tt := range ipstringtests {
+ for _, tt := range ipStringTests {
if out := tt.in.String(); out != tt.out {
t.Errorf("IP.String(%v) = %q, want %q", tt.in, out, tt.out)
}
}
}
-var ipmasktests = []struct {
+var ipMaskTests = []struct {
in IP
mask IPMask
out IP
@@ -82,14 +72,14 @@ var ipmasktests = []struct {
}
func TestIPMask(t *testing.T) {
- for _, tt := range ipmasktests {
+ for _, tt := range ipMaskTests {
if out := tt.in.Mask(tt.mask); out == nil || !tt.out.Equal(out) {
t.Errorf("IP(%v).Mask(%v) = %v, want %v", tt.in, tt.mask, out, tt.out)
}
}
}
-var ipmaskstringtests = []struct {
+var ipMaskStringTests = []struct {
in IPMask
out string
}{
@@ -101,14 +91,14 @@ var ipmaskstringtests = []struct {
}
func TestIPMaskString(t *testing.T) {
- for _, tt := range ipmaskstringtests {
+ for _, tt := range ipMaskStringTests {
if out := tt.in.String(); out != tt.out {
t.Errorf("IPMask.String(%v) = %q, want %q", tt.in, out, tt.out)
}
}
}
-var parsecidrtests = []struct {
+var parseCIDRTests = []struct {
in string
ip IP
net *IPNet
@@ -138,18 +128,18 @@ var parsecidrtests = []struct {
}
func TestParseCIDR(t *testing.T) {
- for _, tt := range parsecidrtests {
+ for _, tt := range parseCIDRTests {
ip, net, err := ParseCIDR(tt.in)
if !reflect.DeepEqual(err, tt.err) {
t.Errorf("ParseCIDR(%q) = %v, %v; want %v, %v", tt.in, ip, net, tt.ip, tt.net)
}
- if err == nil && (!tt.ip.Equal(ip) || !tt.net.IP.Equal(net.IP) || !isEqual(net.Mask, tt.net.Mask)) {
- t.Errorf("ParseCIDR(%q) = %v, {%v, %v}; want %v {%v, %v}", tt.in, ip, net.IP, net.Mask, tt.ip, tt.net.IP, tt.net.Mask)
+ if err == nil && (!tt.ip.Equal(ip) || !tt.net.IP.Equal(net.IP) || !reflect.DeepEqual(net.Mask, tt.net.Mask)) {
+ t.Errorf("ParseCIDR(%q) = %v, {%v, %v}; want %v, {%v, %v}", tt.in, ip, net.IP, net.Mask, tt.ip, tt.net.IP, tt.net.Mask)
}
}
}
-var ipnetcontainstests = []struct {
+var ipNetContainsTests = []struct {
ip IP
net *IPNet
ok bool
@@ -165,14 +155,14 @@ var ipnetcontainstests = []struct {
}
func TestIPNetContains(t *testing.T) {
- for _, tt := range ipnetcontainstests {
+ for _, tt := range ipNetContainsTests {
if ok := tt.net.Contains(tt.ip); ok != tt.ok {
t.Errorf("IPNet(%v).Contains(%v) = %v, want %v", tt.net, tt.ip, ok, tt.ok)
}
}
}
-var ipnetstringtests = []struct {
+var ipNetStringTests = []struct {
in *IPNet
out string
}{
@@ -183,14 +173,14 @@ var ipnetstringtests = []struct {
}
func TestIPNetString(t *testing.T) {
- for _, tt := range ipnetstringtests {
+ for _, tt := range ipNetStringTests {
if out := tt.in.String(); out != tt.out {
t.Errorf("IPNet.String(%v) = %q, want %q", tt.in, out, tt.out)
}
}
}
-var cidrmasktests = []struct {
+var cidrMaskTests = []struct {
ones int
bits int
out IPMask
@@ -210,8 +200,8 @@ var cidrmasktests = []struct {
}
func TestCIDRMask(t *testing.T) {
- for _, tt := range cidrmasktests {
- if out := CIDRMask(tt.ones, tt.bits); !isEqual(out, tt.out) {
+ for _, tt := range cidrMaskTests {
+ if out := CIDRMask(tt.ones, tt.bits); !reflect.DeepEqual(out, tt.out) {
t.Errorf("CIDRMask(%v, %v) = %v, want %v", tt.ones, tt.bits, out, tt.out)
}
}
@@ -229,7 +219,7 @@ var (
v4maskzero = IPMask{0, 0, 0, 0}
)
-var networknumberandmasktests = []struct {
+var networkNumberAndMaskTests = []struct {
in IPNet
out IPNet
}{
@@ -251,75 +241,90 @@ var networknumberandmasktests = []struct {
}
func TestNetworkNumberAndMask(t *testing.T) {
- for _, tt := range networknumberandmasktests {
+ for _, tt := range networkNumberAndMaskTests {
ip, m := networkNumberAndMask(&tt.in)
out := &IPNet{IP: ip, Mask: m}
if !reflect.DeepEqual(&tt.out, out) {
- t.Errorf("networkNumberAndMask(%v) = %v; want %v", tt.in, out, &tt.out)
+ t.Errorf("networkNumberAndMask(%v) = %v, want %v", tt.in, out, &tt.out)
}
}
}
-var splitjointests = []struct {
- Host string
- Port string
- Join string
+var splitJoinTests = []struct {
+ host string
+ port string
+ join string
}{
{"www.google.com", "80", "www.google.com:80"},
{"127.0.0.1", "1234", "127.0.0.1:1234"},
{"::1", "80", "[::1]:80"},
- {"google.com", "https%foo", "google.com:https%foo"}, // Go 1.0 behavior
+ {"fe80::1%lo0", "80", "[fe80::1%lo0]:80"},
+ {"localhost%lo0", "80", "[localhost%lo0]:80"},
{"", "0", ":0"},
- {"127.0.0.1", "", "127.0.0.1:"}, // Go 1.0 behaviour
- {"www.google.com", "", "www.google.com:"}, // Go 1.0 behaviour
+
+ {"google.com", "https%foo", "google.com:https%foo"}, // Go 1.0 behavior
+ {"127.0.0.1", "", "127.0.0.1:"}, // Go 1.0 behaviour
+ {"www.google.com", "", "www.google.com:"}, // Go 1.0 behaviour
}
-var splitfailuretests = []struct {
- HostPort string
- Err string
+var splitFailureTests = []struct {
+ hostPort string
+ err string
}{
{"www.google.com", "missing port in address"},
{"127.0.0.1", "missing port in address"},
{"[::1]", "missing port in address"},
+ {"[fe80::1%lo0]", "missing port in address"},
+ {"[localhost%lo0]", "missing port in address"},
+ {"localhost%lo0", "missing port in address"},
+
{"::1", "too many colons in address"},
+ {"fe80::1%lo0", "too many colons in address"},
+ {"fe80::1%lo0:80", "too many colons in address"},
+
+ {"localhost%lo0:80", "missing brackets in address"},
// Test cases that didn't fail in Go 1.0
+
{"[foo:bar]", "missing port in address"},
{"[foo:bar]baz", "missing port in address"},
- {"[foo]:[bar]:baz", "too many colons in address"},
{"[foo]bar:baz", "missing port in address"},
+
+ {"[foo]:[bar]:baz", "too many colons in address"},
+
{"[foo]:[bar]baz", "unexpected '[' in address"},
{"foo[bar]:baz", "unexpected '[' in address"},
+
{"foo]bar:baz", "unexpected ']' in address"},
}
func TestSplitHostPort(t *testing.T) {
- for _, tt := range splitjointests {
- if host, port, err := SplitHostPort(tt.Join); host != tt.Host || port != tt.Port || err != nil {
- t.Errorf("SplitHostPort(%q) = %q, %q, %v; want %q, %q, nil", tt.Join, host, port, err, tt.Host, tt.Port)
+ for _, tt := range splitJoinTests {
+ if host, port, err := SplitHostPort(tt.join); host != tt.host || port != tt.port || err != nil {
+ t.Errorf("SplitHostPort(%q) = %q, %q, %v; want %q, %q, nil", tt.join, host, port, err, tt.host, tt.port)
}
}
- for _, tt := range splitfailuretests {
- if _, _, err := SplitHostPort(tt.HostPort); err == nil {
- t.Errorf("SplitHostPort(%q) should have failed", tt.HostPort)
+ for _, tt := range splitFailureTests {
+ if _, _, err := SplitHostPort(tt.hostPort); err == nil {
+ t.Errorf("SplitHostPort(%q) should have failed", tt.hostPort)
} else {
e := err.(*AddrError)
- if e.Err != tt.Err {
- t.Errorf("SplitHostPort(%q) = _, _, %q; want %q", tt.HostPort, e.Err, tt.Err)
+ if e.Err != tt.err {
+ t.Errorf("SplitHostPort(%q) = _, _, %q; want %q", tt.hostPort, e.Err, tt.err)
}
}
}
}
func TestJoinHostPort(t *testing.T) {
- for _, tt := range splitjointests {
- if join := JoinHostPort(tt.Host, tt.Port); join != tt.Join {
- t.Errorf("JoinHostPort(%q, %q) = %q; want %q", tt.Host, tt.Port, join, tt.Join)
+ for _, tt := range splitJoinTests {
+ if join := JoinHostPort(tt.host, tt.port); join != tt.join {
+ t.Errorf("JoinHostPort(%q, %q) = %q; want %q", tt.host, tt.port, join, tt.join)
}
}
}
-var ipaftests = []struct {
+var ipAddrFamilyTests = []struct {
in IP
af4 bool
af6 bool
@@ -342,7 +347,7 @@ var ipaftests = []struct {
}
func TestIPAddrFamily(t *testing.T) {
- for _, tt := range ipaftests {
+ for _, tt := range ipAddrFamilyTests {
if af := tt.in.To4() != nil; af != tt.af4 {
t.Errorf("verifying IPv4 address family for %q = %v, want %v", tt.in, af, tt.af4)
}
@@ -352,7 +357,7 @@ func TestIPAddrFamily(t *testing.T) {
}
}
-var ipscopetests = []struct {
+var ipAddrScopeTests = []struct {
scope func(IP) bool
in IP
ok bool
@@ -393,7 +398,7 @@ func name(f interface{}) string {
}
func TestIPAddrScope(t *testing.T) {
- for _, tt := range ipscopetests {
+ for _, tt := range ipAddrScopeTests {
if ok := tt.scope(tt.in); ok != tt.ok {
t.Errorf("%s(%q) = %v, want %v", name(tt.scope), tt.in, ok, tt.ok)
}
diff --git a/src/pkg/net/ipraw_test.go b/src/pkg/net/ipraw_test.go
index 65defc7ea..841b57ab4 100644
--- a/src/pkg/net/ipraw_test.go
+++ b/src/pkg/net/ipraw_test.go
@@ -2,13 +2,12 @@
// 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 (
"bytes"
"errors"
+ "fmt"
"os"
"reflect"
"testing"
@@ -29,6 +28,11 @@ var resolveIPAddrTests = []struct {
{"ip6", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
{"ip6:icmp", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+ {"ip", "::1%en0", &IPAddr{IP: ParseIP("::1"), Zone: "en0"}, nil},
+ {"ip6", "::1%911", &IPAddr{IP: ParseIP("::1"), Zone: "911"}, nil},
+ {"ip6", "fe80::1", &IPAddr{IP: ParseIP("fe80::1"), Zone: "name"}, nil},
+ {"ip6", "fe80::1", &IPAddr{IP: ParseIP("fe80::1"), Zone: "index"}, nil},
+
{"", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, // Go 1.0 behavior
{"", "::1", &IPAddr{IP: ParseIP("::1")}, nil}, // Go 1.0 behavior
@@ -39,6 +43,21 @@ var resolveIPAddrTests = []struct {
func TestResolveIPAddr(t *testing.T) {
for _, tt := range resolveIPAddrTests {
+ if tt.addr != nil && (tt.addr.Zone == "name" || tt.addr.Zone == "index") {
+ ifi := loopbackInterface()
+ if ifi == nil {
+ continue
+ }
+ switch tt.addr.Zone {
+ case "name":
+ tt.litAddr += "%" + ifi.Name
+ tt.addr.Zone = zoneToString(ifi.Index)
+ case "index":
+ index := fmt.Sprintf("%v", ifi.Index)
+ tt.litAddr += "%" + index
+ tt.addr.Zone = index
+ }
+ }
addr, err := ResolveIPAddr(tt.net, tt.litAddr)
if err != tt.err {
t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
@@ -339,3 +358,19 @@ func TestIPConnLocalName(t *testing.T) {
}
}
}
+
+func TestIPConnRemoteName(t *testing.T) {
+ if os.Getuid() != 0 {
+ t.Skip("skipping test; must be root")
+ }
+
+ raddr := &IPAddr{IP: IPv4(127, 0, 0, 10).To4()}
+ c, err := DialIP("ip:tcp", &IPAddr{IP: IPv4(127, 0, 0, 1)}, raddr)
+ if err != nil {
+ t.Fatalf("DialIP failed: %v", err)
+ }
+ defer c.Close()
+ if !reflect.DeepEqual(raddr, c.RemoteAddr()) {
+ t.Fatalf("got %#v, expected %#v", c.RemoteAddr(), raddr)
+ }
+}
diff --git a/src/pkg/net/iprawsock.go b/src/pkg/net/iprawsock.go
index daccba366..9d99e7591 100644
--- a/src/pkg/net/iprawsock.go
+++ b/src/pkg/net/iprawsock.go
@@ -19,12 +19,15 @@ func (a *IPAddr) String() string {
if a == nil {
return "<nil>"
}
+ if a.Zone != "" {
+ return a.IP.String() + "%" + a.Zone
+ }
return a.IP.String()
}
-// ResolveIPAddr parses addr as an IP address and resolves domain
-// names to numeric addresses on the network net, which must be
-// "ip", "ip4" or "ip6".
+// ResolveIPAddr parses addr as an IP address of the form "host" or
+// "ipv6-host%zone" and resolves the domain name on the network net,
+// which must be "ip", "ip4" or "ip6".
func ResolveIPAddr(net, addr string) (*IPAddr, error) {
if net == "" { // a hint wildcard for Go 1.0 undocumented behavior
net = "ip"
diff --git a/src/pkg/net/iprawsock_plan9.go b/src/pkg/net/iprawsock_plan9.go
index 88e3b2c60..43a5eab41 100644
--- a/src/pkg/net/iprawsock_plan9.go
+++ b/src/pkg/net/iprawsock_plan9.go
@@ -34,7 +34,7 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
}
// 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
+// 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 *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index 2ef4db19c..1bcaef9f2 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -98,7 +98,7 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
}
// 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
+// 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 *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
diff --git a/src/pkg/net/ipsock.go b/src/pkg/net/ipsock.go
index 1ef489289..d93059587 100644
--- a/src/pkg/net/ipsock.go
+++ b/src/pkg/net/ipsock.go
@@ -68,15 +68,12 @@ func (e InvalidAddrError) Error() string { return string(e) }
func (e InvalidAddrError) Timeout() bool { return false }
func (e InvalidAddrError) Temporary() bool { return false }
-// SplitHostPort splits a network address of the form
-// "host:port" or "[host]:port" into host and port.
-// The latter form must be used when host contains a colon.
+// SplitHostPort splits a network address of the form "host:port",
+// "[host]:port" or "[ipv6-host%zone]:port" into host or
+// ipv6-host%zone and port. A literal address or host name for IPv6
+// must be enclosed in square brackets, as in "[::1]:80",
+// "[ipv6-host]:http" or "[ipv6-host%zone]:80".
func SplitHostPort(hostport string) (host, port string, err error) {
- host, port, _, err = splitHostPort(hostport)
- return
-}
-
-func splitHostPort(hostport string) (host, port, zone string, err error) {
j, k := 0, 0
// The port starts after the last colon.
@@ -110,10 +107,12 @@ func splitHostPort(hostport string) (host, port, zone string, err error) {
j, k = 1, end+1 // there can't be a '[' resp. ']' before these positions
} else {
host = hostport[:i]
-
if byteIndex(host, ':') >= 0 {
goto tooManyColons
}
+ if byteIndex(host, '%') >= 0 {
+ goto missingBrackets
+ }
}
if byteIndex(hostport[j:], '[') >= 0 {
err = &AddrError{"unexpected '[' in address", hostport}
@@ -134,13 +133,29 @@ missingPort:
tooManyColons:
err = &AddrError{"too many colons in address", hostport}
return
+
+missingBrackets:
+ err = &AddrError{"missing brackets in address", hostport}
+ return
+}
+
+func splitHostZone(s string) (host, zone string) {
+ // The IPv6 scoped addressing zone identifer starts after the
+ // last percent sign.
+ if i := last(s, '%'); i > 0 {
+ host, zone = s[:i], s[i+1:]
+ } else {
+ host = s
+ }
+ return
}
-// JoinHostPort combines host and port into a network address
-// of the form "host:port" or, if host contains a colon, "[host]:port".
+// JoinHostPort combines host and port into a network address of the
+// form "host:port" or, if host contains a colon or a percent sign,
+// "[host]:port".
func JoinHostPort(host, port string) string {
- // If host has colons, have to bracket it.
- if byteIndex(host, ':') >= 0 {
+ // If host has colons or a percent sign, have to bracket it.
+ if byteIndex(host, ':') >= 0 || byteIndex(host, '%') >= 0 {
return "[" + host + "]:" + port
}
return host + ":" + port
@@ -155,7 +170,7 @@ func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
switch net {
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
if addr != "" {
- if host, port, zone, err = splitHostPort(addr); err != nil {
+ if host, port, err = SplitHostPort(addr); err != nil {
return nil, err
}
if portnum, err = parsePort(net, port); err != nil {
@@ -184,21 +199,25 @@ func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
return inetaddr(net, nil, portnum, zone), nil
}
// Try as an IP address.
- if ip := ParseIP(host); ip != nil {
+ if ip := parseIPv4(host); ip != nil {
+ return inetaddr(net, ip, portnum, zone), nil
+ }
+ if ip, zone := parseIPv6(host, true); ip != nil {
return inetaddr(net, ip, portnum, zone), nil
}
+ // Try as a domain name.
+ host, zone = splitHostZone(host)
+ addrs, err := lookupHostDeadline(host, deadline)
+ if err != nil {
+ return nil, err
+ }
var filter func(IP) IP
if net != "" && net[len(net)-1] == '4' {
filter = ipv4only
}
- if net != "" && net[len(net)-1] == '6' {
+ if net != "" && net[len(net)-1] == '6' || zone != "" {
filter = ipv6only
}
- // Try as a DNS name.
- addrs, err := lookupHostDeadline(host, deadline)
- if err != nil {
- return nil, err
- }
ip := firstFavoriteAddr(filter, addrs)
if ip == nil {
// should not happen
diff --git a/src/pkg/net/lookup_plan9.go b/src/pkg/net/lookup_plan9.go
index ae7cf7942..94c553328 100644
--- a/src/pkg/net/lookup_plan9.go
+++ b/src/pkg/net/lookup_plan9.go
@@ -7,7 +7,6 @@ package net
import (
"errors"
"os"
- "syscall"
)
func query(filename, query string, bufSize int) (res []string, err error) {
@@ -70,9 +69,26 @@ func queryDNS(addr string, typ string) (res []string, err error) {
return query("/net/dns", addr+" "+typ, 1024)
}
+// lookupProtocol looks up IP protocol name and returns
+// the corresponding protocol number.
func lookupProtocol(name string) (proto int, err error) {
- // TODO: Implement this
- return 0, syscall.EPLAN9
+ lines, err := query("/net/cs", "!protocol="+name, 128)
+ if err != nil {
+ return 0, err
+ }
+ unknownProtoError := errors.New("unknown IP protocol specified: " + name)
+ if len(lines) == 0 {
+ return 0, unknownProtoError
+ }
+ f := getFields(lines[0])
+ if len(f) < 2 {
+ return 0, unknownProtoError
+ }
+ s := f[1]
+ if n, _, ok := dtoi(s, byteIndex(s, '=')+1); ok {
+ return n, nil
+ }
+ return 0, unknownProtoError
}
func lookupHost(host string) (addrs []string, err error) {
diff --git a/src/pkg/net/multicast_posix_test.go b/src/pkg/net/multicast_posix_test.go
deleted file mode 100644
index ff1edaf83..000000000
--- a/src/pkg/net/multicast_posix_test.go
+++ /dev/null
@@ -1,180 +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 !plan9
-
-package net
-
-import (
- "errors"
- "os"
- "runtime"
- "testing"
-)
-
-var multicastListenerTests = []struct {
- net string
- gaddr *UDPAddr
- flags Flags
- ipv6 bool // test with underlying AF_INET6 socket
-}{
- // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
-
- {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, FlagUp | FlagLoopback, false},
- {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, 0, false},
- {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, FlagUp | FlagLoopback, true},
- {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, 0, true},
-
- {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, FlagUp | FlagLoopback, false},
- {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}, 0, false},
-
- {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}, 0, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}, 0, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}, 0, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}, 0, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}, 0, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, FlagUp | FlagLoopback, true},
- {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}, 0, true},
-}
-
-// TestMulticastListener tests both single and double listen to a test
-// 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":
- t.Skipf("skipping test on %q", runtime.GOOS)
- case "linux":
- if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
- t.Skipf("skipping test on %q/%q", runtime.GOOS, runtime.GOARCH)
- }
- }
-
- for _, tt := range multicastListenerTests {
- if tt.ipv6 && (!*testIPv6 || !supportsIPv6 || os.Getuid() != 0) {
- continue
- }
- ifi, err := availMulticastInterface(t, tt.flags)
- if err != nil {
- continue
- }
- c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
- if err != nil {
- t.Fatalf("First ListenMulticastUDP failed: %v", err)
- }
- checkMulticastListener(t, err, c1, tt.gaddr)
- c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
- if err != nil {
- t.Fatalf("Second ListenMulticastUDP failed: %v", err)
- }
- checkMulticastListener(t, err, c2, tt.gaddr)
- c2.Close()
- c1.Close()
- }
-}
-
-func TestSimpleMulticastListener(t *testing.T) {
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("skipping test on %q", runtime.GOOS)
- case "windows":
- if testing.Short() || !*testExternal {
- t.Skip("skipping test on windows to avoid firewall")
- }
- }
-
- for _, tt := range multicastListenerTests {
- if tt.ipv6 {
- continue
- }
- tt.flags = FlagUp | FlagMulticast // for windows testing
- ifi, err := availMulticastInterface(t, tt.flags)
- if err != nil {
- continue
- }
- c1, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
- if err != nil {
- t.Fatalf("First ListenMulticastUDP failed: %v", err)
- }
- checkSimpleMulticastListener(t, err, c1, tt.gaddr)
- c2, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr)
- if err != nil {
- t.Fatalf("Second ListenMulticastUDP failed: %v", err)
- }
- checkSimpleMulticastListener(t, err, c2, tt.gaddr)
- c2.Close()
- c1.Close()
- }
-}
-
-func checkMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
- if !multicastRIBContains(t, gaddr.IP) {
- t.Errorf("%q not found in RIB", gaddr.String())
- return
- }
- la := c.LocalAddr()
- if la == nil {
- t.Error("LocalAddr failed")
- return
- }
- if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
- t.Errorf("got %v; expected a proper address with non-zero port number", la)
- return
- }
-}
-
-func checkSimpleMulticastListener(t *testing.T, err error, c *UDPConn, gaddr *UDPAddr) {
- la := c.LocalAddr()
- if la == nil {
- t.Error("LocalAddr failed")
- return
- }
- if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
- t.Errorf("got %v; expected a proper address with non-zero port number", la)
- return
- }
-}
-
-func availMulticastInterface(t *testing.T, flags Flags) (*Interface, error) {
- var ifi *Interface
- if flags != Flags(0) {
- ift, err := Interfaces()
- if err != nil {
- t.Fatalf("Interfaces failed: %v", err)
- }
- for _, x := range ift {
- if x.Flags&flags == flags {
- ifi = &x
- break
- }
- }
- if ifi == nil {
- return nil, errors.New("an appropriate multicast interface not found")
- }
- }
- return ifi, nil
-}
-
-func multicastRIBContains(t *testing.T, ip IP) bool {
- ift, err := Interfaces()
- if err != nil {
- t.Fatalf("Interfaces failed: %v", err)
- }
- for _, ifi := range ift {
- ifmat, err := ifi.MulticastAddrs()
- if err != nil {
- t.Fatalf("MulticastAddrs failed: %v", err)
- }
- for _, ifma := range ifmat {
- if ifma.(*IPAddr).IP.Equal(ip) {
- return true
- }
- }
- }
- return false
-}
diff --git a/src/pkg/net/multicast_test.go b/src/pkg/net/multicast_test.go
new file mode 100644
index 000000000..1eb6a420d
--- /dev/null
+++ b/src/pkg/net/multicast_test.go
@@ -0,0 +1,184 @@
+// 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 (
+ "fmt"
+ "os"
+ "runtime"
+ "testing"
+)
+
+var ipv4MulticastListenerTests = []struct {
+ net string
+ gaddr *UDPAddr // see RFC 4727
+}{
+ {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
+
+ {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
+}
+
+// TestIPv4MulticastListener tests both single and double listen to a
+// test listener with same address family, same group address and same
+// port.
+func TestIPv4MulticastListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
+ closer := func(cs []*UDPConn) {
+ for _, c := range cs {
+ if c != nil {
+ c.Close()
+ }
+ }
+ }
+
+ for _, ifi := range []*Interface{loopbackInterface(), nil} {
+ // Note that multicast interface assignment by system
+ // is not recommended because it usually relies on
+ // routing stuff for finding out an appropriate
+ // nexthop containing both network and link layer
+ // adjacencies.
+ if ifi == nil && !*testExternal {
+ continue
+ }
+ for _, tt := range ipv4MulticastListenerTests {
+ var err error
+ cs := make([]*UDPConn, 2)
+ if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+ t.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi, err)
+ }
+ if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
+ closer(cs)
+ t.Fatal(err)
+ }
+ if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+ closer(cs)
+ t.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi, err)
+ }
+ if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
+ closer(cs)
+ t.Fatal(err)
+ }
+ closer(cs)
+ }
+ }
+}
+
+var ipv6MulticastListenerTests = []struct {
+ net string
+ gaddr *UDPAddr // see RFC 4727
+}{
+ {"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
+ {"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
+ {"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
+ {"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
+ {"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
+ {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
+
+ {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
+ {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
+ {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
+ {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
+ {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
+ {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
+}
+
+// TestIPv6MulticastListener tests both single and double listen to a
+// test listener with same address family, same group address and same
+// port.
+func TestIPv6MulticastListener(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9", "solaris", "windows":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ if os.Getuid() != 0 {
+ t.Skip("skipping test; must be root")
+ }
+
+ closer := func(cs []*UDPConn) {
+ for _, c := range cs {
+ if c != nil {
+ c.Close()
+ }
+ }
+ }
+
+ for _, ifi := range []*Interface{loopbackInterface(), nil} {
+ // Note that multicast interface assignment by system
+ // is not recommended because it usually relies on
+ // routing stuff for finding out an appropriate
+ // nexthop containing both network and link layer
+ // adjacencies.
+ if ifi == nil && (!*testExternal || !*testIPv6) {
+ continue
+ }
+ for _, tt := range ipv6MulticastListenerTests {
+ var err error
+ cs := make([]*UDPConn, 2)
+ if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+ t.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi, err)
+ }
+ if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
+ closer(cs)
+ t.Fatal(err)
+ }
+ if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
+ closer(cs)
+ t.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi, err)
+ }
+ if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
+ closer(cs)
+ t.Fatal(err)
+ }
+ closer(cs)
+ }
+ }
+}
+
+func checkMulticastListener(c *UDPConn, ip IP) error {
+ if ok, err := multicastRIBContains(ip); err != nil {
+ return err
+ } else if !ok {
+ return fmt.Errorf("%q not found in multicast RIB", ip.String())
+ }
+ la := c.LocalAddr()
+ if la, ok := la.(*UDPAddr); !ok || la.Port == 0 {
+ return fmt.Errorf("got %v; expected a proper address with non-zero port number", la)
+ }
+ return nil
+}
+
+func multicastRIBContains(ip IP) (bool, error) {
+ switch runtime.GOOS {
+ case "netbsd", "openbsd", "plan9", "solaris", "windows":
+ return true, nil // not implemented yet
+ case "linux":
+ if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
+ return true, nil // not implemented yet
+ }
+ }
+ ift, err := Interfaces()
+ if err != nil {
+ return false, err
+ }
+ for _, ifi := range ift {
+ ifmat, err := ifi.MulticastAddrs()
+ if err != nil {
+ return false, err
+ }
+ for _, ifma := range ifmat {
+ if ifma.(*IPAddr).IP.Equal(ip) {
+ return true, nil
+ }
+ }
+ }
+ return false, nil
+}
diff --git a/src/pkg/net/newpollserver_unix.go b/src/pkg/net/newpollserver_unix.go
deleted file mode 100644
index 618b5b10b..000000000
--- a/src/pkg/net/newpollserver_unix.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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.
-
-// +build darwin freebsd linux netbsd openbsd
-
-package net
-
-import (
- "os"
- "syscall"
-)
-
-func newPollServer() (s *pollServer, err error) {
- s = new(pollServer)
- if s.pr, s.pw, err = os.Pipe(); err != nil {
- return nil, err
- }
- if err = syscall.SetNonblock(int(s.pr.Fd()), true); err != nil {
- goto Errno
- }
- if err = syscall.SetNonblock(int(s.pw.Fd()), true); err != nil {
- goto Errno
- }
- if s.poll, err = newpollster(); err != nil {
- goto Error
- }
- if _, err = s.poll.AddFD(int(s.pr.Fd()), 'r', true); err != nil {
- s.poll.Close()
- goto Error
- }
- s.pending = make(map[int]*netFD)
- go s.Run()
- return s, nil
-
-Errno:
- err = &os.PathError{
- Op: "setnonblock",
- Path: s.pr.Name(),
- Err: err,
- }
-Error:
- s.pr.Close()
- s.pw.Close()
- return nil, err
-}
diff --git a/src/pkg/net/packetconn_test.go b/src/pkg/net/packetconn_test.go
index 93c7a6472..ec5dd710f 100644
--- a/src/pkg/net/packetconn_test.go
+++ b/src/pkg/net/packetconn_test.go
@@ -15,14 +15,20 @@ import (
"time"
)
+func strfunc(s string) func() string {
+ return func() string {
+ return s
+ }
+}
+
var packetConnTests = []struct {
net string
- addr1 string
- addr2 string
+ addr1 func() string
+ addr2 func() string
}{
- {"udp", "127.0.0.1:0", "127.0.0.1:0"},
- {"ip:icmp", "127.0.0.1", "127.0.0.1"},
- {"unixgram", testUnixAddr(), testUnixAddr()},
+ {"udp", strfunc("127.0.0.1:0"), strfunc("127.0.0.1:0")},
+ {"ip:icmp", strfunc("127.0.0.1"), strfunc("127.0.0.1")},
+ {"unixgram", testUnixAddr, testUnixAddr},
}
func TestPacketConn(t *testing.T) {
@@ -70,21 +76,22 @@ func TestPacketConn(t *testing.T) {
continue
}
- c1, err := ListenPacket(tt.net, tt.addr1)
+ addr1, addr2 := tt.addr1(), tt.addr2()
+ c1, err := ListenPacket(tt.net, addr1)
if err != nil {
t.Fatalf("ListenPacket failed: %v", err)
}
- defer closer(c1, netstr[0], tt.addr1, tt.addr2)
+ defer closer(c1, netstr[0], addr1, addr2)
c1.LocalAddr()
c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
- c2, err := ListenPacket(tt.net, tt.addr2)
+ c2, err := ListenPacket(tt.net, addr2)
if err != nil {
t.Fatalf("ListenPacket failed: %v", err)
}
- defer closer(c2, netstr[0], tt.addr1, tt.addr2)
+ defer closer(c2, netstr[0], addr1, addr2)
c2.LocalAddr()
c2.SetDeadline(time.Now().Add(100 * time.Millisecond))
c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
@@ -152,11 +159,12 @@ func TestConnAndPacketConn(t *testing.T) {
continue
}
- c1, err := ListenPacket(tt.net, tt.addr1)
+ addr1, addr2 := tt.addr1(), tt.addr2()
+ c1, err := ListenPacket(tt.net, addr1)
if err != nil {
t.Fatalf("ListenPacket failed: %v", err)
}
- defer closer(c1, netstr[0], tt.addr1, tt.addr2)
+ defer closer(c1, netstr[0], addr1, addr2)
c1.LocalAddr()
c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
diff --git a/src/pkg/net/protoconn_test.go b/src/pkg/net/protoconn_test.go
index 2fe7d1d1f..b59925e01 100644
--- a/src/pkg/net/protoconn_test.go
+++ b/src/pkg/net/protoconn_test.go
@@ -15,9 +15,11 @@ import (
"time"
)
-// testUnixAddr uses ioutil.TempFile to get a name that is unique.
+// testUnixAddr uses ioutil.TempFile to get a name that is unique. It
+// also uses /tmp directory in case it is prohibited to create UNIX
+// sockets in TMPDIR.
func testUnixAddr() string {
- f, err := ioutil.TempFile("", "nettest")
+ f, err := ioutil.TempFile("/tmp", "nettest")
if err != nil {
panic(err)
}
@@ -163,7 +165,7 @@ func TestUDPConnSpecificMethods(t *testing.T) {
func TestIPConnSpecificMethods(t *testing.T) {
switch runtime.GOOS {
case "plan9":
- t.Skipf("skipping read test on %q", runtime.GOOS)
+ t.Skipf("skipping test on %q", runtime.GOOS)
}
if os.Getuid() != 0 {
t.Skipf("skipping test; must be root")
@@ -220,7 +222,7 @@ func TestIPConnSpecificMethods(t *testing.T) {
func TestUnixListenerSpecificMethods(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
- t.Skipf("skipping read test on %q", runtime.GOOS)
+ t.Skipf("skipping test on %q", runtime.GOOS)
}
addr := testUnixAddr()
diff --git a/src/pkg/net/rpc/jsonrpc/all_test.go b/src/pkg/net/rpc/jsonrpc/all_test.go
index 3c7c4d48f..40d4b82d7 100644
--- a/src/pkg/net/rpc/jsonrpc/all_test.go
+++ b/src/pkg/net/rpc/jsonrpc/all_test.go
@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
+ "io/ioutil"
"net"
"net/rpc"
"testing"
@@ -185,6 +186,22 @@ func TestMalformedInput(t *testing.T) {
ServeConn(srv) // must return, not loop
}
+func TestMalformedOutput(t *testing.T) {
+ cli, srv := net.Pipe()
+ go srv.Write([]byte(`{"id":0,"result":null,"error":null}`))
+ go ioutil.ReadAll(srv)
+
+ client := NewClient(cli)
+ defer client.Close()
+
+ args := &Args{7, 8}
+ reply := new(Reply)
+ err := client.Call("Arith.Add", args, reply)
+ if err == nil {
+ t.Error("expected error")
+ }
+}
+
func TestUnexpectedError(t *testing.T) {
cli, srv := myPipe()
go cli.PipeWriter.CloseWithError(errors.New("unexpected error!")) // reader will get this error
diff --git a/src/pkg/net/rpc/jsonrpc/client.go b/src/pkg/net/rpc/jsonrpc/client.go
index 3fa8cbf08..2194f2125 100644
--- a/src/pkg/net/rpc/jsonrpc/client.go
+++ b/src/pkg/net/rpc/jsonrpc/client.go
@@ -83,7 +83,7 @@ func (c *clientCodec) ReadResponseHeader(r *rpc.Response) error {
r.Error = ""
r.Seq = c.resp.Id
- if c.resp.Error != nil {
+ if c.resp.Error != nil || c.resp.Result == nil {
x, ok := c.resp.Error.(string)
if !ok {
return fmt.Errorf("invalid error %v", c.resp.Error)
diff --git a/src/pkg/net/rpc/server_test.go b/src/pkg/net/rpc/server_test.go
index 8a1530623..eb17210ab 100644
--- a/src/pkg/net/rpc/server_test.go
+++ b/src/pkg/net/rpc/server_test.go
@@ -399,12 +399,10 @@ func (WriteFailCodec) WriteRequest(*Request, interface{}) error {
func (WriteFailCodec) ReadResponseHeader(*Response) error {
select {}
- panic("unreachable")
}
func (WriteFailCodec) ReadResponseBody(interface{}) error {
select {}
- panic("unreachable")
}
func (WriteFailCodec) Close() error {
@@ -465,10 +463,16 @@ func countMallocs(dial func() (*Client, error), t *testing.T) float64 {
}
func TestCountMallocs(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
fmt.Printf("mallocs per rpc round trip: %v\n", countMallocs(dialDirect, t))
}
func TestCountMallocsOverHTTP(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
fmt.Printf("mallocs per HTTP rpc round trip: %v\n", countMallocs(dialHTTP, t))
}
diff --git a/src/pkg/net/sendfile_freebsd.go b/src/pkg/net/sendfile_freebsd.go
index 8008bc3b5..dc5b76755 100644
--- a/src/pkg/net/sendfile_freebsd.go
+++ b/src/pkg/net/sendfile_freebsd.go
@@ -83,7 +83,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
break
}
if err1 == syscall.EAGAIN {
- if err1 = c.pollServer.WaitWrite(c); err1 == nil {
+ if err1 = c.pd.WaitWrite(); err1 == nil {
continue
}
}
diff --git a/src/pkg/net/sendfile_linux.go b/src/pkg/net/sendfile_linux.go
index 3357e6538..6f1323b3d 100644
--- a/src/pkg/net/sendfile_linux.go
+++ b/src/pkg/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 {
- if err1 = c.pollServer.WaitWrite(c); err1 == nil {
+ if err1 = c.pd.WaitWrite(); err1 == nil {
continue
}
}
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index 25c2be5a7..c101ffecd 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -9,6 +9,7 @@ import (
"io"
"os"
"runtime"
+ "strconv"
"testing"
"time"
)
@@ -41,6 +42,12 @@ func skipServerTest(net, unixsotype, addr string, ipv6, ipv4map, linuxonly bool)
return false
}
+func tempfile(filename string) string {
+ // use /tmp in case it is prohibited to create
+ // UNIX sockets in TMPDIR
+ return "/tmp/" + filename + "." + strconv.Itoa(os.Getpid())
+}
+
var streamConnServerTests = []struct {
snet string // server side
saddr string
@@ -86,7 +93,7 @@ var streamConnServerTests = []struct {
{snet: "tcp6", saddr: "[::1]", cnet: "tcp6", caddr: "[::1]", ipv6: true},
- {snet: "unix", saddr: "/tmp/gotest1.net", cnet: "unix", caddr: "/tmp/gotest1.net.local"},
+ {snet: "unix", saddr: tempfile("gotest1.net"), cnet: "unix", caddr: tempfile("gotest1.net.local")},
{snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local", linux: true},
}
@@ -135,7 +142,7 @@ var seqpacketConnServerTests = []struct {
caddr string // client address
empty bool // test with empty data
}{
- {net: "unixpacket", saddr: "/tmp/gotest3.net", caddr: "/tmp/gotest3.net.local"},
+ {net: "unixpacket", saddr: tempfile("/gotest3.net"), caddr: tempfile("gotest3.net.local")},
{net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local"},
}
@@ -294,10 +301,10 @@ var datagramPacketConnServerTests = []struct {
{snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, empty: true},
{snet: "udp", saddr: "[::1]", cnet: "udp", caddr: "[::1]", ipv6: true, dial: true, empty: true},
- {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local"},
- {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", dial: true},
- {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", empty: true},
- {snet: "unixgram", saddr: "/tmp/gotest5.net", cnet: "unixgram", caddr: "/tmp/gotest5.net.local", dial: true, empty: true},
+ {snet: "unixgram", saddr: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local")},
+ {snet: "unixgram", saddr: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local"), dial: true},
+ {snet: "unixgram", saddr: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local"), empty: true},
+ {snet: "unixgram", saddr: tempfile("gotest5.net"), cnet: "unixgram", caddr: tempfile("gotest5.net.local"), dial: true, empty: true},
{snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local", linux: true},
}
diff --git a/src/pkg/net/sock_bsd.go b/src/pkg/net/sock_bsd.go
index 3205f9404..d99349265 100644
--- a/src/pkg/net/sock_bsd.go
+++ b/src/pkg/net/sock_bsd.go
@@ -27,5 +27,11 @@ func maxListenerBacklog() int {
if n == 0 || err != nil {
return syscall.SOMAXCONN
}
+ // FreeBSD stores the backlog in a uint16, as does Linux.
+ // Assume the other BSDs do too. Truncate number to avoid wrapping.
+ // See issue 5030.
+ if n > 1<<16-1 {
+ n = 1<<16 - 1
+ }
return int(n)
}
diff --git a/src/pkg/net/sock_cloexec.go b/src/pkg/net/sock_cloexec.go
index 12d0f3488..3f22cd8f5 100644
--- a/src/pkg/net/sock_cloexec.go
+++ b/src/pkg/net/sock_cloexec.go
@@ -44,8 +44,8 @@ func sysSocket(f, t, p int) (int, error) {
func accept(fd int) (int, syscall.Sockaddr, error) {
nfd, sa, err := syscall.Accept4(fd, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
// The accept4 system call was introduced in Linux 2.6.28. If
- // we get an ENOSYS error, fall back to using accept.
- if err == nil || err != syscall.ENOSYS {
+ // we get an ENOSYS or EINVAL error, fall back to using accept.
+ if err == nil || (err != syscall.ENOSYS && err != syscall.EINVAL) {
return nfd, sa, err
}
diff --git a/src/pkg/net/sock_linux.go b/src/pkg/net/sock_linux.go
index 8bbd74ddc..cc5ce153b 100644
--- a/src/pkg/net/sock_linux.go
+++ b/src/pkg/net/sock_linux.go
@@ -21,5 +21,11 @@ func maxListenerBacklog() int {
if n == 0 || !ok {
return syscall.SOMAXCONN
}
+ // Linux stores the backlog in a uint16.
+ // Truncate number to avoid wrapping.
+ // See issue 5030.
+ if n > 1<<16-1 {
+ n = 1<<16 - 1
+ }
return n
}
diff --git a/src/pkg/net/sock_posix.go b/src/pkg/net/sock_posix.go
index b50a892b1..2ebde8799 100644
--- a/src/pkg/net/sock_posix.go
+++ b/src/pkg/net/sock_posix.go
@@ -49,13 +49,17 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
}
if ursa != nil {
- fd.wdeadline.setTime(deadline)
+ if !deadline.IsZero() {
+ setWriteDeadline(fd, deadline)
+ }
if err = fd.connect(ursa); err != nil {
closesocket(s)
return nil, err
}
fd.isConnected = true
- fd.wdeadline.set(0)
+ if !deadline.IsZero() {
+ setWriteDeadline(fd, time.Time{})
+ }
}
lsa, _ := syscall.Getsockname(s)
@@ -63,5 +67,8 @@ func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr,
rsa, _ := syscall.Getpeername(s)
raddr := toAddr(rsa)
fd.setAddr(laddr, raddr)
+ if fd.raddr == nil {
+ fd.raddr = toAddr(ursa)
+ }
return fd, nil
}
diff --git a/src/pkg/net/sock_windows.go b/src/pkg/net/sock_windows.go
index a77c48437..41368d39e 100644
--- a/src/pkg/net/sock_windows.go
+++ b/src/pkg/net/sock_windows.go
@@ -8,6 +8,7 @@ import "syscall"
func maxListenerBacklog() int {
// TODO: Implement this
+ // NOTE: Never return a number bigger than 1<<16 - 1. See issue 5030.
return syscall.SOMAXCONN
}
diff --git a/src/pkg/net/sockopt_posix.go b/src/pkg/net/sockopt_posix.go
index fe371fe0c..1590f4e98 100644
--- a/src/pkg/net/sockopt_posix.go
+++ b/src/pkg/net/sockopt_posix.go
@@ -11,7 +11,6 @@ package net
import (
"os"
"syscall"
- "time"
)
// Boolean to int.
@@ -119,24 +118,6 @@ func setWriteBuffer(fd *netFD, bytes int) error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
}
-// TODO(dfc) these unused error returns could be removed
-
-func setReadDeadline(fd *netFD, t time.Time) error {
- fd.rdeadline.setTime(t)
- return nil
-}
-
-func setWriteDeadline(fd *netFD, t time.Time) error {
- fd.wdeadline.setTime(t)
- return nil
-}
-
-func setDeadline(fd *netFD, t time.Time) error {
- setReadDeadline(fd, t)
- setWriteDeadline(fd, t)
- return nil
-}
-
func setKeepAlive(fd *netFD, keepalive bool) error {
if err := fd.incref(false); err != nil {
return err
diff --git a/src/pkg/net/sockopt_windows.go b/src/pkg/net/sockopt_windows.go
index 509b5963b..0861fe8f4 100644
--- a/src/pkg/net/sockopt_windows.go
+++ b/src/pkg/net/sockopt_windows.go
@@ -9,6 +9,7 @@ package net
import (
"os"
"syscall"
+ "time"
)
func setDefaultSockopts(s syscall.Handle, f, t int, ipv6only bool) error {
@@ -47,3 +48,21 @@ func setDefaultMulticastSockopts(s syscall.Handle) error {
}
return nil
}
+
+// TODO(dfc) these unused error returns could be removed
+
+func setReadDeadline(fd *netFD, t time.Time) error {
+ fd.rdeadline.setTime(t)
+ return nil
+}
+
+func setWriteDeadline(fd *netFD, t time.Time) error {
+ fd.wdeadline.setTime(t)
+ return nil
+}
+
+func setDeadline(fd *netFD, t time.Time) error {
+ setReadDeadline(fd, t)
+ setWriteDeadline(fd, t)
+ return nil
+}
diff --git a/src/pkg/net/tcp_test.go b/src/pkg/net/tcp_test.go
index 6c4485a94..add8e4823 100644
--- a/src/pkg/net/tcp_test.go
+++ b/src/pkg/net/tcp_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "fmt"
"reflect"
"runtime"
"testing"
@@ -158,6 +159,11 @@ var resolveTCPAddrTests = []struct {
{"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil},
{"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
+ {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
+ {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
+ {"tcp6", "[fe80::1]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: "name"}, nil},
+ {"tcp6", "[fe80::1]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: "index"}, nil},
+
{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
@@ -166,6 +172,24 @@ var resolveTCPAddrTests = []struct {
func TestResolveTCPAddr(t *testing.T) {
for _, tt := range resolveTCPAddrTests {
+ if tt.addr != nil && (tt.addr.Zone == "name" || tt.addr.Zone == "index") {
+ ifi := loopbackInterface()
+ if ifi == nil {
+ continue
+ }
+ i := last(tt.litAddr, ']')
+ if i > 0 {
+ switch tt.addr.Zone {
+ case "name":
+ tt.litAddr = tt.litAddr[:i] + "%" + ifi.Name + tt.litAddr[i:]
+ tt.addr.Zone = zoneToString(ifi.Index)
+ case "index":
+ index := fmt.Sprintf("%v", ifi.Index)
+ tt.litAddr = tt.litAddr[:i] + "%" + index + tt.litAddr[i:]
+ tt.addr.Zone = index
+ }
+ }
+ }
addr, err := ResolveTCPAddr(tt.net, tt.litAddr)
if err != tt.err {
t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
@@ -204,3 +228,79 @@ func TestTCPListenerName(t *testing.T) {
}
}
}
+
+func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ ifi := loopbackInterface()
+ if ifi == nil {
+ t.Skip("loopback interface not found")
+ }
+ laddr := ipv6LinkLocalUnicastAddr(ifi)
+ if laddr == "" {
+ t.Skip("ipv6 unicast address on loopback not found")
+ }
+
+ type test struct {
+ net, addr string
+ nameLookup bool
+ }
+ var tests = []test{
+ {"tcp", "[" + laddr + "%" + ifi.Name + "]:0", false},
+ {"tcp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
+ }
+ switch runtime.GOOS {
+ case "darwin", "freebsd", "opensbd", "netbsd":
+ tests = append(tests, []test{
+ {"tcp", "[localhost%" + ifi.Name + "]:0", true},
+ {"tcp6", "[localhost%" + ifi.Name + "]:0", true},
+ }...)
+ case "linux":
+ tests = append(tests, []test{
+ {"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true},
+ {"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
+ }...)
+ }
+ for _, tt := range tests {
+ ln, err := Listen(tt.net, tt.addr)
+ if err != nil {
+ // It might return "LookupHost returned no
+ // suitable address" error on some platforms.
+ t.Logf("Listen failed: %v", err)
+ continue
+ }
+ defer ln.Close()
+ if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+ t.Fatalf("got %v; expected a proper address with zone identifier", la)
+ }
+
+ done := make(chan int)
+ go transponder(t, ln, done)
+
+ c, err := Dial(tt.net, ln.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial failed: %v", err)
+ }
+ defer c.Close()
+ if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+ t.Fatalf("got %v; expected a proper address with zone identifier", la)
+ }
+ if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
+ t.Fatalf("got %v; expected a proper address with zone identifier", ra)
+ }
+
+ if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
+ t.Fatalf("Conn.Write failed: %v", err)
+ }
+ b := make([]byte, 32)
+ if _, err := c.Read(b); err != nil {
+ t.Fatalf("Conn.Read failed: %v", err)
+ }
+
+ <-done
+ }
+}
diff --git a/src/pkg/net/tcpsock.go b/src/pkg/net/tcpsock.go
index d5158b22d..27db11568 100644
--- a/src/pkg/net/tcpsock.go
+++ b/src/pkg/net/tcpsock.go
@@ -20,14 +20,18 @@ func (a *TCPAddr) String() string {
if a == nil {
return "<nil>"
}
+ if a.Zone != "" {
+ return JoinHostPort(a.IP.String()+"%"+a.Zone, itoa(a.Port))
+ }
return JoinHostPort(a.IP.String(), itoa(a.Port))
}
-// ResolveTCPAddr parses addr as a TCP address of the form
-// host:port and resolves domain names or port names to
-// numeric addresses on the network net, which must be "tcp",
-// "tcp4" or "tcp6". A literal IPv6 host address must be
-// enclosed in square brackets, as in "[::]:80".
+// ResolveTCPAddr parses addr as a TCP address of the form "host:port"
+// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
+// port name on the network net, which must be "tcp", "tcp4" or
+// "tcp6". A literal address or host name for IPv6 must be enclosed
+// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
+// "[ipv6-host%zone]:80".
func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
switch net {
case "tcp", "tcp4", "tcp6":
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
index b61bea862..35e27acb5 100644
--- a/src/pkg/net/textproto/reader.go
+++ b/src/pkg/net/textproto/reader.go
@@ -489,7 +489,6 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
return m, err
}
}
- panic("unreachable")
}
// CanonicalMIMEHeaderKey returns the canonical format of the
diff --git a/src/pkg/net/timeout_test.go b/src/pkg/net/timeout_test.go
index 0260efcc0..2e92147b8 100644
--- a/src/pkg/net/timeout_test.go
+++ b/src/pkg/net/timeout_test.go
@@ -532,7 +532,7 @@ func TestReadDeadlineDataAvailable(t *testing.T) {
defer ln.Close()
servec := make(chan copyRes)
- const msg = "data client shouldn't read, even though it it'll be waiting"
+ const msg = "data client shouldn't read, even though it'll be waiting"
go func() {
c, err := ln.Accept()
if err != nil {
@@ -596,6 +596,64 @@ func TestWriteDeadlineBufferAvailable(t *testing.T) {
}
}
+// TestAcceptDeadlineConnectionAvailable tests that accept deadlines work, even
+// if there's incoming connections available.
+func TestAcceptDeadlineConnectionAvailable(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
+ ln := newLocalListener(t).(*TCPListener)
+ defer ln.Close()
+
+ go func() {
+ c, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ defer c.Close()
+ var buf [1]byte
+ c.Read(buf[:]) // block until the connection or listener is closed
+ }()
+ time.Sleep(10 * time.Millisecond)
+ ln.SetDeadline(time.Now().Add(-5 * time.Second)) // in the past
+ c, err := ln.Accept()
+ if err == nil {
+ defer c.Close()
+ }
+ if !isTimeout(err) {
+ t.Fatalf("Accept: got %v; want timeout", err)
+ }
+}
+
+// TestConnectDeadlineInThePast tests that connect deadlines work, even
+// if the connection can be established w/o blocking.
+func TestConnectDeadlineInThePast(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
+ ln := newLocalListener(t).(*TCPListener)
+ defer ln.Close()
+
+ go func() {
+ c, err := ln.Accept()
+ if err == nil {
+ defer c.Close()
+ }
+ }()
+ time.Sleep(10 * time.Millisecond)
+ c, err := DialTimeout("tcp", ln.Addr().String(), -5*time.Second) // in the past
+ if err == nil {
+ defer c.Close()
+ }
+ if !isTimeout(err) {
+ t.Fatalf("DialTimeout: got %v; want timeout", err)
+ }
+}
+
// TestProlongTimeout tests concurrent deadline modification.
// Known to cause data races in the past.
func TestProlongTimeout(t *testing.T) {
diff --git a/src/pkg/net/udp_test.go b/src/pkg/net/udp_test.go
index 220422e13..b3cafb096 100644
--- a/src/pkg/net/udp_test.go
+++ b/src/pkg/net/udp_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "fmt"
"reflect"
"runtime"
"testing"
@@ -22,6 +23,11 @@ var resolveUDPAddrTests = []struct {
{"udp", "[::1]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1}, nil},
{"udp6", "[::1]:65534", &UDPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
+ {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
+ {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
+ {"udp6", "[fe80::1]:3", &UDPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: "name"}, nil},
+ {"udp6", "[fe80::1]:4", &UDPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: "index"}, nil},
+
{"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
{"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
@@ -30,6 +36,24 @@ var resolveUDPAddrTests = []struct {
func TestResolveUDPAddr(t *testing.T) {
for _, tt := range resolveUDPAddrTests {
+ if tt.addr != nil && (tt.addr.Zone == "name" || tt.addr.Zone == "index") {
+ ifi := loopbackInterface()
+ if ifi == nil {
+ continue
+ }
+ i := last(tt.litAddr, ']')
+ if i > 0 {
+ switch tt.addr.Zone {
+ case "name":
+ tt.litAddr = tt.litAddr[:i] + "%" + ifi.Name + tt.litAddr[i:]
+ tt.addr.Zone = zoneToString(ifi.Index)
+ case "index":
+ index := fmt.Sprintf("%v", ifi.Index)
+ tt.litAddr = tt.litAddr[:i] + "%" + index + tt.litAddr[i:]
+ tt.addr.Zone = index
+ }
+ }
+ }
addr, err := ResolveUDPAddr(tt.net, tt.litAddr)
if err != tt.err {
t.Fatalf("ResolveUDPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
@@ -146,3 +170,78 @@ func TestUDPConnLocalName(t *testing.T) {
}
}
}
+
+func TestIPv6LinkLocalUnicastUDP(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+ if !supportsIPv6 {
+ t.Skip("ipv6 is not supported")
+ }
+ ifi := loopbackInterface()
+ if ifi == nil {
+ t.Skip("loopback interface not found")
+ }
+ laddr := ipv6LinkLocalUnicastAddr(ifi)
+ if laddr == "" {
+ t.Skip("ipv6 unicast address on loopback not found")
+ }
+
+ type test struct {
+ net, addr string
+ nameLookup bool
+ }
+ var tests = []test{
+ {"udp", "[" + laddr + "%" + ifi.Name + "]:0", false},
+ {"udp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
+ }
+ switch runtime.GOOS {
+ case "darwin", "freebsd", "openbsd", "netbsd":
+ tests = append(tests, []test{
+ {"udp", "[localhost%" + ifi.Name + "]:0", true},
+ {"udp6", "[localhost%" + ifi.Name + "]:0", true},
+ }...)
+ case "linux":
+ tests = append(tests, []test{
+ {"udp", "[ip6-localhost%" + ifi.Name + "]:0", true},
+ {"udp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
+ }...)
+ }
+ for _, tt := range tests {
+ c1, err := ListenPacket(tt.net, tt.addr)
+ if err != nil {
+ // It might return "LookupHost returned no
+ // suitable address" error on some platforms.
+ t.Logf("ListenPacket failed: %v", err)
+ continue
+ }
+ defer c1.Close()
+ if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+ t.Fatalf("got %v; expected a proper address with zone identifier", la)
+ }
+
+ c2, err := Dial(tt.net, c1.LocalAddr().String())
+ if err != nil {
+ t.Fatalf("Dial failed: %v", err)
+ }
+ defer c2.Close()
+ if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
+ t.Fatalf("got %v; expected a proper address with zone identifier", la)
+ }
+ if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
+ t.Fatalf("got %v; expected a proper address with zone identifier", ra)
+ }
+
+ if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil {
+ t.Fatalf("Conn.Write failed: %v", err)
+ }
+ b := make([]byte, 32)
+ if _, from, err := c1.ReadFrom(b); err != nil {
+ t.Fatalf("PacketConn.ReadFrom failed: %v", err)
+ } else {
+ if ra, ok := from.(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
+ t.Fatalf("got %v; expected a proper address with zone identifier", ra)
+ }
+ }
+ }
+}
diff --git a/src/pkg/net/udpsock.go b/src/pkg/net/udpsock.go
index 6e5e90268..277050606 100644
--- a/src/pkg/net/udpsock.go
+++ b/src/pkg/net/udpsock.go
@@ -24,14 +24,18 @@ func (a *UDPAddr) String() string {
if a == nil {
return "<nil>"
}
+ if a.Zone != "" {
+ return JoinHostPort(a.IP.String()+"%"+a.Zone, itoa(a.Port))
+ }
return JoinHostPort(a.IP.String(), itoa(a.Port))
}
-// ResolveUDPAddr parses addr as a UDP address of the form
-// host:port and resolves domain names or port names to
-// numeric addresses on the network net, which must be "udp",
-// "udp4" or "udp6". A literal IPv6 host address must be
-// enclosed in square brackets, as in "[::]:80".
+// ResolveUDPAddr parses addr as a UDP address of the form "host:port"
+// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
+// port name on the network net, which must be "udp", "udp4" or
+// "udp6". A literal address or host name for IPv6 must be enclosed
+// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
+// "[ipv6-host%zone]:80".
func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
switch net {
case "udp", "udp4", "udp6":
diff --git a/src/pkg/net/udpsock_plan9.go b/src/pkg/net/udpsock_plan9.go
index 2a7e3d19c..66dcbab7c 100644
--- a/src/pkg/net/udpsock_plan9.go
+++ b/src/pkg/net/udpsock_plan9.go
@@ -58,7 +58,7 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
}
// ReadMsgUDP reads a packet from c, copying the payload into b and
-// the associdated out-of-band data into oob. It returns the number
+// 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.
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index 385cd902e..9aafb7083 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -89,7 +89,7 @@ func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
}
// ReadMsgUDP reads a packet from c, copying the payload into b and
-// the associdated out-of-band data into oob. It returns the number
+// 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.
diff --git a/src/pkg/net/unixsock.go b/src/pkg/net/unixsock.go
index ae0956958..977ff9103 100644
--- a/src/pkg/net/unixsock.go
+++ b/src/pkg/net/unixsock.go
@@ -12,7 +12,8 @@ type UnixAddr struct {
Net string
}
-// Network returns the address's network name, "unix" or "unixgram".
+// Network returns the address's network name, "unix", "unixgram" or
+// "unixpacket".
func (a *UnixAddr) Network() string {
return a.Net
}
@@ -36,11 +37,9 @@ func (a *UnixAddr) toAddr() Addr {
// "unixpacket".
func ResolveUnixAddr(net, addr string) (*UnixAddr, error) {
switch net {
- case "unix":
- case "unixpacket":
- case "unixgram":
+ case "unix", "unixgram", "unixpacket":
+ return &UnixAddr{Name: addr, Net: net}, nil
default:
return nil, UnknownNetworkError(net)
}
- return &UnixAddr{addr, net}, nil
}
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index 6d6ce3f5e..8d57dacbd 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -99,7 +99,6 @@ func sotypeToNet(sotype int) string {
default:
panic("sotypeToNet unknown socket type")
}
- return ""
}
// UnixConn is an implementation of the Conn interface for connections
diff --git a/src/pkg/net/url/url.go b/src/pkg/net/url/url.go
index a39964ea1..c1864036c 100644
--- a/src/pkg/net/url/url.go
+++ b/src/pkg/net/url/url.go
@@ -362,7 +362,7 @@ func ParseRequestURI(rawurl string) (url *URL, err error) {
func parse(rawurl string, viaRequest bool) (url *URL, err error) {
var rest string
- if rawurl == "" {
+ if rawurl == "" && viaRequest {
err = errors.New("empty url")
goto Error
}
@@ -583,43 +583,39 @@ func (v Values) Encode() string {
}
// resolvePath applies special path segments from refs and applies
-// them to base, per RFC 2396.
-func resolvePath(basepath string, refpath string) string {
- base := strings.Split(basepath, "/")
- refs := strings.Split(refpath, "/")
- if len(base) == 0 {
- base = []string{""}
+// them to base, per RFC 3986.
+func resolvePath(base, ref string) string {
+ var full string
+ if ref == "" {
+ full = base
+ } else if ref[0] != '/' {
+ i := strings.LastIndex(base, "/")
+ full = base[:i+1] + ref
+ } else {
+ full = ref
}
-
- rm := true
- for idx, ref := range refs {
- switch {
- case ref == ".":
- if idx == 0 {
- base[len(base)-1] = ""
- rm = true
- } else {
- rm = false
- }
- case ref == "..":
- newLen := len(base) - 1
- if newLen < 1 {
- newLen = 1
- }
- base = base[0:newLen]
- if rm {
- base[len(base)-1] = ""
+ if full == "" {
+ return ""
+ }
+ var dst []string
+ src := strings.Split(full, "/")
+ for _, elem := range src {
+ switch elem {
+ case ".":
+ // drop
+ case "..":
+ if len(dst) > 0 {
+ dst = dst[:len(dst)-1]
}
default:
- if idx == 0 || base[len(base)-1] == "" {
- base[len(base)-1] = ref
- } else {
- base = append(base, ref)
- }
- rm = false
+ dst = append(dst, elem)
}
}
- return strings.Join(base, "/")
+ if last := src[len(src)-1]; last == "." || last == ".." {
+ // Add final slash to the joined path.
+ dst = append(dst, "")
+ }
+ return "/" + strings.TrimLeft(strings.Join(dst, "/"), "/")
}
// IsAbs returns true if the URL is absolute.
@@ -639,43 +635,39 @@ func (u *URL) Parse(ref string) (*URL, error) {
}
// ResolveReference resolves a URI reference to an absolute URI from
-// an absolute base URI, per RFC 2396 Section 5.2. The URI reference
+// an absolute base URI, per RFC 3986 Section 5.2. The URI reference
// may be relative or absolute. ResolveReference always returns a new
// URL instance, even if the returned URL is identical to either the
// base or reference. If ref is an absolute URL, then ResolveReference
// ignores base and returns a copy of ref.
func (u *URL) ResolveReference(ref *URL) *URL {
- if ref.IsAbs() {
- url := *ref
+ url := *ref
+ if ref.Scheme == "" {
+ url.Scheme = u.Scheme
+ }
+ if ref.Scheme != "" || ref.Host != "" || ref.User != nil {
+ // The "absoluteURI" or "net_path" cases.
+ url.Path = resolvePath(ref.Path, "")
return &url
}
- // relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
- url := *u
- url.RawQuery = ref.RawQuery
- url.Fragment = ref.Fragment
if ref.Opaque != "" {
- url.Opaque = ref.Opaque
url.User = nil
url.Host = ""
url.Path = ""
return &url
}
- if ref.Host != "" || ref.User != nil {
- // The "net_path" case.
- url.Host = ref.Host
- url.User = ref.User
- }
- if strings.HasPrefix(ref.Path, "/") {
- // The "abs_path" case.
- url.Path = ref.Path
- } else {
- // The "rel_path" case.
- path := resolvePath(u.Path, ref.Path)
- if !strings.HasPrefix(path, "/") {
- path = "/" + path
+ if ref.Path == "" {
+ if ref.RawQuery == "" {
+ url.RawQuery = u.RawQuery
+ if ref.Fragment == "" {
+ url.Fragment = u.Fragment
+ }
}
- url.Path = path
}
+ // The "abs_path" or "rel_path" cases.
+ url.Host = u.Host
+ url.User = u.User
+ url.Path = resolvePath(u.Path, ref.Path)
return &url
}
diff --git a/src/pkg/net/url/url_test.go b/src/pkg/net/url/url_test.go
index 4c4f406c2..9d81289ce 100644
--- a/src/pkg/net/url/url_test.go
+++ b/src/pkg/net/url/url_test.go
@@ -523,18 +523,18 @@ func TestEncodeQuery(t *testing.T) {
var resolvePathTests = []struct {
base, ref, expected string
}{
- {"a/b", ".", "a/"},
- {"a/b", "c", "a/c"},
- {"a/b", "..", ""},
- {"a/", "..", ""},
- {"a/", "../..", ""},
- {"a/b/c", "..", "a/"},
- {"a/b/c", "../d", "a/d"},
- {"a/b/c", ".././d", "a/d"},
- {"a/b", "./..", ""},
- {"a/./b", ".", "a/./"},
- {"a/../", ".", "a/../"},
- {"a/.././b", "c", "a/.././c"},
+ {"a/b", ".", "/a/"},
+ {"a/b", "c", "/a/c"},
+ {"a/b", "..", "/"},
+ {"a/", "..", "/"},
+ {"a/", "../..", "/"},
+ {"a/b/c", "..", "/a/"},
+ {"a/b/c", "../d", "/a/d"},
+ {"a/b/c", ".././d", "/a/d"},
+ {"a/b", "./..", "/"},
+ {"a/./b", ".", "/a/"},
+ {"a/../", ".", "/"},
+ {"a/.././b", "c", "/c"},
}
func TestResolvePath(t *testing.T) {
@@ -587,16 +587,71 @@ var resolveReferenceTests = []struct {
{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/././../../tail", "http://foo.com/bar/quux/tail"},
{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/./.././../tail", "http://foo.com/bar/quux/tail"},
{"http://foo.com/bar/baz", "quux/./dotdot/dotdot/dotdot/./../../.././././tail", "http://foo.com/bar/quux/tail"},
- {"http://foo.com/bar/baz", "quux/./dotdot/../dotdot/../dot/./tail/..", "http://foo.com/bar/quux/dot"},
+ {"http://foo.com/bar/baz", "quux/./dotdot/../dotdot/../dot/./tail/..", "http://foo.com/bar/quux/dot/"},
- // "." and ".." in the base aren't special
- {"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/./dotdot/../baz"},
+ // Remove any dot-segments prior to forming the target URI.
+ // http://tools.ietf.org/html/rfc3986#section-5.2.4
+ {"http://foo.com/dot/./dotdot/../foo/bar", "../baz", "http://foo.com/dot/baz"},
// Triple dot isn't special
{"http://foo.com/bar", "...", "http://foo.com/..."},
// Fragment
{"http://foo.com/bar", ".#frag", "http://foo.com/#frag"},
+
+ // RFC 3986: Normal Examples
+ // http://tools.ietf.org/html/rfc3986#section-5.4.1
+ {"http://a/b/c/d;p?q", "g:h", "g:h"},
+ {"http://a/b/c/d;p?q", "g", "http://a/b/c/g"},
+ {"http://a/b/c/d;p?q", "./g", "http://a/b/c/g"},
+ {"http://a/b/c/d;p?q", "g/", "http://a/b/c/g/"},
+ {"http://a/b/c/d;p?q", "/g", "http://a/g"},
+ {"http://a/b/c/d;p?q", "//g", "http://g"},
+ {"http://a/b/c/d;p?q", "?y", "http://a/b/c/d;p?y"},
+ {"http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y"},
+ {"http://a/b/c/d;p?q", "#s", "http://a/b/c/d;p?q#s"},
+ {"http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s"},
+ {"http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s"},
+ {"http://a/b/c/d;p?q", ";x", "http://a/b/c/;x"},
+ {"http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x"},
+ {"http://a/b/c/d;p?q", "g;x?y#s", "http://a/b/c/g;x?y#s"},
+ {"http://a/b/c/d;p?q", "", "http://a/b/c/d;p?q"},
+ {"http://a/b/c/d;p?q", ".", "http://a/b/c/"},
+ {"http://a/b/c/d;p?q", "./", "http://a/b/c/"},
+ {"http://a/b/c/d;p?q", "..", "http://a/b/"},
+ {"http://a/b/c/d;p?q", "../", "http://a/b/"},
+ {"http://a/b/c/d;p?q", "../g", "http://a/b/g"},
+ {"http://a/b/c/d;p?q", "../..", "http://a/"},
+ {"http://a/b/c/d;p?q", "../../", "http://a/"},
+ {"http://a/b/c/d;p?q", "../../g", "http://a/g"},
+
+ // RFC 3986: Abnormal Examples
+ // http://tools.ietf.org/html/rfc3986#section-5.4.2
+ {"http://a/b/c/d;p?q", "../../../g", "http://a/g"},
+ {"http://a/b/c/d;p?q", "../../../../g", "http://a/g"},
+ {"http://a/b/c/d;p?q", "/./g", "http://a/g"},
+ {"http://a/b/c/d;p?q", "/../g", "http://a/g"},
+ {"http://a/b/c/d;p?q", "g.", "http://a/b/c/g."},
+ {"http://a/b/c/d;p?q", ".g", "http://a/b/c/.g"},
+ {"http://a/b/c/d;p?q", "g..", "http://a/b/c/g.."},
+ {"http://a/b/c/d;p?q", "..g", "http://a/b/c/..g"},
+ {"http://a/b/c/d;p?q", "./../g", "http://a/b/g"},
+ {"http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/"},
+ {"http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h"},
+ {"http://a/b/c/d;p?q", "g/../h", "http://a/b/c/h"},
+ {"http://a/b/c/d;p?q", "g;x=1/./y", "http://a/b/c/g;x=1/y"},
+ {"http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y"},
+ {"http://a/b/c/d;p?q", "g?y/./x", "http://a/b/c/g?y/./x"},
+ {"http://a/b/c/d;p?q", "g?y/../x", "http://a/b/c/g?y/../x"},
+ {"http://a/b/c/d;p?q", "g#s/./x", "http://a/b/c/g#s/./x"},
+ {"http://a/b/c/d;p?q", "g#s/../x", "http://a/b/c/g#s/../x"},
+
+ // Extras.
+ {"https://a/b/c/d;p?q", "//g?q", "https://g?q"},
+ {"https://a/b/c/d;p?q", "//g#s", "https://g#s"},
+ {"https://a/b/c/d;p?q", "//g/d/e/f?y#s", "https://g/d/e/f?y#s"},
+ {"https://a/b/c/d;p#s", "?y", "https://a/b/c/d;p?y"},
+ {"https://a/b/c/d;p?q#s", "?y", "https://a/b/c/d;p?y"},
}
func TestResolveReference(t *testing.T) {
@@ -607,91 +662,44 @@ func TestResolveReference(t *testing.T) {
}
return u
}
+ opaque := &URL{Scheme: "scheme", Opaque: "opaque"}
for _, test := range resolveReferenceTests {
base := mustParse(test.base)
rel := mustParse(test.rel)
url := base.ResolveReference(rel)
- urlStr := url.String()
- if urlStr != test.expected {
- t.Errorf("Resolving %q + %q != %q; got %q", test.base, test.rel, test.expected, urlStr)
+ if url.String() != test.expected {
+ t.Errorf("URL(%q).ResolveReference(%q) == %q, got %q", test.base, test.rel, test.expected, url.String())
}
- }
-
- // Test that new instances are returned.
- base := mustParse("http://foo.com/")
- abs := base.ResolveReference(mustParse("."))
- if base == abs {
- t.Errorf("Expected no-op reference to return new URL instance.")
- }
- barRef := mustParse("http://bar.com/")
- abs = base.ResolveReference(barRef)
- if abs == barRef {
- t.Errorf("Expected resolution of absolute reference to return new URL instance.")
- }
-
- // Test the convenience wrapper too
- base = mustParse("http://foo.com/path/one/")
- abs, _ = base.Parse("../two")
- expected := "http://foo.com/path/two"
- if abs.String() != expected {
- t.Errorf("Parse wrapper got %q; expected %q", abs.String(), expected)
- }
- _, err := base.Parse("")
- if err == nil {
- t.Errorf("Expected an error from Parse wrapper parsing an empty string.")
- }
-
- // Ensure Opaque resets the URL.
- base = mustParse("scheme://user@foo.com/bar")
- abs = base.ResolveReference(&URL{Opaque: "opaque"})
- want := mustParse("scheme:opaque")
- if *abs != *want {
- t.Errorf("ResolveReference failed to resolve opaque URL: want %#v, got %#v", abs, want)
- }
-}
-
-func TestResolveReferenceOpaque(t *testing.T) {
- mustParse := func(url string) *URL {
- u, err := Parse(url)
+ // Ensure that new instances are returned.
+ if base == url {
+ t.Errorf("Expected URL.ResolveReference to return new URL instance.")
+ }
+ // Test the convenience wrapper too.
+ url, err := base.Parse(test.rel)
if err != nil {
- t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
+ t.Errorf("URL(%q).Parse(%q) failed: %v", test.base, test.rel, err)
+ } else if url.String() != test.expected {
+ t.Errorf("URL(%q).Parse(%q) == %q, got %q", test.base, test.rel, test.expected, url.String())
+ } else if base == url {
+ // Ensure that new instances are returned for the wrapper too.
+ t.Errorf("Expected URL.Parse to return new URL instance.")
}
- return u
- }
- for _, test := range resolveReferenceTests {
- base := mustParse(test.base)
- rel := mustParse(test.rel)
- url := base.ResolveReference(rel)
- urlStr := url.String()
- if urlStr != test.expected {
- t.Errorf("Resolving %q + %q != %q; got %q", test.base, test.rel, test.expected, urlStr)
+ // Ensure Opaque resets the URL.
+ url = base.ResolveReference(opaque)
+ if *url != *opaque {
+ t.Errorf("ResolveReference failed to resolve opaque URL: want %#v, got %#v", url, opaque)
+ }
+ // Test the convenience wrapper with an opaque URL too.
+ url, err = base.Parse("scheme:opaque")
+ if err != nil {
+ t.Errorf(`URL(%q).Parse("scheme:opaque") failed: %v`, test.base, err)
+ } else if *url != *opaque {
+ t.Errorf("Parse failed to resolve opaque URL: want %#v, got %#v", url, opaque)
+ } else if base == url {
+ // Ensure that new instances are returned, again.
+ t.Errorf("Expected URL.Parse to return new URL instance.")
}
}
-
- // Test that new instances are returned.
- base := mustParse("http://foo.com/")
- abs := base.ResolveReference(mustParse("."))
- if base == abs {
- t.Errorf("Expected no-op reference to return new URL instance.")
- }
- barRef := mustParse("http://bar.com/")
- abs = base.ResolveReference(barRef)
- if abs == barRef {
- t.Errorf("Expected resolution of absolute reference to return new URL instance.")
- }
-
- // Test the convenience wrapper too
- base = mustParse("http://foo.com/path/one/")
- abs, _ = base.Parse("../two")
- expected := "http://foo.com/path/two"
- if abs.String() != expected {
- t.Errorf("Parse wrapper got %q; expected %q", abs.String(), expected)
- }
- _, err := base.Parse("")
- if err == nil {
- t.Errorf("Expected an error from Parse wrapper parsing an empty string.")
- }
-
}
func TestQueryValues(t *testing.T) {
diff --git a/src/pkg/os/exec/exec.go b/src/pkg/os/exec/exec.go
index 8368491b0..a3bbcf300 100644
--- a/src/pkg/os/exec/exec.go
+++ b/src/pkg/os/exec/exec.go
@@ -235,6 +235,8 @@ func (c *Cmd) Run() error {
// Start starts the specified command but does not wait for it to complete.
func (c *Cmd) Start() error {
if c.err != nil {
+ c.closeDescriptors(c.closeAfterStart)
+ c.closeDescriptors(c.closeAfterWait)
return c.err
}
if c.Process != nil {
diff --git a/src/pkg/os/exec/exec_test.go b/src/pkg/os/exec/exec_test.go
index 611ac0267..dfcf4be23 100644
--- a/src/pkg/os/exec/exec_test.go
+++ b/src/pkg/os/exec/exec_test.go
@@ -151,6 +151,33 @@ func TestPipes(t *testing.T) {
check("Wait", err)
}
+// Issue 5071
+func TestPipeLookPathLeak(t *testing.T) {
+ fd0 := numOpenFDS(t)
+ for i := 0; i < 4; i++ {
+ cmd := Command("something-that-does-not-exist-binary")
+ cmd.StdoutPipe()
+ cmd.StderrPipe()
+ cmd.StdinPipe()
+ if err := cmd.Run(); err == nil {
+ t.Fatal("unexpected success")
+ }
+ }
+ fdGrowth := numOpenFDS(t) - fd0
+ if fdGrowth > 2 {
+ t.Errorf("leaked %d fds; want ~0", fdGrowth)
+ }
+}
+
+func numOpenFDS(t *testing.T) int {
+ lsof, err := Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
+ if err != nil {
+ t.Skip("skipping test; error finding or running lsof")
+ return 0
+ }
+ return bytes.Count(lsof, []byte("\n"))
+}
+
var testedAlreadyLeaked = false
// basefds returns the number of expected file descriptors
diff --git a/src/pkg/os/file_posix.go b/src/pkg/os/file_posix.go
index b979fed97..3df43feaa 100644
--- a/src/pkg/os/file_posix.go
+++ b/src/pkg/os/file_posix.go
@@ -46,8 +46,6 @@ func Readlink(name string) (string, error) {
return string(b[0:n]), nil
}
}
- // Silence 6g.
- return "", nil
}
// Rename renames a file.
diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go
index 4f59c94cb..898e7634a 100644
--- a/src/pkg/os/file_unix.go
+++ b/src/pkg/os/file_unix.go
@@ -198,7 +198,6 @@ func (f *File) write(b []byte) (n int, err error) {
return n, err
}
- panic("not reached")
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go
index 2eba7a475..82af756d8 100644
--- a/src/pkg/os/file_windows.go
+++ b/src/pkg/os/file_windows.go
@@ -243,7 +243,7 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) {
return fi, nil
}
-// readConsole reads utf16 charcters from console File,
+// readConsole reads utf16 characters from console File,
// encodes them into utf8 and stores them in buffer b.
// It returns the number of utf8 bytes read and an error, if any.
func (f *File) readConsole(b []byte) (n int, err error) {
diff --git a/src/pkg/os/getwd.go b/src/pkg/os/getwd.go
index 1b2212306..0235c5d77 100644
--- a/src/pkg/os/getwd.go
+++ b/src/pkg/os/getwd.go
@@ -90,8 +90,6 @@ func Getwd() (pwd string, err error) {
}
}
}
- fd.Close()
- return "", ErrNotExist
Found:
pd, err := fd.Stat()
diff --git a/src/pkg/os/signal/sig.s b/src/pkg/os/signal/sig.s
index d1984cf88..df4855de8 100644
--- a/src/pkg/os/signal/sig.s
+++ b/src/pkg/os/signal/sig.s
@@ -4,10 +4,15 @@
// Assembly to get into package runtime without using exported symbols.
+// +build amd64 arm 386
+
#ifdef GOARCH_arm
#define JMP B
#endif
+TEXT ·signal_disable(SB),7,$0
+ JMP runtime·signal_disable(SB)
+
TEXT ·signal_enable(SB),7,$0
JMP runtime·signal_enable(SB)
diff --git a/src/pkg/os/signal/signal.go b/src/pkg/os/signal/signal.go
index dfdcf4061..300427549 100644
--- a/src/pkg/os/signal/signal.go
+++ b/src/pkg/os/signal/signal.go
@@ -5,7 +5,7 @@
// Package signal implements access to incoming signals.
package signal
-// BUG(rsc): This package is not yet implemented on Plan 9 and Windows.
+// BUG(rsc): This package is not yet implemented on Plan 9.
import (
"os"
@@ -14,13 +14,20 @@ import (
var handlers struct {
sync.Mutex
- list []handler
+ m map[chan<- os.Signal]*handler
+ ref [numSig]int64
}
type handler struct {
- c chan<- os.Signal
- sig os.Signal
- all bool
+ mask [(numSig + 31) / 32]uint32
+}
+
+func (h *handler) want(sig int) bool {
+ return (h.mask[sig/32]>>uint(sig&31))&1 != 0
+}
+
+func (h *handler) set(sig int) {
+ h.mask[sig/32] |= 1 << uint(sig&31)
}
// Notify causes package signal to relay incoming signals to c.
@@ -32,6 +39,13 @@ type handler struct {
// signal rate. For a channel used for notification of just one signal value,
// a buffer of size 1 is sufficient.
//
+// It is allowed to call Notify multiple times with the same channel:
+// each call expands the set of signals sent to that channel.
+// The only way to remove signals from the set is to call Stop.
+//
+// It is allowed to call Notify multiple times with different channels
+// and the same signals: each channel receives copies of incoming
+// signals independently.
func Notify(c chan<- os.Signal, sig ...os.Signal) {
if c == nil {
panic("os/signal: Notify using nil channel")
@@ -39,32 +53,77 @@ func Notify(c chan<- os.Signal, sig ...os.Signal) {
handlers.Lock()
defer handlers.Unlock()
+
+ h := handlers.m[c]
+ if h == nil {
+ if handlers.m == nil {
+ handlers.m = make(map[chan<- os.Signal]*handler)
+ }
+ h = new(handler)
+ handlers.m[c] = h
+ }
+
+ add := func(n int) {
+ if n < 0 {
+ return
+ }
+ if !h.want(n) {
+ h.set(n)
+ if handlers.ref[n] == 0 {
+ enableSignal(n)
+ }
+ handlers.ref[n]++
+ }
+ }
+
if len(sig) == 0 {
- enableSignal(nil)
- handlers.list = append(handlers.list, handler{c: c, all: true})
+ for n := 0; n < numSig; n++ {
+ add(n)
+ }
} else {
for _, s := range sig {
- // We use nil as a special wildcard value for enableSignal,
- // so filter it out of the list of arguments. This is safe because
- // we will never get an incoming nil signal, so discarding the
- // registration cannot affect the observed behavior.
- if s != nil {
- enableSignal(s)
- handlers.list = append(handlers.list, handler{c: c, sig: s})
+ add(signum(s))
+ }
+ }
+}
+
+// Stop causes package signal to stop relaying incoming signals to c.
+// It undoes the effect of all prior calls to Notify using c.
+// When Stop returns, it is guaranteed that c will receive no more signals.
+func Stop(c chan<- os.Signal) {
+ handlers.Lock()
+ defer handlers.Unlock()
+
+ h := handlers.m[c]
+ if h == nil {
+ return
+ }
+ delete(handlers.m, c)
+
+ for n := 0; n < numSig; n++ {
+ if h.want(n) {
+ handlers.ref[n]--
+ if handlers.ref[n] == 0 {
+ disableSignal(n)
}
}
}
}
func process(sig os.Signal) {
+ n := signum(sig)
+ if n < 0 {
+ return
+ }
+
handlers.Lock()
defer handlers.Unlock()
- for _, h := range handlers.list {
- if h.all || h.sig == sig {
+ for c, h := range handlers.m {
+ if h.want(n) {
// send but do not block for it
select {
- case h.c <- sig:
+ case c <- sig:
default:
}
}
diff --git a/src/pkg/os/signal/signal_stub.go b/src/pkg/os/signal/signal_stub.go
index fc227cf4c..d0a6935ff 100644
--- a/src/pkg/os/signal/signal_stub.go
+++ b/src/pkg/os/signal/signal_stub.go
@@ -8,4 +8,10 @@ package signal
import "os"
-func enableSignal(sig os.Signal) {}
+const numSig = 0
+
+func signum(sig os.Signal) int { return -1 }
+
+func disableSignal(int) {}
+
+func enableSignal(int) {}
diff --git a/src/pkg/os/signal/signal_test.go b/src/pkg/os/signal/signal_test.go
index 509b273aa..d13833306 100644
--- a/src/pkg/os/signal/signal_test.go
+++ b/src/pkg/os/signal/signal_test.go
@@ -7,15 +7,17 @@
package signal
import (
+ "flag"
+ "io/ioutil"
"os"
+ "os/exec"
"runtime"
+ "strconv"
"syscall"
"testing"
"time"
)
-const sighup = syscall.SIGHUP
-
func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) {
select {
case s := <-c:
@@ -27,15 +29,17 @@ func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) {
}
}
+// Test that basic signal handling works.
func TestSignal(t *testing.T) {
// Ask for SIGHUP
c := make(chan os.Signal, 1)
- Notify(c, sighup)
+ Notify(c, syscall.SIGHUP)
+ defer Stop(c)
t.Logf("sighup...")
// Send this process a SIGHUP
- syscall.Kill(syscall.Getpid(), sighup)
- waitSig(t, c, sighup)
+ syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
+ waitSig(t, c, syscall.SIGHUP)
// Ask for everything we can get.
c1 := make(chan os.Signal, 1)
@@ -71,6 +75,7 @@ func TestStress(t *testing.T) {
go func() {
sig := make(chan os.Signal, 1)
Notify(sig, syscall.SIGUSR1)
+ defer Stop(sig)
Loop:
for {
select {
@@ -98,4 +103,106 @@ func TestStress(t *testing.T) {
close(done)
<-finished
<-finished
+ // When run with 'go test -cpu=1,2,4' SIGUSR1 from this test can slip
+ // into subsequent TestSignal() causing failure.
+ // Sleep for a while to reduce the possibility of the failure.
+ time.Sleep(10 * time.Millisecond)
+}
+
+var sendUncaughtSighup = flag.Int("send_uncaught_sighup", 0, "send uncaught SIGHUP during TestStop")
+
+// Test that Stop cancels the channel's registrations.
+func TestStop(t *testing.T) {
+ sigs := []syscall.Signal{
+ syscall.SIGWINCH,
+ syscall.SIGHUP,
+ }
+
+ for _, sig := range sigs {
+ // Send the signal.
+ // If it's SIGWINCH, we should not see it.
+ // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
+ if sig != syscall.SIGHUP || *sendUncaughtSighup == 1 {
+ syscall.Kill(syscall.Getpid(), sig)
+ }
+ time.Sleep(10 * time.Millisecond)
+
+ // Ask for signal
+ c := make(chan os.Signal, 1)
+ Notify(c, sig)
+ defer Stop(c)
+
+ // Send this process that signal
+ syscall.Kill(syscall.Getpid(), sig)
+ waitSig(t, c, sig)
+
+ Stop(c)
+ select {
+ case s := <-c:
+ t.Fatalf("unexpected signal %v", s)
+ case <-time.After(10 * time.Millisecond):
+ // nothing to read - good
+ }
+
+ // Send the signal.
+ // If it's SIGWINCH, we should not see it.
+ // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
+ if sig != syscall.SIGHUP || *sendUncaughtSighup == 2 {
+ syscall.Kill(syscall.Getpid(), sig)
+ }
+
+ select {
+ case s := <-c:
+ t.Fatalf("unexpected signal %v", s)
+ case <-time.After(10 * time.Millisecond):
+ // nothing to read - good
+ }
+ }
+}
+
+// Test that when run under nohup, an uncaught SIGHUP does not kill the program,
+// but a
+func TestNohup(t *testing.T) {
+ // Ugly: ask for SIGHUP so that child will not have no-hup set
+ // even if test is running under nohup environment.
+ // We have no intention of reading from c.
+ c := make(chan os.Signal, 1)
+ Notify(c, syscall.SIGHUP)
+
+ // When run without nohup, the test should crash on an uncaught SIGHUP.
+ // When run under nohup, the test should ignore uncaught SIGHUPs,
+ // because the runtime is not supposed to be listening for them.
+ // Either way, TestStop should still be able to catch them when it wants them
+ // and then when it stops wanting them, the original behavior should resume.
+ //
+ // send_uncaught_sighup=1 sends the SIGHUP before starting to listen for SIGHUPs.
+ // send_uncaught_sighup=2 sends the SIGHUP after no longer listening for SIGHUPs.
+ //
+ // Both should fail without nohup and succeed with nohup.
+
+ for i := 1; i <= 2; i++ {
+ out, err := exec.Command(os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput()
+ if err == nil {
+ t.Fatalf("ran test with -send_uncaught_sighup=%d and it succeeded: expected failure.\nOutput:\n%s", i, out)
+ }
+ }
+
+ Stop(c)
+
+ // Again, this time with nohup, assuming we can find it.
+ _, err := os.Stat("/usr/bin/nohup")
+ if err != nil {
+ t.Skip("cannot find nohup; skipping second half of test")
+ }
+
+ for i := 1; i <= 2; i++ {
+ os.Remove("nohup.out")
+ out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput()
+
+ data, _ := ioutil.ReadFile("nohup.out")
+ os.Remove("nohup.out")
+ if err != nil {
+ t.Fatalf("ran test with -send_uncaught_sighup=%d under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", i, err, out, data)
+ }
+ }
}
diff --git a/src/pkg/os/signal/signal_unix.go b/src/pkg/os/signal/signal_unix.go
index 20ee5f26a..6b4c8ab66 100644
--- a/src/pkg/os/signal/signal_unix.go
+++ b/src/pkg/os/signal/signal_unix.go
@@ -12,6 +12,7 @@ import (
)
// In assembly.
+func signal_disable(uint32)
func signal_enable(uint32)
func signal_recv() uint32
@@ -26,13 +27,27 @@ func init() {
go loop()
}
-func enableSignal(sig os.Signal) {
+const (
+ numSig = 65 // max across all systems
+)
+
+func signum(sig os.Signal) int {
switch sig := sig.(type) {
- case nil:
- signal_enable(^uint32(0))
case syscall.Signal:
- signal_enable(uint32(sig))
+ i := int(sig)
+ if i < 0 || i >= numSig {
+ return -1
+ }
+ return i
default:
- // Can ignore: this signal (whatever it is) will never come in.
+ return -1
}
}
+
+func enableSignal(sig int) {
+ signal_enable(uint32(sig))
+}
+
+func disableSignal(sig int) {
+ signal_disable(uint32(sig))
+}
diff --git a/src/pkg/path/filepath/path_test.go b/src/pkg/path/filepath/path_test.go
index e768ad32f..c4d73602f 100644
--- a/src/pkg/path/filepath/path_test.go
+++ b/src/pkg/path/filepath/path_test.go
@@ -107,6 +107,11 @@ func TestClean(t *testing.T) {
}
}
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
+ return
+ }
+
for _, test := range tests {
allocs := testing.AllocsPerRun(100, func() { filepath.Clean(test.result) })
if allocs > 0 {
diff --git a/src/pkg/path/path_test.go b/src/pkg/path/path_test.go
index 220ec1a0b..69caa80e4 100644
--- a/src/pkg/path/path_test.go
+++ b/src/pkg/path/path_test.go
@@ -5,6 +5,7 @@
package path
import (
+ "runtime"
"testing"
)
@@ -72,6 +73,11 @@ func TestClean(t *testing.T) {
}
}
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
+ return
+ }
+
for _, test := range cleantests {
allocs := testing.AllocsPerRun(100, func() { Clean(test.result) })
if allocs > 0 {
diff --git a/src/pkg/reflect/all_test.go b/src/pkg/reflect/all_test.go
index 6f006db18..9a4dd6c31 100644
--- a/src/pkg/reflect/all_test.go
+++ b/src/pkg/reflect/all_test.go
@@ -13,6 +13,7 @@ import (
"math/rand"
"os"
. "reflect"
+ "runtime"
"sync"
"testing"
"time"
@@ -1457,7 +1458,7 @@ func (p Point) AnotherMethod(scale int) int {
// This will be index 1.
func (p Point) Dist(scale int) int {
- // println("Point.Dist", p.x, p.y, scale)
+ //println("Point.Dist", p.x, p.y, scale)
return p.x*p.x*scale + p.y*p.y*scale
}
@@ -1473,23 +1474,23 @@ func TestMethod(t *testing.T) {
if !ok {
t.Fatalf("method by name failed")
}
- m.Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Type MethodByName returned %d; want 250", i)
+ i = m.Func.Call([]Value{ValueOf(p), ValueOf(11)})[0].Int()
+ if i != 275 {
+ t.Errorf("Type MethodByName returned %d; want 275", i)
}
- i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Pointer Type Method returned %d; want 250", i)
+ i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int()
+ if i != 300 {
+ t.Errorf("Pointer Type Method returned %d; want 300", i)
}
m, ok = TypeOf(&p).MethodByName("Dist")
if !ok {
t.Fatalf("ptr method by name failed")
}
- i = m.Func.Call([]Value{ValueOf(&p), ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Pointer Type MethodByName returned %d; want 250", i)
+ i = m.Func.Call([]Value{ValueOf(&p), ValueOf(13)})[0].Int()
+ if i != 325 {
+ t.Errorf("Pointer Type MethodByName returned %d; want 325", i)
}
// Curried method of value.
@@ -1498,7 +1499,74 @@ func TestMethod(t *testing.T) {
if tt := v.Type(); tt != tfunc {
t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
}
- i = v.Call([]Value{ValueOf(10)})[0].Int()
+ i = v.Call([]Value{ValueOf(14)})[0].Int()
+ if i != 350 {
+ t.Errorf("Value Method returned %d; want 350", i)
+ }
+ v = ValueOf(p).MethodByName("Dist")
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(15)})[0].Int()
+ if i != 375 {
+ t.Errorf("Value MethodByName returned %d; want 375", i)
+ }
+
+ // Curried method of pointer.
+ v = ValueOf(&p).Method(1)
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(16)})[0].Int()
+ if i != 400 {
+ t.Errorf("Pointer Value Method returned %d; want 400", i)
+ }
+ v = ValueOf(&p).MethodByName("Dist")
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(17)})[0].Int()
+ if i != 425 {
+ t.Errorf("Pointer Value MethodByName returned %d; want 425", i)
+ }
+
+ // Curried method of interface value.
+ // Have to wrap interface value in a struct to get at it.
+ // Passing it to ValueOf directly would
+ // access the underlying Point, not the interface.
+ var x interface {
+ Dist(int) int
+ } = p
+ pv := ValueOf(&x).Elem()
+ v = pv.Method(0)
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(18)})[0].Int()
+ if i != 450 {
+ t.Errorf("Interface Method returned %d; want 450", i)
+ }
+ v = pv.MethodByName("Dist")
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
+ }
+ i = v.Call([]Value{ValueOf(19)})[0].Int()
+ if i != 475 {
+ t.Errorf("Interface MethodByName returned %d; want 475", i)
+ }
+}
+
+func TestMethodValue(t *testing.T) {
+ p := Point{3, 4}
+ var i int64
+
+ // Curried method of value.
+ 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)
+ }
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(10)})[0].Int()
if i != 250 {
t.Errorf("Value Method returned %d; want 250", i)
}
@@ -1506,9 +1574,9 @@ func TestMethod(t *testing.T) {
if tt := v.Type(); tt != tfunc {
t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
}
- i = v.Call([]Value{ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Value MethodByName returned %d; want 250", i)
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(11)})[0].Int()
+ if i != 275 {
+ t.Errorf("Value MethodByName returned %d; want 275", i)
}
// Curried method of pointer.
@@ -1516,17 +1584,17 @@ func TestMethod(t *testing.T) {
if tt := v.Type(); tt != tfunc {
t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
}
- i = v.Call([]Value{ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Pointer Value Method returned %d; want 250", i)
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(12)})[0].Int()
+ if i != 300 {
+ t.Errorf("Pointer Value Method returned %d; want 300", i)
}
v = ValueOf(&p).MethodByName("Dist")
if tt := v.Type(); tt != tfunc {
t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
}
- i = v.Call([]Value{ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Pointer Value MethodByName returned %d; want 250", i)
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(13)})[0].Int()
+ if i != 325 {
+ t.Errorf("Pointer Value MethodByName returned %d; want 325", i)
}
// Curried method of interface value.
@@ -1543,18 +1611,201 @@ func TestMethod(t *testing.T) {
if tt := v.Type(); tt != tfunc {
t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
}
- i = v.Call([]Value{ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Interface Method returned %d; want 250", i)
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(14)})[0].Int()
+ if i != 350 {
+ t.Errorf("Interface Method returned %d; want 350", i)
}
v = pv.MethodByName("Dist")
if tt := v.Type(); tt != tfunc {
t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
}
- i = v.Call([]Value{ValueOf(10)})[0].Int()
- if i != 250 {
- t.Errorf("Interface MethodByName returned %d; want 250", i)
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(15)})[0].Int()
+ if i != 375 {
+ t.Errorf("Interface MethodByName returned %d; want 375", i)
+ }
+}
+
+// Reflect version of $GOROOT/test/method5.go
+
+// Concrete types implementing M method.
+// Smaller than a word, word-sized, larger than a word.
+// Value and pointer receivers.
+
+type Tinter interface {
+ M(int, byte) (byte, int)
+}
+
+type Tsmallv byte
+
+func (v Tsmallv) M(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type Tsmallp byte
+
+func (p *Tsmallp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type Twordv uintptr
+
+func (v Twordv) M(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type Twordp uintptr
+
+func (p *Twordp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type Tbigv [2]uintptr
+
+func (v Tbigv) M(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
+
+type Tbigp [2]uintptr
+
+func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
+
+// Again, with an unexported method.
+
+type tsmallv byte
+
+func (v tsmallv) m(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type tsmallp byte
+
+func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type twordv uintptr
+
+func (v twordv) m(x int, b byte) (byte, int) { return b, x + int(v) }
+
+type twordp uintptr
+
+func (p *twordp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
+
+type tbigv [2]uintptr
+
+func (v tbigv) m(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
+
+type tbigp [2]uintptr
+
+func (p *tbigp) m(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
+
+type tinter interface {
+ m(int, byte) (byte, int)
+}
+
+// Embedding via pointer.
+
+type Tm1 struct {
+ Tm2
+}
+
+type Tm2 struct {
+ *Tm3
+}
+
+type Tm3 struct {
+ *Tm4
+}
+
+type Tm4 struct {
+}
+
+func (t4 Tm4) M(x int, b byte) (byte, int) { return b, x + 40 }
+
+func TestMethod5(t *testing.T) {
+ CheckF := func(name string, f func(int, byte) (byte, int), inc int) {
+ b, x := f(1000, 99)
+ if b != 99 || x != 1000+inc {
+ t.Errorf("%s(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
+ }
+ }
+
+ CheckV := func(name string, i Value, inc int) {
+ bx := i.Method(0).Call([]Value{ValueOf(1000), ValueOf(byte(99))})
+ b := bx[0].Interface()
+ x := bx[1].Interface()
+ if b != byte(99) || x != 1000+inc {
+ t.Errorf("direct %s.M(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
+ }
+
+ CheckF(name+".M", i.Method(0).Interface().(func(int, byte) (byte, int)), inc)
+ }
+
+ var TinterType = TypeOf(new(Tinter)).Elem()
+ var tinterType = TypeOf(new(tinter)).Elem()
+
+ CheckI := func(name string, i interface{}, inc int) {
+ v := ValueOf(i)
+ CheckV(name, v, inc)
+ CheckV("(i="+name+")", v.Convert(TinterType), inc)
+ }
+
+ sv := Tsmallv(1)
+ CheckI("sv", sv, 1)
+ CheckI("&sv", &sv, 1)
+
+ sp := Tsmallp(2)
+ CheckI("&sp", &sp, 2)
+
+ wv := Twordv(3)
+ CheckI("wv", wv, 3)
+ CheckI("&wv", &wv, 3)
+
+ wp := Twordp(4)
+ CheckI("&wp", &wp, 4)
+
+ bv := Tbigv([2]uintptr{5, 6})
+ CheckI("bv", bv, 11)
+ CheckI("&bv", &bv, 11)
+
+ bp := Tbigp([2]uintptr{7, 8})
+ CheckI("&bp", &bp, 15)
+
+ t4 := Tm4{}
+ t3 := Tm3{&t4}
+ t2 := Tm2{&t3}
+ t1 := Tm1{t2}
+ CheckI("t4", t4, 40)
+ CheckI("&t4", &t4, 40)
+ CheckI("t3", t3, 40)
+ CheckI("&t3", &t3, 40)
+ CheckI("t2", t2, 40)
+ CheckI("&t2", &t2, 40)
+ CheckI("t1", t1, 40)
+ CheckI("&t1", &t1, 40)
+
+ methodShouldPanic := func(name string, i interface{}) {
+ v := ValueOf(i)
+ m := v.Method(0)
+ shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
+ shouldPanic(func() { m.Interface() })
+
+ v = v.Convert(tinterType)
+ m = v.Method(0)
+ shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
+ shouldPanic(func() { m.Interface() })
}
+
+ _sv := tsmallv(1)
+ methodShouldPanic("_sv", _sv)
+ methodShouldPanic("&_sv", &_sv)
+
+ _sp := tsmallp(2)
+ methodShouldPanic("&_sp", &_sp)
+
+ _wv := twordv(3)
+ methodShouldPanic("_wv", _wv)
+ methodShouldPanic("&_wv", &_wv)
+
+ _wp := twordp(4)
+ methodShouldPanic("&_wp", &_wp)
+
+ _bv := tbigv([2]uintptr{5, 6})
+ methodShouldPanic("_bv", _bv)
+ methodShouldPanic("&_bv", &_bv)
+
+ _bp := tbigp([2]uintptr{7, 8})
+ methodShouldPanic("&_bp", &_bp)
+
+ var tnil Tinter
+ vnil := ValueOf(&tnil).Elem()
+ shouldPanic(func() { vnil.Method(0) })
}
func TestInterfaceSet(t *testing.T) {
@@ -2011,6 +2262,9 @@ func TestAddr(t *testing.T) {
}
func noAlloc(t *testing.T, n int, f func(int)) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
i := -1
allocs := testing.AllocsPerRun(n, func() {
f(i)
diff --git a/src/pkg/reflect/asm_386.s b/src/pkg/reflect/asm_386.s
index 27d3fa21d..bbd068d98 100644
--- a/src/pkg/reflect/asm_386.s
+++ b/src/pkg/reflect/asm_386.s
@@ -3,11 +3,21 @@
// license that can be found in the LICENSE file.
// makeFuncStub is the code half of the function returned by MakeFunc.
-// See the comment on the declaration of makeFuncStub in value.go
+// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
TEXT ·makeFuncStub(SB),7,$8
MOVL DX, 0(SP)
- LEAL arg+0(FP), CX
+ LEAL argframe+0(FP), CX
MOVL CX, 4(SP)
CALL ·callReflect(SB)
RET
+
+// methodValueCall is the code half of the function returned by makeMethodValue.
+// See the comment on the declaration of methodValueCall in makefunc.go
+// for more details.
+TEXT ·methodValueCall(SB),7,$8
+ MOVL DX, 0(SP)
+ LEAL argframe+0(FP), CX
+ MOVL CX, 4(SP)
+ CALL ·callMethod(SB)
+ RET
diff --git a/src/pkg/reflect/asm_amd64.s b/src/pkg/reflect/asm_amd64.s
index d51d982a9..2e7fce55d 100644
--- a/src/pkg/reflect/asm_amd64.s
+++ b/src/pkg/reflect/asm_amd64.s
@@ -3,11 +3,21 @@
// license that can be found in the LICENSE file.
// makeFuncStub is the code half of the function returned by MakeFunc.
-// See the comment on the declaration of makeFuncStub in value.go
+// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
TEXT ·makeFuncStub(SB),7,$16
MOVQ DX, 0(SP)
- LEAQ arg+0(FP), CX
+ LEAQ argframe+0(FP), CX
MOVQ CX, 8(SP)
CALL ·callReflect(SB)
RET
+
+// methodValueCall is the code half of the function returned by makeMethodValue.
+// See the comment on the declaration of methodValueCall in makefunc.go
+// for more details.
+TEXT ·methodValueCall(SB),7,$16
+ MOVQ DX, 0(SP)
+ LEAQ argframe+0(FP), CX
+ MOVQ CX, 8(SP)
+ CALL ·callMethod(SB)
+ RET
diff --git a/src/pkg/reflect/asm_arm.s b/src/pkg/reflect/asm_arm.s
index db487f8a5..fb1dddebe 100644
--- a/src/pkg/reflect/asm_arm.s
+++ b/src/pkg/reflect/asm_arm.s
@@ -3,11 +3,21 @@
// license that can be found in the LICENSE file.
// makeFuncStub is jumped to by the code generated by MakeFunc.
-// See the comment on the declaration of makeFuncStub in value.go
+// See the comment on the declaration of makeFuncStub in makefunc.go
// for more details.
TEXT ·makeFuncStub(SB),7,$8
MOVW R7, 4(R13)
- MOVW $arg+0(FP), R1
+ MOVW $argframe+0(FP), R1
MOVW R1, 8(R13)
BL ·callReflect(SB)
RET
+
+// methodValueCall is the code half of the function returned by makeMethodValue.
+// See the comment on the declaration of methodValueCall in makefunc.go
+// for more details.
+TEXT ·methodValueCall(SB),7,$8
+ MOVW R7, 4(R13)
+ MOVW $argframe+0(FP), R1
+ MOVW R1, 8(R13)
+ BL ·callMethod(SB)
+ RET
diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go
index db047963e..915afed4c 100644
--- a/src/pkg/reflect/deepequal.go
+++ b/src/pkg/reflect/deepequal.go
@@ -118,8 +118,6 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
// Normal equality suffices
return valueInterface(v1, false) == valueInterface(v2, false)
}
-
- panic("Not reached")
}
// DeepEqual tests for deep equality. It uses normal == equality where
diff --git a/src/pkg/reflect/makefunc.go b/src/pkg/reflect/makefunc.go
index 024f938f1..ccdd683a0 100644
--- a/src/pkg/reflect/makefunc.go
+++ b/src/pkg/reflect/makefunc.go
@@ -48,8 +48,8 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
t := typ.common()
ftyp := (*funcType)(unsafe.Pointer(t))
- // indirect Go func value (dummy) to obtain
- // actual code address. (A Go func is a pointer
+ // Indirect Go func value (dummy) to obtain
+ // actual code address. (A Go func value is a pointer
// to a C function pointer. http://golang.org/s/go11func.)
dummy := makeFuncStub
code := **(**uintptr)(unsafe.Pointer(&dummy))
@@ -65,3 +65,56 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
// where ctxt is the context register and frame is a pointer to the first
// word in the passed-in argument frame.
func makeFuncStub()
+
+type methodValue struct {
+ fn uintptr
+ method int
+ rcvr Value
+}
+
+// makeMethodValue converts v from the rcvr+method index representation
+// of a method value to an actual method func value, which is
+// basically the receiver value with a special bit set, into a true
+// func value - a value holding an actual func. The output is
+// semantically equivalent to the input as far as the user of package
+// reflect can tell, but the true func representation can be handled
+// by code like Convert and Interface and Assign.
+func makeMethodValue(op string, v Value) Value {
+ if v.flag&flagMethod == 0 {
+ panic("reflect: internal error: invalid use of makePartialFunc")
+ }
+
+ // Ignoring the flagMethod bit, v describes the receiver, not the method type.
+ fl := v.flag & (flagRO | flagAddr | flagIndir)
+ fl |= flag(v.typ.Kind()) << flagKindShift
+ rcvr := Value{v.typ, v.val, fl}
+
+ // v.Type returns the actual type of the method value.
+ funcType := v.Type().(*rtype)
+
+ // Indirect Go func value (dummy) to obtain
+ // actual code address. (A Go func value is a pointer
+ // to a C function pointer. http://golang.org/s/go11func.)
+ dummy := methodValueCall
+ code := **(**uintptr)(unsafe.Pointer(&dummy))
+
+ fv := &methodValue{
+ fn: code,
+ method: int(v.flag) >> flagMethodShift,
+ rcvr: rcvr,
+ }
+
+ // Cause panic if method is not appropriate.
+ // The panic would still happen during the call if we omit this,
+ // but we want Interface() and other operations to fail early.
+ methodReceiver(op, fv.rcvr, fv.method)
+
+ return Value{funcType, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)<<flagKindShift}
+}
+
+// methodValueCall is an assembly function that is the code half of
+// the function returned from makeMethodValue. It expects a *methodValue
+// as its context register, and its job is to invoke callMethod(ctxt, frame)
+// where ctxt is the context register and frame is a pointer to the first
+// word in the passed-in argument frame.
+func methodValueCall()
diff --git a/src/pkg/reflect/tostring_test.go b/src/pkg/reflect/tostring_test.go
index 7486a9bfc..e416fd84d 100644
--- a/src/pkg/reflect/tostring_test.go
+++ b/src/pkg/reflect/tostring_test.go
@@ -92,5 +92,4 @@ func valueToString(val Value) string {
default:
panic("valueToString: can't print type " + typ.String())
}
- return "valueToString: can't happen"
}
diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go
index 94a7521a7..5ec94f576 100644
--- a/src/pkg/reflect/type.go
+++ b/src/pkg/reflect/type.go
@@ -1246,7 +1246,7 @@ func haveIdenticalUnderlyingType(T, V *rtype) bool {
}
// typelinks is implemented in package runtime.
-// It retuns a slice of all the 'typelink' information in the binary,
+// It returns a slice of all the 'typelink' information in the binary,
// which is to say a slice of known types, sorted by string.
// Note that strings are not unique identifiers for types:
// there can be more than one with a given string.
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index c87812c46..5a3720489 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -249,7 +249,7 @@ func (f flag) mustBeExported() {
panic(&ValueError{methodName(), 0})
}
if f&flagRO != 0 {
- panic(methodName() + " using value obtained using unexported field")
+ panic("reflect: " + methodName() + " using value obtained using unexported field")
}
}
@@ -262,10 +262,10 @@ func (f flag) mustBeAssignable() {
}
// Assignable if addressable and not read-only.
if f&flagRO != 0 {
- panic(methodName() + " using value obtained using unexported field")
+ panic("reflect: " + methodName() + " using value obtained using unexported field")
}
if f&flagAddr == 0 {
- panic(methodName() + " using unaddressable value")
+ panic("reflect: " + methodName() + " using unaddressable value")
}
}
@@ -358,7 +358,7 @@ func (v Value) CallSlice(in []Value) []Value {
return v.call("CallSlice", in)
}
-func (v Value) call(method string, in []Value) []Value {
+func (v Value) call(op string, in []Value) []Value {
// Get function pointer, type.
t := v.typ
var (
@@ -366,36 +366,7 @@ func (v Value) call(method string, in []Value) []Value {
rcvr iword
)
if v.flag&flagMethod != 0 {
- i := int(v.flag) >> flagMethodShift
- if v.typ.Kind() == Interface {
- tt := (*interfaceType)(unsafe.Pointer(v.typ))
- if i < 0 || i >= len(tt.methods) {
- panic("reflect: broken Value")
- }
- m := &tt.methods[i]
- if m.pkgPath != nil {
- panic(method + " of unexported method")
- }
- t = m.typ
- iface := (*nonEmptyInterface)(v.val)
- if iface.itab == nil {
- panic(method + " of method on nil interface value")
- }
- fn = unsafe.Pointer(&iface.itab.fun[i])
- rcvr = iface.word
- } else {
- ut := v.typ.uncommon()
- if ut == nil || i < 0 || i >= len(ut.methods) {
- panic("reflect: broken Value")
- }
- m := &ut.methods[i]
- if m.pkgPath != nil {
- panic(method + " of unexported method")
- }
- fn = unsafe.Pointer(&m.ifn)
- t = m.mtyp
- rcvr = v.iword()
- }
+ t, fn, rcvr = methodReceiver(op, v, int(v.flag)>>flagMethodShift)
} else if v.flag&flagIndir != 0 {
fn = *(*unsafe.Pointer)(v.val)
} else {
@@ -406,7 +377,7 @@ func (v Value) call(method string, in []Value) []Value {
panic("reflect.Value.Call: call of nil function")
}
- isSlice := method == "CallSlice"
+ isSlice := op == "CallSlice"
n := t.NumIn()
if isSlice {
if !t.IsVariadic() {
@@ -431,12 +402,12 @@ func (v Value) call(method string, in []Value) []Value {
}
for _, x := range in {
if x.Kind() == Invalid {
- panic("reflect: " + method + " using zero Value argument")
+ panic("reflect: " + op + " using zero Value argument")
}
}
for i := 0; i < n; i++ {
if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
- panic("reflect: " + method + " using " + xt.String() + " as type " + targ.String())
+ panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
}
}
if !isSlice && t.IsVariadic() {
@@ -447,7 +418,7 @@ func (v Value) call(method string, in []Value) []Value {
for i := 0; i < m; i++ {
x := in[n+i]
if xt := x.Type(); !xt.AssignableTo(elem) {
- panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + method)
+ panic("reflect: cannot use " + xt.String() + " as type " + elem.String() + " in " + op)
}
slice.Index(i).Set(x)
}
@@ -467,40 +438,11 @@ func (v Value) call(method string, in []Value) []Value {
// This computation is 5g/6g/8g-dependent
// and probably wrong for gccgo, but so
// is most of this function.
- size := uintptr(0)
- if v.flag&flagMethod != 0 {
- // extra word for receiver interface word
- size += ptrSize
- }
- for i := 0; i < nin; i++ {
- tv := t.In(i)
- a := uintptr(tv.Align())
- size = (size + a - 1) &^ (a - 1)
- size += tv.Size()
- }
- size = (size + ptrSize - 1) &^ (ptrSize - 1)
- for i := 0; i < nout; i++ {
- tv := t.Out(i)
- a := uintptr(tv.Align())
- size = (size + a - 1) &^ (a - 1)
- size += tv.Size()
- }
-
- // size must be > 0 in order for &args[0] to be valid.
- // the argument copying is going to round it up to
- // a multiple of ptrSize anyway, so make it ptrSize to begin with.
- if size < ptrSize {
- size = ptrSize
- }
-
- // round to pointer size
- size = (size + ptrSize - 1) &^ (ptrSize - 1)
+ size, _, _, _ := frameSize(t, v.flag&flagMethod != 0)
// Copy into args.
//
- // TODO(rsc): revisit when reference counting happens.
- // The values are holding up the in references for us,
- // but something must be done for the out references.
+ // TODO(rsc): This will need to be updated for any new garbage collector.
// For now make everything look like a pointer by allocating
// a []unsafe.Pointer.
args := make([]unsafe.Pointer, size/ptrSize)
@@ -616,6 +558,119 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
}
}
+// methodReceiver returns information about the receiver
+// described by v. The Value v may or may not have the
+// flagMethod bit set, so the kind cached in v.flag should
+// not be used.
+func methodReceiver(op string, v Value, methodIndex int) (t *rtype, fn unsafe.Pointer, rcvr iword) {
+ i := methodIndex
+ if v.typ.Kind() == Interface {
+ tt := (*interfaceType)(unsafe.Pointer(v.typ))
+ if i < 0 || i >= len(tt.methods) {
+ panic("reflect: internal error: invalid method index")
+ }
+ m := &tt.methods[i]
+ if m.pkgPath != nil {
+ panic("reflect: " + op + " of unexported method")
+ }
+ t = m.typ
+ iface := (*nonEmptyInterface)(v.val)
+ if iface.itab == nil {
+ panic("reflect: " + op + " of method on nil interface value")
+ }
+ fn = unsafe.Pointer(&iface.itab.fun[i])
+ rcvr = iface.word
+ } else {
+ ut := v.typ.uncommon()
+ if ut == nil || i < 0 || i >= len(ut.methods) {
+ panic("reflect: internal error: invalid method index")
+ }
+ m := &ut.methods[i]
+ if m.pkgPath != nil {
+ panic("reflect: " + op + " of unexported method")
+ }
+ fn = unsafe.Pointer(&m.ifn)
+ t = m.mtyp
+ rcvr = v.iword()
+ }
+ return
+}
+
+// align returns the result of rounding x up to a multiple of n.
+// n must be a power of two.
+func align(x, n uintptr) uintptr {
+ return (x + n - 1) &^ (n - 1)
+}
+
+// frameSize returns the sizes of the argument and result frame
+// for a function of the given type. The rcvr bool specifies whether
+// a one-word receiver should be included in the total.
+func frameSize(t *rtype, rcvr bool) (total, in, outOffset, out uintptr) {
+ if rcvr {
+ // extra word for receiver interface word
+ total += ptrSize
+ }
+
+ nin := t.NumIn()
+ in = -total
+ for i := 0; i < nin; i++ {
+ tv := t.In(i)
+ total = align(total, uintptr(tv.Align()))
+ total += tv.Size()
+ }
+ in += total
+ total = align(total, ptrSize)
+ nout := t.NumOut()
+ outOffset = total
+ out = -total
+ for i := 0; i < nout; i++ {
+ tv := t.Out(i)
+ total = align(total, uintptr(tv.Align()))
+ total += tv.Size()
+ }
+ out += total
+
+ // total must be > 0 in order for &args[0] to be valid.
+ // the argument copying is going to round it up to
+ // a multiple of ptrSize anyway, so make it ptrSize to begin with.
+ if total < ptrSize {
+ total = ptrSize
+ }
+
+ // round to pointer
+ total = align(total, ptrSize)
+
+ return
+}
+
+// callMethod is the call implementation used by a function returned
+// by makeMethodValue (used by v.Method(i).Interface()).
+// It is a streamlined version of the usual reflect call: the caller has
+// already laid out the argument frame for us, so we don't have
+// to deal with individual Values for each argument.
+// It is in this file so that it can be next to the two similar functions above.
+// The remainder of the makeMethodValue implementation is in makefunc.go.
+func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
+ t, fn, rcvr := methodReceiver("call", ctxt.rcvr, ctxt.method)
+ total, in, outOffset, out := frameSize(t, true)
+
+ // Copy into args.
+ //
+ // TODO(rsc): This will need to be updated for any new garbage collector.
+ // For now make everything look like a pointer by allocating
+ // a []unsafe.Pointer.
+ args := make([]unsafe.Pointer, total/ptrSize)
+ args[0] = unsafe.Pointer(rcvr)
+ base := unsafe.Pointer(&args[0])
+ memmove(unsafe.Pointer(uintptr(base)+ptrSize), frame, in)
+
+ // Call.
+ call(fn, unsafe.Pointer(&args[0]), uint32(total))
+
+ // Copy return values.
+ memmove(unsafe.Pointer(uintptr(frame)+outOffset-ptrSize), unsafe.Pointer(uintptr(base)+outOffset), out)
+}
+
// funcName returns the name of f, for use in error messages.
func funcName(f func([]Value) []Value) string {
pc := *(*uintptr)(unsafe.Pointer(&f))
@@ -902,7 +957,7 @@ func (v Value) CanInterface() bool {
if v.flag == 0 {
panic(&ValueError{"reflect.Value.CanInterface", Invalid})
}
- return v.flag&(flagMethod|flagRO) == 0
+ return v.flag&flagRO == 0
}
// Interface returns v's current value as an interface{}.
@@ -921,16 +976,15 @@ func valueInterface(v Value, safe bool) interface{} {
if v.flag == 0 {
panic(&ValueError{"reflect.Value.Interface", 0})
}
- if v.flag&flagMethod != 0 {
- panic("reflect.Value.Interface: cannot create interface value for method with bound receiver")
- }
-
if safe && v.flag&flagRO != 0 {
// Do not allow access to unexported values via Interface,
// because they might be pointers that should not be
// writable or methods or function that should not be callable.
panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
}
+ if v.flag&flagMethod != 0 {
+ v = makeMethodValue("Interface", v)
+ }
k := v.kind()
if k == Interface {
@@ -981,7 +1035,7 @@ func (v Value) IsNil() bool {
switch k {
case Chan, Func, Map, Ptr:
if v.flag&flagMethod != 0 {
- panic("reflect: IsNil of method Value")
+ return false
}
ptr := v.val
if v.flag&flagIndir != 0 {
@@ -1100,7 +1154,7 @@ func (v Value) MapKeys() []Value {
// Method returns a function value corresponding to v's i'th method.
// The arguments to a Call on the returned function should not include
// a receiver; the returned function will always use v as the receiver.
-// Method panics if i is out of range.
+// Method panics if i is out of range or if v is a nil interface value.
func (v Value) Method(i int) Value {
if v.typ == nil {
panic(&ValueError{"reflect.Value.Method", Invalid})
@@ -1108,7 +1162,10 @@ func (v Value) Method(i int) Value {
if v.flag&flagMethod != 0 || i < 0 || i >= v.typ.NumMethod() {
panic("reflect: Method index out of range")
}
- fl := v.flag & (flagRO | flagAddr | flagIndir)
+ if v.typ.Kind() == Interface && v.IsNil() {
+ panic("reflect: Method on nil interface value")
+ }
+ fl := v.flag & (flagRO | flagIndir)
fl |= flag(Func) << flagKindShift
fl |= flag(i)<<flagMethodShift | flagMethod
return Value{v.typ, v.val, fl}
@@ -1232,7 +1289,14 @@ func (v Value) Pointer() uintptr {
return uintptr(p)
case Func:
if v.flag&flagMethod != 0 {
- panic("reflect.Value.Pointer of method Value")
+ // As the doc comment says, the returned pointer is an
+ // underlying code pointer but not necessarily enough to
+ // identify a single function uniquely. All method expressions
+ // created via reflect have the same underlying code pointer,
+ // so their Pointers are equal. The function used here must
+ // match the one used in makeMethodValue.
+ f := methodValueCall
+ return **(**uintptr)(unsafe.Pointer(&f))
}
p := v.val
if v.flag&flagIndir != 0 {
@@ -1267,7 +1331,7 @@ func (v Value) Recv() (x Value, ok bool) {
func (v Value) recv(nb bool) (val Value, ok bool) {
tt := (*chanType)(unsafe.Pointer(v.typ))
if ChanDir(tt.dir)&RecvDir == 0 {
- panic("recv on send-only channel")
+ panic("reflect: recv on send-only channel")
}
word, selected, ok := chanrecv(v.typ, v.iword(), nb)
if selected {
@@ -1295,7 +1359,7 @@ func (v Value) Send(x Value) {
func (v Value) send(x Value, nb bool) (selected bool) {
tt := (*chanType)(unsafe.Pointer(v.typ))
if ChanDir(tt.dir)&SendDir == 0 {
- panic("send on recv-only channel")
+ panic("reflect: send on recv-only channel")
}
x.mustBeExported()
x = x.assignTo("reflect.Value.Send", tt.elem, nil)
@@ -1578,7 +1642,7 @@ func (v Value) Type() Type {
// Method on interface.
tt := (*interfaceType)(unsafe.Pointer(v.typ))
if i < 0 || i >= len(tt.methods) {
- panic("reflect: broken Value")
+ panic("reflect: internal error: invalid method index")
}
m := &tt.methods[i]
return m.typ
@@ -1586,7 +1650,7 @@ func (v Value) Type() Type {
// Method on concrete type.
ut := v.typ.uncommon()
if ut == nil || i < 0 || i >= len(ut.methods) {
- panic("reflect: broken Value")
+ panic("reflect: internal error: invalid method index")
}
m := &ut.methods[i]
return m.mtyp
@@ -2030,7 +2094,7 @@ func NewAt(typ Type, p unsafe.Pointer) Value {
// For a conversion to an interface type, target is a suggested scratch space to use.
func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value {
if v.flag&flagMethod != 0 {
- panic(context + ": cannot assign method value to type " + dst.String())
+ v = makeMethodValue(context, v)
}
switch {
@@ -2064,7 +2128,7 @@ func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value {
// 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")
+ v = makeMethodValue("Convert", v)
}
op := convertOp(t.common(), v.typ)
if op == nil {
diff --git a/src/pkg/regexp/regexp.go b/src/pkg/regexp/regexp.go
index 3aa16dec6..6f6908a74 100644
--- a/src/pkg/regexp/regexp.go
+++ b/src/pkg/regexp/regexp.go
@@ -8,6 +8,8 @@
// general syntax used by Perl, Python, and other languages.
// More precisely, it is the syntax accepted by RE2 and described at
// http://code.google.com/p/re2/wiki/Syntax, except for \C.
+// For an overview of the syntax, run
+// godoc regexp/syntax
//
// All characters are UTF-8-encoded code points.
//
@@ -27,11 +29,11 @@
// of bytes; return values are adjusted as appropriate.
//
// If 'Submatch' is present, the return value is a slice identifying the
-// successive submatches of the expression. Submatches are matches of
-// parenthesized subexpressions within the regular expression, numbered from
-// left to right in order of opening parenthesis. Submatch 0 is the match of
-// the entire expression, submatch 1 the match of the first parenthesized
-// subexpression, and so on.
+// successive submatches of the expression. Submatches are matches of
+// parenthesized subexpressions (also known as capturing groups) within the
+// regular expression, numbered from left to right in order of opening
+// parenthesis. Submatch 0 is the match of the entire expression, submatch 1
+// the match of the first parenthesized subexpression, and so on.
//
// If 'Index' is present, matches and submatches are identified by byte index
// pairs within the input string: result[2*n:2*n+1] identifies the indexes of
diff --git a/src/pkg/regexp/syntax/doc.go b/src/pkg/regexp/syntax/doc.go
index 843a6f6a4..bcb5d051b 100644
--- a/src/pkg/regexp/syntax/doc.go
+++ b/src/pkg/regexp/syntax/doc.go
@@ -47,9 +47,9 @@ Repetitions:
x{n}? exactly n x
Grouping:
- (re) numbered capturing group
- (?P<name>re) named & numbered capturing group
- (?:re) non-capturing group
+ (re) numbered capturing group (submatch)
+ (?P<name>re) named & numbered capturing group (submatch)
+ (?:re) non-capturing group (submatch)
(?flags) set flags within current group; non-capturing
(?flags:re) set flags during re; non-capturing
diff --git a/src/pkg/runtime/alg.c b/src/pkg/runtime/alg.c
index ad85b43ae..2dc821256 100644
--- a/src/pkg/runtime/alg.c
+++ b/src/pkg/runtime/alg.c
@@ -8,6 +8,8 @@
#define M0 (sizeof(uintptr)==4 ? 2860486313UL : 33054211828000289ULL)
#define M1 (sizeof(uintptr)==4 ? 3267000013UL : 23344194077549503ULL)
+static bool use_aeshash;
+
/*
* map and chan helpers for
* dealing with unknown types
@@ -17,6 +19,10 @@ runtime·memhash(uintptr *h, uintptr s, void *a)
{
byte *b;
uintptr hash;
+ if(use_aeshash) {
+ runtime·aeshash(h, s, a);
+ return;
+ }
b = a;
hash = M0 ^ *h;
@@ -467,6 +473,42 @@ runtime·algarray[] =
// Runtime helpers.
+// used in asm_{386,amd64}.s
+byte runtime·aeskeysched[HashRandomBytes];
+
+void
+runtime·hashinit(void)
+{
+ // Install aes hash algorithm if we have the instructions we need
+ if((runtime·cpuid_ecx & (1 << 25)) != 0 && // aes (aesenc)
+ (runtime·cpuid_ecx & (1 << 9)) != 0 && // sse3 (pshufb)
+ (runtime·cpuid_ecx & (1 << 19)) != 0) { // sse4.1 (pinsr{d,q})
+ byte *rnd;
+ int32 n;
+ use_aeshash = true;
+ runtime·algarray[AMEM].hash = runtime·aeshash;
+ runtime·algarray[AMEM8].hash = runtime·aeshash;
+ runtime·algarray[AMEM16].hash = runtime·aeshash;
+ runtime·algarray[AMEM32].hash = runtime·aeshash32;
+ runtime·algarray[AMEM64].hash = runtime·aeshash64;
+ runtime·algarray[AMEM128].hash = runtime·aeshash;
+ runtime·algarray[ASTRING].hash = runtime·aeshashstr;
+
+ // Initialize with random data so hash collisions will be hard to engineer.
+ runtime·get_random_data(&rnd, &n);
+ if(n > HashRandomBytes)
+ n = HashRandomBytes;
+ runtime·memmove(runtime·aeskeysched, rnd, n);
+ if(n < HashRandomBytes) {
+ // Not very random, but better than nothing.
+ int64 t = runtime·nanotime();
+ while (n < HashRandomBytes) {
+ runtime·aeskeysched[n++] = (int8)(t >> (8 * (n % 8)));
+ }
+ }
+ }
+}
+
// func equal(t *Type, x T, y T) (ret bool)
#pragma textflag 7
void
diff --git a/src/pkg/runtime/arch_386.h b/src/pkg/runtime/arch_386.h
index 4df795f71..62ed11b40 100644
--- a/src/pkg/runtime/arch_386.h
+++ b/src/pkg/runtime/arch_386.h
@@ -1,3 +1,7 @@
+// 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.
+
enum {
thechar = '8',
BigEndian = 0,
diff --git a/src/pkg/runtime/arch_amd64.h b/src/pkg/runtime/arch_amd64.h
index e83dc9105..a5e43ca8d 100644
--- a/src/pkg/runtime/arch_amd64.h
+++ b/src/pkg/runtime/arch_amd64.h
@@ -1,3 +1,7 @@
+// 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.
+
enum {
thechar = '6',
BigEndian = 0,
diff --git a/src/pkg/runtime/arch_arm.h b/src/pkg/runtime/arch_arm.h
index f6af58514..bb65d3faf 100644
--- a/src/pkg/runtime/arch_arm.h
+++ b/src/pkg/runtime/arch_arm.h
@@ -1,3 +1,7 @@
+// 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.
+
enum {
thechar = '5',
BigEndian = 0,
diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s
index 96f04e0ae..6bcacf4cc 100644
--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -6,8 +6,8 @@
TEXT _rt0_386(SB),7,$0
// copy arguments forward on an even stack
- MOVL 0(SP), AX // argc
- LEAL 4(SP), BX // argv
+ MOVL argc+0(FP), AX
+ MOVL argv+4(FP), BX
SUBL $128, SP // plenty of scratch
ANDL $~15, SP
MOVL AX, 120(SP) // save argc, argv away
@@ -20,15 +20,25 @@ TEXT _rt0_386(SB),7,$0
MOVL BX, g_stackguard(BP)
MOVL SP, g_stackbase(BP)
+ // find out information about the processor we're on
+ MOVL $0, AX
+ CPUID
+ CMPL AX, $0
+ JE nocpuinfo
+ MOVL $1, AX
+ CPUID
+ MOVL CX, runtime·cpuid_ecx(SB)
+ MOVL DX, runtime·cpuid_edx(SB)
+nocpuinfo:
+
// if there is an _cgo_init, call it to let it
// initialize and to set up GS. if not,
// we set up GS ourselves.
MOVL _cgo_init(SB), AX
TESTL AX, AX
JZ needtls
- PUSHL BP
+ MOVL BP, 0(SP)
CALL AX
- POPL BP
// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
CMPL runtime·iswindows(SB), $0
JEQ ok
@@ -72,6 +82,7 @@ ok:
MOVL AX, 4(SP)
CALL runtime·args(SB)
CALL runtime·osinit(SB)
+ CALL runtime·hashinit(SB)
CALL runtime·schedinit(SB)
// create a new goroutine to start program
@@ -706,7 +717,261 @@ TEXT runtime·stackguard(SB),7,$0
get_tls(CX)
MOVL g(CX), BX
MOVL g_stackguard(BX), DX
- MOVL DX, guard+4(FP)
+ MOVL DX, limit+4(FP)
RET
GLOBL runtime·tls0(SB), $32
+
+// hash function using AES hardware instructions
+TEXT runtime·aeshash(SB),7,$0
+ MOVL 4(SP), DX // ptr to hash value
+ MOVL 8(SP), CX // size
+ MOVL 12(SP), AX // ptr to data
+ JMP runtime·aeshashbody(SB)
+
+TEXT runtime·aeshashstr(SB),7,$0
+ MOVL 4(SP), DX // ptr to hash value
+ MOVL 12(SP), AX // ptr to string struct
+ MOVL 4(AX), CX // length of string
+ MOVL (AX), AX // string data
+ JMP runtime·aeshashbody(SB)
+
+// AX: data
+// CX: length
+// DX: ptr to seed input / hash output
+TEXT runtime·aeshashbody(SB),7,$0
+ MOVL (DX), X0 // seed to low 32 bits of xmm0
+ PINSRD $1, CX, X0 // size to next 32 bits of xmm0
+ MOVO runtime·aeskeysched+0(SB), X2
+ MOVO runtime·aeskeysched+16(SB), X3
+aesloop:
+ CMPL CX, $16
+ JB aesloopend
+ MOVOU (AX), X1
+ AESENC X2, X0
+ AESENC X1, X0
+ SUBL $16, CX
+ ADDL $16, AX
+ JMP aesloop
+aesloopend:
+ TESTL CX, CX
+ JE finalize // no partial block
+
+ TESTL $16, AX
+ JNE highpartial
+
+ // address ends in 0xxxx. 16 bytes loaded
+ // at this address won't cross a page boundary, so
+ // we can load it directly.
+ MOVOU (AX), X1
+ ADDL CX, CX
+ PAND masks(SB)(CX*8), X1
+ JMP partial
+highpartial:
+ // address ends in 1xxxx. Might be up against
+ // a page boundary, so load ending at last byte.
+ // Then shift bytes down using pshufb.
+ MOVOU -16(AX)(CX*1), X1
+ ADDL CX, CX
+ PSHUFB shifts(SB)(CX*8), X1
+partial:
+ // incorporate partial block into hash
+ AESENC X3, X0
+ AESENC X1, X0
+finalize:
+ // finalize hash
+ AESENC X2, X0
+ AESENC X3, X0
+ AESENC X2, X0
+ MOVL X0, (DX)
+ RET
+
+TEXT runtime·aeshash32(SB),7,$0
+ MOVL 4(SP), DX // ptr to hash value
+ MOVL 12(SP), AX // ptr to data
+ MOVL (DX), X0 // seed
+ PINSRD $1, (AX), X0 // data
+ AESENC runtime·aeskeysched+0(SB), X0
+ AESENC runtime·aeskeysched+16(SB), X0
+ AESENC runtime·aeskeysched+0(SB), X0
+ MOVL X0, (DX)
+ RET
+
+TEXT runtime·aeshash64(SB),7,$0
+ MOVL 4(SP), DX // ptr to hash value
+ MOVL 12(SP), AX // ptr to data
+ MOVQ (AX), X0 // data
+ PINSRD $2, (DX), X0 // seed
+ AESENC runtime·aeskeysched+0(SB), X0
+ AESENC runtime·aeskeysched+16(SB), X0
+ AESENC runtime·aeskeysched+0(SB), X0
+ MOVL X0, (DX)
+ RET
+
+
+// simple mask to get rid of data in the high part of the register.
+TEXT masks(SB),7,$0
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0x000000ff
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0x0000ffff
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0x00ffffff
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0x000000ff
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0x0000ffff
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0x00ffffff
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x000000ff
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x0000ffff
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x00ffffff
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x00000000
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x000000ff
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x0000ffff
+
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0x00ffffff
+
+ // these are arguments to pshufb. They move data down from
+ // the high bytes of the register to the low bytes of the register.
+ // index is how many bytes to move.
+TEXT shifts(SB),7,$0
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+ LONG $0x00000000
+
+ LONG $0xffffff0f
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0xffff0f0e
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0xff0f0e0d
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0x0f0e0d0c
+ LONG $0xffffffff
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0x0e0d0c0b
+ LONG $0xffffff0f
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0x0d0c0b0a
+ LONG $0xffff0f0e
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0x0c0b0a09
+ LONG $0xff0f0e0d
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0x0b0a0908
+ LONG $0x0f0e0d0c
+ LONG $0xffffffff
+ LONG $0xffffffff
+
+ LONG $0x0a090807
+ LONG $0x0e0d0c0b
+ LONG $0xffffff0f
+ LONG $0xffffffff
+
+ LONG $0x09080706
+ LONG $0x0d0c0b0a
+ LONG $0xffff0f0e
+ LONG $0xffffffff
+
+ LONG $0x08070605
+ LONG $0x0c0b0a09
+ LONG $0xff0f0e0d
+ LONG $0xffffffff
+
+ LONG $0x07060504
+ LONG $0x0b0a0908
+ LONG $0x0f0e0d0c
+ LONG $0xffffffff
+
+ LONG $0x06050403
+ LONG $0x0a090807
+ LONG $0x0e0d0c0b
+ LONG $0xffffff0f
+
+ LONG $0x05040302
+ LONG $0x09080706
+ LONG $0x0d0c0b0a
+ LONG $0xffff0f0e
+
+ LONG $0x04030201
+ LONG $0x08070605
+ LONG $0x0c0b0a09
+ LONG $0xff0f0e0d
+
diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s
index 987958498..f4cfa576e 100644
--- a/src/pkg/runtime/asm_amd64.s
+++ b/src/pkg/runtime/asm_amd64.s
@@ -6,8 +6,8 @@
TEXT _rt0_amd64(SB),7,$-8
// copy arguments forward on an even stack
- MOVQ 0(DI), AX // argc
- LEAQ 8(DI), BX // argv
+ MOVQ DI, AX // argc
+ MOVQ SI, BX // argv
SUBQ $(4*8+7), SP // 2args 2auto
ANDQ $~15, SP
MOVQ AX, 16(SP)
@@ -20,6 +20,17 @@ TEXT _rt0_amd64(SB),7,$-8
MOVQ BX, g_stackguard(DI)
MOVQ SP, g_stackbase(DI)
+ // find out information about the processor we're on
+ MOVQ $0, AX
+ CPUID
+ CMPQ AX, $0
+ JE nocpuinfo
+ MOVQ $1, AX
+ CPUID
+ MOVL CX, runtime·cpuid_ecx(SB)
+ MOVL DX, runtime·cpuid_edx(SB)
+nocpuinfo:
+
// if there is an _cgo_init, call it.
MOVQ _cgo_init(SB), AX
TESTQ AX, AX
@@ -65,6 +76,7 @@ ok:
MOVQ AX, 8(SP)
CALL runtime·args(SB)
CALL runtime·osinit(SB)
+ CALL runtime·hashinit(SB)
CALL runtime·schedinit(SB)
// create a new goroutine to start program
@@ -442,6 +454,12 @@ TEXT runtime·xchg(SB), 7, $0
XCHGL AX, 0(BX)
RET
+TEXT runtime·xchg64(SB), 7, $0
+ MOVQ 8(SP), BX
+ MOVQ 16(SP), AX
+ XCHGQ AX, 0(BX)
+ RET
+
TEXT runtime·procyield(SB),7,$0
MOVL 8(SP), AX
again:
@@ -719,7 +737,165 @@ TEXT runtime·stackguard(SB),7,$0
get_tls(CX)
MOVQ g(CX), BX
MOVQ g_stackguard(BX), DX
- MOVQ DX, guard+8(FP)
+ MOVQ DX, limit+8(FP)
RET
GLOBL runtime·tls0(SB), $64
+
+// hash function using AES hardware instructions
+TEXT runtime·aeshash(SB),7,$0
+ MOVQ 8(SP), DX // ptr to hash value
+ MOVQ 16(SP), CX // size
+ MOVQ 24(SP), AX // ptr to data
+ JMP runtime·aeshashbody(SB)
+
+TEXT runtime·aeshashstr(SB),7,$0
+ MOVQ 8(SP), DX // ptr to hash value
+ MOVQ 24(SP), AX // ptr to string struct
+ MOVQ 8(AX), CX // length of string
+ MOVQ (AX), AX // string data
+ JMP runtime·aeshashbody(SB)
+
+// AX: data
+// CX: length
+// DX: ptr to seed input / hash output
+TEXT runtime·aeshashbody(SB),7,$0
+ MOVQ (DX), X0 // seed to low 64 bits of xmm0
+ PINSRQ $1, CX, X0 // size to high 64 bits of xmm0
+ MOVO runtime·aeskeysched+0(SB), X2
+ MOVO runtime·aeskeysched+16(SB), X3
+aesloop:
+ CMPQ CX, $16
+ JB aesloopend
+ MOVOU (AX), X1
+ AESENC X2, X0
+ AESENC X1, X0
+ SUBQ $16, CX
+ ADDQ $16, AX
+ JMP aesloop
+aesloopend:
+ TESTQ CX, CX
+ JE finalize // no partial block
+
+ TESTQ $16, AX
+ JNE highpartial
+
+ // address ends in 0xxxx. 16 bytes loaded
+ // at this address won't cross a page boundary, so
+ // we can load it directly.
+ MOVOU (AX), X1
+ ADDQ CX, CX
+ PAND masks(SB)(CX*8), X1
+ JMP partial
+highpartial:
+ // address ends in 1xxxx. Might be up against
+ // a page boundary, so load ending at last byte.
+ // Then shift bytes down using pshufb.
+ MOVOU -16(AX)(CX*1), X1
+ ADDQ CX, CX
+ PSHUFB shifts(SB)(CX*8), X1
+partial:
+ // incorporate partial block into hash
+ AESENC X3, X0
+ AESENC X1, X0
+finalize:
+ // finalize hash
+ AESENC X2, X0
+ AESENC X3, X0
+ AESENC X2, X0
+ MOVQ X0, (DX)
+ RET
+
+TEXT runtime·aeshash32(SB),7,$0
+ MOVQ 8(SP), DX // ptr to hash value
+ MOVQ 24(SP), AX // ptr to data
+ MOVQ (DX), X0 // seed
+ PINSRD $2, (AX), X0 // data
+ AESENC runtime·aeskeysched+0(SB), X0
+ AESENC runtime·aeskeysched+16(SB), X0
+ AESENC runtime·aeskeysched+0(SB), X0
+ MOVQ X0, (DX)
+ RET
+
+TEXT runtime·aeshash64(SB),7,$0
+ MOVQ 8(SP), DX // ptr to hash value
+ MOVQ 24(SP), AX // ptr to data
+ MOVQ (DX), X0 // seed
+ PINSRQ $1, (AX), X0 // data
+ AESENC runtime·aeskeysched+0(SB), X0
+ AESENC runtime·aeskeysched+16(SB), X0
+ AESENC runtime·aeskeysched+0(SB), X0
+ MOVQ X0, (DX)
+ RET
+
+// simple mask to get rid of data in the high part of the register.
+TEXT masks(SB),7,$0
+ QUAD $0x0000000000000000
+ QUAD $0x0000000000000000
+ QUAD $0x00000000000000ff
+ QUAD $0x0000000000000000
+ QUAD $0x000000000000ffff
+ QUAD $0x0000000000000000
+ QUAD $0x0000000000ffffff
+ QUAD $0x0000000000000000
+ QUAD $0x00000000ffffffff
+ QUAD $0x0000000000000000
+ QUAD $0x000000ffffffffff
+ QUAD $0x0000000000000000
+ QUAD $0x0000ffffffffffff
+ QUAD $0x0000000000000000
+ QUAD $0x00ffffffffffffff
+ QUAD $0x0000000000000000
+ QUAD $0xffffffffffffffff
+ QUAD $0x0000000000000000
+ QUAD $0xffffffffffffffff
+ QUAD $0x00000000000000ff
+ QUAD $0xffffffffffffffff
+ QUAD $0x000000000000ffff
+ QUAD $0xffffffffffffffff
+ QUAD $0x0000000000ffffff
+ QUAD $0xffffffffffffffff
+ QUAD $0x00000000ffffffff
+ QUAD $0xffffffffffffffff
+ QUAD $0x000000ffffffffff
+ QUAD $0xffffffffffffffff
+ QUAD $0x0000ffffffffffff
+ QUAD $0xffffffffffffffff
+ QUAD $0x00ffffffffffffff
+
+ // these are arguments to pshufb. They move data down from
+ // the high bytes of the register to the low bytes of the register.
+ // index is how many bytes to move.
+TEXT shifts(SB),7,$0
+ QUAD $0x0000000000000000
+ QUAD $0x0000000000000000
+ QUAD $0xffffffffffffff0f
+ QUAD $0xffffffffffffffff
+ QUAD $0xffffffffffff0f0e
+ QUAD $0xffffffffffffffff
+ QUAD $0xffffffffff0f0e0d
+ QUAD $0xffffffffffffffff
+ QUAD $0xffffffff0f0e0d0c
+ QUAD $0xffffffffffffffff
+ QUAD $0xffffff0f0e0d0c0b
+ QUAD $0xffffffffffffffff
+ QUAD $0xffff0f0e0d0c0b0a
+ QUAD $0xffffffffffffffff
+ QUAD $0xff0f0e0d0c0b0a09
+ QUAD $0xffffffffffffffff
+ QUAD $0x0f0e0d0c0b0a0908
+ QUAD $0xffffffffffffffff
+ QUAD $0x0e0d0c0b0a090807
+ QUAD $0xffffffffffffff0f
+ QUAD $0x0d0c0b0a09080706
+ QUAD $0xffffffffffff0f0e
+ QUAD $0x0c0b0a0908070605
+ QUAD $0xffffffffff0f0e0d
+ QUAD $0x0b0a090807060504
+ QUAD $0xffffffff0f0e0d0c
+ QUAD $0x0a09080706050403
+ QUAD $0xffffff0f0e0d0c0b
+ QUAD $0x0908070605040302
+ QUAD $0xffff0f0e0d0c0b0a
+ QUAD $0x0807060504030201
+ QUAD $0xff0f0e0d0c0b0a09
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
index 45b53541b..6b2d6afda 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/pkg/runtime/asm_arm.s
@@ -47,6 +47,7 @@ TEXT _rt0_arm(SB),7,$-4
MOVW R1, 8(R13)
BL runtime·args(SB)
BL runtime·osinit(SB)
+ BL runtime·hashinit(SB)
BL runtime·schedinit(SB)
// create a new goroutine to start program
@@ -489,3 +490,17 @@ TEXT runtime·stackguard(SB),7,$0
MOVW R1, sp+0(FP)
MOVW R2, limit+4(FP)
RET
+
+// not implemented for ARM
+TEXT runtime·aeshash(SB),7,$-4
+ MOVW $0, R0
+ MOVW (R0), R1
+TEXT runtime·aeshash32(SB),7,$-4
+ MOVW $0, R0
+ MOVW (R0), R1
+TEXT runtime·aeshash64(SB),7,$-4
+ MOVW $0, R0
+ MOVW (R0), R1
+TEXT runtime·aeshashstr(SB),7,$-4
+ MOVW $0, R0
+ MOVW (R0), R1
diff --git a/src/pkg/runtime/atomic_386.c b/src/pkg/runtime/atomic_386.c
index 79b7cbf96..1046eb81e 100644
--- a/src/pkg/runtime/atomic_386.c
+++ b/src/pkg/runtime/atomic_386.c
@@ -30,3 +30,16 @@ runtime·xadd64(uint64 volatile* addr, int64 v)
}
return old+v;
}
+
+#pragma textflag 7
+uint64
+runtime·xchg64(uint64 volatile* addr, uint64 v)
+{
+ uint64 old;
+
+ old = *addr;
+ while(!runtime·cas64(addr, &old, v)) {
+ // nothing
+ }
+ return old;
+}
diff --git a/src/pkg/runtime/atomic_arm.c b/src/pkg/runtime/atomic_arm.c
index 0b54840cc..9193d599d 100644
--- a/src/pkg/runtime/atomic_arm.c
+++ b/src/pkg/runtime/atomic_arm.c
@@ -123,6 +123,19 @@ runtime·xadd64(uint64 volatile *addr, int64 delta)
#pragma textflag 7
uint64
+runtime·xchg64(uint64 volatile *addr, uint64 v)
+{
+ uint64 res;
+
+ runtime·lock(LOCK(addr));
+ res = *addr;
+ *addr = v;
+ runtime·unlock(LOCK(addr));
+ return res;
+}
+
+#pragma textflag 7
+uint64
runtime·atomicload64(uint64 volatile *addr)
{
uint64 res;
diff --git a/src/pkg/runtime/cgo/callbacks.c b/src/pkg/runtime/cgo/callbacks.c
index 51bd529ec..19f6115a6 100644
--- a/src/pkg/runtime/cgo/callbacks.c
+++ b/src/pkg/runtime/cgo/callbacks.c
@@ -12,8 +12,10 @@
// void crosscall2(void (*fn)(void *, int), void *, int);
//
// We need to export the symbol crosscall2 in order to support
-// callbacks from shared libraries.
-#pragma dynexport crosscall2 crosscall2
+// callbacks from shared libraries. This applies regardless of
+// linking mode.
+#pragma cgo_export_static crosscall2
+#pragma cgo_export_dynamic crosscall2
// Allocate memory. This allocates the requested number of bytes in
// memory controlled by the Go runtime. The allocated memory will be
diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
index 3bcb0b270..73c990c28 100644
--- a/src/pkg/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <sys/types.h>
+#include <machine/sysarch.h>
#include <pthread.h>
#include <string.h>
#include "libcgo.h"
@@ -22,10 +24,20 @@ void x_cgo_load_gm(void) __attribute__((naked));
void
__aeabi_read_tp(void)
{
- // read @ 0xffff1000
__asm__ __volatile__ (
+#ifdef ARM_TP_ADDRESS
+ // ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
+ // GCC inline asm doesn't provide a way to provide a constant
+ // to "ldr r0, =??" pseudo instruction, so we hardcode the value
+ // and check it with cpp.
+#if ARM_TP_ADDRESS != 0xffff1000
+#error Wrong ARM_TP_ADDRESS!
+#endif
"ldr r0, =0xffff1000\n\t"
"ldr r0, [r0]\n\t"
+#else
+ "mrc p15, 0, r0, c13, c0, 3\n\t"
+#endif
"mov pc, lr\n\t"
);
}
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_386.c b/src/pkg/runtime/cgo/gcc_openbsd_386.c
index 86c1365ad..80be31b9c 100644
--- a/src/pkg/runtime/cgo/gcc_openbsd_386.c
+++ b/src/pkg/runtime/cgo/gcc_openbsd_386.c
@@ -48,9 +48,9 @@ tcb_fixup(int mainthread)
bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE);
__set_tcb(newtcb + TLS_SIZE);
- // The main thread TCB is a static allocation - do not try to free it.
- if(!mainthread)
- free(oldtcb);
+ // NOTE(jsing, minux): we can't free oldtcb without causing double-free
+ // problem. so newtcb will be memory leaks. Get rid of this when OpenBSD
+ // has proper support for PT_TLS.
}
static void *
diff --git a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
index d3a5e36b0..e9cc8184b 100644
--- a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
+++ b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c
@@ -48,9 +48,9 @@ tcb_fixup(int mainthread)
bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE);
__set_tcb(newtcb + TLS_SIZE);
- // The main thread TCB is a static allocation - do not try to free it.
- if(!mainthread)
- free(oldtcb);
+ // NOTE(jsing, minux): we can't free oldtcb without causing double-free
+ // problem. so newtcb will be memory leaks. Get rid of this when OpenBSD
+ // has proper support for PT_TLS.
}
static void *
diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c
index 590bf9b67..0c9618749 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -95,7 +95,8 @@ static void unwindm(void);
// Call from Go to C.
-static FuncVal unlockOSThread = { runtime·unlockOSThread };
+static void endcgo(void);
+static FuncVal endcgoV = { endcgo };
void
runtime·cgocall(void (*fn)(void*), void *arg)
@@ -123,7 +124,7 @@ runtime·cgocall(void (*fn)(void*), void *arg)
* cgo callback. Add entry to defer stack in case of panic.
*/
runtime·lockOSThread();
- d.fn = &unlockOSThread;
+ d.fn = &endcgoV;
d.siz = 0;
d.link = g->defer;
d.argp = (void*)-1; // unused because unlockm never recovers
@@ -148,6 +149,16 @@ runtime·cgocall(void (*fn)(void*), void *arg)
runtime·asmcgocall(fn, arg);
runtime·exitsyscall();
+ if(g->defer != &d || d.fn != &endcgoV)
+ runtime·throw("runtime: bad defer entry in cgocallback");
+ g->defer = d.link;
+ endcgo();
+}
+
+static void
+endcgo(void)
+{
+ runtime·unlockOSThread();
m->ncgo--;
if(m->ncgo == 0) {
// We are going back to Go and are not in a recursive
@@ -156,11 +167,6 @@ runtime·cgocall(void (*fn)(void*), void *arg)
m->cgomal = nil;
}
- if(g->defer != &d || d.fn != &unlockOSThread)
- runtime·throw("runtime: bad defer entry in cgocallback");
- g->defer = d.link;
- runtime·unlockOSThread();
-
if(raceenabled)
runtime·raceacquire(&cgosync);
}
@@ -280,3 +286,9 @@ runtime·cgounimpl(void) // called from (incomplete) assembly
{
runtime·throw("runtime: cgo not implemented");
}
+
+// For cgo-using programs with external linking,
+// export "main" (defined in assembly) so that libc can handle basic
+// C runtime startup and call the Go program as if it were
+// the C main function.
+#pragma cgo_export_static main
diff --git a/src/pkg/runtime/crash_test.go b/src/pkg/runtime/crash_test.go
index 5f84cb5a2..80549a505 100644
--- a/src/pkg/runtime/crash_test.go
+++ b/src/pkg/runtime/crash_test.go
@@ -91,6 +91,14 @@ func TestLockedDeadlock2(t *testing.T) {
testDeadlock(t, lockedDeadlockSource2)
}
+func TestGoexitDeadlock(t *testing.T) {
+ got := executeTest(t, goexitDeadlockSource, nil)
+ want := ""
+ if got != want {
+ t.Fatalf("expected %q, but got %q", want, got)
+ }
+}
+
const crashSource = `
package main
@@ -175,3 +183,21 @@ func main() {
select {}
}
`
+
+const goexitDeadlockSource = `
+package main
+import (
+ "runtime"
+)
+
+func F() {
+ for i := 0; i < 10; i++ {
+ }
+}
+
+func main() {
+ go F()
+ go F()
+ runtime.Goexit()
+}
+`
diff --git a/src/pkg/runtime/defs2_linux.go b/src/pkg/runtime/defs2_linux.go
index 9b0702955..60ecc69bb 100644
--- a/src/pkg/runtime/defs2_linux.go
+++ b/src/pkg/runtime/defs2_linux.go
@@ -7,7 +7,7 @@
/*
* Input to cgo -cdefs
-GOARCH=386 cgo -cdefs defs2.go >386/defs.h
+GOARCH=386 go tool cgo -cdefs defs2_linux.go >defs_linux_386.h
The asm header tricks we have to use for Linux on amd64
(see defs.c and defs1.c) don't work here, so this is yet another
@@ -17,15 +17,19 @@ file. Sigh.
package runtime
/*
-#cgo CFLAGS: -I/home/rsc/pub/linux-2.6/arch/x86/include -I/home/rsc/pub/linux-2.6/include -D_LOOSE_KERNEL_NAMES -D__ARCH_SI_UID_T=__kernel_uid32_t
+#cgo CFLAGS: -I/tmp/linux/arch/x86/include -I/tmp/linux/include -D_LOOSE_KERNEL_NAMES -D__ARCH_SI_UID_T=__kernel_uid32_t
#define size_t __kernel_size_t
+#define pid_t int
#include <asm/signal.h>
#include <asm/mman.h>
#include <asm/sigcontext.h>
#include <asm/ucontext.h>
#include <asm/siginfo.h>
+#include <asm-generic/errno.h>
#include <asm-generic/fcntl.h>
+#include <asm-generic/poll.h>
+#include <linux/eventpoll.h>
// This is the sigaction structure from the Linux 2.1.68 kernel which
// is used with the rt_sigaction system call. For 386 this is not
@@ -35,12 +39,16 @@ struct kernel_sigaction {
__sighandler_t k_sa_handler;
unsigned long sa_flags;
void (*sa_restorer) (void);
- sigset_t sa_mask;
+ unsigned long long sa_mask;
};
*/
import "C"
const (
+ EINTR = C.EINTR
+ EAGAIN = C.EAGAIN
+ ENOMEM = C.ENOMEM
+
PROT_NONE = C.PROT_NONE
PROT_READ = C.PROT_READ
PROT_WRITE = C.PROT_WRITE
@@ -110,6 +118,17 @@ const (
O_RDONLY = C.O_RDONLY
O_CLOEXEC = C.O_CLOEXEC
+
+ EPOLLIN = C.POLLIN
+ EPOLLOUT = C.POLLOUT
+ EPOLLERR = C.POLLERR
+ EPOLLHUP = C.POLLHUP
+ EPOLLRDHUP = C.POLLRDHUP
+ EPOLLET = C.EPOLLET
+ EPOLL_CLOEXEC = C.EPOLL_CLOEXEC
+ EPOLL_CTL_ADD = C.EPOLL_CTL_ADD
+ EPOLL_CTL_DEL = C.EPOLL_CTL_DEL
+ EPOLL_CTL_MOD = C.EPOLL_CTL_MOD
)
type Fpreg C.struct__fpreg
@@ -124,3 +143,4 @@ type Sigaltstack C.struct_sigaltstack
type Sigcontext C.struct_sigcontext
type Ucontext C.struct_ucontext
type Itimerval C.struct_itimerval
+type EpollEvent C.struct_epoll_event
diff --git a/src/pkg/runtime/defs_darwin.go b/src/pkg/runtime/defs_darwin.go
index 7f22b0b8e..722013ba9 100644
--- a/src/pkg/runtime/defs_darwin.go
+++ b/src/pkg/runtime/defs_darwin.go
@@ -7,8 +7,8 @@
/*
Input to cgo.
-GOARCH=amd64 cgo -cdefs defs_darwin.go >defs_darwin_amd64.h
-GOARCH=386 cgo -cdefs defs_darwin.go >defs_darwin_386.h
+GOARCH=amd64 go tool cgo -cdefs defs_darwin.go >defs_darwin_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_darwin.go >defs_darwin_386.h
*/
package runtime
@@ -19,12 +19,17 @@ package runtime
#include <mach/message.h>
#include <sys/types.h>
#include <sys/time.h>
+#include <errno.h>
#include <signal.h>
+#include <sys/event.h>
#include <sys/mman.h>
*/
import "C"
const (
+ EINTR = C.EINTR
+ EFAULT = C.EFAULT
+
PROT_NONE = C.PROT_NONE
PROT_READ = C.PROT_READ
PROT_WRITE = C.PROT_WRITE
@@ -128,6 +133,14 @@ const (
ITIMER_REAL = C.ITIMER_REAL
ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
ITIMER_PROF = C.ITIMER_PROF
+
+ EV_ADD = C.EV_ADD
+ EV_DELETE = C.EV_DELETE
+ EV_CLEAR = C.EV_CLEAR
+ EV_RECEIPT = C.EV_RECEIPT
+ EV_ERROR = C.EV_ERROR
+ EVFILT_READ = C.EVFILT_READ
+ EVFILT_WRITE = C.EVFILT_WRITE
)
type MachBody C.mach_msg_body_t
@@ -144,6 +157,7 @@ type Sigval C.union_sigval
type Siginfo C.siginfo_t
type Timeval C.struct_timeval
type Itimerval C.struct_itimerval
+type Timespec C.struct_timespec
type FPControl C.struct_fp_control
type FPStatus C.struct_fp_status
@@ -161,3 +175,5 @@ type ExceptionState32 C.struct_i386_exception_state
type Mcontext32 C.struct_mcontext32
type Ucontext C.struct_ucontext
+
+type Kevent C.struct_kevent
diff --git a/src/pkg/runtime/defs_darwin_386.h b/src/pkg/runtime/defs_darwin_386.h
index 92732f460..7b210eebf 100644
--- a/src/pkg/runtime/defs_darwin_386.h
+++ b/src/pkg/runtime/defs_darwin_386.h
@@ -3,6 +3,9 @@
enum {
+ EINTR = 0x4,
+ EFAULT = 0xe,
+
PROT_NONE = 0x0,
PROT_READ = 0x1,
PROT_WRITE = 0x2,
@@ -106,6 +109,14 @@ enum {
ITIMER_REAL = 0x0,
ITIMER_VIRTUAL = 0x1,
ITIMER_PROF = 0x2,
+
+ EV_ADD = 0x1,
+ EV_DELETE = 0x2,
+ EV_CLEAR = 0x20,
+ EV_RECEIPT = 0x40,
+ EV_ERROR = 0x4000,
+ EVFILT_READ = -0x1,
+ EVFILT_WRITE = -0x2,
};
typedef struct MachBody MachBody;
@@ -117,6 +128,7 @@ typedef struct Sigaction Sigaction;
typedef struct Siginfo Siginfo;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
+typedef struct Timespec Timespec;
typedef struct FPControl FPControl;
typedef struct FPStatus FPStatus;
typedef struct RegMMST RegMMST;
@@ -130,6 +142,7 @@ typedef struct FloatState32 FloatState32;
typedef struct ExceptionState32 ExceptionState32;
typedef struct Mcontext32 Mcontext32;
typedef struct Ucontext Ucontext;
+typedef struct Kevent Kevent;
#pragma pack on
@@ -170,7 +183,7 @@ struct StackT {
typedef byte Sighandler[4];
struct Sigaction {
- Sighandler __sigaction_u;
+ byte __sigaction_u[4];
void *sa_tramp;
uint32 sa_mask;
int32 sa_flags;
@@ -185,7 +198,7 @@ struct Siginfo {
uint32 si_uid;
int32 si_status;
byte *si_addr;
- Sigval si_value;
+ byte si_value[4];
int32 si_band;
uint32 __pad[7];
};
@@ -197,6 +210,10 @@ struct Itimerval {
Timeval it_interval;
Timeval it_value;
};
+struct Timespec {
+ int32 tv_sec;
+ int32 tv_nsec;
+};
struct FPControl {
byte Pad_cgo_0[2];
@@ -362,5 +379,14 @@ struct Ucontext {
Mcontext32 *uc_mcontext;
};
+struct Kevent {
+ uint32 ident;
+ int16 filter;
+ uint16 flags;
+ uint32 fflags;
+ int32 data;
+ byte *udata;
+};
+
#pragma pack off
diff --git a/src/pkg/runtime/defs_darwin_amd64.h b/src/pkg/runtime/defs_darwin_amd64.h
index d4fbfef49..2d464a9e5 100644
--- a/src/pkg/runtime/defs_darwin_amd64.h
+++ b/src/pkg/runtime/defs_darwin_amd64.h
@@ -3,6 +3,9 @@
enum {
+ EINTR = 0x4,
+ EFAULT = 0xe,
+
PROT_NONE = 0x0,
PROT_READ = 0x1,
PROT_WRITE = 0x2,
@@ -106,6 +109,14 @@ enum {
ITIMER_REAL = 0x0,
ITIMER_VIRTUAL = 0x1,
ITIMER_PROF = 0x2,
+
+ EV_ADD = 0x1,
+ EV_DELETE = 0x2,
+ EV_CLEAR = 0x20,
+ EV_RECEIPT = 0x40,
+ EV_ERROR = 0x4000,
+ EVFILT_READ = -0x1,
+ EVFILT_WRITE = -0x2,
};
typedef struct MachBody MachBody;
@@ -117,6 +128,7 @@ typedef struct Sigaction Sigaction;
typedef struct Siginfo Siginfo;
typedef struct Timeval Timeval;
typedef struct Itimerval Itimerval;
+typedef struct Timespec Timespec;
typedef struct FPControl FPControl;
typedef struct FPStatus FPStatus;
typedef struct RegMMST RegMMST;
@@ -130,6 +142,7 @@ typedef struct FloatState32 FloatState32;
typedef struct ExceptionState32 ExceptionState32;
typedef struct Mcontext32 Mcontext32;
typedef struct Ucontext Ucontext;
+typedef struct Kevent Kevent;
#pragma pack on
@@ -171,7 +184,7 @@ struct StackT {
typedef byte Sighandler[8];
struct Sigaction {
- Sighandler __sigaction_u;
+ byte __sigaction_u[8];
void *sa_tramp;
uint32 sa_mask;
int32 sa_flags;
@@ -186,7 +199,7 @@ struct Siginfo {
uint32 si_uid;
int32 si_status;
byte *si_addr;
- Sigval si_value;
+ byte si_value[8];
int64 si_band;
uint64 __pad[7];
};
@@ -199,6 +212,10 @@ struct Itimerval {
Timeval it_interval;
Timeval it_value;
};
+struct Timespec {
+ int64 tv_sec;
+ int64 tv_nsec;
+};
struct FPControl {
byte Pad_cgo_0[2];
@@ -365,5 +382,14 @@ struct Ucontext {
Mcontext64 *uc_mcontext;
};
+struct Kevent {
+ uint64 ident;
+ int16 filter;
+ uint16 flags;
+ uint32 fflags;
+ int64 data;
+ byte *udata;
+};
+
#pragma pack off
diff --git a/src/pkg/runtime/defs_linux.go b/src/pkg/runtime/defs_linux.go
index c0275e111..2f4e03a01 100644
--- a/src/pkg/runtime/defs_linux.go
+++ b/src/pkg/runtime/defs_linux.go
@@ -7,7 +7,7 @@
/*
Input to cgo -cdefs
-GOARCH=amd64 cgo -cdefs defs.go defs1.go >amd64/defs.h
+GOARCH=amd64 go tool cgo -cdefs defs_linux.go defs1_linux.go >defs_linux_amd64.h
*/
package runtime
@@ -25,10 +25,17 @@ package runtime
#include <asm/signal.h>
#include <asm/siginfo.h>
#include <asm/mman.h>
+#include <asm-generic/errno.h>
+#include <asm-generic/poll.h>
+#include <linux/eventpoll.h>
*/
import "C"
const (
+ EINTR = C.EINTR
+ EAGAIN = C.EAGAIN
+ ENOMEM = C.ENOMEM
+
PROT_NONE = C.PROT_NONE
PROT_READ = C.PROT_READ
PROT_WRITE = C.PROT_WRITE
@@ -95,6 +102,17 @@ const (
ITIMER_REAL = C.ITIMER_REAL
ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
ITIMER_PROF = C.ITIMER_PROF
+
+ EPOLLIN = C.POLLIN
+ EPOLLOUT = C.POLLOUT
+ EPOLLERR = C.POLLERR
+ EPOLLHUP = C.POLLHUP
+ EPOLLRDHUP = C.POLLRDHUP
+ EPOLLET = C.EPOLLET
+ EPOLL_CLOEXEC = C.EPOLL_CLOEXEC
+ EPOLL_CTL_ADD = C.EPOLL_CTL_ADD
+ EPOLL_CTL_DEL = C.EPOLL_CTL_DEL
+ EPOLL_CTL_MOD = C.EPOLL_CTL_MOD
)
type Timespec C.struct_timespec
@@ -102,3 +120,4 @@ type Timeval C.struct_timeval
type Sigaction C.struct_sigaction
type Siginfo C.siginfo_t
type Itimerval C.struct_itimerval
+type EpollEvent C.struct_epoll_event
diff --git a/src/pkg/runtime/defs_linux_386.h b/src/pkg/runtime/defs_linux_386.h
index e257a6f85..27dae9e82 100644
--- a/src/pkg/runtime/defs_linux_386.h
+++ b/src/pkg/runtime/defs_linux_386.h
@@ -1,8 +1,12 @@
// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs2.go
+// cgo -cdefs defs2_linux.go
enum {
+ EINTR = 0x4,
+ EAGAIN = 0xb,
+ ENOMEM = 0xc,
+
PROT_NONE = 0x0,
PROT_READ = 0x1,
PROT_WRITE = 0x2,
@@ -72,6 +76,17 @@ enum {
O_RDONLY = 0x0,
O_CLOEXEC = 0x80000,
+
+ EPOLLIN = 0x1,
+ EPOLLOUT = 0x4,
+ EPOLLERR = 0x8,
+ EPOLLHUP = 0x10,
+ EPOLLRDHUP = 0x2000,
+ EPOLLET = -0x80000000,
+ EPOLL_CLOEXEC = 0x80000,
+ EPOLL_CTL_ADD = 0x1,
+ EPOLL_CTL_DEL = 0x2,
+ EPOLL_CTL_MOD = 0x3,
};
typedef struct Fpreg Fpreg;
@@ -86,6 +101,7 @@ typedef struct Sigaltstack Sigaltstack;
typedef struct Sigcontext Sigcontext;
typedef struct Ucontext Ucontext;
typedef struct Itimerval Itimerval;
+typedef struct EpollEvent EpollEvent;
#pragma pack on
@@ -186,6 +202,10 @@ struct Itimerval {
Timeval it_interval;
Timeval it_value;
};
+struct EpollEvent {
+ uint32 events;
+ uint64 data;
+};
#pragma pack off
diff --git a/src/pkg/runtime/defs_linux_amd64.h b/src/pkg/runtime/defs_linux_amd64.h
index bf5f79b0e..3e87df68a 100644
--- a/src/pkg/runtime/defs_linux_amd64.h
+++ b/src/pkg/runtime/defs_linux_amd64.h
@@ -1,8 +1,12 @@
// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs.go defs1.go
+// cgo -cdefs defs_linux.go defs1_linux.go
enum {
+ EINTR = 0x4,
+ EAGAIN = 0xb,
+ ENOMEM = 0xc,
+
PROT_NONE = 0x0,
PROT_READ = 0x1,
PROT_WRITE = 0x2,
@@ -69,6 +73,17 @@ enum {
ITIMER_REAL = 0x0,
ITIMER_VIRTUAL = 0x1,
ITIMER_PROF = 0x2,
+
+ EPOLLIN = 0x1,
+ EPOLLOUT = 0x4,
+ EPOLLERR = 0x8,
+ EPOLLHUP = 0x10,
+ EPOLLRDHUP = 0x2000,
+ EPOLLET = -0x80000000,
+ EPOLL_CLOEXEC = 0x80000,
+ EPOLL_CTL_ADD = 0x1,
+ EPOLL_CTL_DEL = 0x2,
+ EPOLL_CTL_MOD = 0x3,
};
typedef struct Timespec Timespec;
@@ -76,6 +91,7 @@ typedef struct Timeval Timeval;
typedef struct Sigaction Sigaction;
typedef struct Siginfo Siginfo;
typedef struct Itimerval Itimerval;
+typedef struct EpollEvent EpollEvent;
#pragma pack on
@@ -104,11 +120,15 @@ struct Itimerval {
Timeval it_interval;
Timeval it_value;
};
+struct EpollEvent {
+ uint32 events;
+ uint64 data;
+};
#pragma pack off
// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs.go defs1.go
+// cgo -cdefs defs_linux.go defs1_linux.go
enum {
diff --git a/src/pkg/runtime/defs_linux_arm.h b/src/pkg/runtime/defs_linux_arm.h
index f72ec3d1b..92160966e 100644
--- a/src/pkg/runtime/defs_linux_arm.h
+++ b/src/pkg/runtime/defs_linux_arm.h
@@ -1,9 +1,11 @@
-// godefs -f-I/usr/src/linux-headers-2.6.26-2-versatile/include defs_arm.c
-
-// MACHINE GENERATED - DO NOT EDIT.
+// TODO: Generate using cgo like defs_linux_{386,amd64}.h
// Constants
enum {
+ EINTR = 0x4,
+ ENOMEM = 0xc,
+ EAGAIN = 0xb,
+
PROT_NONE = 0,
PROT_READ = 0x1,
PROT_WRITE = 0x2,
@@ -64,6 +66,17 @@ enum {
ITIMER_VIRTUAL = 0x1,
O_RDONLY = 0,
O_CLOEXEC = 02000000,
+
+ EPOLLIN = 0x1,
+ EPOLLOUT = 0x4,
+ EPOLLERR = 0x8,
+ EPOLLHUP = 0x10,
+ EPOLLRDHUP = 0x2000,
+ EPOLLET = -0x80000000,
+ EPOLL_CLOEXEC = 0x80000,
+ EPOLL_CTL_ADD = 0x1,
+ EPOLL_CTL_DEL = 0x2,
+ EPOLL_CTL_MOD = 0x3,
};
// Types
@@ -145,4 +158,11 @@ struct Sigaction {
void *sa_restorer;
uint64 sa_mask;
};
+
+typedef struct EpollEvent EpollEvent;
+struct EpollEvent {
+ uint32 events;
+ uint32 _pad;
+ uint64 data;
+};
#pragma pack off
diff --git a/src/pkg/runtime/defs_netbsd.go b/src/pkg/runtime/defs_netbsd.go
index 53e061041..c543593fa 100644
--- a/src/pkg/runtime/defs_netbsd.go
+++ b/src/pkg/runtime/defs_netbsd.go
@@ -9,6 +9,7 @@ Input to cgo.
GOARCH=amd64 go tool cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go >defs_netbsd_amd64.h
GOARCH=386 go tool cgo -cdefs defs_netbsd.go defs_netbsd_386.go >defs_netbsd_386.h
+GOARCH=arm go tool cgo -cdefs defs_netbsd.go defs_netbsd_arm.go >defs_netbsd_arm.h
*/
// +godefs map __fpregset_t [644]byte
diff --git a/src/pkg/runtime/defs_netbsd_386.go b/src/pkg/runtime/defs_netbsd_386.go
index e9e36608e..c26f24607 100644
--- a/src/pkg/runtime/defs_netbsd_386.go
+++ b/src/pkg/runtime/defs_netbsd_386.go
@@ -7,7 +7,6 @@
/*
Input to cgo.
-GOARCH=amd64 go tool cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go >defs_netbsd_amd64.h
GOARCH=386 go tool cgo -cdefs defs_netbsd.go defs_netbsd_386.go >defs_netbsd_386.h
*/
diff --git a/src/pkg/runtime/defs_netbsd_amd64.go b/src/pkg/runtime/defs_netbsd_amd64.go
index 68f586b2f..f18a7b1fe 100644
--- a/src/pkg/runtime/defs_netbsd_amd64.go
+++ b/src/pkg/runtime/defs_netbsd_amd64.go
@@ -8,7 +8,6 @@
Input to cgo.
GOARCH=amd64 go tool cgo -cdefs defs_netbsd.go defs_netbsd_amd64.go >defs_netbsd_amd64.h
-GOARCH=386 go tool cgo -cdefs defs_netbsd.go defs_netbsd_386.go >defs_netbsd_386.h
*/
package runtime
diff --git a/src/pkg/runtime/defs_netbsd_arm.go b/src/pkg/runtime/defs_netbsd_arm.go
new file mode 100644
index 000000000..cb0dce66b
--- /dev/null
+++ b/src/pkg/runtime/defs_netbsd_arm.go
@@ -0,0 +1,39 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=arm go tool cgo -cdefs defs_netbsd.go defs_netbsd_arm.go >defs_netbsd_arm.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <machine/mcontext.h>
+*/
+import "C"
+
+const (
+ REG_R0 = C._REG_R0
+ REG_R1 = C._REG_R1
+ REG_R2 = C._REG_R2
+ REG_R3 = C._REG_R3
+ REG_R4 = C._REG_R4
+ REG_R5 = C._REG_R5
+ REG_R6 = C._REG_R6
+ REG_R7 = C._REG_R7
+ REG_R8 = C._REG_R8
+ REG_R9 = C._REG_R9
+ REG_R10 = C._REG_R10
+ REG_R11 = C._REG_R11
+ REG_R12 = C._REG_R12
+ REG_R13 = C._REG_R13
+ REG_R14 = C._REG_R14
+ REG_R15 = C._REG_R15
+ REG_CPSR = C._REG_CPSR
+)
diff --git a/src/pkg/runtime/defs_netbsd_arm.h b/src/pkg/runtime/defs_netbsd_arm.h
index f67475c76..26b55222e 100644
--- a/src/pkg/runtime/defs_netbsd_arm.h
+++ b/src/pkg/runtime/defs_netbsd_arm.h
@@ -1,5 +1,5 @@
// Created by cgo -cdefs - DO NOT EDIT
-// cgo -cdefs defs_netbsd.go
+// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go
enum {
@@ -138,3 +138,27 @@ struct UcontextT {
};
#pragma pack off
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_netbsd.go defs_netbsd_arm.go
+
+
+enum {
+ REG_R0 = 0x0,
+ REG_R1 = 0x1,
+ REG_R2 = 0x2,
+ REG_R3 = 0x3,
+ REG_R4 = 0x4,
+ REG_R5 = 0x5,
+ REG_R6 = 0x6,
+ REG_R7 = 0x7,
+ REG_R8 = 0x8,
+ REG_R9 = 0x9,
+ REG_R10 = 0xa,
+ REG_R11 = 0xb,
+ REG_R12 = 0xc,
+ REG_R13 = 0xd,
+ REG_R14 = 0xe,
+ REG_R15 = 0xf,
+ REG_CPSR = 0x10,
+};
+
diff --git a/src/pkg/runtime/env_plan9.c b/src/pkg/runtime/env_plan9.c
index 848d73303..0483d7eef 100644
--- a/src/pkg/runtime/env_plan9.c
+++ b/src/pkg/runtime/env_plan9.c
@@ -20,7 +20,7 @@ runtime·getenv(int8 *s)
runtime·memmove((void*)file, (void*)"/env/", 5);
runtime·memmove((void*)(file+5), (void*)s, len);
- fd = runtime·open(file, OREAD);
+ fd = runtime·open((int8*)file, OREAD, 0);
if(fd < 0)
return nil;
n = runtime·seek(fd, 0, 2);
diff --git a/src/pkg/runtime/export_futex_test.go b/src/pkg/runtime/export_futex_test.go
new file mode 100644
index 000000000..bcab60fbe
--- /dev/null
+++ b/src/pkg/runtime/export_futex_test.go
@@ -0,0 +1,13 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux freebsd
+
+package runtime
+
+func futexsleep(addr *uint32, val uint32, ns int64)
+func futexwakeup(addr *uint32, val uint32)
+
+var Futexsleep = futexsleep
+var Futexwakeup = futexwakeup
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index fbaffd1d5..20f234253 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -3,10 +3,54 @@
// license that can be found in the LICENSE file.
/*
- Package runtime contains operations that interact with Go's runtime system,
- such as functions to control goroutines. It also includes the low-level type information
- used by the reflect package; see reflect's documentation for the programmable
- interface to the run-time type system.
+Package runtime contains operations that interact with Go's runtime system,
+such as functions to control goroutines. It also includes the low-level type information
+used by the reflect package; see reflect's documentation for the programmable
+interface to the run-time type system.
+
+Environment Variables
+
+The following environment variables ($name or %name%, depending on the host
+operating system) control the run-time behavior of Go programs. The meanings
+and use may change from release to release.
+
+The GOGC variable sets the initial garbage collection target percentage.
+A collection is triggered when the ratio of freshly allocated data to live data
+remaining after the previous collection reaches this percentage. The default
+is GOGC=100. Setting GOGC=off disables the garbage collector entirely.
+The runtime/debug package's SetGCPercent function allows changing this
+percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
+
+The GOGCTRACE variable controls debug output from the garbage collector.
+Setting GOGCTRACE=1 causes the garbage collector to emit a single line to standard
+error at each collection, summarizing the amount of memory collected and the
+length of the pause. Setting GOGCTRACE=2 emits the same summary but also
+repeats each collection.
+
+The GOMAXPROCS variable limits the number of operating system threads that
+can execute user-level Go code simultaneously. There is no limit to the number of threads
+that can be blocked in system calls on behalf of Go code; those do not count against
+the GOMAXPROCS limit. This package's GOMAXPROCS function queries and changes
+the limit.
+
+The GOTRACEBACK variable controls the amount of output generated when a Go
+program fails due to an unrecovered panic or an unexpected runtime condition.
+By default, a failure prints a stack trace for every extant goroutine, eliding functions
+internal to the run-time system, and then exits with exit code 2.
+If GOTRACEBACK=0, the per-goroutine stack traces are omitted entirely.
+If GOTRACEBACK=1, the default behavior is used.
+If GOTRACEBACK=2, the per-goroutine stack traces include run-time functions.
+If GOTRACEBACK=crash, the per-goroutine stack traces include run-time functions,
+and if possible the program crashes in an operating-specific manner instead of
+exiting. For example, on Unix systems, the program raises SIGABRT to trigger a
+core dump.
+
+The GOARCH, GOOS, GOPATH, and GOROOT environment variables complete
+the set of Go environment variables. They influence the building of Go programs
+(see http://golang.org/cmd/go and http://golang.org/pkg/go/build).
+GOARCH, GOOS, and GOROOT are recorded at compile time and made available by
+constants or functions in this package, but they do not influence the execution
+of the run-time system.
*/
package runtime
diff --git a/src/pkg/runtime/futex_test.go b/src/pkg/runtime/futex_test.go
new file mode 100644
index 000000000..51f4d0f12
--- /dev/null
+++ b/src/pkg/runtime/futex_test.go
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux freebsd
+
+package runtime_test
+
+import (
+ . "runtime"
+ "testing"
+ "time"
+)
+
+func TestFutexsleep(t *testing.T) {
+ ch := make(chan bool, 1)
+ var dummy uint32
+ start := time.Now()
+ go func() {
+ Entersyscall()
+ Futexsleep(&dummy, 0, (1<<31+100)*1e9)
+ Exitsyscall()
+ ch <- true
+ }()
+ select {
+ case <-ch:
+ t.Errorf("futexsleep finished early after %s!", time.Since(start))
+ case <-time.After(time.Second):
+ Futexwakeup(&dummy, 1)
+ }
+}
diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go
index e1e1b1d01..3475339bf 100644
--- a/src/pkg/runtime/gc_test.go
+++ b/src/pkg/runtime/gc_test.go
@@ -7,6 +7,7 @@ package runtime_test
import (
"os"
"runtime"
+ "runtime/debug"
"testing"
)
@@ -82,3 +83,17 @@ func TestGcDeepNesting(t *testing.T) {
t.Fail()
}
}
+
+func TestGcHashmapIndirection(t *testing.T) {
+ defer debug.SetGCPercent(debug.SetGCPercent(1))
+ runtime.GC()
+ type T struct {
+ a [256]int
+ }
+ m := make(map[T]T)
+ for i := 0; i < 2000; i++ {
+ var a T
+ a.a[0] = i
+ m[a] = T{}
+ }
+}
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index 37111daa9..0f92becab 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -9,703 +9,831 @@
#include "type.h"
#include "race.h"
-/* Hmap flag values */
-#define IndirectVal (1<<0) /* storing pointers to values */
-#define IndirectKey (1<<1) /* storing pointers to keys */
-#define CanFreeTable (1<<2) /* okay to free subtables */
-#define CanFreeKey (1<<3) /* okay to free pointers to keys */
-
-struct Hmap { /* a hash table; initialize with hash_init() */
- uintgo count; /* elements in table - must be first */
- uint8 datasize; /* amount of data to store in entry */
- uint8 flag;
- uint8 valoff; /* offset of value in key+value data block */
- int32 changes; /* inc'ed whenever a subtable is created/grown */
- uintptr hash0; /* hash seed */
- struct hash_subtable *st; /* first-level table */
+// This file contains the implementation of Go's map type.
+//
+// The map is just a hash table. The data is arranged
+// into an array of buckets. Each bucket contains up to
+// 8 key/value pairs. The low-order bits of the hash are
+// used to select a bucket. Each bucket contains a few
+// high-order bits of each hash to distinguish the entries
+// within a single bucket.
+//
+// If more than 8 keys hash to a bucket, we chain on
+// extra buckets.
+//
+// When the hashtable grows, we allocate a new array
+// of buckets twice as big. Buckets are incrementally
+// copied from the old bucket array to the new bucket array.
+//
+// Map iterators walk through the array of buckets and
+// return the keys in walk order (bucket #, then overflow
+// chain order, then bucket index). To maintain iteration
+// semantics, we never move keys within their bucket (if
+// we did, keys might be returned 0 or 2 times). When
+// growing the table, iterators remain iterating through the
+// old table and must check the new table if the bucket
+// they are iterating through has been moved ("evacuated")
+// to the new table.
+
+// Maximum number of key/value pairs a bucket can hold.
+#define BUCKETSIZE 8
+
+// Maximum average load of a bucket that triggers growth.
+#define LOAD 6.5
+
+// Picking LOAD: too large and we have lots of overflow
+// buckets, too small and we waste a lot of space. I wrote
+// a simple program to check some stats for different loads:
+// (64-bit, 8 byte keys and values)
+// LOAD %overflow bytes/entry hitprobe missprobe
+// 4.00 2.13 20.77 3.00 4.00
+// 4.50 4.05 17.30 3.25 4.50
+// 5.00 6.85 14.77 3.50 5.00
+// 5.50 10.55 12.94 3.75 5.50
+// 6.00 15.27 11.67 4.00 6.00
+// 6.50 20.90 10.79 4.25 6.50
+// 7.00 27.14 10.15 4.50 7.00
+// 7.50 34.03 9.73 4.75 7.50
+// 8.00 41.10 9.40 5.00 8.00
+//
+// %overflow = percentage of buckets which have an overflow bucket
+// bytes/entry = overhead bytes used per key/value pair
+// hitprobe = # of entries to check when looking up a present key
+// missprobe = # of entries to check when looking up an absent key
+//
+// Keep in mind this data is for maximally loaded tables, i.e. just
+// before the table grows. Typical tables will be somewhat less loaded.
+
+// Maximum key or value size to keep inline (instead of mallocing per element).
+// Must fit in a uint8.
+// Fast versions cannot handle big values - the cutoff size for
+// fast versions in ../../cmd/gc/walk.c must be at most this value.
+#define MAXKEYSIZE 128
+#define MAXVALUESIZE 128
+
+typedef struct Bucket Bucket;
+struct Bucket
+{
+ uint8 tophash[BUCKETSIZE]; // top 8 bits of hash of each entry (0 = empty)
+ Bucket *overflow; // overflow bucket, if any
+ byte data[1]; // BUCKETSIZE keys followed by BUCKETSIZE values
};
+// NOTE: packing all the keys together and then all the values together makes the
+// code a bit more complicated than alternating key/value/key/value/... but it allows
+// us to eliminate padding which would be needed for, e.g., map[int64]int8.
-#define MaxData 255
+// Low-order bit of overflow field is used to mark a bucket as already evacuated
+// without destroying the overflow pointer.
+// Only buckets in oldbuckets will be marked as evacuated.
+// Evacuated bit will be set identically on the base bucket and any overflow buckets.
+#define evacuated(b) (((uintptr)(b)->overflow & 1) != 0)
+#define overflowptr(b) ((Bucket*)((uintptr)(b)->overflow & ~(uintptr)1))
-struct hash_entry {
- hash_hash_t hash; /* hash value of data */
- byte data[1]; /* user data has "datasize" bytes */
-};
+// Initialize bucket to the empty state. This only works if BUCKETSIZE==8!
+#define clearbucket(b) { *(uint64*)((b)->tophash) = 0; (b)->overflow = nil; }
-struct hash_subtable {
- uint8 power; /* bits used to index this table */
- uint8 used; /* bits in hash used before reaching this table */
- uint8 datasize; /* bytes of client data in an entry */
- uint8 max_probes; /* max number of probes when searching */
- int16 limit_bytes; /* max_probes * (datasize+sizeof (hash_hash_t)) */
- struct hash_entry *last; /* points to last element of entry[] */
- struct hash_entry entry[1]; /* 2**power+max_probes-1 elements of elemsize bytes */
+struct Hmap
+{
+ uintgo count; // # live cells == size of map. Must be first (used by len() builtin)
+ uint8 B; // log_2 of # of buckets (can hold up to LOAD * 2^B items)
+ uint8 flags;
+ uint8 keysize; // key size in bytes
+ uint8 valuesize; // value size in bytes
+ uint16 bucketsize; // bucket size in bytes
+
+ uintptr hash0; // hash seed
+ byte *buckets; // array of 2^B Buckets
+ byte *oldbuckets; // previous bucket array of half the size, non-nil only when growing
+ uintptr nevacuate; // progress counter for evacuation (buckets less than this have been evacuated)
};
-#define HASH_DATA_EQ(eq, t, h,x,y) ((eq)=0, (*t->key->alg->equal) (&(eq), t->key->size, (x), (y)), (eq))
-
-#define HASH_REHASH 0x2 /* an internal flag */
-/* the number of bits used is stored in the flags word too */
-#define HASH_USED(x) ((x) >> 2)
-#define HASH_MAKE_USED(x) ((x) << 2)
+// possible flags
+enum
+{
+ IndirectKey = 1, // storing pointers to keys
+ IndirectValue = 2, // storing pointers to values
+ Iterator = 4, // there may be an iterator using buckets
+ OldIterator = 8, // there may be an iterator using oldbuckets
+ CanFreeBucket = 16, // ok to free buckets
+ CanFreeKey = 32, // keys are indirect and ok to free keys
+};
-#define HASH_LOW 6
-#define HASH_ONE (((hash_hash_t)1) << HASH_LOW)
-#define HASH_MASK (HASH_ONE - 1)
-#define HASH_ADJUST(x) (((x) < HASH_ONE) << HASH_LOW)
+// Macros for dereferencing indirect keys
+#define IK(h, p) (((h)->flags & IndirectKey) != 0 ? *(byte**)(p) : (p))
+#define IV(h, p) (((h)->flags & IndirectValue) != 0 ? *(byte**)(p) : (p))
-#define HASH_BITS (sizeof (hash_hash_t) * 8)
+enum
+{
+ docheck = 0, // check invariants before and after every op. Slow!!!
+ debug = 0, // print every operation
+};
+static void
+check(MapType *t, Hmap *h)
+{
+ uintptr bucket, oldbucket;
+ Bucket *b;
+ uintptr i;
+ uintptr hash;
+ uintgo cnt;
+ uint8 top;
+ bool eq;
+ byte *k, *v;
-#define HASH_SUBHASH HASH_MASK
-#define HASH_NIL 0
-#define HASH_NIL_MEMSET 0
+ cnt = 0;
-#define HASH_OFFSET(base, byte_offset) \
- ((struct hash_entry *) (((byte *) (base)) + (byte_offset)))
+ // check buckets
+ for(bucket = 0; bucket < (uintptr)1 << h->B; bucket++) {
+ if(h->oldbuckets != nil) {
+ oldbucket = bucket & (((uintptr)1 << (h->B - 1)) - 1);
+ b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+ if(!evacuated(b))
+ continue; // b is still uninitialized
+ }
+ for(b = (Bucket*)(h->buckets + bucket * h->bucketsize); b != nil; b = b->overflow) {
+ for(i = 0, k = b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] == 0)
+ continue;
+ cnt++;
+ t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
+ if(!eq)
+ continue; // NaN!
+ hash = h->hash0;
+ t->key->alg->hash(&hash, t->key->size, IK(h, k));
+ top = hash >> (8*sizeof(uintptr) - 8);
+ if(top == 0)
+ top = 1;
+ if(top != b->tophash[i])
+ runtime·throw("bad hash");
+ }
+ }
+ }
-#define HASH_MAX_PROBES 15 /* max entries to probe before rehashing */
-#define HASH_MAX_POWER 12 /* max power of 2 to create sub-tables */
+ // check oldbuckets
+ if(h->oldbuckets != nil) {
+ for(oldbucket = 0; oldbucket < (uintptr)1 << (h->B - 1); oldbucket++) {
+ b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+ if(evacuated(b))
+ continue;
+ if(oldbucket < h->nevacuate)
+ runtime·throw("bucket became unevacuated");
+ for(; b != nil; b = overflowptr(b)) {
+ for(i = 0, k = b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] == 0)
+ continue;
+ cnt++;
+ t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
+ if(!eq)
+ continue; // NaN!
+ hash = h->hash0;
+ t->key->alg->hash(&hash, t->key->size, IK(h, k));
+ top = hash >> (8*sizeof(uintptr) - 8);
+ if(top == 0)
+ top = 1;
+ if(top != b->tophash[i])
+ runtime·throw("bad hash (old)");
+ }
+ }
+ }
+ }
-/* return a hash layer with 2**power empty entries */
-static struct hash_subtable *
-hash_subtable_new (Hmap *h, int32 power, int32 used)
-{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- int32 bytes = elemsize << power;
- struct hash_subtable *st;
- int32 limit_bytes = HASH_MAX_PROBES * elemsize;
- int32 max_probes = HASH_MAX_PROBES;
-
- if (bytes < limit_bytes) {
- limit_bytes = bytes;
- max_probes = 1 << power;
+ if(cnt != h->count) {
+ runtime·printf("%D %D\n", (uint64)cnt, (uint64)h->count);
+ runtime·throw("entries missing");
}
- bytes += limit_bytes - elemsize;
- st = runtime·mallocgc(offsetof (struct hash_subtable, entry[0]) + bytes, UseSpanType ? FlagNoPointers : 0, 1, 1);
- st->power = power;
- st->used = used;
- st->datasize = h->datasize;
- st->max_probes = max_probes;
- st->limit_bytes = limit_bytes;
- st->last = HASH_OFFSET (st->entry, bytes) - 1;
- memset (st->entry, HASH_NIL_MEMSET, bytes);
- return (st);
}
static void
-init_sizes (int64 hint, int32 *init_power)
+hash_init(MapType *t, Hmap *h, uint32 hint)
{
- int32 log = 0;
- int32 i;
-
- for (i = 32; i != 0; i >>= 1) {
- if ((hint >> (log + i)) != 0) {
- log += i;
- }
+ uint8 B;
+ byte *buckets;
+ uintptr i;
+ uintptr keysize, valuesize, bucketsize;
+ uint8 flags;
+ Bucket *b;
+
+ flags = CanFreeBucket;
+
+ // figure out how big we have to make everything
+ keysize = t->key->size;
+ if(keysize > MAXKEYSIZE) {
+ flags |= IndirectKey | CanFreeKey;
+ keysize = sizeof(byte*);
}
- log += 1 + (((hint << 3) >> log) >= 11); /* round up for utilization */
- if (log <= 14) {
- *init_power = log;
- } else {
- *init_power = 12;
+ valuesize = t->elem->size;
+ if(valuesize >= MAXVALUESIZE) {
+ flags |= IndirectValue;
+ valuesize = sizeof(byte*);
+ }
+ bucketsize = offsetof(Bucket, data[0]) + (keysize + valuesize) * BUCKETSIZE;
+
+ // invariants we depend on. We should probably check these at compile time
+ // somewhere, but for now we'll do it here.
+ if(t->key->align > BUCKETSIZE)
+ runtime·throw("key align too big");
+ if(t->elem->align > BUCKETSIZE)
+ runtime·throw("value align too big");
+ if(t->key->size % t->key->align != 0)
+ runtime·throw("key size not a multiple of key align");
+ if(t->elem->size % t->elem->align != 0)
+ runtime·throw("value size not a multiple of value align");
+ if(BUCKETSIZE < 8)
+ runtime·throw("bucketsize too small for proper alignment");
+ if(BUCKETSIZE != 8)
+ runtime·throw("must redo clearbucket");
+ if(sizeof(void*) == 4 && t->key->align > 4)
+ runtime·throw("need padding in bucket (key)");
+ if(sizeof(void*) == 4 && t->elem->align > 4)
+ runtime·throw("need padding in bucket (value)");
+
+ // find size parameter which will hold the requested # of elements
+ B = 0;
+ while(hint > BUCKETSIZE && hint > LOAD * ((uintptr)1 << B))
+ B++;
+
+ // allocate initial hash table
+ // If hint is large zeroing this memory could take a while.
+ buckets = runtime·mallocgc(bucketsize << B, 0, 1, 0);
+ for(i = 0; i < (uintptr)1 << B; i++) {
+ b = (Bucket*)(buckets + i * bucketsize);
+ clearbucket(b);
}
-}
-static void
-hash_init (Hmap *h, int32 datasize, int64 hint)
-{
- int32 init_power;
-
- if(datasize < sizeof (void *))
- datasize = sizeof (void *);
- datasize = ROUND(datasize, sizeof (void *));
- init_sizes (hint, &init_power);
- h->datasize = datasize;
- assert (h->datasize == datasize);
- assert (sizeof (void *) <= h->datasize);
+ // initialize Hmap
+ // Note: we save all these stores to the end so gciter doesn't see
+ // a partially initialized map.
h->count = 0;
- h->changes = 0;
- h->st = hash_subtable_new (h, init_power, 0);
+ h->B = B;
+ h->flags = flags;
+ h->keysize = keysize;
+ h->valuesize = valuesize;
+ h->bucketsize = bucketsize;
h->hash0 = runtime·fastrand1();
+ h->buckets = buckets;
+ h->oldbuckets = nil;
+ h->nevacuate = 0;
+ if(docheck)
+ check(t, h);
}
+// Moves entries in oldbuckets[i] to buckets[i] and buckets[i+2^k].
+// We leave the original bucket intact, except for the evacuated marks, so that
+// iterators can still iterate through the old buckets.
static void
-hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
+evacuate(MapType *t, Hmap *h, uintptr oldbucket)
{
- int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
- struct hash_entry *src_e = HASH_OFFSET (dst_e, n * elemsize);
- struct hash_entry *last_e = st->last;
- int32 shift = HASH_BITS - (st->power + st->used);
- int32 index_mask = (((hash_hash_t)1) << st->power) - 1;
- int32 dst_i = (((byte *) dst_e) - ((byte *) st->entry)) / elemsize;
- int32 src_i = dst_i + n;
- hash_hash_t hash;
- int32 skip;
- int32 bytes;
-
- while (dst_e != src_e) {
- if (src_e <= last_e) {
- struct hash_entry *cp_e = src_e;
- int32 save_dst_i = dst_i;
- while (cp_e <= last_e && (hash = cp_e->hash) != HASH_NIL &&
- ((hash >> shift) & index_mask) <= dst_i) {
- cp_e = HASH_OFFSET (cp_e, elemsize);
- dst_i++;
+ Bucket *b;
+ Bucket *nextb;
+ Bucket *x, *y;
+ Bucket *newx, *newy;
+ uintptr xi, yi;
+ uintptr newbit;
+ uintptr hash;
+ uintptr i;
+ byte *k, *v;
+ byte *xk, *yk, *xv, *yv;
+ byte *ob;
+
+ b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+ newbit = (uintptr)1 << (h->B - 1);
+
+ if(!evacuated(b)) {
+ // TODO: reuse overflow buckets instead of using new ones, if there
+ // is no iterator using the old buckets. (If CanFreeBuckets and !OldIterator.)
+
+ x = (Bucket*)(h->buckets + oldbucket * h->bucketsize);
+ y = (Bucket*)(h->buckets + (oldbucket + newbit) * h->bucketsize);
+ clearbucket(x);
+ clearbucket(y);
+ xi = 0;
+ yi = 0;
+ xk = x->data;
+ yk = y->data;
+ xv = xk + h->keysize * BUCKETSIZE;
+ yv = yk + h->keysize * BUCKETSIZE;
+ do {
+ for(i = 0, k = b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] == 0)
+ continue;
+ hash = h->hash0;
+ t->key->alg->hash(&hash, t->key->size, IK(h, k));
+ // NOTE: if key != key, then this hash could be (and probably will be)
+ // entirely different from the old hash. We effectively only update
+ // the B'th bit of the hash in this case.
+ if((hash & newbit) == 0) {
+ if(xi == BUCKETSIZE) {
+ newx = runtime·mallocgc(h->bucketsize, 0, 1, 0);
+ clearbucket(newx);
+ x->overflow = newx;
+ x = newx;
+ xi = 0;
+ xk = x->data;
+ xv = xk + h->keysize * BUCKETSIZE;
+ }
+ x->tophash[xi] = b->tophash[i];
+ if((h->flags & IndirectKey) != 0) {
+ *(byte**)xk = *(byte**)k; // copy pointer
+ } else {
+ t->key->alg->copy(t->key->size, xk, k); // copy value
+ }
+ if((h->flags & IndirectValue) != 0) {
+ *(byte**)xv = *(byte**)v;
+ } else {
+ t->elem->alg->copy(t->elem->size, xv, v);
+ }
+ xi++;
+ xk += h->keysize;
+ xv += h->valuesize;
+ } else {
+ if(yi == BUCKETSIZE) {
+ newy = runtime·mallocgc(h->bucketsize, 0, 1, 0);
+ clearbucket(newy);
+ y->overflow = newy;
+ y = newy;
+ yi = 0;
+ yk = y->data;
+ yv = yk + h->keysize * BUCKETSIZE;
+ }
+ y->tophash[yi] = b->tophash[i];
+ if((h->flags & IndirectKey) != 0) {
+ *(byte**)yk = *(byte**)k;
+ } else {
+ t->key->alg->copy(t->key->size, yk, k);
+ }
+ if((h->flags & IndirectValue) != 0) {
+ *(byte**)yv = *(byte**)v;
+ } else {
+ t->elem->alg->copy(t->elem->size, yv, v);
+ }
+ yi++;
+ yk += h->keysize;
+ yv += h->valuesize;
+ }
}
- bytes = ((byte *) cp_e) - (byte *) src_e;
- memmove (dst_e, src_e, bytes);
- dst_e = HASH_OFFSET (dst_e, bytes);
- src_e = cp_e;
- src_i += dst_i - save_dst_i;
- if (src_e <= last_e && (hash = src_e->hash) != HASH_NIL) {
- skip = ((hash >> shift) & index_mask) - dst_i;
+
+ // mark as evacuated so we don't do it again.
+ // this also tells any iterators that this data isn't golden anymore.
+ nextb = b->overflow;
+ b->overflow = (Bucket*)((uintptr)nextb + 1);
+
+ b = nextb;
+ } while(b != nil);
+
+ // Free old overflow buckets as much as we can.
+ if((h->flags & OldIterator) == 0) {
+ b = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+ if((h->flags & CanFreeBucket) != 0) {
+ while((nextb = overflowptr(b)) != nil) {
+ b->overflow = nextb->overflow;
+ runtime·free(nextb);
+ }
} else {
- skip = src_i - dst_i;
+ // can't explicitly free overflow buckets, but at least
+ // we can unlink them.
+ b->overflow = (Bucket*)1;
}
- } else {
- skip = src_i - dst_i;
}
- bytes = skip * elemsize;
- memset (dst_e, HASH_NIL_MEMSET, bytes);
- dst_e = HASH_OFFSET (dst_e, bytes);
- dst_i += skip;
}
-}
-static int32
-hash_insert_internal (MapType*, struct hash_subtable **pst, int32 flags, hash_hash_t hash,
- Hmap *h, void *data, void **pres);
+ // advance evacuation mark
+ if(oldbucket == h->nevacuate) {
+ h->nevacuate = oldbucket + 1;
+ if(oldbucket + 1 == newbit) { // newbit == # of oldbuckets
+ // free main bucket array
+ if((h->flags & (OldIterator | CanFreeBucket)) == CanFreeBucket) {
+ ob = h->oldbuckets;
+ h->oldbuckets = nil;
+ runtime·free(ob);
+ } else {
+ h->oldbuckets = nil;
+ }
+ }
+ }
+ if(docheck)
+ check(t, h);
+}
static void
-hash_conv (MapType *t, Hmap *h,
- struct hash_subtable *st, int32 flags,
- hash_hash_t hash,
- struct hash_entry *e)
+grow_work(MapType *t, Hmap *h, uintptr bucket)
{
- int32 new_flags = (flags + HASH_MAKE_USED (st->power)) | HASH_REHASH;
- int32 shift = HASH_BITS - HASH_USED (new_flags);
- hash_hash_t prefix_mask = (-(hash_hash_t)1) << shift;
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- void *dummy_result;
- struct hash_entry *de;
- int32 index_mask = (1 << st->power) - 1;
- hash_hash_t e_hash;
- struct hash_entry *pe = HASH_OFFSET (e, -elemsize);
-
- while (e != st->entry && (e_hash = pe->hash) != HASH_NIL && (e_hash & HASH_MASK) != HASH_SUBHASH) {
- e = pe;
- pe = HASH_OFFSET (pe, -elemsize);
- }
+ uintptr noldbuckets;
- de = e;
- while (e <= st->last &&
- (e_hash = e->hash) != HASH_NIL &&
- (e_hash & HASH_MASK) != HASH_SUBHASH) {
- struct hash_entry *target_e = HASH_OFFSET (st->entry, ((e_hash >> shift) & index_mask) * elemsize);
- struct hash_entry *ne = HASH_OFFSET (e, elemsize);
- hash_hash_t current = e_hash & prefix_mask;
- if (de < target_e) {
- memset (de, HASH_NIL_MEMSET, ((byte *) target_e) - (byte *) de);
- de = target_e;
- }
- if ((hash & prefix_mask) == current ||
- (ne <= st->last && (e_hash = ne->hash) != HASH_NIL &&
- (e_hash & prefix_mask) == current)) {
- struct hash_subtable *new_st = hash_subtable_new (h, 1, HASH_USED (new_flags));
- int32 rc = hash_insert_internal (t, &new_st, new_flags, e->hash, h, e->data, &dummy_result);
- assert (rc == 0);
- memcpy(dummy_result, e->data, h->datasize);
- e = ne;
- while (e <= st->last && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) {
- assert ((e_hash & HASH_MASK) != HASH_SUBHASH);
- rc = hash_insert_internal (t, &new_st, new_flags, e_hash, h, e->data, &dummy_result);
- assert (rc == 0);
- memcpy(dummy_result, e->data, h->datasize);
- e = HASH_OFFSET (e, elemsize);
- }
- memset (de->data, HASH_NIL_MEMSET, h->datasize);
- *(struct hash_subtable **)de->data = new_st;
- de->hash = current | HASH_SUBHASH;
- } else {
- if (e != de) {
- memcpy (de, e, elemsize);
- }
- e = HASH_OFFSET (e, elemsize);
- }
- de = HASH_OFFSET (de, elemsize);
- }
- if (e != de) {
- hash_remove_n (st, de, (((byte *) e) - (byte *) de) / elemsize);
- }
+ noldbuckets = (uintptr)1 << (h->B - 1);
+
+ // make sure we evacuate the oldbucket corresponding
+ // to the bucket we're about to use
+ evacuate(t, h, bucket & (noldbuckets - 1));
+
+ // evacuate one more oldbucket to make progress on growing
+ if(h->oldbuckets != nil)
+ evacuate(t, h, h->nevacuate);
}
static void
-hash_grow (MapType *t, Hmap *h, struct hash_subtable **pst, int32 flags)
+hash_grow(MapType *t, Hmap *h)
{
- struct hash_subtable *old_st = *pst;
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- *pst = hash_subtable_new (h, old_st->power + 1, HASH_USED (flags));
- struct hash_entry *last_e = old_st->last;
- struct hash_entry *e;
- void *dummy_result;
- int32 used = 0;
-
- flags |= HASH_REHASH;
- for (e = old_st->entry; e <= last_e; e = HASH_OFFSET (e, elemsize)) {
- hash_hash_t hash = e->hash;
- if (hash != HASH_NIL) {
- int32 rc = hash_insert_internal (t, pst, flags, e->hash, h, e->data, &dummy_result);
- assert (rc == 0);
- memcpy(dummy_result, e->data, h->datasize);
- used++;
- }
+ byte *old_buckets;
+ byte *new_buckets;
+ uint8 flags;
+
+ // allocate a bigger hash table
+ if(h->oldbuckets != nil)
+ runtime·throw("evacuation not done in time");
+ old_buckets = h->buckets;
+ // NOTE: this could be a big malloc, but since we don't need zeroing it is probably fast.
+ new_buckets = runtime·mallocgc(h->bucketsize << (h->B + 1), 0, 1, 0);
+ flags = (h->flags & ~(Iterator | OldIterator));
+ if((h->flags & Iterator) != 0) {
+ flags |= OldIterator;
+ // We can't free indirect keys any more, as
+ // they are potentially aliased across buckets.
+ flags &= ~CanFreeKey;
}
- if (h->flag & CanFreeTable)
- free (old_st);
+
+ // commit the grow (atomic wrt gc)
+ h->B++;
+ h->flags = flags;
+ h->oldbuckets = old_buckets;
+ h->buckets = new_buckets;
+ h->nevacuate = 0;
+
+ // the actual copying of the hash table data is done incrementally
+ // by grow_work() and evacuate().
+ if(docheck)
+ check(t, h);
}
-static int32
-hash_lookup (MapType *t, Hmap *h, void *data, void **pres)
+// returns ptr to value associated with key *keyp, or nil if none.
+// if it returns non-nil, updates *keyp to point to the currently stored key.
+static byte*
+hash_lookup(MapType *t, Hmap *h, byte **keyp)
{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- hash_hash_t hash;
- struct hash_subtable *st = h->st;
- int32 used = 0;
- hash_hash_t e_hash;
- struct hash_entry *e;
- struct hash_entry *end_e;
void *key;
+ uintptr hash;
+ uintptr bucket;
+ Bucket *b;
+ uint8 top;
+ uintptr i;
bool eq;
+ byte *k, *k2, *v;
+ key = *keyp;
+ if(docheck)
+ check(t, h);
hash = h->hash0;
- (*t->key->alg->hash) (&hash, t->key->size, data);
- hash &= ~HASH_MASK;
- hash += HASH_ADJUST (hash);
- for (;;) {
- int32 shift = HASH_BITS - (st->power + used);
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (hash >> shift) & index_mask; /* i is the natural position of hash */
-
- e = HASH_OFFSET (st->entry, i * elemsize); /* e points to element i */
- e_hash = e->hash;
- if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable */
- break;
- }
- used += st->power;
- st = *(struct hash_subtable **)e->data;
- }
- end_e = HASH_OFFSET (e, st->limit_bytes);
- while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
- e = HASH_OFFSET (e, elemsize);
- }
- while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
- key = e->data;
- if (h->flag & IndirectKey)
- key = *(void**)e->data;
- if (HASH_DATA_EQ (eq, t, h, data, key)) { /* a match */
- *pres = e->data;
- return (1);
+ t->key->alg->hash(&hash, t->key->size, key);
+ bucket = hash & (((uintptr)1 << h->B) - 1);
+ if(h->oldbuckets != nil)
+ grow_work(t, h, bucket);
+ b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+ top = hash >> (sizeof(uintptr)*8 - 8);
+ if(top == 0)
+ top = 1;
+ do {
+ for(i = 0, k = b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] == top) {
+ k2 = IK(h, k);
+ t->key->alg->equal(&eq, t->key->size, key, k2);
+ if(eq) {
+ *keyp = k2;
+ return IV(h, v);
+ }
+ }
}
- e = HASH_OFFSET (e, elemsize);
- }
- USED(e_hash);
- *pres = 0;
- return (0);
+ b = b->overflow;
+ } while(b != nil);
+ return nil;
}
-static int32
-hash_remove (MapType *t, Hmap *h, void *data)
+// When an item is not found, fast versions return a pointer to this zeroed memory.
+static uint8 empty_value[MAXVALUESIZE];
+
+// Specialized versions of mapaccess1 for specific types.
+// See ./hashmap_fast and ../../cmd/gc/walk.c.
+#define HASH_LOOKUP1 runtime·mapaccess1_fast32
+#define HASH_LOOKUP2 runtime·mapaccess2_fast32
+#define KEYTYPE uint32
+#define HASHFUNC runtime·algarray[AMEM32].hash
+#define EQFUNC(x,y) ((x) == (y))
+#define QUICKEQ(x) true
+#include "hashmap_fast.c"
+
+#undef HASH_LOOKUP1
+#undef HASH_LOOKUP2
+#undef KEYTYPE
+#undef HASHFUNC
+#undef EQFUNC
+#undef QUICKEQ
+
+#define HASH_LOOKUP1 runtime·mapaccess1_fast64
+#define HASH_LOOKUP2 runtime·mapaccess2_fast64
+#define KEYTYPE uint64
+#define HASHFUNC runtime·algarray[AMEM64].hash
+#define EQFUNC(x,y) ((x) == (y))
+#define QUICKEQ(x) true
+#include "hashmap_fast.c"
+
+#undef HASH_LOOKUP1
+#undef HASH_LOOKUP2
+#undef KEYTYPE
+#undef HASHFUNC
+#undef EQFUNC
+#undef QUICKEQ
+
+#define HASH_LOOKUP1 runtime·mapaccess1_faststr
+#define HASH_LOOKUP2 runtime·mapaccess2_faststr
+#define KEYTYPE String
+#define HASHFUNC runtime·algarray[ASTRING].hash
+#define EQFUNC(x,y) ((x).len == (y).len && ((x).str == (y).str || runtime·mcmp((x).str, (y).str, (x).len) == 0))
+#define QUICKEQ(x) ((x).len < 32)
+#include "hashmap_fast.c"
+
+static void
+hash_insert(MapType *t, Hmap *h, void *key, void *value)
{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- hash_hash_t hash;
- struct hash_subtable *st = h->st;
- int32 used = 0;
- hash_hash_t e_hash;
- struct hash_entry *e;
- struct hash_entry *end_e;
+ uintptr hash;
+ uintptr bucket;
+ uintptr i;
bool eq;
- void *key;
-
+ Bucket *b;
+ Bucket *newb;
+ uint8 *inserti;
+ byte *insertk, *insertv;
+ uint8 top;
+ byte *k, *v;
+ byte *kmem, *vmem;
+
+ if(docheck)
+ check(t, h);
hash = h->hash0;
- (*t->key->alg->hash) (&hash, t->key->size, data);
- hash &= ~HASH_MASK;
- hash += HASH_ADJUST (hash);
- for (;;) {
- int32 shift = HASH_BITS - (st->power + used);
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (hash >> shift) & index_mask; /* i is the natural position of hash */
-
- e = HASH_OFFSET (st->entry, i * elemsize); /* e points to element i */
- e_hash = e->hash;
- if ((e_hash & HASH_MASK) != HASH_SUBHASH) { /* a subtable */
- break;
+ t->key->alg->hash(&hash, t->key->size, key);
+ again:
+ bucket = hash & (((uintptr)1 << h->B) - 1);
+ if(h->oldbuckets != nil)
+ grow_work(t, h, bucket);
+ b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+ top = hash >> (sizeof(uintptr)*8 - 8);
+ if(top == 0)
+ top = 1;
+ inserti = 0;
+ insertk = nil;
+ insertv = nil;
+ while(true) {
+ for(i = 0, k = b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] != top) {
+ if(b->tophash[i] == 0 && inserti == nil) {
+ inserti = &b->tophash[i];
+ insertk = k;
+ insertv = v;
+ }
+ continue;
+ }
+ t->key->alg->equal(&eq, t->key->size, key, IK(h, k));
+ if(!eq)
+ continue;
+ // already have a mapping for key. Update it.
+ t->key->alg->copy(t->key->size, IK(h, k), key); // Need to update key for keys which are distinct but equal (e.g. +0.0 and -0.0)
+ t->elem->alg->copy(t->elem->size, IV(h, v), value);
+ if(docheck)
+ check(t, h);
+ return;
}
- used += st->power;
- st = *(struct hash_subtable **)e->data;
- }
- end_e = HASH_OFFSET (e, st->limit_bytes);
- while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
- e = HASH_OFFSET (e, elemsize);
+ if(b->overflow == nil)
+ break;
+ b = b->overflow;
}
- while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
- key = e->data;
- if (h->flag & IndirectKey)
- key = *(void**)e->data;
- if (HASH_DATA_EQ (eq, t, h, data, key)) { /* a match */
- // Free key if indirect, but only if reflect can't be
- // holding a pointer to it. Deletions are rare,
- // indirect (large) keys are rare, reflect on maps
- // is rare. So in the rare, rare, rare case of deleting
- // an indirect key from a map that has been reflected on,
- // we leave the key for garbage collection instead of
- // freeing it here.
- if (h->flag & CanFreeKey)
- free (key);
- if (h->flag & IndirectVal)
- free (*(void**)((byte*)e->data + h->valoff));
- hash_remove_n (st, e, 1);
- h->count--;
- return (1);
- }
- e = HASH_OFFSET (e, elemsize);
+
+ // did not find mapping for key. Allocate new cell & add entry.
+ if(h->count >= LOAD * ((uintptr)1 << h->B) && h->count >= BUCKETSIZE) {
+ hash_grow(t, h);
+ goto again; // Growing the table invalidates everything, so try again
}
- USED(e_hash);
- return (0);
-}
-static int32
-hash_insert_internal (MapType *t, struct hash_subtable **pst, int32 flags, hash_hash_t hash,
- Hmap *h, void *data, void **pres)
-{
- int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- bool eq;
+ if(inserti == nil) {
+ // all current buckets are full, allocate a new one.
+ newb = runtime·mallocgc(h->bucketsize, 0, 1, 0);
+ clearbucket(newb);
+ b->overflow = newb;
+ inserti = newb->tophash;
+ insertk = newb->data;
+ insertv = insertk + h->keysize * BUCKETSIZE;
+ }
- if ((flags & HASH_REHASH) == 0) {
- hash += HASH_ADJUST (hash);
- hash &= ~HASH_MASK;
+ // store new key/value at insert position
+ if((h->flags & IndirectKey) != 0) {
+ kmem = runtime·mallocgc(t->key->size, 0, 1, 0);
+ *(byte**)insertk = kmem;
+ insertk = kmem;
}
- for (;;) {
- struct hash_subtable *st = *pst;
- int32 shift = HASH_BITS - (st->power + HASH_USED (flags));
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (hash >> shift) & index_mask; /* i is the natural position of hash */
- struct hash_entry *start_e =
- HASH_OFFSET (st->entry, i * elemsize); /* start_e is the pointer to element i */
- struct hash_entry *e = start_e; /* e is going to range over [start_e, end_e) */
- struct hash_entry *end_e;
- hash_hash_t e_hash = e->hash;
-
- if ((e_hash & HASH_MASK) == HASH_SUBHASH) { /* a subtable */
- pst = (struct hash_subtable **) e->data;
- flags += HASH_MAKE_USED (st->power);
- continue;
- }
- end_e = HASH_OFFSET (start_e, st->limit_bytes);
- while (e != end_e && (e_hash = e->hash) != HASH_NIL && e_hash < hash) {
- e = HASH_OFFSET (e, elemsize);
- i++;
- }
- if (e != end_e && e_hash != HASH_NIL) {
- /* ins_e ranges over the elements that may match */
- struct hash_entry *ins_e = e;
- int32 ins_i = i;
- hash_hash_t ins_e_hash;
- void *key;
- while (ins_e != end_e && ((e_hash = ins_e->hash) ^ hash) < HASH_SUBHASH) {
- key = ins_e->data;
- if (h->flag & IndirectKey)
- key = *(void**)key;
- if (HASH_DATA_EQ (eq, t, h, data, key)) { /* a match */
- *pres = ins_e->data;
- return (1);
- }
- if (e_hash == hash) { /* adjust hash if it collides */
- assert ((flags & HASH_REHASH) == 0);
- hash++;
- if ((hash & HASH_MASK) == HASH_SUBHASH)
- runtime·throw("runtime: map hash collision overflow");
- }
- ins_e = HASH_OFFSET (ins_e, elemsize);
- ins_i++;
- if (e_hash <= hash) { /* set e to insertion point */
- e = ins_e;
- i = ins_i;
- }
- }
- /* set ins_e to the insertion point for the new element */
- ins_e = e;
- ins_i = i;
- ins_e_hash = 0;
- /* move ins_e to point at the end of the contiguous block, but
- stop if any element can't be moved by one up */
- while (ins_e <= st->last && (ins_e_hash = ins_e->hash) != HASH_NIL &&
- ins_i + 1 - ((ins_e_hash >> shift) & index_mask) < st->max_probes &&
- (ins_e_hash & HASH_MASK) != HASH_SUBHASH) {
- ins_e = HASH_OFFSET (ins_e, elemsize);
- ins_i++;
- }
- if (e == end_e || ins_e > st->last || ins_e_hash != HASH_NIL) {
- e = end_e; /* can't insert; must grow or convert to subtable */
- } else { /* make space for element */
- memmove (HASH_OFFSET (e, elemsize), e, ((byte *) ins_e) - (byte *) e);
- }
- }
- if (e != end_e) {
- e->hash = hash;
- *pres = e->data;
- return (0);
- }
- h->changes++;
- if (st->power < HASH_MAX_POWER) {
- hash_grow (t, h, pst, flags);
- } else {
- hash_conv (t, h, st, flags, hash, start_e);
- }
+ if((h->flags & IndirectValue) != 0) {
+ vmem = runtime·mallocgc(t->elem->size, 0, 1, 0);
+ *(byte**)insertv = vmem;
+ insertv = vmem;
}
+ t->key->alg->copy(t->key->size, insertk, key);
+ t->elem->alg->copy(t->elem->size, insertv, value);
+ *inserti = top;
+ h->count++;
+ if(docheck)
+ check(t, h);
}
-static int32
-hash_insert (MapType *t, Hmap *h, void *data, void **pres)
+static void
+hash_remove(MapType *t, Hmap *h, void *key)
{
uintptr hash;
- int32 rc;
-
+ uintptr bucket;
+ Bucket *b;
+ uint8 top;
+ uintptr i;
+ byte *k, *v;
+ bool eq;
+
+ if(docheck)
+ check(t, h);
hash = h->hash0;
- (*t->key->alg->hash) (&hash, t->key->size, data);
- rc = hash_insert_internal (t, &h->st, 0, hash, h, data, pres);
+ t->key->alg->hash(&hash, t->key->size, key);
+ bucket = hash & (((uintptr)1 << h->B) - 1);
+ if(h->oldbuckets != nil)
+ grow_work(t, h, bucket);
+ b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+ top = hash >> (sizeof(uintptr)*8 - 8);
+ if(top == 0)
+ top = 1;
+ do {
+ for(i = 0, k = b->data, v = k + h->keysize * BUCKETSIZE; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] != top)
+ continue;
+ t->key->alg->equal(&eq, t->key->size, key, IK(h, k));
+ if(!eq)
+ continue;
+
+ if((h->flags & CanFreeKey) != 0) {
+ k = *(byte**)k;
+ }
+ if((h->flags & IndirectValue) != 0) {
+ v = *(byte**)v;
+ }
- h->count += (rc == 0); /* increment count if element didn't previously exist */
- return (rc);
+ b->tophash[i] = 0;
+ h->count--;
+
+ if((h->flags & CanFreeKey) != 0) {
+ runtime·free(k);
+ }
+ if((h->flags & IndirectValue) != 0) {
+ runtime·free(v);
+ }
+ // TODO: consolidate buckets if they are mostly empty
+ // can only consolidate if there are no live iterators at this size.
+ if(docheck)
+ check(t, h);
+ return;
+ }
+ b = b->overflow;
+ } while(b != nil);
}
-static uint32
-hash_count (Hmap *h)
-{
- return (h->count);
-}
+// TODO: shrink the map, the same way we grow it.
-static void
-iter_restart (struct hash_iter *it, struct hash_subtable *st, int32 used)
+// If you modify hash_iter, also change cmd/gc/range.c to indicate
+// the size of this structure.
+struct hash_iter
{
- int32 elemsize = it->elemsize;
- hash_hash_t last_hash = it->last_hash;
- struct hash_entry *e;
- hash_hash_t e_hash;
- struct hash_iter_sub *sub = &it->subtable_state[it->i];
- struct hash_entry *last;
-
- for (;;) {
- int32 shift = HASH_BITS - (st->power + used);
- int32 index_mask = (1 << st->power) - 1;
- int32 i = (last_hash >> shift) & index_mask;
-
- last = st->last;
- e = HASH_OFFSET (st->entry, i * elemsize);
- sub->start = st->entry;
- sub->last = last;
-
- if ((e->hash & HASH_MASK) != HASH_SUBHASH) {
- break;
- }
- sub->e = HASH_OFFSET (e, elemsize);
- sub = &it->subtable_state[++(it->i)];
- used += st->power;
- st = *(struct hash_subtable **)e->data;
- }
- while (e <= last && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
- e = HASH_OFFSET (e, elemsize);
- }
- sub->e = e;
-}
+ uint8* key; // Must be in first position. Write nil to indicate iteration end (see cmd/gc/range.c).
+ uint8* value;
-static void *
-hash_next (struct hash_iter *it)
-{
- int32 elemsize;
- struct hash_iter_sub *sub;
- struct hash_entry *e;
- struct hash_entry *last;
- hash_hash_t e_hash;
-
- if (it->changes != it->h->changes) { /* hash table's structure changed; recompute */
- if (~it->last_hash == 0)
- return (0);
- it->changes = it->h->changes;
- it->i = 0;
- iter_restart (it, it->h->st, 0);
- }
- elemsize = it->elemsize;
-
-Again:
- e_hash = 0;
- sub = &it->subtable_state[it->i];
- e = sub->e;
- last = sub->last;
-
- if (e != sub->start && it->last_hash != HASH_OFFSET (e, -elemsize)->hash) {
- struct hash_entry *start = HASH_OFFSET (e, -(elemsize * HASH_MAX_PROBES));
- struct hash_entry *pe = HASH_OFFSET (e, -elemsize);
- hash_hash_t last_hash = it->last_hash;
- if (start < sub->start) {
- start = sub->start;
- }
- while (e != start && ((e_hash = pe->hash) == HASH_NIL || last_hash < e_hash)) {
- e = pe;
- pe = HASH_OFFSET (pe, -elemsize);
- }
- while (e <= last && ((e_hash = e->hash) == HASH_NIL || e_hash <= last_hash)) {
- e = HASH_OFFSET (e, elemsize);
- }
- }
+ MapType *t;
+ Hmap *h;
- for (;;) {
- while (e <= last && (e_hash = e->hash) == HASH_NIL) {
- e = HASH_OFFSET (e, elemsize);
- }
- if (e > last) {
- if (it->i == 0) {
- if(!it->cycled) {
- // Wrap to zero and iterate up until it->cycle.
- it->cycled = true;
- it->last_hash = 0;
- it->subtable_state[0].e = it->h->st->entry;
- it->subtable_state[0].start = it->h->st->entry;
- it->subtable_state[0].last = it->h->st->last;
- goto Again;
- }
- // Set last_hash to impossible value and
- // break it->changes, so that check at top of
- // hash_next will be used if we get called again.
- it->last_hash = ~(uintptr_t)0;
- it->changes--;
- return (0);
- } else {
- it->i--;
- sub = &it->subtable_state[it->i];
- e = sub->e;
- last = sub->last;
- }
- } else if ((e_hash & HASH_MASK) != HASH_SUBHASH) {
- if(it->cycled && e->hash > it->cycle) {
- // Already returned this.
- // Set last_hash to impossible value and
- // break it->changes, so that check at top of
- // hash_next will be used if we get called again.
- it->last_hash = ~(uintptr_t)0;
- it->changes--;
- return (0);
- }
- it->last_hash = e->hash;
- sub->e = HASH_OFFSET (e, elemsize);
- return (e->data);
- } else {
- struct hash_subtable *st =
- *(struct hash_subtable **)e->data;
- sub->e = HASH_OFFSET (e, elemsize);
- it->i++;
- assert (it->i < sizeof (it->subtable_state) /
- sizeof (it->subtable_state[0]));
- sub = &it->subtable_state[it->i];
- sub->e = e = st->entry;
- sub->start = st->entry;
- sub->last = last = st->last;
- }
- }
-}
+ // end point for iteration
+ uintptr endbucket;
+ bool wrapped;
+ // state of table at time iterator is initialized
+ uint8 B;
+ byte *buckets;
+
+ // iter state
+ uintptr bucket;
+ struct Bucket *bptr;
+ uintptr i;
+};
+
+// iterator state:
+// bucket: the current bucket ID
+// b: the current Bucket in the chain
+// i: the next offset to check in the current bucket
static void
-hash_iter_init (MapType *t, Hmap *h, struct hash_iter *it)
+hash_iter_init(MapType *t, Hmap *h, struct hash_iter *it)
{
- it->elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- it->changes = h->changes;
- it->i = 0;
- it->h = h;
it->t = t;
- it->last_hash = 0;
- it->subtable_state[0].e = h->st->entry;
- it->subtable_state[0].start = h->st->entry;
- it->subtable_state[0].last = h->st->last;
-
- // fastrand1 returns 31 useful bits.
- // We don't care about not having a bottom bit but we
- // do want top bits.
- if(sizeof(void*) == 8)
- it->cycle = (uint64)runtime·fastrand1()<<33 | (uint64)runtime·fastrand1()<<2;
- else
- it->cycle = runtime·fastrand1()<<1;
- it->cycled = false;
- it->last_hash = it->cycle;
- iter_restart(it, it->h->st, 0);
-}
+ it->h = h;
-static void
-clean_st (Hmap *h, struct hash_subtable *st, int32 *slots, int32 *used)
-{
- int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
- struct hash_entry *e = st->entry;
- struct hash_entry *last = st->last;
- int32 lslots = (((byte *) (last+1)) - (byte *) e) / elemsize;
- int32 lused = 0;
-
- while (e <= last) {
- hash_hash_t hash = e->hash;
- if ((hash & HASH_MASK) == HASH_SUBHASH) {
- clean_st (h, *(struct hash_subtable **)e->data, slots, used);
- } else {
- lused += (hash != HASH_NIL);
- }
- e = HASH_OFFSET (e, elemsize);
- }
- if (h->flag & CanFreeTable)
- free (st);
- *slots += lslots;
- *used += lused;
-}
+ // grab snapshot of bucket state
+ it->B = h->B;
+ it->buckets = h->buckets;
-static void
-hash_destroy (Hmap *h)
-{
- int32 slots = 0;
- int32 used = 0;
+ // iterator state
+ it->bucket = it->endbucket = runtime·fastrand1() & (((uintptr)1 << h->B) - 1);
+ it->wrapped = false;
+ it->bptr = nil;
- clean_st (h, h->st, &slots, &used);
- free (h);
+ // Remember we have an iterator at this level.
+ h->flags |= Iterator;
}
+// initializes it->key and it->value to the next key/value pair
+// in the iteration, or nil if we've reached the end.
static void
-hash_visit_internal (struct hash_subtable *st,
- int32 used, int32 level,
- void (*data_visit) (void *arg, int32 level, void *data),
- void *arg)
+hash_next(struct hash_iter *it)
{
- int32 elemsize = st->datasize + offsetof (struct hash_entry, data[0]);
- struct hash_entry *e = st->entry;
- int32 shift = HASH_BITS - (used + st->power);
- int32 i = 0;
-
- while (e <= st->last) {
- int32 index = ((e->hash >> (shift - 1)) >> 1) & ((1 << st->power) - 1);
- if ((e->hash & HASH_MASK) == HASH_SUBHASH) {
- (*data_visit) (arg, level, e->data);
- hash_visit_internal (*(struct hash_subtable **)e->data,
- used + st->power, level + 1, data_visit, arg);
- } else {
- (*data_visit) (arg, level, e->data);
+ Hmap *h;
+ MapType *t;
+ uintptr bucket;
+ Bucket *b;
+ uintptr i;
+ bool eq;
+ byte *k, *v;
+ byte *rk, *rv;
+
+ h = it->h;
+ t = it->t;
+ bucket = it->bucket;
+ b = it->bptr;
+ i = it->i;
+
+next:
+ if(b == nil) {
+ if(bucket == it->endbucket && it->wrapped) {
+ // end of iteration
+ it->key = nil;
+ it->value = nil;
+ return;
+ }
+ if(h->oldbuckets != nil && it->B == h->B) {
+ // Iterator was started in the middle of a grow, and the grow isn't done yet.
+ // Make sure the bucket we're about to read is valid.
+ grow_work(t, h, bucket);
}
- if (e->hash != HASH_NIL) {
- assert (i < index + st->max_probes);
- assert (index <= i);
+ b = (Bucket*)(it->buckets + bucket * h->bucketsize);
+ bucket++;
+ if(bucket == ((uintptr)1 << it->B)) {
+ bucket = 0;
+ it->wrapped = true;
+ }
+ i = 0;
+ }
+ k = b->data + h->keysize * i;
+ v = b->data + h->keysize * BUCKETSIZE + h->valuesize * i;
+ for(; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] != 0) {
+ if(!evacuated(b)) {
+ // this is the golden data, we can return it.
+ it->key = IK(h, k);
+ it->value = IV(h, v);
+ } else {
+ // The hash table has grown since the iterator was started.
+ // The golden data for this key is now somewhere else.
+ t->key->alg->equal(&eq, t->key->size, IK(h, k), IK(h, k));
+ if(eq) {
+ // Check the current hash table for the data.
+ // This code handles the case where the key
+ // has been deleted, updated, or deleted and reinserted.
+ // NOTE: we need to regrab the key as it has potentially been
+ // updated to an equal() but not identical key (e.g. +0.0 vs -0.0).
+ rk = IK(h, k);
+ rv = hash_lookup(t, it->h, &rk);
+ if(rv == nil)
+ continue; // key has been deleted
+ it->key = rk;
+ it->value = rv;
+ } else {
+ // if key!=key then the entry can't be deleted or
+ // updated, so we can just return it. That's lucky for
+ // us because when key!=key we can't look it up
+ // successfully in the current table.
+ it->key = IK(h, k);
+ it->value = IV(h, v);
+ }
+ }
+ it->bucket = bucket;
+ it->bptr = b;
+ it->i = i + 1;
+ return;
}
- e = HASH_OFFSET (e, elemsize);
- i++;
}
+ b = overflowptr(b);
+ i = 0;
+ goto next;
}
-static void
-hash_visit (Hmap *h, void (*data_visit) (void *arg, int32 level, void *data), void *arg)
-{
- hash_visit_internal (h->st, 0, 0, data_visit, arg);
-}
+
+#define PHASE_BUCKETS 0
+#define PHASE_OLD_BUCKETS 1
+#define PHASE_TABLE 2
+#define PHASE_OLD_TABLE 3
+#define PHASE_DONE 4
// Initialize the iterator.
// Returns false if Hmap contains no pointers (in which case the iterator is not initialized).
@@ -713,73 +841,141 @@ bool
hash_gciter_init (Hmap *h, struct hash_gciter *it)
{
// GC during map initialization
- if(h->st == nil)
+ if(h->buckets == nil)
return false;
- it->elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
- it->flag = h->flag;
- it->valoff = h->valoff;
- it->i = 0;
- it->st = h->st;
- it->subtable_state[it->i].e = h->st->entry;
- it->subtable_state[it->i].last = h->st->last;
+ it->h = h;
+ it->phase = PHASE_BUCKETS;
+ it->bucket = 0;
+ it->b = nil;
+
+ // TODO: finish evacuating oldbuckets so that we can collect
+ // oldbuckets? We don't want to keep a partially evacuated
+ // table around forever, so each gc could make at least some
+ // evacuation progress. Need to be careful about concurrent
+ // access if we do concurrent gc. Even if not, we don't want
+ // to make the gc pause any longer than it has to be.
+
return true;
}
-// Returns true and fills *data with subtable/key/value data,
+// Returns true and fills *data with internal structure/key/value data,
// or returns false if the iterator has terminated.
+// Ugh, this interface is really annoying. I want a callback fn!
bool
-hash_gciter_next (struct hash_gciter *it, struct hash_gciter_data *data)
+hash_gciter_next(struct hash_gciter *it, struct hash_gciter_data *data)
{
- struct hash_entry *e;
- struct hash_gciter_sub *sub;
+ Hmap *h;
+ uintptr bucket, oldbucket;
+ Bucket *b, *oldb;
+ uintptr i;
+ byte *k, *v;
+
+ h = it->h;
+ bucket = it->bucket;
+ b = it->b;
+ i = it->i;
data->st = nil;
data->key_data = nil;
data->val_data = nil;
-
- // pointer to the first-level table
- if(it->st != nil) {
- data->st = it->st;
- it->st = nil;
- return true;
- }
-
-popped:
- sub = &it->subtable_state[it->i];
- e = sub->e;
- while (e <= sub->last) {
- if ((e->hash & HASH_MASK) == HASH_SUBHASH) {
- struct hash_subtable *st = *(struct hash_subtable **)e->data;
- data->st = st;
- sub->e = HASH_OFFSET (e, it->elemsize);
-
- // push
- it->i++;
- assert (it->i < nelem(it->subtable_state));
- sub++;
- sub->e = st->entry;
- sub->last = st->last;
-
- return true;
+ data->indirectkey = (h->flags & IndirectKey) != 0;
+ data->indirectval = (h->flags & IndirectValue) != 0;
+
+next:
+ switch (it->phase) {
+ case PHASE_BUCKETS:
+ if(b != nil) {
+ k = b->data + h->keysize * i;
+ v = b->data + h->keysize * BUCKETSIZE + h->valuesize * i;
+ for(; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] != 0) {
+ data->key_data = k;
+ data->val_data = v;
+ it->bucket = bucket;
+ it->b = b;
+ it->i = i + 1;
+ return true;
+ }
+ }
+ b = b->overflow;
+ if(b != nil) {
+ data->st = (byte*)b;
+ it->bucket = bucket;
+ it->b = b;
+ it->i = 0;
+ return true;
+ }
+ }
+ while(bucket < ((uintptr)1 << h->B)) {
+ if(h->oldbuckets != nil) {
+ oldbucket = bucket & (((uintptr)1 << (h->B - 1)) - 1);
+ oldb = (Bucket*)(h->oldbuckets + oldbucket * h->bucketsize);
+ if(!evacuated(oldb)) {
+ // new bucket isn't valid yet
+ bucket++;
+ continue;
+ }
+ }
+ b = (Bucket*)(h->buckets + bucket * h->bucketsize);
+ i = 0;
+ bucket++;
+ goto next;
+ }
+ it->phase = PHASE_OLD_BUCKETS;
+ bucket = 0;
+ b = nil;
+ goto next;
+ case PHASE_OLD_BUCKETS:
+ if(h->oldbuckets == nil) {
+ it->phase = PHASE_TABLE;
+ goto next;
+ }
+ if(b != nil) {
+ k = b->data + h->keysize * i;
+ v = b->data + h->keysize * BUCKETSIZE + h->valuesize * i;
+ for(; i < BUCKETSIZE; i++, k += h->keysize, v += h->valuesize) {
+ if(b->tophash[i] != 0) {
+ data->key_data = k;
+ data->val_data = v;
+ it->bucket = bucket;
+ it->b = b;
+ it->i = i + 1;
+ return true;
+ }
+ }
+ b = overflowptr(b);
+ if(b != nil) {
+ data->st = (byte*)b;
+ it->bucket = bucket;
+ it->b = b;
+ it->i = 0;
+ return true;
+ }
+ }
+ if(bucket < ((uintptr)1 << (h->B - 1))) {
+ b = (Bucket*)(h->oldbuckets + bucket * h->bucketsize);
+ bucket++;
+ i = 0;
+ goto next;
}
- if(e->hash != HASH_NIL) {
- void *key_data = e->data;
- void *val_data = (byte*)e->data + it->valoff;
- data->key_data = key_data;
- data->val_data = val_data;
- data->indirectkey = (it->flag & IndirectKey) != 0;
- data->indirectval = (it->flag & IndirectVal) != 0;
- sub->e = HASH_OFFSET (e, it->elemsize);
+ it->phase = PHASE_TABLE;
+ goto next;
+ case PHASE_TABLE:
+ it->phase = PHASE_OLD_TABLE;
+ data->st = h->buckets;
+ return true;
+ case PHASE_OLD_TABLE:
+ it->phase = PHASE_DONE;
+ if(h->oldbuckets != nil) {
+ data->st = h->oldbuckets;
return true;
+ } else {
+ goto next;
}
- e = HASH_OFFSET (e, it->elemsize);
- }
- if(it->i != 0) {
- // pop
- it->i--;
- goto popped;
}
+ if(it->phase != PHASE_DONE)
+ runtime·throw("bad phase at done");
return false;
}
@@ -787,35 +983,13 @@ popped:
/// interfaces to go runtime
//
-static void**
-hash_valptr(Hmap *h, void *p)
-{
- p = (byte*)p + h->valoff;
- if(h->flag & IndirectVal)
- p = *(void**)p;
- return p;
-}
-
-
-static void**
-hash_keyptr(Hmap *h, void *p)
-{
- if(h->flag & IndirectKey)
- p = *(void**)p;
- return p;
-}
-
-static int32 debug = 0;
-
Hmap*
runtime·makemap_c(MapType *typ, int64 hint)
{
Hmap *h;
- Type *key, *val;
- uintptr ksize, vsize;
+ Type *key;
key = typ->key;
- val = typ->elem;
if(hint < 0 || (int32)hint != hint)
runtime·panicstring("makemap: size out of range");
@@ -824,7 +998,6 @@ runtime·makemap_c(MapType *typ, int64 hint)
runtime·throw("runtime.makemap: unsupported map key type");
h = runtime·mal(sizeof(*h));
- h->flag |= CanFreeTable; /* until reflect gets involved, free is okay */
if(UseSpanType) {
if(false) {
@@ -833,34 +1006,14 @@ runtime·makemap_c(MapType *typ, int64 hint)
runtime·settype(h, (uintptr)typ | TypeInfo_Map);
}
- ksize = ROUND(key->size, sizeof(void*));
- vsize = ROUND(val->size, sizeof(void*));
- if(ksize > MaxData || vsize > MaxData || ksize+vsize > MaxData) {
- // Either key is too big, or value is, or combined they are.
- // Prefer to keep the key if possible, because we look at
- // keys more often than values.
- if(ksize > MaxData - sizeof(void*)) {
- // No choice but to indirect the key.
- h->flag |= IndirectKey;
- h->flag |= CanFreeKey; /* until reflect gets involved, free is okay */
- ksize = sizeof(void*);
- }
- if(vsize > MaxData - ksize) {
- // Have to indirect the value.
- h->flag |= IndirectVal;
- vsize = sizeof(void*);
- }
- }
-
- h->valoff = ksize;
- hash_init(h, ksize+vsize, hint);
+ hash_init(typ, h, hint);
// these calculations are compiler dependent.
// figure out offsets of map call arguments.
if(debug) {
runtime·printf("makemap: map=%p; keysize=%p; valsize=%p; keyalg=%p; valalg=%p\n",
- h, key->size, val->size, key->alg, val->alg);
+ h, key->size, typ->elem->size, key->alg, typ->elem->alg);
}
return h;
@@ -890,7 +1043,7 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres)
Type *elem;
elem = t->elem;
- if(h == nil) {
+ if(h == nil || h->count == 0) {
elem->alg->copy(elem->size, av, nil);
*pres = false;
return;
@@ -899,10 +1052,11 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres)
if(runtime·gcwaiting)
runtime·gosched();
- res = nil;
- if(hash_lookup(t, h, ak, (void**)&res)) {
+ res = hash_lookup(t, h, &ak);
+
+ if(res != nil) {
*pres = true;
- elem->alg->copy(elem->size, av, hash_valptr(h, res));
+ elem->alg->copy(elem->size, av, res);
} else {
*pres = false;
elem->alg->copy(elem->size, av, nil);
@@ -915,7 +1069,7 @@ void
runtime·mapaccess1(MapType *t, Hmap *h, ...)
{
byte *ak, *av;
- bool pres;
+ byte *res;
if(raceenabled && h != nil)
runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapaccess1);
@@ -923,7 +1077,12 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
ak = (byte*)(&h + 1);
av = ak + ROUND(t->key->size, Structrnd);
- runtime·mapaccess(t, h, ak, av, &pres);
+ if(h == nil || h->count == 0) {
+ t->elem->alg->copy(t->elem->size, av, nil);
+ } else {
+ res = hash_lookup(t, h, &ak);
+ t->elem->alg->copy(t->elem->size, av, res);
+ }
if(debug) {
runtime·prints("runtime.mapaccess1: map=");
@@ -932,8 +1091,6 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
t->key->alg->print(t->key->size, ak);
runtime·prints("; val=");
t->elem->alg->print(t->elem->size, av);
- runtime·prints("; pres=");
- runtime·printbool(pres);
runtime·prints("\n");
}
}
@@ -960,7 +1117,7 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
runtime·prints("; key=");
t->key->alg->print(t->key->size, ak);
runtime·prints("; val=");
- t->elem->alg->print(t->key->size, av);
+ t->elem->alg->print(t->elem->size, av);
runtime·prints("; pres=");
runtime·printbool(*ap);
runtime·prints("\n");
@@ -999,9 +1156,6 @@ reflect·mapaccess(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
void
runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av)
{
- byte *res;
- int32 hit;
-
if(h == nil)
runtime·panicstring("assignment to entry in nil map");
@@ -1010,19 +1164,9 @@ runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av)
if(av == nil) {
hash_remove(t, h, ak);
- return;
- }
-
- res = nil;
- hit = hash_insert(t, h, ak, (void**)&res);
- if(!hit) {
- if(h->flag & IndirectKey)
- *(void**)res = runtime·mal(t->key->size);
- if(h->flag & IndirectVal)
- *(void**)(res+h->valoff) = runtime·mal(t->elem->size);
+ } else {
+ hash_insert(t, h, ak, av);
}
- t->key->alg->copy(t->key->size, hash_keyptr(h, res), ak);
- t->elem->alg->copy(t->elem->size, hash_valptr(h, res), av);
if(debug) {
runtime·prints("mapassign: map=");
@@ -1031,10 +1175,6 @@ runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av)
t->key->alg->print(t->key->size, ak);
runtime·prints("; val=");
t->elem->alg->print(t->elem->size, av);
- runtime·prints("; hit=");
- runtime·printint(hit);
- runtime·prints("; res=");
- runtime·printpointer(res);
runtime·prints("\n");
}
}
@@ -1112,20 +1252,20 @@ void
runtime·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
{
if(h == nil) {
- it->data = nil;
+ it->key = nil;
return;
}
if(raceenabled)
runtime·racereadpc(h, runtime·getcallerpc(&t), runtime·mapiterinit);
hash_iter_init(t, h, it);
- it->data = hash_next(it);
+ hash_next(it);
if(debug) {
runtime·prints("runtime.mapiterinit: map=");
runtime·printpointer(h);
runtime·prints("; iter=");
runtime·printpointer(it);
- runtime·prints("; data=");
- runtime·printpointer(it->data);
+ runtime·prints("; key=");
+ runtime·printpointer(it->key);
runtime·prints("\n");
}
}
@@ -1135,20 +1275,18 @@ runtime·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
void
reflect·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
{
- uint8 flag;
+ uint8 flags;
if(h != nil && t->key->size > sizeof(void*)) {
// reflect·mapiterkey returns pointers to key data,
// and reflect holds them, so we cannot free key data
- // eagerly anymore. Updating h->flag now is racy,
- // but it's okay because this is the only possible store
- // after creation.
- flag = h->flag;
- if(flag & IndirectKey)
- flag &= ~CanFreeKey;
+ // eagerly anymore.
+ flags = h->flags;
+ if(flags & IndirectKey)
+ flags &= ~CanFreeKey;
else
- flag &= ~CanFreeTable;
- h->flag = flag;
+ flags &= ~CanFreeBucket;
+ h->flags = flags;
}
it = runtime·mal(sizeof *it);
@@ -1165,12 +1303,12 @@ runtime·mapiternext(struct hash_iter *it)
if(runtime·gcwaiting)
runtime·gosched();
- it->data = hash_next(it);
+ hash_next(it);
if(debug) {
runtime·prints("runtime.mapiternext: iter=");
runtime·printpointer(it);
- runtime·prints("; data=");
- runtime·printpointer(it->data);
+ runtime·prints("; key=");
+ runtime·printpointer(it->key);
runtime·prints("\n");
}
}
@@ -1188,25 +1326,23 @@ reflect·mapiternext(struct hash_iter *it)
void
runtime·mapiter1(struct hash_iter *it, ...)
{
- Hmap *h;
byte *ak, *res;
Type *key;
- h = it->h;
ak = (byte*)(&it + 1);
- res = it->data;
+ res = it->key;
if(res == nil)
runtime·throw("runtime.mapiter1: key:val nil pointer");
key = it->t->key;
- key->alg->copy(key->size, ak, hash_keyptr(h, res));
+ key->alg->copy(key->size, ak, res);
if(debug) {
- runtime·prints("mapiter2: iter=");
+ runtime·prints("mapiter1: iter=");
runtime·printpointer(it);
runtime·prints("; map=");
- runtime·printpointer(h);
+ runtime·printpointer(it->h);
runtime·prints("\n");
}
}
@@ -1217,11 +1353,11 @@ runtime·mapiterkey(struct hash_iter *it, void *ak)
byte *res;
Type *key;
- res = it->data;
+ res = it->key;
if(res == nil)
return false;
key = it->t->key;
- key->alg->copy(key->size, ak, hash_keyptr(it->h, res));
+ key->alg->copy(key->size, ak, res);
return true;
}
@@ -1237,14 +1373,13 @@ reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok)
key = 0;
ok = false;
- res = it->data;
+ res = it->key;
if(res == nil) {
key = 0;
ok = false;
} else {
tkey = it->t->key;
key = 0;
- res = (byte*)hash_keyptr(it->h, res);
if(tkey->size <= sizeof(key))
tkey->alg->copy(tkey->size, (byte*)&key, res);
else
@@ -1276,7 +1411,6 @@ reflect·maplen(Hmap *h, intgo len)
void
runtime·mapiter2(struct hash_iter *it, ...)
{
- Hmap *h;
byte *ak, *av, *res;
MapType *t;
@@ -1284,19 +1418,18 @@ runtime·mapiter2(struct hash_iter *it, ...)
ak = (byte*)(&it + 1);
av = ak + ROUND(t->key->size, t->elem->align);
- res = it->data;
+ res = it->key;
if(res == nil)
runtime·throw("runtime.mapiter2: key:val nil pointer");
- h = it->h;
- t->key->alg->copy(t->key->size, ak, hash_keyptr(h, res));
- t->elem->alg->copy(t->elem->size, av, hash_valptr(h, res));
+ t->key->alg->copy(t->key->size, ak, res);
+ t->elem->alg->copy(t->elem->size, av, it->value);
if(debug) {
runtime·prints("mapiter2: iter=");
runtime·printpointer(it);
runtime·prints("; map=");
- runtime·printpointer(h);
+ runtime·printpointer(it->h);
runtime·prints("\n");
}
}
diff --git a/src/pkg/runtime/hashmap.h b/src/pkg/runtime/hashmap.h
index 9b82f299e..2988417f6 100644
--- a/src/pkg/runtime/hashmap.h
+++ b/src/pkg/runtime/hashmap.h
@@ -2,180 +2,28 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-/* A hash table.
- Example, hashing nul-terminated char*s:
- hash_hash_t str_hash (void *v) {
- char *s;
- hash_hash_t hash = 0;
- for (s = *(char **)v; *s != 0; s++) {
- hash = (hash ^ *s) * 2654435769U;
- }
- return (hash);
- }
- int str_eq (void *a, void *b) {
- return (strcmp (*(char **)a, *(char **)b) == 0);
- }
- void str_del (void *arg, void *data) {
- *(char **)arg = *(char **)data;
- }
-
- struct hash *h = hash_new (sizeof (char *), &str_hash, &str_eq, &str_del, 3, 12, 15);
- ... 3=> 2**3 entries initial size
- ... 12=> 2**12 entries before sprouting sub-tables
- ... 15=> number of adjacent probes to attempt before growing
-
- Example lookup:
- char *key = "foobar";
- char **result_ptr;
- if (hash_lookup (h, &key, (void **) &result_ptr)) {
- printf ("found in table: %s\n", *result_ptr);
- } else {
- printf ("not found in table\n");
- }
-
- Example insertion:
- char *key = strdup ("foobar");
- char **result_ptr;
- if (hash_lookup (h, &key, (void **) &result_ptr)) {
- printf ("found in table: %s\n", *result_ptr);
- printf ("to overwrite, do *result_ptr = key\n");
- } else {
- printf ("not found in table; inserted as %s\n", *result_ptr);
- assert (*result_ptr == key);
- }
-
- Example deletion:
- char *key = "foobar";
- char *result;
- if (hash_remove (h, &key, &result)) {
- printf ("key found and deleted from table\n");
- printf ("called str_del (&result, data) to copy data to result: %s\n", result);
- } else {
- printf ("not found in table\n");
- }
-
- Example iteration over the elements of *h:
- char **data;
- struct hash_iter it;
- hash_iter_init (h, &it);
- for (data = hash_next (&it); data != 0; data = hash_next (&it)) {
- printf ("%s\n", *data);
- }
- */
-
-#define memset(a,b,c) runtime·memclr((byte*)(a), (uint32)(c))
-#define memcpy(a,b,c) runtime·memmove((byte*)(a),(byte*)(b),(uint32)(c))
-#define assert(a) if(!(a)) runtime·throw("hashmap assert")
-#define free(x) runtime·free(x)
-#define memmove(a,b,c) runtime·memmove(a, b, c)
-
struct Hmap; /* opaque */
-struct hash_subtable; /* opaque */
-struct hash_entry; /* opaque */
-
-typedef uintptr uintptr_t;
-typedef uintptr_t hash_hash_t;
-
-struct hash_iter {
- uint8* data; /* returned from next */
- int32 elemsize; /* size of elements in table */
- int32 changes; /* number of changes observed last time */
- int32 i; /* stack pointer in subtable_state */
- bool cycled; /* have reached the end and wrapped to 0 */
- hash_hash_t last_hash; /* last hash value returned */
- hash_hash_t cycle; /* hash value where we started */
- struct Hmap *h; /* the hash table */
- MapType *t; /* the map type */
- struct hash_iter_sub {
- struct hash_entry *e; /* pointer into subtable */
- struct hash_entry *start; /* start of subtable */
- struct hash_entry *last; /* last entry in subtable */
- } subtable_state[4]; /* Should be large enough unless the hashing is
- so bad that many distinct data values hash
- to the same hash value. */
-};
-
-/* Return a hashtable h 2**init_power empty entries, each with
- "datasize" data bytes.
- (*data_hash)(a) should return the hash value of data element *a.
- (*data_eq)(a,b) should return whether the data at "a" and the data at "b"
- are equal.
- (*data_del)(arg, a) will be invoked when data element *a is about to be removed
- from the table. "arg" is the argument passed to "hash_remove()".
-
- Growing is accomplished by resizing if the current tables size is less than
- a threshold, and by adding subtables otherwise. hint should be set
- the expected maximum size of the table.
- "datasize" should be in [sizeof (void*), ..., 255]. If you need a
- bigger "datasize", store a pointer to another piece of memory. */
-
-//struct hash *hash_new (int32 datasize,
-// hash_hash_t (*data_hash) (void *),
-// int32 (*data_eq) (void *, void *),
-// void (*data_del) (void *, void *),
-// int64 hint);
-
-/* Lookup *data in *h. If the data is found, return 1 and place a pointer to
- the found element in *pres. Otherwise return 0 and place 0 in *pres. */
-// int32 hash_lookup (struct hash *h, void *data, void **pres);
-
-/* Lookup *data in *h. If the data is found, execute (*data_del) (arg, p)
- where p points to the data in the table, then remove it from *h and return
- 1. Otherwise return 0. */
-// int32 hash_remove (struct hash *h, void *data, void *arg);
-
-/* Lookup *data in *h. If the data is found, return 1, and place a pointer
- to the found element in *pres. Otherwise, return 0, allocate a region
- for the data to be inserted, and place a pointer to the inserted element
- in *pres; it is the caller's responsibility to copy the data to be
- inserted to the pointer returned in *pres in this case.
-
- If using garbage collection, it is the caller's responsibility to
- add references for **pres if HASH_ADDED is returned. */
-// int32 hash_insert (struct hash *h, void *data, void **pres);
-
-/* Return the number of elements in the table. */
-// uint32 hash_count (struct hash *h);
-
-/* The following call is useful only if not using garbage collection on the
- table.
- Remove all sub-tables associated with *h.
- This undoes the effects of hash_init().
- If other memory pointed to by user data must be freed, the caller is
- responsible for doing so by iterating over *h first; see
- hash_iter_init()/hash_next(). */
-// void hash_destroy (struct hash *h);
-
-/*----- iteration -----*/
-
-/* Initialize *it from *h. */
-// void hash_iter_init (struct hash *h, struct hash_iter *it);
-
-/* Return the next used entry in the table with which *it was initialized. */
-// void *hash_next (struct hash_iter *it);
-
-/*---- test interface ----*/
-/* Call (*data_visit) (arg, level, data) for every data entry in the table,
- whether used or not. "level" is the subtable level, 0 means first level. */
-/* TESTING ONLY: DO NOT USE THIS ROUTINE IN NORMAL CODE */
-// void hash_visit (struct hash *h, void (*data_visit) (void *arg, int32 level, void *data), void *arg);
/* Used by the garbage collector */
struct hash_gciter
{
- int32 elemsize;
- uint8 flag;
- uint8 valoff;
- uint32 i; /* stack pointer in subtable_state */
- struct hash_subtable *st;
- struct hash_gciter_sub {
- struct hash_entry *e; /* pointer into subtable */
- struct hash_entry *last; /* last entry in subtable */
- } subtable_state[4];
+ Hmap *h;
+ int32 phase;
+ uintptr bucket;
+ struct Bucket *b;
+ uintptr i;
};
+
+// this data is used by the garbage collector to keep the map's
+// internal structures from being reclaimed. The iterator must
+// return in st every live object (ones returned by mallocgc) so
+// that those objects won't be collected, and it must return
+// every key & value in key_data/val_data so they can get scanned
+// for pointers they point to. Note that if you malloc storage
+// for keys and values, you need to do both.
struct hash_gciter_data
{
- struct hash_subtable *st; /* subtable pointer, or nil */
+ uint8 *st; /* internal structure, or nil */
uint8 *key_data; /* key data, or nil */
uint8 *val_data; /* value data, or nil */
bool indirectkey; /* storing pointers to keys */
diff --git a/src/pkg/runtime/hashmap_fast.c b/src/pkg/runtime/hashmap_fast.c
new file mode 100644
index 000000000..2169f4c30
--- /dev/null
+++ b/src/pkg/runtime/hashmap_fast.c
@@ -0,0 +1,149 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Fast hashmap lookup specialized to a specific key type.
+// Included by hashmap.c once for each specialized type.
+
+// Note that this code differs from hash_lookup in that
+// it returns a pointer to the result, not the result itself.
+// The returned pointer is only valid until the next GC
+// point, so the caller must dereference it before then.
+
+// +build ignore
+
+#pragma textflag 7
+void
+HASH_LOOKUP1(MapType *t, Hmap *h, KEYTYPE key, byte *value)
+{
+ uintptr hash;
+ uintptr bucket;
+ Bucket *b;
+ uint8 top;
+ uintptr i;
+ KEYTYPE *k;
+ byte *v;
+
+ if(debug) {
+ runtime·prints("runtime.mapaccess1_fastXXX: map=");
+ runtime·printpointer(h);
+ runtime·prints("; key=");
+ t->key->alg->print(t->key->size, &key);
+ runtime·prints("\n");
+ }
+ if(h == nil || h->count == 0) {
+ value = empty_value;
+ FLUSH(&value);
+ return;
+ }
+ if(raceenabled)
+ runtime·racereadpc(h, runtime·getcallerpc(&t), HASH_LOOKUP1);
+ if(docheck)
+ check(t, h);
+
+ if(h->B == 0 && (h->count == 1 || QUICKEQ(key))) {
+ // One-bucket table. Don't hash, just check each bucket entry.
+ b = (Bucket*)h->buckets;
+ for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
+ if(b->tophash[i] != 0 && EQFUNC(key, *k)) {
+ value = v;
+ FLUSH(&value);
+ return;
+ }
+ }
+ } else {
+ hash = h->hash0;
+ HASHFUNC(&hash, sizeof(KEYTYPE), &key);
+ bucket = hash & (((uintptr)1 << h->B) - 1);
+ if(h->oldbuckets != nil)
+ grow_work(t, h, bucket);
+ b = (Bucket*)(h->buckets + bucket * (offsetof(Bucket, data[0]) + BUCKETSIZE * sizeof(KEYTYPE) + BUCKETSIZE * h->valuesize));
+ top = hash >> (sizeof(uintptr)*8 - 8);
+ if(top == 0)
+ top = 1;
+ do {
+ for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
+ if(b->tophash[i] == top && EQFUNC(key, *k)) {
+ value = v;
+ FLUSH(&value);
+ return;
+ }
+ }
+ b = b->overflow;
+ } while(b != nil);
+ }
+ value = empty_value;
+ FLUSH(&value);
+}
+
+#pragma textflag 7
+void
+HASH_LOOKUP2(MapType *t, Hmap *h, KEYTYPE key, byte *value, bool res)
+{
+ uintptr hash;
+ uintptr bucket;
+ Bucket *b;
+ uint8 top;
+ uintptr i;
+ KEYTYPE *k;
+ byte *v;
+
+ if(debug) {
+ runtime·prints("runtime.mapaccess2_fastXXX: map=");
+ runtime·printpointer(h);
+ runtime·prints("; key=");
+ t->key->alg->print(t->key->size, &key);
+ runtime·prints("\n");
+ }
+ if(h == nil || h->count == 0) {
+ value = empty_value;
+ res = false;
+ FLUSH(&value);
+ FLUSH(&res);
+ return;
+ }
+ if(raceenabled)
+ runtime·racereadpc(h, runtime·getcallerpc(&t), HASH_LOOKUP2);
+ if(docheck)
+ check(t, h);
+
+ if(h->B == 0 && (h->count == 1 || QUICKEQ(key))) {
+ // One-bucket table. Don't hash, just check each bucket entry.
+ b = (Bucket*)h->buckets;
+ for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
+ if(b->tophash[i] != 0 && EQFUNC(key, *k)) {
+ value = v;
+ res = true;
+ FLUSH(&value);
+ FLUSH(&res);
+ return;
+ }
+ }
+ } else {
+ hash = h->hash0;
+ HASHFUNC(&hash, sizeof(KEYTYPE), &key);
+ bucket = hash & (((uintptr)1 << h->B) - 1);
+ if(h->oldbuckets != nil)
+ grow_work(t, h, bucket);
+ b = (Bucket*)(h->buckets + bucket * (offsetof(Bucket, data[0]) + BUCKETSIZE * sizeof(KEYTYPE) + BUCKETSIZE * h->valuesize));
+ top = hash >> (sizeof(uintptr)*8 - 8);
+ if(top == 0)
+ top = 1;
+ do {
+ for(i = 0, k = (KEYTYPE*)b->data, v = (byte*)(k + BUCKETSIZE); i < BUCKETSIZE; i++, k++, v += h->valuesize) {
+ if(b->tophash[i] == top && EQFUNC(key, *k)) {
+ value = v;
+ res = true;
+ FLUSH(&value);
+ FLUSH(&res);
+ return;
+ }
+ }
+ b = b->overflow;
+ } while(b != nil);
+ }
+ value = empty_value;
+ res = false;
+ FLUSH(&value);
+ FLUSH(&res);
+}
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index ac131b3af..fa28e2b73 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -35,7 +35,7 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
MSpan *s;
void *v;
- if(runtime·gcwaiting && g != m->g0 && m->locks == 0)
+ if(runtime·gcwaiting && g != m->g0 && m->locks == 0 && dogc)
runtime·gosched();
if(m->mallocing)
runtime·throw("malloc/free - deadlock");
@@ -516,7 +516,7 @@ runtime·settype_flush(M *mp, bool sysalloc)
nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
if(!sysalloc) {
- data3 = runtime·mallocgc(nbytes3, FlagNoPointers, 0, 1);
+ data3 = runtime·mallocgc(nbytes3, FlagNoProfiling|FlagNoPointers, 0, 1);
} else {
data3 = runtime·SysAlloc(nbytes3);
if(data3 == nil)
@@ -554,7 +554,7 @@ runtime·settype_flush(M *mp, bool sysalloc)
nbytes2 = ntypes * sizeof(uintptr);
if(!sysalloc) {
- data2 = runtime·mallocgc(nbytes2, FlagNoPointers, 0, 1);
+ data2 = runtime·mallocgc(nbytes2, FlagNoProfiling|FlagNoPointers, 0, 1);
} else {
data2 = runtime·SysAlloc(nbytes2);
if(data2 == nil)
diff --git a/src/pkg/runtime/map_test.go b/src/pkg/runtime/map_test.go
new file mode 100644
index 000000000..29e19db2c
--- /dev/null
+++ b/src/pkg/runtime/map_test.go
@@ -0,0 +1,282 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "fmt"
+ "math"
+ "runtime"
+ "sort"
+ "testing"
+)
+
+// negative zero is a good test because:
+// 1) 0 and -0 are equal, yet have distinct representations.
+// 2) 0 is represented as all zeros, -0 isn't.
+// I'm not sure the language spec actually requires this behavior,
+// but it's what the current map implementation does.
+func TestNegativeZero(t *testing.T) {
+ m := make(map[float64]bool, 0)
+
+ m[+0.0] = true
+ m[math.Copysign(0.0, -1.0)] = true // should overwrite +0 entry
+
+ if len(m) != 1 {
+ t.Error("length wrong")
+ }
+
+ for k, _ := range m {
+ if math.Copysign(1.0, k) > 0 {
+ t.Error("wrong sign")
+ }
+ }
+
+ m = make(map[float64]bool, 0)
+ m[math.Copysign(0.0, -1.0)] = true
+ m[+0.0] = true // should overwrite -0.0 entry
+
+ if len(m) != 1 {
+ t.Error("length wrong")
+ }
+
+ for k, _ := range m {
+ if math.Copysign(1.0, k) < 0 {
+ t.Error("wrong sign")
+ }
+ }
+}
+
+// nan is a good test because nan != nan, and nan has
+// a randomized hash value.
+func TestNan(t *testing.T) {
+ m := make(map[float64]int, 0)
+ nan := math.NaN()
+ m[nan] = 1
+ m[nan] = 2
+ m[nan] = 4
+ if len(m) != 3 {
+ t.Error("length wrong")
+ }
+ s := 0
+ for k, v := range m {
+ if k == k {
+ t.Error("nan disappeared")
+ }
+ if (v & (v - 1)) != 0 {
+ t.Error("value wrong")
+ }
+ s |= v
+ }
+ if s != 7 {
+ t.Error("values wrong")
+ }
+}
+
+// Maps aren't actually copied on assignment.
+func TestAlias(t *testing.T) {
+ m := make(map[int]int, 0)
+ m[0] = 5
+ n := m
+ n[0] = 6
+ if m[0] != 6 {
+ t.Error("alias didn't work")
+ }
+}
+
+func TestGrowWithNaN(t *testing.T) {
+ m := make(map[float64]int, 4)
+ nan := math.NaN()
+ m[nan] = 1
+ m[nan] = 2
+ m[nan] = 4
+ cnt := 0
+ s := 0
+ growflag := true
+ for k, v := range m {
+ if growflag {
+ // force a hashtable resize
+ for i := 0; i < 100; i++ {
+ m[float64(i)] = i
+ }
+ growflag = false
+ }
+ if k != k {
+ cnt++
+ s |= v
+ }
+ }
+ if cnt != 3 {
+ t.Error("NaN keys lost during grow")
+ }
+ if s != 7 {
+ t.Error("NaN values lost during grow")
+ }
+}
+
+type FloatInt struct {
+ x float64
+ y int
+}
+
+func TestGrowWithNegativeZero(t *testing.T) {
+ negzero := math.Copysign(0.0, -1.0)
+ m := make(map[FloatInt]int, 4)
+ m[FloatInt{0.0, 0}] = 1
+ m[FloatInt{0.0, 1}] = 2
+ m[FloatInt{0.0, 2}] = 4
+ m[FloatInt{0.0, 3}] = 8
+ growflag := true
+ s := 0
+ cnt := 0
+ negcnt := 0
+ // The first iteration should return the +0 key.
+ // The subsequent iterations should return the -0 key.
+ // I'm not really sure this is required by the spec,
+ // but it makes sense.
+ // TODO: are we allowed to get the first entry returned again???
+ for k, v := range m {
+ if v == 0 {
+ continue
+ } // ignore entries added to grow table
+ cnt++
+ if math.Copysign(1.0, k.x) < 0 {
+ if v&16 == 0 {
+ t.Error("key/value not updated together 1")
+ }
+ negcnt++
+ s |= v & 15
+ } else {
+ if v&16 == 16 {
+ t.Error("key/value not updated together 2", k, v)
+ }
+ s |= v
+ }
+ if growflag {
+ // force a hashtable resize
+ for i := 0; i < 100; i++ {
+ m[FloatInt{3.0, i}] = 0
+ }
+ // then change all the entries
+ // to negative zero
+ m[FloatInt{negzero, 0}] = 1 | 16
+ m[FloatInt{negzero, 1}] = 2 | 16
+ m[FloatInt{negzero, 2}] = 4 | 16
+ m[FloatInt{negzero, 3}] = 8 | 16
+ growflag = false
+ }
+ }
+ if s != 15 {
+ t.Error("entry missing", s)
+ }
+ if cnt != 4 {
+ t.Error("wrong number of entries returned by iterator", cnt)
+ }
+ if negcnt != 3 {
+ t.Error("update to negzero missed by iteration", negcnt)
+ }
+}
+
+func TestIterGrowAndDelete(t *testing.T) {
+ m := make(map[int]int, 4)
+ for i := 0; i < 100; i++ {
+ m[i] = i
+ }
+ growflag := true
+ for k := range m {
+ if growflag {
+ // grow the table
+ for i := 100; i < 1000; i++ {
+ m[i] = i
+ }
+ // delete all odd keys
+ for i := 1; i < 1000; i += 2 {
+ delete(m, i)
+ }
+ growflag = false
+ } else {
+ if k&1 == 1 {
+ t.Error("odd value returned")
+ }
+ }
+ }
+}
+
+// make sure old bucket arrays don't get GCd while
+// an iterator is still using them.
+func TestIterGrowWithGC(t *testing.T) {
+ m := make(map[int]int, 4)
+ for i := 0; i < 16; i++ {
+ m[i] = i
+ }
+ growflag := true
+ bitmask := 0
+ for k := range m {
+ if k < 16 {
+ bitmask |= 1 << uint(k)
+ }
+ if growflag {
+ // grow the table
+ for i := 100; i < 1000; i++ {
+ m[i] = i
+ }
+ // trigger a gc
+ runtime.GC()
+ growflag = false
+ }
+ }
+ if bitmask != 1<<16-1 {
+ t.Error("missing key", bitmask)
+ }
+}
+
+func TestBigItems(t *testing.T) {
+ var key [256]string
+ for i := 0; i < 256; i++ {
+ key[i] = "foo"
+ }
+ m := make(map[[256]string][256]string, 4)
+ for i := 0; i < 100; i++ {
+ key[37] = fmt.Sprintf("string%02d", i)
+ m[key] = key
+ }
+ var keys [100]string
+ var values [100]string
+ i := 0
+ for k, v := range m {
+ keys[i] = k[37]
+ values[i] = v[37]
+ i++
+ }
+ sort.Strings(keys[:])
+ sort.Strings(values[:])
+ for i := 0; i < 100; i++ {
+ if keys[i] != fmt.Sprintf("string%02d", i) {
+ t.Errorf("#%d: missing key: %v", i, keys[i])
+ }
+ if values[i] != fmt.Sprintf("string%02d", i) {
+ t.Errorf("#%d: missing value: %v", i, values[i])
+ }
+ }
+}
+
+type empty struct {
+}
+
+func TestEmptyKeyAndValue(t *testing.T) {
+ a := make(map[int]empty, 4)
+ b := make(map[empty]int, 4)
+ c := make(map[empty]empty, 4)
+ a[0] = empty{}
+ b[empty{}] = 0
+ b[empty{}] = 1
+ c[empty{}] = empty{}
+
+ if len(a) != 1 {
+ t.Errorf("empty value insert problem")
+ }
+ if b[empty{}] != 1 {
+ t.Errorf("empty key returned wrong value")
+ }
+}
diff --git a/src/pkg/runtime/mapspeed_test.go b/src/pkg/runtime/mapspeed_test.go
new file mode 100644
index 000000000..a37974060
--- /dev/null
+++ b/src/pkg/runtime/mapspeed_test.go
@@ -0,0 +1,150 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package runtime_test
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+const size = 10
+
+func BenchmarkHashStringSpeed(b *testing.B) {
+ strings := make([]string, size)
+ for i := 0; i < size; i++ {
+ strings[i] = fmt.Sprintf("string#%d", i)
+ }
+ sum := 0
+ m := make(map[string]int, size)
+ for i := 0; i < size; i++ {
+ m[strings[i]] = 0
+ }
+ idx := 0
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ sum += m[strings[idx]]
+ idx++
+ if idx == size {
+ idx = 0
+ }
+ }
+}
+
+func BenchmarkHashInt32Speed(b *testing.B) {
+ ints := make([]int32, size)
+ for i := 0; i < size; i++ {
+ ints[i] = int32(i)
+ }
+ sum := 0
+ m := make(map[int32]int, size)
+ for i := 0; i < size; i++ {
+ m[ints[i]] = 0
+ }
+ idx := 0
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ sum += m[ints[idx]]
+ idx++
+ if idx == size {
+ idx = 0
+ }
+ }
+}
+
+func BenchmarkHashInt64Speed(b *testing.B) {
+ ints := make([]int64, size)
+ for i := 0; i < size; i++ {
+ ints[i] = int64(i)
+ }
+ sum := 0
+ m := make(map[int64]int, size)
+ for i := 0; i < size; i++ {
+ m[ints[i]] = 0
+ }
+ idx := 0
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ sum += m[ints[idx]]
+ idx++
+ if idx == size {
+ idx = 0
+ }
+ }
+}
+func BenchmarkHashStringArraySpeed(b *testing.B) {
+ stringpairs := make([][2]string, size)
+ for i := 0; i < size; i++ {
+ for j := 0; j < 2; j++ {
+ stringpairs[i][j] = fmt.Sprintf("string#%d/%d", i, j)
+ }
+ }
+ sum := 0
+ m := make(map[[2]string]int, size)
+ for i := 0; i < size; i++ {
+ m[stringpairs[i]] = 0
+ }
+ idx := 0
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ sum += m[stringpairs[idx]]
+ idx++
+ if idx == size {
+ idx = 0
+ }
+ }
+}
+
+func BenchmarkMegMap(b *testing.B) {
+ m := make(map[string]bool)
+ for suffix := 'A'; suffix <= 'G'; suffix++ {
+ m[strings.Repeat("X", 1<<20-1)+fmt.Sprint(suffix)] = true
+ }
+ key := strings.Repeat("X", 1<<20-1) + "k"
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, _ = m[key]
+ }
+}
+
+func BenchmarkMegOneMap(b *testing.B) {
+ m := make(map[string]bool)
+ m[strings.Repeat("X", 1<<20)] = true
+ key := strings.Repeat("Y", 1<<20)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, _ = m[key]
+ }
+}
+
+func BenchmarkMegEmptyMap(b *testing.B) {
+ m := make(map[string]bool)
+ key := strings.Repeat("X", 1<<20)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, _ = m[key]
+ }
+}
+
+func BenchmarkSmallStrMap(b *testing.B) {
+ m := make(map[string]bool)
+ for suffix := 'A'; suffix <= 'G'; suffix++ {
+ m[fmt.Sprint(suffix)] = true
+ }
+ key := "k"
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, _ = m[key]
+ }
+}
+func BenchmarkIntMap(b *testing.B) {
+ m := make(map[int]bool)
+ for i := 0; i < 8; i++ {
+ m[i] = true
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, _ = m[7]
+ }
+}
diff --git a/src/pkg/runtime/mcentral.c b/src/pkg/runtime/mcentral.c
index ac8b5aa0d..ec2a91ad5 100644
--- a/src/pkg/runtime/mcentral.c
+++ b/src/pkg/runtime/mcentral.c
@@ -19,7 +19,6 @@
#include "malloc.h"
static bool MCentral_Grow(MCentral *c);
-static void* MCentral_Alloc(MCentral *c);
static void MCentral_Free(MCentral *c, void *v);
// Initialize a single central free list.
diff --git a/src/pkg/runtime/mem_darwin.c b/src/pkg/runtime/mem_darwin.c
index 04e719394..7aa607f8e 100644
--- a/src/pkg/runtime/mem_darwin.c
+++ b/src/pkg/runtime/mem_darwin.c
@@ -37,7 +37,12 @@ runtime·SysFree(void *v, uintptr n)
void*
runtime·SysReserve(void *v, uintptr n)
{
- return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+ void *p;
+
+ p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+ if(p < (void*)4096)
+ return nil;
+ return p;
}
enum
@@ -52,7 +57,7 @@ runtime·SysMap(void *v, uintptr n)
mstats.sys += n;
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
- if(p == (void*)-ENOMEM)
+ if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v)
runtime·throw("runtime: cannot map pages in arena address space");
diff --git a/src/pkg/runtime/mem_freebsd.c b/src/pkg/runtime/mem_freebsd.c
index f217e9db1..805e74cff 100644
--- a/src/pkg/runtime/mem_freebsd.c
+++ b/src/pkg/runtime/mem_freebsd.c
@@ -8,6 +8,11 @@
#include "os_GOOS.h"
#include "malloc.h"
+enum
+{
+ ENOMEM = 12,
+};
+
void*
runtime·SysAlloc(uintptr n)
{
@@ -36,20 +41,20 @@ runtime·SysFree(void *v, uintptr n)
void*
runtime·SysReserve(void *v, uintptr n)
{
+ void *p;
+
// On 64-bit, people with ulimit -v set complain if we reserve too
// much address space. Instead, assume that the reservation is okay
// and check the assumption in SysMap.
if(sizeof(void*) == 8)
return v;
- return runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+ p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+ if(p < (void*)4096)
+ return nil;
+ return p;
}
-enum
-{
- ENOMEM = 12,
-};
-
void
runtime·SysMap(void *v, uintptr n)
{
@@ -60,7 +65,7 @@ runtime·SysMap(void *v, uintptr n)
// On 64-bit, we don't actually have v reserved, so tread carefully.
if(sizeof(void*) == 8) {
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
- if(p == (void*)-ENOMEM)
+ if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v) {
runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
@@ -70,7 +75,7 @@ runtime·SysMap(void *v, uintptr n)
}
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
- if(p == (void*)-ENOMEM)
+ if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v)
runtime·throw("runtime: cannot map pages in arena address space");
diff --git a/src/pkg/runtime/mem_linux.c b/src/pkg/runtime/mem_linux.c
index ebcec1e86..1bae755fa 100644
--- a/src/pkg/runtime/mem_linux.c
+++ b/src/pkg/runtime/mem_linux.c
@@ -10,8 +10,6 @@
enum
{
- EAGAIN = 11,
- ENOMEM = 12,
_PAGE_SIZE = 4096,
};
diff --git a/src/pkg/runtime/mem_netbsd.c b/src/pkg/runtime/mem_netbsd.c
index 77ce04c4e..e5bdac0ef 100644
--- a/src/pkg/runtime/mem_netbsd.c
+++ b/src/pkg/runtime/mem_netbsd.c
@@ -50,10 +50,9 @@ runtime·SysReserve(void *v, uintptr n)
return v;
p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
- if (p == ((void *)-ENOMEM))
+ if(p < (void*)4096)
return nil;
- else
- return p;
+ return p;
}
void
@@ -66,7 +65,7 @@ runtime·SysMap(void *v, uintptr n)
// On 64-bit, we don't actually have v reserved, so tread carefully.
if(sizeof(void*) == 8) {
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
- if(p == (void*)-ENOMEM)
+ if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v) {
runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
@@ -76,7 +75,7 @@ runtime·SysMap(void *v, uintptr n)
}
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
- if(p == (void*)-ENOMEM)
+ if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v)
runtime·throw("runtime: cannot map pages in arena address space");
diff --git a/src/pkg/runtime/mem_openbsd.c b/src/pkg/runtime/mem_openbsd.c
index 77ce04c4e..e5bdac0ef 100644
--- a/src/pkg/runtime/mem_openbsd.c
+++ b/src/pkg/runtime/mem_openbsd.c
@@ -50,10 +50,9 @@ runtime·SysReserve(void *v, uintptr n)
return v;
p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
- if (p == ((void *)-ENOMEM))
+ if(p < (void*)4096)
return nil;
- else
- return p;
+ return p;
}
void
@@ -66,7 +65,7 @@ runtime·SysMap(void *v, uintptr n)
// On 64-bit, we don't actually have v reserved, so tread carefully.
if(sizeof(void*) == 8) {
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
- if(p == (void*)-ENOMEM)
+ if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v) {
runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
@@ -76,7 +75,7 @@ runtime·SysMap(void *v, uintptr n)
}
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
- if(p == (void*)-ENOMEM)
+ if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v)
runtime·throw("runtime: cannot map pages in arena address space");
diff --git a/src/pkg/runtime/memmove_amd64.s b/src/pkg/runtime/memmove_amd64.s
index e78be8145..6174407e3 100644
--- a/src/pkg/runtime/memmove_amd64.s
+++ b/src/pkg/runtime/memmove_amd64.s
@@ -23,11 +23,12 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+// void runtime·memmove(void*, void*, uintptr)
TEXT runtime·memmove(SB), 7, $0
MOVQ to+0(FP), DI
MOVQ fr+8(FP), SI
- MOVLQSX n+16(FP), BX
+ MOVQ n+16(FP), BX
/*
* check and set for backwards
@@ -38,7 +39,7 @@ TEXT runtime·memmove(SB), 7, $0
/*
* forward copy loop
*/
-forward:
+forward:
MOVQ BX, CX
SHRQ $3, CX
ANDQ $7, BX
diff --git a/src/pkg/runtime/memmove_linux_amd64_test.go b/src/pkg/runtime/memmove_linux_amd64_test.go
new file mode 100644
index 000000000..f7221f4f5
--- /dev/null
+++ b/src/pkg/runtime/memmove_linux_amd64_test.go
@@ -0,0 +1,61 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "io/ioutil"
+ "os"
+ "reflect"
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+// TestMemmoveOverflow maps 3GB of memory and calls memmove on
+// the corresponding slice.
+func TestMemmoveOverflow(t *testing.T) {
+ // Create a temporary file.
+ tmp, err := ioutil.TempFile("", "go-memmovetest")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = tmp.Write(make([]byte, 65536))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmp.Name())
+ defer tmp.Close()
+
+ // Set up mappings.
+ base, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
+ 0xa0<<32, 3<<30, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS, ^uintptr(0), 0)
+ if errno != 0 {
+ t.Skipf("could not create memory mapping: %s", errno)
+ }
+ syscall.Syscall(syscall.SYS_MUNMAP, base, 3<<30, 0)
+
+ for off := uintptr(0); off < 3<<30; off += 65536 {
+ _, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
+ base+off, 65536, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED|syscall.MAP_FIXED, tmp.Fd(), 0)
+ if errno != 0 {
+ t.Fatalf("could not map a page at requested 0x%x: %s", base+off, errno)
+ }
+ defer syscall.Syscall(syscall.SYS_MUNMAP, base+off, 65536, 0)
+ }
+
+ var s []byte
+ sp := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+ sp.Data = base
+ sp.Len, sp.Cap = 3<<30, 3<<30
+
+ n := copy(s[1:], s)
+ if n != 3<<30-1 {
+ t.Fatalf("copied %d bytes, expected %d", n, 3<<30-1)
+ }
+ n = copy(s, s[1:])
+ if n != 3<<30-1 {
+ t.Fatalf("copied %d bytes, expected %d", n, 3<<30-1)
+ }
+}
diff --git a/src/pkg/runtime/mfixalloc.c b/src/pkg/runtime/mfixalloc.c
index c916d588f..c7dab8aea 100644
--- a/src/pkg/runtime/mfixalloc.c
+++ b/src/pkg/runtime/mfixalloc.c
@@ -30,6 +30,11 @@ void*
runtime·FixAlloc_Alloc(FixAlloc *f)
{
void *v;
+
+ if(f->size == 0) {
+ runtime·printf("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n");
+ runtime·throw("runtime: internal error");
+ }
if(f->list) {
v = f->list;
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index 010f9cd96..aa499f476 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -140,6 +140,7 @@ static Workbuf* getempty(Workbuf*);
static Workbuf* getfull(Workbuf*);
static void putempty(Workbuf*);
static Workbuf* handoff(Workbuf*);
+static void gchelperstart(void);
static struct {
uint64 full; // lock-free list of full blocks
@@ -191,7 +192,7 @@ static struct {
// markonly marks an object. It returns true if the object
// has been marked by this function, false otherwise.
-// This function isn't thread-safe and doesn't append the object to any buffer.
+// This function doesn't append the object to any buffer.
static bool
markonly(void *obj)
{
@@ -254,13 +255,23 @@ found:
// Only care about allocated and not marked.
if((bits & (bitAllocated|bitMarked)) != bitAllocated)
return false;
- *bitp |= bitMarked<<shift;
+ if(work.nproc == 1)
+ *bitp |= bitMarked<<shift;
+ else {
+ for(;;) {
+ x = *bitp;
+ if(x & (bitMarked<<shift))
+ return false;
+ if(runtime·casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+ break;
+ }
+ }
// The object is now marked
return true;
}
-// PtrTarget and BitTarget are structures used by intermediate buffers.
+// PtrTarget is a structure used by intermediate buffers.
// The intermediate buffers hold GC data before it
// is moved/flushed to the work buffer (Workbuf).
// The size of an intermediate buffer is very small,
@@ -272,25 +283,17 @@ struct PtrTarget
uintptr ti;
};
-typedef struct BitTarget BitTarget;
-struct BitTarget
-{
- void *p;
- uintptr ti;
- uintptr *bitp, shift;
-};
-
typedef struct BufferList BufferList;
struct BufferList
{
PtrTarget ptrtarget[IntermediateBufferCapacity];
- BitTarget bittarget[IntermediateBufferCapacity];
Obj obj[IntermediateBufferCapacity];
- BufferList *next;
+ uint32 busy;
+ byte pad[CacheLineSize];
};
-static BufferList *bufferList;
+#pragma dataflag 16 // no pointers
+static BufferList bufferList[MaxGcproc];
-static Lock lock;
static Type *itabtype;
static void enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj);
@@ -301,7 +304,6 @@ static void enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj);
// and are prepared to be scanned by the garbage collector.
//
// _wp, _wbuf, _nobj are input/output parameters and are specifying the work buffer.
-// bitbuf holds temporary data generated by this function.
//
// A simplified drawing explaining how the todo-list moves from a structure to another:
//
@@ -309,14 +311,12 @@ static void enqueue(Obj obj, Workbuf **_wbuf, Obj **_wp, uintptr *_nobj);
// (find pointers)
// Obj ------> PtrTarget (pointer targets)
// ↑ |
-// | | flushptrbuf (1st part,
-// | | find block start)
-// | ↓
-// `--------- BitTarget (pointer targets and the corresponding locations in bitmap)
-// flushptrbuf
-// (2nd part, mark and enqueue)
+// | |
+// `----------'
+// flushptrbuf
+// (find block start, mark and enqueue)
static void
-flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf, uintptr *_nobj, BitTarget *bitbuf)
+flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf, uintptr *_nobj)
{
byte *p, *arena_start, *obj;
uintptr size, *bitp, bits, shift, j, x, xbits, off, nobj, ti, n;
@@ -325,7 +325,6 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
Obj *wp;
Workbuf *wbuf;
PtrTarget *ptrbuf_end;
- BitTarget *bitbufpos, *bt;
arena_start = runtime·mheap->arena_start;
@@ -359,8 +358,6 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
{
// Multi-threaded version.
- bitbufpos = bitbuf;
-
while(ptrbuf < ptrbuf_end) {
obj = ptrbuf->p;
ti = ptrbuf->ti;
@@ -438,26 +435,22 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
// Only care about allocated and not marked.
if((bits & (bitAllocated|bitMarked)) != bitAllocated)
continue;
-
- *bitbufpos++ = (BitTarget){obj, ti, bitp, shift};
- }
-
- runtime·lock(&lock);
- for(bt=bitbuf; bt<bitbufpos; bt++){
- xbits = *bt->bitp;
- bits = xbits >> bt->shift;
- if((bits & bitMarked) != 0)
- continue;
-
- // Mark the block
- *bt->bitp = xbits | (bitMarked << bt->shift);
+ if(work.nproc == 1)
+ *bitp |= bitMarked<<shift;
+ else {
+ for(;;) {
+ x = *bitp;
+ if(x & (bitMarked<<shift))
+ goto continue_obj;
+ if(runtime·casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+ break;
+ }
+ }
// If object has no pointers, don't need to scan further.
if((bits & bitNoPointers) != 0)
continue;
- obj = bt->p;
-
// Ask span about size class.
// (Manually inlined copy of MHeap_Lookup.)
x = (uintptr)obj >> PageShift;
@@ -467,11 +460,11 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
PREFETCH(obj);
- *wp = (Obj){obj, s->elemsize, bt->ti};
+ *wp = (Obj){obj, s->elemsize, ti};
wp++;
nobj++;
+ continue_obj:;
}
- runtime·unlock(&lock);
// If another proc wants a pointer, give it some.
if(work.nwait > 0 && nobj > handoffThreshold && work.full == 0) {
@@ -575,20 +568,19 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
byte *b, *arena_start, *arena_used;
uintptr n, i, end_b, elemsize, size, ti, objti, count, type;
uintptr *pc, precise_type, nominal_size;
- uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti;
+ uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret;
void *obj;
Type *t;
Slice *sliceptr;
Frame *stack_ptr, stack_top, stack[GC_STACK_CAPACITY+4];
BufferList *scanbuffers;
PtrTarget *ptrbuf, *ptrbuf_end, *ptrbufpos;
- BitTarget *bitbuf;
Obj *objbuf, *objbuf_end, *objbufpos;
Eface *eface;
Iface *iface;
Hmap *hmap;
MapType *maptype;
- bool didmark, mapkey_kind, mapval_kind;
+ bool mapkey_kind, mapval_kind;
struct hash_gciter map_iter;
struct hash_gciter_data d;
Hchan *chan;
@@ -606,26 +598,13 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
precise_type = false;
nominal_size = 0;
- // Allocate ptrbuf, bitbuf
+ // Allocate ptrbuf
{
- runtime·lock(&lock);
-
- if(bufferList == nil) {
- bufferList = runtime·SysAlloc(sizeof(*bufferList));
- if(bufferList == nil)
- runtime·throw("runtime: cannot allocate memory");
- bufferList->next = nil;
- }
- scanbuffers = bufferList;
- bufferList = bufferList->next;
-
+ scanbuffers = &bufferList[m->helpgc];
ptrbuf = &scanbuffers->ptrtarget[0];
ptrbuf_end = &scanbuffers->ptrtarget[0] + nelem(scanbuffers->ptrtarget);
- bitbuf = &scanbuffers->bittarget[0];
objbuf = &scanbuffers->obj[0];
objbuf_end = &scanbuffers->obj[0] + nelem(scanbuffers->obj);
-
- runtime·unlock(&lock);
}
ptrbufpos = ptrbuf;
@@ -638,6 +617,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
mapkey_ti = mapval_ti = 0;
chan = nil;
chantype = nil;
+ chan_ret = nil;
goto next_block;
@@ -703,7 +683,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
mapval_kind = maptype->elem->kind;
mapval_ti = (uintptr)maptype->elem->gc | PRECISE;
- map_ret = 0;
+ map_ret = nil;
pc = mapProg;
} else {
goto next_block;
@@ -712,6 +692,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
case TypeInfo_Chan:
chan = (Hchan*)b;
chantype = (ChanType*)t;
+ chan_ret = nil;
pc = chanProg;
break;
default:
@@ -759,17 +740,29 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
case GC_STRING:
obj = *(void**)(stack_top.b + pc[1]);
+ markonly(obj);
pc += 2;
- break;
+ continue;
case GC_EFACE:
eface = (Eface*)(stack_top.b + pc[1]);
pc += 2;
- if(eface->type != nil && (eface->data >= arena_start && eface->data < arena_used)) {
- t = eface->type;
+ if(eface->type == nil)
+ continue;
+
+ // eface->type
+ t = eface->type;
+ if((void*)t >= arena_start && (void*)t < arena_used) {
+ *ptrbufpos++ = (PtrTarget){t, 0};
+ if(ptrbufpos == ptrbuf_end)
+ flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj);
+ }
+
+ // eface->data
+ if(eface->data >= arena_start && eface->data < arena_used) {
if(t->size <= sizeof(void*)) {
if((t->kind & KindNoPointers))
- break;
+ continue;
obj = eface->data;
if((t->kind & ~KindNoPointers) == KindPtr)
@@ -785,13 +778,13 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
iface = (Iface*)(stack_top.b + pc[1]);
pc += 2;
if(iface->tab == nil)
- break;
+ continue;
// iface->tab
if((void*)iface->tab >= arena_start && (void*)iface->tab < arena_used) {
*ptrbufpos++ = (PtrTarget){iface->tab, (uintptr)itabtype->gc};
if(ptrbufpos == ptrbuf_end)
- flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+ flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj);
}
// iface->data
@@ -799,7 +792,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
t = iface->tab->type;
if(t->size <= sizeof(void*)) {
if((t->kind & KindNoPointers))
- break;
+ continue;
obj = iface->data;
if((t->kind & ~KindNoPointers) == KindPtr)
@@ -812,13 +805,13 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
break;
case GC_DEFAULT_PTR:
- while((i = stack_top.b) <= end_b) {
+ while(stack_top.b <= end_b) {
+ obj = *(byte**)stack_top.b;
stack_top.b += PtrSize;
- obj = *(byte**)i;
if(obj >= arena_start && obj < arena_used) {
*ptrbufpos++ = (PtrTarget){obj, 0};
if(ptrbufpos == ptrbuf_end)
- flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+ flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj);
}
}
goto next_block;
@@ -826,9 +819,8 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
case GC_END:
if(--stack_top.count != 0) {
// Next iteration of a loop if possible.
- elemsize = stack_top.elemsize;
- stack_top.b += elemsize;
- if(stack_top.b + elemsize <= end_b+PtrSize) {
+ stack_top.b += stack_top.elemsize;
+ if(stack_top.b + stack_top.elemsize <= end_b+PtrSize) {
pc = stack_top.loop_or_ret;
continue;
}
@@ -894,10 +886,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
pc += 3;
continue;
}
- runtime·lock(&lock);
- didmark = markonly(hmap);
- runtime·unlock(&lock);
- if(didmark) {
+ if(markonly(hmap)) {
maptype = (MapType*)pc[2];
if(hash_gciter_init(hmap, &map_iter)) {
mapkey_size = maptype->key->size;
@@ -923,31 +912,41 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
while(hash_gciter_next(&map_iter, &d)) {
// buffers: reserve space for 2 objects.
if(ptrbufpos+2 >= ptrbuf_end)
- flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+ flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj);
if(objbufpos+2 >= objbuf_end)
flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
- if(d.st != nil) {
- runtime·lock(&lock);
+ if(d.st != nil)
markonly(d.st);
- runtime·unlock(&lock);
- }
+
if(d.key_data != nil) {
if(!(mapkey_kind & KindNoPointers) || d.indirectkey) {
if(!d.indirectkey)
*objbufpos++ = (Obj){d.key_data, mapkey_size, mapkey_ti};
- else
+ else {
+ if(Debug) {
+ obj = *(void**)d.key_data;
+ if(!(arena_start <= obj && obj < arena_used))
+ runtime·throw("scanblock: inconsistent hashmap");
+ }
*ptrbufpos++ = (PtrTarget){*(void**)d.key_data, mapkey_ti};
+ }
}
if(!(mapval_kind & KindNoPointers) || d.indirectval) {
if(!d.indirectval)
*objbufpos++ = (Obj){d.val_data, mapval_size, mapval_ti};
- else
+ else {
+ if(Debug) {
+ obj = *(void**)d.val_data;
+ if(!(arena_start <= obj && obj < arena_used))
+ runtime·throw("scanblock: inconsistent hashmap");
+ }
*ptrbufpos++ = (PtrTarget){*(void**)d.val_data, mapval_ti};
+ }
}
}
}
- if(map_ret == 0)
+ if(map_ret == nil)
goto next_block;
pc = map_ret;
continue;
@@ -961,7 +960,26 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
*objbufpos++ = (Obj){obj, size, objti};
if(objbufpos == objbuf_end)
flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
- break;
+ continue;
+
+ case GC_CHAN_PTR:
+ // Similar to GC_MAP_PTR
+ chan = *(Hchan**)(stack_top.b + pc[1]);
+ if(chan == nil) {
+ pc += 3;
+ continue;
+ }
+ if(markonly(chan)) {
+ chantype = (ChanType*)pc[2];
+ if(!(chantype->elem->kind & KindNoPointers)) {
+ // Start chanProg.
+ chan_ret = pc+3;
+ pc = chanProg+1;
+ continue;
+ }
+ }
+ pc += 3;
+ continue;
case GC_CHAN:
// There are no heap pointers in struct Hchan,
@@ -981,7 +999,10 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
}
}
- goto next_block;
+ if(chan_ret == nil)
+ goto next_block;
+ pc = chan_ret;
+ continue;
default:
runtime·throw("scanblock: invalid GC instruction");
@@ -991,7 +1012,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
if(obj >= arena_start && obj < arena_used) {
*ptrbufpos++ = (PtrTarget){obj, objti};
if(ptrbufpos == ptrbuf_end)
- flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+ flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj);
}
}
@@ -1000,7 +1021,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
// the loop by setting b, n, ti to the parameters for the next block.
if(nobj == 0) {
- flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj, bitbuf);
+ flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj);
flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
if(nobj == 0) {
@@ -1026,11 +1047,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
nobj--;
}
-endscan:
- runtime·lock(&lock);
- scanbuffers->next = bufferList;
- bufferList = scanbuffers;
- runtime·unlock(&lock);
+endscan:;
}
// debug_scanblock is the debug copy of scanblock.
@@ -1339,7 +1356,7 @@ addstackroots(G *gp)
runtime·printf("scanstack inconsistent: g%D#%d sp=%p not in [%p,%p]\n", gp->goid, n, sp, guard-StackGuard, stk);
runtime·throw("scanstack");
}
- addroot((Obj){sp, (byte*)stk - sp, 0});
+ addroot((Obj){sp, (byte*)stk - sp, (uintptr)defaultProg | PRECISE | LOOP});
sp = (byte*)stk->gobuf.sp;
guard = stk->stackguard;
stk = (Stktop*)stk->stackbase;
@@ -1381,14 +1398,17 @@ addroots(void)
for(spanidx=0; spanidx<runtime·mheap->nspan; spanidx++) {
s = allspans[spanidx];
if(s->state == MSpanInUse) {
+ // The garbage collector ignores type pointers stored in MSpan.types:
+ // - Compiler-generated types are stored outside of heap.
+ // - The reflect package has runtime-generated types cached in its data structures.
+ // The garbage collector relies on finding the references via that cache.
switch(s->types.compression) {
case MTypes_Empty:
case MTypes_Single:
break;
case MTypes_Words:
case MTypes_Bytes:
- // TODO(atom): consider using defaultProg instead of 0
- addroot((Obj){(byte*)&s->types.data, sizeof(void*), 0});
+ markonly((byte*)s->types.data);
break;
}
}
@@ -1655,6 +1675,8 @@ runtime·memorydump(void)
void
runtime·gchelper(void)
{
+ gchelperstart();
+
// parallel mark for over gc roots
runtime·parfordo(work.markfor);
@@ -1668,6 +1690,7 @@ runtime·gchelper(void)
}
runtime·parfordo(work.sweepfor);
+ bufferList[m->helpgc].busy = 0;
if(runtime·xadd(&work.ndone, +1) == work.nproc-1)
runtime·notewakeup(&work.alldone);
}
@@ -1757,6 +1780,8 @@ runtime·gc(int32 force)
// a problem in the past.
if((((uintptr)&work.empty) & 7) != 0)
runtime·throw("runtime: gc work buffer is misaligned");
+ if((((uintptr)&work.full) & 7) != 0)
+ runtime·throw("runtime: gc work buffer is misaligned");
// The gc is turned off (via enablegc) until
// the bootstrap has completed.
@@ -1857,6 +1882,7 @@ gc(struct gc_args *args)
t1 = runtime·nanotime();
+ gchelperstart();
runtime·parfordo(work.markfor);
scanblock(nil, nil, 0, true);
@@ -1868,6 +1894,7 @@ gc(struct gc_args *args)
t2 = runtime·nanotime();
runtime·parfordo(work.sweepfor);
+ bufferList[m->helpgc].busy = 0;
t3 = runtime·nanotime();
if(work.nproc > 1)
@@ -2009,6 +2036,15 @@ runtime∕debug·setGCPercent(intgo in, intgo out)
}
static void
+gchelperstart(void)
+{
+ if(m->helpgc < 0 || m->helpgc >= MaxGcproc)
+ runtime·throw("gchelperstart: bad m->helpgc");
+ if(runtime·xchg(&bufferList[m->helpgc].busy, 1))
+ runtime·throw("gchelperstart: already busy");
+}
+
+static void
runfinq(void)
{
Finalizer *f;
diff --git a/src/pkg/runtime/mgc0.h b/src/pkg/runtime/mgc0.h
index 87b604a36..18f3654b4 100644
--- a/src/pkg/runtime/mgc0.h
+++ b/src/pkg/runtime/mgc0.h
@@ -24,6 +24,7 @@ enum {
GC_ARRAY_NEXT, // The next element of an array. Args: none
GC_CALL, // Call a subroutine. Args: (off, objgcrel)
GC_MAP_PTR, // Go map. Args: (off, MapType*)
+ GC_CHAN_PTR, // Go channel. Args: (off, ChanType*)
GC_STRING, // Go string. Args: (off)
GC_EFACE, // interface{}. Args: (off)
GC_IFACE, // interface{...}. Args: (off)
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index f45149d63..177f40659 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -409,6 +409,9 @@ runtime·MHeap_Scavenger(void)
bool trace;
Note note, *notep;
+ g->issystem = true;
+ g->isbackground = true;
+
// If we go two minutes without a garbage collection, force one to run.
forcegc = 2*60*1e9;
// If a span goes unused for 5 minutes after a garbage collection,
diff --git a/src/pkg/runtime/netpoll.goc b/src/pkg/runtime/netpoll.goc
new file mode 100644
index 000000000..06b6d6172
--- /dev/null
+++ b/src/pkg/runtime/netpoll.goc
@@ -0,0 +1,351 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin linux
+
+package net
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "arch_GOARCH.h"
+#include "malloc.h"
+
+// Integrated network poller (platform-independent part).
+// A particular implementation (epoll/kqueue) must define the following functions:
+// void runtime·netpollinit(void); // to initialize the poller
+// int32 runtime·netpollopen(int32 fd, PollDesc *pd); // to arm edge-triggered notifications
+ // and associate fd with pd.
+// An implementation must call the following function to denote that the pd is ready.
+// void runtime·netpollready(G **gpp, PollDesc *pd, int32 mode);
+
+#define READY ((G*)1)
+
+struct PollDesc
+{
+ PollDesc* link; // in pollcache, protected by pollcache.Lock
+ Lock; // protectes the following fields
+ int32 fd;
+ bool closing;
+ uintptr seq; // protects from stale timers and ready notifications
+ G* rg; // G waiting for read or READY (binary semaphore)
+ Timer rt; // read deadline timer (set if rt.fv != nil)
+ int64 rd; // read deadline
+ G* wg; // the same for writes
+ Timer wt;
+ int64 wd;
+};
+
+static struct
+{
+ Lock;
+ PollDesc* first;
+ // PollDesc objects must be type-stable,
+ // because we can get ready notification from epoll/kqueue
+ // after the descriptor is closed/reused.
+ // Stale notifications are detected using seq variable,
+ // seq is incremented when deadlines are changed or descriptor is reused.
+} pollcache;
+
+static void netpollblock(PollDesc*, int32);
+static G* netpollunblock(PollDesc*, int32);
+static void deadline(int64, Eface);
+static void readDeadline(int64, Eface);
+static void writeDeadline(int64, Eface);
+static PollDesc* allocPollDesc(void);
+static intgo checkerr(PollDesc *pd, int32 mode);
+
+static FuncVal deadlineFn = {(void(*)(void))deadline};
+static FuncVal readDeadlineFn = {(void(*)(void))readDeadline};
+static FuncVal writeDeadlineFn = {(void(*)(void))writeDeadline};
+
+func runtime_pollServerInit() {
+ runtime·netpollinit();
+}
+
+func runtime_pollOpen(fd int) (pd *PollDesc, errno int) {
+ pd = allocPollDesc();
+ runtime·lock(pd);
+ if(pd->wg != nil && pd->wg != READY)
+ runtime·throw("runtime_pollOpen: blocked write on free descriptor");
+ if(pd->rg != nil && pd->rg != READY)
+ runtime·throw("runtime_pollOpen: blocked read on free descriptor");
+ pd->fd = fd;
+ pd->closing = false;
+ pd->seq++;
+ pd->rg = nil;
+ pd->rd = 0;
+ pd->wg = nil;
+ pd->wd = 0;
+ runtime·unlock(pd);
+
+ errno = runtime·netpollopen(fd, pd);
+}
+
+func runtime_pollClose(pd *PollDesc) {
+ if(!pd->closing)
+ runtime·throw("runtime_pollClose: close w/o unblock");
+ if(pd->wg != nil && pd->wg != READY)
+ runtime·throw("runtime_pollClose: blocked write on closing descriptor");
+ if(pd->rg != nil && pd->rg != READY)
+ runtime·throw("runtime_pollClose: blocked read on closing descriptor");
+ runtime·netpollclose(pd->fd);
+ runtime·lock(&pollcache);
+ pd->link = pollcache.first;
+ pollcache.first = pd;
+ runtime·unlock(&pollcache);
+}
+
+func runtime_pollReset(pd *PollDesc, mode int) (err int) {
+ runtime·lock(pd);
+ err = checkerr(pd, mode);
+ if(err)
+ goto ret;
+ if(mode == 'r')
+ pd->rg = nil;
+ else if(mode == 'w')
+ pd->wg = nil;
+ret:
+ runtime·unlock(pd);
+}
+
+func runtime_pollWait(pd *PollDesc, mode int) (err int) {
+ runtime·lock(pd);
+ err = checkerr(pd, mode);
+ if(err)
+ goto ret;
+ netpollblock(pd, mode);
+ err = checkerr(pd, mode);
+ret:
+ runtime·unlock(pd);
+}
+
+func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
+ runtime·lock(pd);
+ if(pd->closing)
+ goto ret;
+ pd->seq++; // invalidate current timers
+ // Reset current timers.
+ if(pd->rt.fv) {
+ runtime·deltimer(&pd->rt);
+ pd->rt.fv = nil;
+ }
+ if(pd->wt.fv) {
+ runtime·deltimer(&pd->wt);
+ pd->wt.fv = nil;
+ }
+ // Setup new timers.
+ if(d != 0 && d <= runtime·nanotime()) {
+ d = -1;
+ }
+ if(mode == 'r' || mode == 'r'+'w')
+ pd->rd = d;
+ if(mode == 'w' || mode == 'r'+'w')
+ pd->wd = d;
+ if(pd->rd > 0 && pd->rd == pd->wd) {
+ pd->rt.fv = &deadlineFn;
+ pd->rt.when = pd->rd;
+ // Copy current seq into the timer arg.
+ // Timer func will check the seq against current descriptor seq,
+ // if they differ the descriptor was reused or timers were reset.
+ pd->rt.arg.type = (Type*)pd->seq;
+ pd->rt.arg.data = pd;
+ runtime·addtimer(&pd->rt);
+ } else {
+ if(pd->rd > 0) {
+ pd->rt.fv = &readDeadlineFn;
+ pd->rt.when = pd->rd;
+ pd->rt.arg.type = (Type*)pd->seq;
+ pd->rt.arg.data = pd;
+ runtime·addtimer(&pd->rt);
+ }
+ if(pd->wd > 0) {
+ pd->wt.fv = &writeDeadlineFn;
+ pd->wt.when = pd->wd;
+ pd->wt.arg.type = (Type*)pd->seq;
+ pd->wt.arg.data = pd;
+ runtime·addtimer(&pd->wt);
+ }
+ }
+ret:
+ runtime·unlock(pd);
+}
+
+func runtime_pollUnblock(pd *PollDesc) {
+ G *rg, *wg;
+
+ runtime·lock(pd);
+ if(pd->closing)
+ runtime·throw("runtime_pollUnblock: already closing");
+ pd->closing = true;
+ pd->seq++;
+ rg = netpollunblock(pd, 'r');
+ wg = netpollunblock(pd, 'w');
+ if(pd->rt.fv) {
+ runtime·deltimer(&pd->rt);
+ pd->rt.fv = nil;
+ }
+ if(pd->wt.fv) {
+ runtime·deltimer(&pd->wt);
+ pd->wt.fv = nil;
+ }
+ runtime·unlock(pd);
+ if(rg)
+ runtime·ready(rg);
+ if(wg)
+ runtime·ready(wg);
+}
+
+// make pd ready, newly runnable goroutines (if any) are enqueued info gpp list
+void
+runtime·netpollready(G **gpp, PollDesc *pd, int32 mode)
+{
+ G *rg, *wg;
+
+ rg = wg = nil;
+ runtime·lock(pd);
+ if(mode == 'r' || mode == 'r'+'w')
+ rg = netpollunblock(pd, 'r');
+ if(mode == 'w' || mode == 'r'+'w')
+ wg = netpollunblock(pd, 'w');
+ runtime·unlock(pd);
+ if(rg) {
+ rg->schedlink = *gpp;
+ *gpp = rg;
+ }
+ if(wg) {
+ wg->schedlink = *gpp;
+ *gpp = wg;
+ }
+}
+
+static intgo
+checkerr(PollDesc *pd, int32 mode)
+{
+ if(pd->closing)
+ return 1; // errClosing
+ if((mode == 'r' && pd->rd < 0) || (mode == 'w' && pd->wd < 0))
+ return 2; // errTimeout
+ return 0;
+}
+
+static void
+netpollblock(PollDesc *pd, int32 mode)
+{
+ G **gpp;
+
+ gpp = &pd->rg;
+ if(mode == 'w')
+ gpp = &pd->wg;
+ if(*gpp == READY) {
+ *gpp = nil;
+ return;
+ }
+ if(*gpp != nil)
+ runtime·throw("epoll: double wait");
+ *gpp = g;
+ runtime·park(runtime·unlock, &pd->Lock, "IO wait");
+ runtime·lock(pd);
+}
+
+static G*
+netpollunblock(PollDesc *pd, int32 mode)
+{
+ G **gpp, *old;
+
+ gpp = &pd->rg;
+ if(mode == 'w')
+ gpp = &pd->wg;
+ if(*gpp == READY)
+ return nil;
+ if(*gpp == nil) {
+ *gpp = READY;
+ return nil;
+ }
+ old = *gpp;
+ *gpp = nil;
+ return old;
+}
+
+static void
+deadlineimpl(int64 now, Eface arg, bool read, bool write)
+{
+ PollDesc *pd;
+ uint32 seq;
+ G *rg, *wg;
+
+ USED(now);
+ pd = (PollDesc*)arg.data;
+ // This is the seq when the timer was set.
+ // If it's stale, ignore the timer event.
+ seq = (uintptr)arg.type;
+ rg = wg = nil;
+ runtime·lock(pd);
+ if(seq != pd->seq) {
+ // The descriptor was reused or timers were reset.
+ runtime·unlock(pd);
+ return;
+ }
+ if(read) {
+ if(pd->rd <= 0 || pd->rt.fv == nil)
+ runtime·throw("deadlineimpl: inconsistent read deadline");
+ pd->rd = -1;
+ pd->rt.fv = nil;
+ rg = netpollunblock(pd, 'r');
+ }
+ if(write) {
+ if(pd->wd <= 0 || (pd->wt.fv == nil && !read))
+ runtime·throw("deadlineimpl: inconsistent write deadline");
+ pd->wd = -1;
+ pd->wt.fv = nil;
+ wg = netpollunblock(pd, 'w');
+ }
+ runtime·unlock(pd);
+ if(rg)
+ runtime·ready(rg);
+ if(wg)
+ runtime·ready(wg);
+}
+
+static void
+deadline(int64 now, Eface arg)
+{
+ deadlineimpl(now, arg, true, true);
+}
+
+static void
+readDeadline(int64 now, Eface arg)
+{
+ deadlineimpl(now, arg, true, false);
+}
+
+static void
+writeDeadline(int64 now, Eface arg)
+{
+ deadlineimpl(now, arg, false, true);
+}
+
+static PollDesc*
+allocPollDesc(void)
+{
+ PollDesc *pd;
+ uint32 i, n;
+
+ runtime·lock(&pollcache);
+ if(pollcache.first == nil) {
+ n = PageSize/sizeof(*pd);
+ if(n == 0)
+ n = 1;
+ // Must be in non-GC memory because can be referenced
+ // only from epoll/kqueue internals.
+ pd = runtime·SysAlloc(n*sizeof(*pd));
+ for(i = 0; i < n; i++) {
+ pd[i].link = pollcache.first;
+ pollcache.first = &pd[i];
+ }
+ }
+ pd = pollcache.first;
+ pollcache.first = pd->link;
+ runtime·unlock(&pollcache);
+ return pd;
+}
diff --git a/src/pkg/runtime/netpoll_epoll.c b/src/pkg/runtime/netpoll_epoll.c
new file mode 100644
index 000000000..d6ef0d144
--- /dev/null
+++ b/src/pkg/runtime/netpoll_epoll.c
@@ -0,0 +1,92 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+
+int32 runtime·epollcreate(int32 size);
+int32 runtime·epollcreate1(int32 flags);
+int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
+int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+void runtime·closeonexec(int32 fd);
+
+static int32 epfd = -1; // epoll descriptor
+
+void
+runtime·netpollinit(void)
+{
+ epfd = runtime·epollcreate1(EPOLL_CLOEXEC);
+ if(epfd >= 0)
+ return;
+ epfd = runtime·epollcreate(1024);
+ if(epfd >= 0) {
+ runtime·closeonexec(epfd);
+ return;
+ }
+ runtime·printf("netpollinit: failed to create descriptor (%d)\n", -epfd);
+ runtime·throw("netpollinit: failed to create descriptor");
+}
+
+int32
+runtime·netpollopen(int32 fd, PollDesc *pd)
+{
+ EpollEvent ev;
+ int32 res;
+
+ ev.events = EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET;
+ ev.data = (uint64)pd;
+ res = runtime·epollctl(epfd, EPOLL_CTL_ADD, fd, &ev);
+ return -res;
+}
+
+int32
+runtime·netpollclose(int32 fd)
+{
+ EpollEvent ev;
+ int32 res;
+
+ res = runtime·epollctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+ return -res;
+}
+
+// polls for ready network connections
+// returns list of goroutines that become runnable
+G*
+runtime·netpoll(bool block)
+{
+ EpollEvent events[128], *ev;
+ int32 n, i, waitms, mode;
+ G *gp;
+
+ if(epfd == -1)
+ return nil;
+ waitms = -1;
+ if(!block)
+ waitms = 0;
+retry:
+ n = runtime·epollwait(epfd, events, nelem(events), waitms);
+ if(n < 0) {
+ if(n != -EINTR)
+ runtime·printf("epollwait failed with %d\n", -n);
+ goto retry;
+ }
+ gp = nil;
+ for(i = 0; i < n; i++) {
+ ev = &events[i];
+ if(ev->events == 0)
+ continue;
+ mode = 0;
+ if(ev->events & (EPOLLIN|EPOLLRDHUP|EPOLLHUP|EPOLLERR))
+ mode += 'r';
+ if(ev->events & (EPOLLOUT|EPOLLHUP|EPOLLERR))
+ mode += 'w';
+ if(mode)
+ runtime·netpollready(&gp, (void*)ev->data, mode);
+ }
+ if(block && gp == nil)
+ goto retry;
+ return gp;
+}
diff --git a/src/pkg/runtime/netpoll_kqueue.c b/src/pkg/runtime/netpoll_kqueue.c
new file mode 100644
index 000000000..ad721e293
--- /dev/null
+++ b/src/pkg/runtime/netpoll_kqueue.c
@@ -0,0 +1,105 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+
+// Integrated network poller (kqueue-based implementation).
+
+int32 runtime·kqueue(void);
+int32 runtime·kevent(int32, Kevent*, int32, Kevent*, int32, Timespec*);
+void runtime·closeonexec(int32);
+
+static int32 kq = -1;
+
+void
+runtime·netpollinit(void)
+{
+ kq = runtime·kqueue();
+ if(kq < 0) {
+ runtime·printf("netpollinit: kqueue failed with %d\n", -kq);
+ runtime·throw("netpollinit: kqueue failed");
+ }
+ runtime·closeonexec(kq);
+}
+
+int32
+runtime·netpollopen(int32 fd, PollDesc *pd)
+{
+ Kevent ev[2];
+ int32 n;
+
+ // Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
+ // for the whole fd lifetime. The notifications are automatically unregistered
+ // when fd is closed.
+ ev[0].ident = fd;
+ ev[0].filter = EVFILT_READ;
+ ev[0].flags = EV_ADD|EV_RECEIPT|EV_CLEAR;
+ ev[0].fflags = 0;
+ ev[0].data = 0;
+ ev[0].udata = (byte*)pd;
+ ev[1] = ev[0];
+ ev[1].filter = EVFILT_WRITE;
+ n = runtime·kevent(kq, ev, 2, ev, 2, nil);
+ if(n < 0)
+ return -n;
+ if(n != 2 ||
+ (ev[0].flags&EV_ERROR) == 0 || ev[0].ident != fd || ev[0].filter != EVFILT_READ ||
+ (ev[1].flags&EV_ERROR) == 0 || ev[1].ident != fd || ev[1].filter != EVFILT_WRITE)
+ return EFAULT; // just to mark out from other errors
+ if(ev[0].data != 0)
+ return ev[0].data;
+ if(ev[1].data != 0)
+ return ev[1].data;
+ return 0;
+}
+
+int32
+runtime·netpollclose(int32 fd)
+{
+ // Don't need to unregister because calling close()
+ // on fd will remove any kevents that reference the descriptor.
+ USED(fd);
+ return 0;
+}
+
+// Polls for ready network connections.
+// Returns list of goroutines that become runnable.
+G*
+runtime·netpoll(bool block)
+{
+ Kevent events[64], *ev;
+ Timespec ts, *tp;
+ int32 n, i;
+ G *gp;
+
+ if(kq == -1)
+ return nil;
+ tp = nil;
+ if(!block) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ tp = &ts;
+ }
+ gp = nil;
+retry:
+ n = runtime·kevent(kq, nil, 0, events, nelem(events), tp);
+ if(n < 0) {
+ if(n != -EINTR)
+ runtime·printf("kqueue failed with %d\n", -n);
+ goto retry;
+ }
+ for(i = 0; i < n; i++) {
+ ev = &events[i];
+ if(ev->filter == EVFILT_READ)
+ runtime·netpollready(&gp, (PollDesc*)ev->udata, 'r');
+ if(ev->filter == EVFILT_WRITE)
+ runtime·netpollready(&gp, (PollDesc*)ev->udata, 'w');
+ }
+ if(block && gp == nil)
+ goto retry;
+ return gp;
+}
diff --git a/src/pkg/runtime/netpoll_stub.c b/src/pkg/runtime/netpoll_stub.c
new file mode 100644
index 000000000..39d19a4ce
--- /dev/null
+++ b/src/pkg/runtime/netpoll_stub.c
@@ -0,0 +1,18 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd netbsd openbsd plan9 windows
+
+#include "runtime.h"
+
+// Polls for ready network connections.
+// Returns list of goroutines that become runnable.
+G*
+runtime·netpoll(bool block)
+{
+ // Implementation for platforms that do not support
+ // integrated network poller.
+ USED(block);
+ return nil;
+}
diff --git a/src/pkg/runtime/thread_darwin.c b/src/pkg/runtime/os_darwin.c
index adb1ffe6a..6216e3a3c 100644
--- a/src/pkg/runtime/thread_darwin.c
+++ b/src/pkg/runtime/os_darwin.c
@@ -5,6 +5,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
+#include "signal_unix.h"
#include "stack.h"
extern SigTab runtime·sigtab[];
@@ -69,6 +70,22 @@ runtime·osinit(void)
}
void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ static byte urandom_data[HashRandomBytes];
+ int32 fd;
+ fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
+ if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
+ *rnd = urandom_data;
+ *rnd_len = HashRandomBytes;
+ } else {
+ *rnd = nil;
+ *rnd_len = 0;
+ }
+ runtime·close(fd);
+}
+
+void
runtime·goenvs(void)
{
runtime·goenvs_unix();
@@ -392,9 +409,14 @@ int32
runtime·mach_semacquire(uint32 sem, int64 ns)
{
int32 r;
+ int64 secs;
if(ns >= 0) {
- r = runtime·mach_semaphore_timedwait(sem, ns/1000000000LL, ns%1000000000LL);
+ secs = ns/1000000000LL;
+ // Avoid overflow
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ r = runtime·mach_semaphore_timedwait(sem, secs, ns%1000000000LL);
if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT)
return -1;
if(r != 0)
@@ -530,3 +552,41 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
+
+void
+runtime·setsig(int32 i, GoSighandler *fn, bool restart)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask = ~(uintptr)0;
+ sa.sa_tramp = (void*)runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
+ *(uintptr*)sa.__sigaction_u = (uintptr)fn;
+ runtime·sigaction(i, &sa, nil);
+}
+
+GoSighandler*
+runtime·getsig(int32 i)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ runtime·sigaction(i, nil, &sa);
+ return *(void**)sa.__sigaction_u;
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+ StackT st;
+
+ st.ss_sp = (void*)p;
+ st.ss_size = n;
+ st.ss_flags = 0;
+ if(p == nil)
+ st.ss_flags = SS_DISABLE;
+ runtime·sigaltstack(&st, nil);
+}
diff --git a/src/pkg/runtime/os_darwin.h b/src/pkg/runtime/os_darwin.h
index 5fcb717cb..802410975 100644
--- a/src/pkg/runtime/os_darwin.h
+++ b/src/pkg/runtime/os_darwin.h
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-#define SIGHUP 1
#define SS_DISABLE 4
int32 runtime·bsdthread_create(void*, M*, G*, void(*)(void));
@@ -27,8 +24,6 @@ void runtime·sigprocmask(int32, Sigset*, Sigset*);
struct Sigaction;
void runtime·sigaction(uintptr, struct Sigaction*, struct Sigaction*);
-void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
-void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
struct StackT;
void runtime·sigaltstack(struct StackT*, struct StackT*);
@@ -36,7 +31,6 @@ void runtime·sigtramp(void);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
-void runtime·raisesigpipe(void);
#define NSIG 32
#define SI_USER 0 /* empirically true, but not what headers say */
diff --git a/src/pkg/runtime/thread_freebsd.c b/src/pkg/runtime/os_freebsd.c
index 3ae14ee0a..68c0f4750 100644
--- a/src/pkg/runtime/thread_freebsd.c
+++ b/src/pkg/runtime/os_freebsd.c
@@ -1,9 +1,11 @@
-// Use of this source file is governed by a BSD-style
-// license that can be found in the LICENSE file.`
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
+#include "signal_unix.h"
#include "stack.h"
extern SigTab runtime·sigtab[];
@@ -44,11 +46,16 @@ runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
{
int32 ret;
Timespec ts, *tsp;
+ int64 secs;
if(ns < 0)
tsp = nil;
else {
- ts.tv_sec = ns / 1000000000LL;
+ secs = ns / 1000000000LL;
+ // Avoid overflow
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ ts.tv_sec = secs;
ts.tv_nsec = ns % 1000000000LL;
tsp = &ts;
}
@@ -116,6 +123,22 @@ runtime·osinit(void)
}
void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ static byte urandom_data[HashRandomBytes];
+ int32 fd;
+ fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
+ if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
+ *rnd = urandom_data;
+ *rnd_len = HashRandomBytes;
+ } else {
+ *rnd = nil;
+ *rnd_len = 0;
+ }
+ runtime·close(fd);
+}
+
+void
runtime·goenvs(void)
{
runtime·goenvs_unix();
@@ -241,3 +264,58 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+ union {
+ void (*__sa_handler)(int32);
+ void (*__sa_sigaction)(int32, Siginfo*, void *);
+ } __sigaction_u; /* signal handler */
+ int32 sa_flags; /* see signal options below */
+ Sigset sa_mask; /* signal mask to apply */
+} Sigaction;
+
+void
+runtime·setsig(int32 i, GoSighandler *fn, bool restart)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask.__bits[0] = ~(uint32)0;
+ sa.sa_mask.__bits[1] = ~(uint32)0;
+ sa.sa_mask.__bits[2] = ~(uint32)0;
+ sa.sa_mask.__bits[3] = ~(uint32)0;
+ if(fn == runtime·sighandler)
+ fn = (void*)runtime·sigtramp;
+ sa.__sigaction_u.__sa_sigaction = (void*)fn;
+ runtime·sigaction(i, &sa, nil);
+}
+
+GoSighandler*
+runtime·getsig(int32 i)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ runtime·sigaction(i, nil, &sa);
+ if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp)
+ return runtime·sighandler;
+ return (void*)sa.__sigaction_u.__sa_sigaction;
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+ StackT st;
+
+ st.ss_sp = (void*)p;
+ st.ss_size = n;
+ st.ss_flags = 0;
+ if(p == nil)
+ st.ss_flags = SS_DISABLE;
+ runtime·sigaltstack(&st, nil);
+}
diff --git a/src/pkg/runtime/os_freebsd.h b/src/pkg/runtime/os_freebsd.h
index a37ad7cd8..e9be1362c 100644
--- a/src/pkg/runtime/os_freebsd.h
+++ b/src/pkg/runtime/os_freebsd.h
@@ -1,20 +1,18 @@
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-#define SIGHUP 1
+// 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.
+
#define SS_DISABLE 4
int32 runtime·thr_new(ThrParam*, int32);
-void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·sigpanic(void);
void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
struct sigaction;
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigprocmask(Sigset *, Sigset *);
-void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
-void runtime·raisesigpipe(void);
#define NSIG 33
#define SI_USER 0x10001
diff --git a/src/pkg/runtime/os_freebsd_arm.c b/src/pkg/runtime/os_freebsd_arm.c
new file mode 100644
index 000000000..7eaa45c44
--- /dev/null
+++ b/src/pkg/runtime/os_freebsd_arm.c
@@ -0,0 +1,23 @@
+// 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 "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+void
+runtime·checkgoarm(void)
+{
+ // TODO(minux)
+}
+
+#pragma textflag 7
+int64
+runtime·cputicks(void)
+{
+ // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+ // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+ // TODO: need more entropy to better seed fastrand1.
+ return runtime·nanotime();
+}
diff --git a/src/pkg/runtime/thread_linux.c b/src/pkg/runtime/os_linux.c
index 78ddef878..e4ae1a5d8 100644
--- a/src/pkg/runtime/thread_linux.c
+++ b/src/pkg/runtime/os_linux.c
@@ -5,14 +5,11 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
+#include "signal_unix.h"
#include "stack.h"
extern SigTab runtime·sigtab[];
-int32 runtime·open(uint8*, int32, int32);
-int32 runtime·close(int32);
-int32 runtime·read(int32, void*, int32);
-
static Sigset sigset_none;
static Sigset sigset_all = { ~(uint32)0, ~(uint32)0 };
@@ -29,9 +26,6 @@ enum
{
FUTEX_WAIT = 0,
FUTEX_WAKE = 1,
-
- EINTR = 4,
- EAGAIN = 11,
};
// Atomically,
@@ -42,15 +36,17 @@ void
runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
{
Timespec ts, *tsp;
+ int64 secs;
if(ns < 0)
tsp = nil;
else {
- ts.tv_sec = ns/1000000000LL;
- ts.tv_nsec = ns%1000000000LL;
+ secs = ns/1000000000LL;
// Avoid overflow
- if(ts.tv_sec > 1<<30)
- ts.tv_sec = 1<<30;
+ if(secs > 1LL<<30)
+ secs = 1LL<<30;
+ ts.tv_sec = secs;
+ ts.tv_nsec = ns%1000000000LL;
tsp = &ts;
}
@@ -164,6 +160,32 @@ runtime·osinit(void)
runtime·ncpu = getproccount();
}
+// Random bytes initialized at startup. These come
+// from the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.c).
+byte* runtime·startup_random_data;
+uint32 runtime·startup_random_data_len;
+
+void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ if(runtime·startup_random_data != nil) {
+ *rnd = runtime·startup_random_data;
+ *rnd_len = runtime·startup_random_data_len;
+ } else {
+ static byte urandom_data[HashRandomBytes];
+ int32 fd;
+ fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
+ if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
+ *rnd = urandom_data;
+ *rnd_len = HashRandomBytes;
+ } else {
+ *rnd = nil;
+ *rnd_len = 0;
+ }
+ runtime·close(fd);
+ }
+}
+
void
runtime·goenvs(void)
{
@@ -203,8 +225,8 @@ runtime·sigpanic(void)
if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
if(g->sigpc == 0)
runtime·panicstring("call of nil func value");
- }
runtime·panicstring("invalid memory address or nil pointer dereference");
+ }
runtime·printf("unexpected fault address %p\n", g->sigcode1);
runtime·throw("fault");
case SIGSEGV:
@@ -290,3 +312,60 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
+
+#ifdef GOARCH_386
+#define sa_handler k_sa_handler
+#endif
+
+/*
+ * This assembler routine takes the args from registers, puts them on the stack,
+ * and calls sighandler().
+ */
+extern void runtime·sigtramp(void);
+extern void runtime·sigreturn(void); // calls runtime·sigreturn
+
+void
+runtime·setsig(int32 i, GoSighandler *fn, bool restart)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask = ~0ULL;
+ // TODO(adonovan): Linux manpage says "sa_restorer element is
+ // obsolete and should not be used". Avoid it here, and test.
+ sa.sa_restorer = (void*)runtime·sigreturn;
+ if(fn == runtime·sighandler)
+ fn = (void*)runtime·sigtramp;
+ sa.sa_handler = fn;
+ if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
+ runtime·throw("rt_sigaction failure");
+}
+
+GoSighandler*
+runtime·getsig(int32 i)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
+ runtime·throw("rt_sigaction read failure");
+ if((void*)sa.sa_handler == runtime·sigtramp)
+ return runtime·sighandler;
+ return (void*)sa.sa_handler;
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+ Sigaltstack st;
+
+ st.ss_sp = p;
+ st.ss_size = n;
+ st.ss_flags = 0;
+ if(p == nil)
+ st.ss_flags = SS_DISABLE;
+ runtime·sigaltstack(&st, nil);
+}
diff --git a/src/pkg/runtime/os_linux.h b/src/pkg/runtime/os_linux.h
index a23fe0f73..b2d3f6f2a 100644
--- a/src/pkg/runtime/os_linux.h
+++ b/src/pkg/runtime/os_linux.h
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-#define SIGHUP 1
#define SS_DISABLE 2
// Linux-specific system calls
@@ -13,14 +10,11 @@ int32 runtime·clone(int32, void*, M*, G*, void(*)(void));
struct Sigaction;
int32 runtime·rt_sigaction(uintptr, struct Sigaction*, void*, uintptr);
-void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
-void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
-void runtime·raisesigpipe(void);
#define NSIG 65
#define SI_USER 0
diff --git a/src/pkg/runtime/os_linux_386.c b/src/pkg/runtime/os_linux_386.c
new file mode 100644
index 000000000..18becb6e6
--- /dev/null
+++ b/src/pkg/runtime/os_linux_386.c
@@ -0,0 +1,37 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+#define AT_NULL 0
+#define AT_RANDOM 25
+#define AT_SYSINFO 32
+extern uint32 runtime·_vdso;
+
+#pragma textflag 7
+void
+runtime·linux_setup_vdso(int32 argc, byte **argv)
+{
+ byte **envp;
+ uint32 *auxv;
+
+ // skip envp to get to ELF auxiliary vector.
+ for(envp = &argv[argc+1]; *envp != nil; envp++)
+ ;
+ envp++;
+
+ for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
+ if(auxv[0] == AT_SYSINFO) {
+ runtime·_vdso = auxv[1];
+ continue;
+ }
+ if(auxv[0] == AT_RANDOM) {
+ runtime·startup_random_data = (byte*)auxv[1];
+ runtime·startup_random_data_len = 16;
+ continue;
+ }
+ }
+}
diff --git a/src/pkg/runtime/os_linux_arm.c b/src/pkg/runtime/os_linux_arm.c
new file mode 100644
index 000000000..dd0fa9415
--- /dev/null
+++ b/src/pkg/runtime/os_linux_arm.c
@@ -0,0 +1,82 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+#define AT_NULL 0
+#define AT_PLATFORM 15 // introduced in at least 2.6.11
+#define AT_HWCAP 16 // introduced in at least 2.6.11
+#define AT_RANDOM 25 // introduced in 2.6.29
+#define HWCAP_VFP (1 << 6) // introduced in at least 2.6.11
+#define HWCAP_VFPv3 (1 << 13) // introduced in 2.6.30
+static uint32 runtime·randomNumber;
+uint8 runtime·armArch = 6; // we default to ARMv6
+uint32 runtime·hwcap; // set by setup_auxv
+uint8 runtime·goarm; // set by 5l
+
+void
+runtime·checkgoarm(void)
+{
+ if(runtime·goarm > 5 && !(runtime·hwcap & HWCAP_VFP)) {
+ runtime·printf("runtime: this CPU has no floating point hardware, so it cannot run\n");
+ runtime·printf("this GOARM=%d binary. Recompile using GOARM=5.\n", runtime·goarm);
+ runtime·exit(1);
+ }
+ if(runtime·goarm > 6 && !(runtime·hwcap & HWCAP_VFPv3)) {
+ runtime·printf("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n");
+ runtime·printf("this GOARM=%d binary. Recompile using GOARM=6.\n", runtime·goarm);
+ runtime·exit(1);
+ }
+}
+
+#pragma textflag 7
+void
+runtime·setup_auxv(int32 argc, void *argv_list)
+{
+ byte **argv;
+ byte **envp;
+ byte *rnd;
+ uint32 *auxv;
+ uint32 t;
+
+ argv = &argv_list;
+
+ // skip envp to get to ELF auxiliary vector.
+ for(envp = &argv[argc+1]; *envp != nil; envp++)
+ ;
+ envp++;
+
+ for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
+ switch(auxv[0]) {
+ case AT_RANDOM: // kernel provided 16-byte worth of random data
+ if(auxv[1]) {
+ rnd = (byte*)auxv[1];
+ runtime·randomNumber = rnd[4] | rnd[5]<<8 | rnd[6]<<16 | rnd[7]<<24;
+ }
+ break;
+ case AT_PLATFORM: // v5l, v6l, v7l
+ if(auxv[1]) {
+ t = *(uint8*)(auxv[1]+1);
+ if(t >= '5' && t <= '7')
+ runtime·armArch = t - '0';
+ }
+ break;
+ case AT_HWCAP: // CPU capability bit flags
+ runtime·hwcap = auxv[1];
+ break;
+ }
+ }
+}
+
+#pragma textflag 7
+int64
+runtime·cputicks(void)
+{
+ // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+ // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+ // runtime·randomNumber provides better seeding of fastrand1.
+ return runtime·nanotime() + runtime·randomNumber;
+}
diff --git a/src/pkg/runtime/thread_netbsd.c b/src/pkg/runtime/os_netbsd.c
index f333c6dd8..936334cac 100644
--- a/src/pkg/runtime/thread_netbsd.c
+++ b/src/pkg/runtime/os_netbsd.c
@@ -1,9 +1,11 @@
-// Use of this source file is governed by a BSD-style
-// license that can be found in the LICENSE file.`
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
+#include "signal_unix.h"
#include "stack.h"
enum
@@ -181,6 +183,22 @@ runtime·osinit(void)
}
void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ static byte urandom_data[HashRandomBytes];
+ int32 fd;
+ fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
+ if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
+ *rnd = urandom_data;
+ *rnd_len = HashRandomBytes;
+ } else {
+ *rnd = nil;
+ *rnd_len = 0;
+ }
+ runtime·close(fd);
+}
+
+void
runtime·goenvs(void)
{
runtime·goenvs_unix();
@@ -286,3 +304,58 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+ union {
+ void (*_sa_handler)(int32);
+ void (*_sa_sigaction)(int32, Siginfo*, void *);
+ } _sa_u; /* signal handler */
+ uint32 sa_mask[4]; /* signal mask to apply */
+ int32 sa_flags; /* see signal options below */
+} Sigaction;
+
+void
+runtime·setsig(int32 i, GoSighandler *fn, bool restart)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask[0] = ~0U;
+ sa.sa_mask[1] = ~0U;
+ sa.sa_mask[2] = ~0U;
+ sa.sa_mask[3] = ~0U;
+ if (fn == runtime·sighandler)
+ fn = (void*)runtime·sigtramp;
+ sa._sa_u._sa_sigaction = (void*)fn;
+ runtime·sigaction(i, &sa, nil);
+}
+
+GoSighandler*
+runtime·getsig(int32 i)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ runtime·sigaction(i, nil, &sa);
+ if((void*)sa._sa_u._sa_sigaction == runtime·sigtramp)
+ return runtime·sighandler;
+ return (void*)sa._sa_u._sa_sigaction;
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+ StackT st;
+
+ st.ss_sp = (void*)p;
+ st.ss_size = n;
+ st.ss_flags = 0;
+ if(p == nil)
+ st.ss_flags = SS_DISABLE;
+ runtime·sigaltstack(&st, nil);
+}
diff --git a/src/pkg/runtime/os_netbsd.h b/src/pkg/runtime/os_netbsd.h
index 19d72fd25..c193ae0b4 100644
--- a/src/pkg/runtime/os_netbsd.h
+++ b/src/pkg/runtime/os_netbsd.h
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-#define SIGHUP 1
#define SS_DISABLE 4
#define SIG_BLOCK 1
@@ -13,9 +10,6 @@
struct sigaction;
-void runtime·raisesigpipe(void);
-void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
-void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
@@ -23,6 +17,7 @@ void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
void runtime·sigprocmask(int32, Sigset*, Sigset*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+extern void runtime·lwp_tramp(void);
#define NSIG 33
#define SI_USER 0
diff --git a/src/pkg/runtime/os_netbsd_386.c b/src/pkg/runtime/os_netbsd_386.c
new file mode 100644
index 000000000..23e9db3c1
--- /dev/null
+++ b/src/pkg/runtime/os_netbsd_386.c
@@ -0,0 +1,17 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+void
+runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
+{
+ mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp;
+ mc->__gregs[REG_UESP] = (uint32)stack;
+ mc->__gregs[REG_EBX] = (uint32)mp;
+ mc->__gregs[REG_EDX] = (uint32)gp;
+ mc->__gregs[REG_ESI] = (uint32)fn;
+}
diff --git a/src/pkg/runtime/os_netbsd_amd64.c b/src/pkg/runtime/os_netbsd_amd64.c
new file mode 100644
index 000000000..226846cbb
--- /dev/null
+++ b/src/pkg/runtime/os_netbsd_amd64.c
@@ -0,0 +1,18 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+void
+runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
+{
+ // Machine dependent mcontext initialisation for LWP.
+ mc->__gregs[REG_RIP] = (uint64)runtime·lwp_tramp;
+ mc->__gregs[REG_RSP] = (uint64)stack;
+ mc->__gregs[REG_R8] = (uint64)mp;
+ mc->__gregs[REG_R9] = (uint64)gp;
+ mc->__gregs[REG_R12] = (uint64)fn;
+}
diff --git a/src/pkg/runtime/os_netbsd_arm.c b/src/pkg/runtime/os_netbsd_arm.c
new file mode 100644
index 000000000..385e6406d
--- /dev/null
+++ b/src/pkg/runtime/os_netbsd_arm.c
@@ -0,0 +1,33 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signal_GOOS_GOARCH.h"
+
+void
+runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
+{
+ mc->__gregs[REG_R15] = (uint32)runtime·lwp_tramp;
+ mc->__gregs[REG_R13] = (uint32)stack;
+ mc->__gregs[REG_R0] = (uint32)mp;
+ mc->__gregs[REG_R1] = (uint32)gp;
+ mc->__gregs[REG_R2] = (uint32)fn;
+}
+
+void
+runtime·checkgoarm(void)
+{
+ // TODO(minux)
+}
+
+#pragma textflag 7
+int64
+runtime·cputicks() {
+ // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+ // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+ // TODO: need more entropy to better seed fastrand1.
+ return runtime·nanotime();
+}
diff --git a/src/pkg/runtime/thread_openbsd.c b/src/pkg/runtime/os_openbsd.c
index 700c48147..4ce64f9f2 100644
--- a/src/pkg/runtime/thread_openbsd.c
+++ b/src/pkg/runtime/os_openbsd.c
@@ -1,9 +1,11 @@
-// Use of this source file is governed by a BSD-style
-// license that can be found in the LICENSE file.`
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
+#include "signal_unix.h"
#include "stack.h"
enum
@@ -61,6 +63,7 @@ int32
runtime·semasleep(int64 ns)
{
Timespec ts;
+ int64 secs;
// spin-mutex lock
while(runtime·xchg(&m->waitsemalock, 1))
@@ -75,7 +78,11 @@ runtime·semasleep(int64 ns)
runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock, nil);
else {
ns += runtime·nanotime();
- ts.tv_sec = ns/1000000000LL;
+ secs = ns/1000000000LL;
+ // Avoid overflow
+ if(secs >= 1LL<<31)
+ secs = (1LL<<31) - 1;
+ ts.tv_sec = secs;
ts.tv_nsec = ns%1000000000LL;
runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock, nil);
}
@@ -160,6 +167,22 @@ runtime·osinit(void)
}
void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ static byte urandom_data[HashRandomBytes];
+ int32 fd;
+ fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
+ if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
+ *rnd = urandom_data;
+ *rnd_len = HashRandomBytes;
+ } else {
+ *rnd = nil;
+ *rnd_len = 0;
+ }
+ runtime·close(fd);
+}
+
+void
runtime·goenvs(void)
{
runtime·goenvs_unix();
@@ -263,3 +286,55 @@ runtime·badsignal(int32 sig)
runtime·write(2, "\n", 1);
runtime·exit(1);
}
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+ union {
+ void (*__sa_handler)(int32);
+ void (*__sa_sigaction)(int32, Siginfo*, void *);
+ } __sigaction_u; /* signal handler */
+ uint32 sa_mask; /* signal mask to apply */
+ int32 sa_flags; /* see signal options below */
+} Sigaction;
+
+void
+runtime·setsig(int32 i, GoSighandler *fn, bool restart)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask = ~0U;
+ if(fn == runtime·sighandler)
+ fn = (void*)runtime·sigtramp;
+ sa.__sigaction_u.__sa_sigaction = (void*)fn;
+ runtime·sigaction(i, &sa, nil);
+}
+
+GoSighandler*
+runtime·getsig(int32 i)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ runtime·sigaction(i, nil, &sa);
+ if((void*)sa.__sigaction_u.__sa_sigaction == runtime·sigtramp)
+ return runtime·sighandler;
+ return (void*)sa.__sigaction_u.__sa_sigaction;
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+ StackT st;
+
+ st.ss_sp = (void*)p;
+ st.ss_size = n;
+ st.ss_flags = 0;
+ if(p == nil)
+ st.ss_flags = SS_DISABLE;
+ runtime·sigaltstack(&st, nil);
+}
diff --git a/src/pkg/runtime/os_openbsd.h b/src/pkg/runtime/os_openbsd.h
index a599aad05..dbfa4b69f 100644
--- a/src/pkg/runtime/os_openbsd.h
+++ b/src/pkg/runtime/os_openbsd.h
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#define SIG_DFL ((void*)0)
-#define SIG_IGN ((void*)1)
-#define SIGHUP 1
#define SS_DISABLE 4
#define SIG_BLOCK 1
@@ -13,14 +10,11 @@
struct sigaction;
-void runtime·raisesigpipe(void);
-void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
-void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
Sigset runtime·sigprocmask(int32, Sigset);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
diff --git a/src/pkg/runtime/thread_plan9.c b/src/pkg/runtime/os_plan9.c
index 7f94623e7..c7ed59fc9 100644
--- a/src/pkg/runtime/thread_plan9.c
+++ b/src/pkg/runtime/os_plan9.c
@@ -19,6 +19,10 @@ runtime·mpreinit(M *mp)
// Initialize stack and goroutine for note handling.
mp->gsignal = runtime·malg(32*1024);
mp->notesig = (int8*)runtime·malloc(ERRMAX*sizeof(int8));
+
+ // Initialize stack for handling strings from the
+ // errstr system call, as used in package syscall.
+ mp->errstr = (byte*)runtime·malloc(ERRMAX*sizeof(byte));
}
// Called to initialize a new m (including the bootstrap m).
@@ -44,7 +48,7 @@ getproccount(void)
int32 fd, i, n, ncpu;
byte buf[2048];
- fd = runtime·open((byte*)"/dev/sysstat", OREAD);
+ fd = runtime·open("/dev/sysstat", OREAD, 0);
if(fd < 0)
return 1;
ncpu = 0;
@@ -68,7 +72,7 @@ getpid(void)
int32 fd;
runtime·memclr(b, sizeof(b));
- fd = runtime·open((byte*)"#c/pid", 0);
+ fd = runtime·open("#c/pid", 0, 0);
if(fd >= 0) {
runtime·read(fd, b, sizeof(b));
runtime·close(fd);
@@ -88,6 +92,20 @@ runtime·osinit(void)
}
void
+runtime·crash(void)
+{
+ runtime·notify(nil);
+ *(int32*)0 = 0;
+}
+
+void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ *rnd = nil;
+ *rnd_len = 0;
+}
+
+void
runtime·goenvs(void)
{
}
@@ -191,7 +209,7 @@ runtime·postnote(int32 pid, int8* msg)
p--;
runtime·memmove((void*)p, (void*)"/note", 5);
- fd = runtime·open(buf, OWRITE);
+ fd = runtime·open((int8*)buf, OWRITE, 0);
if(fd < 0)
return -1;
diff --git a/src/pkg/runtime/os_plan9.h b/src/pkg/runtime/os_plan9.h
index c2cdf5b44..f0474cda5 100644
--- a/src/pkg/runtime/os_plan9.h
+++ b/src/pkg/runtime/os_plan9.h
@@ -3,12 +3,9 @@
// license that can be found in the LICENSE file.
// Plan 9-specific system calls
-int32 runtime·open(uint8 *file, int32 mode);
int32 runtime·pread(int32 fd, void *buf, int32 nbytes, int64 offset);
int32 runtime·pwrite(int32 fd, void *buf, int32 nbytes, int64 offset);
-int32 runtime·read(int32 fd, void *buf, int32 nbytes);
int64 runtime·seek(int32 fd, int64 offset, int32 whence);
-int32 runtime·close(int32 fd);
void runtime·exits(int8* msg);
intptr runtime·brk_(void*);
int32 runtime·sleep(int32 ms);
@@ -19,7 +16,6 @@ int32 runtime·plan9_semrelease(uint32 *addr, int32 count);
int32 runtime·notify(void (*fn)(void*, int8*));
int32 runtime·noted(int32);
void runtime·sigtramp(void*, int8*);
-int32 runtime·sighandler(void*, int8*, G*);
void runtime·sigpanic(void);
void runtime·goexitsall(int8*);
void runtime·setfpmasks(void);
diff --git a/src/pkg/runtime/signal_plan9_386.c b/src/pkg/runtime/os_plan9_386.c
index 17bc11749..3396e44e7 100644
--- a/src/pkg/runtime/signal_plan9_386.c
+++ b/src/pkg/runtime/os_plan9_386.c
@@ -28,6 +28,7 @@ runtime·dumpregs(Ureg *u)
int32
runtime·sighandler(void *v, int8 *s, G *gp)
{
+ bool crash;
Ureg *ureg;
uintptr *sp;
SigTab *sig, *nsig;
@@ -93,11 +94,15 @@ Throw:
runtime·printf("PC=%X\n", ureg->pc);
runtime·printf("\n");
- if(runtime·gotraceback()) {
+ if(runtime·gotraceback(&crash)) {
runtime·traceback((void*)ureg->pc, (void*)ureg->sp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(ureg);
}
+
+ if(crash)
+ runtime·crash();
+
runtime·goexitsall("");
runtime·exits(s);
@@ -112,6 +117,12 @@ runtime·sigenable(uint32 sig)
}
void
+runtime·sigdisable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
runtime·resetcpuprofiler(int32 hz)
{
// TODO: Enable profiling interrupts.
diff --git a/src/pkg/runtime/signal_plan9_amd64.c b/src/pkg/runtime/os_plan9_amd64.c
index e4f946abc..cf0a82b6b 100644
--- a/src/pkg/runtime/signal_plan9_amd64.c
+++ b/src/pkg/runtime/os_plan9_amd64.c
@@ -36,6 +36,7 @@ runtime·dumpregs(Ureg *u)
int32
runtime·sighandler(void *v, int8 *s, G *gp)
{
+ bool crash;
Ureg *ureg;
uintptr *sp;
SigTab *sig, *nsig;
@@ -101,11 +102,15 @@ Throw:
runtime·printf("PC=%X\n", ureg->ip);
runtime·printf("\n");
- if(runtime·gotraceback()) {
+ if(runtime·gotraceback(&crash)) {
runtime·traceback((void*)ureg->ip, (void*)ureg->sp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(ureg);
}
+
+ if(crash)
+ runtime·crash();
+
runtime·goexitsall("");
runtime·exits(s);
@@ -119,6 +124,12 @@ runtime·sigenable(uint32 sig)
}
void
+runtime·sigdisable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
runtime·resetcpuprofiler(int32 hz)
{
// TODO: Enable profiling interrupts.
diff --git a/src/pkg/runtime/thread_windows.c b/src/pkg/runtime/os_windows.c
index ae4e82e50..b28affe31 100644
--- a/src/pkg/runtime/thread_windows.c
+++ b/src/pkg/runtime/os_windows.c
@@ -11,6 +11,9 @@
#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
#pragma dynimport runtime·CreateWaitableTimer CreateWaitableTimerA "kernel32.dll"
+#pragma dynimport runtime·CryptAcquireContextW CryptAcquireContextW "advapi32.dll"
+#pragma dynimport runtime·CryptGenRandom CryptGenRandom "advapi32.dll"
+#pragma dynimport runtime·CryptReleaseContext CryptReleaseContext "advapi32.dll"
#pragma dynimport runtime·DuplicateHandle DuplicateHandle "kernel32.dll"
#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll"
#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
@@ -31,11 +34,17 @@
#pragma dynimport runtime·timeBeginPeriod timeBeginPeriod "winmm.dll"
#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll"
+#pragma dynimport runtime·NtWaitForSingleObject NtWaitForSingleObject "ntdll.dll"
+
+extern void *runtime·NtWaitForSingleObject;
extern void *runtime·CloseHandle;
extern void *runtime·CreateEvent;
extern void *runtime·CreateThread;
extern void *runtime·CreateWaitableTimer;
+extern void *runtime·CryptAcquireContextW;
+extern void *runtime·CryptGenRandom;
+extern void *runtime·CryptReleaseContext;
extern void *runtime·DuplicateHandle;
extern void *runtime·ExitProcess;
extern void *runtime·FreeEnvironmentStringsW;
@@ -79,6 +88,24 @@ runtime·osinit(void)
}
void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ uintptr handle;
+ *rnd = nil;
+ *rnd_len = 0;
+ if(runtime·stdcall(runtime·CryptAcquireContextW, 5, &handle, nil, nil,
+ (uintptr)1 /* PROV_RSA_FULL */,
+ (uintptr)0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) {
+ static byte random_data[HashRandomBytes];
+ if(runtime·stdcall(runtime·CryptGenRandom, 3, handle, (uintptr)HashRandomBytes, random_data)) {
+ *rnd = random_data;
+ *rnd_len = HashRandomBytes;
+ }
+ runtime·stdcall(runtime·CryptReleaseContext, 2, handle, (uintptr)0);
+ }
+}
+
+void
runtime·goenvs(void)
{
extern Slice syscall·envs;
@@ -135,22 +162,6 @@ runtime·write(int32 fd, void *buf, int32 n)
return written;
}
-#pragma textflag 7
-void
-runtime·osyield(void)
-{
- runtime·stdcall(runtime·Sleep, 1, (uintptr)0);
-}
-
-void
-runtime·usleep(uint32 us)
-{
- us /= 1000;
- if(us == 0)
- us = 1;
- runtime·stdcall(runtime·Sleep, 1, (uintptr)us);
-}
-
#define INFINITE ((uintptr)0xFFFFFFFF)
int32
@@ -444,3 +455,16 @@ int32 runtime·badcallbacklen = sizeof runtime·badcallbackmsg - 1;
int8 runtime·badsignalmsg[] = "runtime: signal received on thread not created by Go.\n";
int32 runtime·badsignallen = sizeof runtime·badsignalmsg - 1;
+
+void
+runtime·crash(void)
+{
+ // TODO: This routine should do whatever is needed
+ // to make the Windows program abort/crash as it
+ // would if Go was not intercepting signals.
+ // On Unix the routine would remove the custom signal
+ // handler and then raise a signal (like SIGABRT).
+ // Something like that should happen here.
+ // It's okay to leave this empty for now: if crash returns
+ // the ordinary exit-after-panic happens.
+}
diff --git a/src/pkg/runtime/signal_windows_386.c b/src/pkg/runtime/os_windows_386.c
index d76d5bf4b..20fbea13d 100644
--- a/src/pkg/runtime/signal_windows_386.c
+++ b/src/pkg/runtime/os_windows_386.c
@@ -27,6 +27,7 @@ runtime·dumpregs(Context *r)
uint32
runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
{
+ bool crash;
uintptr *sp;
switch(info->ExceptionCode) {
@@ -74,11 +75,15 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
}
runtime·printf("\n");
- if(runtime·gotraceback()){
+ if(runtime·gotraceback(&crash)){
runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
}
+
+ if(crash)
+ runtime·crash();
+
runtime·exit(2);
return 0;
@@ -91,6 +96,12 @@ runtime·sigenable(uint32 sig)
}
void
+runtime·sigdisable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
runtime·dosigprof(Context *r, G *gp)
{
runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp);
diff --git a/src/pkg/runtime/signal_windows_amd64.c b/src/pkg/runtime/os_windows_amd64.c
index 3729aa57b..881c73c93 100644
--- a/src/pkg/runtime/signal_windows_amd64.c
+++ b/src/pkg/runtime/os_windows_amd64.c
@@ -35,6 +35,7 @@ runtime·dumpregs(Context *r)
uint32
runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
{
+ bool crash;
uintptr *sp;
switch(info->ExceptionCode) {
@@ -81,11 +82,14 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
}
runtime·printf("\n");
- if(runtime·gotraceback()){
+ if(runtime·gotraceback(&crash)){
runtime·traceback((void*)r->Rip, (void*)r->Rsp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
}
+
+ if(crash)
+ runtime·crash();
runtime·exit(2);
return 0;
@@ -98,6 +102,12 @@ runtime·sigenable(uint32 sig)
}
void
+runtime·sigdisable(uint32 sig)
+{
+ USED(sig);
+}
+
+void
runtime·dosigprof(Context *r, G *gp)
{
runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp);
diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c
index 2f553f417..d0cf3ad6f 100644
--- a/src/pkg/runtime/panic.c
+++ b/src/pkg/runtime/panic.c
@@ -5,6 +5,7 @@
#include "runtime.h"
#include "arch_GOARCH.h"
#include "stack.h"
+#include "malloc.h"
// Code related to defer, panic and recover.
@@ -383,7 +384,10 @@ nomatch:
void
runtime·startpanic(void)
{
- if(m->mcache == nil) // can happen if called from signal handler or throw
+ if(runtime·mheap == 0 || runtime·mheap->cachealloc.size == 0) { // very early
+ runtime·printf("runtime: panic before malloc heap initialized\n");
+ m->mallocing = 1; // tell rest of panic not to try to malloc
+ } else if(m->mcache == nil) // can happen if called from signal handler or throw
m->mcache = runtime·allocmcache();
if(m->dying) {
runtime·printf("panic during panic\n");
@@ -398,12 +402,13 @@ void
runtime·dopanic(int32 unused)
{
static bool didothers;
+ bool crash;
if(g->sig != 0)
runtime·printf("[signal %x code=%p addr=%p pc=%p]\n",
g->sig, g->sigcode0, g->sigcode1, g->sigpc);
- if(runtime·gotraceback()){
+ if(runtime·gotraceback(&crash)){
if(g != m->g0) {
runtime·printf("\n");
runtime·goroutineheader(g);
@@ -424,6 +429,9 @@ runtime·dopanic(int32 unused)
runtime·lock(&deadlock);
runtime·lock(&deadlock);
}
+
+ if(crash)
+ runtime·crash();
runtime·exit(2);
}
diff --git a/src/pkg/runtime/parfor.c b/src/pkg/runtime/parfor.c
index aa5537d02..a4468c2af 100644
--- a/src/pkg/runtime/parfor.c
+++ b/src/pkg/runtime/parfor.c
@@ -46,6 +46,7 @@ void
runtime·parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait, void (*body)(ParFor*, uint32))
{
uint32 i, begin, end;
+ uint64 *pos;
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);
@@ -67,7 +68,10 @@ runtime·parforsetup(ParFor *desc, uint32 nthr, uint32 n, void *ctx, bool wait,
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);
+ pos = &desc->thr[i].pos;
+ if(((uintptr)pos & 7) != 0)
+ runtime·throw("parforsetup: pos is not aligned");
+ *pos = (uint64)begin | (((uint64)end)<<32);
}
}
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 4ce0a718c..8d05730e4 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -49,6 +49,7 @@ struct Sched {
Note stopnote;
uint32 sysmonwait;
Note sysmonnote;
+ uint64 lastpoll;
int32 profilehz; // cpu profiling rate
};
@@ -71,8 +72,6 @@ M* runtime·extram;
int8* runtime·goos;
int32 runtime·ncpu;
static int32 newprocs;
-// Keep trace of scavenger's goroutine for deadlock detection.
-static G *scvg;
void runtime·mstart(void);
static void runqput(P*, G*);
@@ -109,6 +108,7 @@ static void globrunqput(G*);
static G* globrunqget(P*);
static P* pidleget(void);
static void pidleput(P*);
+static void injectglist(G*);
// The bootstrap sequence is:
//
@@ -137,6 +137,7 @@ runtime·schedinit(void)
// so that we don't need to call malloc when we crash.
// runtime·findfunc(0);
+ runtime·sched.lastpoll = runtime·nanotime();
procs = 1;
p = runtime·getenv("GOMAXPROCS");
if(p != nil && (n = runtime·atoi(p)) > 0) {
@@ -174,8 +175,7 @@ runtime·main(void)
runtime·lockOSThread();
if(m != &runtime·m0)
runtime·throw("runtime·main not on m0");
- scvg = runtime·newproc1(&scavenger, nil, 0, 0, runtime·main);
- scvg->issystem = true;
+ runtime·newproc1(&scavenger, nil, 0, 0, runtime·main);
main·init();
runtime·unlockOSThread();
@@ -232,7 +232,7 @@ runtime·tracebackothers(G *me)
G *gp;
int32 traceback;
- traceback = runtime·gotraceback();
+ traceback = runtime·gotraceback(nil);
for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
if(gp == me || gp->status == Gdead)
continue;
@@ -332,7 +332,7 @@ runtime·helpgc(int32 nproc)
mp = mget();
if(mp == nil)
runtime·throw("runtime·gcprocs inconsistency");
- mp->helpgc = 1;
+ mp->helpgc = n;
mp->mcache = runtime·allp[pos]->mcache;
pos++;
runtime·notewakeup(&mp->park);
@@ -386,16 +386,19 @@ runtime·stoptheworld(void)
static void
mhelpgc(void)
{
- m->helpgc = 1;
+ m->helpgc = -1;
}
void
runtime·starttheworld(void)
{
- P *p;
+ P *p, *p1;
M *mp;
+ G *gp;
bool add;
+ gp = runtime·netpoll(false); // non-blocking
+ injectglist(gp);
add = needaddgcproc();
runtime·lock(&runtime·sched);
if(newprocs) {
@@ -405,6 +408,7 @@ runtime·starttheworld(void)
procresize(runtime·gomaxprocs);
runtime·gcwaiting = 0;
+ p1 = nil;
while(p = pidleget()) {
// procresize() puts p's with work at the beginning of the list.
// Once we reach a p without a run queue, the rest don't have one either.
@@ -414,8 +418,9 @@ runtime·starttheworld(void)
}
mp = mget();
if(mp == nil) {
- pidleput(p);
- break;
+ p->link = p1;
+ p1 = p;
+ continue;
}
if(mp->nextp)
runtime·throw("starttheworld: inconsistent mp->nextp");
@@ -428,6 +433,13 @@ runtime·starttheworld(void)
}
runtime·unlock(&runtime·sched);
+ while(p1) {
+ p = p1;
+ p1 = p1->link;
+ add = false;
+ newm(nil, p);
+ }
+
if(add) {
// If GC could have used another helper proc, start one now,
// in the hope that it will be available next time.
@@ -473,7 +485,7 @@ runtime·mstart(void)
m->mstartfn();
if(m->helpgc) {
- m->helpgc = false;
+ m->helpgc = 0;
stopm();
} else if(m != &runtime·m0) {
acquirep(m->nextp);
@@ -782,8 +794,8 @@ retry:
runtime·notesleep(&m->park);
runtime·noteclear(&m->park);
if(m->helpgc) {
- m->helpgc = 0;
runtime·gchelper();
+ m->helpgc = 0;
m->mcache = nil;
goto retry;
}
@@ -970,7 +982,7 @@ execute(G *gp)
}
// Finds a runnable goroutine to execute.
-// Tries to steal from other P's and get g from global queue.
+// Tries to steal from other P's, get g from global queue, poll network.
static G*
findrunnable(void)
{
@@ -995,6 +1007,13 @@ top:
if(gp)
return gp;
}
+ // poll network
+ gp = runtime·netpoll(false); // non-blocking
+ if(gp) {
+ injectglist(gp->schedlink);
+ gp->status = Grunnable;
+ return gp;
+ }
// If number of spinning M's >= number of busy P's, block.
// This is necessary to prevent excessive CPU consumption
// when GOMAXPROCS>>1 but the program parallelism is low.
@@ -1049,10 +1068,54 @@ stop:
break;
}
}
+ // poll network
+ if(runtime·xchg64(&runtime·sched.lastpoll, 0) != 0) {
+ if(m->p)
+ runtime·throw("findrunnable: netpoll with p");
+ if(m->spinning)
+ runtime·throw("findrunnable: netpoll with spinning");
+ gp = runtime·netpoll(true); // block until new work is available
+ runtime·atomicstore64(&runtime·sched.lastpoll, runtime·nanotime());
+ if(gp) {
+ runtime·lock(&runtime·sched);
+ p = pidleget();
+ runtime·unlock(&runtime·sched);
+ if(p) {
+ acquirep(p);
+ injectglist(gp->schedlink);
+ gp->status = Grunnable;
+ return gp;
+ }
+ injectglist(gp);
+ }
+ }
stopm();
goto top;
}
+// Injects the list of runnable G's into the scheduler.
+// Can run concurrently with GC.
+static void
+injectglist(G *glist)
+{
+ int32 n;
+ G *gp;
+
+ if(glist == nil)
+ return;
+ runtime·lock(&runtime·sched);
+ for(n = 0; glist; n++) {
+ gp = glist;
+ glist = gp->schedlink;
+ gp->status = Grunnable;
+ globrunqput(gp);
+ }
+ runtime·unlock(&runtime·sched);
+
+ for(; n && runtime·sched.npidle; n--)
+ startm(nil, false);
+}
+
// One round of scheduler: find a runnable goroutine and execute it.
// Never returns.
static void
@@ -1164,6 +1227,11 @@ goexit0(G *gp)
gp->lockedm = nil;
m->curg = nil;
m->lockedg = nil;
+ if(m->locked & ~LockExternal) {
+ runtime·printf("invalid m->locked = %d", m->locked);
+ runtime·throw("internal lockOSThread error");
+ }
+ m->locked = 0;
runtime·unwindstack(gp, nil);
gfput(m->p, gp);
schedule();
@@ -1251,7 +1319,7 @@ void
p = releasep();
handoffp(p);
- if(g == scvg) // do not consider blocked scavenger for deadlock detection
+ if(g->isbackground) // do not consider blocked scavenger for deadlock detection
inclocked(1);
runtime·gosave(&g->sched); // re-save for traceback
}
@@ -1283,7 +1351,7 @@ runtime·exitsyscall(void)
return;
}
- if(g == scvg) // do not consider blocked scavenger for deadlock detection
+ if(g->isbackground) // do not consider blocked scavenger for deadlock detection
inclocked(-1);
// Try to get any other idle P.
m->p = nil;
@@ -1885,7 +1953,7 @@ checkdead(void)
}
grunning = 0;
for(gp = runtime·allg; gp; gp = gp->alllink) {
- if(gp == scvg)
+ if(gp->isbackground)
continue;
s = gp->status;
if(s == Gwaiting)
@@ -1905,6 +1973,8 @@ static void
sysmon(void)
{
uint32 idle, delay;
+ int64 now, lastpoll;
+ G *gp;
uint32 ticks[MaxGomaxprocs];
idle = 0; // how many cycles in succession we had not wokeup somebody
@@ -1929,6 +1999,14 @@ sysmon(void)
} else
runtime·unlock(&runtime·sched);
}
+ // poll network if not polled for more than 10ms
+ lastpoll = runtime·atomicload64(&runtime·sched.lastpoll);
+ now = runtime·nanotime();
+ if(lastpoll != 0 && lastpoll + 10*1000*1000 > now) {
+ gp = runtime·netpoll(false); // non-blocking
+ injectglist(gp);
+ }
+ // retake P's blocked in syscalls
if(retake(ticks))
idle = 0;
else
diff --git a/src/pkg/runtime/race/testdata/map_test.go b/src/pkg/runtime/race/testdata/map_test.go
index 6f86a50b7..35db8db69 100644
--- a/src/pkg/runtime/race/testdata/map_test.go
+++ b/src/pkg/runtime/race/testdata/map_test.go
@@ -94,8 +94,7 @@ func TestNoRaceMapRangeRange(t *testing.T) {
<-ch
}
-// Map len is not instrumented.
-func TestRaceFailingMapLen(t *testing.T) {
+func TestRaceMapLen(t *testing.T) {
m := make(map[string]bool)
ch := make(chan bool, 1)
go func() {
@@ -117,8 +116,7 @@ func TestRaceMapDelete(t *testing.T) {
<-ch
}
-// Map len is not instrumented.
-func TestRaceFailingMapLenDelete(t *testing.T) {
+func TestRaceMapLenDelete(t *testing.T) {
m := make(map[string]bool)
ch := make(chan bool, 1)
go func() {
diff --git a/src/pkg/runtime/race/testdata/mop_test.go b/src/pkg/runtime/race/testdata/mop_test.go
index f2daa3730..26cd3a4e4 100644
--- a/src/pkg/runtime/race/testdata/mop_test.go
+++ b/src/pkg/runtime/race/testdata/mop_test.go
@@ -306,6 +306,102 @@ func TestNoRacePlus(t *testing.T) {
<-ch
}
+func TestRaceComplement(t *testing.T) {
+ var x, y, z int
+ ch := make(chan int, 2)
+
+ go func() {
+ x = ^y
+ ch <- 1
+ }()
+ go func() {
+ y = ^z
+ ch <- 1
+ }()
+ <-ch
+ <-ch
+}
+
+func TestRaceDiv(t *testing.T) {
+ var x, y, z int
+ ch := make(chan int, 2)
+
+ go func() {
+ x = y / (z + 1)
+ ch <- 1
+ }()
+ go func() {
+ y = z
+ ch <- 1
+ }()
+ <-ch
+ <-ch
+}
+
+func TestRaceDivConst(t *testing.T) {
+ var x, y, z int
+ ch := make(chan int, 2)
+
+ go func() {
+ x = y / 3
+ ch <- 1
+ }()
+ go func() {
+ y = z
+ ch <- 1
+ }()
+ <-ch
+ <-ch
+}
+
+func TestRaceMod(t *testing.T) {
+ var x, y, z int
+ ch := make(chan int, 2)
+
+ go func() {
+ x = y % (z + 1)
+ ch <- 1
+ }()
+ go func() {
+ y = z
+ ch <- 1
+ }()
+ <-ch
+ <-ch
+}
+
+func TestRaceModConst(t *testing.T) {
+ var x, y, z int
+ ch := make(chan int, 2)
+
+ go func() {
+ x = y % 3
+ ch <- 1
+ }()
+ go func() {
+ y = z
+ ch <- 1
+ }()
+ <-ch
+ <-ch
+}
+
+func TestRaceRotate(t *testing.T) {
+ var x, y, z uint32
+ ch := make(chan int, 2)
+
+ go func() {
+ x = y<<12 | y>>20
+ ch <- 1
+ }()
+ go func() {
+ y = z
+ ch <- 1
+ }()
+ <-ch
+ <-ch
+}
+
// May crash if the instrumentation is reckless.
func TestNoRaceEnoughRegisters(t *testing.T) {
// from erf.go
diff --git a/src/pkg/runtime/race/testdata/regression_test.go b/src/pkg/runtime/race/testdata/regression_test.go
index afe8cc5ec..f08ee3ed3 100644
--- a/src/pkg/runtime/race/testdata/regression_test.go
+++ b/src/pkg/runtime/race/testdata/regression_test.go
@@ -45,6 +45,18 @@ func InstrumentMapLen3() {
_ = len(*m[0])
}
+func TestRaceUnaddressableMapLen(t *testing.T) {
+ m := make(map[int]map[int]int)
+ ch := make(chan int, 1)
+ m[0] = make(map[int]int)
+ go func() {
+ _ = len(m[0])
+ ch <- 0
+ }()
+ m[0][0] = 1
+ <-ch
+}
+
type Rect struct {
x, y int
}
diff --git a/src/pkg/runtime/race/testdata/slice_test.go b/src/pkg/runtime/race/testdata/slice_test.go
index 773463662..1fe051b12 100644
--- a/src/pkg/runtime/race/testdata/slice_test.go
+++ b/src/pkg/runtime/race/testdata/slice_test.go
@@ -463,3 +463,24 @@ func TestRaceSliceRuneToString(t *testing.T) {
s[9] = 42
<-c
}
+
+func TestRaceConcatString(t *testing.T) {
+ s := "hello"
+ c := make(chan string, 1)
+ go func() {
+ c <- s + " world"
+ }()
+ s = "world"
+ <-c
+}
+
+func TestRaceCompareString(t *testing.T) {
+ s1 := "hello"
+ s2 := "world"
+ c := make(chan bool, 1)
+ go func() {
+ c <- s1 == s2
+ }()
+ s1 = s2
+ <-c
+}
diff --git a/src/pkg/runtime/rt0_darwin_386.s b/src/pkg/runtime/rt0_darwin_386.s
index 30b497f5e..4b4c1f294 100644
--- a/src/pkg/runtime/rt0_darwin_386.s
+++ b/src/pkg/runtime/rt0_darwin_386.s
@@ -2,7 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Darwin and Linux use the same linkage to main
+TEXT _rt0_386_darwin(SB),7,$8
+ MOVL 8(SP), AX
+ LEAL 12(SP), BX
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ CALL main(SB)
+ INT $3
-TEXT _rt0_386_darwin(SB),7,$0
+TEXT main(SB),7,$0
JMP _rt0_386(SB)
diff --git a/src/pkg/runtime/rt0_darwin_amd64.s b/src/pkg/runtime/rt0_darwin_amd64.s
index 4cfab5876..45e69a015 100644
--- a/src/pkg/runtime/rt0_darwin_amd64.s
+++ b/src/pkg/runtime/rt0_darwin_amd64.s
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Darwin and Linux use the same linkage to main
-
TEXT _rt0_amd64_darwin(SB),7,$-8
+ LEAQ 8(SP), SI // argv
+ MOVQ 0(SP), DI // argc
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT main(SB),7,$-8
MOVQ $_rt0_amd64(SB), AX
- MOVQ SP, DI
JMP AX
diff --git a/src/pkg/runtime/rt0_freebsd_386.s b/src/pkg/runtime/rt0_freebsd_386.s
index 3ca981b3a..c84482cdb 100644
--- a/src/pkg/runtime/rt0_freebsd_386.s
+++ b/src/pkg/runtime/rt0_freebsd_386.s
@@ -2,8 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Darwin and Linux use the same linkage to main
+TEXT _rt0_386_freebsd(SB),7,$8
+ MOVL 8(SP), AX
+ LEAL 12(SP), BX
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ CALL main(SB)
+ INT $3
-TEXT _rt0_386_freebsd(SB),7,$0
+TEXT main(SB),7,$0
JMP _rt0_386(SB)
-
diff --git a/src/pkg/runtime/rt0_freebsd_amd64.s b/src/pkg/runtime/rt0_freebsd_amd64.s
index 5d2eeeeff..e6c6fb9ca 100644
--- a/src/pkg/runtime/rt0_freebsd_amd64.s
+++ b/src/pkg/runtime/rt0_freebsd_amd64.s
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Darwin and Linux use the same linkage to main
-
TEXT _rt0_amd64_freebsd(SB),7,$-8
- MOVQ $_rt0_amd64(SB), DX
- JMP DX
+ LEAQ 8(DI), SI // argv
+ MOVQ 0(DI), DI // argc
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT main(SB),7,$-8
+ MOVQ $_rt0_amd64(SB), AX
+ JMP AX
diff --git a/src/pkg/runtime/rt0_linux_386.s b/src/pkg/runtime/rt0_linux_386.s
index 83149540e..73cca5d98 100644
--- a/src/pkg/runtime/rt0_linux_386.s
+++ b/src/pkg/runtime/rt0_linux_386.s
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Darwin and Linux use the same linkage to main
-
-TEXT _rt0_386_linux(SB),7,$0
+TEXT _rt0_386_linux(SB),7,$8
+ MOVL 8(SP), AX
+ LEAL 12(SP), BX
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
CALL runtime·linux_setup_vdso(SB)
- JMP _rt0_386(SB)
+ CALL main(SB)
+ INT $3
+
+TEXT main(SB),7,$0
+ JMP _rt0_386(SB)
TEXT _fallback_vdso(SB),7,$0
INT $0x80
diff --git a/src/pkg/runtime/rt0_linux_amd64.s b/src/pkg/runtime/rt0_linux_amd64.s
index dac9ae181..dfc9c0421 100644
--- a/src/pkg/runtime/rt0_linux_amd64.s
+++ b/src/pkg/runtime/rt0_linux_amd64.s
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Darwin and Linux use the same linkage to main
-
TEXT _rt0_amd64_linux(SB),7,$-8
+ LEAQ 8(SP), SI // argv
+ MOVQ 0(SP), DI // argc
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT main(SB),7,$-8
MOVQ $_rt0_amd64(SB), AX
- MOVQ SP, DI
JMP AX
diff --git a/src/pkg/runtime/rt0_netbsd_386.s b/src/pkg/runtime/rt0_netbsd_386.s
index 829e4133b..b4c029c53 100644
--- a/src/pkg/runtime/rt0_netbsd_386.s
+++ b/src/pkg/runtime/rt0_netbsd_386.s
@@ -2,5 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-TEXT _rt0_386_netbsd(SB),7,$0
- JMP _rt0_386(SB)
+TEXT _rt0_386_netbsd(SB),7,$8
+ MOVL 8(SP), AX
+ LEAL 12(SP), BX
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ CALL main(SB)
+ INT $3
+
+TEXT main(SB),7,$0
+ JMP _rt0_386(SB)
diff --git a/src/pkg/runtime/rt0_netbsd_amd64.s b/src/pkg/runtime/rt0_netbsd_amd64.s
index 85482b98d..9e7b78edc 100644
--- a/src/pkg/runtime/rt0_netbsd_amd64.s
+++ b/src/pkg/runtime/rt0_netbsd_amd64.s
@@ -3,6 +3,11 @@
// license that can be found in the LICENSE file.
TEXT _rt0_amd64_netbsd(SB),7,$-8
- MOVQ $_rt0_amd64(SB), DX
- MOVQ SP, DI
- JMP DX
+ LEAQ 8(SP), SI // argv
+ MOVQ 0(SP), DI // argc
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT main(SB),7,$-8
+ MOVQ $_rt0_amd64(SB), AX
+ JMP AX
diff --git a/src/pkg/runtime/rt0_openbsd_386.s b/src/pkg/runtime/rt0_openbsd_386.s
index e7e0da78f..9c00a7334 100644
--- a/src/pkg/runtime/rt0_openbsd_386.s
+++ b/src/pkg/runtime/rt0_openbsd_386.s
@@ -2,5 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-TEXT _rt0_386_openbsd(SB),7,$0
- JMP _rt0_386(SB)
+TEXT _rt0_386_openbsd(SB),7,$8
+ MOVL 8(SP), AX
+ LEAL 12(SP), BX
+ MOVL AX, 0(SP)
+ MOVL BX, 4(SP)
+ CALL main(SB)
+ INT $3
+
+TEXT main(SB),7,$0
+ JMP _rt0_386(SB)
diff --git a/src/pkg/runtime/rt0_openbsd_amd64.s b/src/pkg/runtime/rt0_openbsd_amd64.s
index e7fce5969..245a4c0f9 100644
--- a/src/pkg/runtime/rt0_openbsd_amd64.s
+++ b/src/pkg/runtime/rt0_openbsd_amd64.s
@@ -3,6 +3,11 @@
// license that can be found in the LICENSE file.
TEXT _rt0_amd64_openbsd(SB),7,$-8
- MOVQ $_rt0_amd64(SB), DX
- MOVQ SP, DI
- JMP DX
+ LEAQ 8(SP), SI // argv
+ MOVQ 0(SP), DI // argc
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT main(SB),7,$-8
+ MOVQ $_rt0_amd64(SB), AX
+ JMP AX
diff --git a/src/pkg/runtime/rt0_plan9_386.s b/src/pkg/runtime/rt0_plan9_386.s
index 56f3a0f6c..7af1eae7c 100644
--- a/src/pkg/runtime/rt0_plan9_386.s
+++ b/src/pkg/runtime/rt0_plan9_386.s
@@ -26,6 +26,13 @@ argv_fix:
LOOP argv_fix
CALL runtime·asminit(SB)
+
+ MOVL 0(SP), AX
+ LEAL 4(SP), BX
+ PUSHL BX
+ PUSHL AX
+ PUSHL $-1
+
JMP _rt0_386(SB)
DATA runtime·isplan9(SB)/4, $1
diff --git a/src/pkg/runtime/rt0_plan9_amd64.s b/src/pkg/runtime/rt0_plan9_amd64.s
index 2b1fa2ae1..16e5e82b7 100644
--- a/src/pkg/runtime/rt0_plan9_amd64.s
+++ b/src/pkg/runtime/rt0_plan9_amd64.s
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-TEXT _rt0_amd64_plan9(SB),7, $0
+TEXT _rt0_amd64_plan9(SB),7,$-8
+ LEAQ 8(SP), SI // argv
+ MOVQ 0(SP), DI // argc
MOVQ $_rt0_amd64(SB), AX
- MOVQ SP, DI
JMP AX
DATA runtime·isplan9(SB)/4, $1
diff --git a/src/pkg/runtime/rt0_windows_386.s b/src/pkg/runtime/rt0_windows_386.s
index a06aa787e..6e34c6c17 100644
--- a/src/pkg/runtime/rt0_windows_386.s
+++ b/src/pkg/runtime/rt0_windows_386.s
@@ -2,8 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-TEXT _rt0_386_windows(SB),7,$0
+TEXT _rt0_386_windows(SB),7,$12
+ MOVL 12(SP), AX
+ LEAL 16(SP), BX
+ MOVL AX, 4(SP)
+ MOVL BX, 8(SP)
+ MOVL $-1, 0(SP) // return PC for main
+ JMP main(SB)
+
+TEXT main(SB),7,$0
JMP _rt0_386(SB)
+
DATA runtime·iswindows(SB)/4, $1
GLOBL runtime·iswindows(SB), $4
diff --git a/src/pkg/runtime/rt0_windows_amd64.s b/src/pkg/runtime/rt0_windows_amd64.s
index dc1408adc..b48c05570 100644
--- a/src/pkg/runtime/rt0_windows_amd64.s
+++ b/src/pkg/runtime/rt0_windows_amd64.s
@@ -4,9 +4,14 @@
#include "zasm_GOOS_GOARCH.h"
-TEXT _rt0_amd64_windows(SB),7,$-8
+TEXT _rt0_amd64_windows(SB),7,$-8
+ LEAQ 8(SP), SI // argv
+ MOVQ 0(SP), DI // argc
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT main(SB),7,$-8
MOVQ $_rt0_amd64(SB), AX
- MOVQ SP, DI
JMP AX
DATA runtime·iswindows(SB)/4, $1
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index 4d57cbafd..d62408118 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -17,21 +17,34 @@ enum {
*/
void runtime·sigpanic(void);
+// The GOTRACEBACK environment variable controls the
+// behavior of a Go program that is crashing and exiting.
+// GOTRACEBACK=0 suppress all tracebacks
+// GOTRACEBACK=1 default behavior - show tracebacks but exclude runtime frames
+// GOTRACEBACK=2 show tracebacks including runtime frames
+// GOTRACEBACK=crash show tracebacks including runtime frames, then crash (core dump etc)
int32
-runtime·gotraceback(void)
+runtime·gotraceback(bool *crash)
{
byte *p;
+ if(crash != nil)
+ *crash = false;
p = runtime·getenv("GOTRACEBACK");
if(p == nil || p[0] == '\0')
return 1; // default is on
+ if(runtime·strcmp(p, (byte*)"crash") == 0) {
+ if(crash != nil)
+ *crash = true;
+ return 2; // extra information
+ }
return runtime·atoi(p);
}
int32
-runtime·mcmp(byte *s1, byte *s2, uint32 n)
+runtime·mcmp(byte *s1, byte *s2, uintptr n)
{
- uint32 i;
+ uintptr i;
byte c1, c2;
for(i=0; i<n; i++) {
@@ -75,6 +88,11 @@ runtime·args(int32 c, uint8 **v)
int32 runtime·isplan9;
int32 runtime·iswindows;
+// Information about what cpu features are available.
+// Set on startup in asm_{x86/amd64}.s.
+uint32 runtime·cpuid_ecx;
+uint32 runtime·cpuid_edx;
+
void
runtime·goargs(void)
{
@@ -156,6 +174,10 @@ TestAtomic64(void)
runtime·throw("xadd64 failed");
if(runtime·atomicload64(&z64) != (2ull<<40)+2)
runtime·throw("xadd64 failed");
+ if(runtime·xchg64(&z64, (3ull<<40)+3) != (2ull<<40)+2)
+ runtime·throw("xchg64 failed");
+ if(runtime·atomicload64(&z64) != (3ull<<40)+3)
+ runtime·throw("xchg64 failed");
}
void
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 08f43a69b..46c77e3fd 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -85,6 +85,7 @@ typedef struct LFNode LFNode;
typedef struct ParFor ParFor;
typedef struct ParForThread ParForThread;
typedef struct CgoMal CgoMal;
+typedef struct PollDesc PollDesc;
/*
* Per-CPU declaration.
@@ -235,8 +236,9 @@ struct G
int8* waitreason; // if status==Gwaiting
G* schedlink;
bool ispanic;
- bool issystem;
- int8 raceignore; // ignore race detection events
+ bool issystem; // do not output in stack dump
+ bool isbackground; // ignore in deadlock detector
+ int8 raceignore; // ignore race detection events
M* m; // for debuggers, but offset not hard-coded
M* lockedm;
int32 sig;
@@ -320,6 +322,7 @@ struct M
#endif
#ifdef GOOS_plan9
int8* notesig;
+ byte* errstr;
#endif
SEH* seh;
uintptr end[];
@@ -381,6 +384,8 @@ enum
SigThrow = 1<<2, // if signal.Notify doesn't take it, exit loudly
SigPanic = 1<<3, // if the signal is from the kernel, panic
SigDefault = 1<<4, // if the signal isn't explicitly requested, don't monitor it
+ SigHandling = 1<<5, // our signal handler is registered
+ SigIgnored = 1<<6, // the signal was ignored before we registered for it
};
// NOTE(rsc): keep in sync with extern.go:/type.Func.
@@ -482,6 +487,7 @@ struct ParFor
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
+ uint32 pad; // to align ParForThread.pos for 64-bit atomic operations
// stats
uint64 nsteal;
uint64 nstealcnt;
@@ -555,11 +561,25 @@ struct Alg
extern Alg runtime·algarray[Amax];
+byte* runtime·startup_random_data;
+uint32 runtime·startup_random_data_len;
+void runtime·get_random_data(byte**, int32*);
+
+enum {
+ // hashinit wants this many random bytes
+ HashRandomBytes = 32
+};
+void runtime·hashinit(void);
+
void runtime·memhash(uintptr*, uintptr, void*);
void runtime·nohash(uintptr*, uintptr, void*);
void runtime·strhash(uintptr*, uintptr, void*);
void runtime·interhash(uintptr*, uintptr, void*);
void runtime·nilinterhash(uintptr*, uintptr, void*);
+void runtime·aeshash(uintptr*, uintptr, void*);
+void runtime·aeshash32(uintptr*, uintptr, void*);
+void runtime·aeshash64(uintptr*, uintptr, void*);
+void runtime·aeshashstr(uintptr*, uintptr, void*);
void runtime·memequal(bool*, uintptr, void*, void*);
void runtime·noequal(bool*, uintptr, void*, void*);
@@ -578,7 +598,6 @@ void runtime·memcopy16(uintptr, void*, void*);
void runtime·memcopy32(uintptr, void*, void*);
void runtime·memcopy64(uintptr, void*, void*);
void runtime·memcopy128(uintptr, void*, void*);
-void runtime·memcopy(uintptr, void*, void*);
void runtime·strcopy(uintptr, void*, void*);
void runtime·algslicecopy(uintptr, void*, void*);
void runtime·intercopy(uintptr, void*, void*);
@@ -635,6 +654,8 @@ extern bool runtime·iscgo;
extern void (*runtime·sysargs)(int32, uint8**);
extern uint32 runtime·maxstring;
extern uint32 runtime·Hchansize;
+extern uint32 runtime·cpuid_ecx;
+extern uint32 runtime·cpuid_edx;
/*
* common functions and data
@@ -666,8 +687,8 @@ void runtime·panicstring(int8*);
void runtime·prints(int8*);
void runtime·printf(int8*, ...);
byte* runtime·mchr(byte*, byte, byte*);
-int32 runtime·mcmp(byte*, byte*, uint32);
-void runtime·memmove(void*, void*, uint32);
+int32 runtime·mcmp(byte*, byte*, uintptr);
+void runtime·memmove(void*, void*, uintptr);
void* runtime·mal(uintptr);
String runtime·catstring(String, String);
String runtime·gostring(byte*);
@@ -677,11 +698,15 @@ String runtime·gostringnocopy(byte*);
String runtime·gostringw(uint16*);
void runtime·initsig(void);
void runtime·sigenable(uint32 sig);
-int32 runtime·gotraceback(void);
+void runtime·sigdisable(uint32 sig);
+int32 runtime·gotraceback(bool *crash);
void runtime·goroutineheader(G*);
void runtime·traceback(uint8 *pc, uint8 *sp, uint8 *lr, G* gp);
void runtime·tracebackothers(G*);
+int32 runtime·open(int8*, int32, int32);
+int32 runtime·read(int32, void*, int32);
int32 runtime·write(int32, void*, int32);
+int32 runtime·close(int32);
int32 runtime·mincore(void*, uintptr, byte*);
bool runtime·cas(uint32*, uint32, uint32);
bool runtime·cas64(uint64*, uint64*, uint64);
@@ -691,6 +716,7 @@ bool runtime·casp(void**, void*, void*);
uint32 runtime·xadd(uint32 volatile*, int32);
uint64 runtime·xadd64(uint64 volatile*, int64);
uint32 runtime·xchg(uint32 volatile*, uint32);
+uint64 runtime·xchg64(uint64 volatile*, uint64);
uint32 runtime·atomicload(uint32 volatile*);
void runtime·atomicstore(uint32 volatile*, uint32);
void runtime·atomicstore64(uint64 volatile*, uint64);
@@ -761,6 +787,14 @@ int64 runtime·cputicks(void);
int64 runtime·tickspersecond(void);
void runtime·blockevent(int64, int32);
extern int64 runtime·blockprofilerate;
+void runtime·addtimer(Timer*);
+bool runtime·deltimer(Timer*);
+G* runtime·netpoll(bool);
+void runtime·netpollinit(void);
+int32 runtime·netpollopen(int32, PollDesc*);
+int32 runtime·netpollclose(int32);
+void runtime·netpollready(G**, PollDesc*, int32);
+void runtime·crash(void);
#pragma varargck argpos runtime·printf 1
#pragma varargck type "d" int32
@@ -929,7 +963,6 @@ void runtime·mapassign(MapType*, Hmap*, byte*, byte*);
void runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*);
void runtime·mapiternext(struct hash_iter*);
bool runtime·mapiterkey(struct hash_iter*, void*);
-void runtime·mapiterkeyvalue(struct hash_iter*, void*, void*);
Hmap* runtime·makemap_c(MapType*, int64);
Hchan* runtime·makechan_c(ChanType*, int64);
diff --git a/src/pkg/runtime/signal_386.c b/src/pkg/runtime/signal_386.c
new file mode 100644
index 000000000..72b4a66f8
--- /dev/null
+++ b/src/pkg/runtime/signal_386.c
@@ -0,0 +1,123 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signal_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+
+void
+runtime·dumpregs(Siginfo *info, void *ctxt)
+{
+ USED(info);
+ USED(ctxt);
+
+ runtime·printf("eax %x\n", SIG_EAX(info, ctxt));
+ runtime·printf("ebx %x\n", SIG_EBX(info, ctxt));
+ runtime·printf("ecx %x\n", SIG_ECX(info, ctxt));
+ runtime·printf("edx %x\n", SIG_EDX(info, ctxt));
+ runtime·printf("edi %x\n", SIG_EDI(info, ctxt));
+ runtime·printf("esi %x\n", SIG_ESI(info, ctxt));
+ runtime·printf("ebp %x\n", SIG_EBP(info, ctxt));
+ runtime·printf("esp %x\n", SIG_ESP(info, ctxt));
+ runtime·printf("eip %x\n", SIG_EIP(info, ctxt));
+ runtime·printf("eflags %x\n", SIG_EFLAGS(info, ctxt));
+ runtime·printf("cs %x\n", SIG_CS(info, ctxt));
+ runtime·printf("fs %x\n", SIG_FS(info, ctxt));
+ runtime·printf("gs %x\n", SIG_GS(info, ctxt));
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
+{
+ uintptr *sp;
+ SigTab *t;
+ bool crash;
+
+ if(sig == SIGPROF) {
+ if(gp != m->g0 && gp != m->gsignal)
+ runtime·sigprof((byte*)SIG_EIP(info, ctxt), (byte*)SIG_ESP(info, ctxt), nil, gp);
+ return;
+ }
+
+ t = &runtime·sigtab[sig];
+ if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
+ if(gp == nil || gp == m->g0)
+ goto Throw;
+
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp->sig = sig;
+ gp->sigcode0 = SIG_CODE0(info, ctxt);
+ gp->sigcode1 = SIG_CODE1(info, ctxt);
+ gp->sigpc = SIG_EIP(info, ctxt);
+
+#ifdef GOOS_darwin
+ // Work around Leopard bug that doesn't set FPE_INTDIV.
+ // Look at instruction to see if it is a divide.
+ // Not necessary in Snow Leopard (si_code will be != 0).
+ if(sig == SIGFPE && gp->sigcode0 == 0) {
+ byte *pc;
+ pc = (byte*)gp->sigpc;
+ if(pc[0] == 0x66) // 16-bit instruction prefix
+ pc++;
+ if(pc[0] == 0xF6 || pc[0] == 0xF7)
+ gp->sigcode0 = FPE_INTDIV;
+ }
+#endif
+
+ // Only push runtime·sigpanic if eip != 0.
+ // If eip == 0, probably panicked because of a
+ // call to a nil func. Not pushing that onto sp will
+ // make the trace look like a call to runtime·sigpanic instead.
+ // (Otherwise the trace will end at runtime·sigpanic and we
+ // won't get to see who faulted.)
+ if(SIG_EIP(info, ctxt) != 0) {
+ sp = (uintptr*)SIG_ESP(info, ctxt);
+ *--sp = SIG_EIP(info, ctxt);
+ SIG_ESP(info, ctxt) = (uintptr)sp;
+ }
+ SIG_EIP(info, ctxt) = (uintptr)runtime·sigpanic;
+ return;
+ }
+
+ if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
+ if(runtime·sigsend(sig))
+ return;
+ if(t->flags & SigKill)
+ runtime·exit(2);
+ if(!(t->flags & SigThrow))
+ return;
+
+Throw:
+ runtime·startpanic();
+
+ if(sig < 0 || sig >= NSIG)
+ runtime·printf("Signal %d\n", sig);
+ else
+ runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+ runtime·printf("PC=%x\n", SIG_EIP(info, ctxt));
+ if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
+ runtime·printf("signal arrived during cgo execution\n");
+ gp = m->lockedg;
+ }
+ runtime·printf("\n");
+
+ if(runtime·gotraceback(&crash)){
+ runtime·traceback((void*)SIG_EIP(info, ctxt), (void*)SIG_ESP(info, ctxt), 0, gp);
+ runtime·tracebackothers(gp);
+ runtime·dumpregs(info, ctxt);
+ }
+
+ if(crash)
+ runtime·crash();
+
+ runtime·exit(2);
+}
diff --git a/src/pkg/runtime/signal_amd64.c b/src/pkg/runtime/signal_amd64.c
new file mode 100644
index 000000000..ce17bf36d
--- /dev/null
+++ b/src/pkg/runtime/signal_amd64.c
@@ -0,0 +1,133 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signal_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+
+void
+runtime·dumpregs(Siginfo *info, void *ctxt)
+{
+ USED(info);
+ USED(ctxt);
+
+ runtime·printf("rax %X\n", SIG_RAX(info, ctxt));
+ runtime·printf("rbx %X\n", SIG_RBX(info, ctxt));
+ runtime·printf("rcx %X\n", SIG_RCX(info, ctxt));
+ runtime·printf("rdx %X\n", SIG_RDX(info, ctxt));
+ runtime·printf("rdi %X\n", SIG_RDI(info, ctxt));
+ runtime·printf("rsi %X\n", SIG_RSI(info, ctxt));
+ runtime·printf("rbp %X\n", SIG_RBP(info, ctxt));
+ runtime·printf("rsp %X\n", SIG_RSP(info, ctxt));
+ runtime·printf("r8 %X\n", SIG_R8(info, ctxt) );
+ runtime·printf("r9 %X\n", SIG_R9(info, ctxt) );
+ runtime·printf("r10 %X\n", SIG_R10(info, ctxt));
+ runtime·printf("r11 %X\n", SIG_R11(info, ctxt));
+ runtime·printf("r12 %X\n", SIG_R12(info, ctxt));
+ runtime·printf("r13 %X\n", SIG_R13(info, ctxt));
+ runtime·printf("r14 %X\n", SIG_R14(info, ctxt));
+ runtime·printf("r15 %X\n", SIG_R15(info, ctxt));
+ runtime·printf("rip %X\n", SIG_RIP(info, ctxt));
+ runtime·printf("rflags %X\n", SIG_RFLAGS(info, ctxt));
+ runtime·printf("cs %X\n", SIG_CS(info, ctxt));
+ runtime·printf("fs %X\n", SIG_FS(info, ctxt));
+ runtime·printf("gs %X\n", SIG_GS(info, ctxt));
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
+{
+ uintptr *sp;
+ SigTab *t;
+ bool crash;
+
+ if(sig == SIGPROF) {
+ if(gp != m->g0 && gp != m->gsignal)
+ runtime·sigprof((byte*)SIG_RIP(info, ctxt), (byte*)SIG_RSP(info, ctxt), nil, gp);
+ return;
+ }
+
+ t = &runtime·sigtab[sig];
+ if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
+ if(gp == nil || gp == m->g0)
+ goto Throw;
+
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp->sig = sig;
+ gp->sigcode0 = SIG_CODE0(info, ctxt);
+ gp->sigcode1 = SIG_CODE1(info, ctxt);
+ gp->sigpc = SIG_RIP(info, ctxt);
+
+#ifdef GOOS_darwin
+ // Work around Leopard bug that doesn't set FPE_INTDIV.
+ // Look at instruction to see if it is a divide.
+ // Not necessary in Snow Leopard (si_code will be != 0).
+ if(sig == SIGFPE && gp->sigcode0 == 0) {
+ byte *pc;
+ pc = (byte*)gp->sigpc;
+ if((pc[0]&0xF0) == 0x40) // 64-bit REX prefix
+ pc++;
+ else if(pc[0] == 0x66) // 16-bit instruction prefix
+ pc++;
+ if(pc[0] == 0xF6 || pc[0] == 0xF7)
+ gp->sigcode0 = FPE_INTDIV;
+ }
+#endif
+
+ // Only push runtime·sigpanic if rip != 0.
+ // If rip == 0, probably panicked because of a
+ // call to a nil func. Not pushing that onto sp will
+ // make the trace look like a call to runtime·sigpanic instead.
+ // (Otherwise the trace will end at runtime·sigpanic and we
+ // won't get to see who faulted.)
+ if(SIG_RIP(info, ctxt) != 0) {
+ sp = (uintptr*)SIG_RSP(info, ctxt);
+ *--sp = SIG_RIP(info, ctxt);
+ SIG_RSP(info, ctxt) = (uintptr)sp;
+ }
+ SIG_RIP(info, ctxt) = (uintptr)runtime·sigpanic;
+ return;
+ }
+
+ if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
+ if(runtime·sigsend(sig))
+ return;
+ if(t->flags & SigKill)
+ runtime·exit(2);
+ if(!(t->flags & SigThrow))
+ return;
+
+Throw:
+ runtime·startpanic();
+
+ if(sig < 0 || sig >= NSIG)
+ runtime·printf("Signal %d\n", sig);
+ else
+ runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+ runtime·printf("PC=%X\n", SIG_RIP(info, ctxt));
+ if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
+ runtime·printf("signal arrived during cgo execution\n");
+ gp = m->lockedg;
+ }
+ runtime·printf("\n");
+
+ if(runtime·gotraceback(&crash)){
+ runtime·traceback((void*)SIG_RIP(info, ctxt), (void*)SIG_RSP(info, ctxt), 0, gp);
+ runtime·tracebackothers(gp);
+ runtime·dumpregs(info, ctxt);
+ }
+
+ if(crash)
+ runtime·crash();
+
+ runtime·exit(2);
+}
diff --git a/src/pkg/runtime/signal_arm.c b/src/pkg/runtime/signal_arm.c
new file mode 100644
index 000000000..adf61de6b
--- /dev/null
+++ b/src/pkg/runtime/signal_arm.c
@@ -0,0 +1,124 @@
+// 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
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signal_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+
+void
+runtime·dumpregs(Siginfo *info, void *ctxt)
+{
+ USED(info);
+ USED(ctxt);
+
+ runtime·printf("trap %x\n", SIG_TRAP(info, ctxt));
+ runtime·printf("error %x\n", SIG_ERROR(info, ctxt));
+ runtime·printf("oldmask %x\n", SIG_OLDMASK(info, ctxt));
+ runtime·printf("r0 %x\n", SIG_R0(info, ctxt));
+ runtime·printf("r1 %x\n", SIG_R1(info, ctxt));
+ runtime·printf("r2 %x\n", SIG_R2(info, ctxt));
+ runtime·printf("r3 %x\n", SIG_R3(info, ctxt));
+ runtime·printf("r4 %x\n", SIG_R4(info, ctxt));
+ runtime·printf("r5 %x\n", SIG_R5(info, ctxt));
+ runtime·printf("r6 %x\n", SIG_R6(info, ctxt));
+ runtime·printf("r7 %x\n", SIG_R7(info, ctxt));
+ runtime·printf("r8 %x\n", SIG_R8(info, ctxt));
+ runtime·printf("r9 %x\n", SIG_R9(info, ctxt));
+ runtime·printf("r10 %x\n", SIG_R10(info, ctxt));
+ runtime·printf("fp %x\n", SIG_FP(info, ctxt));
+ runtime·printf("ip %x\n", SIG_IP(info, ctxt));
+ runtime·printf("sp %x\n", SIG_SP(info, ctxt));
+ runtime·printf("lr %x\n", SIG_LR(info, ctxt));
+ runtime·printf("pc %x\n", SIG_PC(info, ctxt));
+ runtime·printf("cpsr %x\n", SIG_CPSR(info, ctxt));
+ runtime·printf("fault %x\n", SIG_FAULT(info, ctxt));
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
+{
+ SigTab *t;
+ bool crash;
+
+ if(sig == SIGPROF) {
+ if(gp != m->g0 && gp != m->gsignal)
+ runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp);
+ return;
+ }
+
+ t = &runtime·sigtab[sig];
+ if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
+ if(gp == nil || gp == m->g0)
+ goto Throw;
+
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp->sig = sig;
+ gp->sigcode0 = SIG_CODE0(info, ctxt);
+ gp->sigcode1 = SIG_FAULT(info, ctxt);
+ gp->sigpc = SIG_PC(info, ctxt);
+
+ // We arrange lr, and pc to pretend the panicking
+ // function calls sigpanic directly.
+ // Always save LR to stack so that panics in leaf
+ // functions are correctly handled. This smashes
+ // the stack frame but we're not going back there
+ // anyway.
+ SIG_SP(info, ctxt) -= 4;
+ *(uint32*)SIG_SP(info, ctxt) = SIG_LR(info, ctxt);
+ // Don't bother saving PC if it's zero, which is
+ // probably a call to a nil func: the old link register
+ // is more useful in the stack trace.
+ if(gp->sigpc != 0)
+ SIG_LR(info, ctxt) = gp->sigpc;
+ // In case we are panicking from external C code
+ SIG_R10(info, ctxt) = (uintptr)gp;
+ SIG_R9(info, ctxt) = (uintptr)m;
+ SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic;
+ return;
+ }
+
+ if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
+ if(runtime·sigsend(sig))
+ return;
+ if(t->flags & SigKill)
+ runtime·exit(2);
+ if(!(t->flags & SigThrow))
+ return;
+
+Throw:
+ if(runtime·panicking) // traceback already printed
+ runtime·exit(2);
+ runtime·panicking = 1;
+
+ if(sig < 0 || sig >= NSIG)
+ runtime·printf("Signal %d\n", sig);
+ else
+ runtime·printf("%s\n", runtime·sigtab[sig].name);
+
+ runtime·printf("PC=%x\n", SIG_PC(info, ctxt));
+ if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
+ runtime·printf("signal arrived during cgo execution\n");
+ gp = m->lockedg;
+ }
+ runtime·printf("\n");
+
+ if(runtime·gotraceback(&crash)){
+ runtime·traceback((void*)SIG_PC(info, ctxt), (void*)SIG_SP(info, ctxt), (void*)SIG_LR(info, ctxt), gp);
+ runtime·tracebackothers(gp);
+ runtime·printf("\n");
+ runtime·dumpregs(info, ctxt);
+ }
+
+ if(crash)
+ runtime·crash();
+
+ runtime·exit(2);
+}
diff --git a/src/pkg/runtime/signal_darwin_386.c b/src/pkg/runtime/signal_darwin_386.c
deleted file mode 100644
index 132ca931b..000000000
--- a/src/pkg/runtime/signal_darwin_386.c
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Regs32 *r)
-{
- runtime·printf("eax %x\n", r->eax);
- runtime·printf("ebx %x\n", r->ebx);
- runtime·printf("ecx %x\n", r->ecx);
- runtime·printf("edx %x\n", r->edx);
- runtime·printf("edi %x\n", r->edi);
- runtime·printf("esi %x\n", r->esi);
- runtime·printf("ebp %x\n", r->ebp);
- runtime·printf("esp %x\n", r->esp);
- runtime·printf("eip %x\n", r->eip);
- runtime·printf("eflags %x\n", r->eflags);
- runtime·printf("cs %x\n", r->cs);
- runtime·printf("fs %x\n", r->fs);
- runtime·printf("gs %x\n", r->gs);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Mcontext32 *mc;
- Regs32 *r;
- uintptr *sp;
- byte *pc;
- SigTab *t;
-
- uc = context;
- mc = uc->uc_mcontext;
- r = &mc->ss;
-
- if(sig == SIGPROF) {
- if(gp != m->g0 && gp != m->gsignal)
- runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Work around Leopard bug that doesn't set FPE_INTDIV.
- // Look at instruction to see if it is a divide.
- // Not necessary in Snow Leopard (si_code will be != 0).
- if(sig == SIGFPE && info->si_code == 0) {
- pc = (byte*)r->eip;
- if(pc[0] == 0x66) // 16-bit instruction prefix
- pc++;
- if(pc[0] == 0xF6 || pc[0] == 0xF7)
- info->si_code = FPE_INTDIV;
- }
-
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = (uintptr)info->si_addr;
- gp->sigpc = r->eip;
-
- // Only push runtime·sigpanic if r->eip != 0.
- // If r->eip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->eip != 0) {
- sp = (uintptr*)r->esp;
- *--sp = r->eip;
- r->esp = (uintptr)sp;
- }
- r->eip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG){
- runtime·printf("Signal %d\n", sig);
- }else{
- runtime·printf("%s\n", runtime·sigtab[sig].name);
- }
-
- runtime·printf("PC=%x\n", r->eip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- StackT st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(*(void**)sa.__sigaction_u == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask = ~0U;
- sa.sa_tramp = (void*)runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
- *(uintptr*)sa.__sigaction_u = (uintptr)fn;
- runtime·sigaction(i, &sa, nil);
-}
diff --git a/src/pkg/runtime/signal_darwin_386.h b/src/pkg/runtime/signal_darwin_386.h
new file mode 100644
index 000000000..5459e10a1
--- /dev/null
+++ b/src/pkg/runtime/signal_darwin_386.h
@@ -0,0 +1,23 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext->ss)
+
+#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax)
+#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx)
+#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx)
+#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx)
+#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi)
+#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi)
+#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp)
+#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp)
+#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip)
+#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags)
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/pkg/runtime/signal_darwin_amd64.c b/src/pkg/runtime/signal_darwin_amd64.c
deleted file mode 100644
index 4b7256bf4..000000000
--- a/src/pkg/runtime/signal_darwin_amd64.c
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "os_GOOS.h"
-#include "signals_GOOS.h"
-
-void
-runtime·dumpregs(Regs64 *r)
-{
- runtime·printf("rax %X\n", r->rax);
- runtime·printf("rbx %X\n", r->rbx);
- runtime·printf("rcx %X\n", r->rcx);
- runtime·printf("rdx %X\n", r->rdx);
- runtime·printf("rdi %X\n", r->rdi);
- runtime·printf("rsi %X\n", r->rsi);
- runtime·printf("rbp %X\n", r->rbp);
- runtime·printf("rsp %X\n", r->rsp);
- runtime·printf("r8 %X\n", r->r8 );
- runtime·printf("r9 %X\n", r->r9 );
- runtime·printf("r10 %X\n", r->r10);
- runtime·printf("r11 %X\n", r->r11);
- runtime·printf("r12 %X\n", r->r12);
- runtime·printf("r13 %X\n", r->r13);
- runtime·printf("r14 %X\n", r->r14);
- runtime·printf("r15 %X\n", r->r15);
- runtime·printf("rip %X\n", r->rip);
- runtime·printf("rflags %X\n", r->rflags);
- runtime·printf("cs %X\n", r->cs);
- runtime·printf("fs %X\n", r->fs);
- runtime·printf("gs %X\n", r->gs);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Mcontext64 *mc;
- Regs64 *r;
- uintptr *sp;
- byte *pc;
- SigTab *t;
-
- uc = context;
- mc = uc->uc_mcontext;
- r = &mc->ss;
-
- if(sig == SIGPROF) {
- if(gp != m->g0 && gp != m->gsignal)
- runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Work around Leopard bug that doesn't set FPE_INTDIV.
- // Look at instruction to see if it is a divide.
- // Not necessary in Snow Leopard (si_code will be != 0).
- if(sig == SIGFPE && info->si_code == 0) {
- pc = (byte*)r->rip;
- if((pc[0]&0xF0) == 0x40) // 64-bit REX prefix
- pc++;
- else if(pc[0] == 0x66) // 16-bit instruction prefix
- pc++;
- if(pc[0] == 0xF6 || pc[0] == 0xF7)
- info->si_code = FPE_INTDIV;
- }
-
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = (uintptr)info->si_addr;
- gp->sigpc = r->rip;
-
- // Only push runtime·sigpanic if r->rip != 0.
- // If r->rip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->rip != 0) {
- sp = (uintptr*)r->rsp;
- *--sp = r->rip;
- r->rsp = (uintptr)sp;
- }
- r->rip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG){
- runtime·printf("Signal %d\n", sig);
- }else{
- runtime·printf("%s\n", runtime·sigtab[sig].name);
- }
-
- runtime·printf("PC=%X\n", r->rip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- StackT st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(*(void**)sa.__sigaction_u == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask = ~0ULL;
- sa.sa_tramp = runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
- *(uintptr*)sa.__sigaction_u = (uintptr)fn;
- runtime·sigaction(i, &sa, nil);
-}
diff --git a/src/pkg/runtime/signal_darwin_amd64.h b/src/pkg/runtime/signal_darwin_amd64.h
new file mode 100644
index 000000000..e3da6de3a
--- /dev/null
+++ b/src/pkg/runtime/signal_darwin_amd64.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext->ss)
+
+#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
+#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
+#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
+#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
+#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
+#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
+#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
+#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
+#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
+#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).rflags)
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/pkg/runtime/signal_freebsd_386.c b/src/pkg/runtime/signal_freebsd_386.c
deleted file mode 100644
index 254e5e277..000000000
--- a/src/pkg/runtime/signal_freebsd_386.c
+++ /dev/null
@@ -1,154 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*__sa_handler)(int32);
- void (*__sa_sigaction)(int32, Siginfo*, void *);
- } __sigaction_u; /* signal handler */
- int32 sa_flags; /* see signal options below */
- Sigset sa_mask; /* signal mask to apply */
-} Sigaction;
-
-void
-runtime·dumpregs(Mcontext *r)
-{
- runtime·printf("eax %x\n", r->mc_eax);
- runtime·printf("ebx %x\n", r->mc_ebx);
- runtime·printf("ecx %x\n", r->mc_ecx);
- runtime·printf("edx %x\n", r->mc_edx);
- runtime·printf("edi %x\n", r->mc_edi);
- runtime·printf("esi %x\n", r->mc_esi);
- runtime·printf("ebp %x\n", r->mc_ebp);
- runtime·printf("esp %x\n", r->mc_esp);
- runtime·printf("eip %x\n", r->mc_eip);
- runtime·printf("eflags %x\n", r->mc_eflags);
- runtime·printf("cs %x\n", r->mc_cs);
- runtime·printf("fs %x\n", r->mc_fs);
- runtime·printf("gs %x\n", r->mc_gs);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Mcontext *r;
- uintptr *sp;
- SigTab *t;
-
- uc = context;
- r = &uc->uc_mcontext;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->mc_eip, (uint8*)r->mc_esp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = (uintptr)info->si_addr;
- gp->sigpc = r->mc_eip;
-
- // Only push runtime·sigpanic if r->mc_eip != 0.
- // If r->mc_eip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->mc_eip != 0) {
- sp = (uintptr*)r->mc_esp;
- *--sp = r->mc_eip;
- r->mc_esp = (uintptr)sp;
- }
- r->mc_eip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", r->mc_eip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->mc_eip, (void*)r->mc_esp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = (int8*)p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask.__bits[0] = ~(uint32)0;
- sa.sa_mask.__bits[1] = ~(uint32)0;
- sa.sa_mask.__bits[2] = ~(uint32)0;
- sa.sa_mask.__bits[3] = ~(uint32)0;
- if (fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.__sigaction_u.__sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
diff --git a/src/pkg/runtime/signal_freebsd_386.h b/src/pkg/runtime/signal_freebsd_386.h
new file mode 100644
index 000000000..a24f1ee96
--- /dev/null
+++ b/src/pkg/runtime/signal_freebsd_386.h
@@ -0,0 +1,23 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
+
+#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).mc_eax)
+#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).mc_ebx)
+#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).mc_ecx)
+#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).mc_edx)
+#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).mc_edi)
+#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).mc_esi)
+#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).mc_ebp)
+#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).mc_esp)
+#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).mc_eip)
+#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).mc_eflags)
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).mc_cs)
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).mc_fs)
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).mc_gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/pkg/runtime/signal_freebsd_amd64.c b/src/pkg/runtime/signal_freebsd_amd64.c
deleted file mode 100644
index 7dbf36075..000000000
--- a/src/pkg/runtime/signal_freebsd_amd64.c
+++ /dev/null
@@ -1,162 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*__sa_handler)(int32);
- void (*__sa_sigaction)(int32, Siginfo*, void *);
- } __sigaction_u; /* signal handler */
- int32 sa_flags; /* see signal options below */
- Sigset sa_mask; /* signal mask to apply */
-} Sigaction;
-
-void
-runtime·dumpregs(Mcontext *r)
-{
- runtime·printf("rax %X\n", r->mc_rax);
- runtime·printf("rbx %X\n", r->mc_rbx);
- runtime·printf("rcx %X\n", r->mc_rcx);
- runtime·printf("rdx %X\n", r->mc_rdx);
- runtime·printf("rdi %X\n", r->mc_rdi);
- runtime·printf("rsi %X\n", r->mc_rsi);
- runtime·printf("rbp %X\n", r->mc_rbp);
- runtime·printf("rsp %X\n", r->mc_rsp);
- runtime·printf("r8 %X\n", r->mc_r8 );
- runtime·printf("r9 %X\n", r->mc_r9 );
- runtime·printf("r10 %X\n", r->mc_r10);
- runtime·printf("r11 %X\n", r->mc_r11);
- runtime·printf("r12 %X\n", r->mc_r12);
- runtime·printf("r13 %X\n", r->mc_r13);
- runtime·printf("r14 %X\n", r->mc_r14);
- runtime·printf("r15 %X\n", r->mc_r15);
- runtime·printf("rip %X\n", r->mc_rip);
- runtime·printf("rflags %X\n", r->mc_flags);
- runtime·printf("cs %X\n", r->mc_cs);
- runtime·printf("fs %X\n", r->mc_fs);
- runtime·printf("gs %X\n", r->mc_gs);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Mcontext *r;
- uintptr *sp;
- SigTab *t;
-
- uc = context;
- r = &uc->uc_mcontext;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->mc_rip, (uint8*)r->mc_rsp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = (uintptr)info->si_addr;
- gp->sigpc = r->mc_rip;
-
- // Only push runtime·sigpanic if r->mc_rip != 0.
- // If r->mc_rip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->mc_rip != 0) {
- sp = (uintptr*)r->mc_rsp;
- *--sp = r->mc_rip;
- r->mc_rsp = (uintptr)sp;
- }
- r->mc_rip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", r->mc_rip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->mc_rip, (void*)r->mc_rsp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = (int8*)p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask.__bits[0] = ~(uint32)0;
- sa.sa_mask.__bits[1] = ~(uint32)0;
- sa.sa_mask.__bits[2] = ~(uint32)0;
- sa.sa_mask.__bits[3] = ~(uint32)0;
- if (fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.__sigaction_u.__sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
diff --git a/src/pkg/runtime/signal_freebsd_amd64.h b/src/pkg/runtime/signal_freebsd_amd64.h
new file mode 100644
index 000000000..7d35b7f85
--- /dev/null
+++ b/src/pkg/runtime/signal_freebsd_amd64.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
+
+#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).mc_rax)
+#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).mc_rbx)
+#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).mc_rcx)
+#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).mc_rdx)
+#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).mc_rdi)
+#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).mc_rsi)
+#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).mc_rbp)
+#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).mc_rsp)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).mc_r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).mc_r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).mc_r10)
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).mc_r11)
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).mc_r12)
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).mc_r13)
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).mc_r14)
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).mc_r15)
+#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).mc_rip)
+#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).mc_rflags)
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).mc_cs)
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).mc_fs)
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).mc_gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/pkg/runtime/signal_freebsd_arm.c b/src/pkg/runtime/signal_freebsd_arm.c
deleted file mode 100644
index 50c3221bb..000000000
--- a/src/pkg/runtime/signal_freebsd_arm.c
+++ /dev/null
@@ -1,193 +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.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-#define r0 __gregs[0]
-#define r1 __gregs[1]
-#define r2 __gregs[2]
-#define r3 __gregs[3]
-#define r4 __gregs[4]
-#define r5 __gregs[5]
-#define r6 __gregs[6]
-#define r7 __gregs[7]
-#define r8 __gregs[8]
-#define r9 __gregs[9]
-#define r10 __gregs[10]
-#define r11 __gregs[11]
-#define r12 __gregs[12]
-#define r13 __gregs[13]
-#define r14 __gregs[14]
-#define r15 __gregs[15]
-#define cpsr __gregs[16]
-
-void
-runtime·dumpregs(Mcontext *r)
-{
- runtime·printf("r0 %x\n", r->r0);
- runtime·printf("r1 %x\n", r->r1);
- runtime·printf("r2 %x\n", r->r2);
- runtime·printf("r3 %x\n", r->r3);
- runtime·printf("r4 %x\n", r->r4);
- runtime·printf("r5 %x\n", r->r5);
- runtime·printf("r6 %x\n", r->r6);
- runtime·printf("r7 %x\n", r->r7);
- runtime·printf("r8 %x\n", r->r8);
- runtime·printf("r9 %x\n", r->r9);
- runtime·printf("r10 %x\n", r->r10);
- runtime·printf("fp %x\n", r->r11);
- runtime·printf("ip %x\n", r->r12);
- runtime·printf("sp %x\n", r->r13);
- runtime·printf("lr %x\n", r->r14);
- runtime·printf("pc %x\n", r->r15);
- runtime·printf("cpsr %x\n", r->cpsr);
-}
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*__sa_handler)(int32);
- void (*__sa_sigaction)(int32, Siginfo*, void *);
- } __sigaction_u; /* signal handler */
- int32 sa_flags; /* see signal options below */
- Sigset sa_mask; /* signal mask to apply */
-} Sigaction;
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Mcontext *r;
- SigTab *t;
-
- uc = context;
- r = &uc->uc_mcontext;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = (uintptr)info->si_addr;
- gp->sigpc = r->r15;
-
- // Only push runtime·sigpanic if r->mc_rip != 0.
- // If r->mc_rip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->r15 != 0)
- r->r14 = r->r15;
- // In case we are panicking from external C code
- r->r10 = (uintptr)gp;
- r->r9 = (uintptr)m;
- r->r15 = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%x\n", r->r15);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
- runtime·tracebackothers(gp);
- runtime·printf("\n");
- runtime·dumpregs(r);
- }
-
-// breakpoint();
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = (uint8*)p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask.__bits[0] = ~(uint32)0;
- sa.sa_mask.__bits[1] = ~(uint32)0;
- sa.sa_mask.__bits[2] = ~(uint32)0;
- sa.sa_mask.__bits[3] = ~(uint32)0;
- if (fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.__sigaction_u.__sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·checkgoarm(void)
-{
- // TODO(minux)
-}
-
-#pragma textflag 7
-int64
-runtime·cputicks(void)
-{
- // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
- // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
- // TODO: need more entropy to better seed fastrand1.
- return runtime·nanotime();
-}
diff --git a/src/pkg/runtime/signal_freebsd_arm.h b/src/pkg/runtime/signal_freebsd_arm.h
new file mode 100644
index 000000000..87a45aa27
--- /dev/null
+++ b/src/pkg/runtime/signal_freebsd_arm.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
+
+#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).__gregs[0])
+#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).__gregs[1])
+#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).__gregs[2])
+#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).__gregs[3])
+#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).__gregs[4])
+#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).__gregs[5])
+#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).__gregs[6])
+#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).__gregs[7])
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[8])
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[9])
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[10])
+#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).__gregs[11])
+#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).__gregs[12])
+#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).__gregs[13])
+#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).__gregs[14])
+#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).__gregs[15])
+#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).__gregs[16])
+#define SIG_FAULT(info, ctxt) ((uintptr)(info)->si_addr)
+#define SIG_TRAP(info, ctxt) (0)
+#define SIG_ERROR(info, ctxt) (0)
+#define SIG_OLDMASK(info, ctxt) (0)
+#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
diff --git a/src/pkg/runtime/signal_linux_386.c b/src/pkg/runtime/signal_linux_386.c
deleted file mode 100644
index 9b45ec3bd..000000000
--- a/src/pkg/runtime/signal_linux_386.c
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
- runtime·printf("eax %x\n", r->eax);
- runtime·printf("ebx %x\n", r->ebx);
- runtime·printf("ecx %x\n", r->ecx);
- runtime·printf("edx %x\n", r->edx);
- runtime·printf("edi %x\n", r->edi);
- runtime·printf("esi %x\n", r->esi);
- runtime·printf("ebp %x\n", r->ebp);
- runtime·printf("esp %x\n", r->esp);
- runtime·printf("eip %x\n", r->eip);
- runtime·printf("eflags %x\n", r->eflags);
- runtime·printf("cs %x\n", r->cs);
- runtime·printf("fs %x\n", r->fs);
- runtime·printf("gs %x\n", r->gs);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void runtime·sigtramp(void);
-extern void runtime·sigreturn(void); // calls runtime·sigreturn
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Sigcontext *r;
- uintptr *sp;
- SigTab *t;
-
- uc = context;
- r = &uc->uc_mcontext;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = ((uintptr*)info)[3];
- gp->sigpc = r->eip;
-
- // Only push runtime·sigpanic if r->eip != 0.
- // If r->eip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->eip != 0) {
- sp = (uintptr*)r->esp;
- *--sp = r->eip;
- r->esp = (uintptr)sp;
- }
- r->eip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", r->eip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->eip, (void*)r->esp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
- runtime·throw("rt_sigaction read failure");
- if(sa.k_sa_handler == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask = ~0ULL;
- sa.sa_restorer = (void*)runtime·sigreturn;
- if(fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.k_sa_handler = fn;
- if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
- runtime·throw("rt_sigaction failure");
-}
-
-#define AT_NULL 0
-#define AT_SYSINFO 32
-extern uint32 runtime·_vdso;
-
-#pragma textflag 7
-void
-runtime·linux_setup_vdso(int32 argc, void *argv_list)
-{
- byte **argv = &argv_list;
- byte **envp;
- uint32 *auxv;
-
- // skip envp to get to ELF auxiliary vector.
- for(envp = &argv[argc+1]; *envp != nil; envp++)
- ;
- envp++;
-
- for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
- if(auxv[0] == AT_SYSINFO) {
- runtime·_vdso = auxv[1];
- break;
- }
- }
-}
diff --git a/src/pkg/runtime/signal_linux_386.h b/src/pkg/runtime/signal_linux_386.h
new file mode 100644
index 000000000..f77f1c9d5
--- /dev/null
+++ b/src/pkg/runtime/signal_linux_386.h
@@ -0,0 +1,24 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
+
+#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).eax)
+#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).ebx)
+#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).ecx)
+#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).edx)
+#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).edi)
+#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).esi)
+#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).ebp)
+#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).esp)
+#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).eip)
+#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).eflags)
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).cs)
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).fs)
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) (((uintptr*)(info))[2])
+
diff --git a/src/pkg/runtime/signal_linux_amd64.c b/src/pkg/runtime/signal_linux_amd64.c
deleted file mode 100644
index c4e39a6ab..000000000
--- a/src/pkg/runtime/signal_linux_amd64.c
+++ /dev/null
@@ -1,162 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
- runtime·printf("rax %X\n", r->rax);
- runtime·printf("rbx %X\n", r->rbx);
- runtime·printf("rcx %X\n", r->rcx);
- runtime·printf("rdx %X\n", r->rdx);
- runtime·printf("rdi %X\n", r->rdi);
- runtime·printf("rsi %X\n", r->rsi);
- runtime·printf("rbp %X\n", r->rbp);
- runtime·printf("rsp %X\n", r->rsp);
- runtime·printf("r8 %X\n", r->r8 );
- runtime·printf("r9 %X\n", r->r9 );
- runtime·printf("r10 %X\n", r->r10);
- runtime·printf("r11 %X\n", r->r11);
- runtime·printf("r12 %X\n", r->r12);
- runtime·printf("r13 %X\n", r->r13);
- runtime·printf("r14 %X\n", r->r14);
- runtime·printf("r15 %X\n", r->r15);
- runtime·printf("rip %X\n", r->rip);
- runtime·printf("rflags %X\n", r->eflags);
- runtime·printf("cs %X\n", (uint64)r->cs);
- runtime·printf("fs %X\n", (uint64)r->fs);
- runtime·printf("gs %X\n", (uint64)r->gs);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void runtime·sigtramp(void);
-extern void runtime·sigreturn(void); // calls runtime·sigreturn
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Mcontext *mc;
- Sigcontext *r;
- uintptr *sp;
- SigTab *t;
-
- uc = context;
- mc = &uc->uc_mcontext;
- r = (Sigcontext*)mc; // same layout, more conveient names
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = ((uintptr*)info)[2];
- gp->sigpc = r->rip;
-
- // Only push runtime·sigpanic if r->rip != 0.
- // If r->rip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->rip != 0) {
- sp = (uintptr*)r->rsp;
- *--sp = r->rip;
- r->rsp = (uintptr)sp;
- }
- r->rip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", r->rip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->rip, (void*)r->rsp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
- runtime·throw("rt_sigaction read failure");
- if(sa.sa_handler == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask = ~0ULL;
- // TODO(adonovan): Linux manpage says "sa_restorer element is
- // obsolete and should not be used". Avoid it here, and test.
- sa.sa_restorer = (void*)runtime·sigreturn;
- if(fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.sa_handler = fn;
- if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
- runtime·throw("rt_sigaction failure");
-}
diff --git a/src/pkg/runtime/signal_linux_amd64.h b/src/pkg/runtime/signal_linux_amd64.h
new file mode 100644
index 000000000..5a9a3e5da
--- /dev/null
+++ b/src/pkg/runtime/signal_linux_amd64.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
+
+#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
+#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
+#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
+#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
+#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
+#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
+#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
+#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
+#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
+#define SIG_RFLAGS(info, ctxt) ((uint64)SIG_REGS(ctxt).eflags)
+
+#define SIG_CS(info, ctxt) ((uint64)SIG_REGS(ctxt).cs)
+#define SIG_FS(info, ctxt) ((uint64)SIG_REGS(ctxt).fs)
+#define SIG_GS(info, ctxt) ((uint64)SIG_REGS(ctxt).gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) (((uintptr*)(info))[2])
+
diff --git a/src/pkg/runtime/signal_linux_arm.c b/src/pkg/runtime/signal_linux_arm.c
deleted file mode 100644
index c26caa7cd..000000000
--- a/src/pkg/runtime/signal_linux_arm.c
+++ /dev/null
@@ -1,241 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
- runtime·printf("trap %x\n", r->trap_no);
- runtime·printf("error %x\n", r->error_code);
- runtime·printf("oldmask %x\n", r->oldmask);
- runtime·printf("r0 %x\n", r->arm_r0);
- runtime·printf("r1 %x\n", r->arm_r1);
- runtime·printf("r2 %x\n", r->arm_r2);
- runtime·printf("r3 %x\n", r->arm_r3);
- runtime·printf("r4 %x\n", r->arm_r4);
- runtime·printf("r5 %x\n", r->arm_r5);
- runtime·printf("r6 %x\n", r->arm_r6);
- runtime·printf("r7 %x\n", r->arm_r7);
- runtime·printf("r8 %x\n", r->arm_r8);
- runtime·printf("r9 %x\n", r->arm_r9);
- runtime·printf("r10 %x\n", r->arm_r10);
- runtime·printf("fp %x\n", r->arm_fp);
- runtime·printf("ip %x\n", r->arm_ip);
- runtime·printf("sp %x\n", r->arm_sp);
- runtime·printf("lr %x\n", r->arm_lr);
- runtime·printf("pc %x\n", r->arm_pc);
- runtime·printf("cpsr %x\n", r->arm_cpsr);
- runtime·printf("fault %x\n", r->fault_address);
-}
-
-/*
- * This assembler routine takes the args from registers, puts them on the stack,
- * and calls sighandler().
- */
-extern void runtime·sigtramp(void);
-extern void runtime·sigreturn(void); // calls runtime·sigreturn
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Ucontext *uc;
- Sigcontext *r;
- SigTab *t;
-
- uc = context;
- r = &uc->uc_mcontext;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->arm_pc, (uint8*)r->arm_sp, (uint8*)r->arm_lr, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = r->fault_address;
- gp->sigpc = r->arm_pc;
-
- // We arrange lr, and pc to pretend the panicking
- // function calls sigpanic directly.
- // Always save LR to stack so that panics in leaf
- // functions are correctly handled. This smashes
- // the stack frame but we're not going back there
- // anyway.
- r->arm_sp -= 4;
- *(uint32 *)r->arm_sp = r->arm_lr;
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if(r->arm_pc != 0)
- r->arm_lr = r->arm_pc;
- // In case we are panicking from external C code
- r->arm_r10 = (uintptr)gp;
- r->arm_r9 = (uintptr)m;
- r->arm_pc = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- if(runtime·panicking) // traceback already printed
- runtime·exit(2);
- runtime·panicking = 1;
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%x\n", r->arm_pc);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->arm_pc, (void*)r->arm_sp, (void*)r->arm_lr, gp);
- runtime·tracebackothers(gp);
- runtime·printf("\n");
- runtime·dumpregs(r);
- }
-
-// breakpoint();
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- if(runtime·rt_sigaction(i, nil, &sa, sizeof(sa.sa_mask)) != 0)
- runtime·throw("rt_sigaction read failure");
- if(sa.sa_handler == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask = ~0ULL;
- sa.sa_restorer = (void*)runtime·sigreturn;
- if(fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.sa_handler = fn;
- if(runtime·rt_sigaction(i, &sa, nil, sizeof(sa.sa_mask)) != 0)
- runtime·throw("rt_sigaction failure");
-}
-
-#define AT_NULL 0
-#define AT_PLATFORM 15 // introduced in at least 2.6.11
-#define AT_HWCAP 16 // introduced in at least 2.6.11
-#define AT_RANDOM 25 // introduced in 2.6.29
-#define HWCAP_VFP (1 << 6) // introduced in at least 2.6.11
-#define HWCAP_VFPv3 (1 << 13) // introduced in 2.6.30
-static uint32 runtime·randomNumber;
-uint8 runtime·armArch = 6; // we default to ARMv6
-uint32 runtime·hwcap; // set by setup_auxv
-uint8 runtime·goarm; // set by 5l
-
-void
-runtime·checkgoarm(void)
-{
- if(runtime·goarm > 5 && !(runtime·hwcap & HWCAP_VFP)) {
- runtime·printf("runtime: this CPU has no floating point hardware, so it cannot run\n");
- runtime·printf("this GOARM=%d binary. Recompile using GOARM=5.\n", runtime·goarm);
- runtime·exit(1);
- }
- if(runtime·goarm > 6 && !(runtime·hwcap & HWCAP_VFPv3)) {
- runtime·printf("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n");
- runtime·printf("this GOARM=%d binary. Recompile using GOARM=6.\n", runtime·goarm);
- runtime·exit(1);
- }
-}
-
-#pragma textflag 7
-void
-runtime·setup_auxv(int32 argc, void *argv_list)
-{
- byte **argv;
- byte **envp;
- byte *rnd;
- uint32 *auxv;
- uint32 t;
-
- argv = &argv_list;
-
- // skip envp to get to ELF auxiliary vector.
- for(envp = &argv[argc+1]; *envp != nil; envp++)
- ;
- envp++;
-
- for(auxv=(uint32*)envp; auxv[0] != AT_NULL; auxv += 2) {
- switch(auxv[0]) {
- case AT_RANDOM: // kernel provided 16-byte worth of random data
- if(auxv[1]) {
- rnd = (byte*)auxv[1];
- runtime·randomNumber = rnd[4] | rnd[5]<<8 | rnd[6]<<16 | rnd[7]<<24;
- }
- break;
- case AT_PLATFORM: // v5l, v6l, v7l
- if(auxv[1]) {
- t = *(uint8*)(auxv[1]+1);
- if(t >= '5' && t <= '7')
- runtime·armArch = t - '0';
- }
- break;
- case AT_HWCAP: // CPU capability bit flags
- runtime·hwcap = auxv[1];
- break;
- }
- }
-}
-
-#pragma textflag 7
-int64
-runtime·cputicks(void)
-{
- // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
- // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
- // runtime·randomNumber provides better seeding of fastrand1.
- return runtime·nanotime() + runtime·randomNumber;
-}
diff --git a/src/pkg/runtime/signal_linux_arm.h b/src/pkg/runtime/signal_linux_arm.h
new file mode 100644
index 000000000..a674c0d57
--- /dev/null
+++ b/src/pkg/runtime/signal_linux_arm.h
@@ -0,0 +1,28 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext))
+
+#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).arm_r0)
+#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).arm_r1)
+#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).arm_r2)
+#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).arm_r3)
+#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).arm_r4)
+#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).arm_r5)
+#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).arm_r6)
+#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).arm_r7)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).arm_r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).arm_r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).arm_r10)
+#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).arm_fp)
+#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).arm_ip)
+#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).arm_sp)
+#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).arm_lr)
+#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).arm_pc)
+#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).arm_cpsr)
+#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).fault_address)
+#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap_no)
+#define SIG_ERROR(info, ctxt) (SIG_REGS(ctxt).error_code)
+#define SIG_OLDMASK(info, ctxt) (SIG_REGS(ctxt).oldmask)
+#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
diff --git a/src/pkg/runtime/signal_netbsd_386.c b/src/pkg/runtime/signal_netbsd_386.c
deleted file mode 100644
index 08744c425..000000000
--- a/src/pkg/runtime/signal_netbsd_386.c
+++ /dev/null
@@ -1,164 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-extern void runtime·lwp_tramp(void);
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*_sa_handler)(int32);
- void (*_sa_sigaction)(int32, Siginfo*, void *);
- } _sa_u; /* signal handler */
- uint32 sa_mask[4]; /* signal mask to apply */
- int32 sa_flags; /* see signal options below */
-} Sigaction;
-
-void
-runtime·dumpregs(McontextT *mc)
-{
- runtime·printf("eax %x\n", mc->__gregs[REG_EAX]);
- runtime·printf("ebx %x\n", mc->__gregs[REG_EBX]);
- runtime·printf("ecx %x\n", mc->__gregs[REG_ECX]);
- runtime·printf("edx %x\n", mc->__gregs[REG_EDX]);
- runtime·printf("edi %x\n", mc->__gregs[REG_EDI]);
- runtime·printf("esi %x\n", mc->__gregs[REG_ESI]);
- runtime·printf("ebp %x\n", mc->__gregs[REG_EBP]);
- runtime·printf("esp %x\n", mc->__gregs[REG_UESP]);
- runtime·printf("eip %x\n", mc->__gregs[REG_EIP]);
- runtime·printf("eflags %x\n", mc->__gregs[REG_EFL]);
- runtime·printf("cs %x\n", mc->__gregs[REG_CS]);
- runtime·printf("fs %x\n", mc->__gregs[REG_FS]);
- runtime·printf("gs %x\n", mc->__gregs[REG_GS]);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- UcontextT *uc = context;
- McontextT *mc = &uc->uc_mcontext;
- uintptr *sp;
- SigTab *t;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)mc->__gregs[REG_EIP],
- (uint8*)mc->__gregs[REG_UESP], nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // We need to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->_code;
- gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
- gp->sigpc = mc->__gregs[REG_EIP];
-
- // Only push runtime·sigpanic if __gregs[REG_EIP] != 0.
- // If __gregs[REG_EIP] == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will make the
- // trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic
- // and we won't get to see who faulted.)
- if(mc->__gregs[REG_EIP] != 0) {
- sp = (uintptr*)mc->__gregs[REG_UESP];
- *--sp = mc->__gregs[REG_EIP];
- mc->__gregs[REG_UESP] = (uintptr)sp;
- }
- mc->__gregs[REG_EIP] = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", mc->__gregs[REG_EIP]);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)mc->__gregs[REG_EIP],
- (void*)mc->__gregs[REG_UESP], 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(mc);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa._sa_u._sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask[0] = ~0U;
- sa.sa_mask[1] = ~0U;
- sa.sa_mask[2] = ~0U;
- sa.sa_mask[3] = ~0U;
- if (fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa._sa_u._sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
-{
- mc->__gregs[REG_EIP] = (uint32)runtime·lwp_tramp;
- mc->__gregs[REG_UESP] = (uint32)stack;
- mc->__gregs[REG_EBX] = (uint32)mp;
- mc->__gregs[REG_EDX] = (uint32)gp;
- mc->__gregs[REG_ESI] = (uint32)fn;
-}
diff --git a/src/pkg/runtime/signal_netbsd_386.h b/src/pkg/runtime/signal_netbsd_386.h
new file mode 100644
index 000000000..d5a8a0c4b
--- /dev/null
+++ b/src/pkg/runtime/signal_netbsd_386.h
@@ -0,0 +1,23 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((UcontextT*)(ctxt))->uc_mcontext)
+
+#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EAX])
+#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBX])
+#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ECX])
+#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDX])
+#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EDI])
+#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_ESI])
+#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EBP])
+#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_UESP])
+#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EIP])
+#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_EFL])
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS])
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS])
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS])
+
+#define SIG_CODE0(info, ctxt) ((info)->_code)
+#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0])
diff --git a/src/pkg/runtime/signal_netbsd_amd64.c b/src/pkg/runtime/signal_netbsd_amd64.c
deleted file mode 100644
index 46afb682b..000000000
--- a/src/pkg/runtime/signal_netbsd_amd64.c
+++ /dev/null
@@ -1,172 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-extern void runtime·lwp_tramp(void);
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*_sa_handler)(int32);
- void (*_sa_sigaction)(int32, Siginfo*, void *);
- } _sa_u; /* signal handler */
- uint32 sa_mask[4]; /* signal mask to apply */
- int32 sa_flags; /* see signal options below */
-} Sigaction;
-
-void
-runtime·dumpregs(McontextT *mc)
-{
- runtime·printf("rax %X\n", mc->__gregs[REG_RAX]);
- runtime·printf("rbx %X\n", mc->__gregs[REG_RBX]);
- runtime·printf("rcx %X\n", mc->__gregs[REG_RCX]);
- runtime·printf("rdx %X\n", mc->__gregs[REG_RDX]);
- runtime·printf("rdi %X\n", mc->__gregs[REG_RDI]);
- runtime·printf("rsi %X\n", mc->__gregs[REG_RSI]);
- runtime·printf("rbp %X\n", mc->__gregs[REG_RBP]);
- runtime·printf("rsp %X\n", mc->__gregs[REG_RSP]);
- runtime·printf("r8 %X\n", mc->__gregs[REG_R8]);
- runtime·printf("r9 %X\n", mc->__gregs[REG_R9]);
- runtime·printf("r10 %X\n", mc->__gregs[REG_R10]);
- runtime·printf("r11 %X\n", mc->__gregs[REG_R11]);
- runtime·printf("r12 %X\n", mc->__gregs[REG_R12]);
- runtime·printf("r13 %X\n", mc->__gregs[REG_R13]);
- runtime·printf("r14 %X\n", mc->__gregs[REG_R14]);
- runtime·printf("r15 %X\n", mc->__gregs[REG_R15]);
- runtime·printf("rip %X\n", mc->__gregs[REG_RIP]);
- runtime·printf("rflags %X\n", mc->__gregs[REG_RFLAGS]);
- runtime·printf("cs %X\n", mc->__gregs[REG_CS]);
- runtime·printf("fs %X\n", mc->__gregs[REG_FS]);
- runtime·printf("gs %X\n", mc->__gregs[REG_GS]);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- UcontextT *uc = context;
- McontextT *mc = &uc->uc_mcontext;
- uintptr *sp;
- SigTab *t;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)mc->__gregs[REG_RIP],
- (uint8*)mc->__gregs[REG_RSP], nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // We need to pass arguments out of band since augmenting the
- // stack frame would break the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->_code;
- gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
- gp->sigpc = mc->__gregs[REG_RIP];
-
- // Only push runtime·sigpanic if __gregs[REG_RIP] != 0.
- // If __gregs[REG_RIP] == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will make the
- // trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic
- // and we won't get to see who faulted.)
- if(mc->__gregs[REG_RIP] != 0) {
- sp = (uintptr*)mc->__gregs[REG_RSP];
- *--sp = mc->__gregs[REG_RIP];
- mc->__gregs[REG_RSP] = (uintptr)sp;
- }
- mc->__gregs[REG_RIP] = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", mc->__gregs[REG_RIP]);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)mc->__gregs[REG_RIP],
- (void*)mc->__gregs[REG_RSP], 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(mc);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa._sa_u._sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask[0] = ~0U;
- sa.sa_mask[1] = ~0U;
- sa.sa_mask[2] = ~0U;
- sa.sa_mask[3] = ~0U;
- if (fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa._sa_u._sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
-{
- // Machine dependent mcontext initialisation for LWP.
- mc->__gregs[REG_RIP] = (uint64)runtime·lwp_tramp;
- mc->__gregs[REG_RSP] = (uint64)stack;
- mc->__gregs[REG_R8] = (uint64)mp;
- mc->__gregs[REG_R9] = (uint64)gp;
- mc->__gregs[REG_R12] = (uint64)fn;
-}
diff --git a/src/pkg/runtime/signal_netbsd_amd64.h b/src/pkg/runtime/signal_netbsd_amd64.h
new file mode 100644
index 000000000..7ec4cd98c
--- /dev/null
+++ b/src/pkg/runtime/signal_netbsd_amd64.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((UcontextT*)(ctxt))->uc_mcontext)
+
+#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RAX])
+#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBX])
+#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RCX])
+#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDX])
+#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RDI])
+#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSI])
+#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RBP])
+#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RSP])
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R8])
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R9])
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R10])
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R11])
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R12])
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R13])
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R14])
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R15])
+#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RIP])
+#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_RFLAGS])
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CS])
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_FS])
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_GS])
+
+#define SIG_CODE0(info, ctxt) ((info)->_code)
+#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0])
diff --git a/src/pkg/runtime/signal_netbsd_arm.c b/src/pkg/runtime/signal_netbsd_arm.c
deleted file mode 100644
index 97f62687b..000000000
--- a/src/pkg/runtime/signal_netbsd_arm.c
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-#define r0 __gregs[0]
-#define r1 __gregs[1]
-#define r2 __gregs[2]
-#define r3 __gregs[3]
-#define r4 __gregs[4]
-#define r5 __gregs[5]
-#define r6 __gregs[6]
-#define r7 __gregs[7]
-#define r8 __gregs[8]
-#define r9 __gregs[9]
-#define r10 __gregs[10]
-#define r11 __gregs[11]
-#define r12 __gregs[12]
-#define r13 __gregs[13]
-#define r14 __gregs[14]
-#define r15 __gregs[15]
-#define cpsr __gregs[16]
-
-void
-runtime·dumpregs(McontextT *r)
-{
- runtime·printf("r0 %x\n", r->r0);
- runtime·printf("r1 %x\n", r->r1);
- runtime·printf("r2 %x\n", r->r2);
- runtime·printf("r3 %x\n", r->r3);
- runtime·printf("r4 %x\n", r->r4);
- runtime·printf("r5 %x\n", r->r5);
- runtime·printf("r6 %x\n", r->r6);
- runtime·printf("r7 %x\n", r->r7);
- runtime·printf("r8 %x\n", r->r8);
- runtime·printf("r9 %x\n", r->r9);
- runtime·printf("r10 %x\n", r->r10);
- runtime·printf("fp %x\n", r->r11);
- runtime·printf("ip %x\n", r->r12);
- runtime·printf("sp %x\n", r->r13);
- runtime·printf("lr %x\n", r->r14);
- runtime·printf("pc %x\n", r->r15);
- runtime·printf("cpsr %x\n", r->cpsr);
-}
-
-extern void runtime·lwp_tramp(void);
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*_sa_handler)(int32);
- void (*_sa_sigaction)(int32, Siginfo*, void *);
- } _sa_u; /* signal handler */
- uint32 sa_mask[4]; /* signal mask to apply */
- int32 sa_flags; /* see signal options below */
-} Sigaction;
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- UcontextT *uc;
- McontextT *r;
- SigTab *t;
-
- uc = context;
- r = &uc->uc_mcontext;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // We have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->_code;
- gp->sigcode1 = *(uintptr*)&info->_reason[0]; /* _addr */
- gp->sigpc = r->r15;
-
- // We arrange lr, and pc to pretend the panicking
- // function calls sigpanic directly.
- // Always save LR to stack so that panics in leaf
- // functions are correctly handled. This smashes
- // the stack frame but we're not going back there
- // anyway.
- r->r13 -= 4;
- *(uint32 *)r->r13 = r->r14;
- // Don't bother saving PC if it's zero, which is
- // probably a call to a nil func: the old link register
- // is more useful in the stack trace.
- if(r->r15 != 0)
- r->r14 = r->r15;
- // In case we are panicking from external C code
- r->r10 = (uintptr)gp;
- r->r9 = (uintptr)m;
- r->r15 = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%x\n", r->r15);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
- runtime·tracebackothers(gp);
- runtime·printf("\n");
- runtime·dumpregs(r);
- }
-
-// breakpoint();
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = (uint8*)p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa._sa_u._sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask[0] = ~0U;
- sa.sa_mask[1] = ~0U;
- sa.sa_mask[2] = ~0U;
- sa.sa_mask[3] = ~0U;
- if (fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa._sa_u._sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
-
-void
-runtime·lwp_mcontext_init(McontextT *mc, void *stack, M *mp, G *gp, void (*fn)(void))
-{
- mc->r15 = (uint32)runtime·lwp_tramp;
- mc->r13 = (uint32)stack;
- mc->r0 = (uint32)mp;
- mc->r1 = (uint32)gp;
- mc->r2 = (uint32)fn;
-}
-
-void
-runtime·checkgoarm(void)
-{
- // TODO(minux)
-}
-
-#pragma textflag 7
-int64
-runtime·cputicks() {
- // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
- // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
- // TODO: need more entropy to better seed fastrand1.
- return runtime·nanotime();
-}
diff --git a/src/pkg/runtime/signal_netbsd_arm.h b/src/pkg/runtime/signal_netbsd_arm.h
new file mode 100644
index 000000000..12f5827a6
--- /dev/null
+++ b/src/pkg/runtime/signal_netbsd_arm.h
@@ -0,0 +1,30 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (((UcontextT*)(ctxt))->uc_mcontext)
+
+#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R0])
+#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R1])
+#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R2])
+#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R3])
+#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R4])
+#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R5])
+#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R6])
+#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R7])
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R8])
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R9])
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R10])
+#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R11])
+#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R12])
+#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R13])
+#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R14])
+#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_R15])
+#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).__gregs[REG_CPSR])
+#define SIG_FAULT(info, ctxt) (*(uintptr*)&(info)->_reason[0])
+#define SIG_TRAP(info, ctxt) (0)
+#define SIG_ERROR(info, ctxt) (0)
+#define SIG_OLDMASK(info, ctxt) (0)
+
+#define SIG_CODE0(info, ctxt) ((info)->_code)
+#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->_reason[0])
diff --git a/src/pkg/runtime/signal_openbsd_386.c b/src/pkg/runtime/signal_openbsd_386.c
deleted file mode 100644
index 516797c8d..000000000
--- a/src/pkg/runtime/signal_openbsd_386.c
+++ /dev/null
@@ -1,147 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*__sa_handler)(int32);
- void (*__sa_sigaction)(int32, Siginfo*, void *);
- } __sigaction_u; /* signal handler */
- uint32 sa_mask; /* signal mask to apply */
- int32 sa_flags; /* see signal options below */
-} Sigaction;
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
- runtime·printf("eax %x\n", r->sc_eax);
- runtime·printf("ebx %x\n", r->sc_ebx);
- runtime·printf("ecx %x\n", r->sc_ecx);
- runtime·printf("edx %x\n", r->sc_edx);
- runtime·printf("edi %x\n", r->sc_edi);
- runtime·printf("esi %x\n", r->sc_esi);
- runtime·printf("ebp %x\n", r->sc_ebp);
- runtime·printf("esp %x\n", r->sc_esp);
- runtime·printf("eip %x\n", r->sc_eip);
- runtime·printf("eflags %x\n", r->sc_eflags);
- runtime·printf("cs %x\n", r->sc_cs);
- runtime·printf("fs %x\n", r->sc_fs);
- runtime·printf("gs %x\n", r->sc_gs);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Sigcontext *r = context;
- uintptr *sp;
- SigTab *t;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = *(uintptr*)((byte*)info + 12); /* si_addr */
- gp->sigpc = r->sc_eip;
-
- // Only push runtime·sigpanic if r->sc_eip != 0.
- // If r->sc_eip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->sc_eip != 0) {
- sp = (uintptr*)r->sc_esp;
- *--sp = r->sc_eip;
- r->sc_esp = (uintptr)sp;
- }
- r->sc_eip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", r->sc_eip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask = ~0ULL;
- if (fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.__sigaction_u.__sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
diff --git a/src/pkg/runtime/signal_openbsd_386.h b/src/pkg/runtime/signal_openbsd_386.h
new file mode 100644
index 000000000..0ba66ab9f
--- /dev/null
+++ b/src/pkg/runtime/signal_openbsd_386.h
@@ -0,0 +1,23 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (*(Sigcontext*)(ctxt))
+
+#define SIG_EAX(info, ctxt) (SIG_REGS(ctxt).sc_eax)
+#define SIG_EBX(info, ctxt) (SIG_REGS(ctxt).sc_ebx)
+#define SIG_ECX(info, ctxt) (SIG_REGS(ctxt).sc_ecx)
+#define SIG_EDX(info, ctxt) (SIG_REGS(ctxt).sc_edx)
+#define SIG_EDI(info, ctxt) (SIG_REGS(ctxt).sc_edi)
+#define SIG_ESI(info, ctxt) (SIG_REGS(ctxt).sc_esi)
+#define SIG_EBP(info, ctxt) (SIG_REGS(ctxt).sc_ebp)
+#define SIG_ESP(info, ctxt) (SIG_REGS(ctxt).sc_esp)
+#define SIG_EIP(info, ctxt) (SIG_REGS(ctxt).sc_eip)
+#define SIG_EFLAGS(info, ctxt) (SIG_REGS(ctxt).sc_eflags)
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).sc_cs)
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).sc_fs)
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).sc_gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) ((uintptr)(info)->si_addr)
diff --git a/src/pkg/runtime/signal_openbsd_amd64.c b/src/pkg/runtime/signal_openbsd_amd64.c
deleted file mode 100644
index 0d0db770b..000000000
--- a/src/pkg/runtime/signal_openbsd_amd64.c
+++ /dev/null
@@ -1,156 +0,0 @@
-// 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 "runtime.h"
-#include "defs_GOOS_GOARCH.h"
-#include "signals_GOOS.h"
-#include "os_GOOS.h"
-
-extern void runtime·sigtramp(void);
-
-typedef struct sigaction {
- union {
- void (*__sa_handler)(int32);
- void (*__sa_sigaction)(int32, Siginfo*, void *);
- } __sigaction_u; /* signal handler */
- uint32 sa_mask; /* signal mask to apply */
- int32 sa_flags; /* see signal options below */
-} Sigaction;
-
-void
-runtime·dumpregs(Sigcontext *r)
-{
- runtime·printf("rax %X\n", r->sc_rax);
- runtime·printf("rbx %X\n", r->sc_rbx);
- runtime·printf("rcx %X\n", r->sc_rcx);
- runtime·printf("rdx %X\n", r->sc_rdx);
- runtime·printf("rdi %X\n", r->sc_rdi);
- runtime·printf("rsi %X\n", r->sc_rsi);
- runtime·printf("rbp %X\n", r->sc_rbp);
- runtime·printf("rsp %X\n", r->sc_rsp);
- runtime·printf("r8 %X\n", r->sc_r8);
- runtime·printf("r9 %X\n", r->sc_r9);
- runtime·printf("r10 %X\n", r->sc_r10);
- runtime·printf("r11 %X\n", r->sc_r11);
- runtime·printf("r12 %X\n", r->sc_r12);
- runtime·printf("r13 %X\n", r->sc_r13);
- runtime·printf("r14 %X\n", r->sc_r14);
- runtime·printf("r15 %X\n", r->sc_r15);
- runtime·printf("rip %X\n", r->sc_rip);
- runtime·printf("rflags %X\n", r->sc_rflags);
- runtime·printf("cs %X\n", r->sc_cs);
- runtime·printf("fs %X\n", r->sc_fs);
- runtime·printf("gs %X\n", r->sc_gs);
-}
-
-void
-runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
-{
- Sigcontext *r = context;
- uintptr *sp;
- SigTab *t;
-
- if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->sc_rip,
- (uint8*)r->sc_rsp, nil, gp);
- return;
- }
-
- t = &runtime·sigtab[sig];
- if(info->si_code != SI_USER && (t->flags & SigPanic)) {
- if(gp == nil || gp == m->g0)
- goto Throw;
- // Make it look like a call to the signal func.
- // Have to pass arguments out of band since
- // augmenting the stack frame would break
- // the unwinding code.
- gp->sig = sig;
- gp->sigcode0 = info->si_code;
- gp->sigcode1 = *(uintptr*)((byte*)info + 16); /* si_addr */
- gp->sigpc = r->sc_rip;
-
- // Only push runtime·sigpanic if r->sc_rip != 0.
- // If r->sc_rip == 0, probably panicked because of a
- // call to a nil func. Not pushing that onto sp will
- // make the trace look like a call to runtime·sigpanic instead.
- // (Otherwise the trace will end at runtime·sigpanic and we
- // won't get to see who faulted.)
- if(r->sc_rip != 0) {
- sp = (uintptr*)r->sc_rsp;
- *--sp = r->sc_rip;
- r->sc_rsp = (uintptr)sp;
- }
- r->sc_rip = (uintptr)runtime·sigpanic;
- return;
- }
-
- if(info->si_code == SI_USER || (t->flags & SigNotify))
- if(runtime·sigsend(sig))
- return;
- if(t->flags & SigKill)
- runtime·exit(2);
- if(!(t->flags & SigThrow))
- return;
-
-Throw:
- runtime·startpanic();
-
- if(sig < 0 || sig >= NSIG)
- runtime·printf("Signal %d\n", sig);
- else
- runtime·printf("%s\n", runtime·sigtab[sig].name);
-
- runtime·printf("PC=%X\n", r->sc_rip);
- if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
- runtime·printf("signal arrived during cgo execution\n");
- gp = m->lockedg;
- }
- runtime·printf("\n");
-
- if(runtime·gotraceback()){
- runtime·traceback((void*)r->sc_rip, (void*)r->sc_rsp, 0, gp);
- runtime·tracebackothers(gp);
- runtime·dumpregs(r);
- }
-
- runtime·exit(2);
-}
-
-void
-runtime·signalstack(byte *p, int32 n)
-{
- Sigaltstack st;
-
- st.ss_sp = p;
- st.ss_size = n;
- st.ss_flags = 0;
- if(p == nil)
- st.ss_flags = SS_DISABLE;
- runtime·sigaltstack(&st, nil);
-}
-
-void
-runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
-{
- Sigaction sa;
-
- // If SIGHUP handler is SIG_IGN, assume running
- // under nohup and do not set explicit handler.
- if(i == SIGHUP) {
- runtime·memclr((byte*)&sa, sizeof sa);
- runtime·sigaction(i, nil, &sa);
- if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
- return;
- }
-
- runtime·memclr((byte*)&sa, sizeof sa);
- sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
- if(restart)
- sa.sa_flags |= SA_RESTART;
- sa.sa_mask = ~0U;
- if(fn == runtime·sighandler)
- fn = (void*)runtime·sigtramp;
- sa.__sigaction_u.__sa_sigaction = (void*)fn;
- runtime·sigaction(i, &sa, nil);
-}
diff --git a/src/pkg/runtime/signal_openbsd_amd64.h b/src/pkg/runtime/signal_openbsd_amd64.h
new file mode 100644
index 000000000..b46a5dfa6
--- /dev/null
+++ b/src/pkg/runtime/signal_openbsd_amd64.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_REGS(ctxt) (*(Sigcontext*)(ctxt))
+
+#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).sc_rax)
+#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).sc_rbx)
+#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).sc_rcx)
+#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).sc_rdx)
+#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).sc_rdi)
+#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).sc_rsi)
+#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).sc_rbp)
+#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).sc_rsp)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).sc_r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).sc_r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).sc_r10)
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).sc_r11)
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).sc_r12)
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).sc_r13)
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).sc_r14)
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).sc_r15)
+#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).sc_rip)
+#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).sc_rflags)
+
+#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).sc_cs)
+#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).sc_fs)
+#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).sc_gs)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) (*(uintptr*)((byte*)(info) + 16))
diff --git a/src/pkg/runtime/signal_unix.c b/src/pkg/runtime/signal_unix.c
index 9b7e8b03a..54e461f99 100644
--- a/src/pkg/runtime/signal_unix.c
+++ b/src/pkg/runtime/signal_unix.c
@@ -7,6 +7,7 @@
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
+#include "signal_unix.h"
extern SigTab runtime·sigtab[];
@@ -21,6 +22,20 @@ runtime·initsig(void)
t = &runtime·sigtab[i];
if((t->flags == 0) || (t->flags & SigDefault))
continue;
+
+ // For some signals, we respect an inherited SIG_IGN handler
+ // rather than insist on installing our own default handler.
+ // Even these signals can be fetched using the os/signal package.
+ switch(i) {
+ case SIGHUP:
+ case SIGINT:
+ if(runtime·getsig(i) == SIG_IGN) {
+ t->flags = SigNotify | SigIgnored;
+ continue;
+ }
+ }
+
+ t->flags |= SigHandling;
runtime·setsig(i, runtime·sighandler, true);
}
}
@@ -28,18 +43,35 @@ runtime·initsig(void)
void
runtime·sigenable(uint32 sig)
{
- int32 i;
SigTab *t;
- for(i = 0; i<NSIG; i++) {
- // ~0 means all signals.
- if(~sig == 0 || i == sig) {
- t = &runtime·sigtab[i];
- if(t->flags & SigDefault) {
- runtime·setsig(i, runtime·sighandler, true);
- t->flags &= ~SigDefault; // make this idempotent
- }
- }
+ if(sig >= NSIG)
+ return;
+
+ t = &runtime·sigtab[sig];
+ if((t->flags & SigNotify) && !(t->flags & SigHandling)) {
+ t->flags |= SigHandling;
+ if(runtime·getsig(sig) == SIG_IGN)
+ t->flags |= SigIgnored;
+ runtime·setsig(sig, runtime·sighandler, true);
+ }
+}
+
+void
+runtime·sigdisable(uint32 sig)
+{
+ SigTab *t;
+
+ if(sig >= NSIG)
+ return;
+
+ t = &runtime·sigtab[sig];
+ if((t->flags & SigNotify) && (t->flags & SigHandling)) {
+ t->flags &= ~SigHandling;
+ if(t->flags & SigIgnored)
+ runtime·setsig(sig, SIG_IGN, true);
+ else
+ runtime·setsig(sig, SIG_DFL, true);
}
}
@@ -66,5 +98,23 @@ void
os·sigpipe(void)
{
runtime·setsig(SIGPIPE, SIG_DFL, false);
- runtime·raisesigpipe();
+ runtime·raise(SIGPIPE);
+}
+
+void
+runtime·crash(void)
+{
+#ifdef GOOS_darwin
+ // OS X core dumps are linear dumps of the mapped memory,
+ // from the first virtual byte to the last, with zeros in the gaps.
+ // Because of the way we arrange the address space on 64-bit systems,
+ // this means the OS X core file will be >128 GB and even on a zippy
+ // workstation can take OS X well over an hour to write (uninterruptible).
+ // Save users from making that mistake.
+ if(sizeof(void*) == 8)
+ return;
+#endif
+
+ runtime·setsig(SIGABRT, SIG_DFL, false);
+ runtime·raise(SIGABRT);
}
diff --git a/src/pkg/runtime/signal_unix.h b/src/pkg/runtime/signal_unix.h
new file mode 100644
index 000000000..2d84a0186
--- /dev/null
+++ b/src/pkg/runtime/signal_unix.h
@@ -0,0 +1,14 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SIG_DFL ((void*)0)
+#define SIG_IGN ((void*)1)
+
+typedef void GoSighandler(int32, Siginfo*, void*, G*);
+void runtime·setsig(int32, GoSighandler*, bool);
+GoSighandler* runtime·getsig(int32);
+
+void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
+void runtime·raise(int32);
+
diff --git a/src/pkg/runtime/signals_plan9.h b/src/pkg/runtime/signals_plan9.h
index 0f1165e2a..f9bec65fc 100644
--- a/src/pkg/runtime/signals_plan9.h
+++ b/src/pkg/runtime/signals_plan9.h
@@ -1,3 +1,7 @@
+// 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.
+
#define N SigNotify
#define T SigThrow
#define P SigPanic
diff --git a/src/pkg/runtime/sigqueue.goc b/src/pkg/runtime/sigqueue.goc
index ab5f312e4..7e083685d 100644
--- a/src/pkg/runtime/sigqueue.goc
+++ b/src/pkg/runtime/sigqueue.goc
@@ -133,8 +133,6 @@ done:;
// Must only be called from a single goroutine at a time.
func signal_enable(s uint32) {
- int32 i;
-
if(!sig.inuse) {
// The first call to signal_enable is for us
// to use for initialization. It does not pass
@@ -144,16 +142,16 @@ func signal_enable(s uint32) {
return;
}
- if(~s == 0) {
- // Special case: want everything.
- for(i=0; i<nelem(sig.wanted); i++)
- sig.wanted[i] = ~(uint32)0;
- runtime·sigenable(s);
- return;
- }
-
if(s >= nelem(sig.wanted)*32)
return;
sig.wanted[s/32] |= 1U<<(s&31);
runtime·sigenable(s);
}
+
+// Must only be called from a single goroutine at a time.
+func signal_disable(s uint32) {
+ if(s >= nelem(sig.wanted)*32)
+ return;
+ sig.wanted[s/32] &= ~(1U<<(s&31));
+ runtime·sigdisable(s);
+}
diff --git a/src/pkg/runtime/stack_test.go b/src/pkg/runtime/stack_test.go
index 759f7c46e..da0181a66 100644
--- a/src/pkg/runtime/stack_test.go
+++ b/src/pkg/runtime/stack_test.go
@@ -1533,7 +1533,7 @@ func stack5000() (uintptr, uintptr) { var buf [5000]byte; use(buf[:]); return St
func TestStackMem(t *testing.T) {
const (
BatchSize = 32
- BatchCount = 512
+ BatchCount = 256
ArraySize = 1024
RecursionDepth = 128
)
@@ -1562,6 +1562,11 @@ func TestStackMem(t *testing.T) {
for i := 0; i < BatchSize; i++ {
<-c
}
+
+ // The goroutines have signaled via c that they are ready to exit.
+ // Give them a chance to exit by sleeping. If we don't wait, we
+ // might not reuse them on the next batch.
+ time.Sleep(10 * time.Millisecond)
}
s1 := new(MemStats)
ReadMemStats(s1)
@@ -1571,7 +1576,9 @@ func TestStackMem(t *testing.T) {
if consumed > estimate {
t.Fatalf("Stack mem: want %v, got %v", estimate, consumed)
}
- if s1.StackInuse > 4<<20 {
- t.Fatalf("Stack inuse: want %v, got %v", 4<<20, s1.StackInuse)
+ inuse := s1.StackInuse - s0.StackInuse
+ t.Logf("Inuse %vMB for stack mem", inuse>>20)
+ if inuse > 4<<20 {
+ t.Fatalf("Stack inuse: want %v, got %v", 4<<20, inuse)
}
}
diff --git a/src/pkg/runtime/string_test.go b/src/pkg/runtime/string_test.go
index 8f13f0f42..6ba3c1d29 100644
--- a/src/pkg/runtime/string_test.go
+++ b/src/pkg/runtime/string_test.go
@@ -1,3 +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.
+
package runtime_test
import (
diff --git a/src/pkg/runtime/symtab.c b/src/pkg/runtime/symtab.c
index d7221c476..578406247 100644
--- a/src/pkg/runtime/symtab.c
+++ b/src/pkg/runtime/symtab.c
@@ -670,6 +670,6 @@ runtime·showframe(Func *f, bool current)
if(current && m->throwing > 0)
return 1;
if(traceback < 0)
- traceback = runtime·gotraceback();
+ traceback = runtime·gotraceback(nil);
return traceback > 1 || f != nil && contains(f->name, ".") && !hasprefix(f->name, "runtime.");
}
diff --git a/src/pkg/runtime/sys_darwin_386.s b/src/pkg/runtime/sys_darwin_386.s
index 8a938f9f4..59bb9d80d 100644
--- a/src/pkg/runtime/sys_darwin_386.s
+++ b/src/pkg/runtime/sys_darwin_386.s
@@ -24,18 +24,34 @@ TEXT runtime·exit1(SB),7,$0
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$0
+ MOVL $5, AX
+ INT $0x80
+ RET
+
+TEXT runtime·close(SB),7,$0
+ MOVL $6, AX
+ INT $0x80
+ RET
+
+TEXT runtime·read(SB),7,$0
+ MOVL $3, AX
+ INT $0x80
+ RET
+
TEXT runtime·write(SB),7,$0
MOVL $4, AX
INT $0x80
RET
-TEXT runtime·raisesigpipe(SB),7,$8
- get_tls(CX)
- MOVL m(CX), DX
- MOVL m_procid(DX), DX
- MOVL DX, 0(SP) // thread_port
- MOVL $13, 4(SP) // signal: SIGPIPE
- MOVL $328, AX // __pthread_kill
+TEXT runtime·raise(SB),7,$16
+ MOVL $20, AX // getpid
+ INT $0x80
+ MOVL AX, 4(SP) // pid
+ MOVL sig+0(FP), AX
+ MOVL AX, 8(SP) // signal
+ MOVL $1, 12(SP) // posix
+ MOVL $37, AX // kill
INT $0x80
RET
@@ -473,3 +489,32 @@ TEXT runtime·sysctl(SB),7,$0
RET
MOVL $0, AX
RET
+
+// int32 runtime·kqueue(void);
+TEXT runtime·kqueue(SB),7,$0
+ MOVL $362, AX
+ INT $0x80
+ JAE 2(PC)
+ NEGL AX
+ RET
+
+// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
+TEXT runtime·kevent(SB),7,$0
+ MOVL $363, AX
+ INT $0x80
+ JAE 2(PC)
+ NEGL AX
+ RET
+
+// int32 runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),7,$32
+ MOVL $92, AX // fcntl
+ // 0(SP) is where the caller PC would be; kernel skips it
+ MOVL fd+0(FP), BX
+ MOVL BX, 4(SP) // fd
+ MOVL $2, 8(SP) // F_SETFD
+ MOVL $1, 12(SP) // FD_CLOEXEC
+ INT $0x80
+ JAE 2(PC)
+ NEGL AX
+ RET
diff --git a/src/pkg/runtime/sys_darwin_amd64.s b/src/pkg/runtime/sys_darwin_amd64.s
index 4e43a76c3..b324a0424 100644
--- a/src/pkg/runtime/sys_darwin_amd64.s
+++ b/src/pkg/runtime/sys_darwin_amd64.s
@@ -30,6 +30,28 @@ TEXT runtime·exit1(SB),7,$0
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$0
+ MOVQ 8(SP), DI // arg 1 pathname
+ MOVL 16(SP), SI // arg 2 flags
+ MOVL 20(SP), DX // arg 3 mode
+ MOVL $(0x2000000+5), AX // syscall entry
+ SYSCALL
+ RET
+
+TEXT runtime·close(SB),7,$0
+ MOVL 8(SP), DI // arg 1 fd
+ MOVL $(0x2000000+6), AX // syscall entry
+ SYSCALL
+ RET
+
+TEXT runtime·read(SB),7,$0
+ MOVL 8(SP), DI // arg 1 fd
+ MOVQ 16(SP), SI // arg 2 buf
+ MOVL 24(SP), DX // arg 3 count
+ MOVL $(0x2000000+3), AX // syscall entry
+ SYSCALL
+ RET
+
TEXT runtime·write(SB),7,$0
MOVL 8(SP), DI // arg 1 fd
MOVQ 16(SP), SI // arg 2 buf
@@ -38,12 +60,13 @@ TEXT runtime·write(SB),7,$0
SYSCALL
RET
-TEXT runtime·raisesigpipe(SB),7,$24
- get_tls(CX)
- MOVQ m(CX), DX
- MOVL $13, DI // arg 1 SIGPIPE
- MOVQ m_procid(DX), SI // arg 2 thread_port
- MOVL $(0x2000000+328), AX // syscall entry __pthread_kill
+TEXT runtime·raise(SB),7,$24
+ MOVL $(0x2000000+20), AX // getpid
+ SYSCALL
+ MOVQ AX, DI // arg 1 - pid
+ MOVL sig+0(FP), SI // arg 2 - signal
+ MOVL $1, DX // arg 3 - posix
+ MOVL $(0x2000000+37), AX // kill
SYSCALL
RET
@@ -267,7 +290,7 @@ TEXT runtime·bsdthread_create(SB),7,$0
MOVQ $(0x2000000+360), AX // bsdthread_create
SYSCALL
JCC 3(PC)
- NEGL AX
+ NEGQ AX
RET
MOVL $0, AX
RET
@@ -320,7 +343,7 @@ TEXT runtime·bsdthread_register(SB),7,$0
MOVQ $(0x2000000+366), AX // bsdthread_register
SYSCALL
JCC 3(PC)
- NEGL AX
+ NEGQ AX
RET
MOVL $0, AX
RET
@@ -413,7 +436,41 @@ TEXT runtime·sysctl(SB),7,$0
MOVL $(0x2000000+202), AX // syscall entry
SYSCALL
JCC 3(PC)
- NEGL AX
+ NEGQ AX
RET
MOVL $0, AX
RET
+
+// int32 runtime·kqueue(void);
+TEXT runtime·kqueue(SB),7,$0
+ MOVQ $0, DI
+ MOVQ $0, SI
+ MOVQ $0, DX
+ MOVL $(0x2000000+362), AX
+ SYSCALL
+ JCC 2(PC)
+ NEGQ AX
+ RET
+
+// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
+TEXT runtime·kevent(SB),7,$0
+ MOVL 8(SP), DI
+ MOVQ 16(SP), SI
+ MOVL 24(SP), DX
+ MOVQ 32(SP), R10
+ MOVL 40(SP), R8
+ MOVQ 48(SP), R9
+ MOVL $(0x2000000+363), AX
+ SYSCALL
+ JCC 2(PC)
+ NEGQ AX
+ RET
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),7,$0
+ MOVL 8(SP), DI // fd
+ MOVQ $2, SI // F_SETFD
+ MOVQ $1, DX // FD_CLOEXEC
+ MOVL $(0x2000000+92), AX // fcntl
+ SYSCALL
+ RET
diff --git a/src/pkg/runtime/sys_freebsd_386.s b/src/pkg/runtime/sys_freebsd_386.s
index d5370267a..d960663cb 100644
--- a/src/pkg/runtime/sys_freebsd_386.s
+++ b/src/pkg/runtime/sys_freebsd_386.s
@@ -56,6 +56,21 @@ TEXT runtime·exit1(SB),7,$-4
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$-4
+ MOVL $5, AX
+ INT $0x80
+ RET
+
+TEXT runtime·close(SB),7,$-4
+ MOVL $6, AX
+ INT $0x80
+ RET
+
+TEXT runtime·read(SB),7,$-4
+ MOVL $3, AX
+ INT $0x80
+ RET
+
TEXT runtime·write(SB),7,$-4
MOVL $4, AX
INT $0x80
@@ -66,16 +81,17 @@ TEXT runtime·getrlimit(SB),7,$-4
INT $0x80
RET
-TEXT runtime·raisesigpipe(SB),7,$12
+TEXT runtime·raise(SB),7,$16
// thr_self(&8(SP))
LEAL 8(SP), AX
- MOVL AX, 0(SP)
+ MOVL AX, 4(SP)
MOVL $432, AX
INT $0x80
// thr_kill(self, SIGPIPE)
MOVL 8(SP), AX
- MOVL AX, 0(SP)
- MOVL $13, 4(SP)
+ MOVL AX, 4(SP)
+ MOVL sig+0(FP), AX
+ MOVL AX, 8(SP)
MOVL $433, AX
INT $0x80
RET
diff --git a/src/pkg/runtime/sys_freebsd_amd64.s b/src/pkg/runtime/sys_freebsd_amd64.s
index 40c6237e2..cfa33d4fb 100644
--- a/src/pkg/runtime/sys_freebsd_amd64.s
+++ b/src/pkg/runtime/sys_freebsd_amd64.s
@@ -58,6 +58,28 @@ TEXT runtime·exit1(SB),7,$-8
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$-8
+ MOVQ 8(SP), DI // arg 1 pathname
+ MOVL 16(SP), SI // arg 2 flags
+ MOVL 20(SP), DX // arg 3 mode
+ MOVL $5, AX
+ SYSCALL
+ RET
+
+TEXT runtime·close(SB),7,$-8
+ MOVL 8(SP), DI // arg 1 fd
+ MOVL $6, AX
+ SYSCALL
+ RET
+
+TEXT runtime·read(SB),7,$-8
+ MOVL 8(SP), DI // arg 1 fd
+ MOVQ 16(SP), SI // arg 2 buf
+ MOVL 24(SP), DX // arg 3 count
+ MOVL $3, AX
+ SYSCALL
+ RET
+
TEXT runtime·write(SB),7,$-8
MOVL 8(SP), DI // arg 1 fd
MOVQ 16(SP), SI // arg 2 buf
@@ -73,14 +95,14 @@ TEXT runtime·getrlimit(SB),7,$-8
SYSCALL
RET
-TEXT runtime·raisesigpipe(SB),7,$16
+TEXT runtime·raise(SB),7,$16
// thr_self(&8(SP))
LEAQ 8(SP), DI // arg 1 &8(SP)
MOVL $432, AX
SYSCALL
// thr_kill(self, SIGPIPE)
MOVQ 8(SP), DI // arg 1 id
- MOVQ $13, SI // arg 2 SIGPIPE
+ MOVL sig+0(FP), SI // arg 2
MOVL $433, AX
SYSCALL
RET
@@ -239,7 +261,7 @@ TEXT runtime·sysctl(SB),7,$0
MOVQ $202, AX // sys___sysctl
SYSCALL
JCC 3(PC)
- NEGL AX
+ NEGQ AX
RET
MOVL $0, AX
RET
diff --git a/src/pkg/runtime/sys_freebsd_arm.s b/src/pkg/runtime/sys_freebsd_arm.s
index 77050e8d0..5531936ff 100644
--- a/src/pkg/runtime/sys_freebsd_arm.s
+++ b/src/pkg/runtime/sys_freebsd_arm.s
@@ -54,6 +54,20 @@ TEXT runtime·exit1(SB),7,$-8
MOVW.CS R9, (R9)
RET
+TEXT runtime·open(SB),7,$-8
+ MOVW 0(FP), R0 // arg 1 name
+ MOVW 4(FP), R1 // arg 2 mode
+ MOVW 8(FP), R2 // arg 3 perm
+ SWI $5
+ RET
+
+TEXT runtime·read(SB),7,$-8
+ MOVW 0(FP), R0 // arg 1 fd
+ MOVW 4(FP), R1 // arg 2 buf
+ MOVW 8(FP), R2 // arg 3 count
+ SWI $3
+ RET
+
TEXT runtime·write(SB),7,$-8
MOVW 0(FP), R0 // arg 1 fd
MOVW 4(FP), R1 // arg 2 buf
@@ -61,6 +75,11 @@ TEXT runtime·write(SB),7,$-8
SWI $4
RET
+TEXT runtime·close(SB),7,$-8
+ MOVW 0(FP), R0 // arg 1 fd
+ SWI $6
+ RET
+
TEXT runtime·getrlimit(SB),7,$-8
MOVW 0(FP), R0
MOVW 4(FP), R1
@@ -68,13 +87,13 @@ TEXT runtime·getrlimit(SB),7,$-8
SWI $194
RET
-TEXT runtime·raisesigpipe(SB),7,$8
+TEXT runtime·raise(SB),7,$8
// thr_self(&4(R13))
MOVW $4(R13), R0 // arg 1 &4(R13)
SWI $432
// thr_kill(self, SIGPIPE)
MOVW 4(R13), R0 // arg 1 id
- MOVW $13, R1 // arg 2 SIGPIPE
+ MOVW sig+0(FP), R1 // arg 2 - signal
SWI $433
RET
diff --git a/src/pkg/runtime/sys_linux_386.s b/src/pkg/runtime/sys_linux_386.s
index f27fd4713..76ebe3dcf 100644
--- a/src/pkg/runtime/sys_linux_386.s
+++ b/src/pkg/runtime/sys_linux_386.s
@@ -77,11 +77,11 @@ TEXT runtime·usleep(SB),7,$8
CALL *runtime·_vdso(SB)
RET
-TEXT runtime·raisesigpipe(SB),7,$12
+TEXT runtime·raise(SB),7,$12
MOVL $224, AX // syscall - gettid
CALL *runtime·_vdso(SB)
- MOVL AX, 0(SP) // arg 1 tid
- MOVL $13, 4(SP) // arg 2 SIGPIPE
+ MOVL AX, BX // arg 1 tid
+ MOVL sig+0(FP), CX // arg 2 signal
MOVL $238, AX // syscall - tkill
CALL *runtime·_vdso(SB)
RET
@@ -430,3 +430,46 @@ TEXT runtime·sched_getaffinity(SB),7,$0
MOVL 12(SP), DX
CALL *runtime·_vdso(SB)
RET
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),7,$0
+ MOVL $254, AX
+ MOVL 4(SP), BX
+ CALL *runtime·_vdso(SB)
+ RET
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),7,$0
+ MOVL $329, AX
+ MOVL 4(SP), BX
+ CALL *runtime·_vdso(SB)
+ RET
+
+// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
+TEXT runtime·epollctl(SB),7,$0
+ MOVL $255, AX
+ MOVL 4(SP), BX
+ MOVL 8(SP), CX
+ MOVL 12(SP), DX
+ MOVL 16(SP), SI
+ CALL *runtime·_vdso(SB)
+ RET
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),7,$0
+ MOVL $256, AX
+ MOVL 4(SP), BX
+ MOVL 8(SP), CX
+ MOVL 12(SP), DX
+ MOVL 16(SP), SI
+ CALL *runtime·_vdso(SB)
+ RET
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),7,$0
+ MOVL $55, AX // fcntl
+ MOVL 4(SP), BX // fd
+ MOVL $2, CX // F_SETFD
+ MOVL $1, DX // FD_CLOEXEC
+ CALL *runtime·_vdso(SB)
+ RET
diff --git a/src/pkg/runtime/sys_linux_amd64.s b/src/pkg/runtime/sys_linux_amd64.s
index e45943758..2d802abb6 100644
--- a/src/pkg/runtime/sys_linux_amd64.s
+++ b/src/pkg/runtime/sys_linux_amd64.s
@@ -75,11 +75,11 @@ TEXT runtime·usleep(SB),7,$16
SYSCALL
RET
-TEXT runtime·raisesigpipe(SB),7,$12
+TEXT runtime·raise(SB),7,$12
MOVL $186, AX // syscall - gettid
SYSCALL
MOVL AX, DI // arg 1 tid
- MOVL $13, SI // arg 2 SIGPIPE
+ MOVL sig+0(FP), SI // arg 2
MOVL $200, AX // syscall - tkill
SYSCALL
RET
@@ -347,3 +347,46 @@ TEXT runtime·sched_getaffinity(SB),7,$0
MOVL $204, AX // syscall entry
SYSCALL
RET
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),7,$0
+ MOVL 8(SP), DI
+ MOVL $213, AX // syscall entry
+ SYSCALL
+ RET
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),7,$0
+ MOVL 8(SP), DI
+ MOVL $291, AX // syscall entry
+ SYSCALL
+ RET
+
+// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
+TEXT runtime·epollctl(SB),7,$0
+ MOVL 8(SP), DI
+ MOVL 12(SP), SI
+ MOVL 16(SP), DX
+ MOVQ 24(SP), R10
+ MOVL $233, AX // syscall entry
+ SYSCALL
+ RET
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),7,$0
+ MOVL 8(SP), DI
+ MOVQ 16(SP), SI
+ MOVL 24(SP), DX
+ MOVL 28(SP), R10
+ MOVL $232, AX // syscall entry
+ SYSCALL
+ RET
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),7,$0
+ MOVL 8(SP), DI // fd
+ MOVQ $2, SI // F_SETFD
+ MOVQ $1, DX // FD_CLOEXEC
+ MOVL $72, AX // fcntl
+ SYSCALL
+ RET
diff --git a/src/pkg/runtime/sys_linux_arm.s b/src/pkg/runtime/sys_linux_arm.s
index 8bae2933f..7f813482d 100644
--- a/src/pkg/runtime/sys_linux_arm.s
+++ b/src/pkg/runtime/sys_linux_arm.s
@@ -36,6 +36,11 @@
#define SYS_ugetrlimit (SYS_BASE + 191)
#define SYS_sched_getaffinity (SYS_BASE + 242)
#define SYS_clock_gettime (SYS_BASE + 263)
+#define SYS_epoll_create (SYS_BASE + 250)
+#define SYS_epoll_ctl (SYS_BASE + 251)
+#define SYS_epoll_wait (SYS_BASE + 252)
+#define SYS_epoll_create1 (SYS_BASE + 357)
+#define SYS_fcntl (SYS_BASE + 55)
#define ARM_BASE (SYS_BASE + 0x0f0000)
@@ -92,11 +97,11 @@ TEXT runtime·exit1(SB),7,$-4
MOVW $1003, R1
MOVW R0, (R1) // fail hard
-TEXT runtime·raisesigpipe(SB),7,$-4
+TEXT runtime·raise(SB),7,$-4
MOVW $SYS_gettid, R7
SWI $0
// arg 1 tid already in R0 from gettid
- MOVW $13, R1 // arg 2 SIGPIPE
+ MOVW sig+0(FP), R1 // arg 2 - signal
MOVW $SYS_tkill, R7
SWI $0
RET
@@ -371,7 +376,6 @@ cascheck:
MOVW $0, R0
RET
-
TEXT runtime·casp(SB),7,$0
B runtime·cas(SB)
@@ -387,3 +391,46 @@ TEXT runtime·sched_getaffinity(SB),7,$0
MOVW $SYS_sched_getaffinity, R7
SWI $0
RET
+
+// int32 runtime·epollcreate(int32 size)
+TEXT runtime·epollcreate(SB),7,$0
+ MOVW 0(FP), R0
+ MOVW $SYS_epoll_create, R7
+ SWI $0
+ RET
+
+// int32 runtime·epollcreate1(int32 flags)
+TEXT runtime·epollcreate1(SB),7,$0
+ MOVW 0(FP), R0
+ MOVW $SYS_epoll_create1, R7
+ SWI $0
+ RET
+
+// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev)
+TEXT runtime·epollctl(SB),7,$0
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW 8(FP), R2
+ MOVW 12(FP), R3
+ MOVW $SYS_epoll_ctl, R7
+ SWI $0
+ RET
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout)
+TEXT runtime·epollwait(SB),7,$0
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW 8(FP), R2
+ MOVW 12(FP), R3
+ MOVW $SYS_epoll_wait, R7
+ SWI $0
+ RET
+
+// void runtime·closeonexec(int32 fd)
+TEXT runtime·closeonexec(SB),7,$0
+ MOVW 0(FP), R0 // fd
+ MOVW $2, R1 // F_SETFD
+ MOVW $1, R2 // FD_CLOEXEC
+ MOVW $SYS_fcntl, R7
+ SWI $0
+ RET
diff --git a/src/pkg/runtime/sys_netbsd_386.s b/src/pkg/runtime/sys_netbsd_386.s
index 3d3d31273..992eba77d 100644
--- a/src/pkg/runtime/sys_netbsd_386.s
+++ b/src/pkg/runtime/sys_netbsd_386.s
@@ -22,6 +22,21 @@ TEXT runtime·exit1(SB),7,$-4
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$-4
+ MOVL $5, AX
+ INT $0x80
+ RET
+
+TEXT runtime·close(SB),7,$-4
+ MOVL $6, AX
+ INT $0x80
+ RET
+
+TEXT runtime·read(SB),7,$-4
+ MOVL $3, AX
+ INT $0x80
+ RET
+
TEXT runtime·write(SB),7,$-4
MOVL $4, AX // sys_write
INT $0x80
@@ -46,12 +61,13 @@ TEXT runtime·usleep(SB),7,$24
INT $0x80
RET
-TEXT runtime·raisesigpipe(SB),7,$12
+TEXT runtime·raise(SB),7,$12
MOVL $311, AX // sys__lwp_self
INT $0x80
MOVL $0, 0(SP)
MOVL AX, 4(SP) // arg 1 - target
- MOVL $13, 8(SP) // arg 2 - signo == SIGPIPE
+ MOVL sig+0(FP), AX
+ MOVL AX, 8(SP) // arg 2 - signo
MOVL $318, AX // sys__lwp_kill
INT $0x80
RET
@@ -72,8 +88,6 @@ TEXT runtime·mmap(SB),7,$36
STOSL
MOVL $197, AX // sys_mmap
INT $0x80
- JCC 2(PC)
- NEGL AX
RET
TEXT runtime·munmap(SB),7,$-4
diff --git a/src/pkg/runtime/sys_netbsd_amd64.s b/src/pkg/runtime/sys_netbsd_amd64.s
index e73e83ded..574d8a91b 100644
--- a/src/pkg/runtime/sys_netbsd_amd64.s
+++ b/src/pkg/runtime/sys_netbsd_amd64.s
@@ -16,7 +16,7 @@ TEXT runtime·lwp_create(SB),7,$0
MOVL $309, AX // sys__lwp_create
SYSCALL
JCC 2(PC)
- NEGL AX
+ NEGQ AX
RET
TEXT runtime·lwp_tramp(SB),7,$0
@@ -79,6 +79,28 @@ TEXT runtime·exit1(SB),7,$-8
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$-8
+ MOVQ 8(SP), DI // arg 1 pathname
+ MOVL 16(SP), SI // arg 2 flags
+ MOVL 20(SP), DX // arg 3 mode
+ MOVL $5, AX
+ SYSCALL
+ RET
+
+TEXT runtime·close(SB),7,$-8
+ MOVL 8(SP), DI // arg 1 fd
+ MOVL $6, AX
+ SYSCALL
+ RET
+
+TEXT runtime·read(SB),7,$-8
+ MOVL 8(SP), DI // arg 1 fd
+ MOVQ 16(SP), SI // arg 2 buf
+ MOVL 24(SP), DX // arg 3 count
+ MOVL $3, AX
+ SYSCALL
+ RET
+
TEXT runtime·write(SB),7,$-8
MOVL 8(SP), DI // arg 1 - fd
MOVQ 16(SP), SI // arg 2 - buf
@@ -103,11 +125,11 @@ TEXT runtime·usleep(SB),7,$16
SYSCALL
RET
-TEXT runtime·raisesigpipe(SB),7,$16
+TEXT runtime·raise(SB),7,$16
MOVL $311, AX // sys__lwp_self
SYSCALL
MOVQ AX, DI // arg 1 - target
- MOVQ $13, SI // arg 2 - signo == SIGPIPE
+ MOVL sig+0(FP), SI // arg 2 - signo
MOVL $318, AX // sys__lwp_kill
SYSCALL
RET
@@ -231,8 +253,6 @@ TEXT runtime·mmap(SB),7,$0
MOVQ $0, R9 // arg 6 - pad
MOVL $197, AX // sys_mmap
SYSCALL
- JCC 2(PC)
- NEGL AX
ADDQ $16, SP
RET
@@ -284,7 +304,7 @@ TEXT runtime·sysctl(SB),7,$0
MOVQ $202, AX // sys___sysctl
SYSCALL
JCC 3(PC)
- NEGL AX
+ NEGQ AX
RET
MOVL $0, AX
RET
diff --git a/src/pkg/runtime/sys_netbsd_arm.s b/src/pkg/runtime/sys_netbsd_arm.s
index 4a119c5de..3ff335f4d 100644
--- a/src/pkg/runtime/sys_netbsd_arm.s
+++ b/src/pkg/runtime/sys_netbsd_arm.s
@@ -21,6 +21,25 @@ TEXT runtime·exit1(SB),7,$-4
MOVW $1, R9 // crash
MOVW R9, (R9)
RET
+
+TEXT runtime·open(SB),7,$-8
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW 8(FP), R2
+ SWI $0xa00005
+ RET
+
+TEXT runtime·close(SB),7,$-8
+ MOVW 0(FP), R0
+ SWI $0xa00006
+ RET
+
+TEXT runtime·read(SB),7,$-8
+ MOVW 0(FP), R0
+ MOVW 4(FP), R1
+ MOVW 8(FP), R2
+ SWI $0xa00003
+ RET
TEXT runtime·write(SB),7,$-4
MOVW 0(FP), R0 // arg 1 - fd
@@ -88,9 +107,9 @@ TEXT runtime·usleep(SB),7,$16
SWI $0xa001ae // sys_nanosleep
RET
-TEXT runtime·raisesigpipe(SB),7,$16
+TEXT runtime·raise(SB),7,$16
SWI $0xa00137 // sys__lwp_self, the returned R0 is arg 1
- MOVW $13, R1 // arg 2 - signo == SIGPIPE
+ MOVW sig+0(FP), R1 // arg 2 - signal
SWI $0xa0013e // sys__lwp_kill
RET
diff --git a/src/pkg/runtime/sys_openbsd_386.s b/src/pkg/runtime/sys_openbsd_386.s
index c62e0f949..37b6ff215 100644
--- a/src/pkg/runtime/sys_openbsd_386.s
+++ b/src/pkg/runtime/sys_openbsd_386.s
@@ -24,6 +24,21 @@ TEXT runtime·exit1(SB),7,$8
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$-4
+ MOVL $5, AX
+ INT $0x80
+ RET
+
+TEXT runtime·close(SB),7,$-4
+ MOVL $6, AX
+ INT $0x80
+ RET
+
+TEXT runtime·read(SB),7,$-4
+ MOVL $3, AX
+ INT $0x80
+ RET
+
TEXT runtime·write(SB),7,$-4
MOVL $4, AX // sys_write
INT $0x80
@@ -47,12 +62,13 @@ TEXT runtime·usleep(SB),7,$20
INT $0x80
RET
-TEXT runtime·raisesigpipe(SB),7,$12
+TEXT runtime·raise(SB),7,$12
MOVL $299, AX // sys_getthrid
INT $0x80
MOVL $0, 0(SP)
MOVL AX, 4(SP) // arg 1 - pid
- MOVL $13, 8(SP) // arg 2 - signum == SIGPIPE
+ MOVL sig+0(FP), AX
+ MOVL AX, 8(SP) // arg 2 - signum
MOVL $37, AX // sys_kill
INT $0x80
RET
@@ -73,8 +89,6 @@ TEXT runtime·mmap(SB),7,$36
STOSL
MOVL $197, AX // sys_mmap
INT $0x80
- JCC 2(PC)
- NEGL AX
RET
TEXT runtime·munmap(SB),7,$-4
diff --git a/src/pkg/runtime/sys_openbsd_amd64.s b/src/pkg/runtime/sys_openbsd_amd64.s
index 8a736507f..cbd2c2f76 100644
--- a/src/pkg/runtime/sys_openbsd_amd64.s
+++ b/src/pkg/runtime/sys_openbsd_amd64.s
@@ -23,7 +23,7 @@ TEXT runtime·tfork(SB),7,$32
// Return if tfork syscall failed.
JCC 3(PC)
- NEGL AX
+ NEGQ AX
RET
// In parent, return.
@@ -87,6 +87,28 @@ TEXT runtime·exit1(SB),7,$-8
MOVL $0xf1, 0xf1 // crash
RET
+TEXT runtime·open(SB),7,$-8
+ MOVQ 8(SP), DI // arg 1 pathname
+ MOVL 16(SP), SI // arg 2 flags
+ MOVL 20(SP), DX // arg 3 mode
+ MOVL $5, AX
+ SYSCALL
+ RET
+
+TEXT runtime·close(SB),7,$-8
+ MOVL 8(SP), DI // arg 1 fd
+ MOVL $6, AX
+ SYSCALL
+ RET
+
+TEXT runtime·read(SB),7,$-8
+ MOVL 8(SP), DI // arg 1 fd
+ MOVQ 16(SP), SI // arg 2 buf
+ MOVL 24(SP), DX // arg 3 count
+ MOVL $3, AX
+ SYSCALL
+ RET
+
TEXT runtime·write(SB),7,$-8
MOVL 8(SP), DI // arg 1 - fd
MOVQ 16(SP), SI // arg 2 - buf
@@ -111,11 +133,11 @@ TEXT runtime·usleep(SB),7,$16
SYSCALL
RET
-TEXT runtime·raisesigpipe(SB),7,$16
+TEXT runtime·raise(SB),7,$16
MOVL $299, AX // sys_getthrid
SYSCALL
MOVQ AX, DI // arg 1 - pid
- MOVQ $13, SI // arg 2 - signum == SIGPIPE
+ MOVL sig+0(FP), SI // arg 2 - signum
MOVL $37, AX // sys_kill
SYSCALL
RET
@@ -220,8 +242,6 @@ TEXT runtime·mmap(SB),7,$0
MOVQ $0, R9 // arg 6 - pad
MOVL $197, AX
SYSCALL
- JCC 2(PC)
- NEGL AX
ADDQ $16, SP
RET
@@ -272,7 +292,7 @@ TEXT runtime·sysctl(SB),7,$0
MOVQ $202, AX // sys___sysctl
SYSCALL
JCC 3(PC)
- NEGL AX
+ NEGQ AX
RET
MOVL $0, AX
RET
diff --git a/src/pkg/runtime/sys_plan9_386.s b/src/pkg/runtime/sys_plan9_386.s
index 3385b083a..1f860a961 100644
--- a/src/pkg/runtime/sys_plan9_386.s
+++ b/src/pkg/runtime/sys_plan9_386.s
@@ -170,3 +170,30 @@ TEXT runtime·sigtramp(SB),7,$0
// Only used by the 64-bit runtime.
TEXT runtime·setfpmasks(SB),7,$0
RET
+
+#define ERRMAX 128 /* from os_plan9.h */
+
+// func errstr() String
+// Only used by package syscall.
+// Grab error string due to a syscall made
+// in entersyscall mode, without going
+// through the allocator (issue 4994).
+// See ../syscall/asm_plan9_386.s:/·Syscall/
+TEXT runtime·errstr(SB),7,$0
+ get_tls(AX)
+ MOVL m(AX), BX
+ MOVL m_errstr(BX), CX
+ MOVL CX, 4(SP)
+ MOVL $ERRMAX, 8(SP)
+ MOVL $41, AX
+ INT $64
+
+ // syscall requires caller-save
+ MOVL 4(SP), CX
+
+ // push the argument
+ PUSHL CX
+ CALL runtime·findnull(SB)
+ POPL CX
+ MOVL AX, 8(SP)
+ RET
diff --git a/src/pkg/runtime/sys_plan9_amd64.s b/src/pkg/runtime/sys_plan9_amd64.s
index b34f98a68..c0c896ebc 100644
--- a/src/pkg/runtime/sys_plan9_amd64.s
+++ b/src/pkg/runtime/sys_plan9_amd64.s
@@ -206,3 +206,31 @@ TEXT runtime·setfpmasks(SB),7,$8
MOVL AX, 0(SP)
LDMXCSR 0(SP)
RET
+
+#define ERRMAX 128 /* from os_plan9.h */
+
+// func errstr() String
+// Only used by package syscall.
+// Grab error string due to a syscall made
+// in entersyscall mode, without going
+// through the allocator (issue 4994).
+// See ../syscall/asm_plan9_386.s:/·Syscall/
+TEXT runtime·errstr(SB),7,$0
+ get_tls(AX)
+ MOVQ m(AX), BX
+ MOVQ m_errstr(BX), CX
+ MOVQ CX, 8(SP)
+ MOVQ $ERRMAX, 16(SP)
+ MOVQ $0x8000, AX
+ MOVQ $41, BP
+ SYSCALL
+
+ // syscall requires caller-save
+ MOVQ 8(SP), CX
+
+ // push the argument
+ PUSHQ CX
+ CALL runtime·findnull(SB)
+ POPQ CX
+ MOVQ AX, 16(SP)
+ RET
diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s
index ca59f0a1d..206cdccc4 100644
--- a/src/pkg/runtime/sys_windows_386.s
+++ b/src/pkg/runtime/sys_windows_386.s
@@ -314,3 +314,46 @@ TEXT runtime·remove_exception_handler(SB),7,$0
MOVL AX, 0(FS)
RET
+
+TEXT runtime·osyield(SB),7,$20
+ // Tried NtYieldExecution but it doesn't yield hard enough.
+ // NtWaitForSingleObject being used here as Sleep(0).
+ MOVL runtime·NtWaitForSingleObject(SB), AX
+ MOVL $-1, hi-4(SP)
+ MOVL $-1, lo-8(SP)
+ LEAL lo-8(SP), BX
+ MOVL BX, ptime-12(SP)
+ MOVL $0, alertable-16(SP)
+ MOVL $-1, handle-20(SP)
+ MOVL SP, BP
+ CALL checkstack4<>(SB)
+ CALL AX
+ MOVL BP, SP
+ RET
+
+TEXT runtime·usleep(SB),7,$20
+ MOVL runtime·NtWaitForSingleObject(SB), AX
+ // Have 1us units; need negative 100ns units.
+ // Assume multiply by 10 will not overflow 32-bit word.
+ MOVL usec+0(FP), BX
+ IMULL $10, BX
+ NEGL BX
+ MOVL $-1, hi-4(SP)
+ MOVL BX, lo-8(SP)
+ LEAL lo-8(SP), BX
+ MOVL BX, ptime-12(SP)
+ MOVL $0, alertable-16(SP)
+ MOVL $-1, handle-20(SP)
+ MOVL SP, BP
+ CALL checkstack4<>(SB)
+ CALL AX
+ MOVL BP, SP
+ RET
+
+// This function requires 4 bytes of stack,
+// to simulate what calling NtWaitForSingleObject will use.
+// (It is just a CALL to the system call dispatch.)
+// If the linker okays the call to checkstack4 (a NOSPLIT function)
+// then the call to NtWaitForSingleObject is okay too.
+TEXT checkstack4<>(SB),7,$4
+ RET
diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s
index fe88f3b75..c20a268b1 100644
--- a/src/pkg/runtime/sys_windows_amd64.s
+++ b/src/pkg/runtime/sys_windows_amd64.s
@@ -346,3 +346,35 @@ TEXT runtime·install_exception_handler(SB),7,$0
TEXT runtime·remove_exception_handler(SB),7,$0
RET
+
+TEXT runtime·osyield(SB),7,$8
+ // Tried NtYieldExecution but it doesn't yield hard enough.
+ // NtWaitForSingleObject being used here as Sleep(0).
+ // The CALL is safe because NtXxx is a system call wrapper:
+ // it puts the right system call number in AX, then does
+ // a SYSENTER and a RET.
+ MOVQ runtime·NtWaitForSingleObject(SB), AX
+ MOVQ $1, BX
+ NEGQ BX
+ MOVQ SP, R8 // ptime
+ MOVQ BX, (R8)
+ MOVQ $-1, CX // handle
+ MOVQ $0, DX // alertable
+ CALL AX
+ RET
+
+TEXT runtime·usleep(SB),7,$8
+ // The CALL is safe because NtXxx is a system call wrapper:
+ // it puts the right system call number in AX, then does
+ // a SYSENTER and a RET.
+ MOVQ runtime·NtWaitForSingleObject(SB), AX
+ // Have 1us units; want negative 100ns units.
+ MOVL usec+0(FP), BX
+ IMULQ $10, BX
+ NEGQ BX
+ MOVQ SP, R8 // ptime
+ MOVQ BX, (R8)
+ MOVQ $-1, CX // handle
+ MOVQ $0, DX // alertable
+ CALL AX
+ RET
diff --git a/src/pkg/runtime/time.goc b/src/pkg/runtime/time.goc
index 2babb173d..6de989f51 100644
--- a/src/pkg/runtime/time.goc
+++ b/src/pkg/runtime/time.goc
@@ -15,7 +15,6 @@ package time
static Timers timers;
static void addtimer(Timer*);
-static bool deltimer(Timer*);
// Package time APIs.
// Godoc uses the comments in package time, not these.
@@ -31,15 +30,13 @@ func Sleep(ns int64) {
func startTimer(t *Timer) {
if(raceenabled)
runtime·racerelease(t);
- runtime·lock(&timers);
- addtimer(t);
- runtime·unlock(&timers);
+ runtime·addtimer(t);
}
// stopTimer removes t from the timer heap if it is there.
// It returns true if t was removed, false if t wasn't even there.
func stopTimer(t *Timer) (stopped bool) {
- stopped = deltimer(t);
+ stopped = runtime·deltimer(t);
}
// C runtime.
@@ -79,6 +76,14 @@ runtime·tsleep(int64 ns, int8 *reason)
static FuncVal timerprocv = {timerproc};
+void
+runtime·addtimer(Timer *t)
+{
+ runtime·lock(&timers);
+ addtimer(t);
+ runtime·unlock(&timers);
+}
+
// Add a timer to the heap and start or kick the timer proc
// if the new timer is earlier than any of the others.
static void
@@ -121,8 +126,8 @@ addtimer(Timer *t)
// Delete timer t from the heap.
// Do not need to update the timerproc:
// if it wakes up early, no big deal.
-static bool
-deltimer(Timer *t)
+bool
+runtime·deltimer(Timer *t)
{
int32 i;
diff --git a/src/pkg/runtime/time_plan9_386.c b/src/pkg/runtime/time_plan9_386.c
index a29d45715..fc08a90d6 100644
--- a/src/pkg/runtime/time_plan9_386.c
+++ b/src/pkg/runtime/time_plan9_386.c
@@ -24,7 +24,7 @@ runtime·nanotime(void)
// file descriptor) is roughly four times slower
// in 9vx on a 2.16 GHz Intel Core 2 Duo.
- if(fd < 0 && (fd = runtime·open((byte*)"/dev/bintime", OREAD|OCEXEC)) < 0)
+ if(fd < 0 && (fd = runtime·open("/dev/bintime", OREAD|OCEXEC, 0)) < 0)
return 0;
if(runtime·pread(fd, b, sizeof b, 0) != sizeof b)
return 0;
diff --git a/src/pkg/runtime/vdso_linux_amd64.c b/src/pkg/runtime/vdso_linux_amd64.c
index ab68c23c3..f55d312a0 100644
--- a/src/pkg/runtime/vdso_linux_amd64.c
+++ b/src/pkg/runtime/vdso_linux_amd64.c
@@ -4,6 +4,7 @@
#include "runtime.h"
+#define AT_RANDOM 25
#define AT_SYSINFO_EHDR 33
#define AT_NULL 0 /* End of vector */
#define PT_LOAD 1 /* Loadable program segment */
@@ -319,11 +320,16 @@ runtime·linux_setup_vdso(int32 argc, uint8** argv)
if(elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
if(elf_auxv[i].a_un.a_val == 0) {
// Something went wrong
- return;
+ continue;
}
vdso_init_from_sysinfo_ehdr(&vdso_info, (Elf64_Ehdr*)elf_auxv[i].a_un.a_val);
vdso_parse_symbols(&vdso_info, vdso_find_version(&vdso_info, &linux26));
- return;
+ continue;
+ }
+ if(elf_auxv[i].a_type == AT_RANDOM) {
+ runtime·startup_random_data = (byte*)elf_auxv[i].a_un.a_val;
+ runtime·startup_random_data_len = 16;
+ continue;
}
}
}
diff --git a/src/pkg/sort/search_test.go b/src/pkg/sort/search_test.go
index 4d8d6d930..ee95c663c 100644
--- a/src/pkg/sort/search_test.go
+++ b/src/pkg/sort/search_test.go
@@ -5,6 +5,7 @@
package sort_test
import (
+ "runtime"
. "sort"
"testing"
)
@@ -127,6 +128,9 @@ func runSearchWrappers() {
}
func TestSearchWrappersDontAlloc(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
allocs := testing.AllocsPerRun(100, runSearchWrappers)
if allocs != 0 {
t.Errorf("expected no allocs for runSearchWrappers, got %v", allocs)
diff --git a/src/pkg/strconv/extfloat.go b/src/pkg/strconv/extfloat.go
index b7eaaa61b..bed8b16bd 100644
--- a/src/pkg/strconv/extfloat.go
+++ b/src/pkg/strconv/extfloat.go
@@ -636,7 +636,6 @@ func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool
1<<shift, multiplier*2)
}
}
- return false
}
// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to
diff --git a/src/pkg/strconv/strconv_test.go b/src/pkg/strconv/strconv_test.go
index c3c538926..3cd7835cc 100644
--- a/src/pkg/strconv/strconv_test.go
+++ b/src/pkg/strconv/strconv_test.go
@@ -5,6 +5,7 @@
package strconv_test
import (
+ "runtime"
. "strconv"
"strings"
"testing"
@@ -43,6 +44,9 @@ var (
)
func TestCountMallocs(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
for _, mt := range mallocTest {
allocs := testing.AllocsPerRun(100, mt.fn)
if max := float64(mt.count); allocs > max {
diff --git a/src/pkg/strings/strings.go b/src/pkg/strings/strings.go
index ccf415e69..986f6d61e 100644
--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -26,7 +26,11 @@ func explode(s string, n int) []string {
i, cur := 0, 0
for ; i+1 < n; i++ {
ch, size = utf8.DecodeRuneInString(s[cur:])
- a[i] = string(ch)
+ if ch == utf8.RuneError {
+ a[i] = string(utf8.RuneError)
+ } else {
+ a[i] = s[cur : cur+size]
+ }
cur += size
}
// add the rest, if there is any
@@ -488,10 +492,10 @@ func isSeparator(r rune) bool {
return unicode.IsSpace(r)
}
-// BUG(r): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
-
// Title returns a copy of the string s with all Unicode letters that begin words
// mapped to their title case.
+//
+// BUG: The rule Title uses for word boundaries does not handle Unicode punctuation properly.
func Title(s string) string {
// Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling
diff --git a/src/pkg/strings/strings_test.go b/src/pkg/strings/strings_test.go
index 09de49e5f..68b658ca4 100644
--- a/src/pkg/strings/strings_test.go
+++ b/src/pkg/strings/strings_test.go
@@ -1095,3 +1095,21 @@ func BenchmarkFieldsFunc(b *testing.B) {
FieldsFunc(fieldsInput, unicode.IsSpace)
}
}
+
+func BenchmarkSplit1(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Split(benchInputHard, "")
+ }
+}
+
+func BenchmarkSplit2(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Split(benchInputHard, "/")
+ }
+}
+
+func BenchmarkSplit3(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Split(benchInputHard, "hello")
+ }
+}
diff --git a/src/pkg/sync/atomic/asm_386.s b/src/pkg/sync/atomic/asm_386.s
index 7a98a61d8..8c02f106f 100644
--- a/src/pkg/sync/atomic/asm_386.s
+++ b/src/pkg/sync/atomic/asm_386.s
@@ -28,10 +28,13 @@ TEXT ·CompareAndSwapInt64(SB),7,$0
TEXT ·CompareAndSwapUint64(SB),7,$0
MOVL addr+0(FP), BP
- MOVL old+4(FP), AX
- MOVL old+8(FP), DX
- MOVL new+12(FP), BX
- MOVL new+16(FP), CX
+ TESTL $7, BP
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
+ MOVL old_lo+4(FP), AX
+ MOVL old_hi+8(FP), DX
+ MOVL new_lo+12(FP), BX
+ MOVL new_hi+16(FP), CX
// CMPXCHG8B was introduced on the Pentium.
LOCK
CMPXCHG8B 0(BP)
@@ -61,9 +64,12 @@ TEXT ·AddInt64(SB),7,$0
TEXT ·AddUint64(SB),7,$0
// no XADDQ so use CMPXCHG8B loop
MOVL addr+0(FP), BP
+ TESTL $7, BP
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
// DI:SI = delta
- MOVL delta+4(FP), SI
- MOVL delta+8(FP), DI
+ MOVL delta_lo+4(FP), SI
+ MOVL delta_hi+8(FP), DI
// DX:AX = *addr
MOVL 0(BP), AX
MOVL 4(BP), DX
@@ -87,8 +93,8 @@ addloop:
// success
// return CX:BX
- MOVL BX, new+12(FP)
- MOVL CX, new+16(FP)
+ MOVL BX, new_lo+12(FP)
+ MOVL CX, new_hi+16(FP)
RET
TEXT ·LoadInt32(SB),7,$0
@@ -105,6 +111,9 @@ TEXT ·LoadInt64(SB),7,$0
TEXT ·LoadUint64(SB),7,$0
MOVL addr+0(FP), AX
+ TESTL $7, AX
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
// MOVQ and EMMS were introduced on the Pentium MMX.
// MOVQ (%EAX), %MM0
BYTE $0x0f; BYTE $0x6f; BYTE $0x00
@@ -133,6 +142,9 @@ TEXT ·StoreInt64(SB),7,$0
TEXT ·StoreUint64(SB),7,$0
MOVL addr+0(FP), AX
+ TESTL $7, AX
+ JZ 2(PC)
+ MOVL 0, AX // crash with nil ptr deref
// MOVQ and EMMS were introduced on the Pentium MMX.
// MOVQ 0x8(%ESP), %MM0
BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
diff --git a/src/pkg/sync/atomic/atomic_test.go b/src/pkg/sync/atomic/atomic_test.go
index 3e105561c..72f303040 100644
--- a/src/pkg/sync/atomic/atomic_test.go
+++ b/src/pkg/sync/atomic/atomic_test.go
@@ -1177,3 +1177,29 @@ func TestStoreLoadRelAcq64(t *testing.T) {
<-c
<-c
}
+
+func shouldPanic(t *testing.T, name string, f func()) {
+ defer func() {
+ if recover() == nil {
+ t.Errorf("%s did not panic", name)
+ }
+ }()
+ f()
+}
+
+func TestUnaligned64(t *testing.T) {
+ // Unaligned 64-bit atomics on 32-bit systems are
+ // a continual source of pain. Test that on 386 they crash
+ // instead of failing silently.
+ if runtime.GOARCH != "386" {
+ t.Skip("test only runs on 386")
+ }
+
+ x := make([]uint32, 4)
+ p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
+
+ shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
+ shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
+ shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
+ shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
+}
diff --git a/src/pkg/syscall/asm_plan9_386.s b/src/pkg/syscall/asm_plan9_386.s
index 2ba137608..0ae20f568 100644
--- a/src/pkg/syscall/asm_plan9_386.s
+++ b/src/pkg/syscall/asm_plan9_386.s
@@ -29,7 +29,7 @@ TEXT ·Syscall(SB),7,$0
JNE ok3
SUBL $8, SP
- CALL syscall·errstr(SB)
+ CALL runtime·errstr(SB)
MOVL SP, SI
ADDL $8, SP
JMP copyresult3
@@ -67,7 +67,7 @@ TEXT ·Syscall6(SB),7,$0
JNE ok4
SUBL $8, SP
- CALL syscall·errstr(SB)
+ CALL runtime·errstr(SB)
MOVL SP, SI
ADDL $8, SP
JMP copyresult4
diff --git a/src/pkg/syscall/asm_plan9_amd64.s b/src/pkg/syscall/asm_plan9_amd64.s
index e363b743c..40cc12642 100644
--- a/src/pkg/syscall/asm_plan9_amd64.s
+++ b/src/pkg/syscall/asm_plan9_amd64.s
@@ -32,7 +32,7 @@ TEXT ·Syscall(SB),7,$0
JNE ok3
SUBQ $16, SP
- CALL syscall·errstr(SB)
+ CALL runtime·errstr(SB)
MOVQ SP, SI
ADDQ $16, SP
JMP copyresult3
@@ -71,7 +71,7 @@ TEXT ·Syscall6(SB),7,$0
JNE ok4
SUBQ $16, SP
- CALL syscall·errstr(SB)
+ CALL runtime·errstr(SB)
MOVQ SP, SI
ADDQ $16, SP
JMP copyresult4
diff --git a/src/pkg/syscall/exec_bsd.go b/src/pkg/syscall/exec_bsd.go
index 318cbc060..bc644d97a 100644
--- a/src/pkg/syscall/exec_bsd.go
+++ b/src/pkg/syscall/exec_bsd.go
@@ -215,11 +215,6 @@ childerror:
for {
RawSyscall(SYS_EXIT, 253, 0, 0)
}
-
- // Calling panic is not actually safe,
- // but the for loop above won't break
- // and this shuts up the compiler.
- panic("unreached")
}
// Try to open a pipe with O_CLOEXEC set on both file descriptors.
diff --git a/src/pkg/syscall/mkerrors.sh b/src/pkg/syscall/mkerrors.sh
index e8abb6774..5a39d707b 100755
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -43,6 +43,7 @@ includes_FreeBSD='
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
+#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <net/bpf.h>
diff --git a/src/pkg/syscall/passfd_test.go b/src/pkg/syscall/passfd_test.go
index 079c9303b..a0e590950 100644
--- a/src/pkg/syscall/passfd_test.go
+++ b/src/pkg/syscall/passfd_test.go
@@ -13,7 +13,6 @@ import (
"net"
"os"
"os/exec"
- "runtime"
"syscall"
"testing"
"time"
@@ -27,9 +26,6 @@ import (
// "-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 runtime.GOOS == "openbsd" {
- t.Skip("issue 4956")
- }
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
passFDChild()
return
diff --git a/src/pkg/syscall/syscall_bsd.go b/src/pkg/syscall/syscall_bsd.go
index a1e0d153f..560409a26 100644
--- a/src/pkg/syscall/syscall_bsd.go
+++ b/src/pkg/syscall/syscall_bsd.go
@@ -327,6 +327,11 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
if err = getsockname(fd, &rsa, &len); err != nil {
return
}
+ // TODO(jsing): Remove after OpenBSD 5.4 is released (see issue 3349).
+ if runtime.GOOS == "openbsd" && rsa.Addr.Family == AF_UNSPEC && rsa.Addr.Len == 0 {
+ rsa.Addr.Family = AF_UNIX
+ rsa.Addr.Len = SizeofSockaddrUnix
+ }
return anyToSockaddr(&rsa)
}
diff --git a/src/pkg/syscall/zerrors_freebsd_386.go b/src/pkg/syscall/zerrors_freebsd_386.go
index 9cf82f90e..048687361 100644
--- a/src/pkg/syscall/zerrors_freebsd_386.go
+++ b/src/pkg/syscall/zerrors_freebsd_386.go
@@ -92,6 +92,31 @@ const (
AF_VENDOR45 = 0x81
AF_VENDOR46 = 0x83
AF_VENDOR47 = 0x85
+ B0 = 0x0
+ B110 = 0x6e
+ B115200 = 0x1c200
+ B1200 = 0x4b0
+ B134 = 0x86
+ B14400 = 0x3840
+ B150 = 0x96
+ B1800 = 0x708
+ B19200 = 0x4b00
+ B200 = 0xc8
+ B230400 = 0x38400
+ B2400 = 0x960
+ B28800 = 0x7080
+ B300 = 0x12c
+ B38400 = 0x9600
+ B460800 = 0x70800
+ B4800 = 0x12c0
+ B50 = 0x32
+ B57600 = 0xe100
+ B600 = 0x258
+ B7200 = 0x1c20
+ B75 = 0x4b
+ B76800 = 0x12c00
+ B921600 = 0xe1000
+ B9600 = 0x2580
BIOCFEEDBACK = 0x8004427c
BIOCFLUSH = 0x20004268
BIOCGBLEN = 0x40044266
@@ -106,6 +131,7 @@ const (
BIOCGRTIMEOUT = 0x4008426e
BIOCGSEESENT = 0x40044276
BIOCGSTATS = 0x4008426f
+ BIOCGTSTAMP = 0x40044283
BIOCIMMEDIATE = 0x80044270
BIOCLOCK = 0x2000427a
BIOCPROMISC = 0x20004269
@@ -123,6 +149,7 @@ const (
BIOCSRSIG = 0x80044273
BIOCSRTIMEOUT = 0x8008426d
BIOCSSEESENT = 0x80044277
+ BIOCSTSTAMP = 0x80044284
BIOCVERSION = 0x40044271
BPF_A = 0x10
BPF_ABS = 0x20
@@ -168,13 +195,47 @@ const (
BPF_SUB = 0x10
BPF_TAX = 0x0
BPF_TXA = 0x80
+ BPF_T_BINTIME = 0x2
+ BPF_T_BINTIME_FAST = 0x102
+ BPF_T_BINTIME_MONOTONIC = 0x202
+ BPF_T_BINTIME_MONOTONIC_FAST = 0x302
+ BPF_T_FAST = 0x100
+ BPF_T_FLAG_MASK = 0x300
+ BPF_T_FORMAT_MASK = 0x3
+ BPF_T_MICROTIME = 0x0
+ BPF_T_MICROTIME_FAST = 0x100
+ BPF_T_MICROTIME_MONOTONIC = 0x200
+ BPF_T_MICROTIME_MONOTONIC_FAST = 0x300
+ BPF_T_MONOTONIC = 0x200
+ BPF_T_MONOTONIC_FAST = 0x300
+ BPF_T_NANOTIME = 0x1
+ BPF_T_NANOTIME_FAST = 0x101
+ BPF_T_NANOTIME_MONOTONIC = 0x201
+ BPF_T_NANOTIME_MONOTONIC_FAST = 0x301
+ BPF_T_NONE = 0x3
+ BPF_T_NORMAL = 0x0
BPF_W = 0x0
BPF_X = 0x8
+ BRKINT = 0x2
+ CFLUSH = 0xf
+ CLOCAL = 0x8000
+ CREAD = 0x800
+ CS5 = 0x0
+ CS6 = 0x100
+ CS7 = 0x200
+ CS8 = 0x300
+ CSIZE = 0x300
+ CSTART = 0x11
+ CSTATUS = 0x14
+ CSTOP = 0x13
+ CSTOPB = 0x400
+ CSUSP = 0x1a
CTL_MAXNAME = 0x18
CTL_NET = 0x4
DLT_A429 = 0xb8
DLT_A653_ICM = 0xb9
DLT_AIRONET_HEADER = 0x78
+ DLT_AOS = 0xde
DLT_APPLE_IP_OVER_IEEE1394 = 0x8a
DLT_ARCNET = 0x7
DLT_ARCNET_LINUX = 0x81
@@ -187,12 +248,16 @@ const (
DLT_BLUETOOTH_HCI_H4 = 0xbb
DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9
DLT_CAN20B = 0xbe
+ DLT_CAN_SOCKETCAN = 0xe3
DLT_CHAOS = 0x5
DLT_CHDLC = 0x68
DLT_CISCO_IOS = 0x76
DLT_C_HDLC = 0x68
DLT_C_HDLC_WITH_DIR = 0xcd
+ DLT_DBUS = 0xe7
+ DLT_DECT = 0xdd
DLT_DOCSIS = 0x8f
+ DLT_DVB_CI = 0xeb
DLT_ECONET = 0x73
DLT_EN10MB = 0x1
DLT_EN3MB = 0x2
@@ -200,6 +265,8 @@ const (
DLT_ERF = 0xc5
DLT_ERF_ETH = 0xaf
DLT_ERF_POS = 0xb0
+ DLT_FC_2 = 0xe0
+ DLT_FC_2_WITH_FRAME_DELIMS = 0xe1
DLT_FDDI = 0xa
DLT_FLEXRAY = 0xd2
DLT_FRELAY = 0x6b
@@ -209,6 +276,8 @@ const (
DLT_GPF_F = 0xab
DLT_GPF_T = 0xaa
DLT_GPRS_LLC = 0xa9
+ DLT_GSMTAP_ABIS = 0xda
+ DLT_GSMTAP_UM = 0xd9
DLT_HHDLC = 0x79
DLT_IBM_SN = 0x92
DLT_IBM_SP = 0x91
@@ -218,18 +287,25 @@ const (
DLT_IEEE802_11_RADIO_AVS = 0xa3
DLT_IEEE802_15_4 = 0xc3
DLT_IEEE802_15_4_LINUX = 0xbf
+ DLT_IEEE802_15_4_NOFCS = 0xe6
DLT_IEEE802_15_4_NONASK_PHY = 0xd7
DLT_IEEE802_16_MAC_CPS = 0xbc
DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1
DLT_IPFILTER = 0x74
DLT_IPMB = 0xc7
DLT_IPMB_LINUX = 0xd1
+ DLT_IPNET = 0xe2
+ DLT_IPOIB = 0xf2
+ DLT_IPV4 = 0xe4
+ DLT_IPV6 = 0xe5
DLT_IP_OVER_FC = 0x7a
DLT_JUNIPER_ATM1 = 0x89
DLT_JUNIPER_ATM2 = 0x87
+ DLT_JUNIPER_ATM_CEMIC = 0xee
DLT_JUNIPER_CHDLC = 0xb5
DLT_JUNIPER_ES = 0x84
DLT_JUNIPER_ETHER = 0xb2
+ DLT_JUNIPER_FIBRECHANNEL = 0xea
DLT_JUNIPER_FRELAY = 0xb4
DLT_JUNIPER_GGSN = 0x85
DLT_JUNIPER_ISM = 0xc2
@@ -242,22 +318,32 @@ const (
DLT_JUNIPER_PPPOE = 0xa7
DLT_JUNIPER_PPPOE_ATM = 0xa8
DLT_JUNIPER_SERVICES = 0x88
+ DLT_JUNIPER_SRX_E2E = 0xe9
DLT_JUNIPER_ST = 0xc8
DLT_JUNIPER_VP = 0xb7
+ DLT_JUNIPER_VS = 0xe8
DLT_LAPB_WITH_DIR = 0xcf
DLT_LAPD = 0xcb
DLT_LIN = 0xd4
+ DLT_LINUX_EVDEV = 0xd8
DLT_LINUX_IRDA = 0x90
DLT_LINUX_LAPD = 0xb1
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
DLT_LINUX_SLL = 0x71
DLT_LOOP = 0x6c
DLT_LTALK = 0x72
+ DLT_MATCHING_MAX = 0xf2
+ DLT_MATCHING_MIN = 0x68
DLT_MFR = 0xb6
DLT_MOST = 0xd3
+ DLT_MPLS = 0xdb
DLT_MTP2 = 0x8c
DLT_MTP2_WITH_PHDR = 0x8b
DLT_MTP3 = 0x8d
+ DLT_MUX27010 = 0xec
+ DLT_NETANALYZER = 0xf0
+ DLT_NETANALYZER_TRANSPARENT = 0xf1
+ DLT_NFLOG = 0xef
DLT_NULL = 0x0
DLT_PCI_EXP = 0x7d
DLT_PFLOG = 0x75
@@ -279,11 +365,13 @@ const (
DLT_SITA = 0xc4
DLT_SLIP = 0x8
DLT_SLIP_BSDOS = 0xf
+ DLT_STANAG_5066_D_PDU = 0xed
DLT_SUNATM = 0x7b
DLT_SYMANTEC_FIREWALL = 0x63
DLT_TZSP = 0x80
DLT_USB = 0xba
DLT_USB_LINUX = 0xbd
+ DLT_USB_LINUX_MMAPPED = 0xdc
DLT_USER0 = 0x93
DLT_USER1 = 0x94
DLT_USER10 = 0x9d
@@ -300,6 +388,7 @@ const (
DLT_USER7 = 0x9a
DLT_USER8 = 0x9b
DLT_USER9 = 0x9c
+ DLT_WIHART = 0xdf
DLT_X2E_SERIAL = 0xd5
DLT_X2E_XORAYA = 0xd6
DT_BLK = 0x6
@@ -346,6 +435,7 @@ const (
EXTPROC = 0x800
FD_CLOEXEC = 0x1
FD_SETSIZE = 0x400
+ FLUSHO = 0x800000
F_CANCEL = 0x5
F_DUP2FD = 0xa
F_DUPFD = 0x0
@@ -369,12 +459,17 @@ const (
F_UNLCK = 0x2
F_UNLCKSYS = 0x4
F_WRLCK = 0x3
+ HUPCL = 0x4000
+ ICANON = 0x100
+ ICRNL = 0x100
+ IEXTEN = 0x400
IFAN_ARRIVAL = 0x0
IFAN_DEPARTURE = 0x1
IFF_ALLMULTI = 0x200
IFF_ALTPHYS = 0x4000
IFF_BROADCAST = 0x2
- IFF_CANTCHANGE = 0x208f72
+ IFF_CANTCHANGE = 0x218f72
+ IFF_CANTCONFIG = 0x10000
IFF_DEBUG = 0x4
IFF_DRV_OACTIVE = 0x400
IFF_DRV_RUNNING = 0x40
@@ -488,6 +583,7 @@ const (
IFT_IEEE8023ADLAG = 0xa1
IFT_IFGSN = 0x91
IFT_IMT = 0xbe
+ IFT_INFINIBAND = 0xc7
IFT_INTERLEAVE = 0x7c
IFT_IP = 0x7e
IFT_IPFORWARD = 0x8e
@@ -603,6 +699,12 @@ const (
IFT_X25MLP = 0x79
IFT_X25PLE = 0x28
IFT_XETHER = 0x1a
+ IGNBRK = 0x1
+ IGNCR = 0x80
+ IGNPAR = 0x4
+ IMAXBEL = 0x2000
+ INLCR = 0x40
+ INPCK = 0x10
IN_CLASSA_HOST = 0xffffff
IN_CLASSA_MAX = 0x80
IN_CLASSA_NET = 0xff000000
@@ -618,6 +720,7 @@ const (
IN_CLASSD_NET = 0xf0000000
IN_CLASSD_NSHIFT = 0x1c
IN_LOOPBACKNET = 0x7f
+ IN_RFC3021_MASK = 0xfffffffe
IPPROTO_3PC = 0x22
IPPROTO_ADFS = 0x44
IPPROTO_AH = 0x33
@@ -679,6 +782,7 @@ const (
IPPROTO_MAX = 0x100
IPPROTO_MAXID = 0x34
IPPROTO_MEAS = 0x13
+ IPPROTO_MH = 0x87
IPPROTO_MHRP = 0x30
IPPROTO_MICP = 0x5f
IPPROTO_MOBILE = 0x37
@@ -709,6 +813,7 @@ const (
IPPROTO_SCCSP = 0x60
IPPROTO_SCTP = 0x84
IPPROTO_SDRP = 0x2a
+ IPPROTO_SEND = 0x103
IPPROTO_SEP = 0x21
IPPROTO_SKIP = 0x39
IPPROTO_SPACER = 0x7fff
@@ -856,6 +961,7 @@ const (
IP_RECVIF = 0x14
IP_RECVOPTS = 0x5
IP_RECVRETOPTS = 0x6
+ IP_RECVTOS = 0x44
IP_RECVTTL = 0x41
IP_RETOPTS = 0x8
IP_RF = 0x8000
@@ -867,10 +973,44 @@ const (
IP_TOS = 0x3
IP_TTL = 0x4
IP_UNBLOCK_SOURCE = 0x49
+ ISIG = 0x80
+ ISTRIP = 0x20
+ IXANY = 0x800
+ IXOFF = 0x400
+ IXON = 0x200
LOCK_EX = 0x2
LOCK_NB = 0x4
LOCK_SH = 0x1
LOCK_UN = 0x8
+ MADV_AUTOSYNC = 0x7
+ MADV_CORE = 0x9
+ MADV_DONTNEED = 0x4
+ MADV_FREE = 0x5
+ MADV_NOCORE = 0x8
+ MADV_NORMAL = 0x0
+ MADV_NOSYNC = 0x6
+ MADV_PROTECT = 0xa
+ MADV_RANDOM = 0x1
+ MADV_SEQUENTIAL = 0x2
+ MADV_WILLNEED = 0x3
+ MAP_ANON = 0x1000
+ MAP_ANONYMOUS = 0x1000
+ MAP_COPY = 0x2
+ MAP_FILE = 0x0
+ MAP_FIXED = 0x10
+ MAP_HASSEMAPHORE = 0x200
+ MAP_NOCORE = 0x20000
+ MAP_NORESERVE = 0x40
+ MAP_NOSYNC = 0x800
+ MAP_PREFAULT_READ = 0x40000
+ MAP_PRIVATE = 0x2
+ MAP_RENAME = 0x20
+ MAP_RESERVED0080 = 0x80
+ MAP_RESERVED0100 = 0x100
+ MAP_SHARED = 0x1
+ MAP_STACK = 0x400
+ MCL_CURRENT = 0x1
+ MCL_FUTURE = 0x2
MSG_COMPAT = 0x8000
MSG_CTRUNC = 0x20
MSG_DONTROUTE = 0x4
@@ -884,11 +1024,16 @@ const (
MSG_PEEK = 0x2
MSG_TRUNC = 0x10
MSG_WAITALL = 0x40
+ MS_ASYNC = 0x1
+ MS_INVALIDATE = 0x2
+ MS_SYNC = 0x0
NET_RT_DUMP = 0x1
NET_RT_FLAGS = 0x2
NET_RT_IFLIST = 0x3
+ NET_RT_IFLISTL = 0x5
NET_RT_IFMALIST = 0x4
- NET_RT_MAXID = 0x5
+ NET_RT_MAXID = 0x6
+ NOFLSH = 0x80000000
NOTE_ATTRIB = 0x8
NOTE_CHILD = 0x4
NOTE_DELETE = 0x1
@@ -912,6 +1057,12 @@ const (
NOTE_TRACKERR = 0x2
NOTE_TRIGGER = 0x1000000
NOTE_WRITE = 0x2
+ OCRNL = 0x10
+ ONLCR = 0x2
+ ONLRET = 0x40
+ ONOCR = 0x20
+ ONOEOT = 0x8
+ OPOST = 0x1
O_ACCMODE = 0x3
O_APPEND = 0x8
O_ASYNC = 0x40
@@ -933,6 +1084,14 @@ const (
O_TRUNC = 0x400
O_TTY_INIT = 0x80000
O_WRONLY = 0x1
+ PARENB = 0x1000
+ PARMRK = 0x8
+ PARODD = 0x2000
+ PENDIN = 0x20000000
+ PROT_EXEC = 0x4
+ PROT_NONE = 0x0
+ PROT_READ = 0x1
+ PROT_WRITE = 0x2
RLIMIT_AS = 0xa
RLIMIT_CORE = 0x4
RLIMIT_CPU = 0x0
@@ -1010,6 +1169,8 @@ const (
RTV_SPIPE = 0x10
RTV_SSTHRESH = 0x20
RTV_WEIGHT = 0x100
+ RT_CACHING_CONTEXT = 0x1
+ RT_DEFAULT_FIB = 0x0
RUSAGE_CHILDREN = -0x1
RUSAGE_SELF = 0x0
RUSAGE_THREAD = 0x1
@@ -1042,6 +1203,7 @@ const (
SIOCGIFCONF = 0xc0086924
SIOCGIFDESCR = 0xc020692a
SIOCGIFDSTADDR = 0xc0206922
+ SIOCGIFFIB = 0xc020695c
SIOCGIFFLAGS = 0xc0206911
SIOCGIFGENERIC = 0xc020693a
SIOCGIFGMEMB = 0xc024698a
@@ -1073,6 +1235,7 @@ const (
SIOCSIFCAP = 0x8020691e
SIOCSIFDESCR = 0x80206929
SIOCSIFDSTADDR = 0x8020690e
+ SIOCSIFFIB = 0x8020695d
SIOCSIFFLAGS = 0x80206910
SIOCSIFGENERIC = 0x80206939
SIOCSIFLLADDR = 0x8020693c
@@ -1115,6 +1278,8 @@ const (
SO_NO_OFFLOAD = 0x4000
SO_OOBINLINE = 0x100
SO_PEERLABEL = 0x1010
+ SO_PROTOCOL = 0x1016
+ SO_PROTOTYPE = 0x1016
SO_RCVBUF = 0x1002
SO_RCVLOWAT = 0x1004
SO_RCVTIMEO = 0x1006
@@ -1127,9 +1292,17 @@ const (
SO_TIMESTAMP = 0x400
SO_TYPE = 0x1008
SO_USELOOPBACK = 0x40
+ SO_USER_COOKIE = 0x1015
+ TCIFLUSH = 0x1
+ TCIOFLUSH = 0x3
+ TCOFLUSH = 0x2
TCP_CA_NAME_MAX = 0x10
TCP_CONGESTION = 0x40
TCP_INFO = 0x20
+ TCP_KEEPCNT = 0x400
+ TCP_KEEPIDLE = 0x100
+ TCP_KEEPINIT = 0x80
+ TCP_KEEPINTVL = 0x200
TCP_MAXBURST = 0x4
TCP_MAXHLEN = 0x3c
TCP_MAXOLEN = 0x28
@@ -1139,10 +1312,11 @@ const (
TCP_MAX_WINSHIFT = 0xe
TCP_MD5SIG = 0x10
TCP_MINMSS = 0xd8
- TCP_MSS = 0x200
+ TCP_MSS = 0x218
TCP_NODELAY = 0x1
TCP_NOOPT = 0x8
TCP_NOPUSH = 0x4
+ TCSAFLUSH = 0x2
TIOCCBRK = 0x2000747a
TIOCCDTR = 0x20007478
TIOCCONS = 0x80047462
@@ -1205,6 +1379,26 @@ const (
TIOCSWINSZ = 0x80087467
TIOCTIMESTAMP = 0x40087459
TIOCUCNTL = 0x80047466
+ TOSTOP = 0x400000
+ VDISCARD = 0xf
+ VDSUSP = 0xb
+ VEOF = 0x0
+ VEOL = 0x1
+ VEOL2 = 0x2
+ VERASE = 0x3
+ VERASE2 = 0x7
+ VINTR = 0x8
+ VKILL = 0x5
+ VLNEXT = 0xe
+ VMIN = 0x10
+ VQUIT = 0x9
+ VREPRINT = 0x6
+ VSTART = 0xc
+ VSTATUS = 0x12
+ VSTOP = 0xd
+ VSUSP = 0xa
+ VTIME = 0x11
+ VWERASE = 0x4
WCONTINUED = 0x4
WCOREFLAG = 0x80
WLINUXCLONE = 0x80000000
@@ -1229,6 +1423,7 @@ const (
EBADRPC = Errno(0x48)
EBUSY = Errno(0x10)
ECANCELED = Errno(0x55)
+ ECAPMODE = Errno(0x5e)
ECHILD = Errno(0xa)
ECONNABORTED = Errno(0x35)
ECONNREFUSED = Errno(0x3d)
@@ -1252,7 +1447,7 @@ const (
EIO = Errno(0x5)
EISCONN = Errno(0x38)
EISDIR = Errno(0x15)
- ELAST = Errno(0x5d)
+ ELAST = Errno(0x5e)
ELOOP = Errno(0x3e)
EMFILE = Errno(0x18)
EMLINK = Errno(0x1f)
@@ -1447,6 +1642,7 @@ var errors = [...]string{
91: "link has been severed",
92: "protocol error",
93: "capabilities insufficient",
+ 94: "not permitted in capability mode",
}
// Signal table
diff --git a/src/pkg/syscall/zerrors_freebsd_amd64.go b/src/pkg/syscall/zerrors_freebsd_amd64.go
index 732570659..a45d7f495 100644
--- a/src/pkg/syscall/zerrors_freebsd_amd64.go
+++ b/src/pkg/syscall/zerrors_freebsd_amd64.go
@@ -92,6 +92,31 @@ const (
AF_VENDOR45 = 0x81
AF_VENDOR46 = 0x83
AF_VENDOR47 = 0x85
+ B0 = 0x0
+ B110 = 0x6e
+ B115200 = 0x1c200
+ B1200 = 0x4b0
+ B134 = 0x86
+ B14400 = 0x3840
+ B150 = 0x96
+ B1800 = 0x708
+ B19200 = 0x4b00
+ B200 = 0xc8
+ B230400 = 0x38400
+ B2400 = 0x960
+ B28800 = 0x7080
+ B300 = 0x12c
+ B38400 = 0x9600
+ B460800 = 0x70800
+ B4800 = 0x12c0
+ B50 = 0x32
+ B57600 = 0xe100
+ B600 = 0x258
+ B7200 = 0x1c20
+ B75 = 0x4b
+ B76800 = 0x12c00
+ B921600 = 0xe1000
+ B9600 = 0x2580
BIOCFEEDBACK = 0x8004427c
BIOCFLUSH = 0x20004268
BIOCGBLEN = 0x40044266
@@ -106,6 +131,7 @@ const (
BIOCGRTIMEOUT = 0x4010426e
BIOCGSEESENT = 0x40044276
BIOCGSTATS = 0x4008426f
+ BIOCGTSTAMP = 0x40044283
BIOCIMMEDIATE = 0x80044270
BIOCLOCK = 0x2000427a
BIOCPROMISC = 0x20004269
@@ -123,6 +149,7 @@ const (
BIOCSRSIG = 0x80044273
BIOCSRTIMEOUT = 0x8010426d
BIOCSSEESENT = 0x80044277
+ BIOCSTSTAMP = 0x80044284
BIOCVERSION = 0x40044271
BPF_A = 0x10
BPF_ABS = 0x20
@@ -168,13 +195,47 @@ const (
BPF_SUB = 0x10
BPF_TAX = 0x0
BPF_TXA = 0x80
+ BPF_T_BINTIME = 0x2
+ BPF_T_BINTIME_FAST = 0x102
+ BPF_T_BINTIME_MONOTONIC = 0x202
+ BPF_T_BINTIME_MONOTONIC_FAST = 0x302
+ BPF_T_FAST = 0x100
+ BPF_T_FLAG_MASK = 0x300
+ BPF_T_FORMAT_MASK = 0x3
+ BPF_T_MICROTIME = 0x0
+ BPF_T_MICROTIME_FAST = 0x100
+ BPF_T_MICROTIME_MONOTONIC = 0x200
+ BPF_T_MICROTIME_MONOTONIC_FAST = 0x300
+ BPF_T_MONOTONIC = 0x200
+ BPF_T_MONOTONIC_FAST = 0x300
+ BPF_T_NANOTIME = 0x1
+ BPF_T_NANOTIME_FAST = 0x101
+ BPF_T_NANOTIME_MONOTONIC = 0x201
+ BPF_T_NANOTIME_MONOTONIC_FAST = 0x301
+ BPF_T_NONE = 0x3
+ BPF_T_NORMAL = 0x0
BPF_W = 0x0
BPF_X = 0x8
+ BRKINT = 0x2
+ CFLUSH = 0xf
+ CLOCAL = 0x8000
+ CREAD = 0x800
+ CS5 = 0x0
+ CS6 = 0x100
+ CS7 = 0x200
+ CS8 = 0x300
+ CSIZE = 0x300
+ CSTART = 0x11
+ CSTATUS = 0x14
+ CSTOP = 0x13
+ CSTOPB = 0x400
+ CSUSP = 0x1a
CTL_MAXNAME = 0x18
CTL_NET = 0x4
DLT_A429 = 0xb8
DLT_A653_ICM = 0xb9
DLT_AIRONET_HEADER = 0x78
+ DLT_AOS = 0xde
DLT_APPLE_IP_OVER_IEEE1394 = 0x8a
DLT_ARCNET = 0x7
DLT_ARCNET_LINUX = 0x81
@@ -187,12 +248,16 @@ const (
DLT_BLUETOOTH_HCI_H4 = 0xbb
DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9
DLT_CAN20B = 0xbe
+ DLT_CAN_SOCKETCAN = 0xe3
DLT_CHAOS = 0x5
DLT_CHDLC = 0x68
DLT_CISCO_IOS = 0x76
DLT_C_HDLC = 0x68
DLT_C_HDLC_WITH_DIR = 0xcd
+ DLT_DBUS = 0xe7
+ DLT_DECT = 0xdd
DLT_DOCSIS = 0x8f
+ DLT_DVB_CI = 0xeb
DLT_ECONET = 0x73
DLT_EN10MB = 0x1
DLT_EN3MB = 0x2
@@ -200,6 +265,8 @@ const (
DLT_ERF = 0xc5
DLT_ERF_ETH = 0xaf
DLT_ERF_POS = 0xb0
+ DLT_FC_2 = 0xe0
+ DLT_FC_2_WITH_FRAME_DELIMS = 0xe1
DLT_FDDI = 0xa
DLT_FLEXRAY = 0xd2
DLT_FRELAY = 0x6b
@@ -209,6 +276,8 @@ const (
DLT_GPF_F = 0xab
DLT_GPF_T = 0xaa
DLT_GPRS_LLC = 0xa9
+ DLT_GSMTAP_ABIS = 0xda
+ DLT_GSMTAP_UM = 0xd9
DLT_HHDLC = 0x79
DLT_IBM_SN = 0x92
DLT_IBM_SP = 0x91
@@ -218,18 +287,25 @@ const (
DLT_IEEE802_11_RADIO_AVS = 0xa3
DLT_IEEE802_15_4 = 0xc3
DLT_IEEE802_15_4_LINUX = 0xbf
+ DLT_IEEE802_15_4_NOFCS = 0xe6
DLT_IEEE802_15_4_NONASK_PHY = 0xd7
DLT_IEEE802_16_MAC_CPS = 0xbc
DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1
DLT_IPFILTER = 0x74
DLT_IPMB = 0xc7
DLT_IPMB_LINUX = 0xd1
+ DLT_IPNET = 0xe2
+ DLT_IPOIB = 0xf2
+ DLT_IPV4 = 0xe4
+ DLT_IPV6 = 0xe5
DLT_IP_OVER_FC = 0x7a
DLT_JUNIPER_ATM1 = 0x89
DLT_JUNIPER_ATM2 = 0x87
+ DLT_JUNIPER_ATM_CEMIC = 0xee
DLT_JUNIPER_CHDLC = 0xb5
DLT_JUNIPER_ES = 0x84
DLT_JUNIPER_ETHER = 0xb2
+ DLT_JUNIPER_FIBRECHANNEL = 0xea
DLT_JUNIPER_FRELAY = 0xb4
DLT_JUNIPER_GGSN = 0x85
DLT_JUNIPER_ISM = 0xc2
@@ -242,22 +318,32 @@ const (
DLT_JUNIPER_PPPOE = 0xa7
DLT_JUNIPER_PPPOE_ATM = 0xa8
DLT_JUNIPER_SERVICES = 0x88
+ DLT_JUNIPER_SRX_E2E = 0xe9
DLT_JUNIPER_ST = 0xc8
DLT_JUNIPER_VP = 0xb7
+ DLT_JUNIPER_VS = 0xe8
DLT_LAPB_WITH_DIR = 0xcf
DLT_LAPD = 0xcb
DLT_LIN = 0xd4
+ DLT_LINUX_EVDEV = 0xd8
DLT_LINUX_IRDA = 0x90
DLT_LINUX_LAPD = 0xb1
DLT_LINUX_PPP_WITHDIRECTION = 0xa6
DLT_LINUX_SLL = 0x71
DLT_LOOP = 0x6c
DLT_LTALK = 0x72
+ DLT_MATCHING_MAX = 0xf2
+ DLT_MATCHING_MIN = 0x68
DLT_MFR = 0xb6
DLT_MOST = 0xd3
+ DLT_MPLS = 0xdb
DLT_MTP2 = 0x8c
DLT_MTP2_WITH_PHDR = 0x8b
DLT_MTP3 = 0x8d
+ DLT_MUX27010 = 0xec
+ DLT_NETANALYZER = 0xf0
+ DLT_NETANALYZER_TRANSPARENT = 0xf1
+ DLT_NFLOG = 0xef
DLT_NULL = 0x0
DLT_PCI_EXP = 0x7d
DLT_PFLOG = 0x75
@@ -279,11 +365,13 @@ const (
DLT_SITA = 0xc4
DLT_SLIP = 0x8
DLT_SLIP_BSDOS = 0xf
+ DLT_STANAG_5066_D_PDU = 0xed
DLT_SUNATM = 0x7b
DLT_SYMANTEC_FIREWALL = 0x63
DLT_TZSP = 0x80
DLT_USB = 0xba
DLT_USB_LINUX = 0xbd
+ DLT_USB_LINUX_MMAPPED = 0xdc
DLT_USER0 = 0x93
DLT_USER1 = 0x94
DLT_USER10 = 0x9d
@@ -300,6 +388,7 @@ const (
DLT_USER7 = 0x9a
DLT_USER8 = 0x9b
DLT_USER9 = 0x9c
+ DLT_WIHART = 0xdf
DLT_X2E_SERIAL = 0xd5
DLT_X2E_XORAYA = 0xd6
DT_BLK = 0x6
@@ -346,6 +435,7 @@ const (
EXTPROC = 0x800
FD_CLOEXEC = 0x1
FD_SETSIZE = 0x400
+ FLUSHO = 0x800000
F_CANCEL = 0x5
F_DUP2FD = 0xa
F_DUPFD = 0x0
@@ -369,12 +459,17 @@ const (
F_UNLCK = 0x2
F_UNLCKSYS = 0x4
F_WRLCK = 0x3
+ HUPCL = 0x4000
+ ICANON = 0x100
+ ICRNL = 0x100
+ IEXTEN = 0x400
IFAN_ARRIVAL = 0x0
IFAN_DEPARTURE = 0x1
IFF_ALLMULTI = 0x200
IFF_ALTPHYS = 0x4000
IFF_BROADCAST = 0x2
- IFF_CANTCHANGE = 0x208f72
+ IFF_CANTCHANGE = 0x218f72
+ IFF_CANTCONFIG = 0x10000
IFF_DEBUG = 0x4
IFF_DRV_OACTIVE = 0x400
IFF_DRV_RUNNING = 0x40
@@ -488,6 +583,7 @@ const (
IFT_IEEE8023ADLAG = 0xa1
IFT_IFGSN = 0x91
IFT_IMT = 0xbe
+ IFT_INFINIBAND = 0xc7
IFT_INTERLEAVE = 0x7c
IFT_IP = 0x7e
IFT_IPFORWARD = 0x8e
@@ -603,6 +699,12 @@ const (
IFT_X25MLP = 0x79
IFT_X25PLE = 0x28
IFT_XETHER = 0x1a
+ IGNBRK = 0x1
+ IGNCR = 0x80
+ IGNPAR = 0x4
+ IMAXBEL = 0x2000
+ INLCR = 0x40
+ INPCK = 0x10
IN_CLASSA_HOST = 0xffffff
IN_CLASSA_MAX = 0x80
IN_CLASSA_NET = 0xff000000
@@ -618,6 +720,7 @@ const (
IN_CLASSD_NET = 0xf0000000
IN_CLASSD_NSHIFT = 0x1c
IN_LOOPBACKNET = 0x7f
+ IN_RFC3021_MASK = 0xfffffffe
IPPROTO_3PC = 0x22
IPPROTO_ADFS = 0x44
IPPROTO_AH = 0x33
@@ -679,6 +782,7 @@ const (
IPPROTO_MAX = 0x100
IPPROTO_MAXID = 0x34
IPPROTO_MEAS = 0x13
+ IPPROTO_MH = 0x87
IPPROTO_MHRP = 0x30
IPPROTO_MICP = 0x5f
IPPROTO_MOBILE = 0x37
@@ -709,6 +813,7 @@ const (
IPPROTO_SCCSP = 0x60
IPPROTO_SCTP = 0x84
IPPROTO_SDRP = 0x2a
+ IPPROTO_SEND = 0x103
IPPROTO_SEP = 0x21
IPPROTO_SKIP = 0x39
IPPROTO_SPACER = 0x7fff
@@ -856,6 +961,7 @@ const (
IP_RECVIF = 0x14
IP_RECVOPTS = 0x5
IP_RECVRETOPTS = 0x6
+ IP_RECVTOS = 0x44
IP_RECVTTL = 0x41
IP_RETOPTS = 0x8
IP_RF = 0x8000
@@ -867,10 +973,44 @@ const (
IP_TOS = 0x3
IP_TTL = 0x4
IP_UNBLOCK_SOURCE = 0x49
+ ISIG = 0x80
+ ISTRIP = 0x20
+ IXANY = 0x800
+ IXOFF = 0x400
+ IXON = 0x200
LOCK_EX = 0x2
LOCK_NB = 0x4
LOCK_SH = 0x1
LOCK_UN = 0x8
+ MADV_AUTOSYNC = 0x7
+ MADV_CORE = 0x9
+ MADV_DONTNEED = 0x4
+ MADV_FREE = 0x5
+ MADV_NOCORE = 0x8
+ MADV_NORMAL = 0x0
+ MADV_NOSYNC = 0x6
+ MADV_PROTECT = 0xa
+ MADV_RANDOM = 0x1
+ MADV_SEQUENTIAL = 0x2
+ MADV_WILLNEED = 0x3
+ MAP_ANON = 0x1000
+ MAP_ANONYMOUS = 0x1000
+ MAP_COPY = 0x2
+ MAP_FILE = 0x0
+ MAP_FIXED = 0x10
+ MAP_HASSEMAPHORE = 0x200
+ MAP_NOCORE = 0x20000
+ MAP_NORESERVE = 0x40
+ MAP_NOSYNC = 0x800
+ MAP_PREFAULT_READ = 0x40000
+ MAP_PRIVATE = 0x2
+ MAP_RENAME = 0x20
+ MAP_RESERVED0080 = 0x80
+ MAP_RESERVED0100 = 0x100
+ MAP_SHARED = 0x1
+ MAP_STACK = 0x400
+ MCL_CURRENT = 0x1
+ MCL_FUTURE = 0x2
MSG_COMPAT = 0x8000
MSG_CTRUNC = 0x20
MSG_DONTROUTE = 0x4
@@ -884,11 +1024,16 @@ const (
MSG_PEEK = 0x2
MSG_TRUNC = 0x10
MSG_WAITALL = 0x40
+ MS_ASYNC = 0x1
+ MS_INVALIDATE = 0x2
+ MS_SYNC = 0x0
NET_RT_DUMP = 0x1
NET_RT_FLAGS = 0x2
NET_RT_IFLIST = 0x3
+ NET_RT_IFLISTL = 0x5
NET_RT_IFMALIST = 0x4
- NET_RT_MAXID = 0x5
+ NET_RT_MAXID = 0x6
+ NOFLSH = 0x80000000
NOTE_ATTRIB = 0x8
NOTE_CHILD = 0x4
NOTE_DELETE = 0x1
@@ -912,6 +1057,12 @@ const (
NOTE_TRACKERR = 0x2
NOTE_TRIGGER = 0x1000000
NOTE_WRITE = 0x2
+ OCRNL = 0x10
+ ONLCR = 0x2
+ ONLRET = 0x40
+ ONOCR = 0x20
+ ONOEOT = 0x8
+ OPOST = 0x1
O_ACCMODE = 0x3
O_APPEND = 0x8
O_ASYNC = 0x40
@@ -933,6 +1084,14 @@ const (
O_TRUNC = 0x400
O_TTY_INIT = 0x80000
O_WRONLY = 0x1
+ PARENB = 0x1000
+ PARMRK = 0x8
+ PARODD = 0x2000
+ PENDIN = 0x20000000
+ PROT_EXEC = 0x4
+ PROT_NONE = 0x0
+ PROT_READ = 0x1
+ PROT_WRITE = 0x2
RLIMIT_AS = 0xa
RLIMIT_CORE = 0x4
RLIMIT_CPU = 0x0
@@ -1010,6 +1169,8 @@ const (
RTV_SPIPE = 0x10
RTV_SSTHRESH = 0x20
RTV_WEIGHT = 0x100
+ RT_CACHING_CONTEXT = 0x1
+ RT_DEFAULT_FIB = 0x0
RUSAGE_CHILDREN = -0x1
RUSAGE_SELF = 0x0
RUSAGE_THREAD = 0x1
@@ -1042,6 +1203,7 @@ const (
SIOCGIFCONF = 0xc0106924
SIOCGIFDESCR = 0xc020692a
SIOCGIFDSTADDR = 0xc0206922
+ SIOCGIFFIB = 0xc020695c
SIOCGIFFLAGS = 0xc0206911
SIOCGIFGENERIC = 0xc020693a
SIOCGIFGMEMB = 0xc028698a
@@ -1073,6 +1235,7 @@ const (
SIOCSIFCAP = 0x8020691e
SIOCSIFDESCR = 0x80206929
SIOCSIFDSTADDR = 0x8020690e
+ SIOCSIFFIB = 0x8020695d
SIOCSIFFLAGS = 0x80206910
SIOCSIFGENERIC = 0x80206939
SIOCSIFLLADDR = 0x8020693c
@@ -1115,6 +1278,8 @@ const (
SO_NO_OFFLOAD = 0x4000
SO_OOBINLINE = 0x100
SO_PEERLABEL = 0x1010
+ SO_PROTOCOL = 0x1016
+ SO_PROTOTYPE = 0x1016
SO_RCVBUF = 0x1002
SO_RCVLOWAT = 0x1004
SO_RCVTIMEO = 0x1006
@@ -1127,9 +1292,17 @@ const (
SO_TIMESTAMP = 0x400
SO_TYPE = 0x1008
SO_USELOOPBACK = 0x40
+ SO_USER_COOKIE = 0x1015
+ TCIFLUSH = 0x1
+ TCIOFLUSH = 0x3
+ TCOFLUSH = 0x2
TCP_CA_NAME_MAX = 0x10
TCP_CONGESTION = 0x40
TCP_INFO = 0x20
+ TCP_KEEPCNT = 0x400
+ TCP_KEEPIDLE = 0x100
+ TCP_KEEPINIT = 0x80
+ TCP_KEEPINTVL = 0x200
TCP_MAXBURST = 0x4
TCP_MAXHLEN = 0x3c
TCP_MAXOLEN = 0x28
@@ -1139,10 +1312,11 @@ const (
TCP_MAX_WINSHIFT = 0xe
TCP_MD5SIG = 0x10
TCP_MINMSS = 0xd8
- TCP_MSS = 0x200
+ TCP_MSS = 0x218
TCP_NODELAY = 0x1
TCP_NOOPT = 0x8
TCP_NOPUSH = 0x4
+ TCSAFLUSH = 0x2
TIOCCBRK = 0x2000747a
TIOCCDTR = 0x20007478
TIOCCONS = 0x80047462
@@ -1205,6 +1379,26 @@ const (
TIOCSWINSZ = 0x80087467
TIOCTIMESTAMP = 0x40107459
TIOCUCNTL = 0x80047466
+ TOSTOP = 0x400000
+ VDISCARD = 0xf
+ VDSUSP = 0xb
+ VEOF = 0x0
+ VEOL = 0x1
+ VEOL2 = 0x2
+ VERASE = 0x3
+ VERASE2 = 0x7
+ VINTR = 0x8
+ VKILL = 0x5
+ VLNEXT = 0xe
+ VMIN = 0x10
+ VQUIT = 0x9
+ VREPRINT = 0x6
+ VSTART = 0xc
+ VSTATUS = 0x12
+ VSTOP = 0xd
+ VSUSP = 0xa
+ VTIME = 0x11
+ VWERASE = 0x4
WCONTINUED = 0x4
WCOREFLAG = 0x80
WLINUXCLONE = 0x80000000
@@ -1229,6 +1423,7 @@ const (
EBADRPC = Errno(0x48)
EBUSY = Errno(0x10)
ECANCELED = Errno(0x55)
+ ECAPMODE = Errno(0x5e)
ECHILD = Errno(0xa)
ECONNABORTED = Errno(0x35)
ECONNREFUSED = Errno(0x3d)
@@ -1252,7 +1447,7 @@ const (
EIO = Errno(0x5)
EISCONN = Errno(0x38)
EISDIR = Errno(0x15)
- ELAST = Errno(0x5d)
+ ELAST = Errno(0x5e)
ELOOP = Errno(0x3e)
EMFILE = Errno(0x18)
EMLINK = Errno(0x1f)
@@ -1447,6 +1642,7 @@ var errors = [...]string{
91: "link has been severed",
92: "protocol error",
93: "capabilities insufficient",
+ 94: "not permitted in capability mode",
}
// Signal table
diff --git a/src/pkg/syscall/zerrors_freebsd_arm.go b/src/pkg/syscall/zerrors_freebsd_arm.go
index 92cade265..82f30abc5 100644
--- a/src/pkg/syscall/zerrors_freebsd_arm.go
+++ b/src/pkg/syscall/zerrors_freebsd_arm.go
@@ -7,7 +7,6 @@
package syscall
const (
- //O_CLOEXEC = 0x100000
AF_APPLETALK = 0x10
AF_ARP = 0x23
AF_ATM = 0x1e
@@ -333,10 +332,11 @@ const (
DLT_LINUX_SLL = 0x71
DLT_LOOP = 0x6c
DLT_LTALK = 0x72
- DLT_MATCHING_MAX = 0xf2
+ DLT_MATCHING_MAX = 0xf6
DLT_MATCHING_MIN = 0x68
DLT_MFR = 0xb6
DLT_MOST = 0xd3
+ DLT_MPEG_2_TS = 0xf3
DLT_MPLS = 0xdb
DLT_MTP2 = 0x8c
DLT_MTP2_WITH_PHDR = 0x8b
@@ -344,7 +344,9 @@ const (
DLT_MUX27010 = 0xec
DLT_NETANALYZER = 0xf0
DLT_NETANALYZER_TRANSPARENT = 0xf1
+ DLT_NFC_LLCP = 0xf5
DLT_NFLOG = 0xef
+ DLT_NG40 = 0xf4
DLT_NULL = 0x0
DLT_PCI_EXP = 0x7d
DLT_PFLOG = 0x75
@@ -985,6 +987,35 @@ const (
LOCK_NB = 0x4
LOCK_SH = 0x1
LOCK_UN = 0x8
+ MADV_AUTOSYNC = 0x7
+ MADV_CORE = 0x9
+ MADV_DONTNEED = 0x4
+ MADV_FREE = 0x5
+ MADV_NOCORE = 0x8
+ MADV_NORMAL = 0x0
+ MADV_NOSYNC = 0x6
+ MADV_PROTECT = 0xa
+ MADV_RANDOM = 0x1
+ MADV_SEQUENTIAL = 0x2
+ MADV_WILLNEED = 0x3
+ MAP_ANON = 0x1000
+ MAP_ANONYMOUS = 0x1000
+ MAP_COPY = 0x2
+ MAP_FILE = 0x0
+ MAP_FIXED = 0x10
+ MAP_HASSEMAPHORE = 0x200
+ MAP_NOCORE = 0x20000
+ MAP_NORESERVE = 0x40
+ MAP_NOSYNC = 0x800
+ MAP_PREFAULT_READ = 0x40000
+ MAP_PRIVATE = 0x2
+ MAP_RENAME = 0x20
+ MAP_RESERVED0080 = 0x80
+ MAP_RESERVED0100 = 0x100
+ MAP_SHARED = 0x1
+ MAP_STACK = 0x400
+ MCL_CURRENT = 0x1
+ MCL_FUTURE = 0x2
MSG_COMPAT = 0x8000
MSG_CTRUNC = 0x20
MSG_DONTROUTE = 0x4
@@ -998,6 +1029,9 @@ const (
MSG_PEEK = 0x2
MSG_TRUNC = 0x10
MSG_WAITALL = 0x40
+ MS_ASYNC = 0x1
+ MS_INVALIDATE = 0x2
+ MS_SYNC = 0x0
NET_RT_DUMP = 0x1
NET_RT_FLAGS = 0x2
NET_RT_IFLIST = 0x3
@@ -1059,6 +1093,10 @@ const (
PARMRK = 0x8
PARODD = 0x2000
PENDIN = 0x20000000
+ PROT_EXEC = 0x4
+ PROT_NONE = 0x0
+ PROT_READ = 0x1
+ PROT_WRITE = 0x2
RLIMIT_AS = 0xa
RLIMIT_CORE = 0x4
RLIMIT_CPU = 0x0
@@ -1369,10 +1407,12 @@ const (
VWERASE = 0x4
WCONTINUED = 0x4
WCOREFLAG = 0x80
+ WEXITED = 0x10
WLINUXCLONE = 0x80000000
WNOHANG = 0x1
WNOWAIT = 0x8
WSTOPPED = 0x2
+ WTRAPPED = 0x20
WUNTRACED = 0x2
)
diff --git a/src/pkg/syscall/zsysnum_freebsd_386.go b/src/pkg/syscall/zsysnum_freebsd_386.go
index 5a2bfd119..74400b6f6 100644
--- a/src/pkg/syscall/zsysnum_freebsd_386.go
+++ b/src/pkg/syscall/zsysnum_freebsd_386.go
@@ -149,6 +149,7 @@ const (
SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); }
SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate( \
SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate( \
+ SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id,\
SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); }
SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, \
SYS_RFORK = 251 // { int rfork(int flags); }
@@ -320,7 +321,7 @@ const (
SYS_JAIL_REMOVE = 508 // { int jail_remove(int jid); }
SYS_CLOSEFROM = 509 // { int closefrom(int lowfd); }
SYS_LPATHCONF = 513 // { int lpathconf(char *path, int name); }
- SYS_CAP_NEW = 514 // { int cap_new(int fd, u_int64_t rights); }
+ SYS_CAP_NEW = 514 // { int cap_new(int fd, uint64_t rights); }
SYS_CAP_GETRIGHTS = 515 // { int cap_getrights(int fd, \
SYS_CAP_ENTER = 516 // { int cap_enter(void); }
SYS_CAP_GETMODE = 517 // { int cap_getmode(u_int *modep); }
@@ -337,4 +338,5 @@ const (
SYS_RCTL_REMOVE_RULE = 529 // { int rctl_remove_rule(const void *inbufp, \
SYS_POSIX_FALLOCATE = 530 // { int posix_fallocate(int fd, \
SYS_POSIX_FADVISE = 531 // { int posix_fadvise(int fd, off_t offset, \
+ SYS_WAIT6 = 532 // { int wait6(int idtype, int id, \
)
diff --git a/src/pkg/syscall/zsysnum_freebsd_amd64.go b/src/pkg/syscall/zsysnum_freebsd_amd64.go
index 5a2bfd119..74400b6f6 100644
--- a/src/pkg/syscall/zsysnum_freebsd_amd64.go
+++ b/src/pkg/syscall/zsysnum_freebsd_amd64.go
@@ -149,6 +149,7 @@ const (
SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); }
SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate( \
SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate( \
+ SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id,\
SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); }
SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, \
SYS_RFORK = 251 // { int rfork(int flags); }
@@ -320,7 +321,7 @@ const (
SYS_JAIL_REMOVE = 508 // { int jail_remove(int jid); }
SYS_CLOSEFROM = 509 // { int closefrom(int lowfd); }
SYS_LPATHCONF = 513 // { int lpathconf(char *path, int name); }
- SYS_CAP_NEW = 514 // { int cap_new(int fd, u_int64_t rights); }
+ SYS_CAP_NEW = 514 // { int cap_new(int fd, uint64_t rights); }
SYS_CAP_GETRIGHTS = 515 // { int cap_getrights(int fd, \
SYS_CAP_ENTER = 516 // { int cap_enter(void); }
SYS_CAP_GETMODE = 517 // { int cap_getmode(u_int *modep); }
@@ -337,4 +338,5 @@ const (
SYS_RCTL_REMOVE_RULE = 529 // { int rctl_remove_rule(const void *inbufp, \
SYS_POSIX_FALLOCATE = 530 // { int posix_fallocate(int fd, \
SYS_POSIX_FADVISE = 531 // { int posix_fadvise(int fd, off_t offset, \
+ SYS_WAIT6 = 532 // { int wait6(int idtype, int id, \
)
diff --git a/src/pkg/syscall/zsysnum_freebsd_arm.go b/src/pkg/syscall/zsysnum_freebsd_arm.go
index 5a2bfd119..61a6a3295 100644
--- a/src/pkg/syscall/zsysnum_freebsd_arm.go
+++ b/src/pkg/syscall/zsysnum_freebsd_arm.go
@@ -149,6 +149,7 @@ const (
SYS_FFCLOCK_GETCOUNTER = 241 // { int ffclock_getcounter(ffcounter *ffcount); }
SYS_FFCLOCK_SETESTIMATE = 242 // { int ffclock_setestimate( \
SYS_FFCLOCK_GETESTIMATE = 243 // { int ffclock_getestimate( \
+ SYS_CLOCK_GETCPUCLOCKID2 = 247 // { int clock_getcpuclockid2(id_t id,\
SYS_NTP_GETTIME = 248 // { int ntp_gettime(struct ntptimeval *ntvp); }
SYS_MINHERIT = 250 // { int minherit(void *addr, size_t len, \
SYS_RFORK = 251 // { int rfork(int flags); }
@@ -320,8 +321,8 @@ const (
SYS_JAIL_REMOVE = 508 // { int jail_remove(int jid); }
SYS_CLOSEFROM = 509 // { int closefrom(int lowfd); }
SYS_LPATHCONF = 513 // { int lpathconf(char *path, int name); }
- SYS_CAP_NEW = 514 // { int cap_new(int fd, u_int64_t rights); }
- SYS_CAP_GETRIGHTS = 515 // { int cap_getrights(int fd, \
+ SYS_CAP_NEW = 514 // { int cap_new(int fd, uint64_t rights); }
+ SYS_CAP_RIGHTS_GET = 515 // { int cap_rights_get(int fd, \
SYS_CAP_ENTER = 516 // { int cap_enter(void); }
SYS_CAP_GETMODE = 517 // { int cap_getmode(u_int *modep); }
SYS_PDFORK = 518 // { int pdfork(int *fdp, int flags); }
@@ -337,4 +338,10 @@ const (
SYS_RCTL_REMOVE_RULE = 529 // { int rctl_remove_rule(const void *inbufp, \
SYS_POSIX_FALLOCATE = 530 // { int posix_fallocate(int fd, \
SYS_POSIX_FADVISE = 531 // { int posix_fadvise(int fd, off_t offset, \
+ SYS_WAIT6 = 532 // { int wait6(int idtype, int id, \
+ SYS_CAP_RIGHTS_LIMIT = 533 // { int cap_rights_limit(int fd, \
+ SYS_CAP_IOCTLS_LIMIT = 534 // { int cap_ioctls_limit(int fd, \
+ SYS_CAP_IOCTLS_GET = 535 // { ssize_t cap_ioctls_get(int fd, \
+ SYS_CAP_FCNTLS_LIMIT = 536 // { int cap_fcntls_limit(int fd, \
+ SYS_CAP_FCNTLS_GET = 537 // { int cap_fcntls_get(int fd, \
)
diff --git a/src/pkg/testing/quick/quick.go b/src/pkg/testing/quick/quick.go
index 242709822..761a6471b 100644
--- a/src/pkg/testing/quick/quick.go
+++ b/src/pkg/testing/quick/quick.go
@@ -140,8 +140,6 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
default:
return reflect.Value{}, false
}
-
- return
}
// A Config structure contains options for running a test.
diff --git a/src/pkg/text/template/exec.go b/src/pkg/text/template/exec.go
index b9c03d8f0..12c40b70f 100644
--- a/src/pkg/text/template/exec.go
+++ b/src/pkg/text/template/exec.go
@@ -5,6 +5,7 @@
package template
import (
+ "bytes"
"fmt"
"io"
"reflect"
@@ -125,8 +126,23 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
wr: wr,
vars: []variable{{"$", value}},
}
+ t.init()
if t.Tree == nil || t.Root == nil {
- state.errorf("%q is an incomplete or empty template", t.name)
+ var b bytes.Buffer
+ for name, tmpl := range t.tmpl {
+ if tmpl.Tree == nil || tmpl.Root == nil {
+ continue
+ }
+ if b.Len() > 0 {
+ b.WriteString(", ")
+ }
+ fmt.Fprintf(&b, "%q", name)
+ }
+ var s string
+ if b.Len() > 0 {
+ s = "; defined templates are: " + b.String()
+ }
+ state.errorf("%q is an incomplete or empty template%s", t.Name(), s)
}
state.walk(value, t.Root)
return
diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go
index 683e9ac76..0f8beec5e 100644
--- a/src/pkg/text/template/exec_test.go
+++ b/src/pkg/text/template/exec_test.go
@@ -816,3 +816,40 @@ func TestExecuteOnNewTemplate(t *testing.T) {
// This is issue 3872.
_ = New("Name").Templates()
}
+
+const testTemplates = `{{define "one"}}one{{end}}{{define "two"}}two{{end}}`
+
+func TestMessageForExecuteEmpty(t *testing.T) {
+ // Test a truly empty template.
+ tmpl := New("empty")
+ var b bytes.Buffer
+ err := tmpl.Execute(&b, 0)
+ if err == nil {
+ t.Fatal("expected initial error")
+ }
+ got := err.Error()
+ want := `template: empty: "empty" is an incomplete or empty template`
+ if got != want {
+ t.Errorf("expected error %s got %s", want, got)
+ }
+ // Add a non-empty template to check that the error is helpful.
+ tests, err := New("").Parse(testTemplates)
+ if err != nil {
+ t.Fatal(err)
+ }
+ tmpl.AddParseTree("secondary", tests.Tree)
+ err = tmpl.Execute(&b, 0)
+ if err == nil {
+ t.Fatal("expected second error")
+ }
+ got = err.Error()
+ want = `template: empty: "empty" is an incomplete or empty template; defined templates are: "secondary"`
+ if got != want {
+ t.Errorf("expected error %s got %s", want, got)
+ }
+ // Make sure we can execute the secondary.
+ err = tmpl.ExecuteTemplate(&b, "secondary", 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/src/pkg/text/template/parse/parse.go b/src/pkg/text/template/parse/parse.go
index c0fb9274a..802e298c2 100644
--- a/src/pkg/text/template/parse/parse.go
+++ b/src/pkg/text/template/parse/parse.go
@@ -429,7 +429,6 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
t.unexpected(token, context)
}
}
- return
}
func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
@@ -445,7 +444,6 @@ func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode,
if next.Type() != nodeEnd {
t.errorf("expected end; found %s", next)
}
- elseList = elseList
}
return pipe.Position(), line, pipe, list, elseList
}
diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go
index 4b268f73d..a0ee37ae3 100644
--- a/src/pkg/time/time_test.go
+++ b/src/pkg/time/time_test.go
@@ -11,6 +11,7 @@ import (
"fmt"
"math/big"
"math/rand"
+ "runtime"
"strconv"
"strings"
"testing"
@@ -1299,6 +1300,9 @@ var mallocTest = []struct {
}
func TestCountMallocs(t *testing.T) {
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
for _, mt := range mallocTest {
allocs := int(testing.AllocsPerRun(100, mt.fn))
if allocs > mt.count {
diff --git a/src/pkg/unicode/letter.go b/src/pkg/unicode/letter.go
index 8d56363df..fadaa57d8 100644
--- a/src/pkg/unicode/letter.go
+++ b/src/pkg/unicode/letter.go
@@ -151,7 +151,7 @@ func is32(ranges []Range32, r uint32) bool {
return false
}
-// Is tests whether rune is in the specified table of ranges.
+// Is reports whether the rune is in the specified table of ranges.
func Is(rangeTab *RangeTable, r rune) bool {
r16 := rangeTab.R16
if len(r16) > 0 && r <= rune(r16[len(r16)-1].Hi) {
diff --git a/src/pkg/unicode/maketables.go b/src/pkg/unicode/maketables.go
index 53d8b967e..e5ed08b23 100644
--- a/src/pkg/unicode/maketables.go
+++ b/src/pkg/unicode/maketables.go
@@ -440,7 +440,7 @@ func printCategories() {
varDecl = "\tLetter = _L; // Letter/L is the set of Unicode letters, category L.\n"
varDecl += "\tL = _L\n"
case "M":
- varDecl = "\tMark = _M; // Mark/M is the set of Unicode mark characters, category M.\n"
+ varDecl = "\tMark = _M; // Mark/M is the set of Unicode mark characters, category M.\n"
varDecl += "\tM = _M\n"
case "N":
varDecl = "\tNumber = _N; // Number/N is the set of Unicode number characters, category N.\n"
diff --git a/src/pkg/unicode/tables.go b/src/pkg/unicode/tables.go
index 36b5a3115..939c41dc5 100644
--- a/src/pkg/unicode/tables.go
+++ b/src/pkg/unicode/tables.go
@@ -2864,7 +2864,7 @@ var (
Lo = _Lo // Lo is the set of Unicode characters in category Lo.
Lower = _Ll // Lower is the set of Unicode lower case letters.
Ll = _Ll // Ll is the set of Unicode characters in category Ll.
- Mark = _M // Mark/M is the set of Unicode mark characters, category M.
+ Mark = _M // Mark/M is the set of Unicode mark characters, category M.
M = _M
Mc = _Mc // Mc is the set of Unicode characters in category Mc.
Me = _Me // Me is the set of Unicode characters in category Me.
diff --git a/src/pkg/unicode/utf8/utf8_test.go b/src/pkg/unicode/utf8/utf8_test.go
index c516871c9..758d7a0f8 100644
--- a/src/pkg/unicode/utf8/utf8_test.go
+++ b/src/pkg/unicode/utf8/utf8_test.go
@@ -124,7 +124,7 @@ func TestDecodeRune(t *testing.T) {
s := m.str
r, size = DecodeRuneInString(s)
if r != m.r || size != len(b) {
- t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
+ t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, m.r, len(b))
}
// there's an extra byte that bytes left behind - make sure trailing byte works
@@ -164,7 +164,7 @@ func TestDecodeRune(t *testing.T) {
t.Errorf("DecodeRune(%q) = %#04x, %d want %#04x, %d", b, r, size, RuneError, 1)
}
s = string(b)
- r, size = DecodeRune(b)
+ r, size = DecodeRuneInString(s)
if r != RuneError || size != 1 {
t.Errorf("DecodeRuneInString(%q) = %#04x, %d want %#04x, %d", s, r, size, RuneError, 1)
}
@@ -182,7 +182,7 @@ func TestDecodeSurrogateRune(t *testing.T) {
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)
+ t.Errorf("DecodeRuneInString(%q) = %x, %d want %x, %d", b, r, size, RuneError, 1)
}
}
}
diff --git a/src/run.bash b/src/run.bash
index a026b459c..538d4f6fe 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -74,9 +74,13 @@ go run $GOROOT/test/run.go - .
) || exit $?
[ "$CGO_ENABLED" != 1 ] ||
-[ "$GOHOSTOS" == openbsd ] || # issue 4878
(xcd ../misc/cgo/test
-go test
+go test -ldflags '-linkmode=auto'
+go test -ldflags '-linkmode=internal'
+case "$GOHOSTOS-$GOARCH" in
+darwin-386 | darwin-amd64 | freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd64 | openbsd-386 | openbsd-amd64)
+ go test -ldflags '-linkmode=external'
+esac
) || exit $?
[ "$CGO_ENABLED" != 1 ] ||
@@ -113,9 +117,12 @@ go build ../misc/dashboard/builder ../misc/goplay
./timing.sh -test
) || exit $?
+[ "$GOOS" == openbsd ] || # golang.org/issue/5057
+(
echo
echo '#' ../test/bench/go1
go test ../test/bench/go1
+) || exit $?
(xcd ../test
unset GOMAXPROCS
diff --git a/src/run.bat b/src/run.bat
index 5f7164a0c..3f950f541 100644
--- a/src/run.bat
+++ b/src/run.bat
@@ -72,8 +72,6 @@ if errorlevel 1 goto fail
echo.
:: cgo tests
-:: issue 4955 - cgo is broken
-goto nocgo
if x%CGO_ENABLED% == x0 goto nocgo
echo # ..\misc\cgo\life
go run %GOROOT%\test\run.go - ..\misc\cgo\life
diff --git a/test/bench/garbage/parser.go b/test/bench/garbage/parser.go
index ff7630a9e..d85110b63 100644
--- a/test/bench/garbage/parser.go
+++ b/test/bench/garbage/parser.go
@@ -205,7 +205,6 @@ var packages = []string{
"go/printer",
"go/scanner",
"go/token",
- "go/types",
"hash",
"hash/adler32",
"hash/crc32",
diff --git a/test/bench/go1/fmt_test.go b/test/bench/go1/fmt_test.go
new file mode 100644
index 000000000..d3c695669
--- /dev/null
+++ b/test/bench/go1/fmt_test.go
@@ -0,0 +1,68 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+// benchmark based on fmt/fmt_test.go
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+func BenchmarkFmtFprintfEmpty(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ fmt.Fprintf(&buf, "")
+ }
+}
+
+func BenchmarkFmtFprintfString(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%s", "hello")
+ }
+}
+
+func BenchmarkFmtFprintfInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%d", 5)
+ }
+}
+
+func BenchmarkFmtFprintfIntInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%d %d", 5, 6)
+ }
+}
+
+func BenchmarkFmtFprintfPrefixedInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "This is some meaningless prefix text that needs to be scanned %d", 6)
+ }
+}
+
+func BenchmarkFmtFprintfFloat(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%g", 5.23184)
+ }
+}
+
+func BenchmarkFmtManyArgs(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world")
+ }
+}
diff --git a/test/bench/go1/http_test.go b/test/bench/go1/http_test.go
new file mode 100644
index 000000000..34e789f66
--- /dev/null
+++ b/test/bench/go1/http_test.go
@@ -0,0 +1,45 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+import (
+ "bytes"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+// BenchmarkHTTPClientServer benchmarks both the HTTP client and the HTTP server,
+// on small requests.
+func BenchmarkHTTPClientServer(b *testing.B) {
+ msg := []byte("Hello world.\n")
+ ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ rw.Write(msg)
+ }))
+ defer ts.Close()
+
+ tr := &http.Transport{}
+ defer tr.CloseIdleConnections()
+ cl := &http.Client{
+ Transport: tr,
+ }
+
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ res, err := cl.Get(ts.URL)
+ if err != nil {
+ b.Fatal("Get:", err)
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ b.Fatal("ReadAll:", err)
+ }
+ if !bytes.Equal(all, msg) {
+ b.Fatalf("Got body %q; want %q", all, msg)
+ }
+ }
+}
diff --git a/test/bench/go1/json_test.go b/test/bench/go1/json_test.go
index 614e24a81..1d42619bd 100644
--- a/test/bench/go1/json_test.go
+++ b/test/bench/go1/json_test.go
@@ -7,12 +7,12 @@
package go1
import (
+ "bytes"
"compress/bzip2"
"encoding/base64"
"encoding/json"
"io"
"io/ioutil"
- "strings"
"testing"
)
@@ -23,7 +23,7 @@ var (
func makeJsonBytes() []byte {
var r io.Reader
- r = strings.NewReader(jsonbz2_base64)
+ r = bytes.NewReader(bytes.Replace(jsonbz2_base64, []byte{'\n'}, nil, -1))
r = base64.NewDecoder(base64.StdEncoding, r)
r = bzip2.NewReader(r)
b, err := ioutil.ReadAll(r)
diff --git a/test/bench/go1/jsondata_test.go b/test/bench/go1/jsondata_test.go
index 7d42c9665..cf0fac148 100644
--- a/test/bench/go1/jsondata_test.go
+++ b/test/bench/go1/jsondata_test.go
@@ -13,1806 +13,1807 @@
package go1
-var jsonbz2_base64 = "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" +
- "4Oy2vMLFphr2skmltbAj2yHto+/C1qRSHQI0oYJy4xPAK0hBhkBkzKGIDKfqR5fu" +
- "9Rb6jriPwFfrT57/BORRUS2uxaWe/23vw/VDRJUNDKbcoql9hR1STaoUKFJAhAE0" +
- "AZZLjCTR5qxIgYLhyUQktqwQ0LakMUoDZaYvf1dL7/UTZGZSt/h0bF8bOrkShINm" +
- "UC5JVQoULQdWFmExZOwxx6b/nrJEIzcATXe9RX4uAjQuZbT7+8dvCcTe970nE51j" +
- "cmac2WktrRIBr8KKqmFiShChQWsTPnID4M0CSyZe7rltE0/bIvrM+YcPthAH85JJ" +
- "219mY5mjPQZhiZDYZA1DzBlAjUcjXvLL8BABMGVQh/A/vPwUfqX/5kl6UGGJn8FC" +
- "P2GG+QceVRTNvxzts75paBK7NzM7TzVVUzlIqqif8NJKRImR08cg2cHrQWxKYcNh" +
- "OjnHzz+YPyaL9PWNrPR37fFaHr23fpcy+YYGWlsuQf4q7bXFjzjZ66t5DEnZsqLU" +
- "ixYlKiy0ibZsjalZamaizKs1laSpmk2ratltZbWSta0bazUrFJs0ttalazaQUhKg" +
- "lSUAqyQoWSKtotVYtSmoyW220arUsoo1tpLaNtMsmtaaYsVTbS2UtJgram22rCkS" +
- "qQSxISyQS0FSSyM1KaS2laa0lhNFGhYWigRULZFiyykqoCxFBKRFSItCrIUWLKak" +
- "ppY2WbY2tps1pm2ymqbabbLNiZojaZkrFMKZrKzaWVptZtppijZNM2SzKmmxsRab" +
- "LZs2K1NVqWqEzMlJtmqVRjVNZWllSVLM0LNNZpalZokSlltLasJRUqopUpZIElIE" +
- "lkqrYjVi0aSNqWmLKpslJtFRBbSbbMy1KoplRspaNlNUrNUaaak2mpVFTZVGxk2a" +
- "GTSWmzaCpKbNJW2WqWqKMmNk1GkKUtk2ysrLNs2WwyrMqKpqZmmmKxtmqayKZlUk" +
- "qNltKlRSm2StUtbLWxTNUqlspo1ZtltNKRIqGm0tlRtNmmalNGZYybMozNNKkxpI" +
- "2i2ULJqUrGyyxJslNGpZmtNSsrNWZY222yttmrVNTbWZZMms2lllbKstpmrNMUmp" +
- "KqUtptKyaplKbRSbJbLNplZtqM1KKbabU1ZSUAmUaxpZjUkhUmyZmxbRSltNsrMq" +
- "qVbNtslSptEzVrMqaazNpmkqZsxExpJSk1itlWqay1KppYopMUkkkmbLNlMymsxS" +
- "0TKlNjKbA1TLLLU0lTWalTNMilKmys2ZY2mqViUVKSyksmapVNqSJRqxZSyylMlS" +
- "yLFSWRUliWKLJPR487tzxPbvpf6y887/zT6h9UmfSx2PLPXLE2t67TNb+d8616jt" +
- "tPkeNmjOnd2bULjnN/5x19I3dES+7KaAHB8sg9OaIHogcFmowcPkd56v4UKiqJhg" +
- "oAU9AHxYiJSboAuO2tYkauzYowUsXVGVlc0nYOpihEKtGCELstXcQR40ZwxcKms+" +
- "7pFjCoGnlWDFSsNDI2M37zbDfLv3avdlnZZ+BC52UzTjZKLth+XpejoaOcVlvLIp" +
- "Bt0bICZGx12W3MemDI+BEABpXP87P4rJiq/on3ucmKl3H2qkVoDOXeBVIHThRlRW" +
- "oIeneSsFb5P81QBgJOLBARAX3nH8/r/f8w3ilqIGYIs2ETpWjUrVBz3ap+abPKWH" +
- "pLM3ltPx/+N/Wbt1NbzHN6yn49NkVXLjHsi0YsxWYxt0mpP5liJ0D/BK861JPxVJ" +
- "KrrKd1DEsjkf2fd+E1sqc+0G02nKaZP3/wWYV/JKhVSKU/9f2kP+Es6z7k/gUksW" +
- "JYe1an/921pBsrUdXyfSH+6h3N4k/jE5ItS1VTkajSXnZgf5UtgpKk2jaxZibyd4" +
- "83LeR6x6+RPw/T0lWWVLOy4k54wllqVWtTTUvHd5G6VXZwcLVpZCyOySqT/VUqI2" +
- "a3OjB+BJ/c5vJ17xaYezrA2WTu8JipWJ34en5WSThOGGFkqslgxWw1Riyit2TjUk" +
- "4m2SJs+3WFSYNQcR9lN+j4j1noP93VyHCfI7cNMSZzH2ZNRThulseIk/yU5KdXt9" +
- "v7zmbk+gjtO690cSQSoFfmmeBxfI+vqGsirzNH5C+xTw2WGGHE0X+u176U0uLoPT" +
- "OEn+qsbDvaA4s+lX8EqpJzPrH0sloeXR1c9OiqmXer0zgSe5ZrT6ScTDZPxHCbPN" +
- "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" +
- "1YsdOxwxj98iTq3teHw5yT2NnV6Ms+s+NR8b24bKw/NWKKqqZhiqnM8QftpfQb+C" +
- "Vs3lZLSSASqcfM7yVxGYledbnrN50XJBATYaCsBtFYJlZR2SKwb21+jqRiNFI0Sa" +
- "rSjgiATZnWelW7O0mbziCfju7ylzo7WSqylsYp0JpjJU0qaMlJUUVhGilWTZudCx" +
- "M+kc+l5uTSG84qLYv2ZJMli2qrILI2Tqln4cMqNhAj4gogAncslWOiwaV+BwnPnE" +
- "jdp7E6UlqPtYJYV9Tg3WI95FkO6beZO8nlbeyYVc7od2tLylZPKLTp1I35t2iLsk" +
- "ipSBQqtbUX19H2kWD8z2PyVPmh9rLUcrDSKQsTJIfukqY7Hl5DzdPLdUqq1+LJp5" +
- "emzvHWPLN9YtWeh+2WzylkbFNlTCyVWKZpKyQ4YwqnWq3kKzCwje4lWdzTuDbTZx" +
- "x4bJ8tzHGu7m3prWSakaVZncMwY02dcu7kznctvM5MknBXCmwVtKfU0xWphkowpi" +
- "VsxiVW7I2rWqtRhwpcXDoaZN1MN6tYlKrh3GpWUlJLvXd43OuslSWQ0fVcxqeL+B" +
- "Xv1rpQyBqdm7e1Ra8loulyubVzbXOGoNVpN1/mjcbxaAiUP6xnhT7z2IJaTCQVgt" +
- "DpQcGFJgWSBTA5batqKV5l3ruu7XC3NyZRFeT486vWm68lRqMyRNpSzSpsi1KyzL" +
- "GmTS2azSVMZqtq2bay1a0raVmmyq2yqikIVCwBSIqSpJJKsVBYgSKsBLSopRkS2t" +
- "tKmrVKmA1rSpZU2JTWWSGtUtmsrMWKVLLVRCkSkEqQS0GpKlKZllNtK0WFGTNpZY" +
- "2lmmZKZLbWbabW0ttZTSTFMklmzbbTaajUNZaVNKzWaipYqKmU2mMk2lilaVplhZ" +
- "MykpmlSwamzZsrUtUJCNs2xE2zWbLJpmmmlSyzaYzNqWpssspZTaqtm1VbJlmm01" +
- "kzUtDKks1LIK020pKUpNRlKTSlmUprKzRSmk1NTZZJrNhJIZMlSpNJDMktbNVDEs" +
- "mpKFKVJtllm0ps2WzabGsbM2aQtmsJaMkNaVJmssNbZtbMprNYqWVKlaTUapJmGz" +
- "RClCZhpmEmZpEympqWZmWbRs0SaY0lNTU2lqbLNtts1tsrNtKqSWmGWWW0tZrNiG" +
- "Uy2ylLU2jJWUySmlNmpspWFKJrTVkE1lJmakWTZmUtpS0rKyqpVsilmsNrWWbLMq" +
- "aVLFlNmazabZtNppoZJEkxlJIlplYbNUMaaVKhIUylmxaWkEslm2WoAZmYGmm02k" +
- "mZ9vNcym/zYZ1m/E+UySfg39LUVVWb+0CAnu+IVnzkTYexs7ufDm0VjDZ7mmLPDC" +
- "jvRkCK4NH4KYIPfTEsxAJVJTCY4MNNqKqTgrJkmjRkVkyN9MMuNskxW0mmjTSlSs" +
- "RiUzxDKZmvWVXm9Y8a6VLqbbWXtSMLsZGTNoSqYkyYjI2VEskoLRRUbRRsbWkqSt" +
- "Sau0WgopMsq6V0SZehQ82kyxbJsqq2k6xbaqqpy8chxElkKVybMPBqa1jIGLJqNa" +
- "WSNnw5w5rJRVJ8pXQahwWUzyp0wnz/U0hIEiEYfzEVFZGtr8GqLFqNUUa0pVZVFV" +
- "lLVsEy7VF1qILVeGEk2aS+WJki7F2pqD7InRyG/WjNbxTzY7E029eTdr/1ZJlhzx" +
- "xZEk7TYxZI2Vk4yI8WLZEUcfOpyzjm2I50sicpFjzHRZKelYLMxipnrpolbK2wP3" +
- "Gj5QrZ3mE7dW70dJN3aTWPvGzFnLOYscQkecNk/KdSbVattW/g8tatRJ9BbaVmTU" +
- "cNkbE5NiRgCjqJjBFYYMQEpXT39BIxlLWwvLhFGpGWUqKViqxkcZkznhqQLSNrGQ" +
- "hBUdGYxN2kbWNpAzdTVXSs46S3TNK5yd26mxXO7tXNdm0m6bRbSTJvK6rpKW2TFt" +
- "vPLvJbNaSixoxKyEmNk0kWK0SdjZs2NohYnAsejhFowruXCQlUVFqVGpE0UGZIZE" +
- "c3lktTo03a6N+EiflSdFScJJ0xKRxN5+ZDlCLZB9FWySZUtkhL9OWNS5Kx7HmGk3" +
- "Zm+vn/kuSquatyCwYtGGhIxpQKVBh9sws7qnJ2thu+NtlbJbljpdXFmFp6I0cN3V" +
- "hW7RqTNacWNJ80k/pbIVr82CR/iVzKp1fJPyjz7u0PGnOl53LbDvYakR0ZJD8qm5" +
- "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" +
- "VZY0yZkycNIiDcCJMaGNe5kXBpN+8HIUgoKqYnY1JISR6tshCE6JhknVjg6cMhWn" +
- "JNlbSdppsotV9zG202HYjiEnmTz+E7xXhSrLv5ZtdazVbW2hjEYNKDGEBkJ9/vy+" +
- "vnrFURs1YvpvLuyE245w0VLL1kr7cOg/Ba/Qf0QM8JPxZLLOStL5KZ+faXr7LE9j" +
- "17oH4+OiR8orIu4h/RAagtxGICYpOWtBCN8eXMu7rl485VKQmKi+aU6rwbyfLXpr" +
- "161+qbettfqWN0pL88tJbgpKWur4a8ki2arIszGhZJVK03h6o84nieE+RSDA2EJn" +
- "ygppzrRHjjDHHjQ3oAGNIa0QIJjBiGd8s3glSnsMZSEY1I4BqCBOrFtgXZ7YoGff" +
- "5SOeYkWToVOR6a7/Dmyl7pPebOTUlLEYebR5Ikzr5O+azEJXRy731dGOXtcW5mTx" +
- "HG7GnHVxIbSbnuyUslYdMltVhpO7tytjo3Cx2IyGZDKmmWOxCaYRisSq0VhSVpit" +
- "JWkrS3VY0DcaigxKkRFVBNRkkg1UhOMurldw8knJjznZobpJOCnNMtmM9JI/gses" +
- "Dl0es/T0c4b+aSO5yy8it57PtER7yQ49svq6K2KoqVhjFUqmm02P9rP+enbyTaJy" +
- "k7zyB5VdEyRHyqE2jlT/N+4jPJHNVfOPajFtvo+bRIhxDIiAREIBEBHmAseJvCKp" +
- "aWSr3OREAnaST8LJp9TClbcGN022eOxs0mObY5x+f0+u0ck5RKKUopJrgB87bebv" +
- "yv5u7W3q/fvzQ+JGypskPUreRLIrmybatMsX0a/RksaxtIKIX8sn739qsebzOZiG" +
- "by7s3vdaJR6Dj2macG0WSRT7SDN9KC4xmGSRgRYwaf7MbwGIOPrP6Rb8N/DY1I1H" +
- "JIkrMaQbxJHdIbifDkh15l2d27BHRHVPKch+6RBzeUnBMtctc4pKUyuu2upJrlrq" +
- "667pW6+1t+6Vk20JkkpYV59A5unxbofu3vn21Ey/s+HYx9zasPu1JNm5an1x85Hp" +
- "GG1LFk0RAJ1kfSK+E9UPntJMsjrKWnc/YuFg5pe8Oyx5qIpZEbwKh7e7yTBhymws" +
- "JtGzb8PDzkfvPfLZJ5yR/o9pH2H9KqdtVVX7VbbWI2Nmr22lllliKehVTXVI09Cd" +
- "Z/Ou/e1aKs8lfvPiSD3/Bks8PeYcuVmGgTKW2WyVY/isZRxJN2T4vyfP0vRyfZZK" +
- "rbaZNZsTidKX8ofEcnunxzNEJWu9xbuQ3w1er3T4Y3g7/gteJ4WVbTtmn85O7lJ/" +
- "VEnkTJ9atqsYYYeujDUxIwoxR56sknNj7SbuGneRs8nq4fJO2cpuiWKioslVKlRS" +
- "pJZ/ULtdlKi0b+Z81+yixKtJIPDdvJ+LvDu0SyY/h7/w/FiNs+mias1cSpOznIPK" +
- "yrHt1CY942YTzH+yrZIoqhOEiZIT845d3T6Pps/6Ofl4bEm9vIZB/UJBbEtgRgyB" +
- "QrgTP96/o80lj8FrpZ3WuiX6brraSSqxRuxjTFUbWarrGGKMDbBcSioFSqf3ZLaC" +
- "XBlKqfB9CZLWcmutdlVXXxEzqHZVo2a5uZjrbE5X5CvSKi2WpbDaOR0OqaV2Vjxq" +
- "myEND13YGGgTBqRBqAkgipVktsk1bJm28lu2ll5dkUpklpVLKkqjThs7SaJqeWRG" +
- "VasWSxZLZu4aIgE5GtmzUkyWRexTG+WO1qi40I7X+GXLi6g1d5IU5Kydn5ZoeE4k" +
- "iNK7HJJHZ32hk/RzVTRzKwrOelrcXxZCb6V8ambb6i+3z7g8vV7o2qRK3bNfx+d9" +
- "az5ZypWyvNOJkq2zTDGW3I2kxsrRVg0qaU6NmxvJVssZPf5Ch3jJZiNskkJC5thW" +
- "jziKca5yYTlK0RAJy2l5f1mHrY2Dc6OkI2TTTy2TGVsRATPxGssjZRlnpIg3iSRi" +
- "xI5OR2SOZJPl5/ncvR8vln1Y/uaaeTGFSl5VO11Z1vnvja5W9Kw09ahkgtDDYyAY" +
- "Qw/WRKMp5aFVusKrZpjSKdZ3v58tazxmJb6NXQlD2AabBtG1MLD6P6xKQChW0XsB" +
- "77Y5z/JBkkMXpKgXiWquYcP3Pv6+I4oBI7HediIrxI/Ei95EsFOQPxkk78pP8rbI" +
- "tJ+v+lu6eiHk6+Kqz+L5PSR4npITj7fgsgl+q1VWGLPweJJjUnC/Grtc/J2G01ZT" +
- "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" +
- "GRBBBBBEkFZVQUUkTHdrccRvm2/fthj1pS2KWAbKGFox0dOmXvOlr51nWKGJum43" +
- "BBBIJBq/KsYn0ippp9W01W5ZRjbTSfDNkM7isVOp5Wk82WrJNLTsbRZZzsMYDiQS" +
- "QQGRB573Pe988yZmZmaB0HgHcz7ZHJKFgkEgyIkiSS9eHnk2SvPDryK1aqqqmtW4" +
- "PSycD/w8sflE+v8v83/dyIplqpb1llszKa0Kl8tWXbMGzMy8XWnF0X937o/wO4fq" +
- "0+r7tk9qe2FJ6z3CkozLYqzEKiqUFDKGP7kqsHaWq1aDYcCQokp/eU+vt7uZp4fD" +
- "vw29FcKUSuratW2rX7I00/UcnqCIfPyP4ftqCVUyNaqZi2P7Lo2/nvtw1Ntxu2Ov" +
- "M1cLOMOjTdl/Jw/jqwjhrHX7ljvTS0Ng9YWklWliFUpZUiCjOKclNiKmjWdFMjuo" +
- "dSAo96JmslmGgyCeUmmjEtITqi4DqWXTg4318osVuX2Vfa63aYJNvvZpHIUVXXbr" +
- "pPMYqxKrXRvoXCGuFnXhSb4SVZtAm6ojtvuIBkdOcqdgEZ6lcZZFN1kPKhJJhRBr" +
- "WEQyIWkl1hnFU3uys63k4eJJlSIMlKqoErDI6G4EEUnpZfaOrlixLp9DvOUpB4Ta" +
- "n2/ZW/q+fvPhH07t9H4MT16XESiARMKUE/rVVU3KNwDooJ7dlAzgnD7EhScMIYxZ" +
- "/mOidHDestpVUIAEgC0t7/m9fLzzvPVb1fK+s+Y+f0Pon6xzJ9vzOD8R9GeLf1T5" +
- "3aq222kVRIqwftW1VyfHRO+89MPe5zaktbKQr49+/jZmajwxNu3Zk7fVWkSWG+K2" +
- "a1xZlKFOw5BlJpDTgyzEORiGVhmzt4tctufPV1DsnIxdsV3SbUdlXBrTgwnt41HJ" +
- "0263X9faPss1y+iNSMUfp/X6ff7/6/TW98cccp1bYjhzq/3uXPJj5bT8/7W+nhNo" +
- "/69v1+jGyfY/aaf9UV6T6SQPl1Bq30rH6H4yV69J/bdqqKoSHon4AEpmUtPAez+t" +
- "92Y5lOj2CJ7CYdkZxf0D3R/XfsuFMS/C43Nv5T9sfMZV4L/G9pvd03/3mq9yzlm2" +
- "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" +
- "YS1EJA9jWfE+/5tRUV1ipCoof2zsjgKQ8vpHUIwQU4hNNSOW4tYulfaqfz6P4wYH" +
- "GDM4DID3+NqN1ONUA/PfuPMRXS88tk7zKq/wt5RmaVy9WAxsjPw3pHVUomq01Y27" +
- "q1V1m7Yd2KfWl+O5Zq7729d9zZ0l0p3fEcrJ5YgfbvWje7O3f3xZrowIWRkq4O+T" +
- "FRyxJpiWo4lFPH3WrGdl4cvrRgQWOs7e+Rm7Fg5SGPs7K8wII3++tGhUMYuglST7" +
- "5KtdoyntNOHVVlYkvFyJtG6k2rcPNYnRazDvM0jtv9e0GxHtPw9lbsVHo999iMnW" +
- "ySQyREBBJkSLp6BsnvG/p9faVUKlPzdQ/ZVIRVFqLwVZA3bCzzChJo/VG3vBX5SF" +
- "rWK1RZmzbONI5WDQJSoSvFrWQPYWLVWpk4wJi851alamk1f8QZvBepyqUITCUW1M" +
- "PO3E+bYpbGJWorqrG+spHFPy6ovW+piPxPDpvMK9cLBMXT02D897907tO7q6Tqpw" +
- "mu19VLVj5w68m9aLxrh5pRd60Z1Y7OPlnWyT67h8VWsGO4nUUKiC8Pu5yxhCT898" +
- "xuvPfY+fhoRK5T5qvf5+ore9q8fDLTyk2u/mia2vXGhbTXwjpwro94vOKUYpdrNK" +
- "/ilIKJN59XedxQPPGvYqUmlTpq88kgneW7DHmiG23HMo7Zsh04+H7xMdo7xOJJtY" +
- "eizcYZdt7XbKVK6OL4vQLe/M+3jq86SgU5889oFKfPVuxF3wlFrkIun9efjz79d+" +
- "wYeN/C+u3m1rd0jFGq9X89KmLLXN2C5Po/veZd64ndf3MKIxsceKwWTeL7MD3i1L" +
- "FVj6xz2pzr8QKCFNCFKpIp+xTH6JnyBsNsPitQloYgqd1l5g4jhq6cPDUvHlmwrI" +
- "oOhRQkOJcJfIaDs0KhNWaJJhi4g5WXdYcDKbkpiy7o20IRRpRFyOFooQ42GI3+Su" +
- "oMuUwozR5RSK47UcIoQsIwhhRiAXHRoVM/c+S9/l9R47JC+j+m/Feaff6jz8TUQc" +
- "fBu36cbfXyrsgqiUIyVfLNwCKvgnlBRwKKm+brfbFcOClV8LfTPJElZDw+Yw7n3R" +
- "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" +
- "9Ie3XnPlekWLviZo7sWzm9WT4r4vmvd4+Mn1zI9eadvv8/FYv0fllb9OdHfmF98c" +
- "xiihhSVRBRSemqq32pgz4bzMD6OjNYamHHHp0WsLbYyKxZ3mLD52kY91zW6fPB9d" +
- "GObcd2fPPjX0d4du7bA4tvfmSzb6t9NouC2GU+LHHGJNXK4s3xiY6MfbxT4Z83cZ" +
- "UuZDLGk0mY/Z/iHrRxSY3S1SG9mvzS+bvxc44Th6JqNHLLC4ZR+p+NfpU+sMTeHg" +
- "a67ZI7LO0gsjRa278NqHpyOH+PRsdMcqF5x65vjp0KeJjqR4dknzo+Zsle+oZmSN" +
- "f8ttztuTWnh+4V2fpXP02u7ttibExiUsNhbdfPzh1+rQ09U+enFtXS5qQkjjxMd8" +
- "MkkY56cYwqZcb6vi222vU9cyYersXMh7cOOI2Y7Viz6BNspac/J9fjp3RQw/gqpU" +
- "1kIPpx1mbn6DEJI5wLjKElOj3z3XAvFr+HD+fSn8rhs166dJp1CBw82PeVw26dIv" +
- "7MUi/KQbLXXHt4nPh0fSOYs35zI1WtZGrbfqaOvlNp6VywnitCl7G/RjngwTGOXw" +
- "v3ThnnFFDb8PHJ2lL1vMzxiXS7Hci9P169PULTtp8MorSZB25VNA4Pw6X609+3Vz" +
- "WTVcyRy2dbt8H177mEWSRvh8M+vSerjnx/SZfuZ0beIXSUuzna/Om+czLbbbVfTz" +
- "54naAdd+pE26qa+jh4iOkG3g+U1FmjxmGX6Gj40+jLEntyrIn7/D+T8fy1+Pjjup" +
- "Bc3CtbNuXO2tRdulIu21ItGsL9ccDt6aEtrxfwXjqcDx58HqqhesQkkFR5Hw5s+Y" +
- "95rjxZ49Zxzzzs55zny5Y/Trf42ninShp2tC5MykPXPDq/HSuOcy/Hrg+uXOZjhw" +
- "qpi7evQ+G3aueLbIW2pPLBOXPB2k0qeWcvH8dPX3537NGVVjFVhhjKxliVkqkjay" +
- "ptqZq2S1WktJVZNtVJa0VtCm2mzbZsiNNZVVSy2ti1tS2Sq3md9hy4638z5PHNMz" +
- "Ix3IfMkD8jgU/hevg0z6O9vrhfx2u0pdXi4ooddn1WwLTt3u0dtfx13/DwegMQYQ" +
- "wdp85zgwAfA3hJq69eh7Lu7zLGHl5V6eivCu1elHunTwnjRy61p714uThUcOOcz8" +
- "O1cqxabWOunLt5Rw9iSJHt3F3y3WWZdtujHhx50iRPHtKachw2vnz8eK369x98Ov" +
- "hw2vztQt4JRlnK9QFCycOHEpchMB0Ym5SeIlIUMnPFcafA3klDSwWSTX9VVFP3k/" +
- "KQ0+nzF4rj5wtvArh604+dqCN3Qjz0VcqypVmrlXVlSVcqyiSeckRld1JlJlRlJB" +
- "zmlk1LS0RqoTfWN3vzzprfXjY+ZUWT9c+ednqsvvSSJCkAXphQSFpCgXIwRJFQeP" +
- "HfxpU2Op7pg4ZhX80D8P0HcE+tvtafe0PslS2h6bEUphB+Trt9zcMySlFfrXx8s6" +
- "aKGUneDdfjQ99/yYfX7l9meCDI/bvJDJAQgdu6SzNW3eZlBQykZoKrwo37d0TaW2" +
- "0DnfHOPJfg278PvnXg+re/l0U+vfj83QmJIyIhDN53JH5Px9XhPr2/DXcY+NzGJO" +
- "6t1p8J77+GH2+xfbwXyN7S7ySU8e36ZcY2cmX9ZqJVTbyyJ9LNd2Hy9pFJjOJx48" +
- "YJh9fxDDVU7nuPtjdzVxq4025elJxy5kTGLIXu3JDla90qnLmi/u/hOXSqnQu+mf" +
- "lpHZt8sRqH7saHSSEQXU251XwY4dOFRt18lS6cUnTgWreu+m18JO/RkmYWb9Oofm" +
- "aH1PPXk244ZeFEhws+fI7cknaR6D4fDdfBuITwr5+BweumnDtjA5GjvZpuOHS0si" +
- "Djw9vK9vVXw3M4takTts7RicqcARg31RQ03CvXwCPOWh+DxPrrPL04oI3S1HWXPL" +
- "V28NsefHEu5KGKEqe8NJPYLCCHQMJCQ7PR5y21rbPLh6zyKm7rpxn60/GG3l6l0b" +
- "Mqm2VCL8CsOWG2Qe5VVUemVS2xUlz8FNVTjEzB3gTsxNJ2NL8fkcfOEhUaCuYPW1" +
- "wuNRLHrVBHPnUBbfGqqnLbx2unVlEqcfFU674T6+c8eHON8cbcPxnVY79dPSQXrj" +
- "j02ctOXInljHDTacJEg5ZB5GNDvHrWNOquSOU5GHgGIrXB8Q3PTh49XFuZnMke3D" +
- "Pi349tnTc2x78ZbabfvzMff1Q00qpoqlPdKqaqUObw73hT5rm2u3Djb92qrt3QRw" +
- "acoV3xS8qpNypaaM8CBy9599F75+N8/OM7xre29w+OXpOnjtyeGSEgrypPNCAvLz" +
- "gjvv0nE4N8L06x27SNPjUeRJEjXk3zlzOGsVtiMq9O5Hkcp2VPh8K+XJ7XZx9Zvt" +
- "531nPHGb550jpsrvKpnZ7X182tPp4nB2m23Dj50a+PuHwWvHvJzCvWfD1elNOsfN" +
- "SEgw75bTbwkkc52410eGuLbzmZkZvvVmtPrz195lSMXTdO+GvWa25VN0UMpetNG+" +
- "NwU07IY+Tmk5PCX1drtxw6VwlEnsyq9FxYhCRtIhPTOT09a7ZutZpiLA6pDtYY3V" +
- "5igfFU4zU4brTy7ejat64Qejh0SJHTSTZ3u3h212EB3mgeekTleTDmSOOVnfrh6P" +
- "Y8ntJJ7Pr2KTqnMOYbga2JznETGW1bGqmrY4zLwt8niQD18xElWURb94FyqjnAZ3" +
- "z6YJ1iOcC2nMPuqLNVQhSiLLqoyCroXV+YwVxq9cddcOZJtS0iqScZGJbLQOBQXO" +
- "HE9q+9mbo5znrM8crxzyCVKhGIK9qoKpR4L0FF29epznKxmhKoosQGVDU2h3Ay47" +
- "SFIJE+nw88FX5l03vzu+JfbrzePF0kBSZvDVsr5KaIWZmJzqUoIpQrMhASe/z86c" +
- "6HyL3ZqezLvn2w0+aVZ7vTMRFUZPLRe7Rk+Uox4XrFfp8/Xz18+/jybiRw7VvURT" +
- "5MeVT3Td4+Ma5xHFTVt3xxqcror7cx5cZbWPo78+Fcp3j1jCSRIxTy4+XByxM192" +
- "To8aO6enDlp8Tpwnp5LwvE56l2zffqYlRPPQ4gQywiSLYYacvPXtw/DHocyrt2j0" +
- "e/enNm57m0qsB8YrRH1Lrhwgi85HTIViqnpHjX5odbWnqdJNpywNzy5F55CTpz3b" +
- "Offvji3GWujD788zPCvnTt/r5SH4mbMvVznmrtcufVxUd3tFD8H+XCVA9+aArHR5" +
- "t2MPNpfFspyylwe0mEjs5oJOvfjxfnnNXNbdJPJ5YcaYgXzEbNNe/DNpS95PXWbX" +
- "Lj5me++lriwkeI4ck6bca2nHauuzfPTyrxRXIm23TPacNjajfNUa97T754q3c0rP" +
- "IE5Nere/DaZzyBPTHL667M6YMUiwUw84c4W+5rlfVR6zxCzaeKly9x9x6DhaooPI" +
- "1CNpPHVtq129Z3bpzpOM14nhw8c8mvgVGdYiu3n1jtni6FPTxEt8uOLVAnqxzGvU" +
- "4XXlc09EDkrS68VHEuLovfh0kKjn16nx2624KnuSnHXYVkIprh8uKrXkxp5Z3aqc" +
- "aeE59GkSJ0a8drt6aX+06Y9W1WYqdPi+di9Pw6evm8zGnrTzvvv+GSuG79/XDiov" +
- "H0qepaxPYPTbhXBj1xR4w6Tg6NcOybV4+Om+3X41ItLvfGlU341TWO2R7tSuZO+O" +
- "3asyajzIENvnh5J4Xw8OuDlfBN8GUCx4420ZVU52z250coXTppy6fELl7Rjpy+nP" +
- "x28cG3ng7sNCRkisEe3Ltzt62dtbszTgXpLw27ePvRw+vlFcKR0ekbTaMSHDJB5e" +
- "nZ8vLbTt78dG25fCwkJ//etW1scxPdFsVVsi0tFqS177RsuXJMklSkhrEjSwORa5" +
- "3WlxTnZfjFJJ8qqYtJkGIYaQX+CRXd/3dKH8uAJ8Y9cu+OcSSPAL6Gs336Z468Zz" +
- "vNxQRIyXt3dm7s0SAwKIJ5wEk8AwcCHFznBwg8o1kzNO72t3vAPY+sfngZ9dFb0o" +
- "+X4H6XmWneYezTTiKIZ4CUUD4QEQCdPGmwTwkyTaXmJ2d+i8PAPAvDjERepd2Z2U" +
- "tFeZqfopOh7VAjAeQ8BPpenxxACAkEQhEExObQ9XlR+e37Iw1mN+ICD34z4TEzKK" +
- "dyQ5oUQnsRgHH1l1ker09IZ4KIqyrFUOLmqZbKLYUGaGAgOcGgdbwVvRho1lbYNU" +
- "cdPj1zU4ogY7l1TxfNNPT+zP92ta1Xu6TpY6QeISM9/hrny59kjOErh+Ht2BPj57" +
- "6L5BzgoCDQAx6HNqd9+Dyvbt27Lq3osAuFDt/Zv5zu78vxMXPz5rDDqp1z+Pi2nh" +
- "zxuQkFAnqvWm2HD09db9dvJvpZ775mY/Nd5n5du34vVU6F+N+jTb5SesToqJfaen" +
- "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" +
- "faqcvPWZmV6OkmSyxFrWcJrWi1kksrvvgqr6xW9zj1ymeq4dcNajmbSDkR2mTlry" +
- "5AnE7fgk9Tk978Fs2pXhPvjltkl3AXoF93yfjrr84+98655556eaKe/TcvX8+tDp" +
- "+Pi1RQ8fdUu2pvFdMbdPAQGNN8ivU7S9Ryc166k8yJc5IdVFdb88+uu+/zeZveuG" +
- "j1wuL35UllCnrTCt7IYcNxThFFbQtqjNZgXr60baY2hffWp4+ubvM/NIWzW5Uj1D" +
- "p8eU+ZTg3naukLoZzl+a1n3vGta8samSFp7nvlKVuVxKevXTjTg2duJ3SfNK066b" +
- "lwcPF5xw2+0cZJzrx68c3veNZrGOHXbTSSRwPSDE242fCWz4vTsVKYqOF4bx775p" +
- "0xeOddrOpVXqcPaqqOW22WtV88c4xmZY7dL6ei956V67bbVtWu+nzM5fLQ6pS9sJ" +
- "RXrzSp0cNSpHqF1oswXg7xoeipTO2OO3gSMFkwqyWwWmzzmd5mSrkIb9W0R4V052" +
- "4SQ8m/L07yCFN+NEinDh32PHfHDzfDTYp2pF9vXXneZ84x6vcPRzRtDb1rS9KNoj" +
- "G3tt8trVSm4nKzy3R6xxhOMVR5krVhMyjGXOrVEkqjaow3ghlCSpZNWBcVaxL3Fc" +
- "Y9ZJpkrnJzlzh3m8wze+XP8uV2KlNuHovYPm99afPmu8VUqUJ47l3jmZl5eHCqbb" +
- "HO7xlEBFcBA5Jb3t32Zl9tPvd2smGycKE9uyfDQQPDS8Ltb4qBF9a8qnudmpDwX4" +
- "+wdtdWPrzp5ZJ51IafAcnZAsPkypcqpRFBAcxIYWs3vTR50fEtvnqdcUo/dUXwei" +
- "bTydGiJ4PFIOWjex8NM77ddunuIT3rfm5Wc23BHly1Kmmj152czh1j2qUpWYqJEq" +
- "vL10rcCedpLOreZEjlnPpzu3bt2Pe9pIbbhG5VdskX49R4c9PrbZr3tVMdOn17de" +
- "nw+aNedrTuVI+Pjo67O359n1jijiSSJ9jstJAwAWh6D6ObOekTEOeh3nAr2g7ynr" +
- "8xXTOMYFcwj5xiIpx8cwczh8LfyjzhSPBt74x6zvdzHlySLo8nCSRsk0eS6TRbxm" +
- "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"
+var jsonbz2_base64 = []byte(`
+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
+5dVzU58rFtJ4e3yv9l6buQsjiD1R2Np9hTyeTt6+038W47SRy6PY06E+P3JOgWaQ
+hHAkkR/Xh/2ncXif2afyf4Svf5NvY3/UP3JXCqfaxkZRL/J3CPDzFxNGAzKcQTnd
+cHPayzzbvLxDd1UnVvMbTw9BywcPDfsc2zm/nyMfDmf932T7p87KrxgyeFftQ+tf
+Cfh7HZyeE2aj8Ld3bXw43xb83/u3I6WSftIeD/xbZE/8bwT5H1OjB9vDc2fr8Q+u
+397X9Gf+PSdnVOzpP8PP+c7z52c3SP5Gtkn9kn/w7H1cp+5o+HrPZPv7uTykTn4t
+qMW5ktlnN5X7r3/GJDMMmGVMJN7siu/yfnqffmvSXMu6ft6bOJlTaKqp/L3k/g2n
+c/7fv5SH4e7wSNdHTnGSe7brKd9m2+rfs+75c1sWpbaXqOkkpTo6LvZVDoKaaPJd
+rf6/wabfy//P+Ses/dNe1Wv4P05eaf0Xg/vluP7Okm/5eu4+LJMnvJ6vyfdiuNK0
+Wbn2ZOW7k/O5dVV1S0twqcn6SMKzp/2y3c5D8U7EssiWcxtqybtlfi2p2J1xcn7G
+nI/NwcrP+tfj8/scv7QZ8v3tjkfXsw7Hk28PhyNkcPY3e7To4dLZXs52SnOcp+0v
+BzIaa0rMZV/r4j+X7dHd5OqeK/l2Ng6ZCf3R4MsiMaozClqv621/Cfwfp/G2c4GO
+dLV9XSfLMq1YzWaxrDFXxLOJ3YfCa+Wpzeb8XWTm+JzP+IICf93/kNaqLaNrWSqi
+ttajRqjbapmqtpS2qxVk1bUlWpNqLRWpZqtJNKo1U0ttRsy20zVJqrG2wBY1sVoL
+FUWJs1ikLFTK0am2RVFYUrYNFpNtTCoNYjWpaFbG0TKLTDY1RrJSWwCVU1K0mkrG
+yUpUbZDVikMW0bZkYotZMmZGLRsY0KIViLGjRsUWxtRUzFiTQaisJEzIaWTNYIjU
+RhTZsyUWxsUUlY2oyRsm1G1k1MhLM2Q2gWRRMpDGE0zA0ktFBaZGyBETCCMgSEaj
+EWjaJKU2NqZFooxiokSIyMMUIWEaiMhQoIiiqQmIYEkRhFpEhYqSGCLFCKEMEEGT
+9mvzf2fuM6SFZC4Qd9fugRia8BBCIvlh/UPmUoYBieRgSMiPA/zM5kG80OwWXxVB
+kDKCgX+vVRm/7UQIDInnOZ/vuDq/4D8+p51Kq1Jw/kWTzvI4d9a7SyLfWstuvCsR
+8vO+Ve9WpNJv7s7+fuL8JV+dboUuDPzER7chJZ58smGb6bfHJ+/wytuIdr6d7a47
+bq+tvU9ubKTxSujpWpbkOGArKSYHFiSSfHgG2RPcG5lSlkRGbrdlTVFVeA1pC41W
+V8XE0QYWbMrorO7DWTBoBRpgyaqKdSFItuzQ+QpmRRpSUkgkAkgVhutQk5vCYVVC
+2pCBtTYcnZA1HRmQ5KEKUJCjE441UykKrp04rW12EaksMjEqCmiOKKAiIoVAjHHG
+4Oy2vMLFphr2skmltbAj2yHto+/C1qRSHQI0oYJy4xPAK0hBhkBkzKGIDKfqR5fu
+9Rb6jriPwFfrT57/BORRUS2uxaWe/23vw/VDRJUNDKbcoql9hR1STaoUKFJAhAE0
+AZZLjCTR5qxIgYLhyUQktqwQ0LakMUoDZaYvf1dL7/UTZGZSt/h0bF8bOrkShINm
+UC5JVQoULQdWFmExZOwxx6b/nrJEIzcATXe9RX4uAjQuZbT7+8dvCcTe970nE51j
+cmac2WktrRIBr8KKqmFiShChQWsTPnID4M0CSyZe7rltE0/bIvrM+YcPthAH85JJ
+219mY5mjPQZhiZDYZA1DzBlAjUcjXvLL8BABMGVQh/A/vPwUfqX/5kl6UGGJn8FC
+P2GG+QceVRTNvxzts75paBK7NzM7TzVVUzlIqqif8NJKRImR08cg2cHrQWxKYcNh
+OjnHzz+YPyaL9PWNrPR37fFaHr23fpcy+YYGWlsuQf4q7bXFjzjZ66t5DEnZsqLU
+ixYlKiy0ibZsjalZamaizKs1laSpmk2ratltZbWSta0bazUrFJs0ttalazaQUhKg
+lSUAqyQoWSKtotVYtSmoyW220arUsoo1tpLaNtMsmtaaYsVTbS2UtJgram22rCkS
+qQSxISyQS0FSSyM1KaS2laa0lhNFGhYWigRULZFiyykqoCxFBKRFSItCrIUWLKak
+ppY2WbY2tps1pm2ymqbabbLNiZojaZkrFMKZrKzaWVptZtppijZNM2SzKmmxsRab
+LZs2K1NVqWqEzMlJtmqVRjVNZWllSVLM0LNNZpalZokSlltLasJRUqopUpZIElIE
+lkqrYjVi0aSNqWmLKpslJtFRBbSbbMy1KoplRspaNlNUrNUaaak2mpVFTZVGxk2a
+GTSWmzaCpKbNJW2WqWqKMmNk1GkKUtk2ysrLNs2WwyrMqKpqZmmmKxtmqayKZlUk
+qNltKlRSm2StUtbLWxTNUqlspo1ZtltNKRIqGm0tlRtNmmalNGZYybMozNNKkxpI
+2i2ULJqUrGyyxJslNGpZmtNSsrNWZY222yttmrVNTbWZZMms2lllbKstpmrNMUmp
+KqUtptKyaplKbRSbJbLNplZtqM1KKbabU1ZSUAmUaxpZjUkhUmyZmxbRSltNsrMq
+qVbNtslSptEzVrMqaazNpmkqZsxExpJSk1itlWqay1KppYopMUkkkmbLNlMymsxS
+0TKlNjKbA1TLLLU0lTWalTNMilKmys2ZY2mqViUVKSyksmapVNqSJRqxZSyylMlS
+yLFSWRUliWKLJPR487tzxPbvpf6y887/zT6h9UmfSx2PLPXLE2t67TNb+d8616jt
+tPkeNmjOnd2bULjnN/5x19I3dES+7KaAHB8sg9OaIHogcFmowcPkd56v4UKiqJhg
+oAU9AHxYiJSboAuO2tYkauzYowUsXVGVlc0nYOpihEKtGCELstXcQR40ZwxcKms+
+7pFjCoGnlWDFSsNDI2M37zbDfLv3avdlnZZ+BC52UzTjZKLth+XpejoaOcVlvLIp
+Bt0bICZGx12W3MemDI+BEABpXP87P4rJiq/on3ucmKl3H2qkVoDOXeBVIHThRlRW
+oIeneSsFb5P81QBgJOLBARAX3nH8/r/f8w3ilqIGYIs2ETpWjUrVBz3ap+abPKWH
+pLM3ltPx/+N/Wbt1NbzHN6yn49NkVXLjHsi0YsxWYxt0mpP5liJ0D/BK861JPxVJ
+KrrKd1DEsjkf2fd+E1sqc+0G02nKaZP3/wWYV/JKhVSKU/9f2kP+Es6z7k/gUksW
+JYe1an/921pBsrUdXyfSH+6h3N4k/jE5ItS1VTkajSXnZgf5UtgpKk2jaxZibyd4
+83LeR6x6+RPw/T0lWWVLOy4k54wllqVWtTTUvHd5G6VXZwcLVpZCyOySqT/VUqI2
+a3OjB+BJ/c5vJ17xaYezrA2WTu8JipWJ34en5WSThOGGFkqslgxWw1Riyit2TjUk
+4m2SJs+3WFSYNQcR9lN+j4j1noP93VyHCfI7cNMSZzH2ZNRThulseIk/yU5KdXt9
+v7zmbk+gjtO690cSQSoFfmmeBxfI+vqGsirzNH5C+xTw2WGGHE0X+u176U0uLoPT
+OEn+qsbDvaA4s+lX8EqpJzPrH0sloeXR1c9OiqmXer0zgSe5ZrT6ScTDZPxHCbPN
+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
+am6yrFq3COr+Gv1fkE1ZskzBUlfkrr8b8hzk8yxE2fNMfNrmi187J8z+Bmx2Wzuo
+upumHT834f0K/hL3SkSzQ2U85TkrZYbKMVKVsprfbMMsmUWyWP1W3DVjWss1MNMa
+H1WP6OTaGllrnZoiAS6ssfNp5sy3o6d+z1Phfsunc9WPbpmXPm3eqbeJ3nCllcoS
+R9y0sQeiKPWxdMHSL5yAm6DOmnZx9/de80IwLgMAwP8AgoIErJWSGzBhMaRbyCyG
+/KI3YnIr+zatN5zJm9iJx5FlEPllZszjniMMODP1NDhIdNGSUoDpyr2MFiNFAp7m
+dhmsM3rn7xcKDPsQKdNOmEcqRWE10Vn0f5jdKeQdD+sX9BD/gPSY95PtG5r5T0HY
+ruV86045uEMRVSihTsyZa8MesmkTJVlLKqkjBRhG+JG9NNZ4h9alqTnNfxllQNGA
+0GINwKMDY0ZDqh5V+GFsqw2G6lfuxMZjyPPPVzVO+/y341ul3m+NvxltY2IqNsRY
+1tTEiANRtZmKiypqJVJKtpSltTk/sPm7/O/dRNKm7YOQYxq6uWOcR7KE3fYnBOUc
+rZ8tbxGpQnw+T1h+E9UnrJ+6E4e77/fdEqziI7b4QxqWvgPVY2JuUihvCTzqWzax
+J8k0/ueZNn2cHv/723l7vkvl321HbIYegUM+f6eVz7iFR6+P17uMwF+AHuHwfOrG
+7J7tnlJLoqxiJZp7OkanzOMm8/JPR9k3N9px0iV2kiN/2MZWOp+Dmehw93hD9FiR
+9EvPnH5sfKX5VzOWREnZyUU+va6YuauVpl1jSzGGKqpqKIOVA2BEIIMpS3xoVbiJ
+DZ+4+ep9reEaqbrqJ9X9jOrrvJSr+/C3LCqZIomMTTGl5droWwvUnqT7fVasJ7Q3
+Vdshbp9jH8pBJ6bD2U+Cd/hZbX9ay6kU8KxTu8ttbZlm1Zpptjy1hjMVabYxkKUR
+gyjKMrbFpVVpilVWFxd4lsXb8MOW7fVipDJxhwVyRmzTVLLxkzco2dz5NnmsjnxG
+SQ0xLOUGItVGqYkjaPOd1ixXJ8pvAbHrxPhNAgJ168Kvepi5THZi1Orm5ld4ad8r
+162e8Lnx2rLKuWUXYSACKn+0Q+UPkiWkUT/jy4+mbc//nw1tlzru26a16nw/ipmj
+oukAwgMmggdSKdGbGU/Iprgvjn77Ct2WhTTOcy5KZMORZMZRWwQ6QquGZW1JTVlg
+QmM8osKKGDGMJIGMIBsiwhShSkqxMPy+3NPLDrbgVBbDqzyCBgWZKJrEQiRzR54q
+wia4gUepCJo2SzrcVXl3bH+sTOvr0qFHlmMYpGEQaiFZjEgQmdarIu7T2kdmRlAF
+SkKsnConJTZVYwmzOAdnDjWUlQbpLqEmzOttyWq429ehDBlMRRpyaUji5o2uW/LZ
+8wQgAFSMYB0Wdnuk9X8nH0naSH9JI+g9o2Gzu5nUVw9VrujeRN048OjNoP8LOjhS
+uG/rTtFPk8g307qhpyc48W4wop6dLpbpG62VarE1XE8iOyVK9ztXvOYw0JoSwJZJ
+Ftfft+V8JibSreNomUqaifeYC3fJ5fCnZQIMR8DDQUIxtbZGzGjKKNDyRspoqZqZ
+ossZ6UUDMFZKUgwYwsMaaYqaYrCr66wtypjY2abpVSX/mXeSNkaJPqgQhw2mmMjH
+EHymdzJLzYsvmuuvVbsqy6m7aYqyZnGoerqj3UePiyIVZIoqKthYOZ6vGFsYpWJz
+5ns4SY/yi4BSSyktv0dXbf1b1fl9fp9+36YjGvdRRMDFkx6Pp9wzFt1H2f0Y5CMb
+VjGyUszErxN3k9ks0S1Zk8IeitT1VrI3R37ye53Th502X+9254a+co8o7nMnWdCi
+wosHYmvktSVSyC6P4FSTb4evj8e+aNQ/gr3by2tmlU3bI5CjjaesCuuOTInFMxR6
+BGGiWW1NjQqsYxKUlU0qtak2QF9FdGkKOPTjiqoqd6H0PuA+KaOAwX65yfbt0Uu2
+t+9+OvxwswtdK+Z6T46z9ur6JavYqrVySsYUxinbay2mTZRVK1bWMy8Hm/TRaetZ
+W+L6HJ1GI7KbTEnokj3nzVNViyloqqryY4aU20msYtW5mTfBtWDH/fMFA6MUxGMR
+NFAuSNrZk1GrtLMg2RpFCqVUaUsYRZMiN2Nim9bnyPI1L5d7amo7nk142ZMm73SJ
+/eoPU902bpY5T5yQ6ffJkrLbKvs844reynK6fNsroOIGSOqTdhDZO0IlkpYiq6Oz
+Fkc0U/fPTYvU9bxWXZeLi5F902sZZU2ysGSmlVu0qcXTGyX5KS21VKrYw87pVnOc
+iN204sTwOM8R5cJLXpE8sT3gdCaTqejSJPFnanubqkqvQ5+EkEjrFki/syRPSKqx
+ixHNf1x69+Xp6t6l5LGF8d0xI7umlRgxkIYgsKQGahBGMdwkbbIclCjg2oW00iZA
+hDSVAoDGhqhIDTC4UGjDNVSwINaWT7/c+6B936RGV91beaH+tFpClUqVar6a57xS
+1YsdOxwxj98iTq3teHw5yT2NnV6Ms+s+NR8b24bKw/NWKKqqZhiqnM8QftpfQb+C
+Vs3lZLSSASqcfM7yVxGYledbnrN50XJBATYaCsBtFYJlZR2SKwb21+jqRiNFI0Sa
+rSjgiATZnWelW7O0mbziCfju7ylzo7WSqylsYp0JpjJU0qaMlJUUVhGilWTZudCx
+M+kc+l5uTSG84qLYv2ZJMli2qrILI2Tqln4cMqNhAj4gogAncslWOiwaV+BwnPnE
+jdp7E6UlqPtYJYV9Tg3WI95FkO6beZO8nlbeyYVc7od2tLylZPKLTp1I35t2iLsk
+ipSBQqtbUX19H2kWD8z2PyVPmh9rLUcrDSKQsTJIfukqY7Hl5DzdPLdUqq1+LJp5
+emzvHWPLN9YtWeh+2WzylkbFNlTCyVWKZpKyQ4YwqnWq3kKzCwje4lWdzTuDbTZx
+x4bJ8tzHGu7m3prWSakaVZncMwY02dcu7kznctvM5MknBXCmwVtKfU0xWphkowpi
+VsxiVW7I2rWqtRhwpcXDoaZN1MN6tYlKrh3GpWUlJLvXd43OuslSWQ0fVcxqeL+B
+Xv1rpQyBqdm7e1Ra8loulyubVzbXOGoNVpN1/mjcbxaAiUP6xnhT7z2IJaTCQVgt
+DpQcGFJgWSBTA5batqKV5l3ruu7XC3NyZRFeT486vWm68lRqMyRNpSzSpsi1KyzL
+GmTS2azSVMZqtq2bay1a0raVmmyq2yqikIVCwBSIqSpJJKsVBYgSKsBLSopRkS2t
+tKmrVKmA1rSpZU2JTWWSGtUtmsrMWKVLLVRCkSkEqQS0GpKlKZllNtK0WFGTNpZY
+2lmmZKZLbWbabW0ttZTSTFMklmzbbTaajUNZaVNKzWaipYqKmU2mMk2lilaVplhZ
+MykpmlSwamzZsrUtUJCNs2xE2zWbLJpmmmlSyzaYzNqWpssspZTaqtm1VbJlmm01
+kzUtDKks1LIK020pKUpNRlKTSlmUprKzRSmk1NTZZJrNhJIZMlSpNJDMktbNVDEs
+mpKFKVJtllm0ps2WzabGsbM2aQtmsJaMkNaVJmssNbZtbMprNYqWVKlaTUapJmGz
+RClCZhpmEmZpEympqWZmWbRs0SaY0lNTU2lqbLNtts1tsrNtKqSWmGWWW0tZrNiG
+Uy2ylLU2jJWUySmlNmpspWFKJrTVkE1lJmakWTZmUtpS0rKyqpVsilmsNrWWbLMq
+aVLFlNmazabZtNppoZJEkxlJIlplYbNUMaaVKhIUylmxaWkEslm2WoAZmYGmm02k
+mZ9vNcym/zYZ1m/E+UySfg39LUVVWb+0CAnu+IVnzkTYexs7ufDm0VjDZ7mmLPDC
+jvRkCK4NH4KYIPfTEsxAJVJTCY4MNNqKqTgrJkmjRkVkyN9MMuNskxW0mmjTSlSs
+RiUzxDKZmvWVXm9Y8a6VLqbbWXtSMLsZGTNoSqYkyYjI2VEskoLRRUbRRsbWkqSt
+Sau0WgopMsq6V0SZehQ82kyxbJsqq2k6xbaqqpy8chxElkKVybMPBqa1jIGLJqNa
+WSNnw5w5rJRVJ8pXQahwWUzyp0wnz/U0hIEiEYfzEVFZGtr8GqLFqNUUa0pVZVFV
+lLVsEy7VF1qILVeGEk2aS+WJki7F2pqD7InRyG/WjNbxTzY7E029eTdr/1ZJlhzx
+xZEk7TYxZI2Vk4yI8WLZEUcfOpyzjm2I50sicpFjzHRZKelYLMxipnrpolbK2wP3
+Gj5QrZ3mE7dW70dJN3aTWPvGzFnLOYscQkecNk/KdSbVattW/g8tatRJ9BbaVmTU
+cNkbE5NiRgCjqJjBFYYMQEpXT39BIxlLWwvLhFGpGWUqKViqxkcZkznhqQLSNrGQ
+hBUdGYxN2kbWNpAzdTVXSs46S3TNK5yd26mxXO7tXNdm0m6bRbSTJvK6rpKW2TFt
+vPLvJbNaSixoxKyEmNk0kWK0SdjZs2NohYnAsejhFowruXCQlUVFqVGpE0UGZIZE
+c3lktTo03a6N+EiflSdFScJJ0xKRxN5+ZDlCLZB9FWySZUtkhL9OWNS5Kx7HmGk3
+Zm+vn/kuSquatyCwYtGGhIxpQKVBh9sws7qnJ2thu+NtlbJbljpdXFmFp6I0cN3V
+hW7RqTNacWNJ80k/pbIVr82CR/iVzKp1fJPyjz7u0PGnOl53LbDvYakR0ZJD8qm5
+9mWLpEWRzhu+1n9OUKT1kn8VOh3p4lv5ZjCqf3P82pWjKmxUzVvxpOH8eDZPhDwf
+ii4JZZPcJ67Ts94+JJ8JN6n2RXJ/iPpDEN5uehqR3Yxju2bXbGDrRv6T0R5vdxJO
+R2mD+4dUjVjZFQf6RFZJ8rFskqu7VMy3EjDuzE2K5wH1nnG971lZjE1GMMpMLzVo
+tmMJoN2gv8yApnCpgihcVoiUFH+c9nnbz+momOTD2WTT5sRko0skZYttki1bLSVY
+mmMY0wqhWnGhdSllSSW9z4amEW8VfPq+6qyaeu2jZNvXtEl6ptryvUoxwqtXN1Fm
+Yqyc7Jqlsb2TXkulki/galjcAwqxIxJEkIZjxWvohjDLbjDg3VHCdKtlCUmTvHq1
+g1bKsb1nufaqpD0uQWNon9Cdrrb3LTMlSbUTSbK0ohajIvgjH+99Bt8p3n6qleSV
+ZE6o9h2eHZRzpwc3OYmK009E9R328jxMbJvFH6StQnM1NNmLDBWdD/DwdQc+bD7v
+Uoz8D4pQaY3jgmo4UpCiqrGzZpNbC5h/TXGpNqn1Vaok4ZPk4KphiwyWJy5ZHRwf
+oiZC34h6SrVlWif7FRHs1+Nuh+L5Hs6k7WWyNKyald2mpMaNp8+jr5z3H5HpDpU/
+yqPXPAk91O6UFo2PK2u5jy7lWy35Kw+iPIqfOySOpNDJ1k4nqsilXhkeZbW8c56z
+Rx1kbkR1nBpJ1VUPWotkR0rdsQsexSuL+5pk+Mk2l/i7Oi6XGwkvE5JyD6Ifc0l8
+iIBO6c0DixXt8Wk0H6+6WxFliWWWhO5P1UUsfx/o/JZJ9iprtPkmjEsfWdqnbtat
+q24OckqqqnQw+6k7EfBZHMentbUafUcOiqVVVYFUlFKKqejEY6Y+lfo+ubdLJdCu
+RFXLgVQwrGW3GIYJWGCYwwtWWlUskYxZ+emKaZHyQfWMWTUkP9FV7wTx+WRVUrZI
+0/KPlYWlUqaINRpIxmMlMfoeftr+7+JP2H69M/jD8xaKRKgSrdibLHI0VxjbdHGN
+jQd0aMDA0QIQWEpTRDGZrq3R00OH8GFjuAD9iwhU2MP6wiGD+jp0Ymd06Ksv5piO
+Uq1rMkwZkiw2SmZIUHD5pP5P1qcNmkgD9vum0hi+X4S/PJ3/mfi9rbspyye2Fk1Y
+tSqo+5O33q0nAeTHbg7lc2zBxS2K2xjL/dLmkWZGHQNxp9NkyrGxuvp9akHp3+A3
+ROSdXUb1air5yyvdI8km6PrIgEskaR1ceOmv5q4dpNp4dofKup3NzUTxsvxlZbZ/
+V7KshwsVcSqwxapT6487uYnOE9IdPT5DshyR8GTg8yZIxO7D2Xoe8wbPD2vkrki1
+J6oe6xXDYppjTbDezUkdjZXVjE75bVWXRUdldu05D4OvVbD8SxVZLZ009nJEkSTN
+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
+mStcsHMrio8lNypolKYqrT5AyFDChtZGHuINKBspBGKg7kJt6Bo8fNBswFHISJJt
+PcLdHk1+NWshZCgqnMZITrDX2VnDFGhCe+9um2kaWy3BLFDrBte5ISqMa3whRNX2
+hdsSnCgdmnJiwaaFmqxgEhoSkmS4W5nnc2pOkjMCi0Pn4WGjUumeTCfLJJ1jYrHx
+jaFRrCj5qXWxkTinm7fk9Hu2JvELPk8MMVKpWKtKq1iVVKKUxXlx31G9Tw/vO6Mb
+E80lYmSJp0FRrDJyLJ51U9ZI6GiLTUsTlnZqBqxHcOldSSip2iosJI2Ehx0kHxDZ
+/AZNzYUGDTXrMplachkVuS1tsiYIYyt2mzZDErJJWTTEalrQplZC7YM+li2SUoxV
+VZY0yZkycNIiDcCJMaGNe5kXBpN+8HIUgoKqYnY1JISR6tshCE6JhknVjg6cMhWn
+JNlbSdppsotV9zG202HYjiEnmTz+E7xXhSrLv5ZtdazVbW2hjEYNKDGEBkJ9/vy+
+vnrFURs1YvpvLuyE245w0VLL1kr7cOg/Ba/Qf0QM8JPxZLLOStL5KZ+faXr7LE9j
+17oH4+OiR8orIu4h/RAagtxGICYpOWtBCN8eXMu7rl485VKQmKi+aU6rwbyfLXpr
+161+qbettfqWN0pL88tJbgpKWur4a8ki2arIszGhZJVK03h6o84nieE+RSDA2EJn
+ygppzrRHjjDHHjQ3oAGNIa0QIJjBiGd8s3glSnsMZSEY1I4BqCBOrFtgXZ7YoGff
+5SOeYkWToVOR6a7/Dmyl7pPebOTUlLEYebR5Ikzr5O+azEJXRy731dGOXtcW5mTx
+HG7GnHVxIbSbnuyUslYdMltVhpO7tytjo3Cx2IyGZDKmmWOxCaYRisSq0VhSVpit
+JWkrS3VY0DcaigxKkRFVBNRkkg1UhOMurldw8knJjznZobpJOCnNMtmM9JI/gses
+Dl0es/T0c4b+aSO5yy8it57PtER7yQ49svq6K2KoqVhjFUqmm02P9rP+enbyTaJy
+k7zyB5VdEyRHyqE2jlT/N+4jPJHNVfOPajFtvo+bRIhxDIiAREIBEBHmAseJvCKp
+aWSr3OREAnaST8LJp9TClbcGN022eOxs0mObY5x+f0+u0ck5RKKUopJrgB87bebv
+yv5u7W3q/fvzQ+JGypskPUreRLIrmybatMsX0a/RksaxtIKIX8sn739qsebzOZiG
+by7s3vdaJR6Dj2macG0WSRT7SDN9KC4xmGSRgRYwaf7MbwGIOPrP6Rb8N/DY1I1H
+JIkrMaQbxJHdIbifDkh15l2d27BHRHVPKch+6RBzeUnBMtctc4pKUyuu2upJrlrq
+667pW6+1t+6Vk20JkkpYV59A5unxbofu3vn21Ey/s+HYx9zasPu1JNm5an1x85Hp
+GG1LFk0RAJ1kfSK+E9UPntJMsjrKWnc/YuFg5pe8Oyx5qIpZEbwKh7e7yTBhymws
+JtGzb8PDzkfvPfLZJ5yR/o9pH2H9KqdtVVX7VbbWI2Nmr22lllliKehVTXVI09Cd
+Z/Ou/e1aKs8lfvPiSD3/Bks8PeYcuVmGgTKW2WyVY/isZRxJN2T4vyfP0vRyfZZK
+rbaZNZsTidKX8ofEcnunxzNEJWu9xbuQ3w1er3T4Y3g7/gteJ4WVbTtmn85O7lJ/
+VEnkTJ9atqsYYYeujDUxIwoxR56sknNj7SbuGneRs8nq4fJO2cpuiWKioslVKlRS
+pJZ/ULtdlKi0b+Z81+yixKtJIPDdvJ+LvDu0SyY/h7/w/FiNs+mias1cSpOznIPK
+yrHt1CY942YTzH+yrZIoqhOEiZIT845d3T6Pps/6Ofl4bEm9vIZB/UJBbEtgRgyB
+QrgTP96/o80lj8FrpZ3WuiX6brraSSqxRuxjTFUbWarrGGKMDbBcSioFSqf3ZLaC
+XBlKqfB9CZLWcmutdlVXXxEzqHZVo2a5uZjrbE5X5CvSKi2WpbDaOR0OqaV2Vjxq
+myEND13YGGgTBqRBqAkgipVktsk1bJm28lu2ll5dkUpklpVLKkqjThs7SaJqeWRG
+VasWSxZLZu4aIgE5GtmzUkyWRexTG+WO1qi40I7X+GXLi6g1d5IU5Kydn5ZoeE4k
+iNK7HJJHZ32hk/RzVTRzKwrOelrcXxZCb6V8ambb6i+3z7g8vV7o2qRK3bNfx+d9
+az5ZypWyvNOJkq2zTDGW3I2kxsrRVg0qaU6NmxvJVssZPf5Ch3jJZiNskkJC5thW
+jziKca5yYTlK0RAJy2l5f1mHrY2Dc6OkI2TTTy2TGVsRATPxGssjZRlnpIg3iSRi
+xI5OR2SOZJPl5/ncvR8vln1Y/uaaeTGFSl5VO11Z1vnvja5W9Kw09ahkgtDDYyAY
+Qw/WRKMp5aFVusKrZpjSKdZ3v58tazxmJb6NXQlD2AabBtG1MLD6P6xKQChW0XsB
+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
+Zs2RDWNrUlQ/P8x6SH7v7Pz/8fq/1tn9U3lWuTf1JnUUMBZ0zXwlfGtzjVdDGdNw
+/Wb/TcYvZhOV0yvddt9942XK1inv3hKPY1yG22ftVJYGIHecMa1WHrVRdWNFu82a
+cxAgPKsqap3SvCX1k9lfXPem9N6bX0uaUbPfM+K4StqpjulMkJsnYV74vTdMY1Ed
+oFSIZ4/h6sOvXBROO5iA46Ydg4cPQkTnMmYnMTmTOZL0JQOVaKsWLsGxYqhdCCQM
+UGxBBBEJ7+U3578j0euaooSZ6QPtSOwWKBXnFoZlecqTfq1/RtQ4OItiMpbHqNXS
+LBpu9xQ9UiKIOt8lmoPPrrV81xoI5KWxvXhM3vY8pR7qqK4YLstYwxOVYstg0KRO
+i1fLX6rgTrxlmqlbrkE9LEGeIed9k26rGnWed6Nh06p11O87aBEwmLoD3HcEEAkE
+GRBBBBBEkFZVQUUkTHdrccRvm2/fthj1pS2KWAbKGFox0dOmXvOlr51nWKGJum43
+BBBIJBq/KsYn0ippp9W01W5ZRjbTSfDNkM7isVOp5Wk82WrJNLTsbRZZzsMYDiQS
+QQGRB573Pe988yZmZmaB0HgHcz7ZHJKFgkEgyIkiSS9eHnk2SvPDryK1aqqqmtW4
+PSycD/w8sflE+v8v83/dyIplqpb1llszKa0Kl8tWXbMGzMy8XWnF0X937o/wO4fq
+0+r7tk9qe2FJ6z3CkozLYqzEKiqUFDKGP7kqsHaWq1aDYcCQokp/eU+vt7uZp4fD
+vw29FcKUSuratW2rX7I00/UcnqCIfPyP4ftqCVUyNaqZi2P7Lo2/nvtw1Ntxu2Ov
+M1cLOMOjTdl/Jw/jqwjhrHX7ljvTS0Ng9YWklWliFUpZUiCjOKclNiKmjWdFMjuo
+dSAo96JmslmGgyCeUmmjEtITqi4DqWXTg4318osVuX2Vfa63aYJNvvZpHIUVXXbr
+pPMYqxKrXRvoXCGuFnXhSb4SVZtAm6ojtvuIBkdOcqdgEZ6lcZZFN1kPKhJJhRBr
+WEQyIWkl1hnFU3uys63k4eJJlSIMlKqoErDI6G4EEUnpZfaOrlixLp9DvOUpB4Ta
+n2/ZW/q+fvPhH07t9H4MT16XESiARMKUE/rVVU3KNwDooJ7dlAzgnD7EhScMIYxZ
+/mOidHDestpVUIAEgC0t7/m9fLzzvPVb1fK+s+Y+f0Pon6xzJ9vzOD8R9GeLf1T5
+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
+KIZUKGEwHCFgyKwJcqXSyY9+KkWLMIVwWZW84+AK/Bz5wnaLI44LmU90x/EkyBYo
+YS1EJA9jWfE+/5tRUV1ipCoof2zsjgKQ8vpHUIwQU4hNNSOW4tYulfaqfz6P4wYH
+GDM4DID3+NqN1ONUA/PfuPMRXS88tk7zKq/wt5RmaVy9WAxsjPw3pHVUomq01Y27
+q1V1m7Yd2KfWl+O5Zq7729d9zZ0l0p3fEcrJ5YgfbvWje7O3f3xZrowIWRkq4O+T
+FRyxJpiWo4lFPH3WrGdl4cvrRgQWOs7e+Rm7Fg5SGPs7K8wII3++tGhUMYuglST7
+5KtdoyntNOHVVlYkvFyJtG6k2rcPNYnRazDvM0jtv9e0GxHtPw9lbsVHo999iMnW
+ySQyREBBJkSLp6BsnvG/p9faVUKlPzdQ/ZVIRVFqLwVZA3bCzzChJo/VG3vBX5SF
+rWK1RZmzbONI5WDQJSoSvFrWQPYWLVWpk4wJi851alamk1f8QZvBepyqUITCUW1M
+PO3E+bYpbGJWorqrG+spHFPy6ovW+piPxPDpvMK9cLBMXT02D897907tO7q6Tqpw
+mu19VLVj5w68m9aLxrh5pRd60Z1Y7OPlnWyT67h8VWsGO4nUUKiC8Pu5yxhCT898
+xuvPfY+fhoRK5T5qvf5+ore9q8fDLTyk2u/mia2vXGhbTXwjpwro94vOKUYpdrNK
+/ilIKJN59XedxQPPGvYqUmlTpq88kgneW7DHmiG23HMo7Zsh04+H7xMdo7xOJJtY
+eizcYZdt7XbKVK6OL4vQLe/M+3jq86SgU5889oFKfPVuxF3wlFrkIun9efjz79d+
+wYeN/C+u3m1rd0jFGq9X89KmLLXN2C5Po/veZd64ndf3MKIxsceKwWTeL7MD3i1L
+FVj6xz2pzr8QKCFNCFKpIp+xTH6JnyBsNsPitQloYgqd1l5g4jhq6cPDUvHlmwrI
+oOhRQkOJcJfIaDs0KhNWaJJhi4g5WXdYcDKbkpiy7o20IRRpRFyOFooQ42GI3+Su
+oMuUwozR5RSK47UcIoQsIwhhRiAXHRoVM/c+S9/l9R47JC+j+m/Feaff6jz8TUQc
+fBu36cbfXyrsgqiUIyVfLNwCKvgnlBRwKKm+brfbFcOClV8LfTPJElZDw+Yw7n3R
+/39I96pWacn74akmCfZk9N7Hnbmfnm+G9N9IIVf233Vjv2K+dmOqXTgm/cpSxjx5
+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
+qNO9m2ni+V9vD2uz1tpoxtt5t1PjrlVPhy7WwKnZHuC3ruTKRLY2yUlqGlKqWkiW
+y9iHnhPZO0rN94N2brW8hut0yR51BrPKXs7JGxb5AnRiZTl2Xq1hpiXy8iczq1p0
+4OUvW9g8WPrtcenxbXL58ic8LgbnL1I0m4MeNSM4zVJrWW9uI3DW3tqHzluUwxR9
++s0Vc0hpweORY4VOtNXbALUCyXLqNFcCR7xxw8jTkStO873DPfY017vHfEhE5xAu
+lh+U9Pt+W9++O/u05zeb4c7pzjRaWurtlU91y/Pj38bnSo+8PfvF8I5SNJ62aL20
+QZtJUXrrTO3rYPXw+NeuFWmevi1C41Gt1m2DMqHmySGsXd4XEMFkBpCUlZSTWAUm
+a5gWmZLEQcLCwtjR0rZplkWrZuMqsNpWrMyvBJ5/Gff5lT3FTnKql0x9H4PU/DTX
+OxAXime7qULq7DqoaFW7tVaVWymOAghDdEltpIwwyIooHivfPjSHoqKy0NCBIRpB
+IGQK8fXhPBpMTMhc4OCJWMuxlIYammJ2sgEEXEs8oDopthFpLOUlVTJVAqKGFoiu
+fFmCKtsq1oM33uOW59vV16cDSvt7p7+u80IySXnVy5lF3Mz5ZLDu9ZrDzoUPrekc
+9Ie3XnPlekWLviZo7sWzm9WT4r4vmvd4+Mn1zI9eadvv8/FYv0fllb9OdHfmF98c
+xiihhSVRBRSemqq32pgz4bzMD6OjNYamHHHp0WsLbYyKxZ3mLD52kY91zW6fPB9d
+GObcd2fPPjX0d4du7bA4tvfmSzb6t9NouC2GU+LHHGJNXK4s3xiY6MfbxT4Z83cZ
+UuZDLGk0mY/Z/iHrRxSY3S1SG9mvzS+bvxc44Th6JqNHLLC4ZR+p+NfpU+sMTeHg
+a67ZI7LO0gsjRa278NqHpyOH+PRsdMcqF5x65vjp0KeJjqR4dknzo+Zsle+oZmSN
+f8ttztuTWnh+4V2fpXP02u7ttibExiUsNhbdfPzh1+rQ09U+enFtXS5qQkjjxMd8
+MkkY56cYwqZcb6vi222vU9cyYersXMh7cOOI2Y7Viz6BNspac/J9fjp3RQw/gqpU
+1kIPpx1mbn6DEJI5wLjKElOj3z3XAvFr+HD+fSn8rhs166dJp1CBw82PeVw26dIv
+7MUi/KQbLXXHt4nPh0fSOYs35zI1WtZGrbfqaOvlNp6VywnitCl7G/RjngwTGOXw
+v3ThnnFFDb8PHJ2lL1vMzxiXS7Hci9P169PULTtp8MorSZB25VNA4Pw6X609+3Vz
+WTVcyRy2dbt8H177mEWSRvh8M+vSerjnx/SZfuZ0beIXSUuzna/Om+czLbbbVfTz
+54naAdd+pE26qa+jh4iOkG3g+U1FmjxmGX6Gj40+jLEntyrIn7/D+T8fy1+Pjjup
+Bc3CtbNuXO2tRdulIu21ItGsL9ccDt6aEtrxfwXjqcDx58HqqhesQkkFR5Hw5s+Y
+95rjxZ49Zxzzzs55zny5Y/Trf42ninShp2tC5MykPXPDq/HSuOcy/Hrg+uXOZjhw
+qpi7evQ+G3aueLbIW2pPLBOXPB2k0qeWcvH8dPX3537NGVVjFVhhjKxliVkqkjay
+ptqZq2S1WktJVZNtVJa0VtCm2mzbZsiNNZVVSy2ti1tS2Sq3md9hy4638z5PHNMz
+Ix3IfMkD8jgU/hevg0z6O9vrhfx2u0pdXi4ooddn1WwLTt3u0dtfx13/DwegMQYQ
+wdp85zgwAfA3hJq69eh7Lu7zLGHl5V6eivCu1elHunTwnjRy61p714uThUcOOcz8
+O1cqxabWOunLt5Rw9iSJHt3F3y3WWZdtujHhx50iRPHtKachw2vnz8eK369x98Ov
+hw2vztQt4JRlnK9QFCycOHEpchMB0Ym5SeIlIUMnPFcafA3klDSwWSTX9VVFP3k/
+KQ0+nzF4rj5wtvArh604+dqCN3Qjz0VcqypVmrlXVlSVcqyiSeckRld1JlJlRlJB
+zmlk1LS0RqoTfWN3vzzprfXjY+ZUWT9c+ednqsvvSSJCkAXphQSFpCgXIwRJFQeP
+HfxpU2Op7pg4ZhX80D8P0HcE+tvtafe0PslS2h6bEUphB+Trt9zcMySlFfrXx8s6
+aKGUneDdfjQ99/yYfX7l9meCDI/bvJDJAQgdu6SzNW3eZlBQykZoKrwo37d0TaW2
+0DnfHOPJfg278PvnXg+re/l0U+vfj83QmJIyIhDN53JH5Px9XhPr2/DXcY+NzGJO
+6t1p8J77+GH2+xfbwXyN7S7ySU8e36ZcY2cmX9ZqJVTbyyJ9LNd2Hy9pFJjOJx48
+YJh9fxDDVU7nuPtjdzVxq4025elJxy5kTGLIXu3JDla90qnLmi/u/hOXSqnQu+mf
+lpHZt8sRqH7saHSSEQXU251XwY4dOFRt18lS6cUnTgWreu+m18JO/RkmYWb9Oofm
+aH1PPXk244ZeFEhws+fI7cknaR6D4fDdfBuITwr5+BweumnDtjA5GjvZpuOHS0si
+Djw9vK9vVXw3M4takTts7RicqcARg31RQ03CvXwCPOWh+DxPrrPL04oI3S1HWXPL
+V28NsefHEu5KGKEqe8NJPYLCCHQMJCQ7PR5y21rbPLh6zyKm7rpxn60/GG3l6l0b
+Mqm2VCL8CsOWG2Qe5VVUemVS2xUlz8FNVTjEzB3gTsxNJ2NL8fkcfOEhUaCuYPW1
+wuNRLHrVBHPnUBbfGqqnLbx2unVlEqcfFU674T6+c8eHON8cbcPxnVY79dPSQXrj
+j02ctOXInljHDTacJEg5ZB5GNDvHrWNOquSOU5GHgGIrXB8Q3PTh49XFuZnMke3D
+Pi349tnTc2x78ZbabfvzMff1Q00qpoqlPdKqaqUObw73hT5rm2u3Djb92qrt3QRw
+acoV3xS8qpNypaaM8CBy9599F75+N8/OM7xre29w+OXpOnjtyeGSEgrypPNCAvLz
+gjvv0nE4N8L06x27SNPjUeRJEjXk3zlzOGsVtiMq9O5Hkcp2VPh8K+XJ7XZx9Zvt
+531nPHGb550jpsrvKpnZ7X182tPp4nB2m23Dj50a+PuHwWvHvJzCvWfD1elNOsfN
+SEgw75bTbwkkc52410eGuLbzmZkZvvVmtPrz195lSMXTdO+GvWa25VN0UMpetNG+
+NwU07IY+Tmk5PCX1drtxw6VwlEnsyq9FxYhCRtIhPTOT09a7ZutZpiLA6pDtYY3V
+5igfFU4zU4brTy7ejat64Qejh0SJHTSTZ3u3h212EB3mgeekTleTDmSOOVnfrh6P
+Y8ntJJ7Pr2KTqnMOYbga2JznETGW1bGqmrY4zLwt8niQD18xElWURb94FyqjnAZ3
+z6YJ1iOcC2nMPuqLNVQhSiLLqoyCroXV+YwVxq9cddcOZJtS0iqScZGJbLQOBQXO
+HE9q+9mbo5znrM8crxzyCVKhGIK9qoKpR4L0FF29epznKxmhKoosQGVDU2h3Ay47
+SFIJE+nw88FX5l03vzu+JfbrzePF0kBSZvDVsr5KaIWZmJzqUoIpQrMhASe/z86c
+6HyL3ZqezLvn2w0+aVZ7vTMRFUZPLRe7Rk+Uox4XrFfp8/Xz18+/jybiRw7VvURT
+5MeVT3Td4+Ma5xHFTVt3xxqcror7cx5cZbWPo78+Fcp3j1jCSRIxTy4+XByxM192
+To8aO6enDlp8Tpwnp5LwvE56l2zffqYlRPPQ4gQywiSLYYacvPXtw/DHocyrt2j0
+e/enNm57m0qsB8YrRH1Lrhwgi85HTIViqnpHjX5odbWnqdJNpywNzy5F55CTpz3b
+Offvji3GWujD788zPCvnTt/r5SH4mbMvVznmrtcufVxUd3tFD8H+XCVA9+aArHR5
+t2MPNpfFspyylwe0mEjs5oJOvfjxfnnNXNbdJPJ5YcaYgXzEbNNe/DNpS95PXWbX
+Lj5me++lriwkeI4ck6bca2nHauuzfPTyrxRXIm23TPacNjajfNUa97T754q3c0rP
+IE5Nere/DaZzyBPTHL667M6YMUiwUw84c4W+5rlfVR6zxCzaeKly9x9x6DhaooPI
+1CNpPHVtq129Z3bpzpOM14nhw8c8mvgVGdYiu3n1jtni6FPTxEt8uOLVAnqxzGvU
+4XXlc09EDkrS68VHEuLovfh0kKjn16nx2624KnuSnHXYVkIprh8uKrXkxp5Z3aqc
+aeE59GkSJ0a8drt6aX+06Y9W1WYqdPi+di9Pw6evm8zGnrTzvvv+GSuG79/XDiov
+H0qepaxPYPTbhXBj1xR4w6Tg6NcOybV4+Om+3X41ItLvfGlU341TWO2R7tSuZO+O
+3asyajzIENvnh5J4Xw8OuDlfBN8GUCx4420ZVU52z250coXTppy6fELl7Rjpy+nP
+x28cG3ng7sNCRkisEe3Ltzt62dtbszTgXpLw27ePvRw+vlFcKR0ekbTaMSHDJB5e
+nZ8vLbTt78dG25fCwkJ//etW1scxPdFsVVsi0tFqS177RsuXJMklSkhrEjSwORa5
+3WlxTnZfjFJJ8qqYtJkGIYaQX+CRXd/3dKH8uAJ8Y9cu+OcSSPAL6Gs336Z468Zz
+vNxQRIyXt3dm7s0SAwKIJ5wEk8AwcCHFznBwg8o1kzNO72t3vAPY+sfngZ9dFb0o
++X4H6XmWneYezTTiKIZ4CUUD4QEQCdPGmwTwkyTaXmJ2d+i8PAPAvDjERepd2Z2U
+tFeZqfopOh7VAjAeQ8BPpenxxACAkEQhEExObQ9XlR+e37Iw1mN+ICD34z4TEzKK
+dyQ5oUQnsRgHH1l1ker09IZ4KIqyrFUOLmqZbKLYUGaGAgOcGgdbwVvRho1lbYNU
+cdPj1zU4ogY7l1TxfNNPT+zP92ta1Xu6TpY6QeISM9/hrny59kjOErh+Ht2BPj57
+6L5BzgoCDQAx6HNqd9+Dyvbt27Lq3osAuFDt/Zv5zu78vxMXPz5rDDqp1z+Pi2nh
+zxuQkFAnqvWm2HD09db9dvJvpZ775mY/Nd5n5du34vVU6F+N+jTb5SesToqJfaen
+DXwdO+bu81I8knny2dLk+lPtFD493Hx70x8+ZnD/LrkygIFr4AcZGrTDQcMwVWSB
+UIKC4cStoBZZEzt+9tptwYhbUixKXVLSo3XvhOmipnoTQ+XBJCdfHJ8r47yZmPlN
+tp88W+HnzreZnj2dX2cPfT3zCQm3ifI8tvCeDfBNnl0nnzDynndrPNObjUhIM70k
++Phvzu5niebfbE8NY1HHuJBzqbt41px6TjT2wnuOfnskTlZwenlVTqj+HnLFtEu3
+oQOnRi96VHqH1D1c+g/IZ9nQp1cZlfv1606UPjEUVw/C6dh+Pz4Dro+bIdOl2OTP
+vLTZ5+7/XSX29Bv0PSCdHY28GJ5eY3ddXvTet3d8H187Yn31vrt8fNKu1D4+cOuX
+InT13p65ql8fJv74217Pm/vXbqk3NtnkqrqnTkK7wpfdhA+r975xmcNIp7Twznji
+evTlp74w9peduGxXiNdczaymNYnPSSSSFdH57db5cA+GzcQeEkOBjPVentzlrtHQ
+fBtWJ18UIb3yjguww+BUcg8J5eHbljZU09Ja1euOjrmjp59ooZ2hzKN2Qay4mLA1
+pTOLMipVkiB0k7w4rISoDm5vGxYTTI8ymFxmtm+OGuNY5ZPbcqyxJP8qLkqcrsuN
+XvVCjgr1Q3zy6o5T0ZznGJlVeY1Td52qu2m5V2aq1GXbu10ddY3rOrpy0u3G0gaI
+oCqoGaZwMADnKp1up7vrdzvSOe91CCUrW9pWJcngyfSVtIngw8zxCUFzpAJs+tb5
+Zsn1j4Dp7628zYe6Rgm2wa9FYc1vkPNMB5NQ8Ic3l160dXv1c6zek8W9yRs1O1TS
+z1rN1EhwklOMD2NGX6ryTXTqgq+B6Y+TGD0AgzsO3XvudNp0bcBy7fASeOUcunRo
+167Ew2GNnFZG/O7eEsenI5SHrvvWZ2addPjD+TtfXdODuwvq5huPLaODCtE0ntOn
+L4e8t7dJ5M07bNC1FSRtpsdzzppPfI7dxw1640x8bjJekxsa5Y8VNtjEcBtCWwcl
+ZTbCJcD8HrfbHN5KHTo4Fp819fe92ONY4erddMSl2w76PG6tcHtZwrlPXKVGjFac
+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
+0xeOddrOpVXqcPaqqOW22WtV88c4xmZY7dL6ei956V67bbVtWu+nzM5fLQ6pS9sJ
+RXrzSp0cNSpHqF1oswXg7xoeipTO2OO3gSMFkwqyWwWmzzmd5mSrkIb9W0R4V052
+4SQ8m/L07yCFN+NEinDh32PHfHDzfDTYp2pF9vXXneZ84x6vcPRzRtDb1rS9KNoj
+G3tt8trVSm4nKzy3R6xxhOMVR5krVhMyjGXOrVEkqjaow3ghlCSpZNWBcVaxL3Fc
+Y9ZJpkrnJzlzh3m8wze+XP8uV2KlNuHovYPm99afPmu8VUqUJ47l3jmZl5eHCqbb
+HO7xlEBFcBA5Jb3t32Zl9tPvd2smGycKE9uyfDQQPDS8Ltb4qBF9a8qnudmpDwX4
++wdtdWPrzp5ZJ51IafAcnZAsPkypcqpRFBAcxIYWs3vTR50fEtvnqdcUo/dUXwei
+bTydGiJ4PFIOWjex8NM77ddunuIT3rfm5Wc23BHly1Kmmj152czh1j2qUpWYqJEq
+vL10rcCedpLOreZEjlnPpzu3bt2Pe9pIbbhG5VdskX49R4c9PrbZr3tVMdOn17de
+nw+aNedrTuVI+Pjo67O359n1jijiSSJ9jstJAwAWh6D6ObOekTEOeh3nAr2g7ynr
+8xXTOMYFcwj5xiIpx8cwczh8LfyjzhSPBt74x6zvdzHlySLo8nCSRsk0eS6TRbxm
+Z3wnmxmnHMkNhygxjtJKwkU83mOviqqNjty5d4e44KmUaw855t7i6cPI8nbp5Sqj
+jbpFk2djdy3yk88pG+mJSHbOXfhw58IK24kkSC+DzcXXnNW612O4HXcPOwd+O0Fl
+8PvuZjsCx5376uzwIG+WIPHLtDGueXTEg7dMzfR0JnnGHYm9idAqLLCyKsqxZVXx
+lbdLKpppSUky2SmfGld42pFyh9d+861rCugePr6r6xOggdtdPr4hx457uTlQ/lju
+vcrnltjnbtqu9rUk6cL7e+9cX1mt71d5mJrs2PD2zySR16d72kTx67dPB2rKOy76
+78XpyWhUp8dXq0t/AX04768zWa18ejz5cuUnls27TZy4O2rxRtxcg11S6cfNoYO+
++madlcs6drb67VY8K3zSk4YqtLvupO/Da6JNXUsg3mJLapKtWFixTMIxiMYqYxW1
+DMkpmVKMqXrbSzMt9/sqIqP+t/93+I/0n5Sn7T+QT8zf0X7f+TD+B4CttqUP4hlE
+RRRTARIfupD+YUw/Q0KfxO/YVFVv5cOFw/8J24f+hMf6Mf+DF/3MXL//P7Nv+9/D
+R8PD7NE/L5Y0/73/Q5TalV9v/fbLbfTY6Wd/hbKsn7vhvhcttfh9p/Rx9F7ThpoO
+zo/of+imn7jnrLbavsef4r/UcA+RPuf3Q+f9UqkU/8ap/+MFIjMqlZkqslsVZsrV
+JUlRZLa2yy2qaRaWWqRTKzaZooGCAwg+x/nV+FYg+fi2+gz8s/Z89W73ufUfZfMZ
+rG5jSeX2+tXiLy5tM25ZFqjVUHVXHVO7t3Rjfk7WWV5Xd3zfCC7d74/Bsvzb8BBp
+uu3U3zvXOnzxjyszB3F1Lpzy88Auvjt8OJfX88hg8tvPa23zrze8IBCEkACBACSe
+svoy46IiKqqiKiKrmbpczNUAkJJCTVerLbqur773rXpy1c6c7tea+Z7XygAnXQEQ
+RJmCo+i1VHsgGMnt6oTG4h52C6u8SvLrMP/waB4Bwc2A8sBaDwhBB/o7aeobMefe
+uPi73vZt7rVet2rb0T0fQ/9rykNCbO/hd3LcnNv0nxbJpOOM9dbX3aauDKzP4RVk
+8gGChiP3tin+2Ko0zGvv8rm997r3xV1pt67QJwiEFqEG2tbkdFH93DBwDjIPBfPi
+1V5aFeIAHWiKoxX7fYcN7XsJzs2YByCqCB9JkFUVQVTA6PRvzz5effmf8/OC9PMp
+C+ZtzACFV1K3GMDvG5p00Ri2rRwdRGfGJGZluZmRrhVWSvlPXhbVm0jUeerZfHWX
+OyPb4dvG7fq7d2YuV64ePXrvx6mb41zvjnrfDiqrwFcQ9VbJCMKmIWYsyFKsKZAp
+mGYZYsykKYZSrJYGZBVZVDChZKsAxJMKFRiFQZVKxBZKLJJhJTbbapSlmzRec3cV
+XShD4BDzmq1wkRIYPpUFVy20DjqcYA1wAOHwq+O9r3vWre0sCbAG9xdKyeSrfivb
+QO34ZArRrbCmGhJ6LPbla+t+POc5nw7qzbdSzdq7p0eJSUbVXZtq6NOrQouWy7TR
+Es2HZNRu1Stu7Ysi26gMq7VS751zzvXPF5506HQJCRi6HLltz9uN8Xm7zDLmXMwz
+p7a33LluY0zKuVZCe1T/O/Vl8LrrrqrrpOIUG2dJip/z1f+mv/K98HqwOlWunXPV
+64nVSTpZbdoyVil8PHTcq/c4iSP+Kkth+WA/sxSm2JD/tMfEf8rSNT+n1kfxMmZY
+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 `)
diff --git a/test/bench/go1/parser_test.go b/test/bench/go1/parser_test.go
index 26580b887..7848cadd2 100644
--- a/test/bench/go1/parser_test.go
+++ b/test/bench/go1/parser_test.go
@@ -33,7 +33,7 @@ func makeParserBytes() []byte {
return b
}
-func BenchmarkParse(b *testing.B) {
+func BenchmarkGoParse(b *testing.B) {
b.SetBytes(int64(len(parserbytes)))
for i := 0; i < b.N; i++ {
if _, err := parser.ParseFile(token.NewFileSet(), "", parserbytes, parser.ParseComments); err != nil {
diff --git a/test/bench/go1/regexp_test.go b/test/bench/go1/regexp_test.go
new file mode 100644
index 000000000..3ce9f3a2c
--- /dev/null
+++ b/test/bench/go1/regexp_test.go
@@ -0,0 +1,59 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+import (
+ "math/rand"
+ "regexp"
+ "testing"
+)
+
+// benchmark based on regexp/exec_test.go
+
+var regexpText []byte
+
+func makeRegexpText(n int) []byte {
+ rand.Seed(0) // For reproducibility.
+ if len(regexpText) >= n {
+ return regexpText[:n]
+ }
+ regexpText = make([]byte, n)
+ for i := range regexpText {
+ if rand.Intn(30) == 0 {
+ regexpText[i] = '\n'
+ } else {
+ regexpText[i] = byte(rand.Intn(0x7E+1-0x20) + 0x20)
+ }
+ }
+ return regexpText
+}
+
+func benchmark(b *testing.B, re string, n int) {
+ r := regexp.MustCompile(re)
+ t := makeRegexpText(n)
+ b.ResetTimer()
+ b.SetBytes(int64(n))
+ for i := 0; i < b.N; i++ {
+ if r.Match(t) {
+ b.Fatal("match!")
+ }
+ }
+}
+
+const (
+ easy0 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+ easy1 = "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$"
+ medium = "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+ hard = "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+)
+
+func BenchmarkRegexpMatchEasy0_32(b *testing.B) { benchmark(b, easy0, 32<<0) }
+func BenchmarkRegexpMatchEasy0_1K(b *testing.B) { benchmark(b, easy0, 1<<10) }
+func BenchmarkRegexpMatchEasy1_32(b *testing.B) { benchmark(b, easy1, 32<<0) }
+func BenchmarkRegexpMatchEasy1_1K(b *testing.B) { benchmark(b, easy1, 1<<10) }
+func BenchmarkRegexpMatchMedium_32(b *testing.B) { benchmark(b, medium, 1<<0) }
+func BenchmarkRegexpMatchMedium_1K(b *testing.B) { benchmark(b, medium, 1<<10) }
+func BenchmarkRegexpMatchHard_32(b *testing.B) { benchmark(b, hard, 32<<0) }
+func BenchmarkRegexpMatchHard_1K(b *testing.B) { benchmark(b, hard, 1<<10) }
diff --git a/test/bench/go1/time_test.go b/test/bench/go1/time_test.go
new file mode 100644
index 000000000..4687de31c
--- /dev/null
+++ b/test/bench/go1/time_test.go
@@ -0,0 +1,25 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+// benchmark based on time/time_test.go
+
+import (
+ "testing"
+ "time"
+)
+
+func BenchmarkTimeParse(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ time.Parse(time.ANSIC, "Mon Jan 2 15:04:05 2006")
+ }
+}
+
+func BenchmarkTimeFormat(b *testing.B) {
+ t := time.Unix(1265346057, 0)
+ for i := 0; i < b.N; i++ {
+ t.Format("Mon Jan 2 15:04:05 2006")
+ }
+}
diff --git a/test/cmplx.go b/test/cmplx.go
index 248672e7d..2d8a6229d 100644
--- a/test/cmplx.go
+++ b/test/cmplx.go
@@ -9,12 +9,23 @@
package main
+type (
+ Float32 float32
+ Float64 float64
+ Complex64 complex64
+ Complex128 complex128
+)
+
var (
f32 float32
f64 float64
+ F32 Float32
+ F64 Float64
c64 complex64
c128 complex128
+ C64 Complex64
+ C128 Complex128
)
func main() {
@@ -25,4 +36,19 @@ func main() {
_ = complex128(0) // ok
_ = complex(f32, f64) // ERROR "complex"
_ = complex(f64, f32) // ERROR "complex"
+ _ = complex(f32, F32) // ERROR "complex"
+ _ = complex(F32, f32) // ERROR "complex"
+ _ = complex(f64, F64) // ERROR "complex"
+ _ = complex(F64, f64) // ERROR "complex"
+
+ c128 = complex(f32, f32) // ERROR "cannot use"
+ c64 = complex(f64, f64) // ERROR "cannot use"
+
+ c64 = complex(1.0, 2.0) // ok, constant is untyped
+ c128 = complex(1.0, 2.0)
+ C64 = complex(1.0, 2.0)
+ C128 = complex(1.0, 2.0)
+
+ C64 = complex(f32, f32) // ERROR "cannot use"
+ C128 = complex(f64, f64) // ERROR "cannot use"
}
diff --git a/test/errchk b/test/errchk
index 6b00570bd..b8b312a92 100755
--- a/test/errchk
+++ b/test/errchk
@@ -31,7 +31,7 @@ if(@ARGV < 1) {
# Grab SOURCEFILES
foreach(reverse 0 .. @ARGV-1) {
- unless($ARGV[$_] =~ /\.go$/) {
+ unless($ARGV[$_] =~ /\.(go|s)$/) {
@file = @ARGV[$_+1 .. @ARGV-1];
last;
}
diff --git a/test/escape2.go b/test/escape2.go
index 948161933..511b74a1c 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -80,7 +80,9 @@ func foo12(yyy **int) { // ERROR "leaking param: yyy"
xxx = yyy
}
-func foo13(yyy **int) { // ERROR "yyy does not escape"
+// Must treat yyy as leaking because *yyy leaks, and the escape analysis
+// summaries in exported metadata do not distinguish these two cases.
+func foo13(yyy **int) { // ERROR "leaking param: yyy"
*xxx = *yyy
}
@@ -299,7 +301,8 @@ func (f *Foo) foo45() { // ERROR "f does not escape"
F.x = f.x
}
-func (f *Foo) foo46() { // ERROR "f does not escape"
+// See foo13 above for explanation of why f leaks.
+func (f *Foo) foo46() { // ERROR "leaking param: f"
F.xx = f.xx
}
@@ -1300,3 +1303,25 @@ func G() {
var buf4 [10]byte // ERROR "moved to heap: buf4"
F4(buf4[:]) // ERROR "buf4 escapes to heap"
}
+
+type Tm struct {
+ x int
+}
+
+func (t *Tm) M() { // ERROR "t does not escape"
+}
+
+func foo141() {
+ var f func()
+
+ t := new(Tm) // ERROR "escapes to heap"
+ f = t.M // ERROR "t.M does not escape"
+ _ = f
+}
+
+var gf func()
+
+func foo142() {
+ t := new(Tm) // ERROR "escapes to heap"
+ gf = t.M // ERROR "t.M escapes to heap"
+}
diff --git a/test/fixedbugs/bug040.go b/test/fixedbugs/bug040.go
index 007f47f9f..d2cf88afc 100644
--- a/test/fixedbugs/bug040.go
+++ b/test/fixedbugs/bug040.go
@@ -7,5 +7,5 @@
package main
func f (x, // GCCGO_ERROR "previous"
- x int) { // ERROR "redeclared|redefinition" "duplicate"
+ x int) { // ERROR "duplicate argument|redefinition"
}
diff --git a/test/fixedbugs/bug086.go b/test/fixedbugs/bug086.go
index fc69e0e3f..f03982b30 100644
--- a/test/fixedbugs/bug086.go
+++ b/test/fixedbugs/bug086.go
@@ -6,12 +6,12 @@
package main
-func f() int { // ERROR "return|control"
+func f() int { // GCCGO_ERROR "control"
if false {
return 0;
}
// we should not be able to return successfully w/o a return statement
-}
+} // GC_ERROR "return"
func main() {
print(f(), "\n");
diff --git a/test/fixedbugs/bug342.go b/test/fixedbugs/bug342.go
index 5f1efbdfe..ffcb66811 100644
--- a/test/fixedbugs/bug342.go
+++ b/test/fixedbugs/bug342.go
@@ -9,11 +9,7 @@
package p
type a interface {
- foo(x int) (x int) // ERROR "redeclared|redefinition"
-}
-
-var b interface {
- bar(y int) (y int) // ERROR "redeclared|redefinition"
+ foo(x int) (x int) // ERROR "duplicate argument|redefinition"
}
/*
diff --git a/test/fixedbugs/bug412.go b/test/fixedbugs/bug412.go
index 8dd0a5fcc..c7ddc0cac 100644
--- a/test/fixedbugs/bug412.go
+++ b/test/fixedbugs/bug412.go
@@ -7,8 +7,8 @@
package p
type t struct {
- x int // ERROR "duplicate field x|duplicate field name .x."
- x int
+ x int // GCCGO_ERROR "duplicate field name .x."
+ x int // GC_ERROR "duplicate field x"
}
func f(t *t) int {
diff --git a/test/fixedbugs/bug469.go b/test/fixedbugs/bug469.go
deleted file mode 100644
index 71157a4c4..000000000
--- a/test/fixedbugs/bug469.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile
-
-// 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 gccgo compiler would complain about a redefinition of i, but
-// the spec imposes no requirements on parameter names in a function
-// type.
-
-package p
-
-type F func(i int) (i int)
diff --git a/test/fixedbugs/bug474.go b/test/fixedbugs/bug474.go
new file mode 100644
index 000000000..b8264872a
--- /dev/null
+++ b/test/fixedbugs/bug474.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Bug in method values: escape analysis was off.
+
+package main
+
+import "sync"
+
+var called = false
+
+type T struct {
+ once sync.Once
+}
+
+func (t *T) M() {
+ called = true
+}
+
+func main() {
+ var t T
+ t.once.Do(t.M)
+ if !called {
+ panic("not called")
+ }
+}
diff --git a/test/fixedbugs/issue4663.go b/test/fixedbugs/issue4663.go
index b3d660287..edaee93c5 100644
--- a/test/fixedbugs/issue4663.go
+++ b/test/fixedbugs/issue4663.go
@@ -11,4 +11,5 @@ package main
func a(b int) int64 {
b // ERROR "not used"
+ return 0
}
diff --git a/test/fixedbugs/issue4813.go b/test/fixedbugs/issue4813.go
new file mode 100644
index 000000000..0ca9d3f72
--- /dev/null
+++ b/test/fixedbugs/issue4813.go
@@ -0,0 +1,52 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4813: use of constant floats as indices.
+
+package main
+
+var A [3]int
+var S []int
+var T string
+
+const (
+ i = 1
+ f = 2.0
+ f2 = 2.1
+ c = complex(2, 0)
+ c2 = complex(2, 1)
+)
+
+var (
+ vf = f
+ vc = c
+)
+
+var (
+ a1 = A[i]
+ a2 = A[f]
+ a3 = A[f2] // ERROR "truncated"
+ a4 = A[c]
+ a5 = A[c2] // ERROR "truncated"
+ a6 = A[vf] // ERROR "non-integer"
+ a7 = A[vc] // ERROR "non-integer"
+
+ s1 = S[i]
+ s2 = S[f]
+ s3 = S[f2] // ERROR "truncated"
+ s4 = S[c]
+ s5 = S[c2] // ERROR "truncated"
+ s6 = S[vf] // ERROR "non-integer"
+ s7 = S[vc] // ERROR "non-integer"
+
+ t1 = T[i]
+ t2 = T[f]
+ t3 = T[f2] // ERROR "truncated"
+ t4 = T[c]
+ t5 = T[c2] // ERROR "truncated"
+ t6 = T[vf] // ERROR "non-integer"
+ t7 = T[vc] // ERROR "non-integer"
+)
diff --git a/test/fixedbugs/issue4964.dir/a.go b/test/fixedbugs/issue4964.dir/a.go
new file mode 100644
index 000000000..2b9e44e35
--- /dev/null
+++ b/test/fixedbugs/issue4964.dir/a.go
@@ -0,0 +1,27 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var global, global2 *int
+
+type T struct {
+ Pointer *int
+}
+
+func dontinline() {}
+
+func Store(t *T) {
+ global = t.Pointer
+ dontinline()
+}
+
+func Store2(t *T) {
+ global2 = t.Pointer
+ dontinline()
+}
+
+func Get() *int {
+ return global
+}
diff --git a/test/fixedbugs/issue4964.dir/b.go b/test/fixedbugs/issue4964.dir/b.go
new file mode 100644
index 000000000..42a6f1d76
--- /dev/null
+++ b/test/fixedbugs/issue4964.dir/b.go
@@ -0,0 +1,34 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func F() {
+ // store 1 in a.global
+ x, y := 1, 2
+ t := a.T{Pointer: &x}
+ a.Store(&t)
+ _ = y
+}
+
+func G() {
+ // store 4 in a.global2
+ x, y := 3, 4
+ t := a.T{Pointer: &y}
+ a.Store2(&t)
+ _ = x
+}
+
+func main() {
+ F()
+ G()
+ p := a.Get()
+ n := *p
+ if n != 1 {
+ println(n, "!= 1")
+ panic("n != 1")
+ }
+}
diff --git a/test/fixedbugs/issue4964.go b/test/fixedbugs/issue4964.go
new file mode 100644
index 000000000..8291d1bb9
--- /dev/null
+++ b/test/fixedbugs/issue4964.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4964: exported escape analysis result is not enough
+// for cross package analysis.
+
+package ignored
diff --git a/test/fixedbugs/issue5002.go b/test/fixedbugs/issue5002.go
new file mode 100644
index 000000000..1e74fa1a1
--- /dev/null
+++ b/test/fixedbugs/issue5002.go
@@ -0,0 +1,16 @@
+// build
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5002: 8g produces invalid CMPL $0, $0.
+// Used to fail at link time.
+
+package main
+
+func main() {
+ var y int64
+ if y%1 == 0 {
+ }
+}
diff --git a/test/fixedbugs/issue5056.go b/test/fixedbugs/issue5056.go
new file mode 100644
index 000000000..a2cde2a50
--- /dev/null
+++ b/test/fixedbugs/issue5056.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5056: escape analysis not applied to wrapper functions
+
+package main
+
+type Foo int16
+
+func (f Foo) Esc() *int{
+ x := int(f)
+ return &x
+}
+
+type iface interface {
+ Esc() *int
+}
+
+var bar, foobar *int
+
+func main() {
+ var quux iface
+ var x Foo
+
+ quux = x
+ bar = quux.Esc()
+ foobar = quux.Esc()
+ if bar == foobar {
+ panic("bar == foobar")
+ }
+}
diff --git a/test/fixedbugs/issue5089.go b/test/fixedbugs/issue5089.go
new file mode 100644
index 000000000..14d6bde98
--- /dev/null
+++ b/test/fixedbugs/issue5089.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5089: gc allows methods on non-locals if symbol already exists
+
+package p
+
+import "bufio"
+
+func (b *bufio.Reader) Buffered() int { // ERROR "non-local"
+ return -1
+}
diff --git a/test/func1.go b/test/func1.go
index c89f7ff2e..fb6f56184 100644
--- a/test/func1.go
+++ b/test/func1.go
@@ -14,6 +14,6 @@ func f1(a int) (int, float32) {
}
-func f2(a int) (a int, b float32) { // ERROR "redeclared|definition"
+func f2(a int) (a int, b float32) { // ERROR "duplicate argument a|definition"
return 8, 8.0
}
diff --git a/test/funcdup.go b/test/funcdup.go
new file mode 100644
index 000000000..706dd63ca
--- /dev/null
+++ b/test/funcdup.go
@@ -0,0 +1,27 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T interface {
+ F1(i int) (i int) // ERROR "duplicate argument i"
+ F2(i, i int) // ERROR "duplicate argument i"
+ F3() (i, i int) // ERROR "duplicate argument i"
+}
+
+type T1 func(i, i int) // ERROR "duplicate argument i"
+type T2 func(i int) (i int) // ERROR "duplicate argument i"
+type T3 func() (i, i int) // ERROR "duplicate argument i"
+
+type R struct{}
+
+func (i *R) F1(i int) {} // ERROR "duplicate argument i"
+func (i *R) F2() (i int) {return 0} // ERROR "duplicate argument i"
+func (i *R) F3(j int) (j int) {return 0} // ERROR "duplicate argument j"
+
+func F1(i, i int) {} // ERROR "duplicate argument i"
+func F2(i int) (i int) {return 0} // ERROR "duplicate argument i"
+func F3() (i, i int) {return 0, 0} // ERROR "duplicate argument i"
diff --git a/test/funcdup2.go b/test/funcdup2.go
new file mode 100644
index 000000000..aeb5f7eb6
--- /dev/null
+++ b/test/funcdup2.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var T interface {
+ F1(i int) (i int) // ERROR "duplicate argument i"
+ F2(i, i int) // ERROR "duplicate argument i"
+ F3() (i, i int) // ERROR "duplicate argument i"
+}
+
+var T1 func(i, i int) // ERROR "duplicate argument i"
+var T2 func(i int) (i int) // ERROR "duplicate argument i"
+var T3 func() (i, i int) // ERROR "duplicate argument i"
diff --git a/test/index.go b/test/index.go
index daab45f7a..f9360c102 100644
--- a/test/index.go
+++ b/test/index.go
@@ -36,6 +36,8 @@ const (
ci64big int64 = 1<<31
ci64bigger int64 = 1<<32
chuge = 1<<100
+ cfgood = 2.0
+ cfbad = 2.1
cnj = -2
cni int = -3
@@ -46,6 +48,8 @@ const (
cni64big int64 = -1<<31
cni64bigger int64 = -1<<32
cnhuge = -1<<100
+ cnfgood = -2.0
+ cnfbad = -2.1
)
var j int = 100020
@@ -57,6 +61,8 @@ var i64 int64 = 100023
var i64big int64 = 1<<31
var i64bigger int64 = 1<<32
var huge uint64 = 1<<64 - 1
+var fgood float64 = 2.0
+var fbad float64 = 2.1
var nj int = -10
var ni int = -11
@@ -67,6 +73,8 @@ var ni64 int64 = -13
var ni64big int64 = -1<<31
var ni64bigger int64 = -1<<32
var nhuge int64 = -1<<63
+var nfgood float64 = -2.0
+var nfbad float64 = -2.1
var si []int = make([]int, 10)
var ai [10]int
@@ -156,7 +164,7 @@ func testExpr(b *bufio.Writer, expr string) {
if pass == 0 {
fmt.Fprintf(b, "\ttest(func(){use(%s)}, %q)\n", expr, expr)
} else {
- fmt.Fprintf(b, "\tuse(%s) // ERROR \"index|overflow\"\n", expr)
+ fmt.Fprintf(b, "\tuse(%s) // ERROR \"index|overflow|truncated\"\n", expr)
}
}
@@ -169,15 +177,15 @@ func main() {
fmt.Fprint(b, "// errorcheck\n\n")
}
fmt.Fprint(b, prolog)
-
+
var choices = [][]string{
// Direct value, fetch from struct, fetch from struct pointer.
// The last two cases get us to oindex_const_sudo in gsubr.c.
[]string{"", "t.", "pt."},
-
+
// Array, pointer to array, slice.
[]string{"a", "pa", "s"},
-
+
// Element is int, element is quad (struct).
// This controls whether we end up in gsubr.c (i) or cgen.c (q).
[]string{"i", "q"},
@@ -192,9 +200,9 @@ func main() {
[]string{"", "n"},
// Size of index.
- []string{"j", "i", "i8", "i16", "i32", "i64", "i64big", "i64bigger", "huge"},
+ []string{"j", "i", "i8", "i16", "i32", "i64", "i64big", "i64bigger", "huge", "fgood", "fbad"},
}
-
+
forall(choices, func(x []string) {
p, a, e, big, c, n, i := x[0], x[1], x[2], x[3], x[4], x[5], x[6]
@@ -206,7 +214,7 @@ func main() {
// negative constant
// large constant
thisPass := 0
- if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge") {
+ if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge" || i == "fbad") {
if i == "huge" {
// Due to a detail of 6g's internals,
// the huge constant errors happen in an
@@ -223,27 +231,50 @@ func main() {
thisPass = 2
}
}
-
+
+ pae := p + a + e + big
+ cni := c + n + i
+
// If we're using the big-len data, positive int8 and int16 cannot overflow.
if big == "b" && n == "" && (i == "i8" || i == "i16") {
+ if pass == 0 {
+ fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[0:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[1:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:%s])\n", pae, cni, cni)
+ }
+ return
+ }
+
+ // Float variables cannot be used as indices.
+ if c == "" && (i == "fgood" || i == "fbad") {
+ return
+ }
+ // Integral float constat is ok.
+ if c == "c" && n == "" && i == "fgood" {
+ if pass == 0 {
+ fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[0:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[1:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:%s])\n", pae, cni, cni)
+ }
return
}
// Only print the test case if it is appropriate for this pass.
if thisPass == pass {
- pae := p+a+e+big
- cni := c+n+i
-
// Index operation
- testExpr(b, pae + "[" + cni + "]")
-
+ testExpr(b, pae+"["+cni+"]")
+
// Slice operation.
// Low index 0 is a special case in ggen.c
// so test both 0 and 1.
- testExpr(b, pae + "[0:" + cni + "]")
- testExpr(b, pae + "[1:" + cni + "]")
- testExpr(b, pae + "[" + cni + ":]")
- testExpr(b, pae + "[" + cni + ":" + cni + "]")
+ testExpr(b, pae+"[0:"+cni+"]")
+ testExpr(b, pae+"[1:"+cni+"]")
+ testExpr(b, pae+"["+cni+":]")
+ testExpr(b, pae+"["+cni+":"+cni+"]")
}
})
@@ -253,7 +284,7 @@ func main() {
func forall(choices [][]string, f func([]string)) {
x := make([]string, len(choices))
-
+
var recurse func(d int)
recurse = func(d int) {
if d >= len(choices) {
@@ -261,7 +292,7 @@ func forall(choices [][]string, f func([]string)) {
return
}
for _, x[d] = range choices[d] {
- recurse(d+1)
+ recurse(d + 1)
}
}
recurse(0)
diff --git a/test/method5.go b/test/method5.go
new file mode 100644
index 000000000..36508f2e7
--- /dev/null
+++ b/test/method5.go
@@ -0,0 +1,297 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Concrete types implementing M method.
+// Smaller than a word, word-sized, larger than a word.
+// Value and pointer receivers.
+
+type Tinter interface {
+ M(int, byte) (byte, int)
+}
+
+type Tsmallv byte
+
+func (v Tsmallv) M(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type Tsmallp byte
+
+func (p *Tsmallp) M(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type Twordv uintptr
+
+func (v Twordv) M(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type Twordp uintptr
+
+func (p *Twordp) M(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type Tbigv [2]uintptr
+
+func (v Tbigv) M(x int, b byte) (byte, int) { return b, x+int(v[0])+int(v[1]) }
+
+type Tbigp [2]uintptr
+
+func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x+int(p[0])+int(p[1]) }
+
+// Again, with an unexported method.
+
+type tsmallv byte
+
+func (v tsmallv) m(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type tsmallp byte
+
+func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type twordv uintptr
+
+func (v twordv) m(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type twordp uintptr
+
+func (p *twordp) m(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type tbigv [2]uintptr
+
+func (v tbigv) m(x int, b byte) (byte, int) { return b, x+int(v[0])+int(v[1]) }
+
+type tbigp [2]uintptr
+
+func (p *tbigp) m(x int, b byte) (byte, int) { return b, x+int(p[0])+int(p[1]) }
+
+type tinter interface {
+ m(int, byte) (byte, int)
+}
+
+// Embedding via pointer.
+
+type T1 struct {
+ T2
+}
+
+type T2 struct {
+ *T3
+}
+
+type T3 struct {
+ *T4
+}
+
+type T4 struct {
+}
+
+func (t4 T4) M(x int, b byte) (byte, int) { return b, x+40 }
+
+var failed = false
+
+func CheckI(name string, i Tinter, inc int) {
+ b, x := i.M(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, ".M(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+
+ CheckF("(i="+name+")", i.M, inc)
+}
+
+func CheckF(name string, f func(int, byte) (byte, int), inc int) {
+ b, x := f(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, "(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+}
+
+func checkI(name string, i tinter, inc int) {
+ b, x := i.m(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, ".m(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+
+ checkF("(i="+name+")", i.m, inc)
+}
+
+func checkF(name string, f func(int, byte) (byte, int), inc int) {
+ b, x := f(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, "(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+}
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("not panicking")
+ }
+ }()
+ f()
+}
+
+func shouldNotPanic(f func()) {
+ f()
+}
+
+func main() {
+ sv := Tsmallv(1)
+ CheckI("sv", sv, 1)
+ CheckF("sv.M", sv.M, 1)
+ CheckF("(&sv).M", (&sv).M, 1)
+ psv := &sv
+ CheckI("psv", psv, 1)
+ CheckF("psv.M", psv.M, 1)
+ CheckF("(*psv).M", (*psv).M, 1)
+
+ sp := Tsmallp(2)
+ CheckI("&sp", &sp, 2)
+ CheckF("sp.M", sp.M, 2)
+ CheckF("(&sp).M", (&sp).M, 2)
+ psp := &sp
+ CheckI("psp", psp, 2)
+ CheckF("psp.M", psp.M, 2)
+ CheckF("(*psp).M", (*psp).M, 2)
+
+ wv := Twordv(3)
+ CheckI("wv", wv, 3)
+ CheckF("wv.M", wv.M, 3)
+ CheckF("(&wv).M", (&wv).M, 3)
+ pwv := &wv
+ CheckI("pwv", pwv, 3)
+ CheckF("pwv.M", pwv.M, 3)
+ CheckF("(*pwv).M", (*pwv).M, 3)
+
+ wp := Twordp(4)
+ CheckI("&wp", &wp, 4)
+ CheckF("wp.M", wp.M, 4)
+ CheckF("(&wp).M", (&wp).M, 4)
+ pwp := &wp
+ CheckI("pwp", pwp, 4)
+ CheckF("pwp.M", pwp.M, 4)
+ CheckF("(*pwp).M", (*pwp).M, 4)
+
+ bv := Tbigv([2]uintptr{5, 6})
+ pbv := &bv
+ CheckI("bv", bv, 11)
+ CheckF("bv.M", bv.M, 11)
+ CheckF("(&bv).M", (&bv).M, 11)
+ CheckI("pbv", pbv, 11)
+ CheckF("pbv.M", pbv.M, 11)
+ CheckF("(*pbv).M", (*pbv).M, 11)
+
+ bp := Tbigp([2]uintptr{7,8})
+ CheckI("&bp", &bp, 15)
+ CheckF("bp.M", bp.M, 15)
+ CheckF("(&bp).M", (&bp).M, 15)
+ pbp := &bp
+ CheckI("pbp", pbp, 15)
+ CheckF("pbp.M", pbp.M, 15)
+ CheckF("(*pbp).M", (*pbp).M, 15)
+
+ _sv := tsmallv(1)
+ checkI("_sv", _sv, 1)
+ checkF("_sv.m", _sv.m, 1)
+ checkF("(&_sv).m", (&_sv).m, 1)
+ _psv := &_sv
+ checkI("_psv", _psv, 1)
+ checkF("_psv.m", _psv.m, 1)
+ checkF("(*_psv).m", (*_psv).m, 1)
+
+ _sp := tsmallp(2)
+ checkI("&_sp", &_sp, 2)
+ checkF("_sp.m", _sp.m, 2)
+ checkF("(&_sp).m", (&_sp).m, 2)
+ _psp := &_sp
+ checkI("_psp", _psp, 2)
+ checkF("_psp.m", _psp.m, 2)
+ checkF("(*_psp).m", (*_psp).m, 2)
+
+ _wv := twordv(3)
+ checkI("_wv", _wv, 3)
+ checkF("_wv.m", _wv.m, 3)
+ checkF("(&_wv).m", (&_wv).m, 3)
+ _pwv := &_wv
+ checkI("_pwv", _pwv, 3)
+ checkF("_pwv.m", _pwv.m, 3)
+ checkF("(*_pwv).m", (*_pwv).m, 3)
+
+ _wp := twordp(4)
+ checkI("&_wp", &_wp, 4)
+ checkF("_wp.m", _wp.m, 4)
+ checkF("(&_wp).m", (&_wp).m, 4)
+ _pwp := &_wp
+ checkI("_pwp", _pwp, 4)
+ checkF("_pwp.m", _pwp.m, 4)
+ checkF("(*_pwp).m", (*_pwp).m, 4)
+
+ _bv := tbigv([2]uintptr{5, 6})
+ _pbv := &_bv
+ checkI("_bv", _bv, 11)
+ checkF("_bv.m", _bv.m, 11)
+ checkF("(&_bv).m", (&_bv).m, 11)
+ checkI("_pbv", _pbv, 11)
+ checkF("_pbv.m", _pbv.m, 11)
+ checkF("(*_pbv).m", (*_pbv).m, 11)
+
+ _bp := tbigp([2]uintptr{7,8})
+ checkI("&_bp", &_bp, 15)
+ checkF("_bp.m", _bp.m, 15)
+ checkF("(&_bp).m", (&_bp).m, 15)
+ _pbp := &_bp
+ checkI("_pbp", _pbp, 15)
+ checkF("_pbp.m", _pbp.m, 15)
+ checkF("(*_pbp).m", (*_pbp).m, 15)
+
+ t4 := T4{}
+ t3 := T3{&t4}
+ t2 := T2{&t3}
+ t1 := T1{t2}
+ CheckI("t4", t4, 40)
+ CheckI("&t4", &t4, 40)
+ CheckI("t3", t3, 40)
+ CheckI("&t3", &t3, 40)
+ CheckI("t2", t2, 40)
+ CheckI("&t2", &t2, 40)
+ CheckI("t1", t1, 40)
+ CheckI("&t1", &t1, 40)
+
+ // x.M panics if x is an interface type and is nil,
+ // or if x.M expands to (*x).M where x is nil,
+ // or if x.M expands to x.y.z.w.M where something
+ // along the evaluation of x.y.z.w is nil.
+ var f func(int, byte) (byte, int)
+ shouldPanic(func() { psv = nil; f = psv.M })
+ shouldPanic(func() { pwv = nil; f = pwv.M })
+ shouldPanic(func() { pbv = nil; f = pbv.M })
+ shouldPanic(func() { var i Tinter; f = i.M })
+ shouldPanic(func() { _psv = nil; f = _psv.m })
+ shouldPanic(func() { _pwv = nil; f = _pwv.m })
+ shouldPanic(func() { _pbv = nil; f = _pbv.m })
+ shouldPanic(func() { var _i tinter; f = _i.m })
+ shouldPanic(func() { var t1 T1; f = t1.M })
+ shouldPanic(func() { var t2 T2; f = t2.M })
+ shouldPanic(func() { var t3 *T3; f = t3.M })
+ shouldPanic(func() { var t3 T3; f = t3.M })
+
+ if f != nil {
+ panic("something set f")
+ }
+
+ // x.M does not panic if x is a nil pointer and
+ // M is a method with a pointer receiver.
+ shouldNotPanic(func() { psp = nil; f = psp.M })
+ shouldNotPanic(func() { pwp = nil; f = pwp.M })
+ shouldNotPanic(func() { pbp = nil; f = pbp.M })
+ shouldNotPanic(func() { _psp = nil; f = _psp.m })
+ shouldNotPanic(func() { _pwp = nil; f = _pwp.m })
+ shouldNotPanic(func() { _pbp = nil; f = _pbp.m })
+ shouldNotPanic(func() { var t4 T4; f = t4.M })
+ if f == nil {
+ panic("nothing set f")
+ }
+}
diff --git a/test/return.go b/test/return.go
new file mode 100644
index 000000000..dcf32f86f
--- /dev/null
+++ b/test/return.go
@@ -0,0 +1,2889 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test compiler diagnosis of function missing return statements.
+// See issue 65 and golang.org/s/go11return.
+
+package p
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+ print(1)
+ return 2
+}
+
+// goto is okay
+func _() int {
+L:
+ print(1)
+ goto L
+}
+
+// panic is okay
+func _() int {
+ print(1)
+ panic(2)
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+ print(1)
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ print(1)
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+ print(1)
+ return 2
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ print(1)
+ goto L
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+ print(1)
+ for {}
+}
+
+func _() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+func _() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+ print(1)
+ for { break }
+} // ERROR "missing return"
+
+func _() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+ print(1)
+ for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ for true {}
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+ print(1)
+ select{}
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+ print(1)
+ select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+ return 2
+}
+
+// goto is okay
+func _() int {
+L:
+ goto L
+}
+
+// panic is okay
+func _() int {
+ panic(2)
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+ {
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+ {
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+ return 2
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ goto L
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+func _() int {
+L:
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+func _() int {
+L:
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+ for {}
+}
+
+func _() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+func _() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+ for { break }
+} // ERROR "missing return"
+
+func _() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+ for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for true {}
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+ select{}
+}
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+ select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+func _() int {
+ select {
+ case <-c:
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// again, with func literals
+
+var _ = func() int {
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+} // ERROR "missing return"
+
+// return is okay
+var _ = func() int {
+ print(1)
+ return 2
+}
+
+// goto is okay
+var _ = func() int {
+L:
+ print(1)
+ goto L
+}
+
+// panic is okay
+var _ = func() int {
+ print(1)
+ panic(2)
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+var _ = func() int {
+ print(1)
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+var _ = func() int {
+ print(1)
+ return 2
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+var _ = func() int {
+ print(1)
+ for {}
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+var _ = func() int {
+ print(1)
+ for { break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+var _ = func() int {
+ print(1)
+ for x == nil {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ for true {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+var _ = func() int {
+ print(1)
+ select{}
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+var _ = func() int {
+ print(1)
+ select{ default: break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+var _ = func() int {
+} // ERROR "missing return"
+
+// return is okay
+var _ = func() int {
+ return 2
+}
+
+// goto is okay
+var _ = func() int {
+L:
+ goto L
+}
+
+// panic is okay
+var _ = func() int {
+ panic(2)
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ {
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+var _ = func() int {
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+var _ = func() int {
+ return 2
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ goto L
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+var _ = func() int {
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+var _ = func() int {
+L:
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+var _ = func() int {
+L:
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+var _ = func() int {
+ for {}
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+var _ = func() int {
+ for { break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+var _ = func() int {
+ for x == nil {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+var _ = func() int {
+ select{}
+}
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+var _ = func() int {
+ select{ default: break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ select {
+ case <-c:
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ fallthrough
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+/**/
diff --git a/test/shift1.go b/test/shift1.go
index f1ec0bf58..71f7861c6 100644
--- a/test/shift1.go
+++ b/test/shift1.go
@@ -42,4 +42,199 @@ var (
a3 = 1.0<<s + 0 // ERROR "invalid operation|shift of non-integer operand"
// issue 4937
b3 = 1<<s + 1 + 1.0 // ERROR "invalid operation|shift of non-integer operand"
+ // issue 5014
+ c3 = complex(1<<s, 0) // ERROR "shift of type float64"
+ d3 int = complex(1<<s, 3) // ERROR "cannot use.*as type int" "shift of type float64"
+ e3 = real(1 << s) // ERROR "invalid"
+ f3 = imag(1 << s) // ERROR "invalid"
)
+
+// from the spec
+func _() {
+ 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 != i // 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
+ // next test only fails on 32bit systems
+ // p = 1<<s == 1<<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
+ u = 1.0 << s // ERROR "float64"
+ u1 = 1.0<<s != 0 // ERROR "float64"
+ u2 = 1<<s != 1.0 // ERROR "float64"
+ v float32 = 1 << s // ERROR "float32"
+ w int64 = 1.0 << 33 // 1.0<<33 is a constant shift expression
+ )
+}
+
+// shifts in comparisons w/ untyped operands
+var (
+ _ = 1<<s == 1
+ _ = 1<<s == 1. // ERROR "shift of type float64"
+ _ = 1.<<s == 1 // ERROR "shift of type float64"
+ _ = 1.<<s == 1. // ERROR "shift of type float64"
+
+ _ = 1<<s+1 == 1
+ _ = 1<<s+1 == 1. // ERROR "shift of type float64"
+ _ = 1<<s+1. == 1 // ERROR "shift of type float64"
+ _ = 1<<s+1. == 1. // ERROR "shift of type float64"
+ _ = 1.<<s+1 == 1 // ERROR "shift of type float64"
+ _ = 1.<<s+1 == 1. // ERROR "shift of type float64"
+ _ = 1.<<s+1. == 1 // ERROR "shift of type float64"
+ _ = 1.<<s+1. == 1. // ERROR "shift of type float64"
+
+ _ = 1<<s == 1<<s
+ _ = 1<<s == 1.<<s // ERROR "shift of type float64"
+ _ = 1.<<s == 1<<s // ERROR "shift of type float64"
+ _ = 1.<<s == 1.<<s // ERROR "shift of type float64"
+
+ _ = 1<<s+1<<s == 1
+ _ = 1<<s+1<<s == 1. // ERROR "shift of type float64"
+ _ = 1<<s+1.<<s == 1 // ERROR "shift of type float64"
+ _ = 1<<s+1.<<s == 1. // ERROR "shift of type float64"
+ _ = 1.<<s+1<<s == 1 // ERROR "shift of type float64"
+ _ = 1.<<s+1<<s == 1. // ERROR "shift of type float64"
+ _ = 1.<<s+1.<<s == 1 // ERROR "shift of type float64"
+ _ = 1.<<s+1.<<s == 1. // ERROR "shift of type float64"
+
+ _ = 1<<s+1<<s == 1<<s+1<<s
+ _ = 1<<s+1<<s == 1<<s+1.<<s // ERROR "shift of type float64"
+ _ = 1<<s+1<<s == 1.<<s+1<<s // ERROR "shift of type float64"
+ _ = 1<<s+1<<s == 1.<<s+1.<<s // ERROR "shift of type float64"
+ _ = 1<<s+1.<<s == 1<<s+1<<s // ERROR "shift of type float64"
+ _ = 1<<s+1.<<s == 1<<s+1.<<s // ERROR "shift of type float64"
+ _ = 1<<s+1.<<s == 1.<<s+1<<s // ERROR "shift of type float64"
+ _ = 1<<s+1.<<s == 1.<<s+1.<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1<<s == 1<<s+1<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1<<s == 1<<s+1.<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1<<s == 1.<<s+1<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1<<s == 1.<<s+1.<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1.<<s == 1<<s+1<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1.<<s == 1<<s+1.<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1.<<s == 1.<<s+1<<s // ERROR "shift of type float64"
+ _ = 1.<<s+1.<<s == 1.<<s+1.<<s // ERROR "shift of type float64"
+)
+
+// shifts in comparisons w/ typed operands
+var (
+ x int
+ _ = 1<<s == x
+ _ = 1.<<s == x
+ _ = 1.1<<s == x // ERROR "1.1 truncated"
+
+ _ = 1<<s+x == 1
+ _ = 1<<s+x == 1.
+ _ = 1<<s+x == 1.1 // ERROR "1.1 truncated"
+ _ = 1.<<s+x == 1
+ _ = 1.<<s+x == 1.
+ _ = 1.<<s+x == 1.1 // ERROR "1.1 truncated"
+ _ = 1.1<<s+x == 1 // ERROR "1.1 truncated"
+ _ = 1.1<<s+x == 1. // ERROR "1.1 truncated"
+ _ = 1.1<<s+x == 1.1 // ERROR "1.1 truncated"
+
+ _ = 1<<s == x<<s
+ _ = 1.<<s == x<<s
+ _ = 1.1<<s == x<<s // ERROR "1.1 truncated"
+)
+
+// shifts as operands in non-arithmetic operations and as arguments
+func _() {
+ var s uint
+ var a []int
+ _ = a[1<<s]
+ _ = a[1.]
+ // For now, the spec disallows these. We may revisit past Go 1.1.
+ _ = a[1.<<s] // ERROR "shift of type float64"
+ _ = a[1.1<<s] // ERROR "shift of type float64"
+
+ _ = make([]int, 1)
+ _ = make([]int, 1.)
+ _ = make([]int, 1.<<s)
+ _ = make([]int, 1.1<<s) // ERROR "1.1 truncated"
+
+ _ = float32(1)
+ _ = float32(1 << s) // ERROR "shift of type float32"
+ _ = float32(1.)
+ _ = float32(1. << s) // ERROR "shift of type float32"
+ _ = float32(1.1 << s) // ERROR "shift of type float32"
+
+ _ = append(a, 1<<s)
+ _ = append(a, 1.<<s)
+ _ = append(a, 1.1<<s) // ERROR "1.1 truncated"
+
+ var b []float32
+ _ = append(b, 1<<s) // ERROR "type float32"
+ _ = append(b, 1.<<s) // ERROR "type float32"
+ _ = append(b, 1.1<<s) // ERROR "type float32"
+
+ _ = complex(1.<<s, 0) // ERROR "shift of type float64"
+ _ = complex(1.1<<s, 0) // ERROR "shift of type float64"
+ _ = complex(0, 1.<<s) // ERROR "shift of type float64"
+ _ = complex(0, 1.1<<s) // ERROR "shift of type float64"
+
+ var a4 float64
+ var b4 int
+ _ = complex(1<<s, a4) // ERROR "shift of type float64"
+ _ = complex(1<<s, b4) // ERROR "invalid"
+
+ var m1 map[int]string
+ delete(m1, 1<<s)
+ delete(m1, 1.<<s)
+ delete(m1, 1.1<<s) // ERROR "1.1 truncated|shift of type float64"
+
+ var m2 map[float32]string
+ delete(m2, 1<<s) // ERROR "invalid|cannot use 1 << s as type float32"
+ delete(m2, 1.<<s) // ERROR "invalid|cannot use 1 << s as type float32"
+ delete(m2, 1.1<<s) // ERROR "invalid|cannot use 1.1 << s as type float32"
+}
+
+// shifts of shifts
+func _() {
+ var s uint
+ _ = 1 << (1 << s)
+ _ = 1 << (1. << s)
+ _ = 1 << (1.1 << s) // ERROR "1.1 truncated"
+ _ = 1. << (1 << s) // ERROR "shift of type float64"
+ _ = 1. << (1. << s) // ERROR "shift of type float64"
+ _ = 1.1 << (1.1 << s) // ERROR "invalid|1.1 truncated"
+
+ _ = (1 << s) << (1 << s)
+ _ = (1 << s) << (1. << s)
+ _ = (1 << s) << (1.1 << s) // ERROR "1.1 truncated"
+ _ = (1. << s) << (1 << s) // ERROR "shift of type float64"
+ _ = (1. << s) << (1. << s) // ERROR "shift of type float64"
+ _ = (1.1 << s) << (1.1 << s) // ERROR "invalid|1.1 truncated"
+
+ var x int
+ x = 1 << (1 << s)
+ x = 1 << (1. << s)
+ x = 1 << (1.1 << s) // ERROR "1.1 truncated"
+ x = 1. << (1 << s)
+ x = 1. << (1. << s)
+ x = 1.1 << (1.1 << s) // ERROR "1.1 truncated"
+
+ x = (1 << s) << (1 << s)
+ x = (1 << s) << (1. << s)
+ x = (1 << s) << (1.1 << s) // ERROR "1.1 truncated"
+ x = (1. << s) << (1 << s)
+ x = (1. << s) << (1. << s)
+ x = (1.1 << s) << (1.1 << s) // ERROR "1.1 truncated"
+
+ var y float32
+ y = 1 << (1 << s) // ERROR "type float32"
+ y = 1 << (1. << s) // ERROR "type float32"
+ y = 1 << (1.1 << s) // ERROR "invalid|1.1 truncated|float32"
+ y = 1. << (1 << s) // ERROR "type float32"
+ y = 1. << (1. << s) // ERROR "type float32"
+ y = 1.1 << (1.1 << s) // ERROR "invalid|1.1 truncated|float32"
+
+ var z complex128
+ z = (1 << s) << (1 << s) // ERROR "type complex128"
+ z = (1 << s) << (1. << s) // ERROR "type complex128"
+ z = (1 << s) << (1.1 << s) // ERROR "invalid|1.1 truncated|complex128"
+ z = (1. << s) << (1 << s) // ERROR "type complex128"
+ z = (1. << s) << (1. << s) // ERROR "type complex128"
+ z = (1.1 << s) << (1.1 << s) // ERROR "invalid|1.1 truncated|complex128"
+}
diff --git a/test/switch.go b/test/switch.go
index bcbde68e4..5e1d85bb6 100644
--- a/test/switch.go
+++ b/test/switch.go
@@ -392,15 +392,6 @@ func main() {
}
assert(count == 2, "fail")
- // fallthrough in final case.
- count = 0
- switch i5 {
- case 5:
- count++
- fallthrough
- }
- assert(count == 1, "fail")
-
i := 0
switch x := 5; {
case i < x:
diff --git a/test/switch4.go b/test/switch4.go
new file mode 100644
index 000000000..f38efe68c
--- /dev/null
+++ b/test/switch4.go
@@ -0,0 +1,36 @@
+// errorcheck
+
+// 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.
+
+// Verify that erroneous switch statements are detected by the compiler.
+// Does not compile.
+
+package main
+
+type I interface {
+ M()
+}
+
+func bad() {
+
+ i5 := 5
+ switch i5 {
+ case 5:
+ fallthrough // ERROR "cannot fallthrough final case in switch"
+ }
+}
+
+func good() {
+ var i interface{}
+ var s string
+
+ switch i {
+ case s:
+ }
+
+ switch s {
+ case i:
+ }
+}