From be47d6eceffd2c5dbbc1566d5eea490527fb2bd4 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 16 Jul 2013 06:54:42 +0000 Subject: [PATCH] libgo: Update to Go 1.1.1. From-SVN: r200974 --- libgo/MERGE | 2 +- libgo/Makefile.am | 340 +- libgo/Makefile.in | 506 +- libgo/go/archive/tar/common.go | 149 +- libgo/go/archive/tar/reader.go | 193 +- libgo/go/archive/tar/reader_test.go | 106 +- libgo/go/archive/tar/tar_test.go | 175 +- libgo/go/archive/tar/testdata/pax.tar | Bin 0 -> 10240 bytes libgo/go/archive/tar/testdata/ustar.tar | Bin 0 -> 2048 bytes libgo/go/archive/tar/writer.go | 118 +- libgo/go/archive/tar/writer_test.go | 80 + libgo/go/archive/zip/reader.go | 7 +- libgo/go/archive/zip/reader_test.go | 20 +- libgo/go/archive/zip/struct.go | 9 +- .../zip/testdata/test-trailing-junk.zip | Bin 0 -> 1184 bytes libgo/go/archive/zip/writer.go | 3 + libgo/go/bufio/bufio.go | 5 +- libgo/go/bufio/bufio_test.go | 49 +- libgo/go/bufio/example_test.go | 74 + libgo/go/bufio/export_test.go | 27 + libgo/go/bufio/scan.go | 346 + libgo/go/bufio/scan_test.go | 406 + libgo/go/builtin/builtin.go | 17 + libgo/go/bytes/buffer.go | 56 +- libgo/go/bytes/buffer_test.go | 50 + libgo/go/bytes/bytes.go | 31 +- libgo/go/bytes/bytes_decl.go | 8 + libgo/go/bytes/bytes_test.go | 105 +- libgo/go/bytes/equal_test.go | 47 + libgo/go/bytes/example_test.go | 17 + libgo/go/bytes/export_test.go | 4 + libgo/go/compress/bzip2/huffman.go | 2 - libgo/go/compress/flate/deflate_test.go | 1 - libgo/go/compress/flate/inflate.go | 3 - libgo/go/compress/flate/token.go | 1 - libgo/go/compress/gzip/gunzip.go | 1 - libgo/go/compress/gzip/gzip.go | 24 +- libgo/go/compress/gzip/gzip_test.go | 40 + libgo/go/compress/lzw/reader.go | 2 - libgo/go/container/heap/example_test.go | 100 - libgo/go/container/heap/heap.go | 6 +- libgo/go/container/heap/heap_test.go | 3 +- libgo/go/crypto/cipher/cbc.go | 12 + libgo/go/crypto/cipher/cipher_test.go | 36 + libgo/go/crypto/cipher/example_test.go | 4 +- libgo/go/crypto/dsa/dsa.go | 2 - libgo/go/crypto/dsa/dsa_test.go | 5 +- libgo/go/crypto/ecdsa/ecdsa.go | 2 +- libgo/go/crypto/md5/gen.go | 19 +- libgo/go/crypto/md5/md5_test.go | 9 +- libgo/go/crypto/md5/md5block.go | 5 + libgo/go/crypto/md5/md5block_decl.go | 9 + libgo/go/crypto/rand/util.go | 9 +- libgo/go/crypto/rc4/rc4.go | 17 +- libgo/go/crypto/rc4/rc4_asm.go | 18 + libgo/go/crypto/rc4/rc4_ref.go | 20 + libgo/go/crypto/rc4/rc4_test.go | 127 +- libgo/go/crypto/rsa/rsa.go | 23 +- libgo/go/crypto/rsa/rsa_test.go | 29 +- libgo/go/crypto/sha1/sha1_test.go | 9 +- libgo/go/crypto/sha1/sha1block.go | 2 + libgo/go/crypto/sha1/sha1block_decl.go | 9 + libgo/go/crypto/tls/common.go | 19 +- libgo/go/crypto/tls/generate_cert.go | 60 +- libgo/go/crypto/tls/handshake_server.go | 17 +- libgo/go/crypto/x509/pkcs8.go | 2 - libgo/go/crypto/x509/verify.go | 49 +- libgo/go/crypto/x509/verify_test.go | 100 + libgo/go/crypto/x509/x509.go | 63 +- libgo/go/crypto/x509/x509_test.go | 63 +- libgo/go/database/sql/convert.go | 87 +- libgo/go/database/sql/convert_test.go | 33 +- libgo/go/database/sql/driver/driver.go | 36 +- libgo/go/database/sql/fakedb_test.go | 73 +- libgo/go/database/sql/sql.go | 793 +- libgo/go/database/sql/sql_test.go | 485 +- libgo/go/debug/dwarf/buf.go | 66 +- libgo/go/debug/dwarf/entry.go | 27 +- libgo/go/debug/dwarf/line.go | 2 +- libgo/go/debug/dwarf/type.go | 4 +- libgo/go/debug/dwarf/unit.go | 48 +- libgo/go/debug/elf/file.go | 18 +- libgo/go/debug/gosym/symtab.go | 123 +- libgo/go/debug/macho/file.go | 2 + libgo/go/encoding/ascii85/ascii85.go | 1 - libgo/go/encoding/asn1/marshal.go | 1 - libgo/go/encoding/base32/base32.go | 87 +- libgo/go/encoding/base32/base32_test.go | 106 +- libgo/go/encoding/base64/base64.go | 63 +- libgo/go/encoding/base64/base64_test.go | 72 +- libgo/go/encoding/binary/binary.go | 57 +- libgo/go/encoding/binary/binary_test.go | 9 +- libgo/go/encoding/binary/varint.go | 1 - libgo/go/encoding/csv/reader.go | 3 - libgo/go/encoding/gob/codec_test.go | 6 +- libgo/go/encoding/gob/decode.go | 1 - libgo/go/encoding/gob/gobencdec_test.go | 4 +- libgo/go/encoding/gob/timing_test.go | 46 +- libgo/go/encoding/gob/type.go | 1 - libgo/go/encoding/json/decode.go | 30 +- libgo/go/encoding/json/decode_test.go | 86 +- libgo/go/encoding/json/encode.go | 98 +- libgo/go/encoding/json/encode_test.go | 104 + libgo/go/encoding/json/scanner_test.go | 3 - libgo/go/encoding/xml/marshal.go | 120 +- libgo/go/encoding/xml/marshal_test.go | 80 +- libgo/go/encoding/xml/read.go | 6 +- libgo/go/encoding/xml/read_test.go | 222 + libgo/go/encoding/xml/typeinfo.go | 41 +- libgo/go/encoding/xml/xml.go | 54 +- libgo/go/encoding/xml/xml_test.go | 43 +- libgo/go/exp/cookiejar/jar.go | 89 - libgo/go/exp/cookiejar/storage.go | 101 - libgo/go/exp/cookiejar/storage_test.go | 48 - libgo/go/exp/ebnf/ebnf.go | 269 - libgo/go/exp/ebnf/ebnf_test.go | 71 - libgo/go/exp/ebnf/parser.go | 190 - libgo/go/exp/ebnflint/doc.go | 22 - libgo/go/exp/ebnflint/ebnflint.go | 122 - libgo/go/exp/ebnflint/ebnflint_test.go | 16 - libgo/go/exp/gotype/doc.go | 63 - libgo/go/exp/gotype/gotype.go | 184 - libgo/go/exp/gotype/gotype_test.go | 215 - libgo/go/exp/gotype/testdata/test1.go | 27 - libgo/go/exp/html/atom/atom.go | 81 - libgo/go/exp/html/atom/atom_test.go | 109 - libgo/go/exp/html/atom/gen.go | 636 - libgo/go/exp/html/atom/table.go | 694 - libgo/go/exp/html/atom/table_test.go | 341 - libgo/go/exp/html/const.go | 100 - libgo/go/exp/html/doc.go | 106 - libgo/go/exp/html/doctype.go | 156 - libgo/go/exp/html/entity.go | 2253 - libgo/go/exp/html/entity_test.go | 29 - libgo/go/exp/html/escape.go | 258 - libgo/go/exp/html/foreign.go | 226 - libgo/go/exp/html/node.go | 193 - libgo/go/exp/html/node_test.go | 146 - libgo/go/exp/html/parse.go | 2091 - libgo/go/exp/html/parse_test.go | 390 - libgo/go/exp/html/render.go | 271 - libgo/go/exp/html/render_test.go | 156 - libgo/go/exp/html/testdata/go1.html | 2237 - libgo/go/exp/html/testdata/webkit/README | 28 - .../exp/html/testdata/webkit/adoption01.dat | 194 - .../exp/html/testdata/webkit/adoption02.dat | 31 - .../exp/html/testdata/webkit/comments01.dat | 135 - .../go/exp/html/testdata/webkit/doctype01.dat | 370 - .../exp/html/testdata/webkit/entities01.dat | 603 - .../exp/html/testdata/webkit/entities02.dat | 249 - .../html/testdata/webkit/html5test-com.dat | 246 - .../go/exp/html/testdata/webkit/inbody01.dat | 43 - libgo/go/exp/html/testdata/webkit/isindex.dat | 40 - .../testdata/webkit/pending-spec-changes.dat | 52 - .../exp/html/testdata/webkit/scriptdata01.dat | 308 - .../testdata/webkit/scripted/adoption01.dat | 15 - .../testdata/webkit/scripted/webkit01.dat | 28 - .../go/exp/html/testdata/webkit/tables01.dat | 212 - libgo/go/exp/html/testdata/webkit/tests1.dat | 1952 - libgo/go/exp/html/testdata/webkit/tests10.dat | 799 - libgo/go/exp/html/testdata/webkit/tests11.dat | 482 - libgo/go/exp/html/testdata/webkit/tests12.dat | 62 - libgo/go/exp/html/testdata/webkit/tests14.dat | 74 - libgo/go/exp/html/testdata/webkit/tests15.dat | 208 - libgo/go/exp/html/testdata/webkit/tests16.dat | 2299 - libgo/go/exp/html/testdata/webkit/tests17.dat | 153 - libgo/go/exp/html/testdata/webkit/tests18.dat | 269 - libgo/go/exp/html/testdata/webkit/tests19.dat | 1237 - libgo/go/exp/html/testdata/webkit/tests2.dat | 763 - libgo/go/exp/html/testdata/webkit/tests20.dat | 455 - libgo/go/exp/html/testdata/webkit/tests21.dat | 221 - libgo/go/exp/html/testdata/webkit/tests22.dat | 157 - libgo/go/exp/html/testdata/webkit/tests23.dat | 155 - libgo/go/exp/html/testdata/webkit/tests24.dat | 79 - libgo/go/exp/html/testdata/webkit/tests25.dat | 219 - libgo/go/exp/html/testdata/webkit/tests26.dat | 313 - libgo/go/exp/html/testdata/webkit/tests3.dat | 305 - libgo/go/exp/html/testdata/webkit/tests4.dat | 59 - libgo/go/exp/html/testdata/webkit/tests5.dat | 191 - libgo/go/exp/html/testdata/webkit/tests6.dat | 663 - libgo/go/exp/html/testdata/webkit/tests7.dat | 390 - libgo/go/exp/html/testdata/webkit/tests8.dat | 148 - libgo/go/exp/html/testdata/webkit/tests9.dat | 457 - .../testdata/webkit/tests_innerHTML_1.dat | 741 - .../go/exp/html/testdata/webkit/tricky01.dat | 261 - .../go/exp/html/testdata/webkit/webkit01.dat | 610 - .../go/exp/html/testdata/webkit/webkit02.dat | 159 - libgo/go/exp/html/token.go | 1173 - libgo/go/exp/html/token_test.go | 679 - libgo/go/exp/inotify/inotify_linux.go | 289 - libgo/go/exp/inotify/inotify_linux_test.go | 106 - libgo/go/exp/locale/collate/build/builder.go | 688 - .../exp/locale/collate/build/builder_test.go | 290 - libgo/go/exp/locale/collate/build/colelem.go | 365 - .../exp/locale/collate/build/colelem_test.go | 214 - libgo/go/exp/locale/collate/build/contract.go | 307 - .../exp/locale/collate/build/contract_test.go | 264 - libgo/go/exp/locale/collate/build/order.go | 392 - .../go/exp/locale/collate/build/order_test.go | 228 - libgo/go/exp/locale/collate/build/table.go | 120 - libgo/go/exp/locale/collate/build/trie.go | 290 - .../go/exp/locale/collate/build/trie_test.go | 107 - libgo/go/exp/locale/collate/colelem.go | 317 - libgo/go/exp/locale/collate/colelem_test.go | 274 - libgo/go/exp/locale/collate/collate.go | 586 - libgo/go/exp/locale/collate/colltab.go | 28 - libgo/go/exp/locale/collate/contract.go | 145 - libgo/go/exp/locale/collate/contract_test.go | 132 - libgo/go/exp/locale/collate/export.go | 36 - libgo/go/exp/locale/collate/export_test.go | 90 - libgo/go/exp/locale/collate/maketables.go | 722 - libgo/go/exp/locale/collate/regtest.go | 268 - libgo/go/exp/locale/collate/sort.go | 90 - libgo/go/exp/locale/collate/sort_test.go | 52 - libgo/go/exp/locale/collate/table.go | 317 - libgo/go/exp/locale/collate/tables.go | 51896 ---------------- .../exp/locale/collate/tools/colcmp/chars.go | 937 - .../go/exp/locale/collate/tools/colcmp/col.go | 95 - .../exp/locale/collate/tools/colcmp/colcmp.go | 528 - .../exp/locale/collate/tools/colcmp/darwin.go | 111 - .../go/exp/locale/collate/tools/colcmp/gen.go | 179 - .../go/exp/locale/collate/tools/colcmp/icu.go | 209 - libgo/go/exp/locale/collate/trie.go | 160 - libgo/go/exp/locale/collate/trie_test.go | 106 - libgo/go/exp/norm/composition.go | 382 - libgo/go/exp/norm/composition_test.go | 143 - libgo/go/exp/norm/example_iter_test.go | 81 - libgo/go/exp/norm/forminfo.go | 229 - libgo/go/exp/norm/input.go | 105 - libgo/go/exp/norm/iter.go | 401 - libgo/go/exp/norm/iter_test.go | 188 - libgo/go/exp/norm/maketables.go | 934 - libgo/go/exp/norm/maketesttables.go | 45 - libgo/go/exp/norm/norm_test.go | 14 - libgo/go/exp/norm/normalize.go | 478 - libgo/go/exp/norm/normalize_test.go | 750 - libgo/go/exp/norm/normregtest.go | 308 - libgo/go/exp/norm/readwriter.go | 126 - libgo/go/exp/norm/readwriter_test.go | 68 - libgo/go/exp/norm/tables.go | 6779 -- libgo/go/exp/norm/trie.go | 232 - libgo/go/exp/norm/trie_test.go | 152 - libgo/go/exp/norm/triedata_test.go | 85 - libgo/go/exp/norm/triegen.go | 317 - libgo/go/exp/ssa/blockopt.go | 186 - libgo/go/exp/ssa/doc.go | 113 - libgo/go/exp/ssa/func.go | 428 - libgo/go/exp/ssa/literal.go | 137 - libgo/go/exp/ssa/print.go | 383 - libgo/go/exp/ssa/sanity.go | 263 - libgo/go/exp/ssa/ssa.go | 1100 - libgo/go/exp/ssa/util.go | 172 - libgo/go/exp/utf8string/string.go | 203 - libgo/go/exp/utf8string/string_test.go | 123 - libgo/go/exp/winfsnotify/winfsnotify.go | 572 - libgo/go/exp/winfsnotify/winfsnotify_test.go | 130 - libgo/go/fmt/doc.go | 13 +- libgo/go/fmt/fmt_test.go | 39 +- libgo/go/fmt/print.go | 47 +- libgo/go/go/ast/filter.go | 25 +- libgo/go/go/ast/filter_test.go | 86 + libgo/go/go/ast/print.go | 2 +- libgo/go/go/build/build.go | 148 +- libgo/go/go/build/deps_test.go | 11 +- libgo/go/go/build/doc.go | 16 +- libgo/go/go/doc/doc.go | 18 +- libgo/go/go/doc/example.go | 12 + libgo/go/go/doc/example_test.go | 80 + libgo/go/go/doc/filter.go | 2 +- libgo/go/go/doc/reader.go | 87 +- libgo/go/go/doc/testdata/a.0.golden | 23 +- libgo/go/go/doc/testdata/a.1.golden | 23 +- libgo/go/go/doc/testdata/a.2.golden | 23 +- libgo/go/go/doc/testdata/a0.go | 32 + libgo/go/go/doc/testdata/a1.go | 4 + libgo/go/go/doc/testdata/template.txt | 7 +- libgo/go/go/format/format.go | 9 +- libgo/go/go/parser/error_test.go | 5 +- libgo/go/go/parser/interface.go | 82 +- libgo/go/go/parser/parser.go | 85 +- libgo/go/go/parser/parser_test.go | 13 +- libgo/go/go/parser/short_test.go | 3 + libgo/go/go/printer/nodes.go | 4 +- libgo/go/go/printer/printer.go | 35 +- .../go/printer/testdata/declarations.golden | 25 + .../go/go/printer/testdata/declarations.input | 25 + libgo/go/go/scanner/scanner.go | 13 +- libgo/go/go/scanner/scanner_test.go | 5 +- libgo/go/go/token/token.go | 4 +- libgo/go/go/types/api.go | 96 - libgo/go/go/types/builtins.go | 457 - libgo/go/go/types/check.go | 454 - libgo/go/go/types/check_test.go | 262 - libgo/go/go/types/const.go | 734 - libgo/go/go/types/conversions.go | 128 - libgo/go/go/types/errors.go | 331 - libgo/go/go/types/exportdata.go | 111 - libgo/go/go/types/expr.go | 1334 - libgo/go/go/types/gcimporter.go | 908 - libgo/go/go/types/gcimporter_test.go | 180 - libgo/go/go/types/objects.go | 155 - libgo/go/go/types/operand.go | 393 - libgo/go/go/types/predicates.go | 303 - libgo/go/go/types/resolve.go | 177 - libgo/go/go/types/resolver_test.go | 171 - libgo/go/go/types/scope.go | 59 - libgo/go/go/types/stmt.go | 721 - libgo/go/go/types/testdata/exports.go | 89 - libgo/go/go/types/types.go | 232 - libgo/go/go/types/types_test.go | 171 - libgo/go/go/types/universe.go | 137 - libgo/go/html/template/doc.go | 2 +- libgo/go/html/template/template.go | 22 +- libgo/go/html/template/transition.go | 3 - libgo/go/image/gif/reader.go | 103 +- libgo/go/image/gif/reader_test.go | 138 + libgo/go/image/jpeg/reader.go | 32 +- libgo/go/image/jpeg/reader_test.go | 63 + libgo/go/image/jpeg/scan.go | 8 +- libgo/go/image/jpeg/writer_test.go | 39 +- libgo/go/image/png/reader.go | 5 +- libgo/go/image/png/reader_test.go | 59 +- libgo/go/image/png/writer.go | 2 +- libgo/go/io/io.go | 71 +- libgo/go/io/io_test.go | 44 +- libgo/go/io/ioutil/ioutil.go | 1 - libgo/go/io/ioutil/ioutil_test.go | 3 +- libgo/go/io/ioutil/tempfile_test.go | 3 +- libgo/go/log/syslog/syslog.go | 142 +- libgo/go/log/syslog/syslog_test.go | 269 +- libgo/go/log/syslog/syslog_unix.go | 8 +- libgo/go/math/big/int.go | 16 +- libgo/go/math/big/nat.go | 2 - libgo/go/math/big/rat.go | 14 +- libgo/go/math/big/rat_test.go | 45 +- libgo/go/math/hypot.go | 6 +- libgo/go/math/rand/exp.go | 1 - libgo/go/math/rand/normal.go | 1 - libgo/go/math/rand/zipf.go | 6 +- libgo/go/math/sqrt.go | 8 - libgo/go/math/tanh.go | 2 +- libgo/go/mime/multipart/multipart.go | 10 +- libgo/go/mime/multipart/quotedprintable.go | 40 +- .../go/mime/multipart/quotedprintable_test.go | 154 +- libgo/go/mime/type_unix.go | 15 +- libgo/go/mime/type_windows.go | 1 - libgo/go/net/conn_test.go | 72 +- libgo/go/net/dial.go | 237 +- libgo/go/net/dial_gen.go | 73 + libgo/go/net/dial_test.go | 111 +- libgo/go/net/fd_bsd.go | 4 + libgo/go/net/fd_linux.go | 188 - libgo/go/net/fd_plan9.go | 54 +- libgo/go/net/fd_poll_runtime.go | 119 + libgo/go/net/fd_poll_unix.go | 360 + libgo/go/net/fd_unix.go | 391 +- libgo/go/net/fd_unix_test.go | 48 - libgo/go/net/fd_windows.go | 50 +- libgo/go/net/file_plan9.go | 127 +- libgo/go/net/file_test.go | 2 +- libgo/go/net/file_windows.go | 12 + libgo/go/net/http/cgi/host_test.go | 7 +- libgo/go/net/http/cgi/posix_test.go | 21 + libgo/go/net/http/cgi/testdata/test.cgi | 3 +- libgo/go/net/http/client.go | 12 +- libgo/go/net/http/client_test.go | 30 +- libgo/go/net/http/cookiejar/jar.go | 497 + libgo/go/net/http/cookiejar/jar_test.go | 1267 + libgo/go/net/http/cookiejar/punycode.go | 159 + libgo/go/net/http/cookiejar/punycode_test.go | 161 + libgo/go/net/http/example_test.go | 16 +- libgo/go/net/http/export_test.go | 16 +- libgo/go/net/http/fcgi/child.go | 41 +- libgo/go/net/http/filetransport_test.go | 10 +- libgo/go/net/http/fs_test.go | 18 +- libgo/go/net/http/header.go | 47 +- libgo/go/net/http/header_test.go | 49 +- libgo/go/net/http/httptest/server.go | 56 +- libgo/go/net/http/httputil/dump_test.go | 4 +- libgo/go/net/http/httputil/reverseproxy.go | 37 +- .../go/net/http/httputil/reverseproxy_test.go | 4 + libgo/go/net/http/jar.go | 2 + libgo/go/net/http/npn_test.go | 118 + libgo/go/net/http/pprof/pprof.go | 2 +- libgo/go/net/http/request.go | 46 +- libgo/go/net/http/request_test.go | 114 +- libgo/go/net/http/requestwrite_test.go | 117 +- libgo/go/net/http/response.go | 7 +- libgo/go/net/http/response_test.go | 65 +- libgo/go/net/http/serve_test.go | 582 +- libgo/go/net/http/server.go | 449 +- libgo/go/net/http/server_test.go | 35 +- libgo/go/net/http/sniff_test.go | 11 +- libgo/go/net/http/status.go | 12 + libgo/go/net/http/transfer.go | 63 +- libgo/go/net/http/transport.go | 279 +- libgo/go/net/http/transport_test.go | 410 +- libgo/go/net/http/z_last_test.go | 98 + libgo/go/net/interface.go | 16 +- libgo/go/net/interface_bsd.go | 97 +- libgo/go/net/interface_darwin.go | 36 +- libgo/go/net/interface_freebsd.go | 36 +- libgo/go/net/interface_linux.go | 95 +- libgo/go/net/interface_netbsd.go | 10 +- libgo/go/net/interface_openbsd.go | 10 +- libgo/go/net/interface_stub.go | 17 +- libgo/go/net/interface_test.go | 128 +- libgo/go/net/interface_windows.go | 28 +- libgo/go/net/ip.go | 95 +- libgo/go/net/ip_test.go | 137 +- libgo/go/net/ipraw_test.go | 403 +- libgo/go/net/iprawsock.go | 13 +- libgo/go/net/iprawsock_plan9.go | 6 +- libgo/go/net/iprawsock_posix.go | 36 +- libgo/go/net/ipsock.go | 114 +- libgo/go/net/ipsock_plan9.go | 62 +- libgo/go/net/lookup_plan9.go | 22 +- libgo/go/net/lookup_windows.go | 111 +- libgo/go/net/multicast_posix_test.go | 180 - libgo/go/net/multicast_test.go | 184 + libgo/go/net/net.go | 18 +- libgo/go/net/net_test.go | 4 + libgo/go/net/newpollserver_unix.go | 46 - libgo/go/net/packetconn_test.go | 124 +- libgo/go/net/port_test.go | 2 +- libgo/go/net/protoconn_test.go | 327 +- libgo/go/net/rpc/client.go | 12 +- libgo/go/net/rpc/jsonrpc/all_test.go | 17 + libgo/go/net/rpc/jsonrpc/client.go | 2 +- libgo/go/net/rpc/server_test.go | 43 +- libgo/go/net/sendfile_freebsd.go | 2 +- libgo/go/net/sendfile_linux.go | 2 +- libgo/go/net/server_test.go | 69 +- libgo/go/net/smtp/auth.go | 11 +- libgo/go/net/smtp/smtp_test.go | 35 + libgo/go/net/sock_bsd.go | 37 +- libgo/go/net/sock_cloexec.go | 10 +- libgo/go/net/sock_linux.go | 37 +- libgo/go/net/sock_posix.go | 26 +- libgo/go/net/sock_unix.go | 36 + libgo/go/net/sock_windows.go | 19 +- libgo/go/net/sockopt_posix.go | 19 - libgo/go/net/sockopt_windows.go | 19 + libgo/go/net/sys_cloexec.go | 6 +- libgo/go/net/tcp_test.go | 150 +- libgo/go/net/tcpsock.go | 16 +- libgo/go/net/tcpsock_plan9.go | 20 +- libgo/go/net/tcpsock_posix.go | 67 +- libgo/go/net/textproto/reader.go | 15 +- libgo/go/net/textproto/reader_test.go | 2 + libgo/go/net/textproto/textproto.go | 5 + libgo/go/net/timeout_test.go | 75 +- libgo/go/net/udp_test.go | 139 +- libgo/go/net/udpsock.go | 16 +- libgo/go/net/udpsock_plan9.go | 40 +- libgo/go/net/udpsock_posix.go | 45 +- libgo/go/net/unicast_posix_test.go | 65 +- libgo/go/net/unix_test.go | 246 + libgo/go/net/unixsock.go | 11 +- libgo/go/net/unixsock_plan9.go | 15 +- libgo/go/net/unixsock_posix.go | 55 +- libgo/go/net/url/url.go | 139 +- libgo/go/net/url/url_test.go | 217 +- libgo/go/old/netchan/common.go | 338 - libgo/go/old/netchan/export.go | 400 - libgo/go/old/netchan/import.go | 287 - libgo/go/old/netchan/netchan_test.go | 447 - libgo/go/os/doc.go | 2 + libgo/go/os/env_unix_test.go | 30 + libgo/go/os/exec/exec.go | 2 + libgo/go/os/exec/exec_test.go | 206 +- libgo/go/os/exec/lp_plan9.go | 3 +- libgo/go/os/exec/lp_unix.go | 3 + libgo/go/os/exec/lp_unix_test.go | 55 + libgo/go/os/exec/lp_windows.go | 35 +- libgo/go/os/exec_posix.go | 4 +- libgo/go/os/file_plan9.go | 14 +- libgo/go/os/file_posix.go | 2 - libgo/go/os/file_unix.go | 1 - libgo/go/os/getwd.go | 25 +- libgo/go/os/os_test.go | 1 - libgo/go/os/signal/signal.go | 93 +- libgo/go/os/signal/signal_stub.go | 8 +- libgo/go/os/signal/signal_test.go | 117 +- libgo/go/os/signal/signal_unix.go | 25 +- libgo/go/os/stat.go | 6 +- libgo/go/os/stat_atim.go | 6 +- libgo/go/os/stat_atimespec.go | 6 +- libgo/go/os/stat_plan9.go | 6 +- libgo/go/os/stat_solaris.go | 6 +- libgo/go/os/types.go | 19 +- libgo/go/os/types_notwin.go | 25 + libgo/go/os/types_windows.go | 104 + libgo/go/path/filepath/example_unix_test.go | 39 + libgo/go/path/filepath/match_test.go | 3 +- libgo/go/path/filepath/path.go | 9 +- libgo/go/path/filepath/path_plan9.go | 7 + libgo/go/path/filepath/path_test.go | 57 +- libgo/go/path/filepath/path_unix.go | 7 + libgo/go/path/filepath/path_windows.go | 33 + libgo/go/path/path_test.go | 27 +- libgo/go/reflect/all_test.go | 536 +- libgo/go/reflect/deepequal.go | 2 - libgo/go/reflect/makefunc.go | 66 +- libgo/go/reflect/set_test.go | 6 +- libgo/go/reflect/tostring_test.go | 1 - libgo/go/reflect/type.go | 111 +- libgo/go/reflect/value.go | 196 +- libgo/go/regexp/exec_test.go | 31 +- libgo/go/regexp/regexp.go | 26 +- libgo/go/regexp/syntax/doc.go | 6 +- libgo/go/runtime/append_test.go | 71 + libgo/go/runtime/crash_cgo_test.go | 77 +- libgo/go/runtime/crash_test.go | 158 +- libgo/go/runtime/debug/garbage.go | 101 + libgo/go/runtime/debug/garbage_test.go | 102 + libgo/go/runtime/export_test.go | 6 + libgo/go/runtime/extern.go | 52 +- libgo/go/runtime/gc_test.go | 104 +- libgo/go/runtime/map_test.go | 380 + libgo/go/runtime/mapspeed_test.go | 208 + libgo/go/runtime/pprof/pprof.go | 18 +- libgo/go/runtime/proc_test.go | 171 +- libgo/go/runtime/string_test.go | 32 + libgo/go/sort/example_keys_test.go | 96 + libgo/go/sort/example_multi_test.go | 132 + libgo/go/sort/example_reverse_test.go | 30 - libgo/go/sort/example_test.go | 7 + libgo/go/sort/search_test.go | 27 + libgo/go/sort/sort.go | 66 +- libgo/go/sort/sort_test.go | 41 +- libgo/go/strconv/atof_test.go | 1 + libgo/go/strconv/atoi.go | 2 +- libgo/go/strconv/atoi_test.go | 24 + libgo/go/strconv/extfloat.go | 1 - libgo/go/strconv/fp_test.go | 19 +- libgo/go/strconv/quote.go | 5 +- libgo/go/strconv/strconv_test.go | 24 +- libgo/go/strings/example_test.go | 16 + libgo/go/strings/strings.go | 126 +- libgo/go/strings/strings_test.go | 95 +- libgo/go/sync/atomic/atomic_test.go | 32 +- libgo/go/sync/atomic/race.go | 15 + libgo/go/sync/cond.go | 3 + libgo/go/sync/example_test.go | 6 +- libgo/go/sync/mutex.go | 1 + libgo/go/sync/rwmutex.go | 4 + libgo/go/sync/waitgroup.go | 9 +- libgo/go/syscall/dir_plan9.go | 8 +- libgo/go/syscall/env_plan9.go | 20 +- libgo/go/syscall/env_unix.go | 10 + libgo/go/syscall/exec_bsd.go | 14 +- libgo/go/syscall/exec_linux.go | 10 +- libgo/go/syscall/passfd_test.go | 54 +- libgo/go/syscall/route_bsd.go | 41 +- libgo/go/syscall/route_darwin.go | 34 +- libgo/go/syscall/route_freebsd.go | 45 +- libgo/go/syscall/route_netbsd.go | 32 +- libgo/go/syscall/route_openbsd.go | 32 +- libgo/go/syscall/security_windows.go | 2 +- libgo/go/syscall/sockcmsg_unix.go | 18 +- libgo/go/syscall/socket.go | 11 +- libgo/go/testing/allocs.go | 41 + libgo/go/testing/iotest/reader.go | 8 +- libgo/go/testing/quick/quick.go | 2 - libgo/go/testing/testing.go | 119 +- libgo/go/text/template/exec.go | 20 +- libgo/go/text/template/exec_test.go | 64 +- libgo/go/text/template/funcs.go | 2 +- libgo/go/text/template/parse/parse.go | 2 - libgo/go/time/example_test.go | 43 +- libgo/go/time/format.go | 98 +- libgo/go/time/sleep.go | 25 +- libgo/go/time/sleep_test.go | 25 +- libgo/go/time/time_test.go | 76 +- libgo/go/time/zoneinfo.go | 25 +- libgo/go/time/zoneinfo_read.go | 6 + libgo/go/unicode/letter.go | 2 +- libgo/go/unicode/tables.go | 2 +- libgo/go/unicode/utf8/utf8_test.go | 6 +- libgo/merge.sh | 4 +- libgo/runtime/chan.c | 74 +- libgo/runtime/cpuprof.c | 6 +- libgo/runtime/go-main.c | 11 +- libgo/runtime/go-map-index.c | 2 +- libgo/runtime/go-reflect-map.c | 9 + libgo/runtime/go-signal.c | 108 +- libgo/runtime/go-unsafe-new.c | 11 +- libgo/runtime/go-unsafe-newarray.c | 18 +- libgo/runtime/lock_futex.c | 28 +- libgo/runtime/lock_sema.c | 34 +- libgo/runtime/malloc.goc | 114 +- libgo/runtime/malloc.h | 30 +- libgo/runtime/mcache.c | 4 +- libgo/runtime/mcentral.c | 8 +- libgo/runtime/mem.c | 8 +- libgo/runtime/mfixalloc.c | 5 + libgo/runtime/mgc0.c | 853 +- libgo/runtime/mgc0.h | 7 +- libgo/runtime/mheap.c | 104 +- libgo/runtime/mprof.goc | 91 +- libgo/runtime/netpoll.goc | 356 + libgo/runtime/netpoll_epoll.c | 154 + libgo/runtime/netpoll_kqueue.c | 108 + libgo/runtime/netpoll_stub.c | 18 + libgo/runtime/panic.c | 12 +- libgo/runtime/parfor.c | 8 +- libgo/runtime/print.c | 9 + libgo/runtime/proc.c | 2696 +- libgo/runtime/race.h | 8 +- libgo/runtime/runtime.c | 81 +- libgo/runtime/runtime.h | 255 +- libgo/runtime/sema.goc | 6 +- libgo/runtime/signal_unix.c | 103 +- libgo/runtime/signal_unix.h | 22 + libgo/runtime/sigqueue.goc | 20 +- libgo/runtime/string.goc | 1 + libgo/runtime/thread-linux.c | 46 + libgo/runtime/thread.c | 21 - libgo/runtime/time.goc | 21 +- 620 files changed, 23912 insertions(+), 122673 deletions(-) create mode 100644 libgo/go/archive/tar/testdata/pax.tar create mode 100644 libgo/go/archive/tar/testdata/ustar.tar create mode 100644 libgo/go/archive/zip/testdata/test-trailing-junk.zip create mode 100644 libgo/go/bufio/example_test.go create mode 100644 libgo/go/bufio/export_test.go create mode 100644 libgo/go/bufio/scan.go create mode 100644 libgo/go/bufio/scan_test.go create mode 100644 libgo/go/bytes/equal_test.go delete mode 100644 libgo/go/container/heap/example_test.go create mode 100644 libgo/go/crypto/cipher/cipher_test.go create mode 100644 libgo/go/crypto/md5/md5block_decl.go create mode 100644 libgo/go/crypto/rc4/rc4_asm.go create mode 100644 libgo/go/crypto/rc4/rc4_ref.go create mode 100644 libgo/go/crypto/sha1/sha1block_decl.go delete mode 100644 libgo/go/exp/cookiejar/jar.go delete mode 100644 libgo/go/exp/cookiejar/storage.go delete mode 100644 libgo/go/exp/cookiejar/storage_test.go delete mode 100644 libgo/go/exp/ebnf/ebnf.go delete mode 100644 libgo/go/exp/ebnf/ebnf_test.go delete mode 100644 libgo/go/exp/ebnf/parser.go delete mode 100644 libgo/go/exp/ebnflint/doc.go delete mode 100644 libgo/go/exp/ebnflint/ebnflint.go delete mode 100644 libgo/go/exp/ebnflint/ebnflint_test.go delete mode 100644 libgo/go/exp/gotype/doc.go delete mode 100644 libgo/go/exp/gotype/gotype.go delete mode 100644 libgo/go/exp/gotype/gotype_test.go delete mode 100644 libgo/go/exp/gotype/testdata/test1.go delete mode 100644 libgo/go/exp/html/atom/atom.go delete mode 100644 libgo/go/exp/html/atom/atom_test.go delete mode 100644 libgo/go/exp/html/atom/gen.go delete mode 100644 libgo/go/exp/html/atom/table.go delete mode 100644 libgo/go/exp/html/atom/table_test.go delete mode 100644 libgo/go/exp/html/const.go delete mode 100644 libgo/go/exp/html/doc.go delete mode 100644 libgo/go/exp/html/doctype.go delete mode 100644 libgo/go/exp/html/entity.go delete mode 100644 libgo/go/exp/html/entity_test.go delete mode 100644 libgo/go/exp/html/escape.go delete mode 100644 libgo/go/exp/html/foreign.go delete mode 100644 libgo/go/exp/html/node.go delete mode 100644 libgo/go/exp/html/node_test.go delete mode 100644 libgo/go/exp/html/parse.go delete mode 100644 libgo/go/exp/html/parse_test.go delete mode 100644 libgo/go/exp/html/render.go delete mode 100644 libgo/go/exp/html/render_test.go delete mode 100644 libgo/go/exp/html/testdata/go1.html delete mode 100644 libgo/go/exp/html/testdata/webkit/README delete mode 100644 libgo/go/exp/html/testdata/webkit/adoption01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/adoption02.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/comments01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/doctype01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/entities01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/entities02.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/html5test-com.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/inbody01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/isindex.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/scriptdata01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/scripted/adoption01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/scripted/webkit01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tables01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests1.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests10.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests11.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests12.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests14.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests15.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests16.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests17.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests18.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests19.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests2.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests20.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests21.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests22.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests23.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests24.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests25.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests26.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests3.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests4.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests5.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests6.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests7.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests8.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests9.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/tricky01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/webkit01.dat delete mode 100644 libgo/go/exp/html/testdata/webkit/webkit02.dat delete mode 100644 libgo/go/exp/html/token.go delete mode 100644 libgo/go/exp/html/token_test.go delete mode 100644 libgo/go/exp/inotify/inotify_linux.go delete mode 100644 libgo/go/exp/inotify/inotify_linux_test.go delete mode 100644 libgo/go/exp/locale/collate/build/builder.go delete mode 100644 libgo/go/exp/locale/collate/build/builder_test.go delete mode 100644 libgo/go/exp/locale/collate/build/colelem.go delete mode 100644 libgo/go/exp/locale/collate/build/colelem_test.go delete mode 100644 libgo/go/exp/locale/collate/build/contract.go delete mode 100644 libgo/go/exp/locale/collate/build/contract_test.go delete mode 100644 libgo/go/exp/locale/collate/build/order.go delete mode 100644 libgo/go/exp/locale/collate/build/order_test.go delete mode 100644 libgo/go/exp/locale/collate/build/table.go delete mode 100644 libgo/go/exp/locale/collate/build/trie.go delete mode 100644 libgo/go/exp/locale/collate/build/trie_test.go delete mode 100644 libgo/go/exp/locale/collate/colelem.go delete mode 100644 libgo/go/exp/locale/collate/colelem_test.go delete mode 100644 libgo/go/exp/locale/collate/collate.go delete mode 100644 libgo/go/exp/locale/collate/colltab.go delete mode 100644 libgo/go/exp/locale/collate/contract.go delete mode 100644 libgo/go/exp/locale/collate/contract_test.go delete mode 100644 libgo/go/exp/locale/collate/export.go delete mode 100644 libgo/go/exp/locale/collate/export_test.go delete mode 100644 libgo/go/exp/locale/collate/maketables.go delete mode 100644 libgo/go/exp/locale/collate/regtest.go delete mode 100644 libgo/go/exp/locale/collate/sort.go delete mode 100644 libgo/go/exp/locale/collate/sort_test.go delete mode 100644 libgo/go/exp/locale/collate/table.go delete mode 100644 libgo/go/exp/locale/collate/tables.go delete mode 100644 libgo/go/exp/locale/collate/tools/colcmp/chars.go delete mode 100644 libgo/go/exp/locale/collate/tools/colcmp/col.go delete mode 100644 libgo/go/exp/locale/collate/tools/colcmp/colcmp.go delete mode 100644 libgo/go/exp/locale/collate/tools/colcmp/darwin.go delete mode 100644 libgo/go/exp/locale/collate/tools/colcmp/gen.go delete mode 100644 libgo/go/exp/locale/collate/tools/colcmp/icu.go delete mode 100644 libgo/go/exp/locale/collate/trie.go delete mode 100644 libgo/go/exp/locale/collate/trie_test.go delete mode 100644 libgo/go/exp/norm/composition.go delete mode 100644 libgo/go/exp/norm/composition_test.go delete mode 100644 libgo/go/exp/norm/example_iter_test.go delete mode 100644 libgo/go/exp/norm/forminfo.go delete mode 100644 libgo/go/exp/norm/input.go delete mode 100644 libgo/go/exp/norm/iter.go delete mode 100644 libgo/go/exp/norm/iter_test.go delete mode 100644 libgo/go/exp/norm/maketables.go delete mode 100644 libgo/go/exp/norm/maketesttables.go delete mode 100644 libgo/go/exp/norm/norm_test.go delete mode 100644 libgo/go/exp/norm/normalize.go delete mode 100644 libgo/go/exp/norm/normalize_test.go delete mode 100644 libgo/go/exp/norm/normregtest.go delete mode 100644 libgo/go/exp/norm/readwriter.go delete mode 100644 libgo/go/exp/norm/readwriter_test.go delete mode 100644 libgo/go/exp/norm/tables.go delete mode 100644 libgo/go/exp/norm/trie.go delete mode 100644 libgo/go/exp/norm/trie_test.go delete mode 100644 libgo/go/exp/norm/triedata_test.go delete mode 100644 libgo/go/exp/norm/triegen.go delete mode 100644 libgo/go/exp/ssa/blockopt.go delete mode 100644 libgo/go/exp/ssa/doc.go delete mode 100644 libgo/go/exp/ssa/func.go delete mode 100644 libgo/go/exp/ssa/literal.go delete mode 100644 libgo/go/exp/ssa/print.go delete mode 100644 libgo/go/exp/ssa/sanity.go delete mode 100644 libgo/go/exp/ssa/ssa.go delete mode 100644 libgo/go/exp/ssa/util.go delete mode 100644 libgo/go/exp/utf8string/string.go delete mode 100644 libgo/go/exp/utf8string/string_test.go delete mode 100644 libgo/go/exp/winfsnotify/winfsnotify.go delete mode 100644 libgo/go/exp/winfsnotify/winfsnotify_test.go create mode 100644 libgo/go/go/ast/filter_test.go delete mode 100644 libgo/go/go/types/api.go delete mode 100644 libgo/go/go/types/builtins.go delete mode 100644 libgo/go/go/types/check.go delete mode 100644 libgo/go/go/types/check_test.go delete mode 100644 libgo/go/go/types/const.go delete mode 100644 libgo/go/go/types/conversions.go delete mode 100644 libgo/go/go/types/errors.go delete mode 100644 libgo/go/go/types/exportdata.go delete mode 100644 libgo/go/go/types/expr.go delete mode 100644 libgo/go/go/types/gcimporter.go delete mode 100644 libgo/go/go/types/gcimporter_test.go delete mode 100644 libgo/go/go/types/objects.go delete mode 100644 libgo/go/go/types/operand.go delete mode 100644 libgo/go/go/types/predicates.go delete mode 100644 libgo/go/go/types/resolve.go delete mode 100644 libgo/go/go/types/resolver_test.go delete mode 100644 libgo/go/go/types/scope.go delete mode 100644 libgo/go/go/types/stmt.go delete mode 100644 libgo/go/go/types/testdata/exports.go delete mode 100644 libgo/go/go/types/types.go delete mode 100644 libgo/go/go/types/types_test.go delete mode 100644 libgo/go/go/types/universe.go create mode 100644 libgo/go/image/gif/reader_test.go create mode 100644 libgo/go/net/dial_gen.go delete mode 100644 libgo/go/net/fd_linux.go create mode 100644 libgo/go/net/fd_poll_runtime.go create mode 100644 libgo/go/net/fd_poll_unix.go create mode 100644 libgo/go/net/http/cgi/posix_test.go create mode 100644 libgo/go/net/http/cookiejar/jar.go create mode 100644 libgo/go/net/http/cookiejar/jar_test.go create mode 100644 libgo/go/net/http/cookiejar/punycode.go create mode 100644 libgo/go/net/http/cookiejar/punycode_test.go create mode 100644 libgo/go/net/http/npn_test.go create mode 100644 libgo/go/net/http/z_last_test.go delete mode 100644 libgo/go/net/multicast_posix_test.go create mode 100644 libgo/go/net/multicast_test.go delete mode 100644 libgo/go/net/newpollserver_unix.go create mode 100644 libgo/go/net/sock_unix.go create mode 100644 libgo/go/net/unix_test.go delete mode 100644 libgo/go/old/netchan/common.go delete mode 100644 libgo/go/old/netchan/export.go delete mode 100644 libgo/go/old/netchan/import.go delete mode 100644 libgo/go/old/netchan/netchan_test.go create mode 100644 libgo/go/os/env_unix_test.go create mode 100644 libgo/go/os/exec/lp_unix_test.go create mode 100644 libgo/go/os/types_notwin.go create mode 100644 libgo/go/os/types_windows.go create mode 100644 libgo/go/path/filepath/example_unix_test.go create mode 100644 libgo/go/runtime/debug/garbage.go create mode 100644 libgo/go/runtime/debug/garbage_test.go create mode 100644 libgo/go/runtime/map_test.go create mode 100644 libgo/go/runtime/mapspeed_test.go create mode 100644 libgo/go/sort/example_keys_test.go create mode 100644 libgo/go/sort/example_multi_test.go delete mode 100644 libgo/go/sort/example_reverse_test.go create mode 100644 libgo/go/testing/allocs.go create mode 100644 libgo/runtime/netpoll.goc create mode 100644 libgo/runtime/netpoll_epoll.c create mode 100644 libgo/runtime/netpoll_kqueue.c create mode 100644 libgo/runtime/netpoll_stub.c create mode 100644 libgo/runtime/signal_unix.h diff --git a/libgo/MERGE b/libgo/MERGE index 5cf1a26a66f..5b7344c007d 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -229081515358 +a7bd9a33067b The first line of this file holds the Mercurial revision number of the last merge done from the master library sources. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index d54448c42a0..6a81d336819 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -211,40 +211,11 @@ toolexeclibgoencoding_DATA = \ encoding/pem.gox \ encoding/xml.gox -if LIBGO_IS_LINUX -# exp_inotify_gox = exp/inotify.gox -exp_inotify_gox = -else -exp_inotify_gox = -endif - toolexeclibgoexpdir = $(toolexeclibgodir)/exp toolexeclibgoexp_DATA = \ - exp/cookiejar.gox \ - exp/ebnf.gox \ - exp/html.gox \ - $(exp_inotify_gox) \ - exp/norm.gox \ exp/proxy.gox \ - exp/ssa.gox \ - exp/terminal.gox \ - exp/utf8string.gox - -toolexeclibgoexphtmldir = $(toolexeclibgoexpdir)/html - -toolexeclibgoexphtml_DATA = \ - exp/html/atom.gox - -toolexeclibgoexplocaledir = $(toolexeclibgoexpdir)/locale - -toolexeclibgoexplocale_DATA = \ - exp/locale/collate.gox - -toolexeclibgoexplocalecollatedir = $(toolexeclibgoexplocaledir)/collate - -toolexeclibgoexplocalecollate_DATA = \ - exp/locale/collate/build.gox + exp/terminal.gox toolexeclibgogodir = $(toolexeclibgodir)/go @@ -256,8 +227,7 @@ toolexeclibgogo_DATA = \ go/parser.gox \ go/printer.gox \ go/scanner.gox \ - go/token.gox \ - go/types.gox + go/token.gox toolexeclibgohashdir = $(toolexeclibgodir)/hash @@ -322,6 +292,7 @@ toolexeclibgonethttpdir = $(toolexeclibgonetdir)/http toolexeclibgonethttp_DATA = \ net/http/cgi.gox \ + net/http/cookiejar.gox \ net/http/fcgi.gox \ net/http/httptest.gox \ net/http/httputil.gox \ @@ -335,7 +306,6 @@ toolexeclibgonetrpc_DATA = \ toolexeclibgoolddir = $(toolexeclibgodir)/old toolexeclibgoold_DATA = \ - old/netchan.gox \ old/regexp.gox \ old/template.gox @@ -435,6 +405,16 @@ endif endif endif +if LIBGO_IS_LINUX +runtime_netpoll_files = netpoll.c runtime/netpoll_epoll.c +else +if LIBGO_IS_DARWIN +runtime_netpoll_files = netpoll.c runtime/netpoll_kqueue.c +else +runtime_netpoll_files = runtime/netpoll_stub.c +endif +endif + runtime_files = \ runtime/go-append.c \ runtime/go-assert.c \ @@ -513,6 +493,7 @@ runtime_files = \ runtime/mgc0.c \ runtime/mheap.c \ runtime/msize.c \ + $(runtime_netpoll_files) \ runtime/panic.c \ runtime/parfor.c \ runtime/print.c \ @@ -548,6 +529,10 @@ mprof.c: $(srcdir)/runtime/mprof.goc goc2c ./goc2c $< > $@.tmp mv -f $@.tmp $@ +netpoll.c: $(srcdir)/runtime/netpoll.goc goc2c + ./goc2c $< > $@.tmp + mv -f $@.tmp $@ + reflect.c: $(srcdir)/runtime/reflect.goc goc2c ./goc2c $< > $@.tmp mv -f $@.tmp $@ @@ -573,7 +558,8 @@ time.c: $(srcdir)/runtime/time.goc goc2c mv -f $@.tmp $@ go_bufio_files = \ - go/bufio/bufio.go + go/bufio/bufio.go \ + go/bufio/scan.go go_bytes_files = \ go/bytes/buffer.go \ @@ -678,17 +664,17 @@ go_net_fd_os_file = go/net/fd_select.go go_net_newpollserver_file = go/net/newpollserver_rtems.go else # !LIBGO_IS_RTEMS if LIBGO_IS_LINUX -go_net_fd_os_file = go/net/fd_linux.go -go_net_newpollserver_file = go/net/newpollserver_unix.go +go_net_fd_os_file = +go_net_newpollserver_file = else # !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS if LIBGO_IS_NETBSD go_net_fd_os_file = go/net/fd_bsd.go -go_net_newpollserver_file = go/net/newpollserver_unix.go +go_net_newpollserver_file = else # !LIBGO_IS_NETBSD && !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS # By default use select with pipes. Most systems should have # something better. go_net_fd_os_file = go/net/fd_select.go -go_net_newpollserver_file = go/net/newpollserver_unix.go +go_net_newpollserver_file = endif # !LIBGO_IS_NETBSD endif # !LIBGO_IS_LINUX endif # !LIBGO_IS_RTEMS @@ -759,6 +745,16 @@ else go_net_cloexec_file = go/net/sys_cloexec.go endif +if LIBGO_IS_LINUX +go_net_poll_file = go/net/fd_poll_runtime.go +else +if LIBGO_IS_DARWIN +go_net_poll_file = go/net/fd_poll_runtime.go +else +go_net_poll_file = go/net/fd_poll_unix.go +endif +endif + go_net_files = \ go/net/cgo_unix.go \ $(go_net_cgo_file) \ @@ -786,10 +782,12 @@ go_net_files = \ go/net/net.go \ go/net/parse.go \ go/net/pipe.go \ + $(go_net_poll_file) \ go/net/port.go \ go/net/port_unix.go \ $(go_net_sendfile_file) \ go/net/sock_posix.go \ + go/net/sock_unix.go \ $(go_net_sock_file) \ go/net/sockopt_posix.go \ $(go_net_sockopt_file) \ @@ -890,7 +888,8 @@ go_os_files = \ $(go_os_stat_file) \ go/os/str.go \ $(go_os_sys_file) \ - go/os/types.go + go/os/types.go \ + go/os/types_notwin.go go_path_files = \ go/path/match.go \ @@ -979,6 +978,7 @@ go_syslog_c_files = \ go/log/syslog/syslog_c.c go_testing_files = \ + go/testing/allocs.go \ go/testing/benchmark.go \ go/testing/example.go \ go/testing/testing.go @@ -1101,7 +1101,8 @@ go_crypto_rand_files = \ go/crypto/rand/rand_unix.go \ go/crypto/rand/util.go go_crypto_rc4_files = \ - go/crypto/rc4/rc4.go + go/crypto/rc4/rc4.go \ + go/crypto/rc4/rc4_ref.go go_crypto_rsa_files = \ go/crypto/rsa/pkcs1v15.go \ go/crypto/rsa/rsa.go @@ -1212,73 +1213,14 @@ go_encoding_xml_files = \ go/encoding/xml/typeinfo.go \ go/encoding/xml/xml.go -go_exp_cookiejar_files = \ - go/exp/cookiejar/jar.go \ - go/exp/cookiejar/storage.go -go_exp_ebnf_files = \ - go/exp/ebnf/ebnf.go \ - go/exp/ebnf/parser.go -go_exp_html_files = \ - go/exp/html/const.go \ - go/exp/html/doc.go \ - go/exp/html/doctype.go \ - go/exp/html/entity.go \ - go/exp/html/escape.go \ - go/exp/html/foreign.go \ - go/exp/html/node.go \ - go/exp/html/parse.go \ - go/exp/html/render.go \ - go/exp/html/token.go -go_exp_html_atom_files = \ - go/exp/html/atom/atom.go \ - go/exp/html/atom/table.go -go_exp_inotify_files = \ - go/exp/inotify/inotify_linux.go -go_exp_locale_collate_files = \ - go/exp/locale/collate/colelem.go \ - go/exp/locale/collate/collate.go \ - go/exp/locale/collate/colltab.go \ - go/exp/locale/collate/contract.go \ - go/exp/locale/collate/export.go \ - go/exp/locale/collate/sort.go \ - go/exp/locale/collate/table.go \ - go/exp/locale/collate/tables.go \ - go/exp/locale/collate/trie.go -go_exp_locale_collate_build_files = \ - go/exp/locale/collate/build/builder.go \ - go/exp/locale/collate/build/colelem.go \ - go/exp/locale/collate/build/contract.go \ - go/exp/locale/collate/build/order.go \ - go/exp/locale/collate/build/table.go \ - go/exp/locale/collate/build/trie.go -go_exp_norm_files = \ - go/exp/norm/composition.go \ - go/exp/norm/forminfo.go \ - go/exp/norm/input.go \ - go/exp/norm/iter.go \ - go/exp/norm/normalize.go \ - go/exp/norm/readwriter.go \ - go/exp/norm/tables.go \ - go/exp/norm/trie.go go_exp_proxy_files = \ go/exp/proxy/direct.go \ go/exp/proxy/per_host.go \ go/exp/proxy/proxy.go \ go/exp/proxy/socks5.go -go_exp_ssa_files = \ - go/exp/ssa/blockopt.go \ - go/exp/ssa/doc.go \ - go/exp/ssa/func.go \ - go/exp/ssa/sanity.go \ - go/exp/ssa/ssa.go \ - go/exp/ssa/literal.go \ - go/exp/ssa/print.go \ - go/exp/ssa/util.go go_exp_terminal_files = \ go/exp/terminal/terminal.go \ go/exp/terminal/util.go -go_exp_utf8string_files = \ - go/exp/utf8string/string.go go_go_ast_files = \ go/go/ast/ast.go \ @@ -1317,24 +1259,6 @@ go_go_token_files = \ go/go/token/position.go \ go/go/token/serialize.go \ go/go/token/token.go -go_go_types_files = \ - go/go/types/api.go \ - go/go/types/builtins.go \ - go/go/types/check.go \ - go/go/types/const.go \ - go/go/types/conversions.go \ - go/go/types/errors.go \ - go/go/types/exportdata.go \ - go/go/types/expr.go \ - go/go/types/gcimporter.go \ - go/go/types/objects.go \ - go/go/types/operand.go \ - go/go/types/predicates.go \ - go/go/types/resolve.go \ - go/go/types/scope.go \ - go/go/types/stmt.go \ - go/go/types/types.go \ - go/go/types/universe.go go_hash_adler32_files = \ go/hash/adler32/adler32.go @@ -1458,6 +1382,9 @@ go_net_url_files = \ go_net_http_cgi_files = \ go/net/http/cgi/child.go \ go/net/http/cgi/host.go +go_net_http_cookiejar_files = \ + go/net/http/cookiejar/jar.go \ + go/net/http/cookiejar/punycode.go go_net_http_fcgi_files = \ go/net/http/fcgi/child.go \ go/net/http/fcgi/fcgi.go @@ -1473,10 +1400,6 @@ go_net_http_httputil_files = \ go/net/http/httputil/reverseproxy.go -go_old_netchan_files = \ - go/old/netchan/common.go \ - go/old/netchan/export.go \ - go/old/netchan/import.go go_old_regexp_files = \ go/old/regexp/regexp.go go_old_template_files = \ @@ -1518,6 +1441,7 @@ go_net_rpc_jsonrpc_files = \ go/net/rpc/jsonrpc/server.go go_runtime_debug_files = \ + go/runtime/debug/garbage.go \ go/runtime/debug/stack.go go_runtime_pprof_files = \ go/runtime/pprof/pprof.go @@ -1896,17 +1820,8 @@ libgo_go_objs = \ encoding/json.lo \ encoding/pem.lo \ encoding/xml.lo \ - exp/cookiejar.lo \ - exp/ebnf.lo \ - exp/html.lo \ - exp/html/atom.lo \ - exp/locale/collate.lo \ - exp/locale/collate/build.lo \ - exp/norm.lo \ exp/proxy.lo \ - exp/ssa.lo \ exp/terminal.lo \ - exp/utf8string.lo \ html/template.lo \ go/ast.lo \ go/build.lo \ @@ -1916,12 +1831,12 @@ libgo_go_objs = \ go/printer.lo \ go/scanner.lo \ go/token.lo \ - go/types.lo \ hash/adler32.lo \ hash/crc32.lo \ hash/crc64.lo \ hash/fnv.lo \ net/http/cgi.lo \ + net/http/cookiejar.lo \ net/http/fcgi.lo \ net/http/httptest.lo \ net/http/httputil.lo \ @@ -1945,7 +1860,6 @@ libgo_go_objs = \ net/smtp.lo \ net/textproto.lo \ net/url.lo \ - old/netchan.lo \ old/regexp.lo \ old/template.lo \ os/exec.lo \ @@ -2730,69 +2644,6 @@ encoding/xml/check: $(CHECK_DEPS) @$(CHECK) .PHONY: encoding/xml/check -@go_include@ exp/cookiejar.lo.dep -exp/cookiejar.lo.dep: $(go_exp_cookiejar_files) - $(BUILDDEPS) -exp/cookiejar.lo: $(go_exp_cookiejar_files) - $(BUILDPACKAGE) -exp/cookiejar/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/cookiejar/check - -@go_include@ exp/ebnf.lo.dep -exp/ebnf.lo.dep: $(go_exp_ebnf_files) - $(BUILDDEPS) -exp/ebnf.lo: $(go_exp_ebnf_files) - $(BUILDPACKAGE) -exp/ebnf/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/ebnf/check - -@go_include@ exp/html.lo.dep -exp/html.lo.dep: $(go_exp_html_files) - $(BUILDDEPS) -exp/html.lo: $(go_exp_html_files) - $(BUILDPACKAGE) -exp/html/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/html/check - -@go_include@ exp/html/atom.lo.dep -exp/html/atom.lo.dep: $(go_exp_html_atom_files) - $(BUILDDEPS) -exp/html/atom.lo: $(go_exp_html_atom_files) - $(BUILDPACKAGE) -exp/html/atom/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/html/atom/check - -@go_include@ exp/locale/collate.lo.dep -exp/locale/collate.lo.dep: $(go_exp_locale_collate_files) - $(BUILDDEPS) -exp/locale/collate.lo: $(go_exp_locale_collate_files) - $(BUILDPACKAGE) -exp/locale/collate/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/locale/collate/check - -@go_include@ exp/locale/collate/build.lo.dep -exp/locale/collate/build.lo.dep: $(go_exp_locale_collate_build_files) - $(BUILDDEPS) -exp/locale/collate/build.lo: $(go_exp_locale_collate_build_files) - $(BUILDPACKAGE) -exp/locale/collate/build/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/locale/collate/build/check - -@go_include@ exp/norm.lo.dep -exp/norm.lo.dep: $(go_exp_norm_files) - $(BUILDDEPS) -exp/norm.lo: $(go_exp_norm_files) - $(BUILDPACKAGE) -exp/norm/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/norm/check - @go_include@ exp/proxy.lo.dep exp/proxy.lo.dep: $(go_exp_proxy_files) $(BUILDDEPS) @@ -2802,15 +2653,6 @@ exp/proxy/check: $(CHECK_DEPS) @$(CHECK) .PHONY: exp/proxy/check -@go_include@ exp/ssa.lo.dep -exp/ssa.lo.dep: $(go_exp_ssa_files) - $(BUILDDEPS) -exp/ssa.lo: $(go_exp_ssa_files) - $(BUILDPACKAGE) -exp/ssa/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/ssa/check - @go_include@ exp/terminal.lo.dep exp/terminal.lo.dep: $(go_exp_terminal_files) $(BUILDDEPS) @@ -2820,24 +2662,6 @@ exp/terminal/check: $(CHECK_DEPS) @$(CHECK) .PHONY: exp/terminal/check -@go_include@ exp/utf8string.lo.dep -exp/utf8string.lo.dep: $(go_exp_utf8string_files) - $(BUILDDEPS) -exp/utf8string.lo: $(go_exp_utf8string_files) - $(BUILDPACKAGE) -exp/utf8string/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/utf8string/check - -@go_include@ exp/inotify.lo.dep -exp/inotify.lo.dep: $(go_exp_inotify_files) - $(BUILDDEPS) -exp/inotify.lo: $(go_exp_inotify_files) - $(BUILDPACKAGE) -exp/inotify/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/inotify/check - @go_include@ html/template.lo.dep html/template.lo.dep: $(go_html_template_files) $(BUILDDEPS) @@ -2928,15 +2752,6 @@ go/token/check: $(CHECK_DEPS) @$(CHECK) .PHONY: go/token/check -@go_include@ go/types.lo.dep -go/types.lo.dep: $(go_go_types_files) - $(BUILDDEPS) -go/types.lo: $(go_go_types_files) - $(BUILDPACKAGE) -go/types/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: go/types/check - @go_include@ hash/adler32.lo.dep hash/adler32.lo.dep: $(go_hash_adler32_files) $(BUILDDEPS) @@ -3147,6 +2962,15 @@ net/http/cgi/check: $(CHECK_DEPS) @$(CHECK) .PHONY: net/http/cgi/check +@go_include@ net/http/cookiejar.lo.dep +net/http/cookiejar.lo.dep: $(go_net_http_cookiejar_files) + $(BUILDDEPS) +net/http/cookiejar.lo: $(go_net_http_cookiejar_files) + $(BUILDPACKAGE) +net/http/cookiejar/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: net/http/cookiejar/check + @go_include@ net/http/fcgi.lo.dep net/http/fcgi.lo.dep: $(go_net_http_fcgi_files) $(BUILDDEPS) @@ -3192,15 +3016,6 @@ net/rpc/jsonrpc/check: $(CHECK_DEPS) @$(CHECK) .PHONY: net/rpc/jsonrpc/check -@go_include@ old/netchan.lo.dep -old/netchan.lo.dep: $(go_old_netchan_files) - $(BUILDDEPS) -old/netchan.lo: $(go_old_netchan_files) - $(BUILDPACKAGE) -old/netchan/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: old/netchan/check - @go_include@ old/regexp.lo.dep old/regexp.lo.dep: $(go_old_regexp_files) $(BUILDDEPS) @@ -3549,30 +3364,10 @@ encoding/pem.gox: encoding/pem.lo encoding/xml.gox: encoding/xml.lo $(BUILDGOX) -exp/cookiejar.gox: exp/cookiejar.lo - $(BUILDGOX) -exp/ebnf.gox: exp/ebnf.lo - $(BUILDGOX) -exp/html.gox: exp/html.lo - $(BUILDGOX) -exp/html/atom.gox: exp/html/atom.lo - $(BUILDGOX) -exp/inotify.gox: exp/inotify.lo - $(BUILDGOX) -exp/locale/collate.gox: exp/locale/collate.lo - $(BUILDGOX) -exp/locale/collate/build.gox: exp/locale/collate/build.lo - $(BUILDGOX) -exp/norm.gox: exp/norm.lo - $(BUILDGOX) exp/proxy.gox: exp/proxy.lo $(BUILDGOX) -exp/ssa.gox: exp/ssa.lo - $(BUILDGOX) exp/terminal.gox: exp/terminal.lo $(BUILDGOX) -exp/utf8string.gox: exp/utf8string.lo - $(BUILDGOX) html/template.gox: html/template.lo $(BUILDGOX) @@ -3593,8 +3388,6 @@ go/scanner.gox: go/scanner.lo $(BUILDGOX) go/token.gox: go/token.lo $(BUILDGOX) -go/types.gox: go/types.lo - $(BUILDGOX) hash/adler32.gox: hash/adler32.lo $(BUILDGOX) @@ -3650,6 +3443,8 @@ net/url.gox: net/url.lo net/http/cgi.gox: net/http/cgi.lo $(BUILDGOX) +net/http/cookiejar.gox: net/http/cookiejar.lo + $(BUILDGOX) net/http/fcgi.gox: net/http/fcgi.lo $(BUILDGOX) net/http/httptest.gox: net/http/httptest.lo @@ -3662,8 +3457,6 @@ net/http/pprof.gox: net/http/pprof.lo net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo $(BUILDGOX) -old/netchan.gox: old/netchan.lo - $(BUILDGOX) old/regexp.gox: old/regexp.lo $(BUILDGOX) old/template.gox: old/template.lo @@ -3709,13 +3502,6 @@ unicode/utf16.gox: unicode/utf16.lo unicode/utf8.gox: unicode/utf8.lo $(BUILDGOX) -if LIBGO_IS_LINUX -# exp_inotify_check = exp/inotify/check -exp_inotify_check = -else -exp_inotify_check = -endif - TEST_PACKAGES = \ bufio/check \ bytes/check \ @@ -3786,17 +3572,8 @@ TEST_PACKAGES = \ encoding/json/check \ encoding/pem/check \ encoding/xml/check \ - exp/cookiejar/check \ - exp/ebnf/check \ - exp/html/check \ - exp/html/atom/check \ - $(exp_inotify_check) \ - exp/locale/collate/check \ - exp/locale/collate/build/check \ - exp/norm/check \ exp/proxy/check \ exp/terminal/check \ - exp/utf8string/check \ html/template/check \ go/ast/check \ $(go_build_check_omitted_since_it_calls_6g) \ @@ -3806,7 +3583,6 @@ TEST_PACKAGES = \ go/printer/check \ go/scanner/check \ go/token/check \ - go/types/check \ hash/adler32/check \ hash/crc32/check \ hash/crc64/check \ @@ -3824,6 +3600,7 @@ TEST_PACKAGES = \ mime/multipart/check \ net/http/check \ net/http/cgi/check \ + net/http/cookiejar/check \ net/http/fcgi/check \ net/http/httptest/check \ net/http/httputil/check \ @@ -3833,7 +3610,6 @@ TEST_PACKAGES = \ net/textproto/check \ net/url/check \ net/rpc/jsonrpc/check \ - old/netchan/check \ old/regexp/check \ old/template/check \ os/exec/check \ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 08eae578e51..eccc72d2e3c 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -101,9 +101,6 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \ "$(DESTDIR)$(toolexeclibgodebugdir)" \ "$(DESTDIR)$(toolexeclibgoencodingdir)" \ "$(DESTDIR)$(toolexeclibgoexpdir)" \ - "$(DESTDIR)$(toolexeclibgoexphtmldir)" \ - "$(DESTDIR)$(toolexeclibgoexplocaledir)" \ - "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" \ "$(DESTDIR)$(toolexeclibgogodir)" \ "$(DESTDIR)$(toolexeclibgohashdir)" \ "$(DESTDIR)$(toolexeclibgohtmldir)" \ @@ -153,22 +150,20 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \ debug/pe.lo encoding/ascii85.lo encoding/asn1.lo \ encoding/base32.lo encoding/base64.lo encoding/binary.lo \ encoding/csv.lo encoding/gob.lo encoding/hex.lo \ - encoding/json.lo encoding/pem.lo encoding/xml.lo \ - exp/cookiejar.lo exp/ebnf.lo exp/html.lo exp/html/atom.lo \ - exp/locale/collate.lo exp/locale/collate/build.lo exp/norm.lo \ - exp/proxy.lo exp/ssa.lo exp/terminal.lo exp/utf8string.lo \ - html/template.lo go/ast.lo go/build.lo go/doc.lo go/format.lo \ - go/parser.lo go/printer.lo go/scanner.lo go/token.lo \ - go/types.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \ - hash/fnv.lo net/http/cgi.lo net/http/fcgi.lo \ - net/http/httptest.lo net/http/httputil.lo net/http/pprof.lo \ - image/color.lo image/draw.lo image/gif.lo image/jpeg.lo \ - image/png.lo index/suffixarray.lo io/ioutil.lo log/syslog.lo \ + encoding/json.lo encoding/pem.lo encoding/xml.lo exp/proxy.lo \ + exp/terminal.lo html/template.lo go/ast.lo go/build.lo \ + go/doc.lo go/format.lo go/parser.lo go/printer.lo \ + go/scanner.lo go/token.lo hash/adler32.lo hash/crc32.lo \ + hash/crc64.lo hash/fnv.lo net/http/cgi.lo \ + net/http/cookiejar.lo net/http/fcgi.lo net/http/httptest.lo \ + net/http/httputil.lo net/http/pprof.lo image/color.lo \ + image/draw.lo image/gif.lo image/jpeg.lo image/png.lo \ + index/suffixarray.lo io/ioutil.lo log/syslog.lo \ log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \ mime/multipart.lo net/http.lo net/mail.lo net/rpc.lo \ - net/smtp.lo net/textproto.lo net/url.lo old/netchan.lo \ - old/regexp.lo old/template.lo os/exec.lo $(am__DEPENDENCIES_1) \ - os/signal.lo os/user.lo path/filepath.lo regexp/syntax.lo \ + net/smtp.lo net/textproto.lo net/url.lo old/regexp.lo \ + old/template.lo os/exec.lo $(am__DEPENDENCIES_1) os/signal.lo \ + os/user.lo path/filepath.lo regexp/syntax.lo \ net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \ sync/atomic.lo sync/atomic_c.lo text/scanner.lo \ text/tabwriter.lo text/template.lo text/template/parse.lo \ @@ -183,16 +178,22 @@ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ @LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo @HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo @HAVE_SYS_MMAN_H_TRUE@am__objects_2 = mem.lo -@LIBGO_IS_RTEMS_TRUE@am__objects_3 = rtems-task-variable-add.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-none.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-bsd.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-bsd.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_4 = getncpu-solaris.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_4 = getncpu-irix.lo -@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_4 = \ +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@am__objects_3 = \ +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@ netpoll_stub.lo +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_3 = \ +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ netpoll.lo \ +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ netpoll_kqueue.lo +@LIBGO_IS_LINUX_TRUE@am__objects_3 = netpoll.lo netpoll_epoll.lo +@LIBGO_IS_RTEMS_TRUE@am__objects_4 = rtems-task-variable-add.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-none.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-bsd.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-bsd.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_5 = getncpu-solaris.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_5 = getncpu-irix.lo +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_5 = \ @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ getncpu-bsd.lo -@LIBGO_IS_LINUX_TRUE@am__objects_4 = getncpu-linux.lo -am__objects_5 = go-append.lo go-assert.lo go-assert-interface.lo \ +@LIBGO_IS_LINUX_TRUE@am__objects_5 = getncpu-linux.lo +am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \ go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \ go-callers.lo go-can-convert-interface.lo go-cgo.lo \ go-check-interface.lo go-construct-map.lo \ @@ -215,12 +216,12 @@ am__objects_5 = go-append.lo go-assert.lo go-assert-interface.lo \ go-unsafe-new.lo go-unsafe-newarray.lo go-unsafe-pointer.lo \ go-unwind.lo chan.lo cpuprof.lo env_posix.lo lfstack.lo \ $(am__objects_1) mcache.lo mcentral.lo $(am__objects_2) \ - mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo panic.lo \ - parfor.lo print.lo proc.lo runtime.lo signal_unix.lo thread.lo \ - yield.lo $(am__objects_3) iface.lo malloc.lo map.lo mprof.lo \ - reflect.lo runtime1.lo sema.lo sigqueue.lo string.lo time.lo \ - $(am__objects_4) -am_libgo_la_OBJECTS = $(am__objects_5) + mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo \ + $(am__objects_3) panic.lo parfor.lo print.lo proc.lo \ + runtime.lo signal_unix.lo thread.lo yield.lo $(am__objects_4) \ + iface.lo malloc.lo map.lo mprof.lo reflect.lo runtime1.lo \ + sema.lo sigqueue.lo string.lo time.lo $(am__objects_5) +am_libgo_la_OBJECTS = $(am__objects_6) libgo_la_OBJECTS = $(am_libgo_la_OBJECTS) libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgo_la_LDFLAGS) \ @@ -257,9 +258,7 @@ DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \ $(toolexeclibgocrypto_DATA) $(toolexeclibgocryptox509_DATA) \ $(toolexeclibgodatabase_DATA) $(toolexeclibgodatabasesql_DATA) \ $(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \ - $(toolexeclibgoexp_DATA) $(toolexeclibgoexphtml_DATA) \ - $(toolexeclibgoexplocale_DATA) \ - $(toolexeclibgoexplocalecollate_DATA) $(toolexeclibgogo_DATA) \ + $(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \ $(toolexeclibgohash_DATA) $(toolexeclibgohtml_DATA) \ $(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \ $(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \ @@ -606,33 +605,10 @@ toolexeclibgoencoding_DATA = \ encoding/pem.gox \ encoding/xml.gox -@LIBGO_IS_LINUX_FALSE@exp_inotify_gox = - -# exp_inotify_gox = exp/inotify.gox -@LIBGO_IS_LINUX_TRUE@exp_inotify_gox = toolexeclibgoexpdir = $(toolexeclibgodir)/exp toolexeclibgoexp_DATA = \ - exp/cookiejar.gox \ - exp/ebnf.gox \ - exp/html.gox \ - $(exp_inotify_gox) \ - exp/norm.gox \ exp/proxy.gox \ - exp/ssa.gox \ - exp/terminal.gox \ - exp/utf8string.gox - -toolexeclibgoexphtmldir = $(toolexeclibgoexpdir)/html -toolexeclibgoexphtml_DATA = \ - exp/html/atom.gox - -toolexeclibgoexplocaledir = $(toolexeclibgoexpdir)/locale -toolexeclibgoexplocale_DATA = \ - exp/locale/collate.gox - -toolexeclibgoexplocalecollatedir = $(toolexeclibgoexplocaledir)/collate -toolexeclibgoexplocalecollate_DATA = \ - exp/locale/collate/build.gox + exp/terminal.gox toolexeclibgogodir = $(toolexeclibgodir)/go toolexeclibgogo_DATA = \ @@ -643,8 +619,7 @@ toolexeclibgogo_DATA = \ go/parser.gox \ go/printer.gox \ go/scanner.gox \ - go/token.gox \ - go/types.gox + go/token.gox toolexeclibgohashdir = $(toolexeclibgodir)/hash toolexeclibgohash_DATA = \ @@ -699,6 +674,7 @@ toolexeclibgonet_DATA = \ toolexeclibgonethttpdir = $(toolexeclibgonetdir)/http toolexeclibgonethttp_DATA = \ net/http/cgi.gox \ + net/http/cookiejar.gox \ net/http/fcgi.gox \ net/http/httptest.gox \ net/http/httputil.gox \ @@ -710,7 +686,6 @@ toolexeclibgonetrpc_DATA = \ toolexeclibgoolddir = $(toolexeclibgodir)/old toolexeclibgoold_DATA = \ - old/netchan.gox \ old/regexp.gox \ old/template.gox @@ -770,6 +745,9 @@ toolexeclibgounicode_DATA = \ @LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-irix.c @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c @LIBGO_IS_LINUX_TRUE@runtime_getncpu_file = runtime/getncpu-linux.c +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@runtime_netpoll_files = runtime/netpoll_stub.c +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@runtime_netpoll_files = netpoll.c runtime/netpoll_kqueue.c +@LIBGO_IS_LINUX_TRUE@runtime_netpoll_files = netpoll.c runtime/netpoll_epoll.c runtime_files = \ runtime/go-append.c \ runtime/go-assert.c \ @@ -848,6 +826,7 @@ runtime_files = \ runtime/mgc0.c \ runtime/mheap.c \ runtime/msize.c \ + $(runtime_netpoll_files) \ runtime/panic.c \ runtime/parfor.c \ runtime/print.c \ @@ -870,7 +849,8 @@ runtime_files = \ $(runtime_getncpu_file) go_bufio_files = \ - go/bufio/bufio.go + go/bufio/bufio.go \ + go/bufio/scan.go go_bytes_files = \ go/bytes/buffer.go \ @@ -975,11 +955,11 @@ go_mime_files = \ # something better. @LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_select.go @LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_bsd.go -@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_linux.go +@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = @LIBGO_IS_RTEMS_TRUE@go_net_fd_os_file = go/net/fd_select.go -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver_unix.go -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver_unix.go -@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver_unix.go +@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = +@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = +@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = @LIBGO_IS_RTEMS_TRUE@go_net_newpollserver_file = go/net/newpollserver_rtems.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_bsd.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_cgo_file = go/net/cgo_netbsd.go @@ -1013,6 +993,9 @@ go_mime_files = \ @LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go @LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go @LIBGO_IS_LINUX_TRUE@go_net_cloexec_file = go/net/sock_cloexec.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_poll_file = go/net/fd_poll_unix.go +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_poll_file = go/net/fd_poll_runtime.go +@LIBGO_IS_LINUX_TRUE@go_net_poll_file = go/net/fd_poll_runtime.go go_net_files = \ go/net/cgo_unix.go \ $(go_net_cgo_file) \ @@ -1040,10 +1023,12 @@ go_net_files = \ go/net/net.go \ go/net/parse.go \ go/net/pipe.go \ + $(go_net_poll_file) \ go/net/port.go \ go/net/port_unix.go \ $(go_net_sendfile_file) \ go/net/sock_posix.go \ + go/net/sock_unix.go \ $(go_net_sock_file) \ go/net/sockopt_posix.go \ $(go_net_sockopt_file) \ @@ -1095,7 +1080,8 @@ go_os_files = \ $(go_os_stat_file) \ go/os/str.go \ $(go_os_sys_file) \ - go/os/types.go + go/os/types.go \ + go/os/types_notwin.go go_path_files = \ go/path/match.go \ @@ -1167,6 +1153,7 @@ go_syslog_c_files = \ go/log/syslog/syslog_c.c go_testing_files = \ + go/testing/allocs.go \ go/testing/benchmark.go \ go/testing/example.go \ go/testing/testing.go @@ -1285,7 +1272,8 @@ go_crypto_rand_files = \ go/crypto/rand/util.go go_crypto_rc4_files = \ - go/crypto/rc4/rc4.go + go/crypto/rc4/rc4.go \ + go/crypto/rc4/rc4_ref.go go_crypto_rsa_files = \ go/crypto/rsa/pkcs1v15.go \ @@ -1417,85 +1405,16 @@ go_encoding_xml_files = \ go/encoding/xml/typeinfo.go \ go/encoding/xml/xml.go -go_exp_cookiejar_files = \ - go/exp/cookiejar/jar.go \ - go/exp/cookiejar/storage.go - -go_exp_ebnf_files = \ - go/exp/ebnf/ebnf.go \ - go/exp/ebnf/parser.go - -go_exp_html_files = \ - go/exp/html/const.go \ - go/exp/html/doc.go \ - go/exp/html/doctype.go \ - go/exp/html/entity.go \ - go/exp/html/escape.go \ - go/exp/html/foreign.go \ - go/exp/html/node.go \ - go/exp/html/parse.go \ - go/exp/html/render.go \ - go/exp/html/token.go - -go_exp_html_atom_files = \ - go/exp/html/atom/atom.go \ - go/exp/html/atom/table.go - -go_exp_inotify_files = \ - go/exp/inotify/inotify_linux.go - -go_exp_locale_collate_files = \ - go/exp/locale/collate/colelem.go \ - go/exp/locale/collate/collate.go \ - go/exp/locale/collate/colltab.go \ - go/exp/locale/collate/contract.go \ - go/exp/locale/collate/export.go \ - go/exp/locale/collate/sort.go \ - go/exp/locale/collate/table.go \ - go/exp/locale/collate/tables.go \ - go/exp/locale/collate/trie.go - -go_exp_locale_collate_build_files = \ - go/exp/locale/collate/build/builder.go \ - go/exp/locale/collate/build/colelem.go \ - go/exp/locale/collate/build/contract.go \ - go/exp/locale/collate/build/order.go \ - go/exp/locale/collate/build/table.go \ - go/exp/locale/collate/build/trie.go - -go_exp_norm_files = \ - go/exp/norm/composition.go \ - go/exp/norm/forminfo.go \ - go/exp/norm/input.go \ - go/exp/norm/iter.go \ - go/exp/norm/normalize.go \ - go/exp/norm/readwriter.go \ - go/exp/norm/tables.go \ - go/exp/norm/trie.go - go_exp_proxy_files = \ go/exp/proxy/direct.go \ go/exp/proxy/per_host.go \ go/exp/proxy/proxy.go \ go/exp/proxy/socks5.go -go_exp_ssa_files = \ - go/exp/ssa/blockopt.go \ - go/exp/ssa/doc.go \ - go/exp/ssa/func.go \ - go/exp/ssa/sanity.go \ - go/exp/ssa/ssa.go \ - go/exp/ssa/literal.go \ - go/exp/ssa/print.go \ - go/exp/ssa/util.go - go_exp_terminal_files = \ go/exp/terminal/terminal.go \ go/exp/terminal/util.go -go_exp_utf8string_files = \ - go/exp/utf8string/string.go - go_go_ast_files = \ go/go/ast/ast.go \ go/go/ast/commentmap.go \ @@ -1541,25 +1460,6 @@ go_go_token_files = \ go/go/token/serialize.go \ go/go/token/token.go -go_go_types_files = \ - go/go/types/api.go \ - go/go/types/builtins.go \ - go/go/types/check.go \ - go/go/types/const.go \ - go/go/types/conversions.go \ - go/go/types/errors.go \ - go/go/types/exportdata.go \ - go/go/types/expr.go \ - go/go/types/gcimporter.go \ - go/go/types/objects.go \ - go/go/types/operand.go \ - go/go/types/predicates.go \ - go/go/types/resolve.go \ - go/go/types/scope.go \ - go/go/types/stmt.go \ - go/go/types/types.go \ - go/go/types/universe.go - go_hash_adler32_files = \ go/hash/adler32/adler32.go @@ -1692,6 +1592,10 @@ go_net_http_cgi_files = \ go/net/http/cgi/child.go \ go/net/http/cgi/host.go +go_net_http_cookiejar_files = \ + go/net/http/cookiejar/jar.go \ + go/net/http/cookiejar/punycode.go + go_net_http_fcgi_files = \ go/net/http/fcgi/child.go \ go/net/http/fcgi/fcgi.go @@ -1709,11 +1613,6 @@ go_net_http_httputil_files = \ go/net/http/httputil/persist.go \ go/net/http/httputil/reverseproxy.go -go_old_netchan_files = \ - go/old/netchan/common.go \ - go/old/netchan/export.go \ - go/old/netchan/import.go - go_old_regexp_files = \ go/old/regexp/regexp.go @@ -1756,6 +1655,7 @@ go_net_rpc_jsonrpc_files = \ go/net/rpc/jsonrpc/server.go go_runtime_debug_files = \ + go/runtime/debug/garbage.go \ go/runtime/debug/stack.go go_runtime_pprof_files = \ @@ -2005,17 +1905,8 @@ libgo_go_objs = \ encoding/json.lo \ encoding/pem.lo \ encoding/xml.lo \ - exp/cookiejar.lo \ - exp/ebnf.lo \ - exp/html.lo \ - exp/html/atom.lo \ - exp/locale/collate.lo \ - exp/locale/collate/build.lo \ - exp/norm.lo \ exp/proxy.lo \ - exp/ssa.lo \ exp/terminal.lo \ - exp/utf8string.lo \ html/template.lo \ go/ast.lo \ go/build.lo \ @@ -2025,12 +1916,12 @@ libgo_go_objs = \ go/printer.lo \ go/scanner.lo \ go/token.lo \ - go/types.lo \ hash/adler32.lo \ hash/crc32.lo \ hash/crc64.lo \ hash/fnv.lo \ net/http/cgi.lo \ + net/http/cookiejar.lo \ net/http/fcgi.lo \ net/http/httptest.lo \ net/http/httputil.lo \ @@ -2054,7 +1945,6 @@ libgo_go_objs = \ net/smtp.lo \ net/textproto.lo \ net/url.lo \ - old/netchan.lo \ old/regexp.lo \ old/template.lo \ os/exec.lo \ @@ -2185,10 +2075,6 @@ BUILDGOX = \ f=`echo $< | sed -e 's/.lo$$/.o/'`; \ $(OBJCOPY) -j .go_export $$f $@.tmp && mv -f $@.tmp $@ -@LIBGO_IS_LINUX_FALSE@exp_inotify_check = - -# exp_inotify_check = exp/inotify/check -@LIBGO_IS_LINUX_TRUE@exp_inotify_check = TEST_PACKAGES = \ bufio/check \ bytes/check \ @@ -2259,17 +2145,8 @@ TEST_PACKAGES = \ encoding/json/check \ encoding/pem/check \ encoding/xml/check \ - exp/cookiejar/check \ - exp/ebnf/check \ - exp/html/check \ - exp/html/atom/check \ - $(exp_inotify_check) \ - exp/locale/collate/check \ - exp/locale/collate/build/check \ - exp/norm/check \ exp/proxy/check \ exp/terminal/check \ - exp/utf8string/check \ html/template/check \ go/ast/check \ $(go_build_check_omitted_since_it_calls_6g) \ @@ -2279,7 +2156,6 @@ TEST_PACKAGES = \ go/printer/check \ go/scanner/check \ go/token/check \ - go/types/check \ hash/adler32/check \ hash/crc32/check \ hash/crc64/check \ @@ -2297,6 +2173,7 @@ TEST_PACKAGES = \ mime/multipart/check \ net/http/check \ net/http/cgi/check \ + net/http/cookiejar/check \ net/http/fcgi/check \ net/http/httptest/check \ net/http/httputil/check \ @@ -2306,7 +2183,6 @@ TEST_PACKAGES = \ net/textproto/check \ net/url/check \ net/rpc/jsonrpc/check \ - old/netchan/check \ old/regexp/check \ old/template/check \ os/exec/check \ @@ -2547,6 +2423,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mprof.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msize.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_epoll.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_kqueue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netpoll_stub.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parfor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@ @@ -3167,6 +3047,27 @@ msize.lo: runtime/msize.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c +netpoll_stub.lo: runtime/netpoll_stub.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_stub.lo -MD -MP -MF $(DEPDIR)/netpoll_stub.Tpo -c -o netpoll_stub.lo `test -f 'runtime/netpoll_stub.c' || echo '$(srcdir)/'`runtime/netpoll_stub.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/netpoll_stub.Tpo $(DEPDIR)/netpoll_stub.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/netpoll_stub.c' object='netpoll_stub.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_stub.lo `test -f 'runtime/netpoll_stub.c' || echo '$(srcdir)/'`runtime/netpoll_stub.c + +netpoll_kqueue.lo: runtime/netpoll_kqueue.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_kqueue.lo -MD -MP -MF $(DEPDIR)/netpoll_kqueue.Tpo -c -o netpoll_kqueue.lo `test -f 'runtime/netpoll_kqueue.c' || echo '$(srcdir)/'`runtime/netpoll_kqueue.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/netpoll_kqueue.Tpo $(DEPDIR)/netpoll_kqueue.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/netpoll_kqueue.c' object='netpoll_kqueue.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_kqueue.lo `test -f 'runtime/netpoll_kqueue.c' || echo '$(srcdir)/'`runtime/netpoll_kqueue.c + +netpoll_epoll.lo: runtime/netpoll_epoll.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netpoll_epoll.lo -MD -MP -MF $(DEPDIR)/netpoll_epoll.Tpo -c -o netpoll_epoll.lo `test -f 'runtime/netpoll_epoll.c' || echo '$(srcdir)/'`runtime/netpoll_epoll.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/netpoll_epoll.Tpo $(DEPDIR)/netpoll_epoll.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/netpoll_epoll.c' object='netpoll_epoll.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netpoll_epoll.lo `test -f 'runtime/netpoll_epoll.c' || echo '$(srcdir)/'`runtime/netpoll_epoll.c + panic.lo: runtime/panic.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT panic.lo -MD -MP -MF $(DEPDIR)/panic.Tpo -c -o panic.lo `test -f 'runtime/panic.c' || echo '$(srcdir)/'`runtime/panic.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/panic.Tpo $(DEPDIR)/panic.Plo @@ -3510,66 +3411,6 @@ uninstall-toolexeclibgoexpDATA: test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(toolexeclibgoexpdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(toolexeclibgoexpdir)" && rm -f $$files -install-toolexeclibgoexphtmlDATA: $(toolexeclibgoexphtml_DATA) - @$(NORMAL_INSTALL) - test -z "$(toolexeclibgoexphtmldir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexphtmldir)" - @list='$(toolexeclibgoexphtml_DATA)'; test -n "$(toolexeclibgoexphtmldir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexphtmldir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexphtmldir)" || exit $$?; \ - done - -uninstall-toolexeclibgoexphtmlDATA: - @$(NORMAL_UNINSTALL) - @list='$(toolexeclibgoexphtml_DATA)'; test -n "$(toolexeclibgoexphtmldir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(toolexeclibgoexphtmldir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(toolexeclibgoexphtmldir)" && rm -f $$files -install-toolexeclibgoexplocaleDATA: $(toolexeclibgoexplocale_DATA) - @$(NORMAL_INSTALL) - test -z "$(toolexeclibgoexplocaledir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexplocaledir)" - @list='$(toolexeclibgoexplocale_DATA)'; test -n "$(toolexeclibgoexplocaledir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexplocaledir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexplocaledir)" || exit $$?; \ - done - -uninstall-toolexeclibgoexplocaleDATA: - @$(NORMAL_UNINSTALL) - @list='$(toolexeclibgoexplocale_DATA)'; test -n "$(toolexeclibgoexplocaledir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(toolexeclibgoexplocaledir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(toolexeclibgoexplocaledir)" && rm -f $$files -install-toolexeclibgoexplocalecollateDATA: $(toolexeclibgoexplocalecollate_DATA) - @$(NORMAL_INSTALL) - test -z "$(toolexeclibgoexplocalecollatedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" - @list='$(toolexeclibgoexplocalecollate_DATA)'; test -n "$(toolexeclibgoexplocalecollatedir)" || list=; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexplocalecollatedir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" || exit $$?; \ - done - -uninstall-toolexeclibgoexplocalecollateDATA: - @$(NORMAL_UNINSTALL) - @list='$(toolexeclibgoexplocalecollate_DATA)'; test -n "$(toolexeclibgoexplocalecollatedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(toolexeclibgoexplocalecollatedir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" && rm -f $$files install-toolexeclibgogoDATA: $(toolexeclibgogo_DATA) @$(NORMAL_INSTALL) test -z "$(toolexeclibgogodir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgogodir)" @@ -4151,7 +3992,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \ config.h installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgoexphtmldir)" "$(DESTDIR)$(toolexeclibgoexplocaledir)" "$(DESTDIR)$(toolexeclibgoexplocalecollatedir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \ + for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -4222,9 +4063,6 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \ install-toolexeclibgodatabasesqlDATA \ install-toolexeclibgodebugDATA \ install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \ - install-toolexeclibgoexphtmlDATA \ - install-toolexeclibgoexplocaleDATA \ - install-toolexeclibgoexplocalecollateDATA \ install-toolexeclibgogoDATA install-toolexeclibgohashDATA \ install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \ install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \ @@ -4290,11 +4128,8 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \ uninstall-toolexeclibgodatabasesqlDATA \ uninstall-toolexeclibgodebugDATA \ uninstall-toolexeclibgoencodingDATA \ - uninstall-toolexeclibgoexpDATA \ - uninstall-toolexeclibgoexphtmlDATA \ - uninstall-toolexeclibgoexplocaleDATA \ - uninstall-toolexeclibgoexplocalecollateDATA \ - uninstall-toolexeclibgogoDATA uninstall-toolexeclibgohashDATA \ + uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \ + uninstall-toolexeclibgohashDATA \ uninstall-toolexeclibgohtmlDATA \ uninstall-toolexeclibgoimageDATA \ uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \ @@ -4339,9 +4174,6 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \ install-toolexeclibgodatabasesqlDATA \ install-toolexeclibgodebugDATA \ install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \ - install-toolexeclibgoexphtmlDATA \ - install-toolexeclibgoexplocaleDATA \ - install-toolexeclibgoexplocalecollateDATA \ install-toolexeclibgogoDATA install-toolexeclibgohashDATA \ install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \ install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \ @@ -4371,11 +4203,8 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \ uninstall-toolexeclibgodatabasesqlDATA \ uninstall-toolexeclibgodebugDATA \ uninstall-toolexeclibgoencodingDATA \ - uninstall-toolexeclibgoexpDATA \ - uninstall-toolexeclibgoexphtmlDATA \ - uninstall-toolexeclibgoexplocaleDATA \ - uninstall-toolexeclibgoexplocalecollateDATA \ - uninstall-toolexeclibgogoDATA uninstall-toolexeclibgohashDATA \ + uninstall-toolexeclibgoexpDATA uninstall-toolexeclibgogoDATA \ + uninstall-toolexeclibgohashDATA \ uninstall-toolexeclibgohtmlDATA \ uninstall-toolexeclibgoimageDATA \ uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \ @@ -4408,6 +4237,10 @@ mprof.c: $(srcdir)/runtime/mprof.goc goc2c ./goc2c $< > $@.tmp mv -f $@.tmp $@ +netpoll.c: $(srcdir)/runtime/netpoll.goc goc2c + ./goc2c $< > $@.tmp + mv -f $@.tmp $@ + reflect.c: $(srcdir)/runtime/reflect.goc goc2c ./goc2c $< > $@.tmp mv -f $@.tmp $@ @@ -5163,69 +4996,6 @@ encoding/xml/check: $(CHECK_DEPS) @$(CHECK) .PHONY: encoding/xml/check -@go_include@ exp/cookiejar.lo.dep -exp/cookiejar.lo.dep: $(go_exp_cookiejar_files) - $(BUILDDEPS) -exp/cookiejar.lo: $(go_exp_cookiejar_files) - $(BUILDPACKAGE) -exp/cookiejar/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/cookiejar/check - -@go_include@ exp/ebnf.lo.dep -exp/ebnf.lo.dep: $(go_exp_ebnf_files) - $(BUILDDEPS) -exp/ebnf.lo: $(go_exp_ebnf_files) - $(BUILDPACKAGE) -exp/ebnf/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/ebnf/check - -@go_include@ exp/html.lo.dep -exp/html.lo.dep: $(go_exp_html_files) - $(BUILDDEPS) -exp/html.lo: $(go_exp_html_files) - $(BUILDPACKAGE) -exp/html/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/html/check - -@go_include@ exp/html/atom.lo.dep -exp/html/atom.lo.dep: $(go_exp_html_atom_files) - $(BUILDDEPS) -exp/html/atom.lo: $(go_exp_html_atom_files) - $(BUILDPACKAGE) -exp/html/atom/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/html/atom/check - -@go_include@ exp/locale/collate.lo.dep -exp/locale/collate.lo.dep: $(go_exp_locale_collate_files) - $(BUILDDEPS) -exp/locale/collate.lo: $(go_exp_locale_collate_files) - $(BUILDPACKAGE) -exp/locale/collate/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/locale/collate/check - -@go_include@ exp/locale/collate/build.lo.dep -exp/locale/collate/build.lo.dep: $(go_exp_locale_collate_build_files) - $(BUILDDEPS) -exp/locale/collate/build.lo: $(go_exp_locale_collate_build_files) - $(BUILDPACKAGE) -exp/locale/collate/build/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/locale/collate/build/check - -@go_include@ exp/norm.lo.dep -exp/norm.lo.dep: $(go_exp_norm_files) - $(BUILDDEPS) -exp/norm.lo: $(go_exp_norm_files) - $(BUILDPACKAGE) -exp/norm/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/norm/check - @go_include@ exp/proxy.lo.dep exp/proxy.lo.dep: $(go_exp_proxy_files) $(BUILDDEPS) @@ -5235,15 +5005,6 @@ exp/proxy/check: $(CHECK_DEPS) @$(CHECK) .PHONY: exp/proxy/check -@go_include@ exp/ssa.lo.dep -exp/ssa.lo.dep: $(go_exp_ssa_files) - $(BUILDDEPS) -exp/ssa.lo: $(go_exp_ssa_files) - $(BUILDPACKAGE) -exp/ssa/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/ssa/check - @go_include@ exp/terminal.lo.dep exp/terminal.lo.dep: $(go_exp_terminal_files) $(BUILDDEPS) @@ -5253,24 +5014,6 @@ exp/terminal/check: $(CHECK_DEPS) @$(CHECK) .PHONY: exp/terminal/check -@go_include@ exp/utf8string.lo.dep -exp/utf8string.lo.dep: $(go_exp_utf8string_files) - $(BUILDDEPS) -exp/utf8string.lo: $(go_exp_utf8string_files) - $(BUILDPACKAGE) -exp/utf8string/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/utf8string/check - -@go_include@ exp/inotify.lo.dep -exp/inotify.lo.dep: $(go_exp_inotify_files) - $(BUILDDEPS) -exp/inotify.lo: $(go_exp_inotify_files) - $(BUILDPACKAGE) -exp/inotify/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: exp/inotify/check - @go_include@ html/template.lo.dep html/template.lo.dep: $(go_html_template_files) $(BUILDDEPS) @@ -5361,15 +5104,6 @@ go/token/check: $(CHECK_DEPS) @$(CHECK) .PHONY: go/token/check -@go_include@ go/types.lo.dep -go/types.lo.dep: $(go_go_types_files) - $(BUILDDEPS) -go/types.lo: $(go_go_types_files) - $(BUILDPACKAGE) -go/types/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: go/types/check - @go_include@ hash/adler32.lo.dep hash/adler32.lo.dep: $(go_hash_adler32_files) $(BUILDDEPS) @@ -5580,6 +5314,15 @@ net/http/cgi/check: $(CHECK_DEPS) @$(CHECK) .PHONY: net/http/cgi/check +@go_include@ net/http/cookiejar.lo.dep +net/http/cookiejar.lo.dep: $(go_net_http_cookiejar_files) + $(BUILDDEPS) +net/http/cookiejar.lo: $(go_net_http_cookiejar_files) + $(BUILDPACKAGE) +net/http/cookiejar/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: net/http/cookiejar/check + @go_include@ net/http/fcgi.lo.dep net/http/fcgi.lo.dep: $(go_net_http_fcgi_files) $(BUILDDEPS) @@ -5625,15 +5368,6 @@ net/rpc/jsonrpc/check: $(CHECK_DEPS) @$(CHECK) .PHONY: net/rpc/jsonrpc/check -@go_include@ old/netchan.lo.dep -old/netchan.lo.dep: $(go_old_netchan_files) - $(BUILDDEPS) -old/netchan.lo: $(go_old_netchan_files) - $(BUILDPACKAGE) -old/netchan/check: $(CHECK_DEPS) - @$(CHECK) -.PHONY: old/netchan/check - @go_include@ old/regexp.lo.dep old/regexp.lo.dep: $(go_old_regexp_files) $(BUILDDEPS) @@ -5974,30 +5708,10 @@ encoding/pem.gox: encoding/pem.lo encoding/xml.gox: encoding/xml.lo $(BUILDGOX) -exp/cookiejar.gox: exp/cookiejar.lo - $(BUILDGOX) -exp/ebnf.gox: exp/ebnf.lo - $(BUILDGOX) -exp/html.gox: exp/html.lo - $(BUILDGOX) -exp/html/atom.gox: exp/html/atom.lo - $(BUILDGOX) -exp/inotify.gox: exp/inotify.lo - $(BUILDGOX) -exp/locale/collate.gox: exp/locale/collate.lo - $(BUILDGOX) -exp/locale/collate/build.gox: exp/locale/collate/build.lo - $(BUILDGOX) -exp/norm.gox: exp/norm.lo - $(BUILDGOX) exp/proxy.gox: exp/proxy.lo $(BUILDGOX) -exp/ssa.gox: exp/ssa.lo - $(BUILDGOX) exp/terminal.gox: exp/terminal.lo $(BUILDGOX) -exp/utf8string.gox: exp/utf8string.lo - $(BUILDGOX) html/template.gox: html/template.lo $(BUILDGOX) @@ -6018,8 +5732,6 @@ go/scanner.gox: go/scanner.lo $(BUILDGOX) go/token.gox: go/token.lo $(BUILDGOX) -go/types.gox: go/types.lo - $(BUILDGOX) hash/adler32.gox: hash/adler32.lo $(BUILDGOX) @@ -6075,6 +5787,8 @@ net/url.gox: net/url.lo net/http/cgi.gox: net/http/cgi.lo $(BUILDGOX) +net/http/cookiejar.gox: net/http/cookiejar.lo + $(BUILDGOX) net/http/fcgi.gox: net/http/fcgi.lo $(BUILDGOX) net/http/httptest.gox: net/http/httptest.lo @@ -6087,8 +5801,6 @@ net/http/pprof.gox: net/http/pprof.lo net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo $(BUILDGOX) -old/netchan.gox: old/netchan.lo - $(BUILDGOX) old/regexp.gox: old/regexp.lo $(BUILDGOX) old/template.gox: old/template.lo diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go index 921b9fe9bdd..60d207c4897 100644 --- a/libgo/go/archive/tar/common.go +++ b/libgo/go/archive/tar/common.go @@ -9,12 +9,14 @@ // References: // http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 // http://www.gnu.org/software/tar/manual/html_node/Standard.html +// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html package tar import ( "errors" "fmt" "os" + "path" "time" ) @@ -33,6 +35,8 @@ const ( TypeCont = '7' // reserved TypeXHeader = 'x' // extended header TypeXGlobalHeader = 'g' // global extended header + TypeGNULongName = 'L' // Next file has a long name + TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name ) // A Header represents a single header in a tar archive. @@ -54,55 +58,172 @@ type Header struct { ChangeTime time.Time // status change time } +// File name constants from the tar spec. +const ( + fileNameSize = 100 // Maximum number of bytes in a standard tar name. + fileNamePrefixSize = 155 // Maximum number of ustar extension bytes. +) + +// FileInfo returns an os.FileInfo for the Header. +func (h *Header) FileInfo() os.FileInfo { + return headerFileInfo{h} +} + +// headerFileInfo implements os.FileInfo. +type headerFileInfo struct { + h *Header +} + +func (fi headerFileInfo) Size() int64 { return fi.h.Size } +func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } +func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime } +func (fi headerFileInfo) Sys() interface{} { return fi.h } + +// Name returns the base name of the file. +func (fi headerFileInfo) Name() string { + if fi.IsDir() { + return path.Clean(fi.h.Name) + } + return fi.h.Name +} + +// Mode returns the permission and mode bits for the headerFileInfo. +func (fi headerFileInfo) Mode() (mode os.FileMode) { + // Set file permission bits. + mode = os.FileMode(fi.h.Mode).Perm() + + // Set setuid, setgid and sticky bits. + if fi.h.Mode&c_ISUID != 0 { + // setuid + mode |= os.ModeSetuid + } + if fi.h.Mode&c_ISGID != 0 { + // setgid + mode |= os.ModeSetgid + } + if fi.h.Mode&c_ISVTX != 0 { + // sticky + mode |= os.ModeSticky + } + + // Set file mode bits. + // clear perm, setuid, setgid and sticky bits. + m := os.FileMode(fi.h.Mode) &^ 07777 + if m == c_ISDIR { + // directory + mode |= os.ModeDir + } + if m == c_ISFIFO { + // named pipe (FIFO) + mode |= os.ModeNamedPipe + } + if m == c_ISLNK { + // symbolic link + mode |= os.ModeSymlink + } + if m == c_ISBLK { + // device file + mode |= os.ModeDevice + } + if m == c_ISCHR { + // Unix character device + mode |= os.ModeDevice + mode |= os.ModeCharDevice + } + if m == c_ISSOCK { + // Unix domain socket + mode |= os.ModeSocket + } + + switch fi.h.Typeflag { + case TypeLink, TypeSymlink: + // hard link, symbolic link + mode |= os.ModeSymlink + case TypeChar: + // character device node + mode |= os.ModeDevice + mode |= os.ModeCharDevice + case TypeBlock: + // block device node + mode |= os.ModeDevice + case TypeDir: + // directory + mode |= os.ModeDir + case TypeFifo: + // fifo node + mode |= os.ModeNamedPipe + } + + return mode +} + // sysStat, if non-nil, populates h from system-dependent fields of fi. var sysStat func(fi os.FileInfo, h *Header) error // Mode constants from the tar spec. const ( - c_ISDIR = 040000 - c_ISFIFO = 010000 - c_ISREG = 0100000 - c_ISLNK = 0120000 - c_ISBLK = 060000 - c_ISCHR = 020000 - c_ISSOCK = 0140000 + c_ISUID = 04000 // Set uid + c_ISGID = 02000 // Set gid + c_ISVTX = 01000 // Save text (sticky bit) + c_ISDIR = 040000 // Directory + c_ISFIFO = 010000 // FIFO + c_ISREG = 0100000 // Regular file + c_ISLNK = 0120000 // Symbolic link + c_ISBLK = 060000 // Block special file + c_ISCHR = 020000 // Character special file + c_ISSOCK = 0140000 // Socket ) // FileInfoHeader creates a partially-populated Header from fi. // If fi describes a symlink, FileInfoHeader records link as the link target. +// If fi describes a directory, a slash is appended to the name. func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { if fi == nil { return nil, errors.New("tar: FileInfo is nil") } + fm := fi.Mode() h := &Header{ Name: fi.Name(), ModTime: fi.ModTime(), - Mode: int64(fi.Mode().Perm()), // or'd with c_IS* constants later + Mode: int64(fm.Perm()), // or'd with c_IS* constants later } switch { - case fi.Mode()&os.ModeType == 0: + case fm.IsRegular(): h.Mode |= c_ISREG h.Typeflag = TypeReg h.Size = fi.Size() case fi.IsDir(): h.Typeflag = TypeDir h.Mode |= c_ISDIR - case fi.Mode()&os.ModeSymlink != 0: + h.Name += "/" + case fm&os.ModeSymlink != 0: h.Typeflag = TypeSymlink h.Mode |= c_ISLNK h.Linkname = link - case fi.Mode()&os.ModeDevice != 0: - if fi.Mode()&os.ModeCharDevice != 0 { + case fm&os.ModeDevice != 0: + if fm&os.ModeCharDevice != 0 { h.Mode |= c_ISCHR h.Typeflag = TypeChar } else { h.Mode |= c_ISBLK h.Typeflag = TypeBlock } - case fi.Mode()&os.ModeSocket != 0: + case fm&os.ModeNamedPipe != 0: + h.Typeflag = TypeFifo + h.Mode |= c_ISFIFO + case fm&os.ModeSocket != 0: h.Mode |= c_ISSOCK default: - return nil, fmt.Errorf("archive/tar: unknown file mode %v", fi.Mode()) + return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm) + } + if fm&os.ModeSetuid != 0 { + h.Mode |= c_ISUID + } + if fm&os.ModeSetgid != 0 { + h.Mode |= c_ISGID + } + if fm&os.ModeSticky != 0 { + h.Mode |= c_ISVTX } if sysStat != nil { return h, sysStat(fi, h) diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go index ad825c6be0b..05f82a40dd9 100644 --- a/libgo/go/archive/tar/reader.go +++ b/libgo/go/archive/tar/reader.go @@ -14,6 +14,7 @@ import ( "io/ioutil" "os" "strconv" + "strings" "time" ) @@ -21,24 +22,12 @@ var ( ErrHeader = errors.New("archive/tar: invalid tar header") ) +const maxNanoSecondIntSize = 9 + // A Reader provides sequential access to the contents of a tar archive. // A tar archive consists of a sequence of files. // The Next method advances to the next file in the archive (including the first), // and then it can be treated as an io.Reader to access the file's data. -// -// Example: -// tr := tar.NewReader(r) -// for { -// hdr, err := tr.Next() -// if err == io.EOF { -// // end of tar archive -// break -// } -// if err != nil { -// // handle error -// } -// io.Copy(data, tr) -// } type Reader struct { r io.Reader err error @@ -55,13 +44,183 @@ func (tr *Reader) Next() (*Header, error) { if tr.err == nil { tr.skipUnread() } - if tr.err == nil { + if tr.err != nil { + return hdr, tr.err + } + hdr = tr.readHeader() + if hdr == nil { + return hdr, tr.err + } + // Check for PAX/GNU header. + switch hdr.Typeflag { + case TypeXHeader: + // PAX extended header + headers, err := parsePAX(tr) + if err != nil { + return nil, err + } + // We actually read the whole file, + // but this skips alignment padding + tr.skipUnread() hdr = tr.readHeader() + mergePAX(hdr, headers) + return hdr, nil + case TypeGNULongName: + // We have a GNU long name header. Its contents are the real file name. + realname, err := ioutil.ReadAll(tr) + if err != nil { + return nil, err + } + hdr, err := tr.Next() + hdr.Name = cString(realname) + return hdr, err + case TypeGNULongLink: + // We have a GNU long link header. + realname, err := ioutil.ReadAll(tr) + if err != nil { + return nil, err + } + hdr, err := tr.Next() + hdr.Linkname = cString(realname) + return hdr, err } return hdr, tr.err } -// Parse bytes as a NUL-terminated C-style string. +// mergePAX merges well known headers according to PAX standard. +// In general headers with the same name as those found +// in the header struct overwrite those found in the header +// struct with higher precision or longer values. Esp. useful +// for name and linkname fields. +func mergePAX(hdr *Header, headers map[string]string) error { + for k, v := range headers { + switch k { + case "path": + hdr.Name = v + case "linkpath": + hdr.Linkname = v + case "gname": + hdr.Gname = v + case "uname": + hdr.Uname = v + case "uid": + uid, err := strconv.ParseInt(v, 10, 0) + if err != nil { + return err + } + hdr.Uid = int(uid) + case "gid": + gid, err := strconv.ParseInt(v, 10, 0) + if err != nil { + return err + } + hdr.Gid = int(gid) + case "atime": + t, err := parsePAXTime(v) + if err != nil { + return err + } + hdr.AccessTime = t + case "mtime": + t, err := parsePAXTime(v) + if err != nil { + return err + } + hdr.ModTime = t + case "ctime": + t, err := parsePAXTime(v) + if err != nil { + return err + } + hdr.ChangeTime = t + case "size": + size, err := strconv.ParseInt(v, 10, 0) + if err != nil { + return err + } + hdr.Size = int64(size) + } + + } + return nil +} + +// parsePAXTime takes a string of the form %d.%d as described in +// the PAX specification. +func parsePAXTime(t string) (time.Time, error) { + buf := []byte(t) + pos := bytes.IndexByte(buf, '.') + var seconds, nanoseconds int64 + var err error + if pos == -1 { + seconds, err = strconv.ParseInt(t, 10, 0) + if err != nil { + return time.Time{}, err + } + } else { + seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0) + if err != nil { + return time.Time{}, err + } + nano_buf := string(buf[pos+1:]) + // Pad as needed before converting to a decimal. + // For example .030 -> .030000000 -> 30000000 nanoseconds + if len(nano_buf) < maxNanoSecondIntSize { + // Right pad + nano_buf += strings.Repeat("0", maxNanoSecondIntSize-len(nano_buf)) + } else if len(nano_buf) > maxNanoSecondIntSize { + // Right truncate + nano_buf = nano_buf[:maxNanoSecondIntSize] + } + nanoseconds, err = strconv.ParseInt(string(nano_buf), 10, 0) + if err != nil { + return time.Time{}, err + } + } + ts := time.Unix(seconds, nanoseconds) + return ts, nil +} + +// parsePAX parses PAX headers. +// If an extended header (type 'x') is invalid, ErrHeader is returned +func parsePAX(r io.Reader) (map[string]string, error) { + buf, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + headers := make(map[string]string) + // Each record is constructed as + // "%d %s=%s\n", length, keyword, value + for len(buf) > 0 { + // or the header was empty to start with. + var sp int + // The size field ends at the first space. + sp = bytes.IndexByte(buf, ' ') + if sp == -1 { + return nil, ErrHeader + } + // Parse the first token as a decimal integer. + n, err := strconv.ParseInt(string(buf[:sp]), 10, 0) + if err != nil { + return nil, ErrHeader + } + // Extract everything between the decimal and the n -1 on the + // beginning to to eat the ' ', -1 on the end to skip the newline. + var record []byte + record, buf = buf[sp+1:n-1], buf[n:] + // The first equals is guaranteed to mark the end of the key. + // Everything else is value. + eq := bytes.IndexByte(record, '=') + if eq == -1 { + return nil, ErrHeader + } + key, value := record[:eq], record[eq+1:] + headers[string(key)] = string(value) + } + return headers, nil +} + +// cString parses bytes as a NUL-terminated C-style string. // If a NUL byte is not found then the whole slice is returned as a string. func cString(b []byte) string { n := 0 @@ -99,7 +258,7 @@ func (tr *Reader) octal(b []byte) int64 { return int64(x) } -// Skip any unread bytes in the existing file entry, as well as any alignment padding. +// skipUnread skips any unread bytes in the existing file entry, as well as any alignment padding. func (tr *Reader) skipUnread() { nr := tr.nb + tr.pad // number of bytes to skip tr.nb, tr.pad = 0, 0 diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go index 0a8646c393f..9a196823713 100644 --- a/libgo/go/archive/tar/reader_test.go +++ b/libgo/go/archive/tar/reader_test.go @@ -10,6 +10,8 @@ import ( "fmt" "io" "os" + "reflect" + "strings" "testing" "time" ) @@ -108,6 +110,38 @@ var untarTests = []*untarTest{ }, }, }, + { + file: "testdata/pax.tar", + headers: []*Header{ + { + Name: "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100", + Mode: 0664, + Uid: 1000, + Gid: 1000, + Uname: "shane", + Gname: "shane", + Size: 7, + ModTime: time.Unix(1350244992, 23960108), + ChangeTime: time.Unix(1350244992, 23960108), + AccessTime: time.Unix(1350244992, 23960108), + Typeflag: TypeReg, + }, + { + Name: "a/b", + Mode: 0777, + Uid: 1000, + Gid: 1000, + Uname: "shane", + Gname: "shane", + Size: 0, + ModTime: time.Unix(1350266320, 910238425), + ChangeTime: time.Unix(1350266320, 910238425), + AccessTime: time.Unix(1350266320, 910238425), + Typeflag: TypeSymlink, + Linkname: "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100", + }, + }, + }, } func TestReader(t *testing.T) { @@ -133,7 +167,7 @@ testLoop: } hdr, err := tr.Next() if err == io.EOF { - break + continue testLoop } if hdr != nil || err != nil { t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err) @@ -260,3 +294,73 @@ func TestNonSeekable(t *testing.T) { t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(test.headers), nread) } } + +func TestParsePAXHeader(t *testing.T) { + paxTests := [][3]string{ + {"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths + {"a", "a=name", "9 a=name\n"}, // Test case involving multiple acceptable length + {"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}} + for _, test := range paxTests { + key, expected, raw := test[0], test[1], test[2] + reader := bytes.NewBuffer([]byte(raw)) + headers, err := parsePAX(reader) + if err != nil { + t.Errorf("Couldn't parse correctly formatted headers: %v", err) + continue + } + if strings.EqualFold(headers[key], expected) { + t.Errorf("mtime header incorrectly parsed: got %s, wanted %s", headers[key], expected) + continue + } + trailer := make([]byte, 100) + n, err := reader.Read(trailer) + if err != io.EOF || n != 0 { + t.Error("Buffer wasn't consumed") + } + } + badHeader := bytes.NewBuffer([]byte("3 somelongkey=")) + if _, err := parsePAX(badHeader); err != ErrHeader { + t.Fatal("Unexpected success when parsing bad header") + } +} + +func TestParsePAXTime(t *testing.T) { + // Some valid PAX time values + timestamps := map[string]time.Time{ + "1350244992.023960108": time.Unix(1350244992, 23960108), // The commoon case + "1350244992.02396010": time.Unix(1350244992, 23960100), // Lower precision value + "1350244992.0239601089": time.Unix(1350244992, 23960108), // Higher precision value + "1350244992": time.Unix(1350244992, 0), // Low precision value + } + for input, expected := range timestamps { + ts, err := parsePAXTime(input) + if err != nil { + t.Fatal(err) + } + if !ts.Equal(expected) { + t.Fatalf("Time parsing failure %s %s", ts, expected) + } + } +} + +func TestMergePAX(t *testing.T) { + hdr := new(Header) + // Test a string, integer, and time based value. + headers := map[string]string{ + "path": "a/b/c", + "uid": "1000", + "mtime": "1350244992.023960108", + } + err := mergePAX(hdr, headers) + if err != nil { + t.Fatal(err) + } + want := &Header{ + Name: "a/b/c", + Uid: 1000, + ModTime: time.Unix(1350244992, 23960108), + } + if !reflect.DeepEqual(hdr, want) { + t.Errorf("incorrect merge: got %+v, want %+v", hdr, want) + } +} diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go index 7b190b6a8b2..dd6310313af 100644 --- a/libgo/go/archive/tar/tar_test.go +++ b/libgo/go/archive/tar/tar_test.go @@ -14,13 +14,13 @@ import ( ) func TestFileInfoHeader(t *testing.T) { - fi, err := os.Lstat("testdata/small.txt") + fi, err := os.Stat("testdata/small.txt") if err != nil { t.Fatal(err) } h, err := FileInfoHeader(fi, "") if err != nil { - t.Fatalf("on small.txt: %v", err) + t.Fatalf("FileInfoHeader: %v", err) } if g, e := h.Name, "small.txt"; g != e { t.Errorf("Name = %q; want %q", g, e) @@ -36,6 +36,30 @@ func TestFileInfoHeader(t *testing.T) { } } +func TestFileInfoHeaderDir(t *testing.T) { + fi, err := os.Stat("testdata") + if err != nil { + t.Fatal(err) + } + h, err := FileInfoHeader(fi, "") + if err != nil { + t.Fatalf("FileInfoHeader: %v", err) + } + if g, e := h.Name, "testdata/"; g != e { + t.Errorf("Name = %q; want %q", g, e) + } + // Ignoring c_ISGID for golang.org/issue/4867 + if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm())|c_ISDIR; g != e { + t.Errorf("Mode = %#o; want %#o", g, e) + } + if g, e := h.Size, int64(0); g != e { + t.Errorf("Size = %v; want %v", g, e) + } + if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) { + t.Errorf("ModTime = %v; want %v", g, e) + } +} + func TestFileInfoHeaderSymlink(t *testing.T) { h, err := FileInfoHeader(symlink{}, "some-target") if err != nil { @@ -98,3 +122,150 @@ func TestRoundTrip(t *testing.T) { t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data) } } + +type headerRoundTripTest struct { + h *Header + fm os.FileMode +} + +func TestHeaderRoundTrip(t *testing.T) { + golden := []headerRoundTripTest{ + // regular file. + { + h: &Header{ + Name: "test.txt", + Mode: 0644 | c_ISREG, + Size: 12, + ModTime: time.Unix(1360600916, 0), + Typeflag: TypeReg, + }, + fm: 0644, + }, + // hard link. + { + h: &Header{ + Name: "hard.txt", + Mode: 0644 | c_ISLNK, + Size: 0, + ModTime: time.Unix(1360600916, 0), + Typeflag: TypeLink, + }, + fm: 0644 | os.ModeSymlink, + }, + // symbolic link. + { + h: &Header{ + Name: "link.txt", + Mode: 0777 | c_ISLNK, + Size: 0, + ModTime: time.Unix(1360600852, 0), + Typeflag: TypeSymlink, + }, + fm: 0777 | os.ModeSymlink, + }, + // character device node. + { + h: &Header{ + Name: "dev/null", + Mode: 0666 | c_ISCHR, + Size: 0, + ModTime: time.Unix(1360578951, 0), + Typeflag: TypeChar, + }, + fm: 0666 | os.ModeDevice | os.ModeCharDevice, + }, + // block device node. + { + h: &Header{ + Name: "dev/sda", + Mode: 0660 | c_ISBLK, + Size: 0, + ModTime: time.Unix(1360578954, 0), + Typeflag: TypeBlock, + }, + fm: 0660 | os.ModeDevice, + }, + // directory. + { + h: &Header{ + Name: "dir/", + Mode: 0755 | c_ISDIR, + Size: 0, + ModTime: time.Unix(1360601116, 0), + Typeflag: TypeDir, + }, + fm: 0755 | os.ModeDir, + }, + // fifo node. + { + h: &Header{ + Name: "dev/initctl", + Mode: 0600 | c_ISFIFO, + Size: 0, + ModTime: time.Unix(1360578949, 0), + Typeflag: TypeFifo, + }, + fm: 0600 | os.ModeNamedPipe, + }, + // setuid. + { + h: &Header{ + Name: "bin/su", + Mode: 0755 | c_ISREG | c_ISUID, + Size: 23232, + ModTime: time.Unix(1355405093, 0), + Typeflag: TypeReg, + }, + fm: 0755 | os.ModeSetuid, + }, + // setguid. + { + h: &Header{ + Name: "group.txt", + Mode: 0750 | c_ISREG | c_ISGID, + Size: 0, + ModTime: time.Unix(1360602346, 0), + Typeflag: TypeReg, + }, + fm: 0750 | os.ModeSetgid, + }, + // sticky. + { + h: &Header{ + Name: "sticky.txt", + Mode: 0600 | c_ISREG | c_ISVTX, + Size: 7, + ModTime: time.Unix(1360602540, 0), + Typeflag: TypeReg, + }, + fm: 0600 | os.ModeSticky, + }, + } + + for i, g := range golden { + fi := g.h.FileInfo() + h2, err := FileInfoHeader(fi, "") + if err != nil { + t.Error(err) + continue + } + if got, want := h2.Name, g.h.Name; got != want { + t.Errorf("i=%d: Name: got %v, want %v", i, got, want) + } + if got, want := h2.Size, g.h.Size; got != want { + t.Errorf("i=%d: Size: got %v, want %v", i, got, want) + } + if got, want := h2.Mode, g.h.Mode; got != want { + t.Errorf("i=%d: Mode: got %o, want %o", i, got, want) + } + if got, want := fi.Mode(), g.fm; got != want { + t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want) + } + if got, want := h2.ModTime, g.h.ModTime; got != want { + t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want) + } + if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h { + t.Errorf("i=%d: Sys didn't return original *Header", i) + } + } +} diff --git a/libgo/go/archive/tar/testdata/pax.tar b/libgo/go/archive/tar/testdata/pax.tar new file mode 100644 index 0000000000000000000000000000000000000000..9bc24b6587d726c7fca4e533d9c61a3801a34688 GIT binary patch literal 10240 zcmeH~&u-H|5XOD(Q}_vz`9HIV-Z}CL1|qeBRwxNlAD?kbq{vMJQj94uds*3I@2-Ed zpXb|Q{eF0Qw;4Wdw!4)@_!@~t&7&b8A|a!oqM>78BOoLqCLtvwr=Z5b$i&RT%Er#Y zO+ZjcSVUAHn~8MUp(~vBV+cg7LjpEKCCE6D7E@EwTcMv_>l+&bbg`j1Cv0A776ym5t@+ zSt9MDBFtXbKY&m4pMN0f`l~hhD>#q(-`x$5n+q@eEPmAevA;0XTM8XMYkTvSmQ-t5 zkihVw{(qQ#_JjT})&KMa&-FhG0c8or{CPvw|Jf69WL!B2Wa1KoKYcMW6^2fg(@@ia-%40!5$*6oDd81d2cr_`3;w E2V3|JA^-pY literal 0 HcmV?d00001 diff --git a/libgo/go/archive/tar/testdata/ustar.tar b/libgo/go/archive/tar/testdata/ustar.tar new file mode 100644 index 0000000000000000000000000000000000000000..29679d9a305fc0293f31212541335af824ab32c7 GIT binary patch literal 2048 zcmYex%t_TNsVHHfAus>}GZPaA5N&Q|3Z@N=AbgM*P?o{a$k4#V#K6eR)QrKv#MIE( zgh9c8hHiozU0Pg{SOj!ZaYkZZDqIwk0aTWjhA9jefq29K;yD8YhMfGo^t{B}RQ&;E gz@3MSk&&8{lh1`qc2s;c1V%$(Gz3ONV7P_=0F fileNameSize || len(hdr.Linkname) > fileNameSize { + var err error + prefix, suffix, err = tw.splitUSTARLongName(hdr.Name) + // Either we were unable to pack the long name into ustar format + // or the link name is too long; use PAX headers. + if err == errNameTooLong || len(hdr.Linkname) > fileNameSize { + if err := tw.writePAXHeader(hdr); err != nil { + return err + } + } else if err != nil { + return err + } + } tw.nb = int64(hdr.Size) tw.pad = -tw.nb & (blockSize - 1) // blockSize is a power of two header := make([]byte, blockSize) s := slicer(header) - - // TODO(dsymonds): handle names longer than 100 chars - copy(s.next(100), []byte(hdr.Name)) + tw.cString(s.next(fileNameSize), suffix) // Handle out of range ModTime carefully. var modTime int64 @@ -159,11 +169,15 @@ func (tw *Writer) WriteHeader(hdr *Header) error { tw.cString(s.next(32), hdr.Gname) // 297:329 tw.numeric(s.next(8), hdr.Devmajor) // 329:337 tw.numeric(s.next(8), hdr.Devminor) // 337:345 - + tw.cString(s.next(155), prefix) // 345:500 // Use the GNU magic instead of POSIX magic if we used any GNU extensions. if tw.usedBinary { copy(header[257:265], []byte("ustar \x00")) } + // Use the ustar magic if we used ustar long names. + if len(prefix) > 0 { + copy(header[257:265], []byte("ustar\000")) + } // The chksum field is terminated by a NUL and a space. // This is different from the other octal fields. @@ -181,6 +195,78 @@ func (tw *Writer) WriteHeader(hdr *Header) error { return tw.err } +// writeUSTARLongName splits a USTAR long name hdr.Name. +// name must be < 256 characters. errNameTooLong is returned +// if hdr.Name can't be split. The splitting heuristic +// is compatible with gnu tar. +func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err error) { + length := len(name) + if length > fileNamePrefixSize+1 { + length = fileNamePrefixSize + 1 + } else if name[length-1] == '/' { + length-- + } + i := strings.LastIndex(name[:length], "/") + nlen := length - i - 1 + if i <= 0 || nlen > fileNameSize || nlen == 0 { + err = errNameTooLong + return + } + prefix, suffix = name[:i], name[i+1:] + return +} + +// writePaxHeader writes an extended pax header to the +// archive. +func (tw *Writer) writePAXHeader(hdr *Header) error { + // Prepare extended header + ext := new(Header) + ext.Typeflag = TypeXHeader + // Setting ModTime is required for reader parsing to + // succeed, and seems harmless enough. + ext.ModTime = hdr.ModTime + // The spec asks that we namespace our pseudo files + // with the current pid. + pid := os.Getpid() + dir, file := path.Split(hdr.Name) + ext.Name = path.Join(dir, + fmt.Sprintf("PaxHeaders.%d", pid), file)[0:100] + // Construct the body + var buf bytes.Buffer + if len(hdr.Name) > fileNameSize { + fmt.Fprint(&buf, paxHeader("path="+hdr.Name)) + } + if len(hdr.Linkname) > fileNameSize { + fmt.Fprint(&buf, paxHeader("linkpath="+hdr.Linkname)) + } + ext.Size = int64(len(buf.Bytes())) + if err := tw.WriteHeader(ext); err != nil { + return err + } + if _, err := tw.Write(buf.Bytes()); err != nil { + return err + } + if err := tw.Flush(); err != nil { + return err + } + return nil +} + +// paxHeader formats a single pax record, prefixing it with the appropriate length +func paxHeader(msg string) string { + const padding = 2 // Extra padding for space and newline + size := len(msg) + padding + size += len(strconv.Itoa(size)) + record := fmt.Sprintf("%d %s\n", size, msg) + if len(record) != size { + // Final adjustment if adding size increased + // the number of digits in size + size = len(record) + record = fmt.Sprintf("%d %s\n", size, msg) + } + return record +} + // Write writes to the current entry in the tar archive. // Write returns the error ErrWriteTooLong if more than // hdr.Size bytes are written after WriteHeader. diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go index a214e57b9fc..4cf7c72aff3 100644 --- a/libgo/go/archive/tar/writer_test.go +++ b/libgo/go/archive/tar/writer_test.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "io/ioutil" + "os" "strings" "testing" "testing/iotest" @@ -101,6 +102,27 @@ var writerTests = []*writerTest{ }, }, }, + // This file was produced using gnu tar 1.17 + // gnutar -b 4 --format=ustar (longname/)*15 + file.txt + { + file: "testdata/ustar.tar", + entries: []*writerTestEntry{ + { + header: &Header{ + Name: strings.Repeat("longname/", 15) + "file.txt", + Mode: 0644, + Uid: 0765, + Gid: 024, + Size: 06, + ModTime: time.Unix(1360135598, 0), + Typeflag: '0', + Uname: "shane", + Gname: "staff", + }, + contents: "hello\n", + }, + }, + }, } // Render byte array in a two-character hexadecimal string, spaced for easy visual inspection. @@ -180,3 +202,61 @@ testLoop: } } } + +func TestPax(t *testing.T) { + // Create an archive with a large name + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + hdr, err := FileInfoHeader(fileinfo, "") + if err != nil { + t.Fatalf("os.Stat: %v", err) + } + // Force a PAX long name to be written + longName := strings.Repeat("ab", 100) + contents := strings.Repeat(" ", int(hdr.Size)) + hdr.Name = longName + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if _, err = writer.Write([]byte(contents)); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Simple test to make sure PAX extensions are in effect + if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) { + t.Fatal("Expected at least one PAX header to be written.") + } + // Test that we can get a long name back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if hdr.Name != longName { + t.Fatal("Couldn't recover long file name") + } +} + +func TestPAXHeader(t *testing.T) { + medName := strings.Repeat("CD", 50) + longName := strings.Repeat("AB", 100) + paxTests := [][2]string{ + {"name=/etc/hosts", "19 name=/etc/hosts\n"}, + {"a=b", "6 a=b\n"}, // Single digit length + {"a=names", "11 a=names\n"}, // Test case involving carries + {"name=" + longName, fmt.Sprintf("210 name=%s\n", longName)}, + {"name=" + medName, fmt.Sprintf("110 name=%s\n", medName)}} + + for _, test := range paxTests { + key, expected := test[0], test[1] + if result := paxHeader(key); result != expected { + t.Fatalf("paxHeader: got %s, expected %s", result, expected) + } + } +} diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go index c10f29a8369..f19cf2d1f1e 100644 --- a/libgo/go/archive/zip/reader.go +++ b/libgo/go/archive/zip/reader.go @@ -353,6 +353,11 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) if err != nil { return nil, err } + + // Make sure directoryOffset points to somewhere in our file. + if o := int64(d.directoryOffset); o < 0 || o >= size { + return nil, ErrFormat + } return d, nil } @@ -407,7 +412,7 @@ func findSignatureInBlock(b []byte) int { if b[i] == 'P' && b[i+1] == 'K' && b[i+2] == 0x05 && b[i+3] == 0x06 { // n is length of comment n := int(b[i+directoryEndLen-2]) | int(b[i+directoryEndLen-1])<<8 - if n+directoryEndLen+i == len(b) { + if n+directoryEndLen+i <= len(b) { return i } } diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go index cf9c59c4b92..833ba28ad52 100644 --- a/libgo/go/archive/zip/reader_test.go +++ b/libgo/go/archive/zip/reader_test.go @@ -63,6 +63,24 @@ var tests = []ZipTest{ }, }, }, + { + Name: "test-trailing-junk.zip", + Comment: "This is a zipfile comment.", + File: []ZipTestFile{ + { + Name: "test.txt", + Content: []byte("This is a test text file.\n"), + Mtime: "09-05-10 12:12:02", + Mode: 0644, + }, + { + Name: "gophercolor16x16.png", + File: "gophercolor16x16.png", + Mtime: "09-05-10 15:52:58", + Mode: 0644, + }, + }, + }, { Name: "r.zip", Source: returnRecursiveZip, @@ -262,7 +280,7 @@ func readTestZip(t *testing.T, zt ZipTest) { } } if err != zt.Error { - t.Errorf("error=%v, want %v", err, zt.Error) + t.Errorf("%s: error=%v, want %v", zt.Name, err, zt.Error) return } diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go index ea067f3554f..73972d41cf0 100644 --- a/libgo/go/archive/zip/struct.go +++ b/libgo/go/archive/zip/struct.go @@ -64,8 +64,15 @@ const ( zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field ) +// FileHeader describes a file within a zip file. +// See the zip spec for details. type FileHeader struct { - Name string + // Name is the name of the file. + // It must be a relative path: it must not start with a drive + // letter (e.g. C:) or leading slash, and only forward slashes + // are allowed. + Name string + CreatorVersion uint16 ReaderVersion uint16 Flags uint16 diff --git a/libgo/go/archive/zip/testdata/test-trailing-junk.zip b/libgo/go/archive/zip/testdata/test-trailing-junk.zip new file mode 100644 index 0000000000000000000000000000000000000000..42281b4e3053eec7924b58d234d04e492c3baa38 GIT binary patch literal 1184 zcmWIWW@Zs#U|`^2XiQYKJ#hW)VM!oQ3M?YSP?B0)qE}K;5*otEz+CvJ$)^m6ODnh; z7+JnDGBAL3a-Te*6UMN}rFGJkM?wmLfr}l&aaaM)^pwV1FgBTd*)~VY5GrSri z$jrb1!XgYZ4C(m=8L36d`8oMThGrFpW_ksA>0oQD44Qqcff&u2&Hz7mUM?w+fxMm` zE&U=x?Zy@V2qPe0vcxr_Bsf2F!C6nVlf&(QE?5{rm?pSGb*exy9+#I&RurKk- z+m)0yRCPG=d-HHDZeo&8l5*8w*j(kQ)h25CKV`;*MHBS|=I94cI>i2RTbstM*llm) zO8IWizic_XckQR<_w%av+wcEed*5>UK?&z&H{O(96e0boH{+WCE(bu95f2^3EZ4O=VNZ?3)UvtyJg5QDRcf$^EI~Jki zWtQzJsL_x*GnsW)scd27+nNv&O9`(nP~TLZC!C)&dpmb9Gex+~DL%5m{kC!2{41u2r}!o#L;7=ONQ zE-qq{y7hnokNZ9E^>G%L>tA=N)+ZKnN{AiY63=$`mQ27(iv*7buak|7iv?tIZF@fl zt>|OAAsR5{#f{tFon;*@eKst4U%}L6{!DE$Q;-Gc;z`Q`4>jq0{kyW^?3@=d0sB55 zxoLcI^%PC5#tAeEd>m$^DR^;2N$vDP24)a*LyE?_;6T$0ZaWgUlR!) zO)1Y`?`E^OggslIl9kNpY|u0@YV$J_L(}Dqa{cO(OH|YIR<91PW~;8;CG9SvxT%P1 zf&1?rTi;(l9{BL-LFV7-o3%9b_5H&Yx{{nGExEP)?O%T1_U}*5o%1=o!$7pc+~7{P zVEy`CyQ(f_ZB6^{)1;6Rw%g;&&eO(;vcI48f3W$#VE69d#v5C|RN3w=iCp_vEP-JK z2X8m?^Q2e6G|k}Y>gTe~DWNIAn~_P58CTww04Zev=23TwQdKa(&kYWhQ$ShU>qC|zN%!0JcoK%J6 Y{M_8syb`_Q{M=N9y!^c4R3PF40F)}f^8f$< literal 0 HcmV?d00001 diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go index 4c696e1529e..e9f147cea66 100644 --- a/libgo/go/archive/zip/writer.go +++ b/libgo/go/archive/zip/writer.go @@ -163,6 +163,9 @@ func (w *Writer) Close() error { // Create adds a file to the zip file using the provided name. // It returns a Writer to which the file contents should be written. +// The name must be a relative path: it must not start with a drive +// letter (e.g. C:) or leading slash, and only forward slashes are +// allowed. // The file's contents must be written to the io.Writer before the next // call to Create, CreateHeader, or Close. func (w *Writer) Create(name string) (io.Writer, error) { diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go index 33779014c9c..df3501f2ca1 100644 --- a/libgo/go/bufio/bufio.go +++ b/libgo/go/bufio/bufio.go @@ -274,11 +274,10 @@ 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 -// ReadBytes('\n') or ReadString('\n') instead. +// ReadBytes('\n') or ReadString('\n') instead or use a Scanner. // // ReadLine tries to return a single line, not including the end-of-line bytes. // If the line was too long for the buffer then isPrefix is set and the @@ -331,6 +330,7 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { // it returns the data read before the error and the error itself (often io.EOF). // ReadBytes returns err != nil if and only if the returned data does not end in // delim. +// For simple uses, a Scanner may be more convenient. func (b *Reader) ReadBytes(delim byte) (line []byte, err error) { // Use ReadSlice to look for array, // accumulating full buffers. @@ -378,6 +378,7 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) { // it returns the data read before the error and the error itself (often io.EOF). // ReadString returns err != nil if and only if the returned data does not end in // delim. +// For simple uses, a Scanner may be more convenient. func (b *Reader) ReadString(delim byte) (line string, err error) { bytes, err := b.ReadBytes(delim) return string(bytes), err diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go index 418690aa454..79ed0f178e0 100644 --- a/libgo/go/bufio/bufio_test.go +++ b/libgo/go/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) + } } } } @@ -953,7 +957,7 @@ func TestNegativeRead(t *testing.T) { t.Fatal("read did not panic") case error: if !strings.Contains(err.Error(), "reader returned negative count from Read") { - t.Fatal("wrong panic: %v", err) + t.Fatalf("wrong panic: %v", err) } default: t.Fatalf("unexpected panic value: %T(%v)", err, err) @@ -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/libgo/go/bufio/example_test.go b/libgo/go/bufio/example_test.go new file mode 100644 index 00000000000..08a39441e66 --- /dev/null +++ b/libgo/go/bufio/example_test.go @@ -0,0 +1,74 @@ +// 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 bufio_test + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +// The simplest use of a Scanner, to read standard input as a set of lines. +func ExampleScanner_lines() { + 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) + } +} + +// Use a Scanner to implement a simple word-count utility by scanning the +// input as a sequence of space-delimited tokens. +func ExampleScanner_words() { + // An artificial input source. + const input = "Now is the winter of our discontent,\nMade glorious summer by this sun of York.\n" + scanner := bufio.NewScanner(strings.NewReader(input)) + // Set the split function for the scanning operation. + scanner.Split(bufio.ScanWords) + // Count the words. + count := 0 + for scanner.Scan() { + count++ + } + if err := scanner.Err(); err != nil { + fmt.Fprintln(os.Stderr, "reading input:", err) + } + fmt.Printf("%d\n", count) + // Output: 15 +} + +// Use a Scanner with a custom split function (built by wrapping ScanWords) to validate +// 32-bit decimal input. +func ExampleScanner_custom() { + // An artificial input source. + const input = "1234 5678 1234567901234567890" + scanner := bufio.NewScanner(strings.NewReader(input)) + // Create a custom split function by wrapping the existing ScanWords function. + split := func(data []byte, atEOF bool) (advance int, token []byte, err error) { + advance, token, err = bufio.ScanWords(data, atEOF) + if err == nil && token != nil { + _, err = strconv.ParseInt(string(token), 10, 32) + } + return + } + // Set the split function for the scanning operation. + scanner.Split(split) + // Validate the input + for scanner.Scan() { + fmt.Printf("%s\n", scanner.Text()) + } + + if err := scanner.Err(); err != nil { + fmt.Printf("Invalid input: %s", err) + } + // Output: + // 1234 + // 5678 + // Invalid input: strconv.ParseInt: parsing "1234567901234567890": value out of range +} diff --git a/libgo/go/bufio/export_test.go b/libgo/go/bufio/export_test.go new file mode 100644 index 00000000000..3d3bb27d8da --- /dev/null +++ b/libgo/go/bufio/export_test.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 bufio + +// Exported for testing only. +import ( + "unicode/utf8" +) + +var IsSpace = isSpace + +func (s *Scanner) MaxTokenSize(n int) { + if n < utf8.UTFMax || n > 1e9 { + panic("bad max token size") + } + if n < len(s.buf) { + s.buf = make([]byte, n) + } + s.maxTokenSize = n +} + +// ErrOrEOF is like Err, but returns EOF. Used to test a corner case. +func (s *Scanner) ErrOrEOF() error { + return s.err +} diff --git a/libgo/go/bufio/scan.go b/libgo/go/bufio/scan.go new file mode 100644 index 00000000000..2e1a2e99973 --- /dev/null +++ b/libgo/go/bufio/scan.go @@ -0,0 +1,346 @@ +// 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 bufio + +import ( + "bytes" + "errors" + "io" + "unicode/utf8" +) + +// Scanner provides a convenient interface for reading data such as +// a file of newline-delimited lines of text. Successive calls to +// the Scan method will step through the 'tokens' of a file, skipping +// the bytes between the tokens. The specification of a token is +// defined by a split function of type SplitFunc; the default split +// function breaks the input into lines with line termination stripped. Split +// functions are defined in this package for scanning a file into +// lines, bytes, UTF-8-encoded runes, and space-delimited words. The +// client may instead provide a custom split function. +// +// Scanning stops unrecoverably at EOF, the first I/O error, or a token too +// large to fit in the buffer. When a scan stops, the reader may have +// advanced arbitrarily far past the last token. Programs that need more +// control over error handling or large tokens, or must run sequential scans +// on a reader, should use bufio.Reader instead. +// +type Scanner struct { + r io.Reader // The reader provided by the client. + split SplitFunc // The function to split the tokens. + maxTokenSize int // Maximum size of a token; modified by tests. + token []byte // Last token returned by split. + buf []byte // Buffer used as argument to split. + start int // First non-processed byte in buf. + end int // End of data in buf. + err error // Sticky error. +} + +// SplitFunc is the signature of the split function used to tokenize the +// input. The arguments are an initial substring of the remaining unprocessed +// data and a flag, atEOF, that reports whether the Reader has no more data +// to give. The return values are the number of bytes to advance the input +// and the next token to return to the user, plus an error, if any. If the +// data does not yet hold a complete token, for instance if it has no newline +// while scanning lines, SplitFunc can return (0, nil) to signal the Scanner +// to read more data into the slice and try again with a longer slice +// starting at the same point in the input. +// +// If the returned error is non-nil, scanning stops and the error +// is returned to the client. +// +// The function is never called with an empty data slice unless atEOF +// is true. If atEOF is true, however, data may be non-empty and, +// as always, holds unprocessed text. +type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error) + +// Errors returned by Scanner. +var ( + ErrTooLong = errors.New("bufio.Scanner: token too long") + ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count") + ErrAdvanceTooFar = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input") +) + +const ( + // Maximum size used to buffer a token. The actual maximum token size + // may be smaller as the buffer may need to include, for instance, a newline. + MaxScanTokenSize = 64 * 1024 +) + +// NewScanner returns a new Scanner to read from r. +// The split function defaults to ScanLines. +func NewScanner(r io.Reader) *Scanner { + return &Scanner{ + r: r, + split: ScanLines, + maxTokenSize: MaxScanTokenSize, + buf: make([]byte, 4096), // Plausible starting size; needn't be large. + } +} + +// Err returns the first non-EOF error that was encountered by the Scanner. +func (s *Scanner) Err() error { + if s.err == io.EOF { + return nil + } + return s.err +} + +// Bytes returns the most recent token generated by a call to Scan. +// The underlying array may point to data that will be overwritten +// by a subsequent call to Scan. It does no allocation. +func (s *Scanner) Bytes() []byte { + return s.token +} + +// Text returns the most recent token generated by a call to Scan +// as a newly allocated string holding its bytes. +func (s *Scanner) Text() string { + return string(s.token) +} + +// Scan advances the Scanner to the next token, which will then be +// available through the Bytes or Text method. It returns false when the +// scan stops, either by reaching the end of the input or an error. +// After Scan returns false, the Err method will return any error that +// occurred during scanning, except that if it was io.EOF, Err +// will return nil. +func (s *Scanner) Scan() bool { + // Loop until we have a token. + for { + // See if we can get a token with what we already have. + if s.end > s.start { + advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil) + if err != nil { + s.setErr(err) + return false + } + if !s.advance(advance) { + return false + } + s.token = token + if token != nil { + return true + } + } + // We cannot generate a token with what we are holding. + // If we've already hit EOF or an I/O error, we are done. + if s.err != nil { + // Shut it down. + s.start = 0 + s.end = 0 + return false + } + // Must read more data. + // First, shift data to beginning of buffer if there's lots of empty space + // or space is neded. + if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) { + copy(s.buf, s.buf[s.start:s.end]) + s.end -= s.start + s.start = 0 + } + // Is the buffer full? If so, resize. + if s.end == len(s.buf) { + if len(s.buf) >= s.maxTokenSize { + s.setErr(ErrTooLong) + return false + } + newSize := len(s.buf) * 2 + if newSize > s.maxTokenSize { + newSize = s.maxTokenSize + } + newBuf := make([]byte, newSize) + copy(newBuf, s.buf[s.start:s.end]) + s.buf = newBuf + s.end -= s.start + s.start = 0 + continue + } + // Finally we can read some input. Make sure we don't get stuck with + // a misbehaving Reader. Officially we don't need to do this, but let's + // be extra careful: Scanner is for safe, simple jobs. + for loop := 0; ; { + n, err := s.r.Read(s.buf[s.end:len(s.buf)]) + s.end += n + if err != nil { + s.setErr(err) + break + } + if n > 0 { + break + } + loop++ + if loop > 100 { + s.setErr(io.ErrNoProgress) + break + } + } + } +} + +// advance consumes n bytes of the buffer. It reports whether the advance was legal. +func (s *Scanner) advance(n int) bool { + if n < 0 { + s.setErr(ErrNegativeAdvance) + return false + } + if n > s.end-s.start { + s.setErr(ErrAdvanceTooFar) + return false + } + s.start += n + return true +} + +// setErr records the first error encountered. +func (s *Scanner) setErr(err error) { + if s.err == nil || s.err == io.EOF { + s.err = err + } +} + +// Split sets the split function for the Scanner. If called, it must be +// called before Scan. The default split function is ScanLines. +func (s *Scanner) Split(split SplitFunc) { + s.split = split +} + +// Split functions + +// ScanBytes is a split function for a Scanner that returns each byte as a token. +func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + return 1, data[0:1], nil +} + +var errorRune = []byte(string(utf8.RuneError)) + +// ScanRunes is a split function for a Scanner that returns each +// UTF-8-encoded rune as a token. The sequence of runes returned is +// equivalent to that from a range loop over the input as a string, which +// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd". +// Because of the Scan interface, this makes it impossible for the client to +// distinguish correctly encoded replacement runes from encoding errors. +func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + + // Fast path 1: ASCII. + if data[0] < utf8.RuneSelf { + return 1, data[0:1], nil + } + + // Fast path 2: Correct UTF-8 decode without error. + _, width := utf8.DecodeRune(data) + if width > 1 { + // It's a valid encoding. Width cannot be one for a correctly encoded + // non-ASCII rune. + return width, data[0:width], nil + } + + // We know it's an error: we have width==1 and implicitly r==utf8.RuneError. + // Is the error because there wasn't a full rune to be decoded? + // FullRune distinguishes correctly between erroneous and incomplete encodings. + if !atEOF && !utf8.FullRune(data) { + // Incomplete; get more bytes. + return 0, nil, nil + } + + // We have a real UTF-8 encoding error. Return a properly encoded error rune + // but advance only one byte. This matches the behavior of a range loop over + // an incorrectly encoded string. + return 1, errorRune, nil +} + +// dropCR drops a terminal \r from the data. +func dropCR(data []byte) []byte { + if len(data) > 0 && data[len(data)-1] == '\r' { + return data[0 : len(data)-1] + } + return data +} + +// ScanLines is a split function for a Scanner that returns each line of +// text, stripped of any trailing end-of-line marker. The returned line may +// be empty. The end-of-line marker is one optional carriage return followed +// by one mandatory newline. In regular expression notation, it is `\r?\n`. +// The last non-empty line of input will be returned even if it has no +// newline. +func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + if i := bytes.IndexByte(data, '\n'); i >= 0 { + // We have a full newline-terminated line. + return i + 1, dropCR(data[0:i]), nil + } + // If we're at EOF, we have a final, non-terminated line. Return it. + if atEOF { + return len(data), dropCR(data), nil + } + // Request more data. + return 0, nil, nil +} + +// isSpace returns whether the character is a Unicode white space character. +// We avoid dependency on the unicode package, but check validity of the implementation +// in the tests. +func isSpace(r rune) bool { + if r <= '\u00FF' { + // Obvious ASCII ones: \t through \r plus space. Plus two Latin-1 oddballs. + switch r { + case ' ', '\t', '\n', '\v', '\f', '\r': + return true + case '\u0085', '\u00A0': + return true + } + return false + } + // High-valued ones. + if '\u2000' <= r && r <= '\u200a' { + return true + } + switch r { + case '\u1680', '\u180e', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000': + return true + } + return false +} + +// ScanWords is a split function for a Scanner that returns each +// space-separated word of text, with surrounding spaces deleted. It will +// never return an empty string. The definition of space is set by +// unicode.IsSpace. +func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) { + // Skip leading spaces. + start := 0 + for width := 0; start < len(data); start += width { + var r rune + r, width = utf8.DecodeRune(data[start:]) + if !isSpace(r) { + break + } + } + if atEOF && len(data) == 0 { + return 0, nil, nil + } + // Scan until space, marking end of word. + for width, i := 0, start; i < len(data); i += width { + var r rune + r, width = utf8.DecodeRune(data[i:]) + if isSpace(r) { + return i + width, data[start:i], nil + } + } + // If we're at EOF, we have a final, non-empty, non-terminated word. Return it. + if atEOF && len(data) > start { + return len(data), data[start:], nil + } + // Request more data. + return 0, nil, nil +} diff --git a/libgo/go/bufio/scan_test.go b/libgo/go/bufio/scan_test.go new file mode 100644 index 00000000000..c1483b26858 --- /dev/null +++ b/libgo/go/bufio/scan_test.go @@ -0,0 +1,406 @@ +// 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 bufio_test + +import ( + . "bufio" + "bytes" + "errors" + "io" + "strings" + "testing" + "unicode" + "unicode/utf8" +) + +// Test white space table matches the Unicode definition. +func TestSpace(t *testing.T) { + for r := rune(0); r <= utf8.MaxRune; r++ { + if IsSpace(r) != unicode.IsSpace(r) { + t.Fatalf("white space property disagrees: %#U should be %t", r, unicode.IsSpace(r)) + } + } +} + +var scanTests = []string{ + "", + "a", + "¼", + "☹", + "\x81", // UTF-8 error + "\uFFFD", // correctly encoded RuneError + "abcdefgh", + "abc def\n\t\tgh ", + "abc¼☹\x81\uFFFD日本語\x82abc", +} + +func TestScanByte(t *testing.T) { + for n, test := range scanTests { + buf := bytes.NewBufferString(test) + s := NewScanner(buf) + s.Split(ScanBytes) + var i int + for i = 0; s.Scan(); i++ { + if b := s.Bytes(); len(b) != 1 || b[0] != test[i] { + t.Errorf("#%d: %d: expected %q got %q", n, i, test, b) + } + } + if i != len(test) { + t.Errorf("#%d: termination expected at %d; got %d", n, len(test), i) + } + err := s.Err() + if err != nil { + t.Errorf("#%d: %v", n, err) + } + } +} + +// Test that the rune splitter returns same sequence of runes (not bytes) as for range string. +func TestScanRune(t *testing.T) { + for n, test := range scanTests { + buf := bytes.NewBufferString(test) + s := NewScanner(buf) + s.Split(ScanRunes) + var i, runeCount int + var expect rune + // Use a string range loop to validate the sequence of runes. + for i, expect = range string(test) { + if !s.Scan() { + break + } + runeCount++ + got, _ := utf8.DecodeRune(s.Bytes()) + if got != expect { + t.Errorf("#%d: %d: expected %q got %q", n, i, expect, got) + } + } + if s.Scan() { + t.Errorf("#%d: scan ran too long, got %q", n, s.Text()) + } + testRuneCount := utf8.RuneCountInString(test) + if runeCount != testRuneCount { + t.Errorf("#%d: termination expected at %d; got %d", n, testRuneCount, runeCount) + } + err := s.Err() + if err != nil { + t.Errorf("#%d: %v", n, err) + } + } +} + +var wordScanTests = []string{ + "", + " ", + "\n", + "a", + " a ", + "abc def", + " abc def ", + " abc\tdef\nghi\rjkl\fmno\vpqr\u0085stu\u00a0\n", +} + +// Test that the word splitter returns the same data as strings.Fields. +func TestScanWords(t *testing.T) { + for n, test := range wordScanTests { + buf := bytes.NewBufferString(test) + s := NewScanner(buf) + s.Split(ScanWords) + words := strings.Fields(test) + var wordCount int + for wordCount = 0; wordCount < len(words); wordCount++ { + if !s.Scan() { + break + } + got := s.Text() + if got != words[wordCount] { + t.Errorf("#%d: %d: expected %q got %q", n, wordCount, words[wordCount], got) + } + } + if s.Scan() { + t.Errorf("#%d: scan ran too long, got %q", n, s.Text()) + } + if wordCount != len(words) { + t.Errorf("#%d: termination expected at %d; got %d", n, len(words), wordCount) + } + err := s.Err() + if err != nil { + t.Errorf("#%d: %v", n, err) + } + } +} + +// slowReader is a reader that returns only a few bytes at a time, to test the incremental +// reads in Scanner.Scan. +type slowReader struct { + max int + buf *bytes.Buffer +} + +func (sr *slowReader) Read(p []byte) (n int, err error) { + if len(p) > sr.max { + p = p[0:sr.max] + } + return sr.buf.Read(p) +} + +// genLine writes to buf a predictable but non-trivial line of text of length +// n, including the terminal newline and an occasional carriage return. +// If addNewline is false, the \r and \n are not emitted. +func genLine(buf *bytes.Buffer, lineNum, n int, addNewline bool) { + buf.Reset() + doCR := lineNum%5 == 0 + if doCR { + n-- + } + for i := 0; i < n-1; i++ { // Stop early for \n. + c := 'a' + byte(lineNum+i) + if c == '\n' || c == '\r' { // Don't confuse us. + c = 'N' + } + buf.WriteByte(c) + } + if addNewline { + if doCR { + buf.WriteByte('\r') + } + buf.WriteByte('\n') + } + return +} + +// Test the line splitter, including some carriage returns but no long lines. +func TestScanLongLines(t *testing.T) { + const smallMaxTokenSize = 256 // Much smaller for more efficient testing. + // Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize. + tmp := new(bytes.Buffer) + buf := new(bytes.Buffer) + lineNum := 0 + j := 0 + for i := 0; i < 2*smallMaxTokenSize; i++ { + genLine(tmp, lineNum, j, true) + if j < smallMaxTokenSize { + j++ + } else { + j-- + } + buf.Write(tmp.Bytes()) + lineNum++ + } + s := NewScanner(&slowReader{1, buf}) + s.Split(ScanLines) + s.MaxTokenSize(smallMaxTokenSize) + j = 0 + for lineNum := 0; s.Scan(); lineNum++ { + genLine(tmp, lineNum, j, false) + if j < smallMaxTokenSize { + j++ + } else { + j-- + } + line := tmp.String() // We use the string-valued token here, for variety. + if s.Text() != line { + t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Text(), line) + } + } + err := s.Err() + if err != nil { + t.Fatal(err) + } +} + +// Test that the line splitter errors out on a long line. +func TestScanLineTooLong(t *testing.T) { + const smallMaxTokenSize = 256 // Much smaller for more efficient testing. + // Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize. + tmp := new(bytes.Buffer) + buf := new(bytes.Buffer) + lineNum := 0 + j := 0 + for i := 0; i < 2*smallMaxTokenSize; i++ { + genLine(tmp, lineNum, j, true) + j++ + buf.Write(tmp.Bytes()) + lineNum++ + } + s := NewScanner(&slowReader{3, buf}) + s.Split(ScanLines) + s.MaxTokenSize(smallMaxTokenSize) + j = 0 + for lineNum := 0; s.Scan(); lineNum++ { + genLine(tmp, lineNum, j, false) + if j < smallMaxTokenSize { + j++ + } else { + j-- + } + line := tmp.Bytes() + if !bytes.Equal(s.Bytes(), line) { + t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line) + } + } + err := s.Err() + if err != ErrTooLong { + t.Fatalf("expected ErrTooLong; got %s", err) + } +} + +// Test that the line splitter handles a final line without a newline. +func testNoNewline(text string, lines []string, t *testing.T) { + buf := bytes.NewBufferString(text) + s := NewScanner(&slowReader{7, buf}) + s.Split(ScanLines) + for lineNum := 0; s.Scan(); lineNum++ { + line := lines[lineNum] + if s.Text() != line { + t.Errorf("%d: bad line: %d %d\n%.100q\n%.100q\n", lineNum, len(s.Bytes()), len(line), s.Bytes(), line) + } + } + err := s.Err() + if err != nil { + t.Fatal(err) + } +} + +var noNewlineLines = []string{ + "abcdefghijklmn\nopqrstuvwxyz", +} + +// Test that the line splitter handles a final line without a newline. +func TestScanLineNoNewline(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + } + testNoNewline(text, lines, t) +} + +// Test that the line splitter handles a final line with a carriage return but nonewline. +func TestScanLineReturnButNoNewline(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz\r" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + } + testNoNewline(text, lines, t) +} + +// Test that the line splitter handles a final empty line. +func TestScanLineEmptyFinalLine(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz\n\n" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + "", + } + testNoNewline(text, lines, t) +} + +// Test that the line splitter handles a final empty line with a carriage return but no newline. +func TestScanLineEmptyFinalLineWithCR(t *testing.T) { + const text = "abcdefghijklmn\nopqrstuvwxyz\n\r" + lines := []string{ + "abcdefghijklmn", + "opqrstuvwxyz", + "", + } + testNoNewline(text, lines, t) +} + +var testError = errors.New("testError") + +// Test the correct error is returned when the split function errors out. +func TestSplitError(t *testing.T) { + // Create a split function that delivers a little data, then a predictable error. + numSplits := 0 + const okCount = 7 + errorSplit := func(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF { + panic("didn't get enough data") + } + if numSplits >= okCount { + return 0, nil, testError + } + numSplits++ + return 1, data[0:1], nil + } + // Read the data. + const text = "abcdefghijklmnopqrstuvwxyz" + buf := bytes.NewBufferString(text) + s := NewScanner(&slowReader{1, buf}) + s.Split(errorSplit) + var i int + for i = 0; s.Scan(); i++ { + if len(s.Bytes()) != 1 || text[i] != s.Bytes()[0] { + t.Errorf("#%d: expected %q got %q", i, text[i], s.Bytes()[0]) + } + } + // Check correct termination location and error. + if i != okCount { + t.Errorf("unexpected termination; expected %d tokens got %d", okCount, i) + } + err := s.Err() + if err != testError { + t.Fatalf("expected %q got %v", testError, err) + } +} + +// Test that an EOF is overridden by a user-generated scan error. +func TestErrAtEOF(t *testing.T) { + s := NewScanner(strings.NewReader("1 2 33")) + // This spitter will fail on last entry, after s.err==EOF. + split := func(data []byte, atEOF bool) (advance int, token []byte, err error) { + advance, token, err = ScanWords(data, atEOF) + if len(token) > 1 { + if s.ErrOrEOF() != io.EOF { + t.Fatal("not testing EOF") + } + err = testError + } + return + } + s.Split(split) + for s.Scan() { + } + if s.Err() != testError { + t.Fatal("wrong error:", s.Err()) + } +} + +// Test for issue 5268. +type alwaysError struct{} + +func (alwaysError) Read(p []byte) (int, error) { + return 0, io.ErrUnexpectedEOF +} + +func TestNonEOFWithEmptyRead(t *testing.T) { + scanner := NewScanner(alwaysError{}) + for scanner.Scan() { + t.Fatal("read should fail") + } + err := scanner.Err() + if err != io.ErrUnexpectedEOF { + t.Errorf("unexpected error: %v", err) + } +} + +// Test that Scan finishes if we have endless empty reads. +type endlessZeros struct{} + +func (endlessZeros) Read(p []byte) (int, error) { + return 0, nil +} + +func TestBadReader(t *testing.T) { + scanner := NewScanner(endlessZeros{}) + for scanner.Scan() { + t.Fatal("read should fail") + } + err := scanner.Err() + if err != io.ErrNoProgress { + t.Errorf("unexpected error: %v", err) + } +} diff --git a/libgo/go/builtin/builtin.go b/libgo/go/builtin/builtin.go index 91d263a6234..128a1b5f8fc 100644 --- a/libgo/go/builtin/builtin.go +++ b/libgo/go/builtin/builtin.go @@ -13,6 +13,12 @@ package builtin // bool is the set of boolean values, true and false. type bool bool +// true and false are the two untyped boolean values. +const ( + true = 0 == 0 // Untyped bool. + false = 0 != 0 // Untyped bool. +) + // uint8 is the set of all unsigned 8-bit integers. // Range: 0 through 255. type uint8 uint8 @@ -85,6 +91,15 @@ type byte byte // used, by convention, to distinguish character values from integer values. type rune rune +// iota is a predeclared identifier representing the untyped integer ordinal +// number of the current const specification in a (usually parenthesized) +// const declaration. It is zero-indexed. +const iota = 0 // Untyped int. + +// nil is a predeclared identifier representing the zero value for a +// pointer, channel, func, interface, map, or slice type. +var nil Type // Type must be a pointer, channel, func, interface, map, or slice type + // Type is here for the purposes of documentation only. It is a stand-in // for any Go type, but represents the same type for any given function // invocation. @@ -114,6 +129,8 @@ type ComplexType complex64 // result of append, often in the variable holding the slice itself: // slice = append(slice, elem1, elem2) // slice = append(slice, anotherSlice...) +// As a special case, it is legal to append a string to a byte slice, like this: +// slice = append([]byte("hello "), "world"...) func append(slice []Type, elems ...Type) []Type // The copy built-in function copies elements from a source slice into a diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go index 85c1577985d..46ca1d5ad3f 100644 --- a/libgo/go/bytes/buffer.go +++ b/libgo/go/bytes/buffer.go @@ -87,6 +87,13 @@ func (b *Buffer) grow(n int) int { var buf []byte if b.buf == nil && n <= len(b.bootstrap) { buf = b.bootstrap[0:] + } else if m+n <= cap(b.buf)/2 { + // We can slide things down instead of allocating a new + // slice. We only need m+n <= cap(b.buf) to slide, but + // we instead let capacity get twice as large so we + // don't spend all our time copying. + copy(b.buf[:], b.buf[b.off:]) + buf = b.buf[:m] } else { // not enough space anywhere buf = makeSlice(2*cap(b.buf) + n) @@ -112,20 +119,18 @@ func (b *Buffer) Grow(n int) { b.buf = b.buf[0:m] } -// Write appends the contents of p to the buffer. The return -// value n is the length of p; err is always nil. -// If the buffer becomes too large, Write will panic with -// ErrTooLarge. +// Write appends the contents of p to the buffer, growing the buffer as +// needed. The return value n is the length of p; err is always nil. If the +// buffer becomes too large, Write will panic with ErrTooLarge. func (b *Buffer) Write(p []byte) (n int, err error) { b.lastRead = opInvalid m := b.grow(len(p)) return copy(b.buf[m:], p), nil } -// WriteString appends the contents of s to the buffer. The return -// value n is the length of s; err is always nil. -// If the buffer becomes too large, WriteString will panic with -// ErrTooLarge. +// WriteString appends the contents of s to the buffer, growing the buffer as +// needed. The return value n is the length of s; err is always nil. If the +// buffer becomes too large, WriteString will panic with ErrTooLarge. func (b *Buffer) WriteString(s string) (n int, err error) { b.lastRead = opInvalid m := b.grow(len(s)) @@ -138,12 +143,10 @@ func (b *Buffer) WriteString(s string) (n int, err error) { // underlying buffer. const MinRead = 512 -// ReadFrom reads data from r until EOF and appends it to the buffer. -// The return value n is the number of bytes read. -// Any error except io.EOF encountered during the read -// is also returned. -// If the buffer becomes too large, ReadFrom will panic with -// ErrTooLarge. +// ReadFrom reads data from r until EOF and appends it to the buffer, growing +// the buffer as needed. The return value n is the number of bytes read. Any +// error except io.EOF encountered during the read is also returned. If the +// buffer becomes too large, ReadFrom will panic with ErrTooLarge. func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) { b.lastRead = opInvalid // If buffer is empty, reset to recover space. @@ -188,10 +191,10 @@ func makeSlice(n int) []byte { return make([]byte, n) } -// WriteTo writes data to w until the buffer is drained or an error -// occurs. The return value n is the number of bytes written; it always -// fits into an int, but it is int64 to match the io.WriterTo interface. -// Any error encountered during the write is also returned. +// WriteTo writes data to w until the buffer is drained or an error occurs. +// The return value n is the number of bytes written; it always fits into an +// int, but it is int64 to match the io.WriterTo interface. Any error +// encountered during the write is also returned. func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) { b.lastRead = opInvalid if b.off < len(b.buf) { @@ -216,10 +219,9 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) { return } -// WriteByte appends the byte c to the buffer. -// The returned error is always nil, but is included -// to match bufio.Writer's WriteByte. -// If the buffer becomes too large, WriteByte will panic with +// WriteByte appends the byte c to the buffer, growing the buffer as needed. +// The returned error is always nil, but is included to match bufio.Writer's +// WriteByte. If the buffer becomes too large, WriteByte will panic with // ErrTooLarge. func (b *Buffer) WriteByte(c byte) error { b.lastRead = opInvalid @@ -228,12 +230,10 @@ func (b *Buffer) WriteByte(c byte) error { return nil } -// WriteRune appends the UTF-8 encoding of Unicode -// code point r to the buffer, returning its length and -// an error, which is always nil but is included -// to match bufio.Writer's WriteRune. -// If the buffer becomes too large, WriteRune will panic with -// ErrTooLarge. +// WriteRune appends the UTF-8 encoding of Unicode code point r to the +// buffer, returning its length and an error, which is always nil but is +// included to match bufio.Writer's WriteRune. The buffer is grown as needed; +// if it becomes too large, WriteRune will panic with ErrTooLarge. func (b *Buffer) WriteRune(r rune) (n int, err error) { if r < utf8.RuneSelf { b.WriteByte(byte(r)) diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go index f9fb2625a0f..75145b05e92 100644 --- a/libgo/go/bytes/buffer_test.go +++ b/libgo/go/bytes/buffer_test.go @@ -475,3 +475,53 @@ func TestUnreadByte(t *testing.T) { t.Errorf("ReadByte = %q; want %q", c, 'm') } } + +// Tests that we occasionally compact. Issue 5154. +func TestBufferGrowth(t *testing.T) { + var b Buffer + buf := make([]byte, 1024) + b.Write(buf[0:1]) + var cap0 int + for i := 0; i < 5<<10; i++ { + b.Write(buf) + b.Read(buf) + if i == 0 { + cap0 = b.Cap() + } + } + cap1 := b.Cap() + // (*Buffer).grow allows for 2x capacity slop before sliding, + // so set our error threshold at 3x. + if cap1 > cap0*3 { + t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0) + } +} + +// From Issue 5154. +func BenchmarkBufferNotEmptyWriteRead(b *testing.B) { + buf := make([]byte, 1024) + for i := 0; i < b.N; i++ { + var b Buffer + b.Write(buf[0:1]) + for i := 0; i < 5<<10; i++ { + b.Write(buf) + b.Read(buf) + } + } +} + +// Check that we don't compact too often. From Issue 5154. +func BenchmarkBufferFullSmallReads(b *testing.B) { + buf := make([]byte, 1024) + for i := 0; i < b.N; i++ { + var b Buffer + b.Write(buf) + for b.Len()+20 < b.Cap() { + b.Write(buf[:10]) + } + for i := 0; i < 5<<10; i++ { + b.Read(buf[:1]) + b.Write(buf[:1]) + } + } +} diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go index e3ee5b1d88a..e42f7443946 100644 --- a/libgo/go/bytes/bytes.go +++ b/libgo/go/bytes/bytes.go @@ -37,10 +37,6 @@ func Compare(a, b []byte) int { return 0 } -// Equal returns a boolean reporting whether a == b. -// A nil argument is equivalent to an empty slice. -func Equal(a, b []byte) bool - func equalPortable(a, b []byte) bool { if len(a) != len(b) { return false @@ -465,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 @@ -515,6 +511,24 @@ func TrimFunc(s []byte, f func(r rune) bool) []byte { return TrimRightFunc(TrimLeftFunc(s, f), f) } +// TrimPrefix returns s without the provided leading prefix string. +// If s doesn't start with prefix, s is returned unchanged. +func TrimPrefix(s, prefix []byte) []byte { + if HasPrefix(s, prefix) { + return s[len(prefix):] + } + return s +} + +// TrimSuffix returns s without the provided trailing suffix string. +// If s doesn't end with suffix, s is returned unchanged. +func TrimSuffix(s, suffix []byte) []byte { + if HasSuffix(s, suffix) { + return s[:len(s)-len(suffix)] + } + return s +} + // IndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points. // It returns the byte index in s of the first Unicode // code point satisfying f(c), or -1 if none do. @@ -553,7 +567,10 @@ func indexFunc(s []byte, f func(r rune) bool, truth bool) int { // inverted. func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int { for i := len(s); i > 0; { - r, size := utf8.DecodeLastRune(s[0:i]) + r, size := rune(s[i-1]), 1 + if r >= utf8.RuneSelf { + r, size = utf8.DecodeLastRune(s[0:i]) + } i -= size if f(r) == truth { return i diff --git a/libgo/go/bytes/bytes_decl.go b/libgo/go/bytes/bytes_decl.go index 5d2b9e6393a..fbf92827527 100644 --- a/libgo/go/bytes/bytes_decl.go +++ b/libgo/go/bytes/bytes_decl.go @@ -4,5 +4,13 @@ package bytes +//go:noescape + // IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s. func IndexByte(s []byte, c byte) int // asm_$GOARCH.s + +//go:noescape + +// Equal returns a boolean reporting whether a == b. +// A nil argument is equivalent to an empty slice. +func Equal(a, b []byte) bool // asm_arm.s or ../runtime/asm_{386,amd64}.s diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go index 05956d460a9..d296224ac42 100644 --- a/libgo/go/bytes/bytes_test.go +++ b/libgo/go/bytes/bytes_test.go @@ -61,6 +61,10 @@ var compareTests = []struct { {[]byte("ab"), []byte("x"), -1}, {[]byte("x"), []byte("a"), 1}, {[]byte("b"), []byte("x"), -1}, + // test runtime·memeq's chunked implementation + {[]byte("abcdefgh"), []byte("abcdefgh"), 0}, + {[]byte("abcdefghi"), []byte("abcdefghi"), 0}, + {[]byte("abcdefghi"), []byte("abcdefghj"), -1}, // nil tests {nil, nil, 0}, {[]byte(""), nil, 0}, @@ -86,6 +90,58 @@ func TestCompare(t *testing.T) { } } +func TestEqual(t *testing.T) { + var size = 128 + if testing.Short() { + size = 32 + } + a := make([]byte, size) + b := make([]byte, size) + b_init := make([]byte, size) + // randomish but deterministic data + for i := 0; i < size; i++ { + a[i] = byte(17 * i) + b_init[i] = byte(23*i + 100) + } + + for len := 0; len <= size; len++ { + for x := 0; x <= size-len; x++ { + for y := 0; y <= size-len; y++ { + copy(b, b_init) + copy(b[y:y+len], a[x:x+len]) + if !Equal(a[x:x+len], b[y:y+len]) || !Equal(b[y:y+len], a[x:x+len]) { + t.Errorf("Equal(%d, %d, %d) = false", len, x, y) + } + } + } + } +} + +// make sure Equal returns false for minimally different strings. The data +// is all zeros except for a single one in one location. +func TestNotEqual(t *testing.T) { + var size = 128 + if testing.Short() { + size = 32 + } + a := make([]byte, size) + b := make([]byte, size) + + for len := 0; len <= size; len++ { + for x := 0; x <= size-len; x++ { + for y := 0; y <= size-len; y++ { + for diffpos := x; diffpos < x+len; diffpos++ { + a[diffpos] = 1 + if Equal(a[x:x+len], b[y:y+len]) || Equal(b[y:y+len], a[x:x+len]) { + t.Errorf("NotEqual(%d, %d, %d, %d) = true", len, x, y, diffpos) + } + a[diffpos] = 0 + } + } + } + } +} + var indexTests = []BinOpTest{ {"", "", 0}, {"", "a", -1}, @@ -303,10 +359,30 @@ func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) { buf[n-1] = '\x00' } +func BenchmarkEqual0(b *testing.B) { + var buf [4]byte + buf1 := buf[0:0] + buf2 := buf[1:1] + for i := 0; i < b.N; i++ { + eq := Equal(buf1, buf2) + if !eq { + b.Fatal("bad equal") + } + } +} + +func BenchmarkEqual1(b *testing.B) { bmEqual(b, Equal, 1) } +func BenchmarkEqual6(b *testing.B) { bmEqual(b, Equal, 6) } +func BenchmarkEqual9(b *testing.B) { bmEqual(b, Equal, 9) } +func BenchmarkEqual15(b *testing.B) { bmEqual(b, Equal, 15) } +func BenchmarkEqual16(b *testing.B) { bmEqual(b, Equal, 16) } +func BenchmarkEqual20(b *testing.B) { bmEqual(b, Equal, 20) } func BenchmarkEqual32(b *testing.B) { bmEqual(b, Equal, 32) } func BenchmarkEqual4K(b *testing.B) { bmEqual(b, Equal, 4<<10) } func BenchmarkEqual4M(b *testing.B) { bmEqual(b, Equal, 4<<20) } func BenchmarkEqual64M(b *testing.B) { bmEqual(b, Equal, 64<<20) } +func BenchmarkEqualPort1(b *testing.B) { bmEqual(b, EqualPortable, 1) } +func BenchmarkEqualPort6(b *testing.B) { bmEqual(b, EqualPortable, 6) } func BenchmarkEqualPort32(b *testing.B) { bmEqual(b, EqualPortable, 32) } func BenchmarkEqualPort4K(b *testing.B) { bmEqual(b, EqualPortable, 4<<10) } func BenchmarkEqualPortable4M(b *testing.B) { bmEqual(b, EqualPortable, 4<<20) } @@ -794,8 +870,8 @@ func TestRunes(t *testing.T) { } type TrimTest struct { - f string - in, cutset, out string + f string + in, arg, out string } var trimTests = []TrimTest{ @@ -820,12 +896,17 @@ var trimTests = []TrimTest{ {"TrimRight", "", "123", ""}, {"TrimRight", "", "", ""}, {"TrimRight", "☺\xc0", "☺", "☺\xc0"}, + {"TrimPrefix", "aabb", "a", "abb"}, + {"TrimPrefix", "aabb", "b", "aabb"}, + {"TrimSuffix", "aabb", "a", "aabb"}, + {"TrimSuffix", "aabb", "b", "aab"}, } func TestTrim(t *testing.T) { for _, tc := range trimTests { name := tc.f var f func([]byte, string) []byte + var fb func([]byte, []byte) []byte switch name { case "Trim": f = Trim @@ -833,12 +914,21 @@ func TestTrim(t *testing.T) { f = TrimLeft case "TrimRight": f = TrimRight + case "TrimPrefix": + fb = TrimPrefix + case "TrimSuffix": + fb = TrimSuffix default: t.Errorf("Undefined trim function %s", name) } - actual := string(f([]byte(tc.in), tc.cutset)) + var actual string + if f != nil { + actual = string(f([]byte(tc.in), tc.arg)) + } else { + actual = string(fb([]byte(tc.in), []byte(tc.arg))) + } if actual != tc.out { - t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out) + t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out) } } } @@ -1059,3 +1149,10 @@ func BenchmarkFieldsFunc(b *testing.B) { FieldsFunc(fieldsInput, unicode.IsSpace) } } + +func BenchmarkTrimSpace(b *testing.B) { + s := []byte(" Some text. \n") + for i := 0; i < b.N; i++ { + TrimSpace(s) + } +} diff --git a/libgo/go/bytes/equal_test.go b/libgo/go/bytes/equal_test.go new file mode 100644 index 00000000000..1bf19a74b80 --- /dev/null +++ b/libgo/go/bytes/equal_test.go @@ -0,0 +1,47 @@ +// 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 + +package bytes_test + +import ( + . "bytes" + "syscall" + "testing" + "unsafe" +) + +// This file tests the situation where memeq is checking +// data very near to a page boundary. We want to make sure +// equal does not read across the boundary and cause a page +// fault where it shouldn't. + +// This test runs only on linux. The code being tested is +// not OS-specific, so it does not need to be tested on all +// operating systems. + +func TestEqualNearPageBoundary(t *testing.T) { + pagesize := syscall.Getpagesize() + b := make([]byte, 4*pagesize) + i := pagesize + for ; uintptr(unsafe.Pointer(&b[i]))%uintptr(pagesize) != 0; i++ { + } + syscall.Mprotect(b[i-pagesize:i], 0) + syscall.Mprotect(b[i+pagesize:i+2*pagesize], 0) + defer syscall.Mprotect(b[i-pagesize:i], syscall.PROT_READ|syscall.PROT_WRITE) + defer syscall.Mprotect(b[i+pagesize:i+2*pagesize], syscall.PROT_READ|syscall.PROT_WRITE) + + // both of these should fault + //pagesize += int(b[i-1]) + //pagesize += int(b[i+pagesize]) + + for j := 0; j < pagesize; j++ { + b[i+j] = 'A' + } + for j := 0; j <= pagesize; j++ { + Equal(b[i:i+j], b[i+pagesize-j:i+pagesize]) + Equal(b[i+pagesize-j:i+pagesize], b[i:i+j]) + } +} diff --git a/libgo/go/bytes/example_test.go b/libgo/go/bytes/example_test.go index dc66b6a40f6..ad2dbc69b77 100644 --- a/libgo/go/bytes/example_test.go +++ b/libgo/go/bytes/example_test.go @@ -66,3 +66,20 @@ func ExampleCompare_search() { // Found it! } } + +func ExampleTrimSuffix() { + var b = []byte("Hello, goodbye, etc!") + b = bytes.TrimSuffix(b, []byte("goodbye, etc!")) + b = bytes.TrimSuffix(b, []byte("gopher")) + b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...) + os.Stdout.Write(b) + // Output: Hello, world! +} + +func ExampleTrimPrefix() { + var b = []byte("Goodbye,, world!") + b = bytes.TrimPrefix(b, []byte("Goodbye,")) + b = bytes.TrimPrefix(b, []byte("See ya,")) + fmt.Printf("Hello%s", b) + // Output: Hello, world! +} diff --git a/libgo/go/bytes/export_test.go b/libgo/go/bytes/export_test.go index f61523e60bb..3b915d5ead8 100644 --- a/libgo/go/bytes/export_test.go +++ b/libgo/go/bytes/export_test.go @@ -7,3 +7,7 @@ package bytes // Export func for testing var IndexBytePortable = indexBytePortable var EqualPortable = equalPortable + +func (b *Buffer) Cap() int { + return cap(b.buf) +} diff --git a/libgo/go/compress/bzip2/huffman.go b/libgo/go/compress/bzip2/huffman.go index 078c1cb8954..f755019bb50 100644 --- a/libgo/go/compress/bzip2/huffman.go +++ b/libgo/go/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/libgo/go/compress/flate/deflate_test.go b/libgo/go/compress/flate/deflate_test.go index 8f4e196b427..8c4a6d6b36f 100644 --- a/libgo/go/compress/flate/deflate_test.go +++ b/libgo/go/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/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go index a8d64601925..beca34b4d8c 100644 --- a/libgo/go/compress/flate/inflate.go +++ b/libgo/go/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/libgo/go/compress/flate/token.go b/libgo/go/compress/flate/token.go index 38aea5fa650..4d491768717 100644 --- a/libgo/go/compress/flate/token.go +++ b/libgo/go/compress/flate/token.go @@ -99,5 +99,4 @@ func offsetCode(off uint32) uint32 { default: return offsetCodes[off>>14] + 28 } - panic("unreachable") } diff --git a/libgo/go/compress/gzip/gunzip.go b/libgo/go/compress/gzip/gunzip.go index 33736f63508..1fb9b0964ce 100644 --- a/libgo/go/compress/gzip/gunzip.go +++ b/libgo/go/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/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go index 3035dfffccf..45558b74289 100644 --- a/libgo/go/compress/gzip/gzip.go +++ b/libgo/go/compress/gzip/gzip.go @@ -28,7 +28,7 @@ type Writer struct { Header w io.Writer level int - compressor io.WriteCloser + compressor *flate.Writer digest hash.Hash32 size uint32 closed bool @@ -191,6 +191,28 @@ func (z *Writer) Write(p []byte) (int, error) { return n, z.err } +// Flush flushes any pending compressed data to the underlying writer. +// +// It is useful mainly in compressed network protocols, to ensure that +// a remote reader has enough data to reconstruct a packet. Flush does +// not return until the data has been written. If the underlying +// writer returns an error, Flush returns that error. +// +// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. +func (z *Writer) Flush() error { + if z.err != nil { + return z.err + } + if z.closed { + return nil + } + if z.compressor == nil { + z.Write(nil) + } + z.err = z.compressor.Flush() + return z.err +} + // Close closes the Writer. It does not close the underlying io.Writer. func (z *Writer) Close() error { if z.err != nil { diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go index 6f7b5936449..4d1af94381c 100644 --- a/libgo/go/compress/gzip/gzip_test.go +++ b/libgo/go/compress/gzip/gzip_test.go @@ -157,3 +157,43 @@ func TestLatin1RoundTrip(t *testing.T) { } } } + +func TestWriterFlush(t *testing.T) { + buf := new(bytes.Buffer) + + w := NewWriter(buf) + w.Comment = "comment" + w.Extra = []byte("extra") + w.ModTime = time.Unix(1e8, 0) + w.Name = "name" + + n0 := buf.Len() + if n0 != 0 { + t.Fatalf("buffer size = %d before writes; want 0", n0) + } + + if err := w.Flush(); err != nil { + t.Fatal(err) + } + + n1 := buf.Len() + if n1 == 0 { + t.Fatal("no data after first flush") + } + + w.Write([]byte("x")) + + n2 := buf.Len() + if n1 != n2 { + t.Fatalf("after writing a single byte, size changed from %d to %d; want no change", n1, n2) + } + + if err := w.Flush(); err != nil { + t.Fatal(err) + } + + n3 := buf.Len() + if n2 == n3 { + t.Fatal("Flush didn't flush any data") + } +} diff --git a/libgo/go/compress/lzw/reader.go b/libgo/go/compress/lzw/reader.go index 0ed742c8977..efbc758f94b 100644 --- a/libgo/go/compress/lzw/reader.go +++ b/libgo/go/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/libgo/go/container/heap/example_test.go b/libgo/go/container/heap/example_test.go deleted file mode 100644 index 70f654a0079..00000000000 --- a/libgo/go/container/heap/example_test.go +++ /dev/null @@ -1,100 +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 example demonstrates a priority queue built using the heap interface. -package heap_test - -import ( - "container/heap" - "fmt" -) - -// An Item is something we manage in a priority queue. -type Item struct { - value string // The value of the item; arbitrary. - priority int // The priority of the item in the queue. - // The index is needed by changePriority and is maintained by the heap.Interface methods. - index int // The index of the item in the heap. -} - -// A PriorityQueue implements heap.Interface and holds Items. -type PriorityQueue []*Item - -func (pq PriorityQueue) Len() int { return len(pq) } - -func (pq PriorityQueue) Less(i, j int) bool { - // We want Pop to give us the highest, not lowest, priority so we use greater than here. - return pq[i].priority > pq[j].priority -} - -func (pq PriorityQueue) Swap(i, j int) { - pq[i], pq[j] = pq[j], pq[i] - pq[i].index = i - pq[j].index = j -} - -func (pq *PriorityQueue) Push(x interface{}) { - // Push and Pop use pointer receivers because they modify the slice's length, - // not just its contents. - n := len(*pq) - item := x.(*Item) - item.index = n - *pq = append(*pq, item) -} - -func (pq *PriorityQueue) Pop() interface{} { - a := *pq - n := len(a) - item := a[n-1] - item.index = -1 // for safety - *pq = a[0 : n-1] - return item -} - -// update is not used by the example but shows how to take the top item from -// the queue, update its priority and value, and put it back. -func (pq *PriorityQueue) update(value string, priority int) { - item := heap.Pop(pq).(*Item) - item.value = value - item.priority = priority - heap.Push(pq, item) -} - -// changePriority is not used by the example but shows how to change the -// priority of an arbitrary item. -func (pq *PriorityQueue) changePriority(item *Item, priority int) { - heap.Remove(pq, item.index) - item.priority = priority - heap.Push(pq, item) -} - -// This example pushes 10 items into a PriorityQueue and takes them out in -// order of priority. -func Example() { - const nItem = 10 - // Random priorities for the items (a permutation of 0..9, times 11)). - priorities := [nItem]int{ - 77, 22, 44, 55, 11, 88, 33, 99, 00, 66, - } - values := [nItem]string{ - "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", - } - // Create a priority queue and put some items in it. - pq := make(PriorityQueue, 0, nItem) - for i := 0; i < cap(pq); i++ { - item := &Item{ - value: values[i], - priority: priorities[i], - } - heap.Push(&pq, item) - } - // Take the items out; should arrive in decreasing priority order. - // For example, the highest priority (99) is the seventh item, so output starts with 99:"seven". - for i := 0; i < nItem; i++ { - item := heap.Pop(&pq).(*Item) - fmt.Printf("%.2d:%s ", item.priority, item.value) - } - // Output: - // 99:seven 88:five 77:zero 66:nine 55:three 44:two 33:six 22:one 11:four 00:eight -} diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go index bbaf40a989d..c37e50e3c40 100644 --- a/libgo/go/container/heap/heap.go +++ b/libgo/go/container/heap/heap.go @@ -4,13 +4,13 @@ // Package heap provides heap operations for any type that implements // heap.Interface. A heap is a tree with the property that each node is the -// highest-valued node in its subtree. +// minimum-valued node in its subtree. // // A heap is a common way to implement a priority queue. To build a priority // queue, implement the Heap interface with the (negative) priority as the // ordering for the Less method, so Push adds items while Pop removes the // highest-priority item from the queue. The Examples include such an -// implementation; the file example_test.go has the complete source. +// implementation; the file example_pq_test.go has the complete source. // package heap @@ -90,7 +90,7 @@ func up(h Interface, j int) { func down(h Interface, i, n int) { for { j1 := 2*i + 1 - if j1 >= n { + if j1 >= n || j1 < 0 { // j1 < 0 after int overflow break } j := j1 // left child diff --git a/libgo/go/container/heap/heap_test.go b/libgo/go/container/heap/heap_test.go index 73f33e8d2cf..274d587d874 100644 --- a/libgo/go/container/heap/heap_test.go +++ b/libgo/go/container/heap/heap_test.go @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package heap_test +package heap import ( - . "container/heap" "testing" ) diff --git a/libgo/go/crypto/cipher/cbc.go b/libgo/go/crypto/cipher/cbc.go index 6fab9b42131..913a5643f22 100644 --- a/libgo/go/crypto/cipher/cbc.go +++ b/libgo/go/crypto/cipher/cbc.go @@ -42,6 +42,12 @@ func NewCBCEncrypter(b Block, iv []byte) BlockMode { func (x *cbcEncrypter) BlockSize() int { return x.blockSize } func (x *cbcEncrypter) CryptBlocks(dst, src []byte) { + if len(src)%x.blockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } for len(src) > 0 { for i := 0; i < x.blockSize; i++ { x.iv[i] ^= src[i] @@ -70,6 +76,12 @@ func NewCBCDecrypter(b Block, iv []byte) BlockMode { func (x *cbcDecrypter) BlockSize() int { return x.blockSize } func (x *cbcDecrypter) CryptBlocks(dst, src []byte) { + if len(src)%x.blockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } for len(src) > 0 { x.b.Decrypt(x.tmp, src[:x.blockSize]) for i := 0; i < x.blockSize; i++ { diff --git a/libgo/go/crypto/cipher/cipher_test.go b/libgo/go/crypto/cipher/cipher_test.go new file mode 100644 index 00000000000..8da5bce93ff --- /dev/null +++ b/libgo/go/crypto/cipher/cipher_test.go @@ -0,0 +1,36 @@ +// 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 cipher_test + +import ( + "crypto/aes" + "crypto/cipher" + "testing" +) + +func TestCryptBlocks(t *testing.T) { + buf := make([]byte, 16) + block, _ := aes.NewCipher(buf) + + mode := cipher.NewCBCDecrypter(block, buf) + mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) }) + mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) }) + + mode = cipher.NewCBCEncrypter(block, buf) + mustPanic(t, "crypto/cipher: input not full blocks", func() { mode.CryptBlocks(buf, buf[:3]) }) + mustPanic(t, "crypto/cipher: output smaller than input", func() { mode.CryptBlocks(buf[:3], buf) }) +} + +func mustPanic(t *testing.T, msg string, f func()) { + defer func() { + err := recover() + if err == nil { + t.Errorf("function did not panic, wanted %q", msg) + } else if err != msg { + t.Errorf("got panic %v, wanted %q", err, msg) + } + }() + f() +} diff --git a/libgo/go/crypto/cipher/example_test.go b/libgo/go/crypto/cipher/example_test.go index e0027cac23b..373f6791be4 100644 --- a/libgo/go/crypto/cipher/example_test.go +++ b/libgo/go/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/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go index 05766a2f136..5a2a65744ed 100644 --- a/libgo/go/crypto/dsa/dsa.go +++ b/libgo/go/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/libgo/go/crypto/dsa/dsa_test.go b/libgo/go/crypto/dsa/dsa_test.go index 177aa444dfd..568416d0dfb 100644 --- a/libgo/go/crypto/dsa/dsa_test.go +++ b/libgo/go/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/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index 512d20c635c..25500022939 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -49,7 +49,7 @@ func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) return } -// GenerateKey generates a public&private key pair. +// GenerateKey generates a public and private key pair. func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error) { k, err := randFieldElement(c, rand) if err != nil { diff --git a/libgo/go/crypto/md5/gen.go b/libgo/go/crypto/md5/gen.go index 966bdae267b..275b4aeea39 100644 --- a/libgo/go/crypto/md5/gen.go +++ b/libgo/go/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/libgo/go/crypto/md5/md5_test.go b/libgo/go/crypto/md5/md5_test.go index cac39ad054b..3ef4519b9ad 100644 --- a/libgo/go/crypto/md5/md5_test.go +++ b/libgo/go/crypto/md5/md5_test.go @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package md5_test +package md5 import ( - "crypto/md5" "fmt" "io" "testing" @@ -54,7 +53,7 @@ var golden = []md5Test{ func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] - c := md5.New() + c := New() buf := make([]byte, len(g.in)+4) for j := 0; j < 3+4; j++ { if j < 2 { @@ -79,14 +78,14 @@ func TestGolden(t *testing.T) { } func ExampleNew() { - h := md5.New() + h := New() io.WriteString(h, "The fog is getting thicker!") io.WriteString(h, "And Leon's getting laaarger!") fmt.Printf("%x", h.Sum(nil)) // Output: e2c569be17396eca2a2e3c11578123ed } -var bench = md5.New() +var bench = New() var buf = make([]byte, 8192+1) var sum = make([]byte, bench.Size()) diff --git a/libgo/go/crypto/md5/md5block.go b/libgo/go/crypto/md5/md5block.go index 0ca42177403..a376fbee99b 100644 --- a/libgo/go/crypto/md5/md5block.go +++ b/libgo/go/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/libgo/go/crypto/md5/md5block_decl.go b/libgo/go/crypto/md5/md5block_decl.go new file mode 100644 index 00000000000..14190c6ff29 --- /dev/null +++ b/libgo/go/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/libgo/go/crypto/rand/util.go b/libgo/go/crypto/rand/util.go index 50e5b162bdd..0cd5e0e022f 100644 --- a/libgo/go/crypto/rand/util.go +++ b/libgo/go/crypto/rand/util.go @@ -98,12 +98,13 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) { return } } - - return } -// Int returns a uniform random value in [0, max). +// Int returns a uniform random value in [0, max). It panics if max <= 0. func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) { + if max.Sign() <= 0 { + panic("crypto/rand: argument to Int is <= 0") + } k := (max.BitLen() + 7) / 8 // b is the number of bits in the most significant byte of max. @@ -130,6 +131,4 @@ func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) { return } } - - return } diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go index 1bb278f74a4..3d717c63b0c 100644 --- a/libgo/go/crypto/rc4/rc4.go +++ b/libgo/go/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,27 +32,16 @@ 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 } -// 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. -func (c *Cipher) XORKeyStream(dst, src []byte) { - for i := range src { - c.i += 1 - c.j += c.s[c.i] - c.s[c.i], c.s[c.j] = c.s[c.j], c.s[c.i] - dst[i] = src[i] ^ c.s[c.s[c.i]+c.s[c.j]] - } -} - // Reset zeros the key data so that it will no longer appear in the // process's memory. func (c *Cipher) Reset() { diff --git a/libgo/go/crypto/rc4/rc4_asm.go b/libgo/go/crypto/rc4/rc4_asm.go new file mode 100644 index 00000000000..c582a4488b8 --- /dev/null +++ b/libgo/go/crypto/rc4/rc4_asm.go @@ -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 amd64 arm 386 + +package rc4 + +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. +func (c *Cipher) XORKeyStream(dst, src []byte) { + if len(src) == 0 { + return + } + xorKeyStream(&dst[0], &src[0], len(src), &c.s, &c.i, &c.j) +} diff --git a/libgo/go/crypto/rc4/rc4_ref.go b/libgo/go/crypto/rc4/rc4_ref.go new file mode 100644 index 00000000000..13d52b95dd3 --- /dev/null +++ b/libgo/go/crypto/rc4/rc4_ref.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. + +// +build !amd64,!arm,!386 + +package rc4 + +// 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. +func (c *Cipher) XORKeyStream(dst, src []byte) { + i, j := c.i, c.j + for k, v := range src { + i += 1 + j += uint8(c.s[i]) + c.s[i], c.s[j] = c.s[j], c.s[i] + dst[k] = v ^ byte(c.s[byte(c.s[i]+c.s[j])]) + } + c.i, c.j = i, j +} diff --git a/libgo/go/crypto/rc4/rc4_test.go b/libgo/go/crypto/rc4/rc4_test.go index 6265d9408f4..7b4df6791d9 100644 --- a/libgo/go/crypto/rc4/rc4_test.go +++ b/libgo/go/crypto/rc4/rc4_test.go @@ -5,6 +5,8 @@ package rc4 import ( + "bytes" + "fmt" "testing" ) @@ -37,23 +39,124 @@ var golden = []rc4Test{ []byte{0x57, 0x69, 0x6b, 0x69}, []byte{0x60, 0x44, 0xdb, 0x6d, 0x41, 0xb7}, }, + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + []byte{ + 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a, + 0x8a, 0x06, 0x1e, 0x67, 0x57, 0x6e, 0x92, 0x6d, + 0xc7, 0x1a, 0x7f, 0xa3, 0xf0, 0xcc, 0xeb, 0x97, + 0x45, 0x2b, 0x4d, 0x32, 0x27, 0x96, 0x5f, 0x9e, + 0xa8, 0xcc, 0x75, 0x07, 0x6d, 0x9f, 0xb9, 0xc5, + 0x41, 0x7a, 0xa5, 0xcb, 0x30, 0xfc, 0x22, 0x19, + 0x8b, 0x34, 0x98, 0x2d, 0xbb, 0x62, 0x9e, 0xc0, + 0x4b, 0x4f, 0x8b, 0x05, 0xa0, 0x71, 0x08, 0x50, + 0x92, 0xa0, 0xc3, 0x58, 0x4a, 0x48, 0xe4, 0xa3, + 0x0a, 0x39, 0x7b, 0x8a, 0xcd, 0x1d, 0x00, 0x9e, + 0xc8, 0x7d, 0x68, 0x11, 0xf2, 0x2c, 0xf4, 0x9c, + 0xa3, 0xe5, 0x93, 0x54, 0xb9, 0x45, 0x15, 0x35, + 0xa2, 0x18, 0x7a, 0x86, 0x42, 0x6c, 0xca, 0x7d, + 0x5e, 0x82, 0x3e, 0xba, 0x00, 0x44, 0x12, 0x67, + 0x12, 0x57, 0xb8, 0xd8, 0x60, 0xae, 0x4c, 0xbd, + 0x4c, 0x49, 0x06, 0xbb, 0xc5, 0x35, 0xef, 0xe1, + 0x58, 0x7f, 0x08, 0xdb, 0x33, 0x95, 0x5c, 0xdb, + 0xcb, 0xad, 0x9b, 0x10, 0xf5, 0x3f, 0xc4, 0xe5, + 0x2c, 0x59, 0x15, 0x65, 0x51, 0x84, 0x87, 0xfe, + 0x08, 0x4d, 0x0e, 0x3f, 0x03, 0xde, 0xbc, 0xc9, + 0xda, 0x1c, 0xe9, 0x0d, 0x08, 0x5c, 0x2d, 0x8a, + 0x19, 0xd8, 0x37, 0x30, 0x86, 0x16, 0x36, 0x92, + 0x14, 0x2b, 0xd8, 0xfc, 0x5d, 0x7a, 0x73, 0x49, + 0x6a, 0x8e, 0x59, 0xee, 0x7e, 0xcf, 0x6b, 0x94, + 0x06, 0x63, 0xf4, 0xa6, 0xbe, 0xe6, 0x5b, 0xd2, + 0xc8, 0x5c, 0x46, 0x98, 0x6c, 0x1b, 0xef, 0x34, + 0x90, 0xd3, 0x7b, 0x38, 0xda, 0x85, 0xd3, 0x2e, + 0x97, 0x39, 0xcb, 0x23, 0x4a, 0x2b, 0xe7, 0x40, + }, + }, +} + +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", i) - 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) + if err != nil { + panic(err) + } + b.SetBytes(size) + + for i := 0; i < b.N; i++ { + c.XORKeyStream(buf, buf) + } +} + +func BenchmarkRC4_128(b *testing.B) { + benchmark(b, 128) +} + +func BenchmarkRC4_1K(b *testing.B) { + benchmark(b, 1024) +} + +func BenchmarkRC4_8K(b *testing.B) { + benchmark(b, 8096) +} diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go index 543070f90fb..f56fb37ee54 100644 --- a/libgo/go/crypto/rsa/rsa.go +++ b/libgo/go/crypto/rsa/rsa.go @@ -150,6 +150,20 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (priv *Priva NextSetOfPrimes: for { todo := bits + // crypto/rand should set the top two bits in each prime. + // Thus each prime has the form + // p_i = 2^bitlen(p_i) × 0.11... (in base 2). + // And the product is: + // P = 2^todo × α + // where α is the product of nprimes numbers of the form 0.11... + // + // If α < 1/2 (which can happen for nprimes > 2), we need to + // shift todo to compensate for lost bits: the mean value of 0.11... + // is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2 + // will give good results. + if nprimes >= 7 { + todo += (nprimes - 2) / 5 + } for i := 0; i < nprimes; i++ { primes[i], err = rand.Prime(random, todo/(nprimes-i)) if err != nil { @@ -176,8 +190,9 @@ NextSetOfPrimes: totient.Mul(totient, pminus1) } if n.BitLen() != bits { - // This should never happen because crypto/rand should - // set the top two bits in each prime. + // This should never happen for nprimes == 2 because + // crypto/rand should set the top two bits in each prime. + // For nprimes > 2 we hope it does not happen often. continue NextSetOfPrimes } @@ -188,7 +203,9 @@ NextSetOfPrimes: g.GCD(priv.D, y, e, totient) if g.Cmp(bigOne) == 0 { - priv.D.Add(priv.D, totient) + if priv.D.Sign() < 0 { + priv.D.Add(priv.D, totient) + } priv.Primes = primes priv.N = n diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go index 9be22a8f0bf..ffd96e62f64 100644 --- a/libgo/go/crypto/rsa/rsa_test.go +++ b/libgo/go/crypto/rsa/rsa_test.go @@ -28,11 +28,11 @@ func TestKeyGeneration(t *testing.T) { } func Test3PrimeKeyGeneration(t *testing.T) { + size := 768 if testing.Short() { - return + size = 256 } - size := 768 priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size) if err != nil { t.Errorf("failed to generate key") @@ -41,11 +41,11 @@ func Test3PrimeKeyGeneration(t *testing.T) { } func Test4PrimeKeyGeneration(t *testing.T) { + size := 768 if testing.Short() { - return + size = 256 } - size := 768 priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size) if err != nil { t.Errorf("failed to generate key") @@ -53,6 +53,24 @@ func Test4PrimeKeyGeneration(t *testing.T) { testKeyBasics(t, priv) } +func TestNPrimeKeyGeneration(t *testing.T) { + primeSize := 64 + maxN := 24 + if testing.Short() { + primeSize = 16 + maxN = 16 + } + // Test that generation of N-prime keys works for N > 4. + for n := 5; n < maxN; n++ { + priv, err := GenerateMultiPrimeKey(rand.Reader, n, 64+n*primeSize) + if err == nil { + testKeyBasics(t, priv) + } else { + t.Errorf("failed to generate %d-prime key", n) + } + } +} + func TestGnuTLSKey(t *testing.T) { // This is a key generated by `certtool --generate-privkey --bits 128`. // It's such that de ≢ 1 mod φ(n), but is congruent mod the order of @@ -75,6 +93,9 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { if err := priv.Validate(); err != nil { t.Errorf("Validate() failed: %s", err) } + if priv.D.Cmp(priv.N) > 0 { + t.Errorf("private exponent too large") + } pub := &priv.PublicKey m := big.NewInt(42) diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go index 58541127784..57cd4313eb2 100644 --- a/libgo/go/crypto/sha1/sha1_test.go +++ b/libgo/go/crypto/sha1/sha1_test.go @@ -4,10 +4,9 @@ // SHA1 hash algorithm. See RFC 3174. -package sha1_test +package sha1 import ( - "crypto/sha1" "fmt" "io" "testing" @@ -55,7 +54,7 @@ var golden = []sha1Test{ func TestGolden(t *testing.T) { for i := 0; i < len(golden); i++ { g := golden[i] - c := sha1.New() + c := New() for j := 0; j < 3; j++ { if j < 2 { io.WriteString(c, g.in) @@ -74,13 +73,13 @@ func TestGolden(t *testing.T) { } func ExampleNew() { - h := sha1.New() + h := New() io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.") fmt.Printf("% x", h.Sum(nil)) // Output: 59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd } -var bench = sha1.New() +var bench = New() var buf = make([]byte, 8192) func benchmarkSize(b *testing.B, size int) { diff --git a/libgo/go/crypto/sha1/sha1block.go b/libgo/go/crypto/sha1/sha1block.go index 1c9507c68e5..92224fc0ef8 100644 --- a/libgo/go/crypto/sha1/sha1block.go +++ b/libgo/go/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/libgo/go/crypto/sha1/sha1block_decl.go b/libgo/go/crypto/sha1/sha1block_decl.go new file mode 100644 index 00000000000..3512a582991 --- /dev/null +++ b/libgo/go/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/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go index a888df762db..f86c90de74d 100644 --- a/libgo/go/crypto/tls/common.go +++ b/libgo/go/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/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go index 84be5bfd856..215644d2435 100644 --- a/libgo/go/crypto/tls/generate_cert.go +++ b/libgo/go/crypto/tls/generate_cert.go @@ -16,36 +16,80 @@ import ( "crypto/x509/pkix" "encoding/pem" "flag" + "fmt" "log" "math/big" + "net" "os" + "strings" "time" ) -var hostName *string = flag.String("host", "127.0.0.1", "Hostname to generate a certificate for") +var ( + host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") + validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") + validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") + isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") + rsaBits = flag.Int("rsa-bits", 1024, "Size of RSA key to generate") +) func main() { flag.Parse() - priv, err := rsa.GenerateKey(rand.Reader, 1024) + if len(*host) == 0 { + log.Fatalf("Missing required --host parameter") + } + + priv, err := rsa.GenerateKey(rand.Reader, *rsaBits) if err != nil { log.Fatalf("failed to generate private key: %s", err) return } - now := time.Now() + var notBefore time.Time + if len(*validFrom) == 0 { + notBefore = time.Now() + } else { + notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err) + os.Exit(1) + } + } + + notAfter := notBefore.Add(*validFor) + + // end of ASN.1 time + endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) + if notAfter.After(endOfTime) { + notAfter = endOfTime + } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ - CommonName: *hostName, Organization: []string{"Acme Co"}, }, - NotBefore: now.Add(-5 * time.Minute).UTC(), - NotAfter: now.AddDate(1, 0, 0).UTC(), // valid for 1 year. + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + + hosts := strings.Split(*host, ",") + for _, h := range hosts { + if ip := net.ParseIP(h); ip != nil { + template.IPAddresses = append(template.IPAddresses, ip) + } else { + template.DNSNames = append(template.DNSNames, h) + } + } - SubjectKeyId: []byte{1, 2, 3, 4}, - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + if *isCA { + template.IsCA = true + template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go index 730991016aa..823730c605c 100644 --- a/libgo/go/crypto/tls/handshake_server.go +++ b/libgo/go/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/libgo/go/crypto/x509/pkcs8.go b/libgo/go/crypto/x509/pkcs8.go index 30caacb3c54..8e1585e15cc 100644 --- a/libgo/go/crypto/x509/pkcs8.go +++ b/libgo/go/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/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go index 51be5feb063..b29ddbc80f0 100644 --- a/libgo/go/crypto/x509/verify.go +++ b/libgo/go/crypto/x509/verify.go @@ -5,6 +5,7 @@ package x509 import ( + "net" "runtime" "strings" "time" @@ -63,14 +64,28 @@ type HostnameError struct { } func (h HostnameError) Error() string { - var valid string c := h.Certificate - if len(c.DNSNames) > 0 { - valid = strings.Join(c.DNSNames, ", ") + + var valid string + if ip := net.ParseIP(h.Host); ip != nil { + // Trying to validate an IP + if len(c.IPAddresses) == 0 { + return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs" + } + for _, san := range c.IPAddresses { + if len(valid) > 0 { + valid += ", " + } + valid += san.String() + } } else { - valid = c.Subject.CommonName + if len(c.DNSNames) > 0 { + valid = strings.Join(c.DNSNames, ", ") + } else { + valid = c.Subject.CommonName + } } - return "certificate is valid for " + valid + ", not " + h.Host + return "x509: certificate is valid for " + valid + ", not " + h.Host } // UnknownAuthorityError results when the certificate issuer is unknown @@ -334,6 +349,22 @@ func toLowerCaseASCII(in string) string { // VerifyHostname returns nil if c is a valid certificate for the named host. // Otherwise it returns an error describing the mismatch. func (c *Certificate) VerifyHostname(h string) error { + // IP addresses may be written in [ ]. + candidateIP := h + if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { + candidateIP = h[1 : len(h)-1] + } + if ip := net.ParseIP(candidateIP); ip != nil { + // We only match IP addresses against IP SANs. + // https://tools.ietf.org/html/rfc6125#appendix-B.2 + for _, candidate := range c.IPAddresses { + if ip.Equal(candidate) { + return nil + } + } + return HostnameError{c, candidateIP} + } + lowered := toLowerCaseASCII(h) if len(c.DNSNames) > 0 { @@ -389,6 +420,14 @@ func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { for _, usage := range cert.ExtKeyUsage { if requestedUsage == usage { continue NextRequestedUsage + } else if requestedUsage == ExtKeyUsageServerAuth && + (usage == ExtKeyUsageNetscapeServerGatedCrypto || + usage == ExtKeyUsageMicrosoftServerGatedCrypto) { + // In order to support COMODO + // certificate chains, we have to + // accept Netscape or Microsoft SGC + // usages as equal to ServerAuth. + continue NextRequestedUsage } } diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go index 631a0f84981..5103ed814aa 100644 --- a/libgo/go/crypto/x509/verify_test.go +++ b/libgo/go/crypto/x509/verify_test.go @@ -158,6 +158,19 @@ var verifyTests = []verifyTest{ {"Ryan Hurst", "GlobalSign PersonalSign 2 CA - G2"}, }, }, + { + leaf: megaLeaf, + intermediates: []string{comodoIntermediate1}, + roots: []string{comodoRoot}, + currentTime: 1360431182, + + // CryptoAPI can find alternative validation paths so we don't + // perform this test with system validation. + systemSkip: true, + expectedChains: [][]string{ + {"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"}, + }, + }, } func expectHostnameError(t *testing.T, i int, err error) (ok bool) { @@ -563,3 +576,90 @@ YEvTWbWwGdPytDFPYIl3/6OqNSXSnZ7DxPcdLJq2uyiga8PB/TTIIHYkdM2+1DE0 7y3rH/7TjwDVD7SLu5/SdOfKskuMPTjOEvz3K161mymW06klVhubCIWOro/Gx1Q2 2FQOZ7/2k4uYoOdBTSlb8kTAuzZNgIE0rB2BIYCTz/P6zZIKW0ogbRSH -----END CERTIFICATE-----` + +var megaLeaf = `-----BEGIN CERTIFICATE----- +MIIFOjCCBCKgAwIBAgIQWYE8Dup170kZ+k11Lg51OjANBgkqhkiG9w0BAQUFADBy +MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD +VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEYMBYGA1UE +AxMPRXNzZW50aWFsU1NMIENBMB4XDTEyMTIxNDAwMDAwMFoXDTE0MTIxNDIzNTk1 +OVowfzEhMB8GA1UECxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMS4wLAYDVQQL +EyVIb3N0ZWQgYnkgSW5zdHJhIENvcnBvcmF0aW9uIFB0eS4gTFREMRUwEwYDVQQL +EwxFc3NlbnRpYWxTU0wxEzARBgNVBAMTCm1lZ2EuY28ubnowggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDcxMCClae8BQIaJHBUIVttlLvhbK4XhXPk3RQ3 +G5XA6tLZMBQ33l3F9knYJ0YErXtr8IdfYoulRQFmKFMJl9GtWyg4cGQi2Rcr5VN5 +S5dA1vu4oyJBxE9fPELcK6Yz1vqaf+n6za+mYTiQYKggVdS8/s8hmNuXP9Zk1pIn ++q0pGsf8NAcSHMJgLqPQrTDw+zae4V03DvcYfNKjuno88d2226ld7MAmQZ7uRNsI +/CnkdelVs+akZsXf0szefSqMJlf08SY32t2jj4Ra7RApVYxOftD9nij/aLfuqOU6 +ow6IgIcIG2ZvXLZwK87c5fxL7UAsTTV+M1sVv8jA33V2oKLhAgMBAAGjggG9MIIB +uTAfBgNVHSMEGDAWgBTay+qtWwhdzP/8JlTOSeVVxjj0+DAdBgNVHQ4EFgQUmP9l +6zhyrZ06Qj4zogt+6LKFk4AwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAw +NAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3CgMDBglghkgB +hvhCBAEwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQICBzArMCkGCCsGAQUFBwIBFh1o +dHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAIBgZngQwBAgEwOwYDVR0fBDQw +MjAwoC6gLIYqaHR0cDovL2NybC5jb21vZG9jYS5jb20vRXNzZW50aWFsU1NMQ0Eu +Y3JsMG4GCCsGAQUFBwEBBGIwYDA4BggrBgEFBQcwAoYsaHR0cDovL2NydC5jb21v +ZG9jYS5jb20vRXNzZW50aWFsU1NMQ0FfMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6 +Ly9vY3NwLmNvbW9kb2NhLmNvbTAlBgNVHREEHjAcggptZWdhLmNvLm56gg53d3cu +bWVnYS5jby5uejANBgkqhkiG9w0BAQUFAAOCAQEAcYhrsPSvDuwihMOh0ZmRpbOE +Gw6LqKgLNTmaYUPQhzi2cyIjhUhNvugXQQlP5f0lp5j8cixmArafg1dTn4kQGgD3 +ivtuhBTgKO1VYB/VRoAt6Lmswg3YqyiS7JiLDZxjoV7KoS5xdiaINfHDUaBBY4ZH +j2BUlPniNBjCqXe/HndUTVUewlxbVps9FyCmH+C4o9DWzdGBzDpCkcmo5nM+cp7q +ZhTIFTvZfo3zGuBoyu8BzuopCJcFRm3cRiXkpI7iOMUIixO1szkJS6WpL1sKdT73 +UXp08U0LBqoqG130FbzEJBBV3ixbvY6BWMHoCWuaoF12KJnC5kHt2RoWAAgMXA== +-----END CERTIFICATE-----` + +var comodoIntermediate1 = `-----BEGIN CERTIFICATE----- +MIIFAzCCA+ugAwIBAgIQGLLLuqME8aAPwfLzJkYqSjANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0xOTEyMzEyMzU5NTlaMHIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh +dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9E +TyBDQSBMaW1pdGVkMRgwFgYDVQQDEw9Fc3NlbnRpYWxTU0wgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt8AiwcsargxIxF3CJhakgEtSYau2A1NHf +5I5ZLdOWIY120j8YC0YZYwvHIPPlC92AGvFaoL0dds23Izp0XmEbdaqb1IX04XiR +0y3hr/yYLgbSeT1awB8hLRyuIVPGOqchfr7tZ291HRqfalsGs2rjsQuqag7nbWzD +ypWMN84hHzWQfdvaGlyoiBSyD8gSIF/F03/o4Tjg27z5H6Gq1huQByH6RSRQXScq +oChBRVt9vKCiL6qbfltTxfEFFld+Edc7tNkBdtzffRDPUanlOPJ7FAB1WfnwWdsX +Pvev5gItpHnBXaIcw5rIp6gLSApqLn8tl2X2xQScRMiZln5+pN0vAgMBAAGjggGD +MIIBfzAfBgNVHSMEGDAWgBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAdBgNVHQ4EFgQU +2svqrVsIXcz//CZUzknlVcY49PgwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI +MAYBAf8CAQAwIAYDVR0lBBkwFwYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMD4GA1Ud +IAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21v +ZG8uY29tL0NQUzBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9kb2Nh +LmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBsBggrBgEFBQcB +AQRgMF4wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NvbW9k +b1VUTlNHQ0NBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2Eu +Y29tMA0GCSqGSIb3DQEBBQUAA4IBAQAtlzR6QDLqcJcvgTtLeRJ3rvuq1xqo2l/z +odueTZbLN3qo6u6bldudu+Ennv1F7Q5Slqz0J790qpL0pcRDAB8OtXj5isWMcL2a +ejGjKdBZa0wztSz4iw+SY1dWrCRnilsvKcKxudokxeRiDn55w/65g+onO7wdQ7Vu +F6r7yJiIatnyfKH2cboZT7g440LX8NqxwCPf3dfxp+0Jj1agq8MLy6SSgIGSH6lv ++Wwz3D5XxqfyH8wqfOQsTEZf6/Nh9yvENZ+NWPU6g0QO2JOsTGvMd/QDzczc4BxL +XSXaPV7Od4rhPsbXlM1wSTz/Dr0ISKvlUhQVnQ6cGodWaK2cCQBk +-----END CERTIFICATE-----` + +var comodoRoot = `-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE-----` diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index 7983217696e..4dfea2c9499 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -19,6 +19,8 @@ import ( "errors" "io" "math/big" + "net" + "strconv" "time" ) @@ -360,16 +362,18 @@ const ( // id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } // id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } var ( - oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0} - oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} - oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2} - oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3} - oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4} - oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5} - oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6} - oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7} - oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} - oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9} + oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0} + oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} + oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2} + oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3} + oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4} + oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5} + oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6} + oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7} + oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} + oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9} + oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3} + oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1} ) // ExtKeyUsage represents an extended set of actions that are valid for a given key. @@ -387,6 +391,8 @@ const ( ExtKeyUsageIPSECUser ExtKeyUsageTimeStamping ExtKeyUsageOCSPSigning + ExtKeyUsageMicrosoftServerGatedCrypto + ExtKeyUsageNetscapeServerGatedCrypto ) // extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID. @@ -404,6 +410,8 @@ var extKeyUsageOIDs = []struct { {ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser}, {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping}, {ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning}, + {ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto}, + {ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto}, } func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) { @@ -458,6 +466,7 @@ type Certificate struct { // Subject Alternate Name values DNSNames []string EmailAddresses []string + IPAddresses []net.IP // Name constraints PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical. @@ -660,6 +669,13 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ return nil, err } + if p.N.Sign() <= 0 { + return nil, errors.New("x509: RSA modulus is not a positive number") + } + if p.E <= 0 { + return nil, errors.New("x509: RSA public exponent is not a positive number") + } + pub := &rsa.PublicKey{ E: p.E, N: p.N, @@ -713,7 +729,6 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ default: return nil, nil } - panic("unreachable") } func parseCertificate(in *certificate) (*Certificate, error) { @@ -828,6 +843,13 @@ func parseCertificate(in *certificate) (*Certificate, error) { case 2: out.DNSNames = append(out.DNSNames, string(v.Bytes)) parsedName = true + case 7: + switch len(v.Bytes) { + case net.IPv4len, net.IPv6len: + out.IPAddresses = append(out.IPAddresses, v.Bytes) + default: + return nil, errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) + } } } @@ -1072,11 +1094,22 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { n++ } - if len(template.DNSNames) > 0 { + if len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 { ret[n].Id = oidExtensionSubjectAltName - rawValues := make([]asn1.RawValue, len(template.DNSNames)) - for i, name := range template.DNSNames { - rawValues[i] = asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)} + var rawValues []asn1.RawValue + for _, name := range template.DNSNames { + rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)}) + } + for _, email := range template.EmailAddresses { + rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)}) + } + for _, rawIP := range template.IPAddresses { + // If possible, we always want to encode IPv4 addresses in 4 bytes. + ip := rawIP.To4() + if ip == nil { + ip = rawIP + } + rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip}) } ret[n].Value, err = asn1.Marshal(rawValues) if err != nil { diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go index b2d6fe3d552..abd4fe84d7e 100644 --- a/libgo/go/crypto/x509/x509_test.go +++ b/libgo/go/crypto/x509/x509_test.go @@ -19,6 +19,7 @@ import ( "encoding/hex" "encoding/pem" "math/big" + "net" "reflect" "testing" "time" @@ -174,6 +175,49 @@ func TestMatchHostnames(t *testing.T) { } } +func TestMatchIP(t *testing.T) { + // Check that pattern matching is working. + c := &Certificate{ + DNSNames: []string{"*.foo.bar.baz"}, + Subject: pkix.Name{ + CommonName: "*.foo.bar.baz", + }, + } + err := c.VerifyHostname("quux.foo.bar.baz") + if err != nil { + t.Fatalf("VerifyHostname(quux.foo.bar.baz): %v", err) + } + + // But check that if we change it to be matching against an IP address, + // it is rejected. + c = &Certificate{ + DNSNames: []string{"*.2.3.4"}, + Subject: pkix.Name{ + CommonName: "*.2.3.4", + }, + } + err = c.VerifyHostname("1.2.3.4") + if err == nil { + t.Fatalf("VerifyHostname(1.2.3.4) should have failed, did not") + } + + c = &Certificate{ + IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}, + } + err = c.VerifyHostname("127.0.0.1") + if err != nil { + t.Fatalf("VerifyHostname(127.0.0.1): %v", err) + } + err = c.VerifyHostname("::1") + if err != nil { + t.Fatalf("VerifyHostname(::1): %v", err) + } + err = c.VerifyHostname("[::1]") + if err != nil { + t.Fatalf("VerifyHostname([::1]): %v", err) + } +} + func TestCertificateParse(t *testing.T) { s, _ := hex.DecodeString(certBytes) certs, err := ParseCertificates(s) @@ -284,8 +328,11 @@ func TestCreateSelfSignedCertificate(t *testing.T) { UnknownExtKeyUsage: testUnknownExtKeyUsage, BasicConstraintsValid: true, - IsCA: true, - DNSNames: []string{"test.example.com"}, + IsCA: true, + + DNSNames: []string{"test.example.com"}, + EmailAddresses: []string{"gopher@golang.org"}, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, PermittedDNSDomains: []string{".example.com", "example.com"}, @@ -327,6 +374,18 @@ func TestCreateSelfSignedCertificate(t *testing.T) { t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage) } + if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) { + t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames) + } + + if !reflect.DeepEqual(cert.EmailAddresses, template.EmailAddresses) { + t.Errorf("%s: SAN emails differ from template. Got %v, want %v", test.name, cert.EmailAddresses, template.EmailAddresses) + } + + if !reflect.DeepEqual(cert.IPAddresses, template.IPAddresses) { + t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses) + } + if test.checkSig { err = cert.CheckSignatureFrom(cert) if err != nil { diff --git a/libgo/go/database/sql/convert.go b/libgo/go/database/sql/convert.go index 964dc184850..c04adde1fc1 100644 --- a/libgo/go/database/sql/convert.go +++ b/libgo/go/database/sql/convert.go @@ -14,12 +14,18 @@ import ( "strconv" ) +var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error + // 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. @@ -58,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) } @@ -75,34 +83,68 @@ func driverArgs(si driver.Stmt, args []interface{}) ([]driver.Value, error) { // An error is returned if the copy would result in loss of information. // dest should be a pointer type. func convertAssign(dest, src interface{}) error { - // Common cases, without reflect. Fall through. + // Common cases, without reflect. switch s := src.(type) { case string: switch d := dest.(type) { case *string: + if d == nil { + return errNilPtr + } *d = s return nil case *[]byte: + if d == nil { + return errNilPtr + } *d = []byte(s) return nil } case []byte: switch d := dest.(type) { case *string: + if d == nil { + return errNilPtr + } *d = string(s) return nil case *interface{}: - bcopy := make([]byte, len(s)) - copy(bcopy, s) - *d = bcopy + if d == nil { + return errNilPtr + } + *d = cloneBytes(s) return nil case *[]byte: + if d == nil { + return errNilPtr + } + *d = cloneBytes(s) + return nil + case *RawBytes: + if d == nil { + return errNilPtr + } *d = s return nil } case nil: switch d := dest.(type) { + case *interface{}: + if d == nil { + return errNilPtr + } + *d = nil + return nil case *[]byte: + if d == nil { + return errNilPtr + } + *d = nil + return nil + case *RawBytes: + if d == nil { + return errNilPtr + } *d = nil return nil } @@ -121,6 +163,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 { @@ -140,6 +202,9 @@ func convertAssign(dest, src interface{}) error { if dpv.Kind() != reflect.Ptr { return errors.New("destination not a pointer") } + if dpv.IsNil() { + return errNilPtr + } if !sv.IsValid() { sv = reflect.ValueOf(src) @@ -189,6 +254,16 @@ func convertAssign(dest, src interface{}) error { return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest) } +func cloneBytes(b []byte) []byte { + if b == nil { + return nil + } else { + c := make([]byte, len(b)) + copy(c, b) + return c + } +} + func asString(src interface{}) string { switch v := src.(type) { case string: diff --git a/libgo/go/database/sql/convert_test.go b/libgo/go/database/sql/convert_test.go index 9c362d7320a..950e24fc3a8 100644 --- a/libgo/go/database/sql/convert_test.go +++ b/libgo/go/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`}, @@ -113,6 +143,7 @@ var conversionTests = []conversionTest{ {s: []byte("byteslice"), d: &scaniface, wantiface: []byte("byteslice")}, {s: true, d: &scaniface, wantiface: true}, {s: nil, d: &scaniface}, + {s: []byte(nil), d: &scaniface, wantiface: []byte(nil)}, } func intPtrValue(intptr interface{}) interface{} { @@ -191,7 +222,7 @@ func TestConversions(t *testing.T) { } if srcBytes, ok := ct.s.([]byte); ok { dstBytes := (*ifptr).([]byte) - if &dstBytes[0] == &srcBytes[0] { + if len(srcBytes) > 0 && &dstBytes[0] == &srcBytes[0] { errf("copy into interface{} didn't copy []byte data") } } diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go index 2f5280db810..d7ca94f7809 100644 --- a/libgo/go/database/sql/driver/driver.go +++ b/libgo/go/database/sql/driver/driver.go @@ -10,8 +10,8 @@ package driver import "errors" -// A driver Value is a value that drivers must be able to handle. -// A Value is either nil or an instance of one of these types: +// Value is a value that drivers must be able to handle. +// It is either nil or an instance of one of these types: // // int64 // float64 @@ -56,7 +56,7 @@ var ErrBadConn = errors.New("driver: bad connection") // Execer is an optional interface that may be implemented by a Conn. // -// If a Conn does not implement Execer, the db package's DB.Exec will +// If a Conn does not implement Execer, the sql package's DB.Exec will // first prepare a query, execute the statement, and then close the // statement. // @@ -65,6 +65,17 @@ type Execer interface { Exec(query string, args []Value) (Result, error) } +// Queryer is an optional interface that may be implemented by a Conn. +// +// If a Conn does not implement Queryer, the sql package's DB.Query will +// first prepare a query, execute the statement, and then close the +// statement. +// +// Query may return ErrSkip. +type Queryer interface { + Query(query string, args []Value) (Rows, error) +} + // Conn is a connection to a database. It is not used concurrently // by multiple goroutines. // @@ -104,23 +115,8 @@ type Result interface { type Stmt interface { // Close closes the statement. // - // Closing a statement should not interrupt any outstanding - // query created from that statement. That is, the following - // order of operations is valid: - // - // * create a driver statement - // * call Query on statement, returning Rows - // * close the statement - // * read from Rows - // - // If closing a statement invalidates currently-running - // queries, the final step above will incorrectly fail. - // - // TODO(bradfitz): possibly remove the restriction above, if - // enough driver authors object and find it complicates their - // code too much. The sql package could be smarter about - // refcounting the statement and closing it at the appropriate - // time. + // As of Go 1.1, a Stmt will not be closed if it's in use + // by any queries. Close() error // NumInput returns the number of placeholder parameters. diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go index c38ba7c8492..d900e2cebe8 100644 --- a/libgo/go/database/sql/fakedb_test.go +++ b/libgo/go/database/sql/fakedb_test.go @@ -13,6 +13,7 @@ import ( "strconv" "strings" "sync" + "testing" "time" ) @@ -34,9 +35,10 @@ var _ = log.Printf // When opening a fakeDriver's database, it starts empty with no // tables. All tables and data are stored in memory only. type fakeDriver struct { - mu sync.Mutex - openCount int - dbs map[string]*fakeDB + mu sync.Mutex // guards 3 following fields + openCount int // conn opens + closeCount int // conn closes + dbs map[string]*fakeDB } type fakeDB struct { @@ -229,7 +231,43 @@ func (c *fakeConn) Begin() (driver.Tx, error) { return c.currTx, nil } -func (c *fakeConn) Close() error { +var hookPostCloseConn struct { + sync.Mutex + fn func(*fakeConn, error) +} + +func setHookpostCloseConn(fn func(*fakeConn, error)) { + hookPostCloseConn.Lock() + defer hookPostCloseConn.Unlock() + hookPostCloseConn.fn = fn +} + +var testStrictClose *testing.T + +// setStrictFakeConnClose sets the t to Errorf on when fakeConn.Close +// fails to close. If nil, the check is disabled. +func setStrictFakeConnClose(t *testing.T) { + testStrictClose = t +} + +func (c *fakeConn) Close() (err error) { + drv := fdriver.(*fakeDriver) + defer func() { + if err != nil && testStrictClose != nil { + testStrictClose.Errorf("failed to close a test fakeConn: %v", err) + } + hookPostCloseConn.Lock() + fn := hookPostCloseConn.fn + hookPostCloseConn.Unlock() + if fn != nil { + fn(c, err) + } + if err == nil { + drv.mu.Lock() + drv.closeCount++ + drv.mu.Unlock() + } + }() if c.currTx != nil { return errors.New("can't close fakeConn; in a Transaction") } @@ -266,6 +304,18 @@ func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error return nil, driver.ErrSkip } +func (c *fakeConn) Query(query string, args []driver.Value) (driver.Rows, error) { + // This is an optional interface, but it's implemented here + // just to check that all the args are of the proper types. + // ErrSkip is returned so the caller acts as if we didn't + // implement this at all. + err := checkSubsetTypes(args) + if err != nil { + return nil, err + } + return nil, driver.ErrSkip +} + func errf(msg string, args ...interface{}) error { return errors.New("fakedb: " + fmt.Sprintf(msg, args...)) } @@ -412,6 +462,12 @@ func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter { } func (s *fakeStmt) Close() error { + if s.c == nil { + panic("nil conn in fakeStmt.Close") + } + if s.c.db == nil { + panic("in fakeStmt.Close, conn's db is nil (already closed)") + } if !s.closed { s.c.incrStat(&s.c.stmtsClosed) s.closed = true @@ -503,6 +559,15 @@ func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) { if !ok { return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table) } + + if s.table == "magicquery" { + if len(s.whereCol) == 2 && s.whereCol[0] == "op" && s.whereCol[1] == "millis" { + if args[0] == "sleep" { + time.Sleep(time.Duration(args[1].(int64)) * time.Millisecond) + } + } + } + t.mu.Lock() defer t.mu.Unlock() diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go index 29aef78b240..a80782bfedc 100644 --- a/libgo/go/database/sql/sql.go +++ b/libgo/go/database/sql/sql.go @@ -4,6 +4,9 @@ // Package sql provides a generic interface around SQL (or SQL-like) // databases. +// +// The sql package must be used in conjunction with a database driver. +// See http://golang.org/s/sqldrivers for a list of drivers. package sql import ( @@ -11,6 +14,7 @@ import ( "errors" "fmt" "io" + "runtime" "sync" ) @@ -176,22 +180,197 @@ 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 freeConn and closed - freeConn []driver.Conn + mu sync.Mutex // protects following fields + freeConn []*driverConn closed bool + dep map[finalCloser]depSet + 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 { + db *DB + + sync.Mutex // guards following + ci driver.Conn + closed bool + finalClosed bool // ci.Close has been called + openStmt map[driver.Stmt]bool + + // guarded by db.mu + inUse bool + onPut []func() // code (with db.mu held) run when conn is next returned + dbmuClosed bool // same as closed, but guarded by db.mu, for connIfFree +} + +func (dc *driverConn) removeOpenStmt(si driver.Stmt) { + dc.Lock() + defer dc.Unlock() + delete(dc.openStmt, si) +} + +func (dc *driverConn) prepareLocked(query string) (driver.Stmt, error) { + si, err := dc.ci.Prepare(query) + if err == nil { + // Track each driverConn's open statements, so we can close them + // before closing the conn. + // + // TODO(bradfitz): let drivers opt out of caring about + // stmt closes if the conn is about to close anyway? For now + // do the safe thing, in case stmts need to be closed. + // + // TODO(bradfitz): after Go 1.1, closing driver.Stmts + // should be moved to driverStmt, using unique + // *driverStmts everywhere (including from + // *Stmt.connStmt, instead of returning a + // driver.Stmt), using driverStmt as a pointer + // everywhere, and making it a finalCloser. + if dc.openStmt == nil { + dc.openStmt = make(map[driver.Stmt]bool) + } + dc.openStmt[si] = true + } + return si, err +} + +// the dc.db's Mutex is held. +func (dc *driverConn) closeDBLocked() error { + dc.Lock() + if dc.closed { + dc.Unlock() + return errors.New("sql: duplicate driverConn close") + } + dc.closed = true + dc.Unlock() // not defer; removeDep finalClose calls may need to lock + return dc.db.removeDepLocked(dc, dc)() +} + +func (dc *driverConn) Close() error { + dc.Lock() + if dc.closed { + dc.Unlock() + return errors.New("sql: duplicate driverConn close") + } + dc.closed = true + dc.Unlock() // not defer; removeDep finalClose calls may need to lock + + // And now updates that require holding dc.mu.Lock. + dc.db.mu.Lock() + dc.dbmuClosed = true + fn := dc.db.removeDepLocked(dc, dc) + dc.db.mu.Unlock() + return fn() +} + +func (dc *driverConn) finalClose() error { + dc.Lock() + + for si := range dc.openStmt { + si.Close() + } + dc.openStmt = nil + + err := dc.ci.Close() + dc.ci = nil + dc.finalClosed = true + + dc.Unlock() + return err +} + +// 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 +type depSet map[interface{}]bool // set of true bools + +// The finalCloser interface is used by (*DB).addDep and related +// dependency reference counting. +type finalCloser interface { + // finalClose is called when the reference count of an object + // goes to zero. (*DB).mu is not held while calling it. + finalClose() error +} + +// addDep notes that x now depends on dep, and x's finalClose won't be +// called until all of x's dependencies are removed with removeDep. +func (db *DB) addDep(x finalCloser, dep interface{}) { + //println(fmt.Sprintf("addDep(%T %p, %T %p)", x, x, dep, dep)) + db.mu.Lock() + defer db.mu.Unlock() + db.addDepLocked(x, dep) +} + +func (db *DB) addDepLocked(x finalCloser, dep interface{}) { + if db.dep == nil { + db.dep = make(map[finalCloser]depSet) + } + xdep := db.dep[x] + if xdep == nil { + xdep = make(depSet) + db.dep[x] = xdep + } + xdep[dep] = true +} + +// removeDep notes that x no longer depends on dep. +// If x still has dependencies, nil is returned. +// If x no longer has any dependencies, its finalClose method will be +// called and its error value will be returned. +func (db *DB) removeDep(x finalCloser, dep interface{}) error { + db.mu.Lock() + fn := db.removeDepLocked(x, dep) + db.mu.Unlock() + return fn() +} + +func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error { + //println(fmt.Sprintf("removeDep(%T %p, %T %p)", x, x, dep, dep)) + done := false + + xdep := db.dep[x] + if xdep != nil { + delete(xdep, dep) + if len(xdep) == 0 { + delete(db.dep, x) + done = true + } + } + + if !done { + return func() error { return nil } + } + return func() error { + //println(fmt.Sprintf("calling final close on %T %v (%#v)", x, x, x)) + return x.finalClose() + } } // Open opens a database specified by its database driver name and a @@ -199,13 +378,38 @@ type DB struct { // database name and connection information. // // Most users will open a database via a driver-specific connection -// helper function that returns a *DB. +// helper function that returns a *DB. No database drivers are included +// in the Go standard library. See http://golang.org/s/sqldrivers for +// a list of third-party drivers. +// +// 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) { - driver, ok := drivers[driverName] + driveri, ok := drivers[driverName] if !ok { return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName) } - return &DB{driver: driver, dsn: dataSourceName}, nil + db := &DB{ + driver: driveri, + dsn: dataSourceName, + lastPut: make(map[*driverConn]string), + } + 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. @@ -213,8 +417,8 @@ 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 { + err1 := dc.closeDBLocked() if err1 != nil { err = err1 } @@ -224,15 +428,45 @@ 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 dc.Close() + } } -// 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() @@ -241,53 +475,132 @@ func (db *DB) conn() (driver.Conn, error) { if n := len(db.freeConn); n > 0 { conn := db.freeConn[n-1] db.freeConn = db.freeConn[:n-1] + conn.inUse = true db.mu.Unlock() return conn, nil } db.mu.Unlock() - return db.driver.Open(db.dsn) + + ci, err := db.driver.Open(db.dsn) + if err != nil { + return nil, err + } + dc := &driverConn{ + db: db, + ci: ci, + } + db.mu.Lock() + db.addDepLocked(dc, dc) + dc.inUse = true + db.mu.Unlock() + return dc, nil } -func (db *DB) connIfFree(wanted driver.Conn) (conn driver.Conn, ok bool) { +var ( + errConnClosed = errors.New("database/sql: internal sentinel error: conn is closed") + errConnBusy = errors.New("database/sql: internal sentinel error: conn is busy") +) + +// connIfFree returns (wanted, nil) if wanted is still a valid conn and +// isn't in use. +// +// The error is errConnClosed if the connection if the requested connection +// is invalid because it's been closed. +// +// The error is errConnBusy if the connection is in use. +func (db *DB) connIfFree(wanted *driverConn) (*driverConn, error) { db.mu.Lock() defer db.mu.Unlock() + if wanted.inUse { + return nil, errConnBusy + } + if wanted.dbmuClosed { + return nil, errConnClosed + } for i, conn := range db.freeConn { if conn != wanted { continue } db.freeConn[i] = db.freeConn[len(db.freeConn)-1] db.freeConn = db.freeConn[:len(db.freeConn)-1] - return wanted, true - } - return nil, false + wanted.inUse = true + return wanted, nil + } + // TODO(bradfitz): shouldn't get here. After Go 1.1, change this to: + // panic("connIfFree call requested a non-closed, non-busy, non-free conn") + // Which passes all the tests, but I'm too paranoid to include this + // late in Go 1.1. + // Instead, treat it like a busy connection: + return nil, errConnBusy } // 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 *driverConn, si driver.Stmt) { + db.mu.Lock() + defer db.mu.Unlock() + if c.inUse { + c.onPut = append(c.onPut, func() { + si.Close() + }) + } else { + c.Lock() + defer c.Unlock() + if !c.finalClosed { + si.Close() + } + } +} + +// debugGetPut determines whether getConn & putConn calls' stack traces +// are returned for more verbose crashes. +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 !dc.inUse { + if debugGetPut { + 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[dc] = stack() + } + dc.inUse = false + + for _, fn := range dc.onPut { + fn() + } + dc.onPut = nil + if err == driver.ErrBadConn { // Don't reuse bad connections. + db.mu.Unlock() return } - db.mu.Lock() 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.Close() } -// Prepare creates a prepared statement for later execution. +// Prepare creates a prepared statement for later queries or executions. +// Multiple queries or executions may be run concurrently from the +// returned statement. func (db *DB) Prepare(query string) (*Stmt, error) { var stmt *Stmt var err error @@ -300,34 +613,36 @@ func (db *DB) Prepare(query string) (*Stmt, error) { return stmt, err } -func (db *DB) prepare(query string) (stmt *Stmt, err error) { +func (db *DB) prepare(query string) (*Stmt, error) { // TODO: check if db.driver supports an optional // driver.Preparer interface and call that instead, if so, // otherwise we make a prepared statement that's bound // 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 } - defer func() { - db.putConn(ci, err) - }() - - si, err := ci.Prepare(query) + dc.Lock() + si, err := dc.prepareLocked(query) + dc.Unlock() if err != nil { + db.putConn(dc, err) return nil, err } - stmt = &Stmt{ + 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 } // Exec executes a query without returning any rows. +// The args are for any placeholder parameters in the query. func (db *DB) Exec(query string, args ...interface{}) (Result, error) { var res Result var err error @@ -341,50 +656,119 @@ 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() - - return resultFromStatement(sti, args...) + defer withLock(dc, func() { si.Close() }) + return resultFromStatement(driverStmt{dc, si}, args...) } // Query executes a query that returns rows, typically a SELECT. // The args are for any placeholder parameters in the query. func (db *DB) Query(query string, args ...interface{}) (*Rows, error) { - stmt, err := db.Prepare(query) + var rows *Rows + var err error + for i := 0; i < 10; i++ { + rows, err = db.query(query, args) + if err != driver.ErrBadConn { + break + } + } + return rows, err +} + +func (db *DB) query(query string, args []interface{}) (*Rows, error) { + ci, err := db.conn() + if err != nil { + return nil, err + } + + releaseConn := func(err error) { db.putConn(ci, err) } + + return db.queryConn(ci, releaseConn, query, args) +} + +// queryConn executes a query on the given connection. +// The connection gets released by the releaseConn function. +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 dc passes to the *Rows, to be freed + // with releaseConn. + rows := &Rows{ + dc: dc, + releaseConn: releaseConn, + rowsi: rowsi, + } + return rows, nil + } + } + + dc.Lock() + si, err := dc.ci.Prepare(query) + dc.Unlock() if err != nil { + releaseConn(err) return nil, err } - rows, err := stmt.Query(args...) + + ds := driverStmt{dc, si} + rowsi, err := rowsiFromStatement(ds, args...) if err != nil { - stmt.Close() + releaseConn(err) + dc.Lock() + si.Close() + dc.Unlock() return nil, err } - rows.closeStmt = stmt + + // Note: ownership of ci passes to the *Rows, to be freed + // with releaseConn. + rows := &Rows{ + dc: dc, + releaseConn: releaseConn, + rowsi: rowsi, + closeStmt: si, + } return rows, nil } @@ -411,18 +795,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 } @@ -441,15 +827,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. @@ -463,21 +845,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. @@ -486,6 +863,8 @@ func (tx *Tx) Commit() error { return ErrTxDone } defer tx.close() + tx.dc.Lock() + defer tx.dc.Unlock() return tx.txi.Commit() } @@ -495,6 +874,8 @@ func (tx *Tx) Rollback() error { return ErrTxDone } defer tx.close() + tx.dc.Lock() + defer tx.dc.Unlock() return tx.txi.Rollback() } @@ -518,21 +899,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 @@ -556,16 +941,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, } @@ -574,51 +963,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) { - if tx.done { - return nil, ErrTxDone - } - stmt, err := tx.Prepare(query) + dc, err := tx.grabConn() if err != nil { return nil, err } - rows, err := stmt.Query(args...) - if err != nil { - stmt.Close() - return nil, err - } - rows.closeStmt = stmt - return rows, err + releaseConn := func(error) {} + return tx.db.queryConn(dc, releaseConn, query, args) } // QueryRow executes a query that is expected to return at most one row. @@ -631,7 +1015,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 } @@ -642,9 +1026,11 @@ type Stmt struct { query string // that created the Stmt stickyErr error // if non-nil, this error is returned for all operations + closemu sync.RWMutex // held exclusively during close, for read otherwise. + // 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 @@ -659,39 +1045,47 @@ type Stmt struct { // Exec executes a prepared statement with the given arguments and // returns a Result summarizing the effect of the statement. func (s *Stmt) Exec(args ...interface{}) (Result, error) { - _, releaseConn, si, err := s.connStmt() + s.closemu.RLock() + defer s.closemu.RUnlock() + 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 } @@ -710,19 +1104,27 @@ 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 match := false - 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 { + for i := 0; i < len(s.css); i++ { + v := s.css[i] + _, err := s.db.connIfFree(v.dc) + if err == nil { + match = true cs = v break } + if err == errConnClosed { + // Lazily remove dead conn from our freelist. + s.css[i] = s.css[len(s.css)-1] + s.css = s.css[:len(s.css)-1] + i-- + } + } s.mu.Unlock() @@ -730,11 +1132,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.prepareLocked(s.query) + dc.Unlock() if err == driver.ErrBadConn && i < 10 { continue } @@ -742,14 +1146,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 } @@ -757,37 +1161,60 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(error), si driver.St // Query executes a prepared query statement with the given arguments // and returns the query results as a *Rows. func (s *Stmt) Query(args ...interface{}) (*Rows, error) { - ci, releaseConn, si, err := s.connStmt() + s.closemu.RLock() + defer s.closemu.RUnlock() + + dc, releaseConn, si, err := s.connStmt() + if err != nil { + return nil, err + } + + ds := driverStmt{dc, si} + rowsi, err := rowsiFromStatement(ds, args...) if err != nil { + releaseConn(err) return nil, err } + // Note: ownership of ci passes to the *Rows, to be freed + // with releaseConn. + rows := &Rows{ + dc: dc, + rowsi: rowsi, + // releaseConn set below + } + s.db.addDep(s, rows) + rows.releaseConn = func(err error) { + releaseConn(err) + s.db.removeDep(s, rows) + } + return rows, nil +} + +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 { - releaseConn(err) return nil, err } - // Note: ownership of ci passes to the *Rows, to be freed - // with releaseConn. - rows := &Rows{ - db: s.db, - ci: ci, - releaseConn: releaseConn, - rowsi: rowsi, - } - return rows, nil + return rowsi, nil } // QueryRow executes a prepared query statement with the given arguments. @@ -811,6 +1238,9 @@ func (s *Stmt) QueryRow(args ...interface{}) *Row { // Close closes the statement. func (s *Stmt) Close() error { + s.closemu.Lock() + defer s.closemu.Unlock() + if s.stickyErr != nil { return s.stickyErr } @@ -823,18 +1253,19 @@ func (s *Stmt) Close() error { if s.tx != nil { s.txsi.Close() - } else { - for _, v := range s.css { - if ci, match := s.db.connIfFree(v.ci); match { - v.si.Close() - s.db.putConn(ci, nil) - } else { - // TODO(bradfitz): care that we can't close - // this statement because the statement's - // connection is in use? - } - } + return nil + } + + return s.db.removeDep(s, s) +} + +func (s *Stmt) finalClose() error { + for _, v := range s.css { + s.db.noteUnusedDriverStatement(v.dc, v.si) + v.dc.removeOpenStmt(v.si) + s.db.removeDep(v.dc, s) } + s.css = nil return nil } @@ -852,15 +1283,14 @@ func (s *Stmt) Close() error { // err = rows.Err() // get any error encountered during iteration // ... type Rows struct { - db *DB - ci driver.Conn // owned; must call putconn when closed to release + dc *driverConn // owned; must call releaseConn when closed to release releaseConn func(error) rowsi driver.Rows closed bool lastcols []driver.Value lasterr error - closeStmt *Stmt // if non-nil, statement to Close on close + closeStmt driver.Stmt // if non-nil, statement to Close on close } // Next prepares the next result row for reading with the Scan method. @@ -936,24 +1366,6 @@ func (rs *Rows) Scan(dest ...interface{}) error { return fmt.Errorf("sql: Scan error on column index %d: %v", i, err) } } - for _, dp := range dest { - b, ok := dp.(*[]byte) - if !ok { - continue - } - if *b == nil { - // If the []byte is now nil (for a NULL value), - // don't fall through to below which would - // turn it into a non-nil 0-length byte slice - continue - } - if _, ok = dp.(*RawBytes); ok { - continue - } - clone := make([]byte, len(*b)) - copy(clone, *b) - *b = clone - } return nil } @@ -966,10 +1378,10 @@ func (rs *Rows) Close() error { } rs.closed = true err := rs.rowsi.Close() - rs.releaseConn(err) if rs.closeStmt != nil { rs.closeStmt.Close() } + rs.releaseConn(err) return err } @@ -1026,6 +1438,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 [2 << 10]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/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go index b702b850ec2..e6cc667fa97 100644 --- a/libgo/go/database/sql/sql_test.go +++ b/libgo/go/database/sql/sql_test.go @@ -5,11 +5,11 @@ package sql import ( - "database/sql/driver" "fmt" "reflect" "runtime" "strings" + "sync" "testing" "time" ) @@ -17,10 +17,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 @@ -38,7 +38,15 @@ const fakeDBName = "foo" var chrisBirthday = time.Unix(123456789, 0) -func newTestDB(t *testing.T, name string) *DB { +type testOrBench interface { + Fatalf(string, ...interface{}) + Errorf(string, ...interface{}) + Fatal(...interface{}) + Error(...interface{}) + Logf(string, ...interface{}) +} + +func newTestDB(t testOrBench, name string) *DB { db, err := Open("test", fakeDBName) if err != nil { t.Fatalf("Open: %v", err) @@ -52,17 +60,42 @@ func newTestDB(t *testing.T, name string) *DB { exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2) exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) } + if name == "magicquery" { + // Magic table name and column, known by fakedb_test.go. + exec(t, db, "CREATE|magicquery|op=string,millis=int32") + exec(t, db, "INSERT|magicquery|op=sleep,millis=10") + } return db } -func exec(t *testing.T, db *DB, query string, args ...interface{}) { +func exec(t testOrBench, db *DB, query string, args ...interface{}) { _, err := db.Exec(query, args...) if err != nil { t.Fatalf("Exec of %q: %v", query, err) } } -func closeDB(t *testing.T, db *DB) { +func closeDB(t testOrBench, db *DB) { + if e := recover(); e != nil { + fmt.Printf("Panic: %v\n", e) + panic(e) + } + defer setHookpostCloseConn(nil) + setHookpostCloseConn(func(_ *fakeConn, err error) { + if err != nil { + t.Errorf("Error closing fakeConn: %v", err) + } + }) + for i, dc := range db.freeConn { + if n := len(dc.openStmt); n > 0 { + // Just a sanity check. This is legal in + // general, but if we make the tests clean up + // their statements first, then we can safely + // verify this is always zero here, and any + // other value is a leak. + t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n) + } + } err := db.Close() if err != nil { t.Fatalf("error closing DB: %v", err) @@ -75,7 +108,52 @@ 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 (db *DB) numDeps() int { + db.mu.Lock() + defer db.mu.Unlock() + return len(db.dep) +} + +// Dependencies are closed via a goroutine, so this polls waiting for +// numDeps to fall to want, waiting up to d. +func (db *DB) numDepsPollUntil(want int, d time.Duration) int { + deadline := time.Now().Add(d) + for { + n := db.numDeps() + if n <= want || time.Now().After(deadline) { + return n + } + time.Sleep(50 * time.Millisecond) + } +} + +func (db *DB) numFreeConns() int { + db.mu.Lock() + defer db.mu.Unlock() + return len(db.freeConn) +} + +func (db *DB) dumpDeps(t *testing.T) { + for fc := range db.dep { + db.dumpDep(t, 0, fc, map[finalCloser]bool{}) + } +} + +func (db *DB) dumpDep(t *testing.T, depth int, dep finalCloser, seen map[finalCloser]bool) { + seen[dep] = true + indent := strings.Repeat(" ", depth) + ds := db.dep[dep] + for k := range ds { + t.Logf("%s%T (%p) waiting for -> %T (%p)", indent, dep, dep, k, k) + if fc, ok := k.(finalCloser); ok { + if !seen[fc] { + db.dumpDep(t, depth+1, fc, seen) + } + } + } } func TestQuery(t *testing.T) { @@ -114,7 +192,7 @@ func TestQuery(t *testing.T) { // And verify that the final rows.Next() call, which hit EOF, // also closed the rows connection. - if n := len(db.freeConn); n != 1 { + if n := db.numFreeConns(); n != 1 { t.Fatalf("free conns after query hitting EOF = %d; want 1", n) } if prepares := numPrepares(t, db) - prepares0; prepares != 1 { @@ -270,6 +348,35 @@ func TestStatementQueryRow(t *testing.T) { } +// golang.org/issue/3734 +func TestStatementQueryRowConcurrent(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + stmt, err := db.Prepare("SELECT|people|age|name=?") + if err != nil { + t.Fatalf("Prepare: %v", err) + } + defer stmt.Close() + + const n = 10 + ch := make(chan error, n) + for i := 0; i < n; i++ { + go func() { + var age int + err := stmt.QueryRow("Alice").Scan(&age) + if err == nil && age != 1 { + err = fmt.Errorf("unexpected age %d", age) + } + ch <- err + }() + } + for i := 0; i < n; i++ { + if err := <-ch; err != nil { + t.Error(err) + } + } +} + // just a test of fakedb itself func TestBogusPreboundParameters(t *testing.T) { db := newTestDB(t, "foo") @@ -448,6 +555,30 @@ func TestIssue2542Deadlock(t *testing.T) { } } +// From golang.org/issue/3865 +func TestCloseStmtBeforeRows(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + + s, err := db.Prepare("SELECT|people|name|") + if err != nil { + t.Fatal(err) + } + + r, err := s.Query() + if err != nil { + s.Close() + t.Fatal(err) + } + + err = s.Close() + if err != nil { + t.Fatal(err) + } + + r.Close() +} + // Tests fix for issue 2788, that we bind nil to a []byte if the // value in the column is sql null func TestNullByteSlice(t *testing.T) { @@ -520,7 +651,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) } @@ -641,7 +772,337 @@ func nullTestRun(t *testing.T, spec nullTestSpec) { } } -func stack() string { - buf := make([]byte, 1024) - return string(buf[:runtime.Stack(buf, false)]) +// golang.org/issue/4859 +func TestQueryRowNilScanDest(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + var name *string // nil pointer + err := db.QueryRow("SELECT|people|name|").Scan(name) + want := "sql: Scan error on column index 0: destination pointer is nil" + if err == nil || err.Error() != want { + 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) + } +} + +// golang.org/issue/5323 +func TestStmtCloseDeps(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + defer setHookpostCloseConn(nil) + setHookpostCloseConn(func(_ *fakeConn, err error) { + if err != nil { + t.Errorf("Error closing fakeConn: %v", err) + } + }) + + db := newTestDB(t, "magicquery") + defer closeDB(t, db) + + driver := db.driver.(*fakeDriver) + + driver.mu.Lock() + opens0 := driver.openCount + closes0 := driver.closeCount + driver.mu.Unlock() + openDelta0 := opens0 - closes0 + + stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") + if err != nil { + t.Fatal(err) + } + + // Start 50 parallel slow queries. + const ( + nquery = 50 + sleepMillis = 25 + nbatch = 2 + ) + var wg sync.WaitGroup + for batch := 0; batch < nbatch; batch++ { + for i := 0; i < nquery; i++ { + wg.Add(1) + go func() { + defer wg.Done() + var op string + if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { + t.Error(err) + } + }() + } + // Sleep for twice the expected length of time for the + // batch of 50 queries above to finish before starting + // the next round. + time.Sleep(2 * sleepMillis * time.Millisecond) + } + wg.Wait() + + if g, w := db.numFreeConns(), 2; g != w { + t.Errorf("free conns = %d; want %d", g, w) + } + + if n := db.numDepsPollUntil(4, time.Second); n > 4 { + t.Errorf("number of dependencies = %d; expected <= 4", n) + db.dumpDeps(t) + } + + driver.mu.Lock() + opens := driver.openCount - opens0 + closes := driver.closeCount - closes0 + driver.mu.Unlock() + openDelta := (driver.openCount - driver.closeCount) - openDelta0 + + if openDelta > 2 { + t.Logf("open calls = %d", opens) + t.Logf("close calls = %d", closes) + t.Logf("open delta = %d", openDelta) + t.Errorf("db connections opened = %d; want <= 2", openDelta) + db.dumpDeps(t) + } + + if len(stmt.css) > nquery { + t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery) + } + + if err := stmt.Close(); err != nil { + t.Fatal(err) + } + + if g, w := db.numFreeConns(), 2; g != w { + t.Errorf("free conns = %d; want %d", g, w) + } + + if n := db.numDepsPollUntil(2, time.Second); n > 2 { + t.Errorf("number of dependencies = %d; expected <= 2", n) + db.dumpDeps(t) + } + + db.SetMaxIdleConns(0) + + if g, w := db.numFreeConns(), 0; g != w { + t.Errorf("free conns = %d; want %d", g, w) + } + + if n := db.numDepsPollUntil(0, time.Second); n > 0 { + t.Errorf("number of dependencies = %d; expected 0", n) + db.dumpDeps(t) + } +} + +// golang.org/issue/5046 +func TestCloseConnBeforeStmts(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + + defer setHookpostCloseConn(nil) + setHookpostCloseConn(func(_ *fakeConn, err error) { + if err != nil { + t.Errorf("Error closing fakeConn: %v; from %s", err, stack()) + db.dumpDeps(t) + t.Errorf("DB = %#v", db) + } + }) + + stmt, err := db.Prepare("SELECT|people|name|") + if err != nil { + t.Fatal(err) + } + + if len(db.freeConn) != 1 { + t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn)) + } + dc := db.freeConn[0] + if dc.closed { + t.Errorf("conn shouldn't be closed") + } + + if n := len(dc.openStmt); n != 1 { + t.Errorf("driverConn num openStmt = %d; want 1", n) + } + err = db.Close() + if err != nil { + t.Errorf("db Close = %v", err) + } + if !dc.closed { + t.Errorf("after db.Close, driverConn should be closed") + } + if n := len(dc.openStmt); n != 0 { + t.Errorf("driverConn num openStmt = %d; want 0", n) + } + + err = stmt.Close() + if err != nil { + t.Errorf("Stmt close = %v", err) + } + + if !dc.closed { + t.Errorf("conn should be closed") + } + if dc.ci != nil { + t.Errorf("after Stmt Close, driverConn's Conn interface should be nil") + } +} + +// golang.org/issue/5283: don't release the Rows' connection in Close +// before calling Stmt.Close. +func TestRowsCloseOrder(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + + db.SetMaxIdleConns(0) + setStrictFakeConnClose(t) + defer setStrictFakeConnClose(nil) + + rows, err := db.Query("SELECT|people|age,name|") + if err != nil { + t.Fatal(err) + } + err = rows.Close() + if err != nil { + t.Fatal(err) + } +} + +func manyConcurrentQueries(t testOrBench) { + maxProcs, numReqs := 16, 500 + if testing.Short() { + maxProcs, numReqs = 4, 50 + } + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) + + db := newTestDB(t, "people") + defer closeDB(t, db) + + stmt, err := db.Prepare("SELECT|people|name|") + if err != nil { + t.Fatal(err) + } + defer stmt.Close() + + var wg sync.WaitGroup + wg.Add(numReqs) + + reqs := make(chan bool) + defer close(reqs) + + for i := 0; i < maxProcs*2; i++ { + go func() { + for _ = range reqs { + rows, err := stmt.Query() + if err != nil { + t.Errorf("error on query: %v", err) + wg.Done() + continue + } + + var name string + for rows.Next() { + rows.Scan(&name) + } + rows.Close() + + wg.Done() + } + }() + } + + for i := 0; i < numReqs; i++ { + reqs <- true + } + + wg.Wait() +} + +func TestConcurrency(t *testing.T) { + manyConcurrentQueries(t) +} + +func BenchmarkConcurrency(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + manyConcurrentQueries(b) + } } diff --git a/libgo/go/debug/dwarf/buf.go b/libgo/go/debug/dwarf/buf.go index 08e37be4b38..53c46eb4b81 100644 --- a/libgo/go/debug/dwarf/buf.go +++ b/libgo/go/debug/dwarf/buf.go @@ -13,17 +13,45 @@ import ( // Data buffer being decoded. type buf struct { - dwarf *Data - u *unit - order binary.ByteOrder - name string - off Offset - data []byte - err error + dwarf *Data + order binary.ByteOrder + format dataFormat + name string + off Offset + data []byte + err error } -func makeBuf(d *Data, u *unit, name string, off Offset, data []byte) buf { - return buf{d, u, d.order, name, off, data, 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,17 +149,15 @@ func (b *buf) int() int64 { // Address-sized uint. func (b *buf) addr() uint64 { - if b.u != nil { - switch b.u.addrsize { - case 1: - return uint64(b.uint8()) - case 2: - return uint64(b.uint16()) - case 4: - return uint64(b.uint32()) - case 8: - return uint64(b.uint64()) - } + switch b.format.addrsize() { + case 1: + return uint64(b.uint8()) + case 2: + return uint64(b.uint16()) + case 4: + return uint64(b.uint32()) + case 8: + return uint64(b.uint64()) } b.error("unknown address size") return 0 diff --git a/libgo/go/debug/dwarf/entry.go b/libgo/go/debug/dwarf/entry.go index 4761d74cd79..ada723163a4 100644 --- a/libgo/go/debug/dwarf/entry.go +++ b/libgo/go/debug/dwarf/entry.go @@ -40,7 +40,7 @@ func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) { } else { data = data[off:] } - b := makeBuf(d, nil, "abbrev", 0, data) + b := makeBuf(d, unknownFormat{}, "abbrev", 0, data) // Error handling is simplified by the buf getters // returning an endless stream of 0s after an error. @@ -190,13 +190,16 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { case formFlag: val = b.uint8() == 1 case formFlagPresent: + // The attribute is implicitly indicated as present, and no value is + // encoded in the debugging information entry itself. val = true // lineptr, loclistptr, macptr, rangelistptr case formSecOffset: - if b.u == nil { + is64, known := b.format.dwarf64() + if !known { b.error("unknown size for DW_FORM_sec_offset") - } else if b.u.dwarf64 { + } else if is64 { val = Offset(b.uint64()) } else { val = Offset(b.uint32()) @@ -204,14 +207,20 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { // reference to other entry case formRefAddr: - if b.u == nil { + vers := b.format.version() + if vers == 0 { b.error("unknown version for DW_FORM_ref_addr") - } else if b.u.version == 2 { + } else if vers == 2 { val = Offset(b.addr()) - } else if b.u.dwarf64 { - val = Offset(b.uint64()) } else { - val = Offset(b.uint32()) + 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 @@ -234,7 +243,7 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { if b.err != nil { return nil } - b1 := makeBuf(b.dwarf, b.u, "str", 0, b.dwarf.str) + b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str) b1.skip(int(off)) val = b1.string() if b1.err != nil { diff --git a/libgo/go/debug/dwarf/line.go b/libgo/go/debug/dwarf/line.go index 3ab2f2b30cb..c463c3b0d8f 100644 --- a/libgo/go/debug/dwarf/line.go +++ b/libgo/go/debug/dwarf/line.go @@ -112,7 +112,7 @@ func (d *Data) readUnitLine(i int, u *unit) error { func (d *Data) readAddressRanges(off Offset, base uint64, u *unit) error { b := makeBuf(d, u, "ranges", off, d.ranges[off:]) var highest uint64 - switch u.addrsize { + switch u.addrsize() { case 1: highest = 0xff case 2: diff --git a/libgo/go/debug/dwarf/type.go b/libgo/go/debug/dwarf/type.go index 2ef8ca01bf8..54000fbd75e 100644 --- a/libgo/go/debug/dwarf/type.go +++ b/libgo/go/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, nil, "location", 0, loc) + // 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/libgo/go/debug/dwarf/unit.go b/libgo/go/debug/dwarf/unit.go index b1903208715..8e09298a8b4 100644 --- a/libgo/go/debug/dwarf/unit.go +++ b/libgo/go/debug/dwarf/unit.go @@ -10,17 +10,31 @@ 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 - lineoff Offset // byte offset of data within the line info - data []byte - atable abbrevTable - addrsize int - version int - dwarf64 bool // True for 64-bit DWARF format - dir string - pc []addrRange // PC ranges in this compilation unit - lines []mapLineInfo // PC -> line mapping + base Offset // byte offset of header within the aggregate info + off Offset // byte offset of data within the aggregate info + lineoff Offset // byte offset of data within the line info + data []byte + atable abbrevTable + asize int + vers int + is64 bool // True for 64-bit DWARF format + dir string + pc []addrRange // PC ranges in this compilation unit + lines []mapLineInfo // PC -> line mapping +} + +// 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 } // A range is an address range. @@ -32,12 +46,12 @@ type addrRange struct { func (d *Data) parseUnits() ([]unit, error) { // Count units. nunit := 0 - b := makeBuf(d, nil, "info", 0, d.info) + b := makeBuf(d, unknownFormat{}, "info", 0, d.info) for len(b.data) > 0 { len := b.uint32() if len == 0xffffffff { len64 := b.uint64() - if len64 != uint64(int(len64)) { + if len64 != uint64(uint32(len64)) { b.error("unit length overflow") break } @@ -51,14 +65,14 @@ func (d *Data) parseUnits() ([]unit, error) { } // Again, this time writing them down. - b = makeBuf(d, nil, "info", 0, d.info) + 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 n == 0xffffffff { - u.dwarf64 = true + u.is64 = true n = uint32(b.uint64()) } vers := b.uint16() @@ -66,6 +80,7 @@ func (d *Data) parseUnits() ([]unit, error) { 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 { @@ -73,9 +88,8 @@ func (d *Data) parseUnits() ([]unit, error) { } break } - u.version = int(vers) 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/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go index eb3d72f7126..8023eb0a0b7 100644 --- a/libgo/go/debug/elf/file.go +++ b/libgo/go/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/libgo/go/debug/gosym/symtab.go b/libgo/go/debug/gosym/symtab.go index cc01e0b9d69..81ed4fb27dc 100644 --- a/libgo/go/debug/gosym/symtab.go +++ b/libgo/go/debug/gosym/symtab.go @@ -99,31 +99,116 @@ type Table struct { } type sym struct { - value uint32 - gotype uint32 + value uint64 + gotype uint64 typ byte name []byte } -var littleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00} +var littleEndianSymtab = []byte{0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00} +var bigEndianSymtab = []byte{0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00} + +var oldLittleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00} func walksymtab(data []byte, fn func(sym) error) error { var order binary.ByteOrder = binary.BigEndian - if bytes.HasPrefix(data, littleEndianSymtab) { + newTable := false + switch { + case bytes.HasPrefix(data, oldLittleEndianSymtab): + // Same as Go 1.0, but little endian. + // Format was used during interim development between Go 1.0 and Go 1.1. + // Should not be widespread, but easy to support. data = data[6:] order = binary.LittleEndian + case bytes.HasPrefix(data, bigEndianSymtab): + newTable = true + case bytes.HasPrefix(data, littleEndianSymtab): + newTable = true + order = binary.LittleEndian + } + var ptrsz int + if newTable { + if len(data) < 8 { + return &DecodingError{len(data), "unexpected EOF", nil} + } + ptrsz = int(data[7]) + if ptrsz != 4 && ptrsz != 8 { + return &DecodingError{7, "invalid pointer size", ptrsz} + } + data = data[8:] } var s sym p := data - for len(p) >= 6 { - s.value = order.Uint32(p[0:4]) - typ := p[4] - if typ&0x80 == 0 { - return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ} + for len(p) >= 4 { + var typ byte + if newTable { + // Symbol type, value, Go type. + typ = p[0] & 0x3F + wideValue := p[0]&0x40 != 0 + goType := p[0]&0x80 != 0 + if typ < 26 { + typ += 'A' + } else { + typ += 'a' - 26 + } + s.typ = typ + p = p[1:] + if wideValue { + if len(p) < ptrsz { + return &DecodingError{len(data), "unexpected EOF", nil} + } + // fixed-width value + if ptrsz == 8 { + s.value = order.Uint64(p[0:8]) + p = p[8:] + } else { + s.value = uint64(order.Uint32(p[0:4])) + p = p[4:] + } + } else { + // varint value + s.value = 0 + shift := uint(0) + for len(p) > 0 && p[0]&0x80 != 0 { + s.value |= uint64(p[0]&0x7F) << shift + shift += 7 + p = p[1:] + } + if len(p) == 0 { + return &DecodingError{len(data), "unexpected EOF", nil} + } + s.value |= uint64(p[0]) << shift + p = p[1:] + } + if goType { + if len(p) < ptrsz { + return &DecodingError{len(data), "unexpected EOF", nil} + } + // fixed-width go type + if ptrsz == 8 { + s.gotype = order.Uint64(p[0:8]) + p = p[8:] + } else { + s.gotype = uint64(order.Uint32(p[0:4])) + p = p[4:] + } + } + } else { + // Value, symbol type. + s.value = uint64(order.Uint32(p[0:4])) + if len(p) < 5 { + return &DecodingError{len(data), "unexpected EOF", nil} + } + typ = p[4] + if typ&0x80 == 0 { + return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ} + } + typ &^= 0x80 + s.typ = typ + p = p[5:] } - typ &^= 0x80 - s.typ = typ - p = p[5:] + + // Name. var i int var nnul int for i = 0; i < len(p); i++ { @@ -142,13 +227,21 @@ func walksymtab(data []byte, fn func(sym) error) error { } } } - if i+nnul+4 > len(p) { + if len(p) < i+nnul { return &DecodingError{len(data), "unexpected EOF", nil} } s.name = p[0:i] i += nnul - s.gotype = order.Uint32(p[i : i+4]) - p = p[i+4:] + p = p[i:] + + if !newTable { + if len(p) < 4 { + return &DecodingError{len(data), "unexpected EOF", nil} + } + // Go type. + s.gotype = uint64(order.Uint32(p[:4])) + p = p[4:] + } fn(s) } return nil diff --git a/libgo/go/debug/macho/file.go b/libgo/go/debug/macho/file.go index 6577803a075..9d912e7a087 100644 --- a/libgo/go/debug/macho/file.go +++ b/libgo/go/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/libgo/go/encoding/ascii85/ascii85.go b/libgo/go/encoding/ascii85/ascii85.go index 705022792a8..e2afc587140 100644 --- a/libgo/go/encoding/ascii85/ascii85.go +++ b/libgo/go/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/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go index 0c216fdb3cd..adaf80dcdb0 100644 --- a/libgo/go/encoding/asn1/marshal.go +++ b/libgo/go/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/libgo/go/encoding/base32/base32.go b/libgo/go/encoding/base32/base32.go index dbefc48fa37..fe17b732207 100644 --- a/libgo/go/encoding/base32/base32.go +++ b/libgo/go/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/libgo/go/encoding/base32/base32_test.go b/libgo/go/encoding/base32/base32_test.go index 98365e18cfc..63298d1c94c 100644 --- a/libgo/go/encoding/base32/base32_test.go +++ b/libgo/go/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/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go index e66672a1c93..85e398fd0b7 100644 --- a/libgo/go/encoding/base64/base64.go +++ b/libgo/go/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/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go index f9b863c364c..579591a88d7 100644 --- a/libgo/go/encoding/base64/base64_test.go +++ b/libgo/go/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) @@ -257,6 +269,7 @@ func TestDecoderIssue3577(t *testing.T) { wantErr := errors.New("my error") next <- nextRead{5, nil} next <- nextRead{10, wantErr} + next <- nextRead{0, wantErr} d := NewDecoder(StdEncoding, &faultInjectReader{ source: "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", // twas brillig... nextc: next, @@ -275,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/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go index 04d5723c1e2..edbac197d64 100644 --- a/libgo/go/encoding/binary/binary.go +++ b/libgo/go/encoding/binary/binary.go @@ -167,9 +167,9 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error { default: return errors.New("binary.Read: invalid type " + d.Type().String()) } - size := dataSize(v) - if size < 0 { - return errors.New("binary.Read: invalid type " + v.Type().String()) + size, err := dataSize(v) + if err != nil { + return errors.New("binary.Read: " + err.Error()) } d := &decoder{order: order, buf: make([]byte, size)} if _, err := io.ReadFull(r, d.buf); err != nil { @@ -247,64 +247,68 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error { // Fallback to reflect-based encoding. v := reflect.Indirect(reflect.ValueOf(data)) - size := dataSize(v) - if size < 0 { - return errors.New("binary.Write: invalid type " + v.Type().String()) + size, err := dataSize(v) + if err != nil { + return errors.New("binary.Write: " + err.Error()) } buf := make([]byte, size) e := &encoder{order: order, buf: buf} e.value(v) - _, err := w.Write(buf) + _, err = w.Write(buf) return err } // Size returns how many bytes Write would generate to encode the value v, which // must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. func Size(v interface{}) int { - return dataSize(reflect.Indirect(reflect.ValueOf(v))) + n, err := dataSize(reflect.Indirect(reflect.ValueOf(v))) + if err != nil { + return -1 + } + return n } // dataSize returns the number of bytes the actual data represented by v occupies in memory. // For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice // it returns the length of the slice times the element size and does not count the memory // occupied by the header. -func dataSize(v reflect.Value) int { +func dataSize(v reflect.Value) (int, error) { if v.Kind() == reflect.Slice { - elem := sizeof(v.Type().Elem()) - if elem < 0 { - return -1 + elem, err := sizeof(v.Type().Elem()) + if err != nil { + return 0, err } - return v.Len() * elem + return v.Len() * elem, nil } return sizeof(v.Type()) } -func sizeof(t reflect.Type) int { +func sizeof(t reflect.Type) (int, error) { switch t.Kind() { case reflect.Array: - n := sizeof(t.Elem()) - if n < 0 { - return -1 + n, err := sizeof(t.Elem()) + if err != nil { + return 0, err } - return t.Len() * n + return t.Len() * n, nil case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { - s := sizeof(t.Field(i).Type) - if s < 0 { - return -1 + s, err := sizeof(t.Field(i).Type) + if err != nil { + return 0, err } sum += s } - return sum + return sum, nil case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: - return int(t.Size()) + return int(t.Size()), nil } - return -1 + return 0, errors.New("invalid type " + t.String()) } type coder struct { @@ -514,11 +518,12 @@ func (e *encoder) value(v reflect.Value) { } func (d *decoder) skip(v reflect.Value) { - d.buf = d.buf[dataSize(v):] + n, _ := dataSize(v) + d.buf = d.buf[n:] } func (e *encoder) skip(v reflect.Value) { - n := dataSize(v) + n, _ := dataSize(v) for i := range e.buf[0:n] { e.buf[i] = 0 } diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go index cfad8d36c7b..056f0998f27 100644 --- a/libgo/go/encoding/binary/binary_test.go +++ b/libgo/go/encoding/binary/binary_test.go @@ -9,6 +9,7 @@ import ( "io" "math" "reflect" + "strings" "testing" ) @@ -149,8 +150,14 @@ func TestWriteT(t *testing.T) { tv := reflect.Indirect(reflect.ValueOf(ts)) for i, n := 0, tv.NumField(); i < n; i++ { + typ := tv.Field(i).Type().String() + if typ == "[4]int" { + typ = "int" // the problem is int, not the [4] + } if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil { t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type()) + } else if !strings.Contains(err.Error(), typ) { + t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ) } } } @@ -238,7 +245,7 @@ func BenchmarkReadStruct(b *testing.B) { bsr := &byteSliceReader{} var buf bytes.Buffer Write(&buf, BigEndian, &s) - n := dataSize(reflect.ValueOf(s)) + n, _ := dataSize(reflect.ValueOf(s)) b.SetBytes(int64(n)) t := s b.ResetTimer() diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go index 7035529f279..3a2dfa3c74e 100644 --- a/libgo/go/encoding/binary/varint.go +++ b/libgo/go/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/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go index db4d988526f..b099caf60a8 100644 --- a/libgo/go/encoding/csv/reader.go +++ b/libgo/go/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/libgo/go/encoding/gob/codec_test.go b/libgo/go/encoding/gob/codec_test.go index 482212b7467..9e38e31d5da 100644 --- a/libgo/go/encoding/gob/codec_test.go +++ b/libgo/go/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/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go index a80d9f9195f..7cc7565409c 100644 --- a/libgo/go/encoding/gob/decode.go +++ b/libgo/go/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/libgo/go/encoding/gob/gobencdec_test.go b/libgo/go/encoding/gob/gobencdec_test.go index 18f4450da6d..ddcd80b1a7a 100644 --- a/libgo/go/encoding/gob/gobencdec_test.go +++ b/libgo/go/encoding/gob/gobencdec_test.go @@ -1,4 +1,4 @@ -// Copyright 20011 The Go Authors. All rights reserved. +// 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. @@ -348,7 +348,7 @@ func TestGobEncoderFieldsOfDifferentType(t *testing.T) { t.Fatal("decode error:", err) } if y.G.s != "XYZ" { - t.Fatalf("expected `XYZ` got %c", y.G.s) + t.Fatalf("expected `XYZ` got %q", y.G.s) } } diff --git a/libgo/go/encoding/gob/timing_test.go b/libgo/go/encoding/gob/timing_test.go index 9a0e51d1fe1..f589675dd98 100644 --- a/libgo/go/encoding/gob/timing_test.go +++ b/libgo/go/encoding/gob/timing_test.go @@ -50,49 +50,51 @@ func BenchmarkEndToEndByteBuffer(b *testing.B) { } func TestCountEncodeMallocs(t *testing.T) { - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1)) + if runtime.GOMAXPROCS(0) > 1 { + t.Skip("skipping; GOMAXPROCS>1") + } + + const N = 1000 + var buf bytes.Buffer enc := NewEncoder(&buf) bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - memstats := new(runtime.MemStats) - runtime.ReadMemStats(memstats) - mallocs := 0 - memstats.Mallocs - const count = 1000 - for i := 0; i < count; i++ { + + allocs := testing.AllocsPerRun(N, func() { err := enc.Encode(bench) if err != nil { t.Fatal("encode:", err) } - } - runtime.ReadMemStats(memstats) - mallocs += memstats.Mallocs - fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count) + }) + fmt.Printf("mallocs per encode of type Bench: %v\n", allocs) } func TestCountDecodeMallocs(t *testing.T) { - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1)) + if runtime.GOMAXPROCS(0) > 1 { + t.Skip("skipping; GOMAXPROCS>1") + } + + const N = 1000 + var buf bytes.Buffer enc := NewEncoder(&buf) bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - const count = 1000 - for i := 0; i < count; i++ { + + // Fill the buffer with enough to decode + testing.AllocsPerRun(N, func() { err := enc.Encode(bench) if err != nil { t.Fatal("encode:", err) } - } + }) + dec := NewDecoder(&buf) - memstats := new(runtime.MemStats) - runtime.ReadMemStats(memstats) - mallocs := 0 - memstats.Mallocs - for i := 0; i < count; i++ { + allocs := testing.AllocsPerRun(N, func() { *bench = Bench{} err := dec.Decode(&bench) if err != nil { t.Fatal("decode:", err) } - } - runtime.ReadMemStats(memstats) - mallocs += memstats.Mallocs - fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count) + }) + fmt.Printf("mallocs per decode of type Bench: %v\n", allocs) } diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go index ea0db4eac45..7fa0b499f02 100644 --- a/libgo/go/encoding/gob/type.go +++ b/libgo/go/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/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go index 95e91209184..62ac294b89f 100644 --- a/libgo/go/encoding/json/decode.go +++ b/libgo/go/encoding/json/decode.go @@ -33,6 +33,10 @@ import ( // the value pointed at by the pointer. If the pointer is nil, Unmarshal // allocates a new value for it to point to. // +// To unmarshal JSON into a struct, Unmarshal matches incoming object +// keys to the keys used by Marshal (either the struct field name or its tag), +// preferring an exact match but also accepting a case-insensitive match. +// // To unmarshal JSON into an interface value, Unmarshal unmarshals // the JSON into the concrete value contained in the interface value. // If the interface value is nil, that is, has no concrete value stored in it, @@ -51,17 +55,22 @@ import ( // If no more serious errors are encountered, Unmarshal returns // an UnmarshalTypeError describing the earliest such error. // +// When unmarshaling quoted strings, invalid UTF-8 or +// invalid UTF-16 surrogate pairs are not treated as an error. +// Instead, they are replaced by the Unicode replacement +// character U+FFFD. +// func Unmarshal(data []byte, v interface{}) error { - d := new(decodeState).init(data) - - // Quick check for well-formedness. + // Check for well-formedness. // Avoids filling out half a data structure // before discovering a JSON syntax error. + var d decodeState err := checkValid(data, &d.scan) if err != nil { return err } + d.init(data) return d.unmarshal(v) } @@ -252,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 } @@ -730,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: @@ -737,12 +757,11 @@ func (d *decodeState) valueInterface() interface{} { case scanBeginLiteral: return d.literalInterface() } - panic("unreachable") } // arrayInterface is like array but returns []interface{}. func (d *decodeState) arrayInterface() []interface{} { - var v []interface{} + var v = make([]interface{}, 0) for { // Look ahead for ] - can only happen on first iteration. op := d.scanWhile(scanSkipSpace) @@ -849,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/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go index a91c6da01d3..f845f69ab7f 100644 --- a/libgo/go/encoding/json/decode_test.go +++ b/libgo/go/encoding/json/decode_test.go @@ -11,6 +11,7 @@ import ( "reflect" "strings" "testing" + "time" ) type T struct { @@ -29,7 +30,7 @@ type V struct { F3 Number } -// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshalling with and +// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and // without UseNumber var ifaceNumAsFloat64 = map[string]interface{}{ "k1": float64(1), @@ -239,6 +240,12 @@ var unmarshalTests = []unmarshalTest{ {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}}, {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}}, + // empty array to interface test + {in: `[]`, ptr: new([]interface{}), out: []interface{}{}}, + {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)}, + {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}}, + {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}}, + // composite tests {in: allValueIndent, ptr: new(All), out: allValue}, {in: allValueCompact, ptr: new(All), out: allValue}, @@ -323,6 +330,43 @@ var unmarshalTests = []unmarshalTest{ ptr: new(S10), out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}}, }, + + // invalid UTF-8 is coerced to valid UTF-8. + { + in: "\"hello\xffworld\"", + ptr: new(string), + out: "hello\ufffdworld", + }, + { + in: "\"hello\xc2\xc2world\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\xc2\xffworld\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\\ud800world\"", + ptr: new(string), + out: "hello\ufffdworld", + }, + { + in: "\"hello\\ud800\\ud800world\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\\ud800\\ud800world\"", + ptr: new(string), + out: "hello\ufffd\ufffdworld", + }, + { + in: "\"hello\xed\xa0\x80\xed\xb0\x80world\"", + ptr: new(string), + out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld", + }, } func TestMarshal(t *testing.T) { @@ -1107,3 +1151,43 @@ func TestUnmarshalUnexported(t *testing.T) { t.Errorf("got %q, want %q", out, want) } } + +// Time3339 is a time.Time which encodes to and from JSON +// as an RFC 3339 time in UTC. +type Time3339 time.Time + +func (t *Time3339) UnmarshalJSON(b []byte) error { + if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { + return fmt.Errorf("types: failed to unmarshal non-string value %q as an RFC 3339 time", b) + } + tm, err := time.Parse(time.RFC3339, string(b[1:len(b)-1])) + if err != nil { + return err + } + *t = Time3339(tm) + return nil +} + +func TestUnmarshalJSONLiteralError(t *testing.T) { + var t3 Time3339 + err := Unmarshal([]byte(`"0000-00-00T00:00:00Z"`), &t3) + if err == nil { + t.Fatalf("expected error; got time %v", time.Time(t3)) + } + if !strings.Contains(err.Error(), "range") { + 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/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go index fb57f1d51b2..85727ba61c0 100644 --- a/libgo/go/encoding/json/encode.go +++ b/libgo/go/encoding/json/encode.go @@ -3,7 +3,8 @@ // license that can be found in the LICENSE file. // Package json implements encoding and decoding of JSON objects as defined in -// RFC 4627. +// RFC 4627. The mapping between JSON objects and Go values is described +// in the documentation for the Marshal and Unmarshal functions. // // See "JSON and Go" for an introduction to this package: // http://golang.org/doc/articles/json_and_go.html @@ -38,8 +39,8 @@ import ( // // Floating point, integer, and Number values encode as JSON numbers. // -// String values encode as JSON strings, with each invalid UTF-8 sequence -// replaced by the encoding of the Unicode replacement character U+FFFD. +// String values encode as JSON strings. InvalidUTF8Error will be returned +// if an invalid UTF-8 sequence is encountered. // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" // to keep some browsers from misinterpreting JSON output as HTML. // @@ -86,9 +87,21 @@ import ( // underscores and slashes. // // Anonymous struct fields are usually marshaled as if their inner exported fields -// were fields in the outer struct, subject to the usual Go visibility rules. +// were fields in the outer struct, subject to the usual Go visibility rules amended +// as described in the next paragraph. // An anonymous struct field with a name given in its JSON tag is treated as -// having that name instead of as anonymous. +// having that name, rather than being anonymous. +// +// The Go visibility rules for struct fields are amended for JSON when +// deciding which field to marshal or unmarshal. If there are +// multiple fields at the same level, and that level is the least +// nested (and would therefore be the nesting level selected by the +// usual Go rules), the following extra rules apply: +// +// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered, +// even if there are multiple untagged fields that would otherwise conflict. +// 2) If there is exactly one field (tagged or not according to the first rule), that is selected. +// 3) Otherwise there are multiple fields, and all are ignored; no error occurs. // // Handling of anonymous struct fields is new in Go 1.1. // Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of @@ -187,8 +200,10 @@ func (e *UnsupportedValueError) Error() string { return "json: unsupported value: " + e.Str } +// An InvalidUTF8Error is returned by Marshal when attempting +// to encode a string value with invalid UTF-8 sequences. type InvalidUTF8Error struct { - S string + S string // the whole string value that caused the error } func (e *InvalidUTF8Error) Error() string { @@ -654,27 +669,78 @@ func typeFields(t reflect.Type) []field { sort.Sort(byName(fields)) - // Remove fields with annihilating name collisions - // and also fields shadowed by fields with explicit JSON tags. - name := "" + // Delete all fields that are hidden by the Go rules for embedded fields, + // except that fields with JSON tags are promoted. + + // The fields are sorted in primary order of name, secondary order + // of field index length. Loop over names; for each name, delete + // hidden fields by choosing the one dominant field that survives. out := fields[:0] - for _, f := range fields { - if f.name != name { - name = f.name - out = append(out, f) + for advance, i := 0, 0; i < len(fields); i += advance { + // One iteration per name. + // Find the sequence of fields with the name of this first field. + fi := fields[i] + name := fi.name + for advance = 1; i+advance < len(fields); advance++ { + fj := fields[i+advance] + if fj.name != name { + break + } + } + if advance == 1 { // Only one field with this name + out = append(out, fi) continue } - if n := len(out); n > 0 && out[n-1].name == name && (!out[n-1].tag || f.tag) { - out = out[:n-1] + dominant, ok := dominantField(fields[i : i+advance]) + if ok { + out = append(out, dominant) } } - fields = out + fields = out sort.Sort(byIndex(fields)) return fields } +// dominantField looks through the fields, all of which are known to +// have the same name, to find the single field that dominates the +// others using Go's embedding rules, modified by the presence of +// JSON tags. If there are multiple top-level fields, the boolean +// will be false: This condition is an error in Go and we skip all +// the fields. +func dominantField(fields []field) (field, bool) { + // The fields are sorted in increasing index-length order. The winner + // must therefore be one with the shortest index length. Drop all + // longer entries, which is easy: just truncate the slice. + length := len(fields[0].index) + tagged := -1 // Index of first tagged field. + for i, f := range fields { + if len(f.index) > length { + fields = fields[:i] + break + } + if f.tag { + if tagged >= 0 { + // Multiple tagged fields at the same level: conflict. + // Return no field. + return field{}, false + } + tagged = i + } + } + if tagged >= 0 { + return fields[tagged], true + } + // All remaining fields have the same length. If there's more than one, + // we have a conflict (two fields named "X" at the same level) and we + // return no field. + if len(fields) > 1 { + return field{}, false + } + return fields[0], true +} + var fieldCache struct { sync.RWMutex m map[reflect.Type][]field diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go index be74c997cf8..5be0a992e1c 100644 --- a/libgo/go/encoding/json/encode_test.go +++ b/libgo/go/encoding/json/encode_test.go @@ -206,3 +206,107 @@ func TestAnonymousNonstruct(t *testing.T) { t.Errorf("got %q, want %q", got, want) } } + +type BugA struct { + S string +} + +type BugB struct { + BugA + S string +} + +type BugC struct { + S string +} + +// Legal Go: We never use the repeated embedded field (S). +type BugX struct { + A int + BugA + BugB +} + +// Issue 5245. +func TestEmbeddedBug(t *testing.T) { + v := BugB{ + BugA{"A"}, + "B", + } + b, err := Marshal(v) + if err != nil { + t.Fatal("Marshal:", err) + } + want := `{"S":"B"}` + got := string(b) + if got != want { + t.Fatalf("Marshal: got %s want %s", got, want) + } + // Now check that the duplicate field, S, does not appear. + x := BugX{ + A: 23, + } + b, err = Marshal(x) + if err != nil { + t.Fatal("Marshal:", err) + } + want = `{"A":23}` + got = string(b) + if got != want { + t.Fatalf("Marshal: got %s want %s", got, want) + } +} + +type BugD struct { // Same as BugA after tagging. + XXX string `json:"S"` +} + +// BugD's tagged S field should dominate BugA's. +type BugY struct { + BugA + BugD +} + +// Test that a field with a tag dominates untagged fields. +func TestTaggedFieldDominates(t *testing.T) { + v := BugY{ + BugA{"BugA"}, + BugD{"BugD"}, + } + b, err := Marshal(v) + if err != nil { + t.Fatal("Marshal:", err) + } + want := `{"S":"BugD"}` + got := string(b) + if got != want { + t.Fatalf("Marshal: got %s want %s", got, want) + } +} + +// There are no tags here, so S should not appear. +type BugZ struct { + BugA + BugC + BugY // Contains a tagged S field through BugD; should not dominate. +} + +func TestDuplicatedFieldDisappears(t *testing.T) { + v := BugZ{ + BugA{"BugA"}, + BugC{"BugC"}, + BugY{ + BugA{"nested BugA"}, + BugD{"nested BugD"}, + }, + } + b, err := Marshal(v) + if err != nil { + t.Fatal("Marshal:", err) + } + want := `{}` + got := string(b) + if got != want { + t.Fatalf("Marshal: got %s want %s", got, want) + } +} diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go index adb35715b96..77d3455d307 100644 --- a/libgo/go/encoding/json/scanner_test.go +++ b/libgo/go/encoding/json/scanner_test.go @@ -277,9 +277,6 @@ func genArray(n int) []interface{} { if f > n { f = n } - if n > 0 && f == 0 { - f = 1 - } x := make([]interface{}, f) for i := range x { x[i] = genValue(((i+1)*n)/f - (i*n)/f) diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go index aacb50c9cfc..47b00176342 100644 --- a/libgo/go/encoding/xml/marshal.go +++ b/libgo/go/encoding/xml/marshal.go @@ -81,8 +81,7 @@ func Marshal(v interface{}) ([]byte, error) { func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { var b bytes.Buffer enc := NewEncoder(&b) - enc.prefix = prefix - enc.indent = indent + enc.Indent(prefix, indent) if err := enc.Encode(v); err != nil { return nil, err } @@ -99,6 +98,14 @@ func NewEncoder(w io.Writer) *Encoder { return &Encoder{printer{Writer: bufio.NewWriter(w)}} } +// Indent sets the encoder to generate XML in which each element +// begins on a new indented line that starts with prefix and is followed by +// one or more copies of indent according to the nesting depth. +func (enc *Encoder) Indent(prefix, indent string) { + enc.prefix = prefix + enc.indent = indent +} + // Encode writes the XML encoding of v to the stream. // // See the documentation for Marshal for details about the conversion @@ -113,10 +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. @@ -185,7 +258,9 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error { if xmlns != "" { p.WriteString(` xmlns="`) // TODO: EscapeString, to avoid the allocation. - Escape(p, []byte(xmlns)) + if err := EscapeText(p, []byte(xmlns)); err != nil { + return err + } p.WriteByte('"') } @@ -200,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 { @@ -244,19 +327,22 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error { p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits())) case reflect.String: // TODO: Add EscapeString. - Escape(p, []byte(val.String())) + EscapeText(p, []byte(val.String())) case reflect.Bool: p.WriteString(strconv.FormatBool(val.Bool())) case reflect.Array: // will be [...]byte - bytes := make([]byte, val.Len()) - for i := range bytes { - bytes[i] = val.Index(i).Interface().(byte) + var bytes []byte + if val.CanAddr() { + bytes = val.Slice(0, val.Len()).Bytes() + } else { + bytes = make([]byte, val.Len()) + reflect.Copy(reflect.ValueOf(bytes), val) } - Escape(p, bytes) + EscapeText(p, bytes) case reflect.Slice: // will be []byte - Escape(p, val.Bytes()) + EscapeText(p, val.Bytes()) default: return &UnsupportedTypeError{typ} } @@ -273,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) @@ -290,10 +376,14 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error { case reflect.Bool: Escape(p, strconv.AppendBool(scratch[:0], vf.Bool())) case reflect.String: - Escape(p, []byte(vf.String())) + if err := EscapeText(p, []byte(vf.String())); err != nil { + return err + } case reflect.Slice: if elem, ok := vf.Interface().([]byte); ok { - Escape(p, elem) + if err := EscapeText(p, elem); err != nil { + return err + } } case reflect.Struct: if vf.Type() == timeType { @@ -387,7 +477,11 @@ func (p *printer) writeIndent(depthDelta int) { } p.indentedIn = false } - p.WriteByte('\n') + if p.putNewline { + p.WriteByte('\n') + } else { + p.putNewline = true + } if len(p.prefix) > 0 { p.WriteString(p.prefix) } diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go index 67fcfd9ed56..ca14a1e53db 100644 --- a/libgo/go/encoding/xml/marshal_test.go +++ b/libgo/go/encoding/xml/marshal_test.go @@ -7,6 +7,7 @@ package xml import ( "bytes" "errors" + "fmt" "io" "reflect" "strconv" @@ -265,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 @@ -789,6 +800,17 @@ var marshalTests = []struct { }, UnmarshalOnly: true, }, + { + ExpectXML: `42`, + Value: &EmbedInt{ + MyInt: 42, + }, + }, + // Test omitempty with parent chain; see golang.org/issue/4168. + { + ExpectXML: ``, + Value: &Strings{}, + }, } func TestMarshal(t *testing.T) { @@ -811,6 +833,10 @@ func TestMarshal(t *testing.T) { } } +type AttrParent struct { + X string `xml:"X>Y,attr"` +} + var marshalErrorTests = []struct { Value interface{} Err string @@ -838,12 +864,39 @@ 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 { + Value interface{} + Prefix string + Indent string + ExpectXML string +}{ + { + Value: &SecretAgent{ + Handle: "007", + Identity: "James Bond", + Obfuscate: "", + }, + Prefix: "", + Indent: "\t", + ExpectXML: fmt.Sprintf("\n\tJames Bond\n"), + }, } 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 { @@ -884,6 +937,19 @@ func TestUnmarshal(t *testing.T) { } } +func TestMarshalIndent(t *testing.T) { + for i, test := range marshalIndentTests { + data, err := MarshalIndent(test.Value, test.Prefix, test.Indent) + if err != nil { + t.Errorf("#%d: Error: %s", i, err) + continue + } + if got, want := string(data), test.ExpectXML; got != want { + t.Errorf("#%d: MarshalIndent:\nGot:%s\nWant:\n%s", i, got, want) + } + } +} + type limitedBytesWriter struct { w io.Writer remain int // until writes fail @@ -933,6 +999,16 @@ func TestMarshalWriteErrors(t *testing.T) { } } +func TestMarshalWriteIOErrors(t *testing.T) { + enc := NewEncoder(errWriter{}) + + expectErr := "unwritable" + err := enc.Encode(&Passenger{}) + if err == nil || err.Error() != expectErr { + t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr) + } +} + func BenchmarkMarshal(b *testing.B) { for i := 0; i < b.N; i++ { Marshal(atomValue) diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go index 344ab514e37..a7a2a9655bb 100644 --- a/libgo/go/encoding/xml/read.go +++ b/libgo/go/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/libgo/go/encoding/xml/read_test.go b/libgo/go/encoding/xml/read_test.go index b45e2f0e61e..7d28c5d7d6c 100644 --- a/libgo/go/encoding/xml/read_test.go +++ b/libgo/go/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: `` + + `hello
` + + `world
` + + `
`, + tab: Tables{"hello", "world"}, + }, + { + xml: `` + + `world
` + + `hello
` + + `
`, + tab: Tables{"hello", "world"}, + }, + { + xml: `` + + `world` + + `hello` + + ``, + tab: Tables{"hello", "world"}, + }, + { + xml: `` + + `bogus
` + + `
`, + tab: Tables{}, + }, + { + xml: `` + + `only
` + + `
`, + tab: Tables{HTable: "only"}, + ns: "http://www.w3.org/TR/html4/", + }, + { + xml: `` + + `only
` + + `
`, + tab: Tables{FTable: "only"}, + ns: "http://www.w3schools.com/furniture", + }, + { + xml: `` + + `only
` + + `
`, + 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 := `hello
world
` + 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: ``, + tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}}, + }, + { + xml: ``, + tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}}, + }, + { + xml: ``, + tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}}, + }, + { + // Default space does not apply to attribute names. + xml: ``, + tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}}, + }, + { + // Default space does not apply to attribute names. + xml: ``, + tab: TableAttrs{TAttr{HTable: "", FTable: "world"}}, + }, + { + xml: ``, + tab: TableAttrs{}, + }, + { + // Default space does not apply to attribute names. + xml: ``, + tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}}, + ns: "http://www.w3schools.com/furniture", + }, + { + // Default space does not apply to attribute names. + xml: ``, + tab: TableAttrs{TAttr{HTable: "", FTable: "world"}}, + ns: "http://www.w3.org/TR/html4/", + }, + { + xml: ``, + 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 := `` + 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/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go index bbeb28d87ea..83e65402c00 100644 --- a/libgo/go/encoding/xml/typeinfo.go +++ b/libgo/go/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/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go index decb2bec650..021f7e47d91 100644 --- a/libgo/go/encoding/xml/xml.go +++ b/libgo/go/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)" } @@ -1692,7 +1703,7 @@ var HTMLAutoClose = htmlAutoClose var htmlAutoClose = []string{ /* hget http://www.w3.org/TR/html4/loose.dtd | - 9 sed -n 's/", "illegal character code U+FFFE"}, {"\r\n\x07", "illegal character code U+0007"}, {"what's up", "expected attribute name in element"}, + {"&abc\x01;", "invalid character entity &abc (no semicolon)"}, {"&\x01;", "invalid character entity & (no semicolon)"}, - {"&\xef\xbf\xbe;", "invalid character entity & (no semicolon)"}, + {"&\xef\xbf\xbe;", "invalid character entity &\uFFFE;"}, + {"&hello;", "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) } } } @@ -689,3 +685,32 @@ func TestDirectivesWithComments(t *testing.T) { } } } + +// Writer whose Write method always returns an error. +type errWriter struct{} + +func (errWriter) Write(p []byte) (n int, err error) { return 0, fmt.Errorf("unwritable") } + +func TestEscapeTextIOErrors(t *testing.T) { + expectErr := "unwritable" + err := EscapeText(errWriter{}, []byte{'A'}) + + if err == nil || err.Error() != 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/libgo/go/exp/cookiejar/jar.go b/libgo/go/exp/cookiejar/jar.go deleted file mode 100644 index 2159ec532a2..00000000000 --- a/libgo/go/exp/cookiejar/jar.go +++ /dev/null @@ -1,89 +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 cookiejar implements an RFC 6265-compliant http.CookieJar. -// -// TODO: example code to create a memory-backed cookie jar with the default -// public suffix list. -package cookiejar - -import ( - "net/http" - "net/url" -) - -// PublicSuffixList provides the public suffix of a domain. For example: -// - the public suffix of "example.com" is "com", -// - the public suffix of "foo1.foo2.foo3.co.uk" is "co.uk", and -// - the public suffix of "bar.pvt.k12.wy.us" is "pvt.k12.wy.us". -// -// Implementations of PublicSuffixList must be safe for concurrent use by -// multiple goroutines. -// -// An implementation that always returns "" is valid and may be useful for -// testing but it is not secure: it means that the HTTP server for foo.com can -// set a cookie for bar.com. -type PublicSuffixList interface { - // PublicSuffix returns the public suffix of domain. - // - // TODO: specify which of the caller and callee is responsible for IP - // addresses, for leading and trailing dots, for case sensitivity, and - // for IDN/Punycode. - PublicSuffix(domain string) string - - // String returns a description of the source of this public suffix list. - // A Jar will store its PublicSuffixList's description in its storage, - // and update the stored cookies if its list has a different description - // than the stored list. The description will typically contain something - // like a time stamp or version number. - String() string -} - -// Options are the options for creating a new Jar. -type Options struct { - // Storage is the cookie jar storage. It may not be nil. - Storage Storage - - // PublicSuffixList is the public suffix list that determines whether an - // HTTP server can set a cookie for a domain. It may not be nil. - PublicSuffixList PublicSuffixList - - // TODO: ErrorFunc for handling storage errors? -} - -// Jar implements the http.CookieJar interface from the net/http package. -type Jar struct { - storage Storage - psList PublicSuffixList -} - -// New returns a new cookie jar. -func New(o *Options) *Jar { - return &Jar{ - storage: o.Storage, - psList: o.PublicSuffixList, - } -} - -// TODO(nigeltao): how do we reject HttpOnly cookies? Do we post-process the -// return value from Jar.Cookies? -// -// HttpOnly cookies are those for regular HTTP(S) requests but should not be -// visible from JavaScript. The HttpOnly bit mitigates XSS attacks; it's not -// for HTTP vs HTTPS vs FTP transports. - -// Cookies implements the Cookies method of the http.CookieJar interface. -// -// It returns an empty slice if the URL's scheme is not HTTP or HTTPS. -func (j *Jar) Cookies(u *url.URL) []*http.Cookie { - // TODO. - return nil -} - -// SetCookies implements the SetCookies method of the http.CookieJar interface. -// -// It does nothing if the URL's scheme is not HTTP or HTTPS. -func (j *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) { - // TODO. -} diff --git a/libgo/go/exp/cookiejar/storage.go b/libgo/go/exp/cookiejar/storage.go deleted file mode 100644 index 5294f587e4c..00000000000 --- a/libgo/go/exp/cookiejar/storage.go +++ /dev/null @@ -1,101 +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 cookiejar - -import ( - "time" -) - -// Storage is a Jar's storage. It is a multi-map, mapping keys to one or more -// entries. Each entry consists of a subkey, creation time, last access time, -// and some arbitrary data. -// -// The Add and Delete methods have undefined behavior if the key is invalid. -// A valid key must use only bytes in the character class [a-z0-9.-] and -// must have at least one non-. byte. Note that this excludes any key -// containing a capital ASCII letter as well as the empty string. -type Storage interface { - // A client must call Lock before calling other methods and must call - // Unlock when finished. Between the calls to Lock and Unlock, a client - // can assume that other clients are not modifying the Storage. - Lock() - Unlock() - - // Add adds entries to the storage. Each entry's Subkey and Data must - // both be non-empty. - // - // If the Storage already contains an entry with the same key and - // subkey then the new entry is stored with the creation time of the - // old entry, and the old entry is deleted. - // - // Adding entries may cause other entries to be deleted, to maintain an - // implementation-specific storage constraint. - Add(key string, entries ...Entry) error - - // Delete deletes all entries for the given key. - Delete(key string) error - - // Entries calls f for each entry stored for that key. If f returns a - // non-nil error then the iteration stops and Entries returns that - // error. Iteration is not guaranteed to be in any particular order. - // - // If f returns an Update action then that stored entry's LastAccess - // time will be set to the time that f returned. If f returns a Delete - // action then that entry will be deleted from the Storage. - // - // f may call a Storage's Add and Delete methods; those modifications - // will not affect the list of entries visited in this call to Entries. - Entries(key string, f func(entry Entry) (Action, time.Time, error)) error - - // Keys calls f for each key stored. f will not be called on a key with - // zero entries. If f returns a non-nil error then the iteration stops - // and Keys returns that error. Iteration is not guaranteed to be in any - // particular order. - // - // f may call a Storage's Add, Delete and Entries methods; those - // modifications will not affect the list of keys visited in this call - // to Keys. - Keys(f func(key string) error) error -} - -// Entry is an entry in a Storage. -type Entry struct { - Subkey string - Data string - Creation time.Time - LastAccess time.Time -} - -// Action is an action returned by the function passed to Entries. -type Action int - -const ( - // Pass means to take no further action with an Entry. - Pass Action = iota - // Update means to update the LastAccess time of an Entry. - Update - // Delete means to delete an Entry. - Delete -) - -// ValidStorageKey returns whether the given key is valid for a Storage. -func ValidStorageKey(key string) bool { - hasNonDot := false - for i := 0; i < len(key); i++ { - switch c := key[i]; { - case 'a' <= c && c <= 'z': - fallthrough - case '0' <= c && c <= '9': - fallthrough - case c == '-': - hasNonDot = true - case c == '.': - // No-op. - default: - return false - } - } - return hasNonDot -} diff --git a/libgo/go/exp/cookiejar/storage_test.go b/libgo/go/exp/cookiejar/storage_test.go deleted file mode 100644 index de6aa2b6a7f..00000000000 --- a/libgo/go/exp/cookiejar/storage_test.go +++ /dev/null @@ -1,48 +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 cookiejar - -import ( - "testing" -) - -var validStorageKeyTests = map[string]bool{ - "": false, - ".": false, - "..": false, - "/": false, - "EXAMPLE.com": false, - "\n": false, - "\r": false, - "\r\n": false, - "\x00": false, - "back\\slash": false, - "co:lon": false, - "com,ma": false, - "semi;colon": false, - "sl/ash": false, - "sp ace": false, - "under_score": false, - "π": false, - - "-": true, - ".dot": true, - ".dot.": true, - ".metadata": true, - ".x..y..z...": true, - "dot.": true, - "example.com": true, - "foo": true, - "hy-phen": true, - "xn--bcher-kva.ch": true, -} - -func TestValidStorageKey(t *testing.T) { - for key, want := range validStorageKeyTests { - if got := ValidStorageKey(key); got != want { - t.Errorf("%q: got %v, want %v", key, got, want) - } - } -} diff --git a/libgo/go/exp/ebnf/ebnf.go b/libgo/go/exp/ebnf/ebnf.go deleted file mode 100644 index cd8c83c9210..00000000000 --- a/libgo/go/exp/ebnf/ebnf.go +++ /dev/null @@ -1,269 +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. - -// Package ebnf is a library for EBNF grammars. The input is text ([]byte) -// satisfying the following grammar (represented itself in EBNF): -// -// Production = name "=" [ Expression ] "." . -// Expression = Alternative { "|" Alternative } . -// Alternative = Term { Term } . -// Term = name | token [ "…" token ] | Group | Option | Repetition . -// Group = "(" Expression ")" . -// Option = "[" Expression "]" . -// Repetition = "{" Expression "}" . -// -// A name is a Go identifier, a token is a Go string, and comments -// and white space follow the same rules as for the Go language. -// Production names starting with an uppercase Unicode letter denote -// non-terminal productions (i.e., productions which allow white-space -// and comments between tokens); all other production names denote -// lexical productions. -// -package ebnf - -import ( - "errors" - "fmt" - "text/scanner" - "unicode" - "unicode/utf8" -) - -// ---------------------------------------------------------------------------- -// Error handling - -type errorList []error - -func (list errorList) Err() error { - if len(list) == 0 { - return nil - } - return list -} - -func (list errorList) Error() string { - switch len(list) { - case 0: - return "no errors" - case 1: - return list[0].Error() - } - return fmt.Sprintf("%s (and %d more errors)", list[0], len(list)-1) -} - -func newError(pos scanner.Position, msg string) error { - return errors.New(fmt.Sprintf("%s: %s", pos, msg)) -} - -// ---------------------------------------------------------------------------- -// Internal representation - -type ( - // An Expression node represents a production expression. - Expression interface { - // Pos is the position of the first character of the syntactic construct - Pos() scanner.Position - } - - // An Alternative node represents a non-empty list of alternative expressions. - Alternative []Expression // x | y | z - - // A Sequence node represents a non-empty list of sequential expressions. - Sequence []Expression // x y z - - // A Name node represents a production name. - Name struct { - StringPos scanner.Position - String string - } - - // A Token node represents a literal. - Token struct { - StringPos scanner.Position - String string - } - - // A List node represents a range of characters. - Range struct { - Begin, End *Token // begin ... end - } - - // A Group node represents a grouped expression. - Group struct { - Lparen scanner.Position - Body Expression // (body) - } - - // An Option node represents an optional expression. - Option struct { - Lbrack scanner.Position - Body Expression // [body] - } - - // A Repetition node represents a repeated expression. - Repetition struct { - Lbrace scanner.Position - Body Expression // {body} - } - - // A Production node represents an EBNF production. - Production struct { - Name *Name - Expr Expression - } - - // A Bad node stands for pieces of source code that lead to a parse error. - Bad struct { - TokPos scanner.Position - Error string // parser error message - } - - // A Grammar is a set of EBNF productions. The map - // is indexed by production name. - // - Grammar map[string]*Production -) - -func (x Alternative) Pos() scanner.Position { return x[0].Pos() } // the parser always generates non-empty Alternative -func (x Sequence) Pos() scanner.Position { return x[0].Pos() } // the parser always generates non-empty Sequences -func (x *Name) Pos() scanner.Position { return x.StringPos } -func (x *Token) Pos() scanner.Position { return x.StringPos } -func (x *Range) Pos() scanner.Position { return x.Begin.Pos() } -func (x *Group) Pos() scanner.Position { return x.Lparen } -func (x *Option) Pos() scanner.Position { return x.Lbrack } -func (x *Repetition) Pos() scanner.Position { return x.Lbrace } -func (x *Production) Pos() scanner.Position { return x.Name.Pos() } -func (x *Bad) Pos() scanner.Position { return x.TokPos } - -// ---------------------------------------------------------------------------- -// Grammar verification - -func isLexical(name string) bool { - ch, _ := utf8.DecodeRuneInString(name) - return !unicode.IsUpper(ch) -} - -type verifier struct { - errors errorList - worklist []*Production - reached Grammar // set of productions reached from (and including) the root production - grammar Grammar -} - -func (v *verifier) error(pos scanner.Position, msg string) { - v.errors = append(v.errors, newError(pos, msg)) -} - -func (v *verifier) push(prod *Production) { - name := prod.Name.String - if _, found := v.reached[name]; !found { - v.worklist = append(v.worklist, prod) - v.reached[name] = prod - } -} - -func (v *verifier) verifyChar(x *Token) rune { - s := x.String - if utf8.RuneCountInString(s) != 1 { - v.error(x.Pos(), "single char expected, found "+s) - return 0 - } - ch, _ := utf8.DecodeRuneInString(s) - return ch -} - -func (v *verifier) verifyExpr(expr Expression, lexical bool) { - switch x := expr.(type) { - case nil: - // empty expression - case Alternative: - for _, e := range x { - v.verifyExpr(e, lexical) - } - case Sequence: - for _, e := range x { - v.verifyExpr(e, lexical) - } - case *Name: - // a production with this name must exist; - // add it to the worklist if not yet processed - if prod, found := v.grammar[x.String]; found { - v.push(prod) - } else { - v.error(x.Pos(), "missing production "+x.String) - } - // within a lexical production references - // to non-lexical productions are invalid - if lexical && !isLexical(x.String) { - v.error(x.Pos(), "reference to non-lexical production "+x.String) - } - case *Token: - // nothing to do for now - case *Range: - i := v.verifyChar(x.Begin) - j := v.verifyChar(x.End) - if i >= j { - v.error(x.Pos(), "decreasing character range") - } - case *Group: - v.verifyExpr(x.Body, lexical) - case *Option: - v.verifyExpr(x.Body, lexical) - case *Repetition: - v.verifyExpr(x.Body, lexical) - case *Bad: - v.error(x.Pos(), x.Error) - default: - panic(fmt.Sprintf("internal error: unexpected type %T", expr)) - } -} - -func (v *verifier) verify(grammar Grammar, start string) { - // find root production - root, found := grammar[start] - if !found { - var noPos scanner.Position - v.error(noPos, "no start production "+start) - return - } - - // initialize verifier - v.worklist = v.worklist[0:0] - v.reached = make(Grammar) - v.grammar = grammar - - // work through the worklist - v.push(root) - for { - n := len(v.worklist) - 1 - if n < 0 { - break - } - prod := v.worklist[n] - v.worklist = v.worklist[0:n] - v.verifyExpr(prod.Expr, isLexical(prod.Name.String)) - } - - // check if all productions were reached - if len(v.reached) < len(v.grammar) { - for name, prod := range v.grammar { - if _, found := v.reached[name]; !found { - v.error(prod.Pos(), name+" is unreachable") - } - } - } -} - -// Verify checks that: -// - all productions used are defined -// - all productions defined are used when beginning at start -// - lexical productions refer only to other lexical productions -// -// Position information is interpreted relative to the file set fset. -// -func Verify(grammar Grammar, start string) error { - var v verifier - v.verify(grammar, start) - return v.errors.Err() -} diff --git a/libgo/go/exp/ebnf/ebnf_test.go b/libgo/go/exp/ebnf/ebnf_test.go deleted file mode 100644 index 8cfd6b9c370..00000000000 --- a/libgo/go/exp/ebnf/ebnf_test.go +++ /dev/null @@ -1,71 +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. - -package ebnf - -import ( - "bytes" - "testing" -) - -var goodGrammars = []string{ - `Program = .`, - - `Program = foo . - foo = "foo" .`, - - `Program = "a" | "b" "c" .`, - - `Program = "a" … "z" .`, - - `Program = Song . - Song = { Note } . - Note = Do | (Re | Mi | Fa | So | La) | Ti . - Do = "c" . - Re = "d" . - Mi = "e" . - Fa = "f" . - So = "g" . - La = "a" . - Ti = ti . - ti = "b" .`, -} - -var badGrammars = []string{ - `Program = | .`, - `Program = | b .`, - `Program = a … b .`, - `Program = "a" … .`, - `Program = … "b" .`, - `Program = () .`, - `Program = [] .`, - `Program = {} .`, -} - -func checkGood(t *testing.T, src string) { - grammar, err := Parse("", bytes.NewBuffer([]byte(src))) - if err != nil { - t.Errorf("Parse(%s) failed: %v", src, err) - return - } - if err = Verify(grammar, "Program"); err != nil { - t.Errorf("Verify(%s) failed: %v", src, err) - } -} - -func checkBad(t *testing.T, src string) { - _, err := Parse("", bytes.NewBuffer([]byte(src))) - if err == nil { - t.Errorf("Parse(%s) should have failed", src) - } -} - -func TestGrammars(t *testing.T) { - for _, src := range goodGrammars { - checkGood(t, src) - } - for _, src := range badGrammars { - checkBad(t, src) - } -} diff --git a/libgo/go/exp/ebnf/parser.go b/libgo/go/exp/ebnf/parser.go deleted file mode 100644 index 7a7e3cc16e4..00000000000 --- a/libgo/go/exp/ebnf/parser.go +++ /dev/null @@ -1,190 +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. - -package ebnf - -import ( - "io" - "strconv" - "text/scanner" -) - -type parser struct { - errors errorList - scanner scanner.Scanner - pos scanner.Position // token position - tok rune // one token look-ahead - lit string // token literal -} - -func (p *parser) next() { - p.tok = p.scanner.Scan() - p.pos = p.scanner.Position - p.lit = p.scanner.TokenText() -} - -func (p *parser) error(pos scanner.Position, msg string) { - p.errors = append(p.errors, newError(pos, msg)) -} - -func (p *parser) errorExpected(pos scanner.Position, msg string) { - msg = `expected "` + msg + `"` - if pos.Offset == p.pos.Offset { - // the error happened at the current position; - // make the error message more specific - msg += ", found " + scanner.TokenString(p.tok) - if p.tok < 0 { - msg += " " + p.lit - } - } - p.error(pos, msg) -} - -func (p *parser) expect(tok rune) scanner.Position { - pos := p.pos - if p.tok != tok { - p.errorExpected(pos, scanner.TokenString(tok)) - } - p.next() // make progress in any case - return pos -} - -func (p *parser) parseIdentifier() *Name { - pos := p.pos - name := p.lit - p.expect(scanner.Ident) - return &Name{pos, name} -} - -func (p *parser) parseToken() *Token { - pos := p.pos - value := "" - if p.tok == scanner.String { - value, _ = strconv.Unquote(p.lit) - // Unquote may fail with an error, but only if the scanner found - // an illegal string in the first place. In this case the error - // has already been reported. - p.next() - } else { - p.expect(scanner.String) - } - return &Token{pos, value} -} - -// ParseTerm returns nil if no term was found. -func (p *parser) parseTerm() (x Expression) { - pos := p.pos - - switch p.tok { - case scanner.Ident: - x = p.parseIdentifier() - - case scanner.String: - tok := p.parseToken() - x = tok - const ellipsis = '…' // U+2026, the horizontal ellipsis character - if p.tok == ellipsis { - p.next() - x = &Range{tok, p.parseToken()} - } - - case '(': - p.next() - x = &Group{pos, p.parseExpression()} - p.expect(')') - - case '[': - p.next() - x = &Option{pos, p.parseExpression()} - p.expect(']') - - case '{': - p.next() - x = &Repetition{pos, p.parseExpression()} - p.expect('}') - } - - return x -} - -func (p *parser) parseSequence() Expression { - var list Sequence - - for x := p.parseTerm(); x != nil; x = p.parseTerm() { - list = append(list, x) - } - - // no need for a sequence if list.Len() < 2 - switch len(list) { - case 0: - p.errorExpected(p.pos, "term") - return &Bad{p.pos, "term expected"} - case 1: - return list[0] - } - - return list -} - -func (p *parser) parseExpression() Expression { - var list Alternative - - for { - list = append(list, p.parseSequence()) - if p.tok != '|' { - break - } - p.next() - } - // len(list) > 0 - - // no need for an Alternative node if list.Len() < 2 - if len(list) == 1 { - return list[0] - } - - return list -} - -func (p *parser) parseProduction() *Production { - name := p.parseIdentifier() - p.expect('=') - var expr Expression - if p.tok != '.' { - expr = p.parseExpression() - } - p.expect('.') - return &Production{name, expr} -} - -func (p *parser) parse(filename string, src io.Reader) Grammar { - p.scanner.Init(src) - p.scanner.Filename = filename - p.next() // initializes pos, tok, lit - - grammar := make(Grammar) - for p.tok != scanner.EOF { - prod := p.parseProduction() - name := prod.Name.String - if _, found := grammar[name]; !found { - grammar[name] = prod - } else { - p.error(prod.Pos(), name+" declared already") - } - } - - return grammar -} - -// Parse parses a set of EBNF productions from source src. -// It returns a set of productions. Errors are reported -// for incorrect syntax and if a production is declared -// more than once; the filename is used only for error -// positions. -// -func Parse(filename string, src io.Reader) (Grammar, error) { - var p parser - grammar := p.parse(filename, src) - return grammar, p.errors.Err() -} diff --git a/libgo/go/exp/ebnflint/doc.go b/libgo/go/exp/ebnflint/doc.go deleted file mode 100644 index 4bb22a4cb80..00000000000 --- a/libgo/go/exp/ebnflint/doc.go +++ /dev/null @@ -1,22 +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. - -/* - -Ebnflint verifies that EBNF productions are consistent and grammatically correct. -It reads them from an HTML document such as the Go specification. - -Grammar productions are grouped in boxes demarcated by the HTML elements -
-	
- - -Usage: - go tool ebnflint [--start production] [file] - -The --start flag specifies the name of the start production for -the grammar; it defaults to "Start". - -*/ -package documentation diff --git a/libgo/go/exp/ebnflint/ebnflint.go b/libgo/go/exp/ebnflint/ebnflint.go deleted file mode 100644 index d54fb229d03..00000000000 --- a/libgo/go/exp/ebnflint/ebnflint.go +++ /dev/null @@ -1,122 +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. - -package main - -import ( - "bytes" - "exp/ebnf" - "flag" - "fmt" - "go/scanner" - "go/token" - "io" - "io/ioutil" - "os" - "path/filepath" -) - -var fset = token.NewFileSet() -var start = flag.String("start", "Start", "name of start production") - -func usage() { - fmt.Fprintf(os.Stderr, "usage: go tool ebnflint [flags] [filename]\n") - flag.PrintDefaults() - os.Exit(1) -} - -// Markers around EBNF sections in .html files -var ( - open = []byte(`
`)
-	close = []byte(`
`) -) - -func report(err error) { - scanner.PrintError(os.Stderr, err) - os.Exit(1) -} - -func extractEBNF(src []byte) []byte { - var buf bytes.Buffer - - for { - // i = beginning of EBNF text - i := bytes.Index(src, open) - if i < 0 { - break // no EBNF found - we are done - } - i += len(open) - - // write as many newlines as found in the excluded text - // to maintain correct line numbers in error messages - for _, ch := range src[0:i] { - if ch == '\n' { - buf.WriteByte('\n') - } - } - - // j = end of EBNF text (or end of source) - j := bytes.Index(src[i:], close) // close marker - if j < 0 { - j = len(src) - i - } - j += i - - // copy EBNF text - buf.Write(src[i:j]) - - // advance - src = src[j:] - } - - return buf.Bytes() -} - -func main() { - flag.Parse() - - var ( - name string - r io.Reader - ) - switch flag.NArg() { - case 0: - name, r = "", os.Stdin - case 1: - name = flag.Arg(0) - default: - usage() - } - - if err := verify(name, *start, r); err != nil { - report(err) - } -} - -func verify(name, start string, r io.Reader) error { - if r == nil { - f, err := os.Open(name) - if err != nil { - return err - } - defer f.Close() - r = f - } - - src, err := ioutil.ReadAll(r) - if err != nil { - return err - } - - if filepath.Ext(name) == ".html" || bytes.Index(src, open) >= 0 { - src = extractEBNF(src) - } - - grammar, err := ebnf.Parse(name, bytes.NewBuffer(src)) - if err != nil { - return err - } - - return ebnf.Verify(grammar, start) -} diff --git a/libgo/go/exp/ebnflint/ebnflint_test.go b/libgo/go/exp/ebnflint/ebnflint_test.go deleted file mode 100644 index 875dbc19aca..00000000000 --- a/libgo/go/exp/ebnflint/ebnflint_test.go +++ /dev/null @@ -1,16 +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 main - -import ( - "runtime" - "testing" -) - -func TestSpec(t *testing.T) { - if err := verify(runtime.GOROOT()+"/doc/go_spec.html", "SourceFile", nil); err != nil { - t.Fatal(err) - } -} diff --git a/libgo/go/exp/gotype/doc.go b/libgo/go/exp/gotype/doc.go deleted file mode 100644 index 1168086771f..00000000000 --- a/libgo/go/exp/gotype/doc.go +++ /dev/null @@ -1,63 +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. - -/* -The gotype command does syntactic and semantic analysis of Go files -and packages similar to the analysis performed by the front-end of -a Go compiler. Errors are reported if the analysis fails; otherwise -gotype is quiet (unless -v is set). - -Without a list of paths, gotype processes the standard input, which must -be the source of a single package file. - -Given a list of file names, each file must be a source file belonging to -the same package unless the package name is explicitly specified with the --p flag. - -Given a directory name, gotype collects all .go files in the directory -and processes them as if they were provided as an explicit list of file -names. Each directory is processed independently. Files starting with . -or not ending in .go are ignored. - -Usage: - gotype [flags] [path ...] - -The flags are: - -e - Print all (including spurious) errors. - -p pkgName - Process only those files in package pkgName. - -r - Recursively process subdirectories. - -v - Verbose mode. - -Debugging flags: - -comments - Parse comments (ignored if -ast not set). - -ast - Print AST (disables concurrent parsing). - -trace - Print parse trace (disables concurrent parsing). - - -Examples - -To check the files file.go, old.saved, and .ignored: - - gotype file.go old.saved .ignored - -To check all .go files belonging to package main in the current directory -and recursively in all subdirectories: - - gotype -p main -r . - -To verify the output of a pipe: - - echo "package foo" | gotype - -*/ -package documentation - -// BUG(gri): At the moment, only single-file scope analysis is performed. diff --git a/libgo/go/exp/gotype/gotype.go b/libgo/go/exp/gotype/gotype.go deleted file mode 100644 index bb3237c37cb..00000000000 --- a/libgo/go/exp/gotype/gotype.go +++ /dev/null @@ -1,184 +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 main - -import ( - "flag" - "fmt" - "go/ast" - "go/parser" - "go/scanner" - "go/token" - "go/types" - "io/ioutil" - "os" - "path/filepath" - "strings" -) - -var ( - // main operation modes - pkgName = flag.String("p", "", "process only those files in package pkgName") - recursive = flag.Bool("r", false, "recursively process subdirectories") - verbose = flag.Bool("v", false, "verbose mode") - allErrors = flag.Bool("e", false, "print all (including spurious) errors") - - // debugging support - parseComments = flag.Bool("comments", false, "parse comments (ignored if -ast not set)") - printTrace = flag.Bool("trace", false, "print parse trace") - printAST = flag.Bool("ast", false, "print AST") -) - -var exitCode = 0 - -func usage() { - fmt.Fprintf(os.Stderr, "usage: gotype [flags] [path ...]\n") - flag.PrintDefaults() - os.Exit(2) -} - -func report(err error) { - scanner.PrintError(os.Stderr, err) - exitCode = 2 -} - -// parse returns the AST for the Go source src. -// The filename is for error reporting only. -// The result is nil if there were errors or if -// the file does not belong to the -p package. -func parse(fset *token.FileSet, filename string, src []byte) *ast.File { - if *verbose { - fmt.Println(filename) - } - - // ignore files with different package name - if *pkgName != "" { - file, err := parser.ParseFile(fset, filename, src, parser.PackageClauseOnly) - if err != nil { - report(err) - return nil - } - if file.Name.Name != *pkgName { - if *verbose { - fmt.Printf("\tignored (package %s)\n", file.Name.Name) - } - return nil - } - } - - // parse entire file - mode := parser.DeclarationErrors - if *allErrors { - mode |= parser.SpuriousErrors - } - if *parseComments && *printAST { - mode |= parser.ParseComments - } - if *printTrace { - mode |= parser.Trace - } - file, err := parser.ParseFile(fset, filename, src, mode) - if err != nil { - report(err) - return nil - } - if *printAST { - ast.Print(fset, file) - } - - return file -} - -func parseStdin(fset *token.FileSet) (files []*ast.File) { - src, err := ioutil.ReadAll(os.Stdin) - if err != nil { - report(err) - return - } - const filename = "" - if file := parse(fset, filename, src); file != nil { - files = []*ast.File{file} - } - return -} - -func parseFiles(fset *token.FileSet, filenames []string) (files []*ast.File) { - for _, filename := range filenames { - src, err := ioutil.ReadFile(filename) - if err != nil { - report(err) - continue - } - if file := parse(fset, filename, src); file != nil { - files = append(files, file) - } - } - return -} - -func isGoFilename(filename string) bool { - // ignore non-Go files - return !strings.HasPrefix(filename, ".") && strings.HasSuffix(filename, ".go") -} - -func processDirectory(dirname string) { - f, err := os.Open(dirname) - if err != nil { - report(err) - return - } - filenames, err := f.Readdirnames(-1) - f.Close() - if err != nil { - report(err) - // continue since filenames may not be empty - } - for i, filename := range filenames { - filenames[i] = filepath.Join(dirname, filename) - } - processFiles(filenames, false) -} - -func processFiles(filenames []string, allFiles bool) { - i := 0 - for _, filename := range filenames { - switch info, err := os.Stat(filename); { - case err != nil: - report(err) - case info.IsDir(): - if allFiles || *recursive { - processDirectory(filename) - } - default: - if allFiles || isGoFilename(info.Name()) { - filenames[i] = filename - i++ - } - } - } - fset := token.NewFileSet() - processPackage(fset, parseFiles(fset, filenames[0:i])) -} - -func processPackage(fset *token.FileSet, files []*ast.File) { - _, err := types.Check(fset, files) - if err != nil { - report(err) - } -} - -func main() { - flag.Usage = usage - flag.Parse() - - if flag.NArg() == 0 { - fset := token.NewFileSet() - processPackage(fset, parseStdin(fset)) - } else { - processFiles(flag.Args(), true) - } - - os.Exit(exitCode) -} diff --git a/libgo/go/exp/gotype/gotype_test.go b/libgo/go/exp/gotype/gotype_test.go deleted file mode 100644 index 67ab7cfa74a..00000000000 --- a/libgo/go/exp/gotype/gotype_test.go +++ /dev/null @@ -1,215 +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 main - -import ( - "go/build" - "path/filepath" - "runtime" - "strings" - "testing" -) - -func runTest(t *testing.T, path string) { - exitCode = 0 - - *recursive = false - if suffix := ".go"; strings.HasSuffix(path, suffix) { - // single file - path = filepath.Join(runtime.GOROOT(), "src/pkg", path) - path, file := filepath.Split(path) - *pkgName = file[:len(file)-len(suffix)] - processFiles([]string{path}, true) - } else { - // package directory - // TODO(gri) gotype should use the build package instead - ctxt := build.Default - ctxt.CgoEnabled = false - pkg, err := ctxt.Import(path, "", 0) - if err != nil { - t.Errorf("build.Import error for path = %s: %s", path, err) - return - } - // TODO(gri) there ought to be a more direct way using the build package... - files := make([]string, len(pkg.GoFiles)) - for i, file := range pkg.GoFiles { - files[i] = filepath.Join(pkg.Dir, file) - } - *pkgName = pkg.Name - processFiles(files, true) - } - - if exitCode != 0 { - t.Errorf("processing %s failed: exitCode = %d", path, exitCode) - } -} - -var tests = []string{ - // individual files - "exp/gotype/testdata/test1.go", - - // directories - // Note: Packages that don't typecheck yet are commented out. - // Unless there is a comment next to the commented out packages, - // the package doesn't typecheck due to errors in the shift - // expression checker. - "archive/tar", - "archive/zip", - - "bufio", - "bytes", - - // "compress/bzip2", - "compress/flate", - "compress/gzip", - // "compress/lzw", - "compress/zlib", - - "container/heap", - "container/list", - "container/ring", - - "crypto", - "crypto/aes", - "crypto/cipher", - "crypto/des", - "crypto/dsa", - "crypto/ecdsa", - "crypto/elliptic", - "crypto/hmac", - "crypto/md5", - // "crypto/rand", - "crypto/rc4", - // "crypto/rsa", // intermittent failure: /home/gri/go2/src/pkg/crypto/rsa/pkcs1v15.go:21:27: undeclared name: io - "crypto/sha1", - "crypto/sha256", - "crypto/sha512", - "crypto/subtle", - "crypto/tls", - "crypto/x509", - "crypto/x509/pkix", - - "database/sql", - "database/sql/driver", - - // "debug/dwarf", - "debug/elf", - "debug/gosym", - "debug/macho", - "debug/pe", - - "encoding/ascii85", - // "encoding/asn1", - "encoding/base32", - "encoding/base64", - "encoding/binary", - "encoding/csv", - "encoding/gob", - "encoding/hex", - "encoding/json", - "encoding/pem", - "encoding/xml", - - "errors", - "expvar", - "flag", - "fmt", - - "exp/gotype", - - "go/ast", - "go/build", - "go/doc", - "go/format", - "go/parser", - "go/printer", - "go/scanner", - // "go/token", - "go/types", - - "hash/adler32", - "hash/crc32", - "hash/crc64", - "hash/fnv", - - "image", - "image/color", - "image/draw", - "image/gif", - // "image/jpeg", - "image/png", - - "index/suffixarray", - - "io", - "io/ioutil", - - "log", - "log/syslog", - - // "math", - //"math/big", - "math/cmplx", - "math/rand", - - "mime", - "mime/multipart", - - // "net", - "net/http", - "net/http/cgi", - "net/http/fcgi", - "net/http/httptest", - "net/http/httputil", - "net/http/pprof", - "net/mail", - "net/rpc", - "net/rpc/jsonrpc", - "net/smtp", - // "net/textproto", - "net/url", - - "path", - "path/filepath", - - "reflect", - - "regexp", - "regexp/syntax", - - // "runtime", - "runtime/cgo", - "runtime/debug", - "runtime/pprof", - - "sort", - // "strconv", - "strings", - - "sync", - "sync/atomic", - - // "syscall", - - "testing", - "testing/iotest", - "testing/quick", - - // "text/scanner", - "text/tabwriter", - "text/template", - "text/template/parse", - - "time", - "unicode", - "unicode/utf16", - "unicode/utf8", -} - -func Test(t *testing.T) { - for _, test := range tests { - runTest(t, test) - } -} diff --git a/libgo/go/exp/gotype/testdata/test1.go b/libgo/go/exp/gotype/testdata/test1.go deleted file mode 100644 index 6a6f477e780..00000000000 --- a/libgo/go/exp/gotype/testdata/test1.go +++ /dev/null @@ -1,27 +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 test1 - -func _() { - // the scope of a local type declaration starts immediately after the type name - type T struct{ _ *T } -} - -func _(x interface{}) { - // the variable defined by a TypeSwitchGuard is declared in each TypeCaseClause - switch t := x.(type) { - case int: - _ = t - case float32: - _ = t - default: - _ = t - } - - // the variable defined by a TypeSwitchGuard must not conflict with other - // variables declared in the initial simple statement - switch t := 0; t := x.(type) { - } -} diff --git a/libgo/go/exp/html/atom/atom.go b/libgo/go/exp/html/atom/atom.go deleted file mode 100644 index 2dbd0fbf7f5..00000000000 --- a/libgo/go/exp/html/atom/atom.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 atom provides integer codes (also known as atoms) for a fixed set of -// frequently occurring HTML strings: tag names and attribute keys such as "p" -// and "id". -// -// Sharing an atom's name between all elements with the same tag can result in -// fewer string allocations when tokenizing and parsing HTML. Integer -// comparisons are also generally faster than string comparisons. -// -// The value of an atom's particular code is not guaranteed to stay the same -// between versions of this package. Neither is any ordering guaranteed: -// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to -// be dense. The only guarantees are that e.g. looking up "div" will yield -// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0. -// -// TODO(rsc): When this package moves out of exp we need to freeze atom values -// across releases. -package atom - -// Atom is an integer code for a string. The zero value maps to "". -type Atom uint32 - -// String returns the atom's name. -func (a Atom) String() string { - start := uint32(a >> 8) - n := uint32(a & 0xff) - if start+n > uint32(len(atomText)) { - return "" - } - return atomText[start : start+n] -} - -func (a Atom) string() string { - return atomText[a>>8 : a>>8+a&0xff] -} - -// fnv computes the FNV hash with an arbitrary starting value h. -func fnv(h uint32, s []byte) uint32 { - for i := range s { - h ^= uint32(s[i]) - h *= 16777619 - } - return h -} - -func match(s string, t []byte) bool { - for i, c := range t { - if s[i] != c { - return false - } - } - return true -} - -// Lookup returns the atom whose name is s. It returns zero if there is no -// such atom. The lookup is case sensitive. -func Lookup(s []byte) Atom { - if len(s) == 0 || len(s) > maxAtomLen { - return 0 - } - h := fnv(hash0, s) - if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { - return a - } - if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { - return a - } - return 0 -} - -// String returns a string whose contents are equal to s. In that sense, it is -// equivalent to string(s) but may be more efficient. -func String(s []byte) string { - if a := Lookup(s); a != 0 { - return a.String() - } - return string(s) -} diff --git a/libgo/go/exp/html/atom/atom_test.go b/libgo/go/exp/html/atom/atom_test.go deleted file mode 100644 index 6e33704dd5e..00000000000 --- a/libgo/go/exp/html/atom/atom_test.go +++ /dev/null @@ -1,109 +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 atom - -import ( - "sort" - "testing" -) - -func TestKnown(t *testing.T) { - for _, s := range testAtomList { - if atom := Lookup([]byte(s)); atom.String() != s { - t.Errorf("Lookup(%q) = %#x (%q)", s, uint32(atom), atom.String()) - } - } -} - -func TestHits(t *testing.T) { - for _, a := range table { - if a == 0 { - continue - } - got := Lookup([]byte(a.String())) - if got != a { - t.Errorf("Lookup(%q) = %#x, want %#x", a.String(), uint32(got), uint32(a)) - } - } -} - -func TestMisses(t *testing.T) { - testCases := []string{ - "", - "\x00", - "\xff", - "A", - "DIV", - "Div", - "dIV", - "aa", - "a\x00", - "ab", - "abb", - "abbr0", - "abbr ", - " abbr", - " a", - "acceptcharset", - "acceptCharset", - "accept_charset", - "h0", - "h1h2", - "h7", - "onClick", - "λ", - // The following string has the same hash (0xa1d7fab7) as "onmouseover". - "\x00\x00\x00\x00\x00\x50\x18\xae\x38\xd0\xb7", - } - for _, tc := range testCases { - got := Lookup([]byte(tc)) - if got != 0 { - t.Errorf("Lookup(%q): got %d, want 0", tc, got) - } - } -} - -func TestForeignObject(t *testing.T) { - const ( - afo = Foreignobject - afO = ForeignObject - sfo = "foreignobject" - sfO = "foreignObject" - ) - if got := Lookup([]byte(sfo)); got != afo { - t.Errorf("Lookup(%q): got %#v, want %#v", sfo, got, afo) - } - if got := Lookup([]byte(sfO)); got != afO { - t.Errorf("Lookup(%q): got %#v, want %#v", sfO, got, afO) - } - if got := afo.String(); got != sfo { - t.Errorf("Atom(%#v).String(): got %q, want %q", afo, got, sfo) - } - if got := afO.String(); got != sfO { - t.Errorf("Atom(%#v).String(): got %q, want %q", afO, got, sfO) - } -} - -func BenchmarkLookup(b *testing.B) { - sortedTable := make([]string, 0, len(table)) - for _, a := range table { - if a != 0 { - sortedTable = append(sortedTable, a.String()) - } - } - sort.Strings(sortedTable) - - x := make([][]byte, 1000) - for i := range x { - x[i] = []byte(sortedTable[i%len(sortedTable)]) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - for _, s := range x { - Lookup(s) - } - } -} diff --git a/libgo/go/exp/html/atom/gen.go b/libgo/go/exp/html/atom/gen.go deleted file mode 100644 index 9958a718842..00000000000 --- a/libgo/go/exp/html/atom/gen.go +++ /dev/null @@ -1,636 +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. - -// +build ignore - -package main - -// This program generates table.go and table_test.go. -// Invoke as -// -// go run gen.go |gofmt >table.go -// go run gen.go -test |gofmt >table_test.go - -import ( - "flag" - "fmt" - "math/rand" - "os" - "sort" - "strings" -) - -// identifier converts s to a Go exported identifier. -// It converts "div" to "Div" and "accept-charset" to "AcceptCharset". -func identifier(s string) string { - b := make([]byte, 0, len(s)) - cap := true - for _, c := range s { - if c == '-' { - cap = true - continue - } - if cap && 'a' <= c && c <= 'z' { - c -= 'a' - 'A' - } - cap = false - b = append(b, byte(c)) - } - return string(b) -} - -var test = flag.Bool("test", false, "generate table_test.go") - -func main() { - flag.Parse() - - var all []string - all = append(all, elements...) - all = append(all, attributes...) - all = append(all, eventHandlers...) - all = append(all, extra...) - sort.Strings(all) - - if *test { - fmt.Printf("// generated by go run gen.go -test; DO NOT EDIT\n\n") - fmt.Printf("package atom\n\n") - fmt.Printf("var testAtomList = []string{\n") - for _, s := range all { - fmt.Printf("\t%q,\n", s) - } - fmt.Printf("}\n") - return - } - - // uniq - lists have dups - // compute max len too - maxLen := 0 - w := 0 - for _, s := range all { - if w == 0 || all[w-1] != s { - if maxLen < len(s) { - maxLen = len(s) - } - all[w] = s - w++ - } - } - all = all[:w] - - // Find hash that minimizes table size. - var best *table - for i := 0; i < 1000000; i++ { - if best != nil && 1<<(best.k-1) < len(all) { - break - } - h := rand.Uint32() - for k := uint(0); k <= 16; k++ { - if best != nil && k >= best.k { - break - } - var t table - if t.init(h, k, all) { - best = &t - break - } - } - } - if best == nil { - fmt.Fprintf(os.Stderr, "failed to construct string table\n") - os.Exit(1) - } - - // Lay out strings, using overlaps when possible. - layout := append([]string{}, all...) - - // Remove strings that are substrings of other strings - for changed := true; changed; { - changed = false - for i, s := range layout { - if s == "" { - continue - } - for j, t := range layout { - if i != j && t != "" && strings.Contains(s, t) { - changed = true - layout[j] = "" - } - } - } - } - - // Join strings where one suffix matches another prefix. - for { - // Find best i, j, k such that layout[i][len-k:] == layout[j][:k], - // maximizing overlap length k. - besti := -1 - bestj := -1 - bestk := 0 - for i, s := range layout { - if s == "" { - continue - } - for j, t := range layout { - if i == j { - continue - } - for k := bestk + 1; k <= len(s) && k <= len(t); k++ { - if s[len(s)-k:] == t[:k] { - besti = i - bestj = j - bestk = k - } - } - } - } - if bestk > 0 { - layout[besti] += layout[bestj][bestk:] - layout[bestj] = "" - continue - } - break - } - - text := strings.Join(layout, "") - - atom := map[string]uint32{} - for _, s := range all { - off := strings.Index(text, s) - if off < 0 { - panic("lost string " + s) - } - atom[s] = uint32(off<<8 | len(s)) - } - - // Generate the Go code. - fmt.Printf("// generated by go run gen.go; DO NOT EDIT\n\n") - fmt.Printf("package atom\n\nconst (\n") - for _, s := range all { - fmt.Printf("\t%s Atom = %#x\n", identifier(s), atom[s]) - } - fmt.Printf(")\n\n") - - fmt.Printf("const hash0 = %#x\n\n", best.h0) - fmt.Printf("const maxAtomLen = %d\n\n", maxLen) - - fmt.Printf("var table = [1<<%d]Atom{\n", best.k) - for i, s := range best.tab { - if s == "" { - continue - } - fmt.Printf("\t%#x: %#x, // %s\n", i, atom[s], s) - } - fmt.Printf("}\n") - datasize := (1 << best.k) * 4 - - fmt.Printf("const atomText =\n") - textsize := len(text) - for len(text) > 60 { - fmt.Printf("\t%q +\n", text[:60]) - text = text[60:] - } - fmt.Printf("\t%q\n\n", text) - - fmt.Fprintf(os.Stderr, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) -} - -type byLen []string - -func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } -func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x byLen) Len() int { return len(x) } - -// fnv computes the FNV hash with an arbitrary starting value h. -func fnv(h uint32, s string) uint32 { - for i := 0; i < len(s); i++ { - h ^= uint32(s[i]) - h *= 16777619 - } - return h -} - -// A table represents an attempt at constructing the lookup table. -// The lookup table uses cuckoo hashing, meaning that each string -// can be found in one of two positions. -type table struct { - h0 uint32 - k uint - mask uint32 - tab []string -} - -// hash returns the two hashes for s. -func (t *table) hash(s string) (h1, h2 uint32) { - h := fnv(t.h0, s) - h1 = h & t.mask - h2 = (h >> 16) & t.mask - return -} - -// init initializes the table with the given parameters. -// h0 is the initial hash value, -// k is the number of bits of hash value to use, and -// x is the list of strings to store in the table. -// init returns false if the table cannot be constructed. -func (t *table) init(h0 uint32, k uint, x []string) bool { - t.h0 = h0 - t.k = k - t.tab = make([]string, 1< len(t.tab) { - return false - } - s := t.tab[i] - h1, h2 := t.hash(s) - j := h1 + h2 - i - if t.tab[j] != "" && !t.push(j, depth+1) { - return false - } - t.tab[j] = s - return true -} - -// The lists of element names and attribute keys were taken from -// http://www.whatwg.org/specs/web-apps/current-work/multipage/section-index.html -// as of the "HTML Living Standard - Last Updated 30 May 2012" version. - -var elements = []string{ - "a", - "abbr", - "address", - "area", - "article", - "aside", - "audio", - "b", - "base", - "bdi", - "bdo", - "blockquote", - "body", - "br", - "button", - "canvas", - "caption", - "cite", - "code", - "col", - "colgroup", - "command", - "data", - "datalist", - "dd", - "del", - "details", - "dfn", - "dialog", - "div", - "dl", - "dt", - "em", - "embed", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "head", - "header", - "hgroup", - "hr", - "html", - "i", - "iframe", - "img", - "input", - "ins", - "kbd", - "keygen", - "label", - "legend", - "li", - "link", - "map", - "mark", - "menu", - "meta", - "meter", - "nav", - "noscript", - "object", - "ol", - "optgroup", - "option", - "output", - "p", - "param", - "pre", - "progress", - "q", - "rp", - "rt", - "ruby", - "s", - "samp", - "script", - "section", - "select", - "small", - "source", - "span", - "strong", - "style", - "sub", - "summary", - "sup", - "table", - "tbody", - "td", - "textarea", - "tfoot", - "th", - "thead", - "time", - "title", - "tr", - "track", - "u", - "ul", - "var", - "video", - "wbr", -} - -var attributes = []string{ - "accept", - "accept-charset", - "accesskey", - "action", - "alt", - "async", - "autocomplete", - "autofocus", - "autoplay", - "border", - "challenge", - "charset", - "checked", - "cite", - "class", - "cols", - "colspan", - "command", - "content", - "contenteditable", - "contextmenu", - "controls", - "coords", - "crossorigin", - "data", - "datetime", - "default", - "defer", - "dir", - "dirname", - "disabled", - "download", - "draggable", - "dropzone", - "enctype", - "for", - "form", - "formaction", - "formenctype", - "formmethod", - "formnovalidate", - "formtarget", - "headers", - "height", - "hidden", - "high", - "href", - "hreflang", - "http-equiv", - "icon", - "id", - "inert", - "ismap", - "itemid", - "itemprop", - "itemref", - "itemscope", - "itemtype", - "keytype", - "kind", - "label", - "lang", - "list", - "loop", - "low", - "manifest", - "max", - "maxlength", - "media", - "mediagroup", - "method", - "min", - "multiple", - "muted", - "name", - "novalidate", - "open", - "optimum", - "pattern", - "ping", - "placeholder", - "poster", - "preload", - "radiogroup", - "readonly", - "rel", - "required", - "reversed", - "rows", - "rowspan", - "sandbox", - "spellcheck", - "scope", - "scoped", - "seamless", - "selected", - "shape", - "size", - "sizes", - "span", - "src", - "srcdoc", - "srclang", - "start", - "step", - "style", - "tabindex", - "target", - "title", - "translate", - "type", - "typemustmatch", - "usemap", - "value", - "width", - "wrap", -} - -var eventHandlers = []string{ - "onabort", - "onafterprint", - "onbeforeprint", - "onbeforeunload", - "onblur", - "oncancel", - "oncanplay", - "oncanplaythrough", - "onchange", - "onclick", - "onclose", - "oncontextmenu", - "oncuechange", - "ondblclick", - "ondrag", - "ondragend", - "ondragenter", - "ondragleave", - "ondragover", - "ondragstart", - "ondrop", - "ondurationchange", - "onemptied", - "onended", - "onerror", - "onfocus", - "onhashchange", - "oninput", - "oninvalid", - "onkeydown", - "onkeypress", - "onkeyup", - "onload", - "onloadeddata", - "onloadedmetadata", - "onloadstart", - "onmessage", - "onmousedown", - "onmousemove", - "onmouseout", - "onmouseover", - "onmouseup", - "onmousewheel", - "onoffline", - "ononline", - "onpagehide", - "onpageshow", - "onpause", - "onplay", - "onplaying", - "onpopstate", - "onprogress", - "onratechange", - "onreset", - "onresize", - "onscroll", - "onseeked", - "onseeking", - "onselect", - "onshow", - "onstalled", - "onstorage", - "onsubmit", - "onsuspend", - "ontimeupdate", - "onunload", - "onvolumechange", - "onwaiting", -} - -// extra are ad-hoc values not covered by any of the lists above. -var extra = []string{ - "align", - "annotation", - "annotation-xml", - "applet", - "basefont", - "bgsound", - "big", - "blink", - "center", - "color", - "desc", - "face", - "font", - "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive. - "foreignobject", - "frame", - "frameset", - "image", - "isindex", - "listing", - "malignmark", - "marquee", - "math", - "mglyph", - "mi", - "mn", - "mo", - "ms", - "mtext", - "nobr", - "noembed", - "noframes", - "plaintext", - "prompt", - "public", - "spacer", - "strike", - "svg", - "system", - "tt", - "xmp", -} diff --git a/libgo/go/exp/html/atom/table.go b/libgo/go/exp/html/atom/table.go deleted file mode 100644 index 20b8b8a5903..00000000000 --- a/libgo/go/exp/html/atom/table.go +++ /dev/null @@ -1,694 +0,0 @@ -// generated by go run gen.go; DO NOT EDIT - -package atom - -const ( - A Atom = 0x1 - Abbr Atom = 0x4 - Accept Atom = 0x2106 - AcceptCharset Atom = 0x210e - Accesskey Atom = 0x3309 - Action Atom = 0x21b06 - Address Atom = 0x5d507 - Align Atom = 0x1105 - Alt Atom = 0x4503 - Annotation Atom = 0x18d0a - AnnotationXml Atom = 0x18d0e - Applet Atom = 0x2d106 - Area Atom = 0x31804 - Article Atom = 0x39907 - Aside Atom = 0x4f05 - Async Atom = 0x9305 - Audio Atom = 0xaf05 - Autocomplete Atom = 0xd50c - Autofocus Atom = 0xe109 - Autoplay Atom = 0x10c08 - B Atom = 0x101 - Base Atom = 0x11404 - Basefont Atom = 0x11408 - Bdi Atom = 0x1a03 - Bdo Atom = 0x12503 - Bgsound Atom = 0x13807 - Big Atom = 0x14403 - Blink Atom = 0x14705 - Blockquote Atom = 0x14c0a - Body Atom = 0x2f04 - Border Atom = 0x15606 - Br Atom = 0x202 - Button Atom = 0x15c06 - Canvas Atom = 0x4b06 - Caption Atom = 0x1e007 - Center Atom = 0x2df06 - Challenge Atom = 0x23e09 - Charset Atom = 0x2807 - Checked Atom = 0x33f07 - Cite Atom = 0x9704 - Class Atom = 0x3d905 - Code Atom = 0x16f04 - Col Atom = 0x17603 - Colgroup Atom = 0x17608 - Color Atom = 0x18305 - Cols Atom = 0x18804 - Colspan Atom = 0x18807 - Command Atom = 0x19b07 - Content Atom = 0x42c07 - Contenteditable Atom = 0x42c0f - Contextmenu Atom = 0x3480b - Controls Atom = 0x1ae08 - Coords Atom = 0x1ba06 - Crossorigin Atom = 0x1c40b - Data Atom = 0x44304 - Datalist Atom = 0x44308 - Datetime Atom = 0x25b08 - Dd Atom = 0x28802 - Default Atom = 0x5207 - Defer Atom = 0x17105 - Del Atom = 0x4d603 - Desc Atom = 0x4804 - Details Atom = 0x6507 - Dfn Atom = 0x8303 - Dialog Atom = 0x1b06 - Dir Atom = 0x9d03 - Dirname Atom = 0x9d07 - Disabled Atom = 0x10008 - Div Atom = 0x10703 - Dl Atom = 0x13e02 - Download Atom = 0x40908 - Draggable Atom = 0x1a109 - Dropzone Atom = 0x3a208 - Dt Atom = 0x4e402 - Em Atom = 0x7f02 - Embed Atom = 0x7f05 - Enctype Atom = 0x23007 - Face Atom = 0x2dd04 - Fieldset Atom = 0x1d508 - Figcaption Atom = 0x1dd0a - Figure Atom = 0x1f106 - Font Atom = 0x11804 - Footer Atom = 0x5906 - For Atom = 0x1fd03 - ForeignObject Atom = 0x1fd0d - Foreignobject Atom = 0x20a0d - Form Atom = 0x21704 - Formaction Atom = 0x2170a - Formenctype Atom = 0x22c0b - Formmethod Atom = 0x2470a - Formnovalidate Atom = 0x2510e - Formtarget Atom = 0x2660a - Frame Atom = 0x8705 - Frameset Atom = 0x8708 - H1 Atom = 0x13602 - H2 Atom = 0x29602 - H3 Atom = 0x2c502 - H4 Atom = 0x30e02 - H5 Atom = 0x4e602 - H6 Atom = 0x27002 - Head Atom = 0x2fa04 - Header Atom = 0x2fa06 - Headers Atom = 0x2fa07 - Height Atom = 0x27206 - Hgroup Atom = 0x27a06 - Hidden Atom = 0x28606 - High Atom = 0x29304 - Hr Atom = 0x13102 - Href Atom = 0x29804 - Hreflang Atom = 0x29808 - Html Atom = 0x27604 - HttpEquiv Atom = 0x2a00a - I Atom = 0x601 - Icon Atom = 0x42b04 - Id Atom = 0x5102 - Iframe Atom = 0x2b406 - Image Atom = 0x2ba05 - Img Atom = 0x2bf03 - Inert Atom = 0x4c105 - Input Atom = 0x3f605 - Ins Atom = 0x1cd03 - Isindex Atom = 0x2c707 - Ismap Atom = 0x2ce05 - Itemid Atom = 0x9806 - Itemprop Atom = 0x57e08 - Itemref Atom = 0x2d707 - Itemscope Atom = 0x2e509 - Itemtype Atom = 0x2ef08 - Kbd Atom = 0x1903 - Keygen Atom = 0x3906 - Keytype Atom = 0x51207 - Kind Atom = 0xfd04 - Label Atom = 0xba05 - Lang Atom = 0x29c04 - Legend Atom = 0x1a806 - Li Atom = 0x1202 - Link Atom = 0x14804 - List Atom = 0x44704 - Listing Atom = 0x44707 - Loop Atom = 0xbe04 - Low Atom = 0x13f03 - Malignmark Atom = 0x100a - Manifest Atom = 0x5b608 - Map Atom = 0x2d003 - Mark Atom = 0x1604 - Marquee Atom = 0x5f207 - Math Atom = 0x2f704 - Max Atom = 0x30603 - Maxlength Atom = 0x30609 - Media Atom = 0xa205 - Mediagroup Atom = 0xa20a - Menu Atom = 0x34f04 - Meta Atom = 0x45604 - Meter Atom = 0x26105 - Method Atom = 0x24b06 - Mglyph Atom = 0x2c006 - Mi Atom = 0x9b02 - Min Atom = 0x31003 - Mn Atom = 0x25402 - Mo Atom = 0x47a02 - Ms Atom = 0x2e802 - Mtext Atom = 0x31305 - Multiple Atom = 0x32108 - Muted Atom = 0x32905 - Name Atom = 0xa004 - Nav Atom = 0x3e03 - Nobr Atom = 0x7404 - Noembed Atom = 0x7d07 - Noframes Atom = 0x8508 - Noscript Atom = 0x28b08 - Novalidate Atom = 0x2550a - Object Atom = 0x21106 - Ol Atom = 0xcd02 - Onabort Atom = 0x16007 - Onafterprint Atom = 0x1e50c - Onbeforeprint Atom = 0x21f0d - Onbeforeunload Atom = 0x5c90e - Onblur Atom = 0x3e206 - Oncancel Atom = 0xb308 - Oncanplay Atom = 0x12709 - Oncanplaythrough Atom = 0x12710 - Onchange Atom = 0x3b808 - Onclick Atom = 0x2ad07 - Onclose Atom = 0x32e07 - Oncontextmenu Atom = 0x3460d - Oncuechange Atom = 0x3530b - Ondblclick Atom = 0x35e0a - Ondrag Atom = 0x36806 - Ondragend Atom = 0x36809 - Ondragenter Atom = 0x3710b - Ondragleave Atom = 0x37c0b - Ondragover Atom = 0x3870a - Ondragstart Atom = 0x3910b - Ondrop Atom = 0x3a006 - Ondurationchange Atom = 0x3b010 - Onemptied Atom = 0x3a709 - Onended Atom = 0x3c007 - Onerror Atom = 0x3c707 - Onfocus Atom = 0x3ce07 - Onhashchange Atom = 0x3e80c - Oninput Atom = 0x3f407 - Oninvalid Atom = 0x3fb09 - Onkeydown Atom = 0x40409 - Onkeypress Atom = 0x4110a - Onkeyup Atom = 0x42107 - Onload Atom = 0x43b06 - Onloadeddata Atom = 0x43b0c - Onloadedmetadata Atom = 0x44e10 - Onloadstart Atom = 0x4640b - Onmessage Atom = 0x46f09 - Onmousedown Atom = 0x4780b - Onmousemove Atom = 0x4830b - Onmouseout Atom = 0x48e0a - Onmouseover Atom = 0x49b0b - Onmouseup Atom = 0x4a609 - Onmousewheel Atom = 0x4af0c - Onoffline Atom = 0x4bb09 - Ononline Atom = 0x4c608 - Onpagehide Atom = 0x4ce0a - Onpageshow Atom = 0x4d90a - Onpause Atom = 0x4e807 - Onplay Atom = 0x4f206 - Onplaying Atom = 0x4f209 - Onpopstate Atom = 0x4fb0a - Onprogress Atom = 0x5050a - Onratechange Atom = 0x5190c - Onreset Atom = 0x52507 - Onresize Atom = 0x52c08 - Onscroll Atom = 0x53a08 - Onseeked Atom = 0x54208 - Onseeking Atom = 0x54a09 - Onselect Atom = 0x55308 - Onshow Atom = 0x55d06 - Onstalled Atom = 0x56609 - Onstorage Atom = 0x56f09 - Onsubmit Atom = 0x57808 - Onsuspend Atom = 0x58809 - Ontimeupdate Atom = 0x1190c - Onunload Atom = 0x59108 - Onvolumechange Atom = 0x5990e - Onwaiting Atom = 0x5a709 - Open Atom = 0x58404 - Optgroup Atom = 0xc008 - Optimum Atom = 0x5b007 - Option Atom = 0x5c506 - Output Atom = 0x49506 - P Atom = 0xc01 - Param Atom = 0xc05 - Pattern Atom = 0x6e07 - Ping Atom = 0xab04 - Placeholder Atom = 0xc70b - Plaintext Atom = 0xf109 - Poster Atom = 0x17d06 - Pre Atom = 0x27f03 - Preload Atom = 0x27f07 - Progress Atom = 0x50708 - Prompt Atom = 0x5bf06 - Public Atom = 0x42706 - Q Atom = 0x15101 - Radiogroup Atom = 0x30a - Readonly Atom = 0x31908 - Rel Atom = 0x28003 - Required Atom = 0x1f508 - Reversed Atom = 0x5e08 - Rows Atom = 0x7704 - Rowspan Atom = 0x7707 - Rp Atom = 0x1eb02 - Rt Atom = 0x16502 - Ruby Atom = 0xd104 - S Atom = 0x2c01 - Samp Atom = 0x6b04 - Sandbox Atom = 0xe907 - Scope Atom = 0x2e905 - Scoped Atom = 0x2e906 - Script Atom = 0x28d06 - Seamless Atom = 0x33308 - Section Atom = 0x3dd07 - Select Atom = 0x55506 - Selected Atom = 0x55508 - Shape Atom = 0x1b505 - Size Atom = 0x53004 - Sizes Atom = 0x53005 - Small Atom = 0x1bf05 - Source Atom = 0x1cf06 - Spacer Atom = 0x30006 - Span Atom = 0x7a04 - Spellcheck Atom = 0x33a0a - Src Atom = 0x3d403 - Srcdoc Atom = 0x3d406 - Srclang Atom = 0x41a07 - Start Atom = 0x39705 - Step Atom = 0x5bc04 - Strike Atom = 0x50e06 - Strong Atom = 0x53406 - Style Atom = 0x5db05 - Sub Atom = 0x57a03 - Summary Atom = 0x5e007 - Sup Atom = 0x5e703 - Svg Atom = 0x5ea03 - System Atom = 0x5ed06 - Tabindex Atom = 0x45c08 - Table Atom = 0x43605 - Target Atom = 0x26a06 - Tbody Atom = 0x2e05 - Td Atom = 0x4702 - Textarea Atom = 0x31408 - Tfoot Atom = 0x5805 - Th Atom = 0x13002 - Thead Atom = 0x2f905 - Time Atom = 0x11b04 - Title Atom = 0x8e05 - Tr Atom = 0xf902 - Track Atom = 0xf905 - Translate Atom = 0x16609 - Tt Atom = 0x7002 - Type Atom = 0x23304 - Typemustmatch Atom = 0x2330d - U Atom = 0xb01 - Ul Atom = 0x5602 - Usemap Atom = 0x4ec06 - Value Atom = 0x4005 - Var Atom = 0x10903 - Video Atom = 0x2a905 - Wbr Atom = 0x14103 - Width Atom = 0x4e205 - Wrap Atom = 0x56204 - Xmp Atom = 0xef03 -) - -const hash0 = 0xc17da63e - -const maxAtomLen = 16 - -var table = [1 << 9]Atom{ - 0x1: 0x4830b, // onmousemove - 0x2: 0x5a709, // onwaiting - 0x4: 0x5bf06, // prompt - 0x7: 0x5b007, // optimum - 0x8: 0x1604, // mark - 0xa: 0x2d707, // itemref - 0xb: 0x4d90a, // onpageshow - 0xc: 0x55506, // select - 0xd: 0x1a109, // draggable - 0xe: 0x3e03, // nav - 0xf: 0x19b07, // command - 0x11: 0xb01, // u - 0x14: 0x2fa07, // headers - 0x15: 0x44308, // datalist - 0x17: 0x6b04, // samp - 0x1a: 0x40409, // onkeydown - 0x1b: 0x53a08, // onscroll - 0x1c: 0x17603, // col - 0x20: 0x57e08, // itemprop - 0x21: 0x2a00a, // http-equiv - 0x22: 0x5e703, // sup - 0x24: 0x1f508, // required - 0x2b: 0x27f07, // preload - 0x2c: 0x21f0d, // onbeforeprint - 0x2d: 0x3710b, // ondragenter - 0x2e: 0x4e402, // dt - 0x2f: 0x57808, // onsubmit - 0x30: 0x13102, // hr - 0x31: 0x3460d, // oncontextmenu - 0x33: 0x2ba05, // image - 0x34: 0x4e807, // onpause - 0x35: 0x27a06, // hgroup - 0x36: 0xab04, // ping - 0x37: 0x55308, // onselect - 0x3a: 0x10703, // div - 0x40: 0x9b02, // mi - 0x41: 0x33308, // seamless - 0x42: 0x2807, // charset - 0x43: 0x5102, // id - 0x44: 0x4fb0a, // onpopstate - 0x45: 0x4d603, // del - 0x46: 0x5f207, // marquee - 0x47: 0x3309, // accesskey - 0x49: 0x5906, // footer - 0x4a: 0x2d106, // applet - 0x4b: 0x2ce05, // ismap - 0x51: 0x34f04, // menu - 0x52: 0x2f04, // body - 0x55: 0x8708, // frameset - 0x56: 0x52507, // onreset - 0x57: 0x14705, // blink - 0x58: 0x8e05, // title - 0x59: 0x39907, // article - 0x5b: 0x13002, // th - 0x5d: 0x15101, // q - 0x5e: 0x58404, // open - 0x5f: 0x31804, // area - 0x61: 0x43b06, // onload - 0x62: 0x3f605, // input - 0x63: 0x11404, // base - 0x64: 0x18807, // colspan - 0x65: 0x51207, // keytype - 0x66: 0x13e02, // dl - 0x68: 0x1d508, // fieldset - 0x6a: 0x31003, // min - 0x6b: 0x10903, // var - 0x6f: 0x2fa06, // header - 0x70: 0x16502, // rt - 0x71: 0x17608, // colgroup - 0x72: 0x25402, // mn - 0x74: 0x16007, // onabort - 0x75: 0x3906, // keygen - 0x76: 0x4bb09, // onoffline - 0x77: 0x23e09, // challenge - 0x78: 0x2d003, // map - 0x7a: 0x30e02, // h4 - 0x7b: 0x3c707, // onerror - 0x7c: 0x30609, // maxlength - 0x7d: 0x31305, // mtext - 0x7e: 0x5805, // tfoot - 0x7f: 0x11804, // font - 0x80: 0x100a, // malignmark - 0x81: 0x45604, // meta - 0x82: 0x9305, // async - 0x83: 0x2c502, // h3 - 0x84: 0x28802, // dd - 0x85: 0x29804, // href - 0x86: 0xa20a, // mediagroup - 0x87: 0x1ba06, // coords - 0x88: 0x41a07, // srclang - 0x89: 0x35e0a, // ondblclick - 0x8a: 0x4005, // value - 0x8c: 0xb308, // oncancel - 0x8e: 0x33a0a, // spellcheck - 0x8f: 0x8705, // frame - 0x91: 0x14403, // big - 0x94: 0x21b06, // action - 0x95: 0x9d03, // dir - 0x97: 0x31908, // readonly - 0x99: 0x43605, // table - 0x9a: 0x5e007, // summary - 0x9b: 0x14103, // wbr - 0x9c: 0x30a, // radiogroup - 0x9d: 0xa004, // name - 0x9f: 0x5ed06, // system - 0xa1: 0x18305, // color - 0xa2: 0x4b06, // canvas - 0xa3: 0x27604, // html - 0xa5: 0x54a09, // onseeking - 0xac: 0x1b505, // shape - 0xad: 0x28003, // rel - 0xae: 0x12710, // oncanplaythrough - 0xaf: 0x3870a, // ondragover - 0xb1: 0x1fd0d, // foreignObject - 0xb3: 0x7704, // rows - 0xb6: 0x44707, // listing - 0xb7: 0x49506, // output - 0xb9: 0x3480b, // contextmenu - 0xbb: 0x13f03, // low - 0xbc: 0x1eb02, // rp - 0xbd: 0x58809, // onsuspend - 0xbe: 0x15c06, // button - 0xbf: 0x4804, // desc - 0xc1: 0x3dd07, // section - 0xc2: 0x5050a, // onprogress - 0xc3: 0x56f09, // onstorage - 0xc4: 0x2f704, // math - 0xc5: 0x4f206, // onplay - 0xc7: 0x5602, // ul - 0xc8: 0x6e07, // pattern - 0xc9: 0x4af0c, // onmousewheel - 0xca: 0x36809, // ondragend - 0xcb: 0xd104, // ruby - 0xcc: 0xc01, // p - 0xcd: 0x32e07, // onclose - 0xce: 0x26105, // meter - 0xcf: 0x13807, // bgsound - 0xd2: 0x27206, // height - 0xd4: 0x101, // b - 0xd5: 0x2ef08, // itemtype - 0xd8: 0x1e007, // caption - 0xd9: 0x10008, // disabled - 0xdc: 0x5ea03, // svg - 0xdd: 0x1bf05, // small - 0xde: 0x44304, // data - 0xe0: 0x4c608, // ononline - 0xe1: 0x2c006, // mglyph - 0xe3: 0x7f05, // embed - 0xe4: 0xf902, // tr - 0xe5: 0x4640b, // onloadstart - 0xe7: 0x3b010, // ondurationchange - 0xed: 0x12503, // bdo - 0xee: 0x4702, // td - 0xef: 0x4f05, // aside - 0xf0: 0x29602, // h2 - 0xf1: 0x50708, // progress - 0xf2: 0x14c0a, // blockquote - 0xf4: 0xba05, // label - 0xf5: 0x601, // i - 0xf7: 0x7707, // rowspan - 0xfb: 0x4f209, // onplaying - 0xfd: 0x2bf03, // img - 0xfe: 0xc008, // optgroup - 0xff: 0x42c07, // content - 0x101: 0x5190c, // onratechange - 0x103: 0x3e80c, // onhashchange - 0x104: 0x6507, // details - 0x106: 0x40908, // download - 0x109: 0xe907, // sandbox - 0x10b: 0x42c0f, // contenteditable - 0x10d: 0x37c0b, // ondragleave - 0x10e: 0x2106, // accept - 0x10f: 0x55508, // selected - 0x112: 0x2170a, // formaction - 0x113: 0x2df06, // center - 0x115: 0x44e10, // onloadedmetadata - 0x116: 0x14804, // link - 0x117: 0x11b04, // time - 0x118: 0x1c40b, // crossorigin - 0x119: 0x3ce07, // onfocus - 0x11a: 0x56204, // wrap - 0x11b: 0x42b04, // icon - 0x11d: 0x2a905, // video - 0x11e: 0x3d905, // class - 0x121: 0x5990e, // onvolumechange - 0x122: 0x3e206, // onblur - 0x123: 0x2e509, // itemscope - 0x124: 0x5db05, // style - 0x127: 0x42706, // public - 0x129: 0x2510e, // formnovalidate - 0x12a: 0x55d06, // onshow - 0x12c: 0x16609, // translate - 0x12d: 0x9704, // cite - 0x12e: 0x2e802, // ms - 0x12f: 0x1190c, // ontimeupdate - 0x130: 0xfd04, // kind - 0x131: 0x2660a, // formtarget - 0x135: 0x3c007, // onended - 0x136: 0x28606, // hidden - 0x137: 0x2c01, // s - 0x139: 0x2470a, // formmethod - 0x13a: 0x44704, // list - 0x13c: 0x27002, // h6 - 0x13d: 0xcd02, // ol - 0x13e: 0x3530b, // oncuechange - 0x13f: 0x20a0d, // foreignobject - 0x143: 0x5c90e, // onbeforeunload - 0x145: 0x3a709, // onemptied - 0x146: 0x17105, // defer - 0x147: 0xef03, // xmp - 0x148: 0xaf05, // audio - 0x149: 0x1903, // kbd - 0x14c: 0x46f09, // onmessage - 0x14d: 0x5c506, // option - 0x14e: 0x4503, // alt - 0x14f: 0x33f07, // checked - 0x150: 0x10c08, // autoplay - 0x152: 0x202, // br - 0x153: 0x2550a, // novalidate - 0x156: 0x7d07, // noembed - 0x159: 0x2ad07, // onclick - 0x15a: 0x4780b, // onmousedown - 0x15b: 0x3b808, // onchange - 0x15e: 0x3fb09, // oninvalid - 0x15f: 0x2e906, // scoped - 0x160: 0x1ae08, // controls - 0x161: 0x32905, // muted - 0x163: 0x4ec06, // usemap - 0x164: 0x1dd0a, // figcaption - 0x165: 0x36806, // ondrag - 0x166: 0x29304, // high - 0x168: 0x3d403, // src - 0x169: 0x17d06, // poster - 0x16b: 0x18d0e, // annotation-xml - 0x16c: 0x5bc04, // step - 0x16d: 0x4, // abbr - 0x16e: 0x1b06, // dialog - 0x170: 0x1202, // li - 0x172: 0x47a02, // mo - 0x175: 0x1fd03, // for - 0x176: 0x1cd03, // ins - 0x178: 0x53004, // size - 0x17a: 0x5207, // default - 0x17b: 0x1a03, // bdi - 0x17c: 0x4ce0a, // onpagehide - 0x17d: 0x9d07, // dirname - 0x17e: 0x23304, // type - 0x17f: 0x21704, // form - 0x180: 0x4c105, // inert - 0x181: 0x12709, // oncanplay - 0x182: 0x8303, // dfn - 0x183: 0x45c08, // tabindex - 0x186: 0x7f02, // em - 0x187: 0x29c04, // lang - 0x189: 0x3a208, // dropzone - 0x18a: 0x4110a, // onkeypress - 0x18b: 0x25b08, // datetime - 0x18c: 0x18804, // cols - 0x18d: 0x1, // a - 0x18e: 0x43b0c, // onloadeddata - 0x191: 0x15606, // border - 0x192: 0x2e05, // tbody - 0x193: 0x24b06, // method - 0x195: 0xbe04, // loop - 0x196: 0x2b406, // iframe - 0x198: 0x2fa04, // head - 0x19e: 0x5b608, // manifest - 0x19f: 0xe109, // autofocus - 0x1a0: 0x16f04, // code - 0x1a1: 0x53406, // strong - 0x1a2: 0x32108, // multiple - 0x1a3: 0xc05, // param - 0x1a6: 0x23007, // enctype - 0x1a7: 0x2dd04, // face - 0x1a8: 0xf109, // plaintext - 0x1a9: 0x13602, // h1 - 0x1aa: 0x56609, // onstalled - 0x1ad: 0x28d06, // script - 0x1ae: 0x30006, // spacer - 0x1af: 0x52c08, // onresize - 0x1b0: 0x49b0b, // onmouseover - 0x1b1: 0x59108, // onunload - 0x1b2: 0x54208, // onseeked - 0x1b4: 0x2330d, // typemustmatch - 0x1b5: 0x1f106, // figure - 0x1b6: 0x48e0a, // onmouseout - 0x1b7: 0x27f03, // pre - 0x1b8: 0x4e205, // width - 0x1bb: 0x7404, // nobr - 0x1be: 0x7002, // tt - 0x1bf: 0x1105, // align - 0x1c0: 0x3f407, // oninput - 0x1c3: 0x42107, // onkeyup - 0x1c6: 0x1e50c, // onafterprint - 0x1c7: 0x210e, // accept-charset - 0x1c8: 0x9806, // itemid - 0x1cb: 0x50e06, // strike - 0x1cc: 0x57a03, // sub - 0x1cd: 0xf905, // track - 0x1ce: 0x39705, // start - 0x1d0: 0x11408, // basefont - 0x1d6: 0x1cf06, // source - 0x1d7: 0x1a806, // legend - 0x1d8: 0x2f905, // thead - 0x1da: 0x2e905, // scope - 0x1dd: 0x21106, // object - 0x1de: 0xa205, // media - 0x1df: 0x18d0a, // annotation - 0x1e0: 0x22c0b, // formenctype - 0x1e2: 0x28b08, // noscript - 0x1e4: 0x53005, // sizes - 0x1e5: 0xd50c, // autocomplete - 0x1e6: 0x7a04, // span - 0x1e7: 0x8508, // noframes - 0x1e8: 0x26a06, // target - 0x1e9: 0x3a006, // ondrop - 0x1ea: 0x3d406, // srcdoc - 0x1ec: 0x5e08, // reversed - 0x1f0: 0x2c707, // isindex - 0x1f3: 0x29808, // hreflang - 0x1f5: 0x4e602, // h5 - 0x1f6: 0x5d507, // address - 0x1fa: 0x30603, // max - 0x1fb: 0xc70b, // placeholder - 0x1fc: 0x31408, // textarea - 0x1fe: 0x4a609, // onmouseup - 0x1ff: 0x3910b, // ondragstart -} - -const atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" + - "genavaluealtdescanvasidefaultfootereversedetailsampatternobr" + - "owspanoembedfnoframesetitleasyncitemidirnamediagroupingaudio" + - "ncancelabelooptgrouplaceholderubyautocompleteautofocusandbox" + - "mplaintextrackindisabledivarautoplaybasefontimeupdatebdoncan" + - "playthrough1bgsoundlowbrbigblinkblockquoteborderbuttonabortr" + - "anslatecodefercolgroupostercolorcolspannotation-xmlcommandra" + - "ggablegendcontrolshapecoordsmallcrossoriginsourcefieldsetfig" + - "captionafterprintfigurequiredforeignObjectforeignobjectforma" + - "ctionbeforeprintformenctypemustmatchallengeformmethodformnov" + - "alidatetimeterformtargeth6heightmlhgroupreloadhiddenoscripth" + - "igh2hreflanghttp-equivideonclickiframeimageimglyph3isindexis" + - "mappletitemrefacenteritemscopeditemtypematheaderspacermaxlen" + - "gth4minmtextareadonlymultiplemutedoncloseamlesspellcheckedon" + - "contextmenuoncuechangeondblclickondragendondragenterondragle" + - "aveondragoverondragstarticleondropzonemptiedondurationchange" + - "onendedonerroronfocusrcdoclassectionbluronhashchangeoninputo" + - "ninvalidonkeydownloadonkeypressrclangonkeyupublicontentedita" + - "bleonloadeddatalistingonloadedmetadatabindexonloadstartonmes" + - "sageonmousedownonmousemoveonmouseoutputonmouseoveronmouseupo" + - "nmousewheelonofflinertononlineonpagehidelonpageshowidth5onpa" + - "usemaponplayingonpopstateonprogresstrikeytypeonratechangeonr" + - "esetonresizestrongonscrollonseekedonseekingonselectedonshowr" + - "aponstalledonstorageonsubmitempropenonsuspendonunloadonvolum" + - "echangeonwaitingoptimumanifestepromptoptionbeforeunloaddress" + - "tylesummarysupsvgsystemarquee" diff --git a/libgo/go/exp/html/atom/table_test.go b/libgo/go/exp/html/atom/table_test.go deleted file mode 100644 index db016a1c01c..00000000000 --- a/libgo/go/exp/html/atom/table_test.go +++ /dev/null @@ -1,341 +0,0 @@ -// generated by go run gen.go -test; DO NOT EDIT - -package atom - -var testAtomList = []string{ - "a", - "abbr", - "accept", - "accept-charset", - "accesskey", - "action", - "address", - "align", - "alt", - "annotation", - "annotation-xml", - "applet", - "area", - "article", - "aside", - "async", - "audio", - "autocomplete", - "autofocus", - "autoplay", - "b", - "base", - "basefont", - "bdi", - "bdo", - "bgsound", - "big", - "blink", - "blockquote", - "body", - "border", - "br", - "button", - "canvas", - "caption", - "center", - "challenge", - "charset", - "checked", - "cite", - "cite", - "class", - "code", - "col", - "colgroup", - "color", - "cols", - "colspan", - "command", - "command", - "content", - "contenteditable", - "contextmenu", - "controls", - "coords", - "crossorigin", - "data", - "data", - "datalist", - "datetime", - "dd", - "default", - "defer", - "del", - "desc", - "details", - "dfn", - "dialog", - "dir", - "dirname", - "disabled", - "div", - "dl", - "download", - "draggable", - "dropzone", - "dt", - "em", - "embed", - "enctype", - "face", - "fieldset", - "figcaption", - "figure", - "font", - "footer", - "for", - "foreignObject", - "foreignobject", - "form", - "form", - "formaction", - "formenctype", - "formmethod", - "formnovalidate", - "formtarget", - "frame", - "frameset", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "head", - "header", - "headers", - "height", - "hgroup", - "hidden", - "high", - "hr", - "href", - "hreflang", - "html", - "http-equiv", - "i", - "icon", - "id", - "iframe", - "image", - "img", - "inert", - "input", - "ins", - "isindex", - "ismap", - "itemid", - "itemprop", - "itemref", - "itemscope", - "itemtype", - "kbd", - "keygen", - "keytype", - "kind", - "label", - "label", - "lang", - "legend", - "li", - "link", - "list", - "listing", - "loop", - "low", - "malignmark", - "manifest", - "map", - "mark", - "marquee", - "math", - "max", - "maxlength", - "media", - "mediagroup", - "menu", - "meta", - "meter", - "method", - "mglyph", - "mi", - "min", - "mn", - "mo", - "ms", - "mtext", - "multiple", - "muted", - "name", - "nav", - "nobr", - "noembed", - "noframes", - "noscript", - "novalidate", - "object", - "ol", - "onabort", - "onafterprint", - "onbeforeprint", - "onbeforeunload", - "onblur", - "oncancel", - "oncanplay", - "oncanplaythrough", - "onchange", - "onclick", - "onclose", - "oncontextmenu", - "oncuechange", - "ondblclick", - "ondrag", - "ondragend", - "ondragenter", - "ondragleave", - "ondragover", - "ondragstart", - "ondrop", - "ondurationchange", - "onemptied", - "onended", - "onerror", - "onfocus", - "onhashchange", - "oninput", - "oninvalid", - "onkeydown", - "onkeypress", - "onkeyup", - "onload", - "onloadeddata", - "onloadedmetadata", - "onloadstart", - "onmessage", - "onmousedown", - "onmousemove", - "onmouseout", - "onmouseover", - "onmouseup", - "onmousewheel", - "onoffline", - "ononline", - "onpagehide", - "onpageshow", - "onpause", - "onplay", - "onplaying", - "onpopstate", - "onprogress", - "onratechange", - "onreset", - "onresize", - "onscroll", - "onseeked", - "onseeking", - "onselect", - "onshow", - "onstalled", - "onstorage", - "onsubmit", - "onsuspend", - "ontimeupdate", - "onunload", - "onvolumechange", - "onwaiting", - "open", - "optgroup", - "optimum", - "option", - "output", - "p", - "param", - "pattern", - "ping", - "placeholder", - "plaintext", - "poster", - "pre", - "preload", - "progress", - "prompt", - "public", - "q", - "radiogroup", - "readonly", - "rel", - "required", - "reversed", - "rows", - "rowspan", - "rp", - "rt", - "ruby", - "s", - "samp", - "sandbox", - "scope", - "scoped", - "script", - "seamless", - "section", - "select", - "selected", - "shape", - "size", - "sizes", - "small", - "source", - "spacer", - "span", - "span", - "spellcheck", - "src", - "srcdoc", - "srclang", - "start", - "step", - "strike", - "strong", - "style", - "style", - "sub", - "summary", - "sup", - "svg", - "system", - "tabindex", - "table", - "target", - "tbody", - "td", - "textarea", - "tfoot", - "th", - "thead", - "time", - "title", - "title", - "tr", - "track", - "translate", - "tt", - "type", - "typemustmatch", - "u", - "ul", - "usemap", - "value", - "var", - "video", - "wbr", - "width", - "wrap", - "xmp", -} diff --git a/libgo/go/exp/html/const.go b/libgo/go/exp/html/const.go deleted file mode 100644 index d7cc8bb9a99..00000000000 --- a/libgo/go/exp/html/const.go +++ /dev/null @@ -1,100 +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 html - -// Section 12.2.3.2 of the HTML5 specification says "The following elements -// have varying levels of special parsing rules". -// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#the-stack-of-open-elements -var isSpecialElementMap = map[string]bool{ - "address": true, - "applet": true, - "area": true, - "article": true, - "aside": true, - "base": true, - "basefont": true, - "bgsound": true, - "blockquote": true, - "body": true, - "br": true, - "button": true, - "caption": true, - "center": true, - "col": true, - "colgroup": true, - "command": true, - "dd": true, - "details": true, - "dir": true, - "div": true, - "dl": true, - "dt": true, - "embed": true, - "fieldset": true, - "figcaption": true, - "figure": true, - "footer": true, - "form": true, - "frame": true, - "frameset": true, - "h1": true, - "h2": true, - "h3": true, - "h4": true, - "h5": true, - "h6": true, - "head": true, - "header": true, - "hgroup": true, - "hr": true, - "html": true, - "iframe": true, - "img": true, - "input": true, - "isindex": true, - "li": true, - "link": true, - "listing": true, - "marquee": true, - "menu": true, - "meta": true, - "nav": true, - "noembed": true, - "noframes": true, - "noscript": true, - "object": true, - "ol": true, - "p": true, - "param": true, - "plaintext": true, - "pre": true, - "script": true, - "section": true, - "select": true, - "style": true, - "summary": true, - "table": true, - "tbody": true, - "td": true, - "textarea": true, - "tfoot": true, - "th": true, - "thead": true, - "title": true, - "tr": true, - "ul": true, - "wbr": true, - "xmp": true, -} - -func isSpecialElement(element *Node) bool { - switch element.Namespace { - case "", "html": - return isSpecialElementMap[element.Data] - case "svg": - return element.Data == "foreignObject" - } - return false -} diff --git a/libgo/go/exp/html/doc.go b/libgo/go/exp/html/doc.go deleted file mode 100644 index fac0f54e78a..00000000000 --- a/libgo/go/exp/html/doc.go +++ /dev/null @@ -1,106 +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. - -/* -Package html implements an HTML5-compliant tokenizer and parser. - -Tokenization is done by creating a Tokenizer for an io.Reader r. It is the -caller's responsibility to ensure that r provides UTF-8 encoded HTML. - - z := html.NewTokenizer(r) - -Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(), -which parses the next token and returns its type, or an error: - - for { - tt := z.Next() - if tt == html.ErrorToken { - // ... - return ... - } - // Process the current token. - } - -There are two APIs for retrieving the current token. The high-level API is to -call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs -allow optionally calling Raw after Next but before Token, Text, TagName, or -TagAttr. In EBNF notation, the valid call sequence per token is: - - Next {Raw} [ Token | Text | TagName {TagAttr} ] - -Token returns an independent data structure that completely describes a token. -Entities (such as "<") are unescaped, tag names and attribute keys are -lower-cased, and attributes are collected into a []Attribute. For example: - - for { - if z.Next() == html.ErrorToken { - // Returning io.EOF indicates success. - return z.Err() - } - emitToken(z.Token()) - } - -The low-level API performs fewer allocations and copies, but the contents of -the []byte values returned by Text, TagName and TagAttr may change on the next -call to Next. For example, to extract an HTML page's anchor text: - - depth := 0 - for { - tt := z.Next() - switch tt { - case ErrorToken: - return z.Err() - case TextToken: - if depth > 0 { - // emitBytes should copy the []byte it receives, - // if it doesn't process it immediately. - emitBytes(z.Text()) - } - case StartTagToken, EndTagToken: - tn, _ := z.TagName() - if len(tn) == 1 && tn[0] == 'a' { - if tt == StartTagToken { - depth++ - } else { - depth-- - } - } - } - } - -Parsing is done by calling Parse with an io.Reader, which returns the root of -the parse tree (the document element) as a *Node. It is the caller's -responsibility to ensure that the Reader provides UTF-8 encoded HTML. For -example, to process each anchor node in depth-first order: - - doc, err := html.Parse(r) - if err != nil { - // ... - } - var f func(*html.Node) - f = func(n *html.Node) { - if n.Type == html.ElementNode && n.Data == "a" { - // Do something with n... - } - for c := n.FirstChild; c != nil; c = c.NextSibling { - f(c) - } - } - f(doc) - -The relevant specifications include: -http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html and -http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html -*/ -package html - -// The tokenization algorithm implemented by this package is not a line-by-line -// transliteration of the relatively verbose state-machine in the WHATWG -// specification. A more direct approach is used instead, where the program -// counter implies the state, such as whether it is tokenizing a tag or a text -// node. Specification compliance is verified by checking expected and actual -// outputs over a test suite rather than aiming for algorithmic fidelity. - -// TODO(nigeltao): Does a DOM API belong in this package or a separate one? -// TODO(nigeltao): How does parsing interact with a JavaScript engine? diff --git a/libgo/go/exp/html/doctype.go b/libgo/go/exp/html/doctype.go deleted file mode 100644 index c484e5a94fb..00000000000 --- a/libgo/go/exp/html/doctype.go +++ /dev/null @@ -1,156 +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 html - -import ( - "strings" -) - -// parseDoctype parses the data from a DoctypeToken into a name, -// public identifier, and system identifier. It returns a Node whose Type -// is DoctypeNode, whose Data is the name, and which has attributes -// named "system" and "public" for the two identifiers if they were present. -// quirks is whether the document should be parsed in "quirks mode". -func parseDoctype(s string) (n *Node, quirks bool) { - n = &Node{Type: DoctypeNode} - - // Find the name. - space := strings.IndexAny(s, whitespace) - if space == -1 { - space = len(s) - } - n.Data = s[:space] - // The comparison to "html" is case-sensitive. - if n.Data != "html" { - quirks = true - } - n.Data = strings.ToLower(n.Data) - s = strings.TrimLeft(s[space:], whitespace) - - if len(s) < 6 { - // It can't start with "PUBLIC" or "SYSTEM". - // Ignore the rest of the string. - return n, quirks || s != "" - } - - key := strings.ToLower(s[:6]) - s = s[6:] - for key == "public" || key == "system" { - s = strings.TrimLeft(s, whitespace) - if s == "" { - break - } - quote := s[0] - if quote != '"' && quote != '\'' { - break - } - s = s[1:] - q := strings.IndexRune(s, rune(quote)) - var id string - if q == -1 { - id = s - s = "" - } else { - id = s[:q] - s = s[q+1:] - } - n.Attr = append(n.Attr, Attribute{Key: key, Val: id}) - if key == "public" { - key = "system" - } else { - key = "" - } - } - - if key != "" || s != "" { - quirks = true - } else if len(n.Attr) > 0 { - if n.Attr[0].Key == "public" { - public := strings.ToLower(n.Attr[0].Val) - switch public { - case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html": - quirks = true - default: - for _, q := range quirkyIDs { - if strings.HasPrefix(public, q) { - quirks = true - break - } - } - } - // The following two public IDs only cause quirks mode if there is no system ID. - if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") || - strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) { - quirks = true - } - } - if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" && - strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" { - quirks = true - } - } - - return n, quirks -} - -// quirkyIDs is a list of public doctype identifiers that cause a document -// to be interpreted in quirks mode. The identifiers should be in lower case. -var quirkyIDs = []string{ - "+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//", -} diff --git a/libgo/go/exp/html/entity.go b/libgo/go/exp/html/entity.go deleted file mode 100644 index af8a007ed04..00000000000 --- a/libgo/go/exp/html/entity.go +++ /dev/null @@ -1,2253 +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. - -package html - -// All entities that do not end with ';' are 6 or fewer bytes long. -const longestEntityWithoutSemicolon = 6 - -// entity is a map from HTML entity names to their values. The semicolon matters: -// http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html -// lists both "amp" and "amp;" as two separate entries. -// -// Note that the HTML5 list is larger than the HTML4 list at -// http://www.w3.org/TR/html4/sgml/entities.html -var entity = map[string]rune{ - "AElig;": '\U000000C6', - "AMP;": '\U00000026', - "Aacute;": '\U000000C1', - "Abreve;": '\U00000102', - "Acirc;": '\U000000C2', - "Acy;": '\U00000410', - "Afr;": '\U0001D504', - "Agrave;": '\U000000C0', - "Alpha;": '\U00000391', - "Amacr;": '\U00000100', - "And;": '\U00002A53', - "Aogon;": '\U00000104', - "Aopf;": '\U0001D538', - "ApplyFunction;": '\U00002061', - "Aring;": '\U000000C5', - "Ascr;": '\U0001D49C', - "Assign;": '\U00002254', - "Atilde;": '\U000000C3', - "Auml;": '\U000000C4', - "Backslash;": '\U00002216', - "Barv;": '\U00002AE7', - "Barwed;": '\U00002306', - "Bcy;": '\U00000411', - "Because;": '\U00002235', - "Bernoullis;": '\U0000212C', - "Beta;": '\U00000392', - "Bfr;": '\U0001D505', - "Bopf;": '\U0001D539', - "Breve;": '\U000002D8', - "Bscr;": '\U0000212C', - "Bumpeq;": '\U0000224E', - "CHcy;": '\U00000427', - "COPY;": '\U000000A9', - "Cacute;": '\U00000106', - "Cap;": '\U000022D2', - "CapitalDifferentialD;": '\U00002145', - "Cayleys;": '\U0000212D', - "Ccaron;": '\U0000010C', - "Ccedil;": '\U000000C7', - "Ccirc;": '\U00000108', - "Cconint;": '\U00002230', - "Cdot;": '\U0000010A', - "Cedilla;": '\U000000B8', - "CenterDot;": '\U000000B7', - "Cfr;": '\U0000212D', - "Chi;": '\U000003A7', - "CircleDot;": '\U00002299', - "CircleMinus;": '\U00002296', - "CirclePlus;": '\U00002295', - "CircleTimes;": '\U00002297', - "ClockwiseContourIntegral;": '\U00002232', - "CloseCurlyDoubleQuote;": '\U0000201D', - "CloseCurlyQuote;": '\U00002019', - "Colon;": '\U00002237', - "Colone;": '\U00002A74', - "Congruent;": '\U00002261', - "Conint;": '\U0000222F', - "ContourIntegral;": '\U0000222E', - "Copf;": '\U00002102', - "Coproduct;": '\U00002210', - "CounterClockwiseContourIntegral;": '\U00002233', - "Cross;": '\U00002A2F', - "Cscr;": '\U0001D49E', - "Cup;": '\U000022D3', - "CupCap;": '\U0000224D', - "DD;": '\U00002145', - "DDotrahd;": '\U00002911', - "DJcy;": '\U00000402', - "DScy;": '\U00000405', - "DZcy;": '\U0000040F', - "Dagger;": '\U00002021', - "Darr;": '\U000021A1', - "Dashv;": '\U00002AE4', - "Dcaron;": '\U0000010E', - "Dcy;": '\U00000414', - "Del;": '\U00002207', - "Delta;": '\U00000394', - "Dfr;": '\U0001D507', - "DiacriticalAcute;": '\U000000B4', - "DiacriticalDot;": '\U000002D9', - "DiacriticalDoubleAcute;": '\U000002DD', - "DiacriticalGrave;": '\U00000060', - "DiacriticalTilde;": '\U000002DC', - "Diamond;": '\U000022C4', - "DifferentialD;": '\U00002146', - "Dopf;": '\U0001D53B', - "Dot;": '\U000000A8', - "DotDot;": '\U000020DC', - "DotEqual;": '\U00002250', - "DoubleContourIntegral;": '\U0000222F', - "DoubleDot;": '\U000000A8', - "DoubleDownArrow;": '\U000021D3', - "DoubleLeftArrow;": '\U000021D0', - "DoubleLeftRightArrow;": '\U000021D4', - "DoubleLeftTee;": '\U00002AE4', - "DoubleLongLeftArrow;": '\U000027F8', - "DoubleLongLeftRightArrow;": '\U000027FA', - "DoubleLongRightArrow;": '\U000027F9', - "DoubleRightArrow;": '\U000021D2', - "DoubleRightTee;": '\U000022A8', - "DoubleUpArrow;": '\U000021D1', - "DoubleUpDownArrow;": '\U000021D5', - "DoubleVerticalBar;": '\U00002225', - "DownArrow;": '\U00002193', - "DownArrowBar;": '\U00002913', - "DownArrowUpArrow;": '\U000021F5', - "DownBreve;": '\U00000311', - "DownLeftRightVector;": '\U00002950', - "DownLeftTeeVector;": '\U0000295E', - "DownLeftVector;": '\U000021BD', - "DownLeftVectorBar;": '\U00002956', - "DownRightTeeVector;": '\U0000295F', - "DownRightVector;": '\U000021C1', - "DownRightVectorBar;": '\U00002957', - "DownTee;": '\U000022A4', - "DownTeeArrow;": '\U000021A7', - "Downarrow;": '\U000021D3', - "Dscr;": '\U0001D49F', - "Dstrok;": '\U00000110', - "ENG;": '\U0000014A', - "ETH;": '\U000000D0', - "Eacute;": '\U000000C9', - "Ecaron;": '\U0000011A', - "Ecirc;": '\U000000CA', - "Ecy;": '\U0000042D', - "Edot;": '\U00000116', - "Efr;": '\U0001D508', - "Egrave;": '\U000000C8', - "Element;": '\U00002208', - "Emacr;": '\U00000112', - "EmptySmallSquare;": '\U000025FB', - "EmptyVerySmallSquare;": '\U000025AB', - "Eogon;": '\U00000118', - "Eopf;": '\U0001D53C', - "Epsilon;": '\U00000395', - "Equal;": '\U00002A75', - "EqualTilde;": '\U00002242', - "Equilibrium;": '\U000021CC', - "Escr;": '\U00002130', - "Esim;": '\U00002A73', - "Eta;": '\U00000397', - "Euml;": '\U000000CB', - "Exists;": '\U00002203', - "ExponentialE;": '\U00002147', - "Fcy;": '\U00000424', - "Ffr;": '\U0001D509', - "FilledSmallSquare;": '\U000025FC', - "FilledVerySmallSquare;": '\U000025AA', - "Fopf;": '\U0001D53D', - "ForAll;": '\U00002200', - "Fouriertrf;": '\U00002131', - "Fscr;": '\U00002131', - "GJcy;": '\U00000403', - "GT;": '\U0000003E', - "Gamma;": '\U00000393', - "Gammad;": '\U000003DC', - "Gbreve;": '\U0000011E', - "Gcedil;": '\U00000122', - "Gcirc;": '\U0000011C', - "Gcy;": '\U00000413', - "Gdot;": '\U00000120', - "Gfr;": '\U0001D50A', - "Gg;": '\U000022D9', - "Gopf;": '\U0001D53E', - "GreaterEqual;": '\U00002265', - "GreaterEqualLess;": '\U000022DB', - "GreaterFullEqual;": '\U00002267', - "GreaterGreater;": '\U00002AA2', - "GreaterLess;": '\U00002277', - "GreaterSlantEqual;": '\U00002A7E', - "GreaterTilde;": '\U00002273', - "Gscr;": '\U0001D4A2', - "Gt;": '\U0000226B', - "HARDcy;": '\U0000042A', - "Hacek;": '\U000002C7', - "Hat;": '\U0000005E', - "Hcirc;": '\U00000124', - "Hfr;": '\U0000210C', - "HilbertSpace;": '\U0000210B', - "Hopf;": '\U0000210D', - "HorizontalLine;": '\U00002500', - "Hscr;": '\U0000210B', - "Hstrok;": '\U00000126', - "HumpDownHump;": '\U0000224E', - "HumpEqual;": '\U0000224F', - "IEcy;": '\U00000415', - "IJlig;": '\U00000132', - "IOcy;": '\U00000401', - "Iacute;": '\U000000CD', - "Icirc;": '\U000000CE', - "Icy;": '\U00000418', - "Idot;": '\U00000130', - "Ifr;": '\U00002111', - "Igrave;": '\U000000CC', - "Im;": '\U00002111', - "Imacr;": '\U0000012A', - "ImaginaryI;": '\U00002148', - "Implies;": '\U000021D2', - "Int;": '\U0000222C', - "Integral;": '\U0000222B', - "Intersection;": '\U000022C2', - "InvisibleComma;": '\U00002063', - "InvisibleTimes;": '\U00002062', - "Iogon;": '\U0000012E', - "Iopf;": '\U0001D540', - "Iota;": '\U00000399', - "Iscr;": '\U00002110', - "Itilde;": '\U00000128', - "Iukcy;": '\U00000406', - "Iuml;": '\U000000CF', - "Jcirc;": '\U00000134', - "Jcy;": '\U00000419', - "Jfr;": '\U0001D50D', - "Jopf;": '\U0001D541', - "Jscr;": '\U0001D4A5', - "Jsercy;": '\U00000408', - "Jukcy;": '\U00000404', - "KHcy;": '\U00000425', - "KJcy;": '\U0000040C', - "Kappa;": '\U0000039A', - "Kcedil;": '\U00000136', - "Kcy;": '\U0000041A', - "Kfr;": '\U0001D50E', - "Kopf;": '\U0001D542', - "Kscr;": '\U0001D4A6', - "LJcy;": '\U00000409', - "LT;": '\U0000003C', - "Lacute;": '\U00000139', - "Lambda;": '\U0000039B', - "Lang;": '\U000027EA', - "Laplacetrf;": '\U00002112', - "Larr;": '\U0000219E', - "Lcaron;": '\U0000013D', - "Lcedil;": '\U0000013B', - "Lcy;": '\U0000041B', - "LeftAngleBracket;": '\U000027E8', - "LeftArrow;": '\U00002190', - "LeftArrowBar;": '\U000021E4', - "LeftArrowRightArrow;": '\U000021C6', - "LeftCeiling;": '\U00002308', - "LeftDoubleBracket;": '\U000027E6', - "LeftDownTeeVector;": '\U00002961', - "LeftDownVector;": '\U000021C3', - "LeftDownVectorBar;": '\U00002959', - "LeftFloor;": '\U0000230A', - "LeftRightArrow;": '\U00002194', - "LeftRightVector;": '\U0000294E', - "LeftTee;": '\U000022A3', - "LeftTeeArrow;": '\U000021A4', - "LeftTeeVector;": '\U0000295A', - "LeftTriangle;": '\U000022B2', - "LeftTriangleBar;": '\U000029CF', - "LeftTriangleEqual;": '\U000022B4', - "LeftUpDownVector;": '\U00002951', - "LeftUpTeeVector;": '\U00002960', - "LeftUpVector;": '\U000021BF', - "LeftUpVectorBar;": '\U00002958', - "LeftVector;": '\U000021BC', - "LeftVectorBar;": '\U00002952', - "Leftarrow;": '\U000021D0', - "Leftrightarrow;": '\U000021D4', - "LessEqualGreater;": '\U000022DA', - "LessFullEqual;": '\U00002266', - "LessGreater;": '\U00002276', - "LessLess;": '\U00002AA1', - "LessSlantEqual;": '\U00002A7D', - "LessTilde;": '\U00002272', - "Lfr;": '\U0001D50F', - "Ll;": '\U000022D8', - "Lleftarrow;": '\U000021DA', - "Lmidot;": '\U0000013F', - "LongLeftArrow;": '\U000027F5', - "LongLeftRightArrow;": '\U000027F7', - "LongRightArrow;": '\U000027F6', - "Longleftarrow;": '\U000027F8', - "Longleftrightarrow;": '\U000027FA', - "Longrightarrow;": '\U000027F9', - "Lopf;": '\U0001D543', - "LowerLeftArrow;": '\U00002199', - "LowerRightArrow;": '\U00002198', - "Lscr;": '\U00002112', - "Lsh;": '\U000021B0', - "Lstrok;": '\U00000141', - "Lt;": '\U0000226A', - "Map;": '\U00002905', - "Mcy;": '\U0000041C', - "MediumSpace;": '\U0000205F', - "Mellintrf;": '\U00002133', - "Mfr;": '\U0001D510', - "MinusPlus;": '\U00002213', - "Mopf;": '\U0001D544', - "Mscr;": '\U00002133', - "Mu;": '\U0000039C', - "NJcy;": '\U0000040A', - "Nacute;": '\U00000143', - "Ncaron;": '\U00000147', - "Ncedil;": '\U00000145', - "Ncy;": '\U0000041D', - "NegativeMediumSpace;": '\U0000200B', - "NegativeThickSpace;": '\U0000200B', - "NegativeThinSpace;": '\U0000200B', - "NegativeVeryThinSpace;": '\U0000200B', - "NestedGreaterGreater;": '\U0000226B', - "NestedLessLess;": '\U0000226A', - "NewLine;": '\U0000000A', - "Nfr;": '\U0001D511', - "NoBreak;": '\U00002060', - "NonBreakingSpace;": '\U000000A0', - "Nopf;": '\U00002115', - "Not;": '\U00002AEC', - "NotCongruent;": '\U00002262', - "NotCupCap;": '\U0000226D', - "NotDoubleVerticalBar;": '\U00002226', - "NotElement;": '\U00002209', - "NotEqual;": '\U00002260', - "NotExists;": '\U00002204', - "NotGreater;": '\U0000226F', - "NotGreaterEqual;": '\U00002271', - "NotGreaterLess;": '\U00002279', - "NotGreaterTilde;": '\U00002275', - "NotLeftTriangle;": '\U000022EA', - "NotLeftTriangleEqual;": '\U000022EC', - "NotLess;": '\U0000226E', - "NotLessEqual;": '\U00002270', - "NotLessGreater;": '\U00002278', - "NotLessTilde;": '\U00002274', - "NotPrecedes;": '\U00002280', - "NotPrecedesSlantEqual;": '\U000022E0', - "NotReverseElement;": '\U0000220C', - "NotRightTriangle;": '\U000022EB', - "NotRightTriangleEqual;": '\U000022ED', - "NotSquareSubsetEqual;": '\U000022E2', - "NotSquareSupersetEqual;": '\U000022E3', - "NotSubsetEqual;": '\U00002288', - "NotSucceeds;": '\U00002281', - "NotSucceedsSlantEqual;": '\U000022E1', - "NotSupersetEqual;": '\U00002289', - "NotTilde;": '\U00002241', - "NotTildeEqual;": '\U00002244', - "NotTildeFullEqual;": '\U00002247', - "NotTildeTilde;": '\U00002249', - "NotVerticalBar;": '\U00002224', - "Nscr;": '\U0001D4A9', - "Ntilde;": '\U000000D1', - "Nu;": '\U0000039D', - "OElig;": '\U00000152', - "Oacute;": '\U000000D3', - "Ocirc;": '\U000000D4', - "Ocy;": '\U0000041E', - "Odblac;": '\U00000150', - "Ofr;": '\U0001D512', - "Ograve;": '\U000000D2', - "Omacr;": '\U0000014C', - "Omega;": '\U000003A9', - "Omicron;": '\U0000039F', - "Oopf;": '\U0001D546', - "OpenCurlyDoubleQuote;": '\U0000201C', - "OpenCurlyQuote;": '\U00002018', - "Or;": '\U00002A54', - "Oscr;": '\U0001D4AA', - "Oslash;": '\U000000D8', - "Otilde;": '\U000000D5', - "Otimes;": '\U00002A37', - "Ouml;": '\U000000D6', - "OverBar;": '\U0000203E', - "OverBrace;": '\U000023DE', - "OverBracket;": '\U000023B4', - "OverParenthesis;": '\U000023DC', - "PartialD;": '\U00002202', - "Pcy;": '\U0000041F', - "Pfr;": '\U0001D513', - "Phi;": '\U000003A6', - "Pi;": '\U000003A0', - "PlusMinus;": '\U000000B1', - "Poincareplane;": '\U0000210C', - "Popf;": '\U00002119', - "Pr;": '\U00002ABB', - "Precedes;": '\U0000227A', - "PrecedesEqual;": '\U00002AAF', - "PrecedesSlantEqual;": '\U0000227C', - "PrecedesTilde;": '\U0000227E', - "Prime;": '\U00002033', - "Product;": '\U0000220F', - "Proportion;": '\U00002237', - "Proportional;": '\U0000221D', - "Pscr;": '\U0001D4AB', - "Psi;": '\U000003A8', - "QUOT;": '\U00000022', - "Qfr;": '\U0001D514', - "Qopf;": '\U0000211A', - "Qscr;": '\U0001D4AC', - "RBarr;": '\U00002910', - "REG;": '\U000000AE', - "Racute;": '\U00000154', - "Rang;": '\U000027EB', - "Rarr;": '\U000021A0', - "Rarrtl;": '\U00002916', - "Rcaron;": '\U00000158', - "Rcedil;": '\U00000156', - "Rcy;": '\U00000420', - "Re;": '\U0000211C', - "ReverseElement;": '\U0000220B', - "ReverseEquilibrium;": '\U000021CB', - "ReverseUpEquilibrium;": '\U0000296F', - "Rfr;": '\U0000211C', - "Rho;": '\U000003A1', - "RightAngleBracket;": '\U000027E9', - "RightArrow;": '\U00002192', - "RightArrowBar;": '\U000021E5', - "RightArrowLeftArrow;": '\U000021C4', - "RightCeiling;": '\U00002309', - "RightDoubleBracket;": '\U000027E7', - "RightDownTeeVector;": '\U0000295D', - "RightDownVector;": '\U000021C2', - "RightDownVectorBar;": '\U00002955', - "RightFloor;": '\U0000230B', - "RightTee;": '\U000022A2', - "RightTeeArrow;": '\U000021A6', - "RightTeeVector;": '\U0000295B', - "RightTriangle;": '\U000022B3', - "RightTriangleBar;": '\U000029D0', - "RightTriangleEqual;": '\U000022B5', - "RightUpDownVector;": '\U0000294F', - "RightUpTeeVector;": '\U0000295C', - "RightUpVector;": '\U000021BE', - "RightUpVectorBar;": '\U00002954', - "RightVector;": '\U000021C0', - "RightVectorBar;": '\U00002953', - "Rightarrow;": '\U000021D2', - "Ropf;": '\U0000211D', - "RoundImplies;": '\U00002970', - "Rrightarrow;": '\U000021DB', - "Rscr;": '\U0000211B', - "Rsh;": '\U000021B1', - "RuleDelayed;": '\U000029F4', - "SHCHcy;": '\U00000429', - "SHcy;": '\U00000428', - "SOFTcy;": '\U0000042C', - "Sacute;": '\U0000015A', - "Sc;": '\U00002ABC', - "Scaron;": '\U00000160', - "Scedil;": '\U0000015E', - "Scirc;": '\U0000015C', - "Scy;": '\U00000421', - "Sfr;": '\U0001D516', - "ShortDownArrow;": '\U00002193', - "ShortLeftArrow;": '\U00002190', - "ShortRightArrow;": '\U00002192', - "ShortUpArrow;": '\U00002191', - "Sigma;": '\U000003A3', - "SmallCircle;": '\U00002218', - "Sopf;": '\U0001D54A', - "Sqrt;": '\U0000221A', - "Square;": '\U000025A1', - "SquareIntersection;": '\U00002293', - "SquareSubset;": '\U0000228F', - "SquareSubsetEqual;": '\U00002291', - "SquareSuperset;": '\U00002290', - "SquareSupersetEqual;": '\U00002292', - "SquareUnion;": '\U00002294', - "Sscr;": '\U0001D4AE', - "Star;": '\U000022C6', - "Sub;": '\U000022D0', - "Subset;": '\U000022D0', - "SubsetEqual;": '\U00002286', - "Succeeds;": '\U0000227B', - "SucceedsEqual;": '\U00002AB0', - "SucceedsSlantEqual;": '\U0000227D', - "SucceedsTilde;": '\U0000227F', - "SuchThat;": '\U0000220B', - "Sum;": '\U00002211', - "Sup;": '\U000022D1', - "Superset;": '\U00002283', - "SupersetEqual;": '\U00002287', - "Supset;": '\U000022D1', - "THORN;": '\U000000DE', - "TRADE;": '\U00002122', - "TSHcy;": '\U0000040B', - "TScy;": '\U00000426', - "Tab;": '\U00000009', - "Tau;": '\U000003A4', - "Tcaron;": '\U00000164', - "Tcedil;": '\U00000162', - "Tcy;": '\U00000422', - "Tfr;": '\U0001D517', - "Therefore;": '\U00002234', - "Theta;": '\U00000398', - "ThinSpace;": '\U00002009', - "Tilde;": '\U0000223C', - "TildeEqual;": '\U00002243', - "TildeFullEqual;": '\U00002245', - "TildeTilde;": '\U00002248', - "Topf;": '\U0001D54B', - "TripleDot;": '\U000020DB', - "Tscr;": '\U0001D4AF', - "Tstrok;": '\U00000166', - "Uacute;": '\U000000DA', - "Uarr;": '\U0000219F', - "Uarrocir;": '\U00002949', - "Ubrcy;": '\U0000040E', - "Ubreve;": '\U0000016C', - "Ucirc;": '\U000000DB', - "Ucy;": '\U00000423', - "Udblac;": '\U00000170', - "Ufr;": '\U0001D518', - "Ugrave;": '\U000000D9', - "Umacr;": '\U0000016A', - "UnderBar;": '\U0000005F', - "UnderBrace;": '\U000023DF', - "UnderBracket;": '\U000023B5', - "UnderParenthesis;": '\U000023DD', - "Union;": '\U000022C3', - "UnionPlus;": '\U0000228E', - "Uogon;": '\U00000172', - "Uopf;": '\U0001D54C', - "UpArrow;": '\U00002191', - "UpArrowBar;": '\U00002912', - "UpArrowDownArrow;": '\U000021C5', - "UpDownArrow;": '\U00002195', - "UpEquilibrium;": '\U0000296E', - "UpTee;": '\U000022A5', - "UpTeeArrow;": '\U000021A5', - "Uparrow;": '\U000021D1', - "Updownarrow;": '\U000021D5', - "UpperLeftArrow;": '\U00002196', - "UpperRightArrow;": '\U00002197', - "Upsi;": '\U000003D2', - "Upsilon;": '\U000003A5', - "Uring;": '\U0000016E', - "Uscr;": '\U0001D4B0', - "Utilde;": '\U00000168', - "Uuml;": '\U000000DC', - "VDash;": '\U000022AB', - "Vbar;": '\U00002AEB', - "Vcy;": '\U00000412', - "Vdash;": '\U000022A9', - "Vdashl;": '\U00002AE6', - "Vee;": '\U000022C1', - "Verbar;": '\U00002016', - "Vert;": '\U00002016', - "VerticalBar;": '\U00002223', - "VerticalLine;": '\U0000007C', - "VerticalSeparator;": '\U00002758', - "VerticalTilde;": '\U00002240', - "VeryThinSpace;": '\U0000200A', - "Vfr;": '\U0001D519', - "Vopf;": '\U0001D54D', - "Vscr;": '\U0001D4B1', - "Vvdash;": '\U000022AA', - "Wcirc;": '\U00000174', - "Wedge;": '\U000022C0', - "Wfr;": '\U0001D51A', - "Wopf;": '\U0001D54E', - "Wscr;": '\U0001D4B2', - "Xfr;": '\U0001D51B', - "Xi;": '\U0000039E', - "Xopf;": '\U0001D54F', - "Xscr;": '\U0001D4B3', - "YAcy;": '\U0000042F', - "YIcy;": '\U00000407', - "YUcy;": '\U0000042E', - "Yacute;": '\U000000DD', - "Ycirc;": '\U00000176', - "Ycy;": '\U0000042B', - "Yfr;": '\U0001D51C', - "Yopf;": '\U0001D550', - "Yscr;": '\U0001D4B4', - "Yuml;": '\U00000178', - "ZHcy;": '\U00000416', - "Zacute;": '\U00000179', - "Zcaron;": '\U0000017D', - "Zcy;": '\U00000417', - "Zdot;": '\U0000017B', - "ZeroWidthSpace;": '\U0000200B', - "Zeta;": '\U00000396', - "Zfr;": '\U00002128', - "Zopf;": '\U00002124', - "Zscr;": '\U0001D4B5', - "aacute;": '\U000000E1', - "abreve;": '\U00000103', - "ac;": '\U0000223E', - "acd;": '\U0000223F', - "acirc;": '\U000000E2', - "acute;": '\U000000B4', - "acy;": '\U00000430', - "aelig;": '\U000000E6', - "af;": '\U00002061', - "afr;": '\U0001D51E', - "agrave;": '\U000000E0', - "alefsym;": '\U00002135', - "aleph;": '\U00002135', - "alpha;": '\U000003B1', - "amacr;": '\U00000101', - "amalg;": '\U00002A3F', - "amp;": '\U00000026', - "and;": '\U00002227', - "andand;": '\U00002A55', - "andd;": '\U00002A5C', - "andslope;": '\U00002A58', - "andv;": '\U00002A5A', - "ang;": '\U00002220', - "ange;": '\U000029A4', - "angle;": '\U00002220', - "angmsd;": '\U00002221', - "angmsdaa;": '\U000029A8', - "angmsdab;": '\U000029A9', - "angmsdac;": '\U000029AA', - "angmsdad;": '\U000029AB', - "angmsdae;": '\U000029AC', - "angmsdaf;": '\U000029AD', - "angmsdag;": '\U000029AE', - "angmsdah;": '\U000029AF', - "angrt;": '\U0000221F', - "angrtvb;": '\U000022BE', - "angrtvbd;": '\U0000299D', - "angsph;": '\U00002222', - "angst;": '\U000000C5', - "angzarr;": '\U0000237C', - "aogon;": '\U00000105', - "aopf;": '\U0001D552', - "ap;": '\U00002248', - "apE;": '\U00002A70', - "apacir;": '\U00002A6F', - "ape;": '\U0000224A', - "apid;": '\U0000224B', - "apos;": '\U00000027', - "approx;": '\U00002248', - "approxeq;": '\U0000224A', - "aring;": '\U000000E5', - "ascr;": '\U0001D4B6', - "ast;": '\U0000002A', - "asymp;": '\U00002248', - "asympeq;": '\U0000224D', - "atilde;": '\U000000E3', - "auml;": '\U000000E4', - "awconint;": '\U00002233', - "awint;": '\U00002A11', - "bNot;": '\U00002AED', - "backcong;": '\U0000224C', - "backepsilon;": '\U000003F6', - "backprime;": '\U00002035', - "backsim;": '\U0000223D', - "backsimeq;": '\U000022CD', - "barvee;": '\U000022BD', - "barwed;": '\U00002305', - "barwedge;": '\U00002305', - "bbrk;": '\U000023B5', - "bbrktbrk;": '\U000023B6', - "bcong;": '\U0000224C', - "bcy;": '\U00000431', - "bdquo;": '\U0000201E', - "becaus;": '\U00002235', - "because;": '\U00002235', - "bemptyv;": '\U000029B0', - "bepsi;": '\U000003F6', - "bernou;": '\U0000212C', - "beta;": '\U000003B2', - "beth;": '\U00002136', - "between;": '\U0000226C', - "bfr;": '\U0001D51F', - "bigcap;": '\U000022C2', - "bigcirc;": '\U000025EF', - "bigcup;": '\U000022C3', - "bigodot;": '\U00002A00', - "bigoplus;": '\U00002A01', - "bigotimes;": '\U00002A02', - "bigsqcup;": '\U00002A06', - "bigstar;": '\U00002605', - "bigtriangledown;": '\U000025BD', - "bigtriangleup;": '\U000025B3', - "biguplus;": '\U00002A04', - "bigvee;": '\U000022C1', - "bigwedge;": '\U000022C0', - "bkarow;": '\U0000290D', - "blacklozenge;": '\U000029EB', - "blacksquare;": '\U000025AA', - "blacktriangle;": '\U000025B4', - "blacktriangledown;": '\U000025BE', - "blacktriangleleft;": '\U000025C2', - "blacktriangleright;": '\U000025B8', - "blank;": '\U00002423', - "blk12;": '\U00002592', - "blk14;": '\U00002591', - "blk34;": '\U00002593', - "block;": '\U00002588', - "bnot;": '\U00002310', - "bopf;": '\U0001D553', - "bot;": '\U000022A5', - "bottom;": '\U000022A5', - "bowtie;": '\U000022C8', - "boxDL;": '\U00002557', - "boxDR;": '\U00002554', - "boxDl;": '\U00002556', - "boxDr;": '\U00002553', - "boxH;": '\U00002550', - "boxHD;": '\U00002566', - "boxHU;": '\U00002569', - "boxHd;": '\U00002564', - "boxHu;": '\U00002567', - "boxUL;": '\U0000255D', - "boxUR;": '\U0000255A', - "boxUl;": '\U0000255C', - "boxUr;": '\U00002559', - "boxV;": '\U00002551', - "boxVH;": '\U0000256C', - "boxVL;": '\U00002563', - "boxVR;": '\U00002560', - "boxVh;": '\U0000256B', - "boxVl;": '\U00002562', - "boxVr;": '\U0000255F', - "boxbox;": '\U000029C9', - "boxdL;": '\U00002555', - "boxdR;": '\U00002552', - "boxdl;": '\U00002510', - "boxdr;": '\U0000250C', - "boxh;": '\U00002500', - "boxhD;": '\U00002565', - "boxhU;": '\U00002568', - "boxhd;": '\U0000252C', - "boxhu;": '\U00002534', - "boxminus;": '\U0000229F', - "boxplus;": '\U0000229E', - "boxtimes;": '\U000022A0', - "boxuL;": '\U0000255B', - "boxuR;": '\U00002558', - "boxul;": '\U00002518', - "boxur;": '\U00002514', - "boxv;": '\U00002502', - "boxvH;": '\U0000256A', - "boxvL;": '\U00002561', - "boxvR;": '\U0000255E', - "boxvh;": '\U0000253C', - "boxvl;": '\U00002524', - "boxvr;": '\U0000251C', - "bprime;": '\U00002035', - "breve;": '\U000002D8', - "brvbar;": '\U000000A6', - "bscr;": '\U0001D4B7', - "bsemi;": '\U0000204F', - "bsim;": '\U0000223D', - "bsime;": '\U000022CD', - "bsol;": '\U0000005C', - "bsolb;": '\U000029C5', - "bsolhsub;": '\U000027C8', - "bull;": '\U00002022', - "bullet;": '\U00002022', - "bump;": '\U0000224E', - "bumpE;": '\U00002AAE', - "bumpe;": '\U0000224F', - "bumpeq;": '\U0000224F', - "cacute;": '\U00000107', - "cap;": '\U00002229', - "capand;": '\U00002A44', - "capbrcup;": '\U00002A49', - "capcap;": '\U00002A4B', - "capcup;": '\U00002A47', - "capdot;": '\U00002A40', - "caret;": '\U00002041', - "caron;": '\U000002C7', - "ccaps;": '\U00002A4D', - "ccaron;": '\U0000010D', - "ccedil;": '\U000000E7', - "ccirc;": '\U00000109', - "ccups;": '\U00002A4C', - "ccupssm;": '\U00002A50', - "cdot;": '\U0000010B', - "cedil;": '\U000000B8', - "cemptyv;": '\U000029B2', - "cent;": '\U000000A2', - "centerdot;": '\U000000B7', - "cfr;": '\U0001D520', - "chcy;": '\U00000447', - "check;": '\U00002713', - "checkmark;": '\U00002713', - "chi;": '\U000003C7', - "cir;": '\U000025CB', - "cirE;": '\U000029C3', - "circ;": '\U000002C6', - "circeq;": '\U00002257', - "circlearrowleft;": '\U000021BA', - "circlearrowright;": '\U000021BB', - "circledR;": '\U000000AE', - "circledS;": '\U000024C8', - "circledast;": '\U0000229B', - "circledcirc;": '\U0000229A', - "circleddash;": '\U0000229D', - "cire;": '\U00002257', - "cirfnint;": '\U00002A10', - "cirmid;": '\U00002AEF', - "cirscir;": '\U000029C2', - "clubs;": '\U00002663', - "clubsuit;": '\U00002663', - "colon;": '\U0000003A', - "colone;": '\U00002254', - "coloneq;": '\U00002254', - "comma;": '\U0000002C', - "commat;": '\U00000040', - "comp;": '\U00002201', - "compfn;": '\U00002218', - "complement;": '\U00002201', - "complexes;": '\U00002102', - "cong;": '\U00002245', - "congdot;": '\U00002A6D', - "conint;": '\U0000222E', - "copf;": '\U0001D554', - "coprod;": '\U00002210', - "copy;": '\U000000A9', - "copysr;": '\U00002117', - "crarr;": '\U000021B5', - "cross;": '\U00002717', - "cscr;": '\U0001D4B8', - "csub;": '\U00002ACF', - "csube;": '\U00002AD1', - "csup;": '\U00002AD0', - "csupe;": '\U00002AD2', - "ctdot;": '\U000022EF', - "cudarrl;": '\U00002938', - "cudarrr;": '\U00002935', - "cuepr;": '\U000022DE', - "cuesc;": '\U000022DF', - "cularr;": '\U000021B6', - "cularrp;": '\U0000293D', - "cup;": '\U0000222A', - "cupbrcap;": '\U00002A48', - "cupcap;": '\U00002A46', - "cupcup;": '\U00002A4A', - "cupdot;": '\U0000228D', - "cupor;": '\U00002A45', - "curarr;": '\U000021B7', - "curarrm;": '\U0000293C', - "curlyeqprec;": '\U000022DE', - "curlyeqsucc;": '\U000022DF', - "curlyvee;": '\U000022CE', - "curlywedge;": '\U000022CF', - "curren;": '\U000000A4', - "curvearrowleft;": '\U000021B6', - "curvearrowright;": '\U000021B7', - "cuvee;": '\U000022CE', - "cuwed;": '\U000022CF', - "cwconint;": '\U00002232', - "cwint;": '\U00002231', - "cylcty;": '\U0000232D', - "dArr;": '\U000021D3', - "dHar;": '\U00002965', - "dagger;": '\U00002020', - "daleth;": '\U00002138', - "darr;": '\U00002193', - "dash;": '\U00002010', - "dashv;": '\U000022A3', - "dbkarow;": '\U0000290F', - "dblac;": '\U000002DD', - "dcaron;": '\U0000010F', - "dcy;": '\U00000434', - "dd;": '\U00002146', - "ddagger;": '\U00002021', - "ddarr;": '\U000021CA', - "ddotseq;": '\U00002A77', - "deg;": '\U000000B0', - "delta;": '\U000003B4', - "demptyv;": '\U000029B1', - "dfisht;": '\U0000297F', - "dfr;": '\U0001D521', - "dharl;": '\U000021C3', - "dharr;": '\U000021C2', - "diam;": '\U000022C4', - "diamond;": '\U000022C4', - "diamondsuit;": '\U00002666', - "diams;": '\U00002666', - "die;": '\U000000A8', - "digamma;": '\U000003DD', - "disin;": '\U000022F2', - "div;": '\U000000F7', - "divide;": '\U000000F7', - "divideontimes;": '\U000022C7', - "divonx;": '\U000022C7', - "djcy;": '\U00000452', - "dlcorn;": '\U0000231E', - "dlcrop;": '\U0000230D', - "dollar;": '\U00000024', - "dopf;": '\U0001D555', - "dot;": '\U000002D9', - "doteq;": '\U00002250', - "doteqdot;": '\U00002251', - "dotminus;": '\U00002238', - "dotplus;": '\U00002214', - "dotsquare;": '\U000022A1', - "doublebarwedge;": '\U00002306', - "downarrow;": '\U00002193', - "downdownarrows;": '\U000021CA', - "downharpoonleft;": '\U000021C3', - "downharpoonright;": '\U000021C2', - "drbkarow;": '\U00002910', - "drcorn;": '\U0000231F', - "drcrop;": '\U0000230C', - "dscr;": '\U0001D4B9', - "dscy;": '\U00000455', - "dsol;": '\U000029F6', - "dstrok;": '\U00000111', - "dtdot;": '\U000022F1', - "dtri;": '\U000025BF', - "dtrif;": '\U000025BE', - "duarr;": '\U000021F5', - "duhar;": '\U0000296F', - "dwangle;": '\U000029A6', - "dzcy;": '\U0000045F', - "dzigrarr;": '\U000027FF', - "eDDot;": '\U00002A77', - "eDot;": '\U00002251', - "eacute;": '\U000000E9', - "easter;": '\U00002A6E', - "ecaron;": '\U0000011B', - "ecir;": '\U00002256', - "ecirc;": '\U000000EA', - "ecolon;": '\U00002255', - "ecy;": '\U0000044D', - "edot;": '\U00000117', - "ee;": '\U00002147', - "efDot;": '\U00002252', - "efr;": '\U0001D522', - "eg;": '\U00002A9A', - "egrave;": '\U000000E8', - "egs;": '\U00002A96', - "egsdot;": '\U00002A98', - "el;": '\U00002A99', - "elinters;": '\U000023E7', - "ell;": '\U00002113', - "els;": '\U00002A95', - "elsdot;": '\U00002A97', - "emacr;": '\U00000113', - "empty;": '\U00002205', - "emptyset;": '\U00002205', - "emptyv;": '\U00002205', - "emsp;": '\U00002003', - "emsp13;": '\U00002004', - "emsp14;": '\U00002005', - "eng;": '\U0000014B', - "ensp;": '\U00002002', - "eogon;": '\U00000119', - "eopf;": '\U0001D556', - "epar;": '\U000022D5', - "eparsl;": '\U000029E3', - "eplus;": '\U00002A71', - "epsi;": '\U000003B5', - "epsilon;": '\U000003B5', - "epsiv;": '\U000003F5', - "eqcirc;": '\U00002256', - "eqcolon;": '\U00002255', - "eqsim;": '\U00002242', - "eqslantgtr;": '\U00002A96', - "eqslantless;": '\U00002A95', - "equals;": '\U0000003D', - "equest;": '\U0000225F', - "equiv;": '\U00002261', - "equivDD;": '\U00002A78', - "eqvparsl;": '\U000029E5', - "erDot;": '\U00002253', - "erarr;": '\U00002971', - "escr;": '\U0000212F', - "esdot;": '\U00002250', - "esim;": '\U00002242', - "eta;": '\U000003B7', - "eth;": '\U000000F0', - "euml;": '\U000000EB', - "euro;": '\U000020AC', - "excl;": '\U00000021', - "exist;": '\U00002203', - "expectation;": '\U00002130', - "exponentiale;": '\U00002147', - "fallingdotseq;": '\U00002252', - "fcy;": '\U00000444', - "female;": '\U00002640', - "ffilig;": '\U0000FB03', - "fflig;": '\U0000FB00', - "ffllig;": '\U0000FB04', - "ffr;": '\U0001D523', - "filig;": '\U0000FB01', - "flat;": '\U0000266D', - "fllig;": '\U0000FB02', - "fltns;": '\U000025B1', - "fnof;": '\U00000192', - "fopf;": '\U0001D557', - "forall;": '\U00002200', - "fork;": '\U000022D4', - "forkv;": '\U00002AD9', - "fpartint;": '\U00002A0D', - "frac12;": '\U000000BD', - "frac13;": '\U00002153', - "frac14;": '\U000000BC', - "frac15;": '\U00002155', - "frac16;": '\U00002159', - "frac18;": '\U0000215B', - "frac23;": '\U00002154', - "frac25;": '\U00002156', - "frac34;": '\U000000BE', - "frac35;": '\U00002157', - "frac38;": '\U0000215C', - "frac45;": '\U00002158', - "frac56;": '\U0000215A', - "frac58;": '\U0000215D', - "frac78;": '\U0000215E', - "frasl;": '\U00002044', - "frown;": '\U00002322', - "fscr;": '\U0001D4BB', - "gE;": '\U00002267', - "gEl;": '\U00002A8C', - "gacute;": '\U000001F5', - "gamma;": '\U000003B3', - "gammad;": '\U000003DD', - "gap;": '\U00002A86', - "gbreve;": '\U0000011F', - "gcirc;": '\U0000011D', - "gcy;": '\U00000433', - "gdot;": '\U00000121', - "ge;": '\U00002265', - "gel;": '\U000022DB', - "geq;": '\U00002265', - "geqq;": '\U00002267', - "geqslant;": '\U00002A7E', - "ges;": '\U00002A7E', - "gescc;": '\U00002AA9', - "gesdot;": '\U00002A80', - "gesdoto;": '\U00002A82', - "gesdotol;": '\U00002A84', - "gesles;": '\U00002A94', - "gfr;": '\U0001D524', - "gg;": '\U0000226B', - "ggg;": '\U000022D9', - "gimel;": '\U00002137', - "gjcy;": '\U00000453', - "gl;": '\U00002277', - "glE;": '\U00002A92', - "gla;": '\U00002AA5', - "glj;": '\U00002AA4', - "gnE;": '\U00002269', - "gnap;": '\U00002A8A', - "gnapprox;": '\U00002A8A', - "gne;": '\U00002A88', - "gneq;": '\U00002A88', - "gneqq;": '\U00002269', - "gnsim;": '\U000022E7', - "gopf;": '\U0001D558', - "grave;": '\U00000060', - "gscr;": '\U0000210A', - "gsim;": '\U00002273', - "gsime;": '\U00002A8E', - "gsiml;": '\U00002A90', - "gt;": '\U0000003E', - "gtcc;": '\U00002AA7', - "gtcir;": '\U00002A7A', - "gtdot;": '\U000022D7', - "gtlPar;": '\U00002995', - "gtquest;": '\U00002A7C', - "gtrapprox;": '\U00002A86', - "gtrarr;": '\U00002978', - "gtrdot;": '\U000022D7', - "gtreqless;": '\U000022DB', - "gtreqqless;": '\U00002A8C', - "gtrless;": '\U00002277', - "gtrsim;": '\U00002273', - "hArr;": '\U000021D4', - "hairsp;": '\U0000200A', - "half;": '\U000000BD', - "hamilt;": '\U0000210B', - "hardcy;": '\U0000044A', - "harr;": '\U00002194', - "harrcir;": '\U00002948', - "harrw;": '\U000021AD', - "hbar;": '\U0000210F', - "hcirc;": '\U00000125', - "hearts;": '\U00002665', - "heartsuit;": '\U00002665', - "hellip;": '\U00002026', - "hercon;": '\U000022B9', - "hfr;": '\U0001D525', - "hksearow;": '\U00002925', - "hkswarow;": '\U00002926', - "hoarr;": '\U000021FF', - "homtht;": '\U0000223B', - "hookleftarrow;": '\U000021A9', - "hookrightarrow;": '\U000021AA', - "hopf;": '\U0001D559', - "horbar;": '\U00002015', - "hscr;": '\U0001D4BD', - "hslash;": '\U0000210F', - "hstrok;": '\U00000127', - "hybull;": '\U00002043', - "hyphen;": '\U00002010', - "iacute;": '\U000000ED', - "ic;": '\U00002063', - "icirc;": '\U000000EE', - "icy;": '\U00000438', - "iecy;": '\U00000435', - "iexcl;": '\U000000A1', - "iff;": '\U000021D4', - "ifr;": '\U0001D526', - "igrave;": '\U000000EC', - "ii;": '\U00002148', - "iiiint;": '\U00002A0C', - "iiint;": '\U0000222D', - "iinfin;": '\U000029DC', - "iiota;": '\U00002129', - "ijlig;": '\U00000133', - "imacr;": '\U0000012B', - "image;": '\U00002111', - "imagline;": '\U00002110', - "imagpart;": '\U00002111', - "imath;": '\U00000131', - "imof;": '\U000022B7', - "imped;": '\U000001B5', - "in;": '\U00002208', - "incare;": '\U00002105', - "infin;": '\U0000221E', - "infintie;": '\U000029DD', - "inodot;": '\U00000131', - "int;": '\U0000222B', - "intcal;": '\U000022BA', - "integers;": '\U00002124', - "intercal;": '\U000022BA', - "intlarhk;": '\U00002A17', - "intprod;": '\U00002A3C', - "iocy;": '\U00000451', - "iogon;": '\U0000012F', - "iopf;": '\U0001D55A', - "iota;": '\U000003B9', - "iprod;": '\U00002A3C', - "iquest;": '\U000000BF', - "iscr;": '\U0001D4BE', - "isin;": '\U00002208', - "isinE;": '\U000022F9', - "isindot;": '\U000022F5', - "isins;": '\U000022F4', - "isinsv;": '\U000022F3', - "isinv;": '\U00002208', - "it;": '\U00002062', - "itilde;": '\U00000129', - "iukcy;": '\U00000456', - "iuml;": '\U000000EF', - "jcirc;": '\U00000135', - "jcy;": '\U00000439', - "jfr;": '\U0001D527', - "jmath;": '\U00000237', - "jopf;": '\U0001D55B', - "jscr;": '\U0001D4BF', - "jsercy;": '\U00000458', - "jukcy;": '\U00000454', - "kappa;": '\U000003BA', - "kappav;": '\U000003F0', - "kcedil;": '\U00000137', - "kcy;": '\U0000043A', - "kfr;": '\U0001D528', - "kgreen;": '\U00000138', - "khcy;": '\U00000445', - "kjcy;": '\U0000045C', - "kopf;": '\U0001D55C', - "kscr;": '\U0001D4C0', - "lAarr;": '\U000021DA', - "lArr;": '\U000021D0', - "lAtail;": '\U0000291B', - "lBarr;": '\U0000290E', - "lE;": '\U00002266', - "lEg;": '\U00002A8B', - "lHar;": '\U00002962', - "lacute;": '\U0000013A', - "laemptyv;": '\U000029B4', - "lagran;": '\U00002112', - "lambda;": '\U000003BB', - "lang;": '\U000027E8', - "langd;": '\U00002991', - "langle;": '\U000027E8', - "lap;": '\U00002A85', - "laquo;": '\U000000AB', - "larr;": '\U00002190', - "larrb;": '\U000021E4', - "larrbfs;": '\U0000291F', - "larrfs;": '\U0000291D', - "larrhk;": '\U000021A9', - "larrlp;": '\U000021AB', - "larrpl;": '\U00002939', - "larrsim;": '\U00002973', - "larrtl;": '\U000021A2', - "lat;": '\U00002AAB', - "latail;": '\U00002919', - "late;": '\U00002AAD', - "lbarr;": '\U0000290C', - "lbbrk;": '\U00002772', - "lbrace;": '\U0000007B', - "lbrack;": '\U0000005B', - "lbrke;": '\U0000298B', - "lbrksld;": '\U0000298F', - "lbrkslu;": '\U0000298D', - "lcaron;": '\U0000013E', - "lcedil;": '\U0000013C', - "lceil;": '\U00002308', - "lcub;": '\U0000007B', - "lcy;": '\U0000043B', - "ldca;": '\U00002936', - "ldquo;": '\U0000201C', - "ldquor;": '\U0000201E', - "ldrdhar;": '\U00002967', - "ldrushar;": '\U0000294B', - "ldsh;": '\U000021B2', - "le;": '\U00002264', - "leftarrow;": '\U00002190', - "leftarrowtail;": '\U000021A2', - "leftharpoondown;": '\U000021BD', - "leftharpoonup;": '\U000021BC', - "leftleftarrows;": '\U000021C7', - "leftrightarrow;": '\U00002194', - "leftrightarrows;": '\U000021C6', - "leftrightharpoons;": '\U000021CB', - "leftrightsquigarrow;": '\U000021AD', - "leftthreetimes;": '\U000022CB', - "leg;": '\U000022DA', - "leq;": '\U00002264', - "leqq;": '\U00002266', - "leqslant;": '\U00002A7D', - "les;": '\U00002A7D', - "lescc;": '\U00002AA8', - "lesdot;": '\U00002A7F', - "lesdoto;": '\U00002A81', - "lesdotor;": '\U00002A83', - "lesges;": '\U00002A93', - "lessapprox;": '\U00002A85', - "lessdot;": '\U000022D6', - "lesseqgtr;": '\U000022DA', - "lesseqqgtr;": '\U00002A8B', - "lessgtr;": '\U00002276', - "lesssim;": '\U00002272', - "lfisht;": '\U0000297C', - "lfloor;": '\U0000230A', - "lfr;": '\U0001D529', - "lg;": '\U00002276', - "lgE;": '\U00002A91', - "lhard;": '\U000021BD', - "lharu;": '\U000021BC', - "lharul;": '\U0000296A', - "lhblk;": '\U00002584', - "ljcy;": '\U00000459', - "ll;": '\U0000226A', - "llarr;": '\U000021C7', - "llcorner;": '\U0000231E', - "llhard;": '\U0000296B', - "lltri;": '\U000025FA', - "lmidot;": '\U00000140', - "lmoust;": '\U000023B0', - "lmoustache;": '\U000023B0', - "lnE;": '\U00002268', - "lnap;": '\U00002A89', - "lnapprox;": '\U00002A89', - "lne;": '\U00002A87', - "lneq;": '\U00002A87', - "lneqq;": '\U00002268', - "lnsim;": '\U000022E6', - "loang;": '\U000027EC', - "loarr;": '\U000021FD', - "lobrk;": '\U000027E6', - "longleftarrow;": '\U000027F5', - "longleftrightarrow;": '\U000027F7', - "longmapsto;": '\U000027FC', - "longrightarrow;": '\U000027F6', - "looparrowleft;": '\U000021AB', - "looparrowright;": '\U000021AC', - "lopar;": '\U00002985', - "lopf;": '\U0001D55D', - "loplus;": '\U00002A2D', - "lotimes;": '\U00002A34', - "lowast;": '\U00002217', - "lowbar;": '\U0000005F', - "loz;": '\U000025CA', - "lozenge;": '\U000025CA', - "lozf;": '\U000029EB', - "lpar;": '\U00000028', - "lparlt;": '\U00002993', - "lrarr;": '\U000021C6', - "lrcorner;": '\U0000231F', - "lrhar;": '\U000021CB', - "lrhard;": '\U0000296D', - "lrm;": '\U0000200E', - "lrtri;": '\U000022BF', - "lsaquo;": '\U00002039', - "lscr;": '\U0001D4C1', - "lsh;": '\U000021B0', - "lsim;": '\U00002272', - "lsime;": '\U00002A8D', - "lsimg;": '\U00002A8F', - "lsqb;": '\U0000005B', - "lsquo;": '\U00002018', - "lsquor;": '\U0000201A', - "lstrok;": '\U00000142', - "lt;": '\U0000003C', - "ltcc;": '\U00002AA6', - "ltcir;": '\U00002A79', - "ltdot;": '\U000022D6', - "lthree;": '\U000022CB', - "ltimes;": '\U000022C9', - "ltlarr;": '\U00002976', - "ltquest;": '\U00002A7B', - "ltrPar;": '\U00002996', - "ltri;": '\U000025C3', - "ltrie;": '\U000022B4', - "ltrif;": '\U000025C2', - "lurdshar;": '\U0000294A', - "luruhar;": '\U00002966', - "mDDot;": '\U0000223A', - "macr;": '\U000000AF', - "male;": '\U00002642', - "malt;": '\U00002720', - "maltese;": '\U00002720', - "map;": '\U000021A6', - "mapsto;": '\U000021A6', - "mapstodown;": '\U000021A7', - "mapstoleft;": '\U000021A4', - "mapstoup;": '\U000021A5', - "marker;": '\U000025AE', - "mcomma;": '\U00002A29', - "mcy;": '\U0000043C', - "mdash;": '\U00002014', - "measuredangle;": '\U00002221', - "mfr;": '\U0001D52A', - "mho;": '\U00002127', - "micro;": '\U000000B5', - "mid;": '\U00002223', - "midast;": '\U0000002A', - "midcir;": '\U00002AF0', - "middot;": '\U000000B7', - "minus;": '\U00002212', - "minusb;": '\U0000229F', - "minusd;": '\U00002238', - "minusdu;": '\U00002A2A', - "mlcp;": '\U00002ADB', - "mldr;": '\U00002026', - "mnplus;": '\U00002213', - "models;": '\U000022A7', - "mopf;": '\U0001D55E', - "mp;": '\U00002213', - "mscr;": '\U0001D4C2', - "mstpos;": '\U0000223E', - "mu;": '\U000003BC', - "multimap;": '\U000022B8', - "mumap;": '\U000022B8', - "nLeftarrow;": '\U000021CD', - "nLeftrightarrow;": '\U000021CE', - "nRightarrow;": '\U000021CF', - "nVDash;": '\U000022AF', - "nVdash;": '\U000022AE', - "nabla;": '\U00002207', - "nacute;": '\U00000144', - "nap;": '\U00002249', - "napos;": '\U00000149', - "napprox;": '\U00002249', - "natur;": '\U0000266E', - "natural;": '\U0000266E', - "naturals;": '\U00002115', - "nbsp;": '\U000000A0', - "ncap;": '\U00002A43', - "ncaron;": '\U00000148', - "ncedil;": '\U00000146', - "ncong;": '\U00002247', - "ncup;": '\U00002A42', - "ncy;": '\U0000043D', - "ndash;": '\U00002013', - "ne;": '\U00002260', - "neArr;": '\U000021D7', - "nearhk;": '\U00002924', - "nearr;": '\U00002197', - "nearrow;": '\U00002197', - "nequiv;": '\U00002262', - "nesear;": '\U00002928', - "nexist;": '\U00002204', - "nexists;": '\U00002204', - "nfr;": '\U0001D52B', - "nge;": '\U00002271', - "ngeq;": '\U00002271', - "ngsim;": '\U00002275', - "ngt;": '\U0000226F', - "ngtr;": '\U0000226F', - "nhArr;": '\U000021CE', - "nharr;": '\U000021AE', - "nhpar;": '\U00002AF2', - "ni;": '\U0000220B', - "nis;": '\U000022FC', - "nisd;": '\U000022FA', - "niv;": '\U0000220B', - "njcy;": '\U0000045A', - "nlArr;": '\U000021CD', - "nlarr;": '\U0000219A', - "nldr;": '\U00002025', - "nle;": '\U00002270', - "nleftarrow;": '\U0000219A', - "nleftrightarrow;": '\U000021AE', - "nleq;": '\U00002270', - "nless;": '\U0000226E', - "nlsim;": '\U00002274', - "nlt;": '\U0000226E', - "nltri;": '\U000022EA', - "nltrie;": '\U000022EC', - "nmid;": '\U00002224', - "nopf;": '\U0001D55F', - "not;": '\U000000AC', - "notin;": '\U00002209', - "notinva;": '\U00002209', - "notinvb;": '\U000022F7', - "notinvc;": '\U000022F6', - "notni;": '\U0000220C', - "notniva;": '\U0000220C', - "notnivb;": '\U000022FE', - "notnivc;": '\U000022FD', - "npar;": '\U00002226', - "nparallel;": '\U00002226', - "npolint;": '\U00002A14', - "npr;": '\U00002280', - "nprcue;": '\U000022E0', - "nprec;": '\U00002280', - "nrArr;": '\U000021CF', - "nrarr;": '\U0000219B', - "nrightarrow;": '\U0000219B', - "nrtri;": '\U000022EB', - "nrtrie;": '\U000022ED', - "nsc;": '\U00002281', - "nsccue;": '\U000022E1', - "nscr;": '\U0001D4C3', - "nshortmid;": '\U00002224', - "nshortparallel;": '\U00002226', - "nsim;": '\U00002241', - "nsime;": '\U00002244', - "nsimeq;": '\U00002244', - "nsmid;": '\U00002224', - "nspar;": '\U00002226', - "nsqsube;": '\U000022E2', - "nsqsupe;": '\U000022E3', - "nsub;": '\U00002284', - "nsube;": '\U00002288', - "nsubseteq;": '\U00002288', - "nsucc;": '\U00002281', - "nsup;": '\U00002285', - "nsupe;": '\U00002289', - "nsupseteq;": '\U00002289', - "ntgl;": '\U00002279', - "ntilde;": '\U000000F1', - "ntlg;": '\U00002278', - "ntriangleleft;": '\U000022EA', - "ntrianglelefteq;": '\U000022EC', - "ntriangleright;": '\U000022EB', - "ntrianglerighteq;": '\U000022ED', - "nu;": '\U000003BD', - "num;": '\U00000023', - "numero;": '\U00002116', - "numsp;": '\U00002007', - "nvDash;": '\U000022AD', - "nvHarr;": '\U00002904', - "nvdash;": '\U000022AC', - "nvinfin;": '\U000029DE', - "nvlArr;": '\U00002902', - "nvrArr;": '\U00002903', - "nwArr;": '\U000021D6', - "nwarhk;": '\U00002923', - "nwarr;": '\U00002196', - "nwarrow;": '\U00002196', - "nwnear;": '\U00002927', - "oS;": '\U000024C8', - "oacute;": '\U000000F3', - "oast;": '\U0000229B', - "ocir;": '\U0000229A', - "ocirc;": '\U000000F4', - "ocy;": '\U0000043E', - "odash;": '\U0000229D', - "odblac;": '\U00000151', - "odiv;": '\U00002A38', - "odot;": '\U00002299', - "odsold;": '\U000029BC', - "oelig;": '\U00000153', - "ofcir;": '\U000029BF', - "ofr;": '\U0001D52C', - "ogon;": '\U000002DB', - "ograve;": '\U000000F2', - "ogt;": '\U000029C1', - "ohbar;": '\U000029B5', - "ohm;": '\U000003A9', - "oint;": '\U0000222E', - "olarr;": '\U000021BA', - "olcir;": '\U000029BE', - "olcross;": '\U000029BB', - "oline;": '\U0000203E', - "olt;": '\U000029C0', - "omacr;": '\U0000014D', - "omega;": '\U000003C9', - "omicron;": '\U000003BF', - "omid;": '\U000029B6', - "ominus;": '\U00002296', - "oopf;": '\U0001D560', - "opar;": '\U000029B7', - "operp;": '\U000029B9', - "oplus;": '\U00002295', - "or;": '\U00002228', - "orarr;": '\U000021BB', - "ord;": '\U00002A5D', - "order;": '\U00002134', - "orderof;": '\U00002134', - "ordf;": '\U000000AA', - "ordm;": '\U000000BA', - "origof;": '\U000022B6', - "oror;": '\U00002A56', - "orslope;": '\U00002A57', - "orv;": '\U00002A5B', - "oscr;": '\U00002134', - "oslash;": '\U000000F8', - "osol;": '\U00002298', - "otilde;": '\U000000F5', - "otimes;": '\U00002297', - "otimesas;": '\U00002A36', - "ouml;": '\U000000F6', - "ovbar;": '\U0000233D', - "par;": '\U00002225', - "para;": '\U000000B6', - "parallel;": '\U00002225', - "parsim;": '\U00002AF3', - "parsl;": '\U00002AFD', - "part;": '\U00002202', - "pcy;": '\U0000043F', - "percnt;": '\U00000025', - "period;": '\U0000002E', - "permil;": '\U00002030', - "perp;": '\U000022A5', - "pertenk;": '\U00002031', - "pfr;": '\U0001D52D', - "phi;": '\U000003C6', - "phiv;": '\U000003D5', - "phmmat;": '\U00002133', - "phone;": '\U0000260E', - "pi;": '\U000003C0', - "pitchfork;": '\U000022D4', - "piv;": '\U000003D6', - "planck;": '\U0000210F', - "planckh;": '\U0000210E', - "plankv;": '\U0000210F', - "plus;": '\U0000002B', - "plusacir;": '\U00002A23', - "plusb;": '\U0000229E', - "pluscir;": '\U00002A22', - "plusdo;": '\U00002214', - "plusdu;": '\U00002A25', - "pluse;": '\U00002A72', - "plusmn;": '\U000000B1', - "plussim;": '\U00002A26', - "plustwo;": '\U00002A27', - "pm;": '\U000000B1', - "pointint;": '\U00002A15', - "popf;": '\U0001D561', - "pound;": '\U000000A3', - "pr;": '\U0000227A', - "prE;": '\U00002AB3', - "prap;": '\U00002AB7', - "prcue;": '\U0000227C', - "pre;": '\U00002AAF', - "prec;": '\U0000227A', - "precapprox;": '\U00002AB7', - "preccurlyeq;": '\U0000227C', - "preceq;": '\U00002AAF', - "precnapprox;": '\U00002AB9', - "precneqq;": '\U00002AB5', - "precnsim;": '\U000022E8', - "precsim;": '\U0000227E', - "prime;": '\U00002032', - "primes;": '\U00002119', - "prnE;": '\U00002AB5', - "prnap;": '\U00002AB9', - "prnsim;": '\U000022E8', - "prod;": '\U0000220F', - "profalar;": '\U0000232E', - "profline;": '\U00002312', - "profsurf;": '\U00002313', - "prop;": '\U0000221D', - "propto;": '\U0000221D', - "prsim;": '\U0000227E', - "prurel;": '\U000022B0', - "pscr;": '\U0001D4C5', - "psi;": '\U000003C8', - "puncsp;": '\U00002008', - "qfr;": '\U0001D52E', - "qint;": '\U00002A0C', - "qopf;": '\U0001D562', - "qprime;": '\U00002057', - "qscr;": '\U0001D4C6', - "quaternions;": '\U0000210D', - "quatint;": '\U00002A16', - "quest;": '\U0000003F', - "questeq;": '\U0000225F', - "quot;": '\U00000022', - "rAarr;": '\U000021DB', - "rArr;": '\U000021D2', - "rAtail;": '\U0000291C', - "rBarr;": '\U0000290F', - "rHar;": '\U00002964', - "racute;": '\U00000155', - "radic;": '\U0000221A', - "raemptyv;": '\U000029B3', - "rang;": '\U000027E9', - "rangd;": '\U00002992', - "range;": '\U000029A5', - "rangle;": '\U000027E9', - "raquo;": '\U000000BB', - "rarr;": '\U00002192', - "rarrap;": '\U00002975', - "rarrb;": '\U000021E5', - "rarrbfs;": '\U00002920', - "rarrc;": '\U00002933', - "rarrfs;": '\U0000291E', - "rarrhk;": '\U000021AA', - "rarrlp;": '\U000021AC', - "rarrpl;": '\U00002945', - "rarrsim;": '\U00002974', - "rarrtl;": '\U000021A3', - "rarrw;": '\U0000219D', - "ratail;": '\U0000291A', - "ratio;": '\U00002236', - "rationals;": '\U0000211A', - "rbarr;": '\U0000290D', - "rbbrk;": '\U00002773', - "rbrace;": '\U0000007D', - "rbrack;": '\U0000005D', - "rbrke;": '\U0000298C', - "rbrksld;": '\U0000298E', - "rbrkslu;": '\U00002990', - "rcaron;": '\U00000159', - "rcedil;": '\U00000157', - "rceil;": '\U00002309', - "rcub;": '\U0000007D', - "rcy;": '\U00000440', - "rdca;": '\U00002937', - "rdldhar;": '\U00002969', - "rdquo;": '\U0000201D', - "rdquor;": '\U0000201D', - "rdsh;": '\U000021B3', - "real;": '\U0000211C', - "realine;": '\U0000211B', - "realpart;": '\U0000211C', - "reals;": '\U0000211D', - "rect;": '\U000025AD', - "reg;": '\U000000AE', - "rfisht;": '\U0000297D', - "rfloor;": '\U0000230B', - "rfr;": '\U0001D52F', - "rhard;": '\U000021C1', - "rharu;": '\U000021C0', - "rharul;": '\U0000296C', - "rho;": '\U000003C1', - "rhov;": '\U000003F1', - "rightarrow;": '\U00002192', - "rightarrowtail;": '\U000021A3', - "rightharpoondown;": '\U000021C1', - "rightharpoonup;": '\U000021C0', - "rightleftarrows;": '\U000021C4', - "rightleftharpoons;": '\U000021CC', - "rightrightarrows;": '\U000021C9', - "rightsquigarrow;": '\U0000219D', - "rightthreetimes;": '\U000022CC', - "ring;": '\U000002DA', - "risingdotseq;": '\U00002253', - "rlarr;": '\U000021C4', - "rlhar;": '\U000021CC', - "rlm;": '\U0000200F', - "rmoust;": '\U000023B1', - "rmoustache;": '\U000023B1', - "rnmid;": '\U00002AEE', - "roang;": '\U000027ED', - "roarr;": '\U000021FE', - "robrk;": '\U000027E7', - "ropar;": '\U00002986', - "ropf;": '\U0001D563', - "roplus;": '\U00002A2E', - "rotimes;": '\U00002A35', - "rpar;": '\U00000029', - "rpargt;": '\U00002994', - "rppolint;": '\U00002A12', - "rrarr;": '\U000021C9', - "rsaquo;": '\U0000203A', - "rscr;": '\U0001D4C7', - "rsh;": '\U000021B1', - "rsqb;": '\U0000005D', - "rsquo;": '\U00002019', - "rsquor;": '\U00002019', - "rthree;": '\U000022CC', - "rtimes;": '\U000022CA', - "rtri;": '\U000025B9', - "rtrie;": '\U000022B5', - "rtrif;": '\U000025B8', - "rtriltri;": '\U000029CE', - "ruluhar;": '\U00002968', - "rx;": '\U0000211E', - "sacute;": '\U0000015B', - "sbquo;": '\U0000201A', - "sc;": '\U0000227B', - "scE;": '\U00002AB4', - "scap;": '\U00002AB8', - "scaron;": '\U00000161', - "sccue;": '\U0000227D', - "sce;": '\U00002AB0', - "scedil;": '\U0000015F', - "scirc;": '\U0000015D', - "scnE;": '\U00002AB6', - "scnap;": '\U00002ABA', - "scnsim;": '\U000022E9', - "scpolint;": '\U00002A13', - "scsim;": '\U0000227F', - "scy;": '\U00000441', - "sdot;": '\U000022C5', - "sdotb;": '\U000022A1', - "sdote;": '\U00002A66', - "seArr;": '\U000021D8', - "searhk;": '\U00002925', - "searr;": '\U00002198', - "searrow;": '\U00002198', - "sect;": '\U000000A7', - "semi;": '\U0000003B', - "seswar;": '\U00002929', - "setminus;": '\U00002216', - "setmn;": '\U00002216', - "sext;": '\U00002736', - "sfr;": '\U0001D530', - "sfrown;": '\U00002322', - "sharp;": '\U0000266F', - "shchcy;": '\U00000449', - "shcy;": '\U00000448', - "shortmid;": '\U00002223', - "shortparallel;": '\U00002225', - "shy;": '\U000000AD', - "sigma;": '\U000003C3', - "sigmaf;": '\U000003C2', - "sigmav;": '\U000003C2', - "sim;": '\U0000223C', - "simdot;": '\U00002A6A', - "sime;": '\U00002243', - "simeq;": '\U00002243', - "simg;": '\U00002A9E', - "simgE;": '\U00002AA0', - "siml;": '\U00002A9D', - "simlE;": '\U00002A9F', - "simne;": '\U00002246', - "simplus;": '\U00002A24', - "simrarr;": '\U00002972', - "slarr;": '\U00002190', - "smallsetminus;": '\U00002216', - "smashp;": '\U00002A33', - "smeparsl;": '\U000029E4', - "smid;": '\U00002223', - "smile;": '\U00002323', - "smt;": '\U00002AAA', - "smte;": '\U00002AAC', - "softcy;": '\U0000044C', - "sol;": '\U0000002F', - "solb;": '\U000029C4', - "solbar;": '\U0000233F', - "sopf;": '\U0001D564', - "spades;": '\U00002660', - "spadesuit;": '\U00002660', - "spar;": '\U00002225', - "sqcap;": '\U00002293', - "sqcup;": '\U00002294', - "sqsub;": '\U0000228F', - "sqsube;": '\U00002291', - "sqsubset;": '\U0000228F', - "sqsubseteq;": '\U00002291', - "sqsup;": '\U00002290', - "sqsupe;": '\U00002292', - "sqsupset;": '\U00002290', - "sqsupseteq;": '\U00002292', - "squ;": '\U000025A1', - "square;": '\U000025A1', - "squarf;": '\U000025AA', - "squf;": '\U000025AA', - "srarr;": '\U00002192', - "sscr;": '\U0001D4C8', - "ssetmn;": '\U00002216', - "ssmile;": '\U00002323', - "sstarf;": '\U000022C6', - "star;": '\U00002606', - "starf;": '\U00002605', - "straightepsilon;": '\U000003F5', - "straightphi;": '\U000003D5', - "strns;": '\U000000AF', - "sub;": '\U00002282', - "subE;": '\U00002AC5', - "subdot;": '\U00002ABD', - "sube;": '\U00002286', - "subedot;": '\U00002AC3', - "submult;": '\U00002AC1', - "subnE;": '\U00002ACB', - "subne;": '\U0000228A', - "subplus;": '\U00002ABF', - "subrarr;": '\U00002979', - "subset;": '\U00002282', - "subseteq;": '\U00002286', - "subseteqq;": '\U00002AC5', - "subsetneq;": '\U0000228A', - "subsetneqq;": '\U00002ACB', - "subsim;": '\U00002AC7', - "subsub;": '\U00002AD5', - "subsup;": '\U00002AD3', - "succ;": '\U0000227B', - "succapprox;": '\U00002AB8', - "succcurlyeq;": '\U0000227D', - "succeq;": '\U00002AB0', - "succnapprox;": '\U00002ABA', - "succneqq;": '\U00002AB6', - "succnsim;": '\U000022E9', - "succsim;": '\U0000227F', - "sum;": '\U00002211', - "sung;": '\U0000266A', - "sup;": '\U00002283', - "sup1;": '\U000000B9', - "sup2;": '\U000000B2', - "sup3;": '\U000000B3', - "supE;": '\U00002AC6', - "supdot;": '\U00002ABE', - "supdsub;": '\U00002AD8', - "supe;": '\U00002287', - "supedot;": '\U00002AC4', - "suphsol;": '\U000027C9', - "suphsub;": '\U00002AD7', - "suplarr;": '\U0000297B', - "supmult;": '\U00002AC2', - "supnE;": '\U00002ACC', - "supne;": '\U0000228B', - "supplus;": '\U00002AC0', - "supset;": '\U00002283', - "supseteq;": '\U00002287', - "supseteqq;": '\U00002AC6', - "supsetneq;": '\U0000228B', - "supsetneqq;": '\U00002ACC', - "supsim;": '\U00002AC8', - "supsub;": '\U00002AD4', - "supsup;": '\U00002AD6', - "swArr;": '\U000021D9', - "swarhk;": '\U00002926', - "swarr;": '\U00002199', - "swarrow;": '\U00002199', - "swnwar;": '\U0000292A', - "szlig;": '\U000000DF', - "target;": '\U00002316', - "tau;": '\U000003C4', - "tbrk;": '\U000023B4', - "tcaron;": '\U00000165', - "tcedil;": '\U00000163', - "tcy;": '\U00000442', - "tdot;": '\U000020DB', - "telrec;": '\U00002315', - "tfr;": '\U0001D531', - "there4;": '\U00002234', - "therefore;": '\U00002234', - "theta;": '\U000003B8', - "thetasym;": '\U000003D1', - "thetav;": '\U000003D1', - "thickapprox;": '\U00002248', - "thicksim;": '\U0000223C', - "thinsp;": '\U00002009', - "thkap;": '\U00002248', - "thksim;": '\U0000223C', - "thorn;": '\U000000FE', - "tilde;": '\U000002DC', - "times;": '\U000000D7', - "timesb;": '\U000022A0', - "timesbar;": '\U00002A31', - "timesd;": '\U00002A30', - "tint;": '\U0000222D', - "toea;": '\U00002928', - "top;": '\U000022A4', - "topbot;": '\U00002336', - "topcir;": '\U00002AF1', - "topf;": '\U0001D565', - "topfork;": '\U00002ADA', - "tosa;": '\U00002929', - "tprime;": '\U00002034', - "trade;": '\U00002122', - "triangle;": '\U000025B5', - "triangledown;": '\U000025BF', - "triangleleft;": '\U000025C3', - "trianglelefteq;": '\U000022B4', - "triangleq;": '\U0000225C', - "triangleright;": '\U000025B9', - "trianglerighteq;": '\U000022B5', - "tridot;": '\U000025EC', - "trie;": '\U0000225C', - "triminus;": '\U00002A3A', - "triplus;": '\U00002A39', - "trisb;": '\U000029CD', - "tritime;": '\U00002A3B', - "trpezium;": '\U000023E2', - "tscr;": '\U0001D4C9', - "tscy;": '\U00000446', - "tshcy;": '\U0000045B', - "tstrok;": '\U00000167', - "twixt;": '\U0000226C', - "twoheadleftarrow;": '\U0000219E', - "twoheadrightarrow;": '\U000021A0', - "uArr;": '\U000021D1', - "uHar;": '\U00002963', - "uacute;": '\U000000FA', - "uarr;": '\U00002191', - "ubrcy;": '\U0000045E', - "ubreve;": '\U0000016D', - "ucirc;": '\U000000FB', - "ucy;": '\U00000443', - "udarr;": '\U000021C5', - "udblac;": '\U00000171', - "udhar;": '\U0000296E', - "ufisht;": '\U0000297E', - "ufr;": '\U0001D532', - "ugrave;": '\U000000F9', - "uharl;": '\U000021BF', - "uharr;": '\U000021BE', - "uhblk;": '\U00002580', - "ulcorn;": '\U0000231C', - "ulcorner;": '\U0000231C', - "ulcrop;": '\U0000230F', - "ultri;": '\U000025F8', - "umacr;": '\U0000016B', - "uml;": '\U000000A8', - "uogon;": '\U00000173', - "uopf;": '\U0001D566', - "uparrow;": '\U00002191', - "updownarrow;": '\U00002195', - "upharpoonleft;": '\U000021BF', - "upharpoonright;": '\U000021BE', - "uplus;": '\U0000228E', - "upsi;": '\U000003C5', - "upsih;": '\U000003D2', - "upsilon;": '\U000003C5', - "upuparrows;": '\U000021C8', - "urcorn;": '\U0000231D', - "urcorner;": '\U0000231D', - "urcrop;": '\U0000230E', - "uring;": '\U0000016F', - "urtri;": '\U000025F9', - "uscr;": '\U0001D4CA', - "utdot;": '\U000022F0', - "utilde;": '\U00000169', - "utri;": '\U000025B5', - "utrif;": '\U000025B4', - "uuarr;": '\U000021C8', - "uuml;": '\U000000FC', - "uwangle;": '\U000029A7', - "vArr;": '\U000021D5', - "vBar;": '\U00002AE8', - "vBarv;": '\U00002AE9', - "vDash;": '\U000022A8', - "vangrt;": '\U0000299C', - "varepsilon;": '\U000003F5', - "varkappa;": '\U000003F0', - "varnothing;": '\U00002205', - "varphi;": '\U000003D5', - "varpi;": '\U000003D6', - "varpropto;": '\U0000221D', - "varr;": '\U00002195', - "varrho;": '\U000003F1', - "varsigma;": '\U000003C2', - "vartheta;": '\U000003D1', - "vartriangleleft;": '\U000022B2', - "vartriangleright;": '\U000022B3', - "vcy;": '\U00000432', - "vdash;": '\U000022A2', - "vee;": '\U00002228', - "veebar;": '\U000022BB', - "veeeq;": '\U0000225A', - "vellip;": '\U000022EE', - "verbar;": '\U0000007C', - "vert;": '\U0000007C', - "vfr;": '\U0001D533', - "vltri;": '\U000022B2', - "vopf;": '\U0001D567', - "vprop;": '\U0000221D', - "vrtri;": '\U000022B3', - "vscr;": '\U0001D4CB', - "vzigzag;": '\U0000299A', - "wcirc;": '\U00000175', - "wedbar;": '\U00002A5F', - "wedge;": '\U00002227', - "wedgeq;": '\U00002259', - "weierp;": '\U00002118', - "wfr;": '\U0001D534', - "wopf;": '\U0001D568', - "wp;": '\U00002118', - "wr;": '\U00002240', - "wreath;": '\U00002240', - "wscr;": '\U0001D4CC', - "xcap;": '\U000022C2', - "xcirc;": '\U000025EF', - "xcup;": '\U000022C3', - "xdtri;": '\U000025BD', - "xfr;": '\U0001D535', - "xhArr;": '\U000027FA', - "xharr;": '\U000027F7', - "xi;": '\U000003BE', - "xlArr;": '\U000027F8', - "xlarr;": '\U000027F5', - "xmap;": '\U000027FC', - "xnis;": '\U000022FB', - "xodot;": '\U00002A00', - "xopf;": '\U0001D569', - "xoplus;": '\U00002A01', - "xotime;": '\U00002A02', - "xrArr;": '\U000027F9', - "xrarr;": '\U000027F6', - "xscr;": '\U0001D4CD', - "xsqcup;": '\U00002A06', - "xuplus;": '\U00002A04', - "xutri;": '\U000025B3', - "xvee;": '\U000022C1', - "xwedge;": '\U000022C0', - "yacute;": '\U000000FD', - "yacy;": '\U0000044F', - "ycirc;": '\U00000177', - "ycy;": '\U0000044B', - "yen;": '\U000000A5', - "yfr;": '\U0001D536', - "yicy;": '\U00000457', - "yopf;": '\U0001D56A', - "yscr;": '\U0001D4CE', - "yucy;": '\U0000044E', - "yuml;": '\U000000FF', - "zacute;": '\U0000017A', - "zcaron;": '\U0000017E', - "zcy;": '\U00000437', - "zdot;": '\U0000017C', - "zeetrf;": '\U00002128', - "zeta;": '\U000003B6', - "zfr;": '\U0001D537', - "zhcy;": '\U00000436', - "zigrarr;": '\U000021DD', - "zopf;": '\U0001D56B', - "zscr;": '\U0001D4CF', - "zwj;": '\U0000200D', - "zwnj;": '\U0000200C', - "AElig": '\U000000C6', - "AMP": '\U00000026', - "Aacute": '\U000000C1', - "Acirc": '\U000000C2', - "Agrave": '\U000000C0', - "Aring": '\U000000C5', - "Atilde": '\U000000C3', - "Auml": '\U000000C4', - "COPY": '\U000000A9', - "Ccedil": '\U000000C7', - "ETH": '\U000000D0', - "Eacute": '\U000000C9', - "Ecirc": '\U000000CA', - "Egrave": '\U000000C8', - "Euml": '\U000000CB', - "GT": '\U0000003E', - "Iacute": '\U000000CD', - "Icirc": '\U000000CE', - "Igrave": '\U000000CC', - "Iuml": '\U000000CF', - "LT": '\U0000003C', - "Ntilde": '\U000000D1', - "Oacute": '\U000000D3', - "Ocirc": '\U000000D4', - "Ograve": '\U000000D2', - "Oslash": '\U000000D8', - "Otilde": '\U000000D5', - "Ouml": '\U000000D6', - "QUOT": '\U00000022', - "REG": '\U000000AE', - "THORN": '\U000000DE', - "Uacute": '\U000000DA', - "Ucirc": '\U000000DB', - "Ugrave": '\U000000D9', - "Uuml": '\U000000DC', - "Yacute": '\U000000DD', - "aacute": '\U000000E1', - "acirc": '\U000000E2', - "acute": '\U000000B4', - "aelig": '\U000000E6', - "agrave": '\U000000E0', - "amp": '\U00000026', - "aring": '\U000000E5', - "atilde": '\U000000E3', - "auml": '\U000000E4', - "brvbar": '\U000000A6', - "ccedil": '\U000000E7', - "cedil": '\U000000B8', - "cent": '\U000000A2', - "copy": '\U000000A9', - "curren": '\U000000A4', - "deg": '\U000000B0', - "divide": '\U000000F7', - "eacute": '\U000000E9', - "ecirc": '\U000000EA', - "egrave": '\U000000E8', - "eth": '\U000000F0', - "euml": '\U000000EB', - "frac12": '\U000000BD', - "frac14": '\U000000BC', - "frac34": '\U000000BE', - "gt": '\U0000003E', - "iacute": '\U000000ED', - "icirc": '\U000000EE', - "iexcl": '\U000000A1', - "igrave": '\U000000EC', - "iquest": '\U000000BF', - "iuml": '\U000000EF', - "laquo": '\U000000AB', - "lt": '\U0000003C', - "macr": '\U000000AF', - "micro": '\U000000B5', - "middot": '\U000000B7', - "nbsp": '\U000000A0', - "not": '\U000000AC', - "ntilde": '\U000000F1', - "oacute": '\U000000F3', - "ocirc": '\U000000F4', - "ograve": '\U000000F2', - "ordf": '\U000000AA', - "ordm": '\U000000BA', - "oslash": '\U000000F8', - "otilde": '\U000000F5', - "ouml": '\U000000F6', - "para": '\U000000B6', - "plusmn": '\U000000B1', - "pound": '\U000000A3', - "quot": '\U00000022', - "raquo": '\U000000BB', - "reg": '\U000000AE', - "sect": '\U000000A7', - "shy": '\U000000AD', - "sup1": '\U000000B9', - "sup2": '\U000000B2', - "sup3": '\U000000B3', - "szlig": '\U000000DF', - "thorn": '\U000000FE', - "times": '\U000000D7', - "uacute": '\U000000FA', - "ucirc": '\U000000FB', - "ugrave": '\U000000F9', - "uml": '\U000000A8', - "uuml": '\U000000FC', - "yacute": '\U000000FD', - "yen": '\U000000A5', - "yuml": '\U000000FF', -} - -// HTML entities that are two unicode codepoints. -var entity2 = map[string][2]rune{ - // TODO(nigeltao): Handle replacements that are wider than their names. - // "nLt;": {'\u226A', '\u20D2'}, - // "nGt;": {'\u226B', '\u20D2'}, - "NotEqualTilde;": {'\u2242', '\u0338'}, - "NotGreaterFullEqual;": {'\u2267', '\u0338'}, - "NotGreaterGreater;": {'\u226B', '\u0338'}, - "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'}, - "NotHumpDownHump;": {'\u224E', '\u0338'}, - "NotHumpEqual;": {'\u224F', '\u0338'}, - "NotLeftTriangleBar;": {'\u29CF', '\u0338'}, - "NotLessLess;": {'\u226A', '\u0338'}, - "NotLessSlantEqual;": {'\u2A7D', '\u0338'}, - "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'}, - "NotNestedLessLess;": {'\u2AA1', '\u0338'}, - "NotPrecedesEqual;": {'\u2AAF', '\u0338'}, - "NotRightTriangleBar;": {'\u29D0', '\u0338'}, - "NotSquareSubset;": {'\u228F', '\u0338'}, - "NotSquareSuperset;": {'\u2290', '\u0338'}, - "NotSubset;": {'\u2282', '\u20D2'}, - "NotSucceedsEqual;": {'\u2AB0', '\u0338'}, - "NotSucceedsTilde;": {'\u227F', '\u0338'}, - "NotSuperset;": {'\u2283', '\u20D2'}, - "ThickSpace;": {'\u205F', '\u200A'}, - "acE;": {'\u223E', '\u0333'}, - "bne;": {'\u003D', '\u20E5'}, - "bnequiv;": {'\u2261', '\u20E5'}, - "caps;": {'\u2229', '\uFE00'}, - "cups;": {'\u222A', '\uFE00'}, - "fjlig;": {'\u0066', '\u006A'}, - "gesl;": {'\u22DB', '\uFE00'}, - "gvertneqq;": {'\u2269', '\uFE00'}, - "gvnE;": {'\u2269', '\uFE00'}, - "lates;": {'\u2AAD', '\uFE00'}, - "lesg;": {'\u22DA', '\uFE00'}, - "lvertneqq;": {'\u2268', '\uFE00'}, - "lvnE;": {'\u2268', '\uFE00'}, - "nGg;": {'\u22D9', '\u0338'}, - "nGtv;": {'\u226B', '\u0338'}, - "nLl;": {'\u22D8', '\u0338'}, - "nLtv;": {'\u226A', '\u0338'}, - "nang;": {'\u2220', '\u20D2'}, - "napE;": {'\u2A70', '\u0338'}, - "napid;": {'\u224B', '\u0338'}, - "nbump;": {'\u224E', '\u0338'}, - "nbumpe;": {'\u224F', '\u0338'}, - "ncongdot;": {'\u2A6D', '\u0338'}, - "nedot;": {'\u2250', '\u0338'}, - "nesim;": {'\u2242', '\u0338'}, - "ngE;": {'\u2267', '\u0338'}, - "ngeqq;": {'\u2267', '\u0338'}, - "ngeqslant;": {'\u2A7E', '\u0338'}, - "nges;": {'\u2A7E', '\u0338'}, - "nlE;": {'\u2266', '\u0338'}, - "nleqq;": {'\u2266', '\u0338'}, - "nleqslant;": {'\u2A7D', '\u0338'}, - "nles;": {'\u2A7D', '\u0338'}, - "notinE;": {'\u22F9', '\u0338'}, - "notindot;": {'\u22F5', '\u0338'}, - "nparsl;": {'\u2AFD', '\u20E5'}, - "npart;": {'\u2202', '\u0338'}, - "npre;": {'\u2AAF', '\u0338'}, - "npreceq;": {'\u2AAF', '\u0338'}, - "nrarrc;": {'\u2933', '\u0338'}, - "nrarrw;": {'\u219D', '\u0338'}, - "nsce;": {'\u2AB0', '\u0338'}, - "nsubE;": {'\u2AC5', '\u0338'}, - "nsubset;": {'\u2282', '\u20D2'}, - "nsubseteqq;": {'\u2AC5', '\u0338'}, - "nsucceq;": {'\u2AB0', '\u0338'}, - "nsupE;": {'\u2AC6', '\u0338'}, - "nsupset;": {'\u2283', '\u20D2'}, - "nsupseteqq;": {'\u2AC6', '\u0338'}, - "nvap;": {'\u224D', '\u20D2'}, - "nvge;": {'\u2265', '\u20D2'}, - "nvgt;": {'\u003E', '\u20D2'}, - "nvle;": {'\u2264', '\u20D2'}, - "nvlt;": {'\u003C', '\u20D2'}, - "nvltrie;": {'\u22B4', '\u20D2'}, - "nvrtrie;": {'\u22B5', '\u20D2'}, - "nvsim;": {'\u223C', '\u20D2'}, - "race;": {'\u223D', '\u0331'}, - "smtes;": {'\u2AAC', '\uFE00'}, - "sqcaps;": {'\u2293', '\uFE00'}, - "sqcups;": {'\u2294', '\uFE00'}, - "varsubsetneq;": {'\u228A', '\uFE00'}, - "varsubsetneqq;": {'\u2ACB', '\uFE00'}, - "varsupsetneq;": {'\u228B', '\uFE00'}, - "varsupsetneqq;": {'\u2ACC', '\uFE00'}, - "vnsub;": {'\u2282', '\u20D2'}, - "vnsup;": {'\u2283', '\u20D2'}, - "vsubnE;": {'\u2ACB', '\uFE00'}, - "vsubne;": {'\u228A', '\uFE00'}, - "vsupnE;": {'\u2ACC', '\uFE00'}, - "vsupne;": {'\u228B', '\uFE00'}, -} diff --git a/libgo/go/exp/html/entity_test.go b/libgo/go/exp/html/entity_test.go deleted file mode 100644 index b53f866fa2d..00000000000 --- a/libgo/go/exp/html/entity_test.go +++ /dev/null @@ -1,29 +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. - -package html - -import ( - "testing" - "unicode/utf8" -) - -func TestEntityLength(t *testing.T) { - // We verify that the length of UTF-8 encoding of each value is <= 1 + len(key). - // The +1 comes from the leading "&". This property implies that the length of - // unescaped text is <= the length of escaped text. - for k, v := range entity { - if 1+len(k) < utf8.RuneLen(v) { - t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v)) - } - if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' { - t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon) - } - } - for k, v := range entity2 { - if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) { - t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1])) - } - } -} diff --git a/libgo/go/exp/html/escape.go b/libgo/go/exp/html/escape.go deleted file mode 100644 index 75bddff094f..00000000000 --- a/libgo/go/exp/html/escape.go +++ /dev/null @@ -1,258 +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. - -package html - -import ( - "bytes" - "strings" - "unicode/utf8" -) - -// These replacements permit compatibility with old numeric entities that -// assumed Windows-1252 encoding. -// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference -var replacementTable = [...]rune{ - '\u20AC', // First entry is what 0x80 should be replaced with. - '\u0081', - '\u201A', - '\u0192', - '\u201E', - '\u2026', - '\u2020', - '\u2021', - '\u02C6', - '\u2030', - '\u0160', - '\u2039', - '\u0152', - '\u008D', - '\u017D', - '\u008F', - '\u0090', - '\u2018', - '\u2019', - '\u201C', - '\u201D', - '\u2022', - '\u2013', - '\u2014', - '\u02DC', - '\u2122', - '\u0161', - '\u203A', - '\u0153', - '\u009D', - '\u017E', - '\u0178', // Last entry is 0x9F. - // 0x00->'\uFFFD' is handled programmatically. - // 0x0D->'\u000D' is a no-op. -} - -// unescapeEntity reads an entity like "<" from b[src:] and writes the -// corresponding "<" to b[dst:], returning the incremented dst and src cursors. -// Precondition: b[src] == '&' && dst <= src. -// attribute should be true if parsing an attribute value. -func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) { - // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference - - // i starts at 1 because we already know that s[0] == '&'. - i, s := 1, b[src:] - - if len(s) <= 1 { - b[dst] = b[src] - return dst + 1, src + 1 - } - - if s[i] == '#' { - if len(s) <= 3 { // We need to have at least "&#.". - b[dst] = b[src] - return dst + 1, src + 1 - } - i++ - c := s[i] - hex := false - if c == 'x' || c == 'X' { - hex = true - i++ - } - - x := '\x00' - for i < len(s) { - c = s[i] - i++ - if hex { - if '0' <= c && c <= '9' { - x = 16*x + rune(c) - '0' - continue - } else if 'a' <= c && c <= 'f' { - x = 16*x + rune(c) - 'a' + 10 - continue - } else if 'A' <= c && c <= 'F' { - x = 16*x + rune(c) - 'A' + 10 - continue - } - } else if '0' <= c && c <= '9' { - x = 10*x + rune(c) - '0' - continue - } - if c != ';' { - i-- - } - break - } - - if i <= 3 { // No characters matched. - b[dst] = b[src] - return dst + 1, src + 1 - } - - if 0x80 <= x && x <= 0x9F { - // Replace characters from Windows-1252 with UTF-8 equivalents. - x = replacementTable[x-0x80] - } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF { - // Replace invalid characters with the replacement character. - x = '\uFFFD' - } - - return dst + utf8.EncodeRune(b[dst:], x), src + i - } - - // Consume the maximum number of characters possible, with the - // consumed characters matching one of the named references. - - for i < len(s) { - c := s[i] - i++ - // Lower-cased characters are more common in entities, so we check for them first. - if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' { - continue - } - if c != ';' { - i-- - } - break - } - - entityName := string(s[1:i]) - if entityName == "" { - // No-op. - } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' { - // No-op. - } else if x := entity[entityName]; x != 0 { - return dst + utf8.EncodeRune(b[dst:], x), src + i - } else if x := entity2[entityName]; x[0] != 0 { - dst1 := dst + utf8.EncodeRune(b[dst:], x[0]) - return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i - } else if !attribute { - maxLen := len(entityName) - 1 - if maxLen > longestEntityWithoutSemicolon { - maxLen = longestEntityWithoutSemicolon - } - for j := maxLen; j > 1; j-- { - if x := entity[entityName[:j]]; x != 0 { - return dst + utf8.EncodeRune(b[dst:], x), src + j + 1 - } - } - } - - dst1, src1 = dst+i, src+i - copy(b[dst:dst1], b[src:src1]) - return dst1, src1 -} - -// unescape unescapes b's entities in-place, so that "a<b" becomes "a': - esc = ">" - case '"': - // """ is shorter than """. - esc = """ - case '\r': - esc = " " - default: - panic("unrecognized escape character") - } - s = s[i+1:] - if _, err := w.WriteString(esc); err != nil { - return err - } - i = strings.IndexAny(s, escapedChars) - } - _, err := w.WriteString(s) - return err -} - -// EscapeString escapes special characters like "<" to become "<". It -// escapes only five such characters: <, >, &, ' and ". -// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't -// always true. -func EscapeString(s string) string { - if strings.IndexAny(s, escapedChars) == -1 { - return s - } - var buf bytes.Buffer - escape(&buf, s) - return buf.String() -} - -// UnescapeString unescapes entities like "<" to become "<". It unescapes a -// larger range of entities than EscapeString escapes. For example, "á" -// unescapes to "á", as does "á" and "&xE1;". -// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't -// always true. -func UnescapeString(s string) string { - for _, c := range s { - if c == '&' { - return string(unescape([]byte(s), false)) - } - } - return s -} diff --git a/libgo/go/exp/html/foreign.go b/libgo/go/exp/html/foreign.go deleted file mode 100644 index d3b3844099b..00000000000 --- a/libgo/go/exp/html/foreign.go +++ /dev/null @@ -1,226 +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 html - -import ( - "strings" -) - -func adjustAttributeNames(aa []Attribute, nameMap map[string]string) { - for i := range aa { - if newName, ok := nameMap[aa[i].Key]; ok { - aa[i].Key = newName - } - } -} - -func adjustForeignAttributes(aa []Attribute) { - for i, a := range aa { - if a.Key == "" || a.Key[0] != 'x' { - continue - } - switch a.Key { - case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", - "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink": - j := strings.Index(a.Key, ":") - aa[i].Namespace = a.Key[:j] - aa[i].Key = a.Key[j+1:] - } - } -} - -func htmlIntegrationPoint(n *Node) bool { - if n.Type != ElementNode { - return false - } - switch n.Namespace { - case "math": - if n.Data == "annotation-xml" { - for _, a := range n.Attr { - if a.Key == "encoding" { - val := strings.ToLower(a.Val) - if val == "text/html" || val == "application/xhtml+xml" { - return true - } - } - } - } - case "svg": - switch n.Data { - case "desc", "foreignObject", "title": - return true - } - } - return false -} - -func mathMLTextIntegrationPoint(n *Node) bool { - if n.Namespace != "math" { - return false - } - switch n.Data { - case "mi", "mo", "mn", "ms", "mtext": - return true - } - return false -} - -// Section 12.2.5.5. -var breakout = map[string]bool{ - "b": true, - "big": true, - "blockquote": true, - "body": true, - "br": true, - "center": true, - "code": true, - "dd": true, - "div": true, - "dl": true, - "dt": true, - "em": true, - "embed": true, - "h1": true, - "h2": true, - "h3": true, - "h4": true, - "h5": true, - "h6": true, - "head": true, - "hr": true, - "i": true, - "img": true, - "li": true, - "listing": true, - "menu": true, - "meta": true, - "nobr": true, - "ol": true, - "p": true, - "pre": true, - "ruby": true, - "s": true, - "small": true, - "span": true, - "strong": true, - "strike": true, - "sub": true, - "sup": true, - "table": true, - "tt": true, - "u": true, - "ul": true, - "var": true, -} - -// Section 12.2.5.5. -var svgTagNameAdjustments = map[string]string{ - "altglyph": "altGlyph", - "altglyphdef": "altGlyphDef", - "altglyphitem": "altGlyphItem", - "animatecolor": "animateColor", - "animatemotion": "animateMotion", - "animatetransform": "animateTransform", - "clippath": "clipPath", - "feblend": "feBlend", - "fecolormatrix": "feColorMatrix", - "fecomponenttransfer": "feComponentTransfer", - "fecomposite": "feComposite", - "feconvolvematrix": "feConvolveMatrix", - "fediffuselighting": "feDiffuseLighting", - "fedisplacementmap": "feDisplacementMap", - "fedistantlight": "feDistantLight", - "feflood": "feFlood", - "fefunca": "feFuncA", - "fefuncb": "feFuncB", - "fefuncg": "feFuncG", - "fefuncr": "feFuncR", - "fegaussianblur": "feGaussianBlur", - "feimage": "feImage", - "femerge": "feMerge", - "femergenode": "feMergeNode", - "femorphology": "feMorphology", - "feoffset": "feOffset", - "fepointlight": "fePointLight", - "fespecularlighting": "feSpecularLighting", - "fespotlight": "feSpotLight", - "fetile": "feTile", - "feturbulence": "feTurbulence", - "foreignobject": "foreignObject", - "glyphref": "glyphRef", - "lineargradient": "linearGradient", - "radialgradient": "radialGradient", - "textpath": "textPath", -} - -// Section 12.2.5.1 -var mathMLAttributeAdjustments = map[string]string{ - "definitionurl": "definitionURL", -} - -var svgAttributeAdjustments = map[string]string{ - "attributename": "attributeName", - "attributetype": "attributeType", - "basefrequency": "baseFrequency", - "baseprofile": "baseProfile", - "calcmode": "calcMode", - "clippathunits": "clipPathUnits", - "contentscripttype": "contentScriptType", - "contentstyletype": "contentStyleType", - "diffuseconstant": "diffuseConstant", - "edgemode": "edgeMode", - "externalresourcesrequired": "externalResourcesRequired", - "filterres": "filterRes", - "filterunits": "filterUnits", - "glyphref": "glyphRef", - "gradienttransform": "gradientTransform", - "gradientunits": "gradientUnits", - "kernelmatrix": "kernelMatrix", - "kernelunitlength": "kernelUnitLength", - "keypoints": "keyPoints", - "keysplines": "keySplines", - "keytimes": "keyTimes", - "lengthadjust": "lengthAdjust", - "limitingconeangle": "limitingConeAngle", - "markerheight": "markerHeight", - "markerunits": "markerUnits", - "markerwidth": "markerWidth", - "maskcontentunits": "maskContentUnits", - "maskunits": "maskUnits", - "numoctaves": "numOctaves", - "pathlength": "pathLength", - "patterncontentunits": "patternContentUnits", - "patterntransform": "patternTransform", - "patternunits": "patternUnits", - "pointsatx": "pointsAtX", - "pointsaty": "pointsAtY", - "pointsatz": "pointsAtZ", - "preservealpha": "preserveAlpha", - "preserveaspectratio": "preserveAspectRatio", - "primitiveunits": "primitiveUnits", - "refx": "refX", - "refy": "refY", - "repeatcount": "repeatCount", - "repeatdur": "repeatDur", - "requiredextensions": "requiredExtensions", - "requiredfeatures": "requiredFeatures", - "specularconstant": "specularConstant", - "specularexponent": "specularExponent", - "spreadmethod": "spreadMethod", - "startoffset": "startOffset", - "stddeviation": "stdDeviation", - "stitchtiles": "stitchTiles", - "surfacescale": "surfaceScale", - "systemlanguage": "systemLanguage", - "tablevalues": "tableValues", - "targetx": "targetX", - "targety": "targetY", - "textlength": "textLength", - "viewbox": "viewBox", - "viewtarget": "viewTarget", - "xchannelselector": "xChannelSelector", - "ychannelselector": "yChannelSelector", - "zoomandpan": "zoomAndPan", -} diff --git a/libgo/go/exp/html/node.go b/libgo/go/exp/html/node.go deleted file mode 100644 index 01f8c42ce3a..00000000000 --- a/libgo/go/exp/html/node.go +++ /dev/null @@ -1,193 +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 html - -import ( - "exp/html/atom" -) - -// A NodeType is the type of a Node. -type NodeType uint32 - -const ( - ErrorNode NodeType = iota - TextNode - DocumentNode - ElementNode - CommentNode - DoctypeNode - scopeMarkerNode -) - -// Section 12.2.3.3 says "scope markers are inserted when entering applet -// elements, buttons, object elements, marquees, table cells, and table -// captions, and are used to prevent formatting from 'leaking'". -var scopeMarker = Node{Type: scopeMarkerNode} - -// A Node consists of a NodeType and some Data (tag name for element nodes, -// content for text) and are part of a tree of Nodes. Element nodes may also -// have a Namespace and contain a slice of Attributes. Data is unescaped, so -// that it looks like "a 0 { - return (*s)[i-1] - } - return nil -} - -// index returns the index of the top-most occurrence of n in the stack, or -1 -// if n is not present. -func (s *nodeStack) index(n *Node) int { - for i := len(*s) - 1; i >= 0; i-- { - if (*s)[i] == n { - return i - } - } - return -1 -} - -// insert inserts a node at the given index. -func (s *nodeStack) insert(i int, n *Node) { - (*s) = append(*s, nil) - copy((*s)[i+1:], (*s)[i:]) - (*s)[i] = n -} - -// remove removes a node from the stack. It is a no-op if n is not present. -func (s *nodeStack) remove(n *Node) { - i := s.index(n) - if i == -1 { - return - } - copy((*s)[i:], (*s)[i+1:]) - j := len(*s) - 1 - (*s)[j] = nil - *s = (*s)[:j] -} diff --git a/libgo/go/exp/html/node_test.go b/libgo/go/exp/html/node_test.go deleted file mode 100644 index 471102f3a22..00000000000 --- a/libgo/go/exp/html/node_test.go +++ /dev/null @@ -1,146 +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. - -package html - -import ( - "fmt" -) - -// checkTreeConsistency checks that a node and its descendants are all -// consistent in their parent/child/sibling relationships. -func checkTreeConsistency(n *Node) error { - return checkTreeConsistency1(n, 0) -} - -func checkTreeConsistency1(n *Node, depth int) error { - if depth == 1e4 { - return fmt.Errorf("html: tree looks like it contains a cycle") - } - if err := checkNodeConsistency(n); err != nil { - return err - } - for c := n.FirstChild; c != nil; c = c.NextSibling { - if err := checkTreeConsistency1(c, depth+1); err != nil { - return err - } - } - return nil -} - -// checkNodeConsistency checks that a node's parent/child/sibling relationships -// are consistent. -func checkNodeConsistency(n *Node) error { - if n == nil { - return nil - } - - nParent := 0 - for p := n.Parent; p != nil; p = p.Parent { - nParent++ - if nParent == 1e4 { - return fmt.Errorf("html: parent list looks like an infinite loop") - } - } - - nForward := 0 - for c := n.FirstChild; c != nil; c = c.NextSibling { - nForward++ - if nForward == 1e6 { - return fmt.Errorf("html: forward list of children looks like an infinite loop") - } - if c.Parent != n { - return fmt.Errorf("html: inconsistent child/parent relationship") - } - } - - nBackward := 0 - for c := n.LastChild; c != nil; c = c.PrevSibling { - nBackward++ - if nBackward == 1e6 { - return fmt.Errorf("html: backward list of children looks like an infinite loop") - } - if c.Parent != n { - return fmt.Errorf("html: inconsistent child/parent relationship") - } - } - - if n.Parent != nil { - if n.Parent == n { - return fmt.Errorf("html: inconsistent parent relationship") - } - if n.Parent == n.FirstChild { - return fmt.Errorf("html: inconsistent parent/first relationship") - } - if n.Parent == n.LastChild { - return fmt.Errorf("html: inconsistent parent/last relationship") - } - if n.Parent == n.PrevSibling { - return fmt.Errorf("html: inconsistent parent/prev relationship") - } - if n.Parent == n.NextSibling { - return fmt.Errorf("html: inconsistent parent/next relationship") - } - - parentHasNAsAChild := false - for c := n.Parent.FirstChild; c != nil; c = c.NextSibling { - if c == n { - parentHasNAsAChild = true - break - } - } - if !parentHasNAsAChild { - return fmt.Errorf("html: inconsistent parent/child relationship") - } - } - - if n.PrevSibling != nil && n.PrevSibling.NextSibling != n { - return fmt.Errorf("html: inconsistent prev/next relationship") - } - if n.NextSibling != nil && n.NextSibling.PrevSibling != n { - return fmt.Errorf("html: inconsistent next/prev relationship") - } - - if (n.FirstChild == nil) != (n.LastChild == nil) { - return fmt.Errorf("html: inconsistent first/last relationship") - } - if n.FirstChild != nil && n.FirstChild == n.LastChild { - // We have a sole child. - if n.FirstChild.PrevSibling != nil || n.FirstChild.NextSibling != nil { - return fmt.Errorf("html: inconsistent sole child's sibling relationship") - } - } - - seen := map[*Node]bool{} - - var last *Node - for c := n.FirstChild; c != nil; c = c.NextSibling { - if seen[c] { - return fmt.Errorf("html: inconsistent repeated child") - } - seen[c] = true - last = c - } - if last != n.LastChild { - return fmt.Errorf("html: inconsistent last relationship") - } - - var first *Node - for c := n.LastChild; c != nil; c = c.PrevSibling { - if !seen[c] { - return fmt.Errorf("html: inconsistent missing child") - } - delete(seen, c) - first = c - } - if first != n.FirstChild { - return fmt.Errorf("html: inconsistent first relationship") - } - - if len(seen) != 0 { - return fmt.Errorf("html: inconsistent forwards/backwards child list") - } - - return nil -} diff --git a/libgo/go/exp/html/parse.go b/libgo/go/exp/html/parse.go deleted file mode 100644 index 0ff15746f21..00000000000 --- a/libgo/go/exp/html/parse.go +++ /dev/null @@ -1,2091 +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. - -package html - -import ( - "errors" - a "exp/html/atom" - "fmt" - "io" - "strings" -) - -// A parser implements the HTML5 parsing algorithm: -// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#tree-construction -type parser struct { - // tokenizer provides the tokens for the parser. - tokenizer *Tokenizer - // tok is the most recently read token. - tok Token - // Self-closing tags like
are treated as start tags, except that - // hasSelfClosingToken is set while they are being processed. - hasSelfClosingToken bool - // doc is the document root element. - doc *Node - // The stack of open elements (section 12.2.3.2) and active formatting - // elements (section 12.2.3.3). - oe, afe nodeStack - // Element pointers (section 12.2.3.4). - head, form *Node - // Other parsing state flags (section 12.2.3.5). - scripting, framesetOK bool - // im is the current insertion mode. - im insertionMode - // originalIM is the insertion mode to go back to after completing a text - // or inTableText insertion mode. - originalIM insertionMode - // fosterParenting is whether new elements should be inserted according to - // the foster parenting rules (section 12.2.5.3). - fosterParenting bool - // quirks is whether the parser is operating in "quirks mode." - quirks bool - // fragment is whether the parser is parsing an HTML fragment. - fragment bool - // context is the context element when parsing an HTML fragment - // (section 12.4). - context *Node -} - -func (p *parser) top() *Node { - if n := p.oe.top(); n != nil { - return n - } - return p.doc -} - -// Stop tags for use in popUntil. These come from section 12.2.3.2. -var ( - defaultScopeStopTags = map[string][]a.Atom{ - "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object}, - "math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext}, - "svg": {a.Desc, a.ForeignObject, a.Title}, - } -) - -type scope int - -const ( - defaultScope scope = iota - listItemScope - buttonScope - tableScope - tableRowScope - tableBodyScope - selectScope -) - -// popUntil pops the stack of open elements at the highest element whose tag -// is in matchTags, provided there is no higher element in the scope's stop -// tags (as defined in section 12.2.3.2). It returns whether or not there was -// such an element. If there was not, popUntil leaves the stack unchanged. -// -// For example, the set of stop tags for table scope is: "html", "table". If -// the stack was: -// ["html", "body", "font", "table", "b", "i", "u"] -// then popUntil(tableScope, "font") would return false, but -// popUntil(tableScope, "i") would return true and the stack would become: -// ["html", "body", "font", "table", "b"] -// -// If an element's tag is in both the stop tags and matchTags, then the stack -// will be popped and the function returns true (provided, of course, there was -// no higher element in the stack that was also in the stop tags). For example, -// popUntil(tableScope, "table") returns true and leaves: -// ["html", "body", "font"] -func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool { - if i := p.indexOfElementInScope(s, matchTags...); i != -1 { - p.oe = p.oe[:i] - return true - } - return false -} - -// indexOfElementInScope returns the index in p.oe of the highest element whose -// tag is in matchTags that is in scope. If no matching element is in scope, it -// returns -1. -func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int { - for i := len(p.oe) - 1; i >= 0; i-- { - tagAtom := p.oe[i].DataAtom - if p.oe[i].Namespace == "" { - for _, t := range matchTags { - if t == tagAtom { - return i - } - } - switch s { - case defaultScope: - // No-op. - case listItemScope: - if tagAtom == a.Ol || tagAtom == a.Ul { - return -1 - } - case buttonScope: - if tagAtom == a.Button { - return -1 - } - case tableScope: - if tagAtom == a.Html || tagAtom == a.Table { - return -1 - } - case selectScope: - if tagAtom != a.Optgroup && tagAtom != a.Option { - return -1 - } - default: - panic("unreachable") - } - } - switch s { - case defaultScope, listItemScope, buttonScope: - for _, t := range defaultScopeStopTags[p.oe[i].Namespace] { - if t == tagAtom { - return -1 - } - } - } - } - return -1 -} - -// elementInScope is like popUntil, except that it doesn't modify the stack of -// open elements. -func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool { - return p.indexOfElementInScope(s, matchTags...) != -1 -} - -// clearStackToContext pops elements off the stack of open elements until a -// scope-defined element is found. -func (p *parser) clearStackToContext(s scope) { - for i := len(p.oe) - 1; i >= 0; i-- { - tagAtom := p.oe[i].DataAtom - switch s { - case tableScope: - if tagAtom == a.Html || tagAtom == a.Table { - p.oe = p.oe[:i+1] - return - } - case tableRowScope: - if tagAtom == a.Html || tagAtom == a.Tr { - p.oe = p.oe[:i+1] - return - } - case tableBodyScope: - if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead { - p.oe = p.oe[:i+1] - return - } - default: - panic("unreachable") - } - } -} - -// generateImpliedEndTags pops nodes off the stack of open elements as long as -// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt. -// If exceptions are specified, nodes with that name will not be popped off. -func (p *parser) generateImpliedEndTags(exceptions ...string) { - var i int -loop: - for i = len(p.oe) - 1; i >= 0; i-- { - n := p.oe[i] - if n.Type == ElementNode { - switch n.DataAtom { - case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt: - for _, except := range exceptions { - if n.Data == except { - break loop - } - } - continue - } - } - break - } - - p.oe = p.oe[:i+1] -} - -// addChild adds a child node n to the top element, and pushes n onto the stack -// of open elements if it is an element node. -func (p *parser) addChild(n *Node) { - if p.shouldFosterParent() { - p.fosterParent(n) - } else { - p.top().AppendChild(n) - } - - if n.Type == ElementNode { - p.oe = append(p.oe, n) - } -} - -// shouldFosterParent returns whether the next node to be added should be -// foster parented. -func (p *parser) shouldFosterParent() bool { - if p.fosterParenting { - switch p.top().DataAtom { - case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr: - return true - } - } - return false -} - -// fosterParent adds a child node according to the foster parenting rules. -// Section 12.2.5.3, "foster parenting". -func (p *parser) fosterParent(n *Node) { - var table, parent, prev *Node - var i int - for i = len(p.oe) - 1; i >= 0; i-- { - if p.oe[i].DataAtom == a.Table { - table = p.oe[i] - break - } - } - - if table == nil { - // The foster parent is the html element. - parent = p.oe[0] - } else { - parent = table.Parent - } - if parent == nil { - parent = p.oe[i-1] - } - - if table != nil { - prev = table.PrevSibling - } else { - prev = parent.LastChild - } - if prev != nil && prev.Type == TextNode && n.Type == TextNode { - prev.Data += n.Data - return - } - - parent.InsertBefore(n, table) -} - -// addText adds text to the preceding node if it is a text node, or else it -// calls addChild with a new text node. -func (p *parser) addText(text string) { - if text == "" { - return - } - - if p.shouldFosterParent() { - p.fosterParent(&Node{ - Type: TextNode, - Data: text, - }) - return - } - - t := p.top() - if n := t.LastChild; n != nil && n.Type == TextNode { - n.Data += text - return - } - p.addChild(&Node{ - Type: TextNode, - Data: text, - }) -} - -// addElement adds a child element based on the current token. -func (p *parser) addElement() { - p.addChild(&Node{ - Type: ElementNode, - DataAtom: p.tok.DataAtom, - Data: p.tok.Data, - Attr: p.tok.Attr, - }) -} - -// Section 12.2.3.3. -func (p *parser) addFormattingElement() { - tagAtom, attr := p.tok.DataAtom, p.tok.Attr - p.addElement() - - // Implement the Noah's Ark clause, but with three per family instead of two. - identicalElements := 0 -findIdenticalElements: - for i := len(p.afe) - 1; i >= 0; i-- { - n := p.afe[i] - if n.Type == scopeMarkerNode { - break - } - if n.Type != ElementNode { - continue - } - if n.Namespace != "" { - continue - } - if n.DataAtom != tagAtom { - continue - } - if len(n.Attr) != len(attr) { - continue - } - compareAttributes: - for _, t0 := range n.Attr { - for _, t1 := range attr { - if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val { - // Found a match for this attribute, continue with the next attribute. - continue compareAttributes - } - } - // If we get here, there is no attribute that matches a. - // Therefore the element is not identical to the new one. - continue findIdenticalElements - } - - identicalElements++ - if identicalElements >= 3 { - p.afe.remove(n) - } - } - - p.afe = append(p.afe, p.top()) -} - -// Section 12.2.3.3. -func (p *parser) clearActiveFormattingElements() { - for { - n := p.afe.pop() - if len(p.afe) == 0 || n.Type == scopeMarkerNode { - return - } - } -} - -// Section 12.2.3.3. -func (p *parser) reconstructActiveFormattingElements() { - n := p.afe.top() - if n == nil { - return - } - if n.Type == scopeMarkerNode || p.oe.index(n) != -1 { - return - } - i := len(p.afe) - 1 - for n.Type != scopeMarkerNode && p.oe.index(n) == -1 { - if i == 0 { - i = -1 - break - } - i-- - n = p.afe[i] - } - for { - i++ - clone := p.afe[i].clone() - p.addChild(clone) - p.afe[i] = clone - if i == len(p.afe)-1 { - break - } - } -} - -// Section 12.2.4. -func (p *parser) acknowledgeSelfClosingTag() { - p.hasSelfClosingToken = false -} - -// An insertion mode (section 12.2.3.1) is the state transition function from -// a particular state in the HTML5 parser's state machine. It updates the -// parser's fields depending on parser.tok (where ErrorToken means EOF). -// It returns whether the token was consumed. -type insertionMode func(*parser) bool - -// setOriginalIM sets the insertion mode to return to after completing a text or -// inTableText insertion mode. -// Section 12.2.3.1, "using the rules for". -func (p *parser) setOriginalIM() { - if p.originalIM != nil { - panic("html: bad parser state: originalIM was set twice") - } - p.originalIM = p.im -} - -// Section 12.2.3.1, "reset the insertion mode". -func (p *parser) resetInsertionMode() { - for i := len(p.oe) - 1; i >= 0; i-- { - n := p.oe[i] - if i == 0 && p.context != nil { - n = p.context - } - - switch n.DataAtom { - case a.Select: - p.im = inSelectIM - case a.Td, a.Th: - p.im = inCellIM - case a.Tr: - p.im = inRowIM - case a.Tbody, a.Thead, a.Tfoot: - p.im = inTableBodyIM - case a.Caption: - p.im = inCaptionIM - case a.Colgroup: - p.im = inColumnGroupIM - case a.Table: - p.im = inTableIM - case a.Head: - p.im = inBodyIM - case a.Body: - p.im = inBodyIM - case a.Frameset: - p.im = inFramesetIM - case a.Html: - p.im = beforeHeadIM - default: - continue - } - return - } - p.im = inBodyIM -} - -const whitespace = " \t\r\n\f" - -// Section 12.2.5.4.1. -func initialIM(p *parser) bool { - switch p.tok.Type { - case TextToken: - p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace) - if len(p.tok.Data) == 0 { - // It was all whitespace, so ignore it. - return true - } - case CommentToken: - p.doc.AppendChild(&Node{ - Type: CommentNode, - Data: p.tok.Data, - }) - return true - case DoctypeToken: - n, quirks := parseDoctype(p.tok.Data) - p.doc.AppendChild(n) - p.quirks = quirks - p.im = beforeHTMLIM - return true - } - p.quirks = true - p.im = beforeHTMLIM - return false -} - -// Section 12.2.5.4.2. -func beforeHTMLIM(p *parser) bool { - switch p.tok.Type { - case DoctypeToken: - // Ignore the token. - return true - case TextToken: - p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace) - if len(p.tok.Data) == 0 { - // It was all whitespace, so ignore it. - return true - } - case StartTagToken: - if p.tok.DataAtom == a.Html { - p.addElement() - p.im = beforeHeadIM - return true - } - case EndTagToken: - switch p.tok.DataAtom { - case a.Head, a.Body, a.Html, a.Br: - p.parseImpliedToken(StartTagToken, a.Html, a.Html.String()) - return false - default: - // Ignore the token. - return true - } - case CommentToken: - p.doc.AppendChild(&Node{ - Type: CommentNode, - Data: p.tok.Data, - }) - return true - } - p.parseImpliedToken(StartTagToken, a.Html, a.Html.String()) - return false -} - -// Section 12.2.5.4.3. -func beforeHeadIM(p *parser) bool { - switch p.tok.Type { - case TextToken: - p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace) - if len(p.tok.Data) == 0 { - // It was all whitespace, so ignore it. - return true - } - case StartTagToken: - switch p.tok.DataAtom { - case a.Head: - p.addElement() - p.head = p.top() - p.im = inHeadIM - return true - case a.Html: - return inBodyIM(p) - } - case EndTagToken: - switch p.tok.DataAtom { - case a.Head, a.Body, a.Html, a.Br: - p.parseImpliedToken(StartTagToken, a.Head, a.Head.String()) - return false - default: - // Ignore the token. - return true - } - case CommentToken: - p.addChild(&Node{ - Type: CommentNode, - Data: p.tok.Data, - }) - return true - case DoctypeToken: - // Ignore the token. - return true - } - - p.parseImpliedToken(StartTagToken, a.Head, a.Head.String()) - return false -} - -// Section 12.2.5.4.4. -func inHeadIM(p *parser) bool { - switch p.tok.Type { - case TextToken: - s := strings.TrimLeft(p.tok.Data, whitespace) - if len(s) < len(p.tok.Data) { - // Add the initial whitespace to the current node. - p.addText(p.tok.Data[:len(p.tok.Data)-len(s)]) - if s == "" { - return true - } - p.tok.Data = s - } - case StartTagToken: - switch p.tok.DataAtom { - case a.Html: - return inBodyIM(p) - case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta: - p.addElement() - p.oe.pop() - p.acknowledgeSelfClosingTag() - return true - case a.Script, a.Title, a.Noscript, a.Noframes, a.Style: - p.addElement() - p.setOriginalIM() - p.im = textIM - return true - case a.Head: - // Ignore the token. - return true - } - case EndTagToken: - switch p.tok.DataAtom { - case a.Head: - n := p.oe.pop() - if n.DataAtom != a.Head { - panic("html: bad parser state: element not found, in the in-head insertion mode") - } - p.im = afterHeadIM - return true - case a.Body, a.Html, a.Br: - p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) - return false - default: - // Ignore the token. - return true - } - case CommentToken: - p.addChild(&Node{ - Type: CommentNode, - Data: p.tok.Data, - }) - return true - case DoctypeToken: - // Ignore the token. - return true - } - - p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) - return false -} - -// Section 12.2.5.4.6. -func afterHeadIM(p *parser) bool { - switch p.tok.Type { - case TextToken: - s := strings.TrimLeft(p.tok.Data, whitespace) - if len(s) < len(p.tok.Data) { - // Add the initial whitespace to the current node. - p.addText(p.tok.Data[:len(p.tok.Data)-len(s)]) - if s == "" { - return true - } - p.tok.Data = s - } - case StartTagToken: - switch p.tok.DataAtom { - case a.Html: - return inBodyIM(p) - case a.Body: - p.addElement() - p.framesetOK = false - p.im = inBodyIM - return true - case a.Frameset: - p.addElement() - p.im = inFramesetIM - return true - case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: - p.oe = append(p.oe, p.head) - defer p.oe.remove(p.head) - return inHeadIM(p) - case a.Head: - // Ignore the token. - return true - } - case EndTagToken: - switch p.tok.DataAtom { - case a.Body, a.Html, a.Br: - // Drop down to creating an implied tag. - default: - // Ignore the token. - return true - } - case CommentToken: - p.addChild(&Node{ - Type: CommentNode, - Data: p.tok.Data, - }) - return true - case DoctypeToken: - // Ignore the token. - return true - } - - p.parseImpliedToken(StartTagToken, a.Body, a.Body.String()) - p.framesetOK = true - return false -} - -// copyAttributes copies attributes of src not found on dst to dst. -func copyAttributes(dst *Node, src Token) { - if len(src.Attr) == 0 { - return - } - attr := map[string]string{} - for _, t := range dst.Attr { - attr[t.Key] = t.Val - } - for _, t := range src.Attr { - if _, ok := attr[t.Key]; !ok { - dst.Attr = append(dst.Attr, t) - attr[t.Key] = t.Val - } - } -} - -// Section 12.2.5.4.7. -func inBodyIM(p *parser) bool { - switch p.tok.Type { - case TextToken: - d := p.tok.Data - switch n := p.oe.top(); n.DataAtom { - case a.Pre, a.Listing: - if n.FirstChild == nil { - // Ignore a newline at the start of a
 block.
-				if d != "" && d[0] == '\r' {
-					d = d[1:]
-				}
-				if d != "" && d[0] == '\n' {
-					d = d[1:]
-				}
-			}
-		}
-		d = strings.Replace(d, "\x00", "", -1)
-		if d == "" {
-			return true
-		}
-		p.reconstructActiveFormattingElements()
-		p.addText(d)
-		if p.framesetOK && strings.TrimLeft(d, whitespace) != "" {
-			// There were non-whitespace characters inserted.
-			p.framesetOK = false
-		}
-	case StartTagToken:
-		switch p.tok.DataAtom {
-		case a.Html:
-			copyAttributes(p.oe[0], p.tok)
-		case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
-			return inHeadIM(p)
-		case a.Body:
-			if len(p.oe) >= 2 {
-				body := p.oe[1]
-				if body.Type == ElementNode && body.DataAtom == a.Body {
-					p.framesetOK = false
-					copyAttributes(body, p.tok)
-				}
-			}
-		case a.Frameset:
-			if !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {
-				// Ignore the token.
-				return true
-			}
-			body := p.oe[1]
-			if body.Parent != nil {
-				body.Parent.RemoveChild(body)
-			}
-			p.oe = p.oe[:1]
-			p.addElement()
-			p.im = inFramesetIM
-			return true
-		case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
-			p.popUntil(buttonScope, a.P)
-			p.addElement()
-		case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
-			p.popUntil(buttonScope, a.P)
-			switch n := p.top(); n.DataAtom {
-			case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
-				p.oe.pop()
-			}
-			p.addElement()
-		case a.Pre, a.Listing:
-			p.popUntil(buttonScope, a.P)
-			p.addElement()
-			// The newline, if any, will be dealt with by the TextToken case.
-			p.framesetOK = false
-		case a.Form:
-			if p.form == nil {
-				p.popUntil(buttonScope, a.P)
-				p.addElement()
-				p.form = p.top()
-			}
-		case a.Li:
-			p.framesetOK = false
-			for i := len(p.oe) - 1; i >= 0; i-- {
-				node := p.oe[i]
-				switch node.DataAtom {
-				case a.Li:
-					p.oe = p.oe[:i]
-				case a.Address, a.Div, a.P:
-					continue
-				default:
-					if !isSpecialElement(node) {
-						continue
-					}
-				}
-				break
-			}
-			p.popUntil(buttonScope, a.P)
-			p.addElement()
-		case a.Dd, a.Dt:
-			p.framesetOK = false
-			for i := len(p.oe) - 1; i >= 0; i-- {
-				node := p.oe[i]
-				switch node.DataAtom {
-				case a.Dd, a.Dt:
-					p.oe = p.oe[:i]
-				case a.Address, a.Div, a.P:
-					continue
-				default:
-					if !isSpecialElement(node) {
-						continue
-					}
-				}
-				break
-			}
-			p.popUntil(buttonScope, a.P)
-			p.addElement()
-		case a.Plaintext:
-			p.popUntil(buttonScope, a.P)
-			p.addElement()
-		case a.Button:
-			p.popUntil(defaultScope, a.Button)
-			p.reconstructActiveFormattingElements()
-			p.addElement()
-			p.framesetOK = false
-		case a.A:
-			for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
-				if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
-					p.inBodyEndTagFormatting(a.A)
-					p.oe.remove(n)
-					p.afe.remove(n)
-					break
-				}
-			}
-			p.reconstructActiveFormattingElements()
-			p.addFormattingElement()
-		case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
-			p.reconstructActiveFormattingElements()
-			p.addFormattingElement()
-		case a.Nobr:
-			p.reconstructActiveFormattingElements()
-			if p.elementInScope(defaultScope, a.Nobr) {
-				p.inBodyEndTagFormatting(a.Nobr)
-				p.reconstructActiveFormattingElements()
-			}
-			p.addFormattingElement()
-		case a.Applet, a.Marquee, a.Object:
-			p.reconstructActiveFormattingElements()
-			p.addElement()
-			p.afe = append(p.afe, &scopeMarker)
-			p.framesetOK = false
-		case a.Table:
-			if !p.quirks {
-				p.popUntil(buttonScope, a.P)
-			}
-			p.addElement()
-			p.framesetOK = false
-			p.im = inTableIM
-			return true
-		case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
-			p.reconstructActiveFormattingElements()
-			p.addElement()
-			p.oe.pop()
-			p.acknowledgeSelfClosingTag()
-			if p.tok.DataAtom == a.Input {
-				for _, t := range p.tok.Attr {
-					if t.Key == "type" {
-						if strings.ToLower(t.Val) == "hidden" {
-							// Skip setting framesetOK = false
-							return true
-						}
-					}
-				}
-			}
-			p.framesetOK = false
-		case a.Param, a.Source, a.Track:
-			p.addElement()
-			p.oe.pop()
-			p.acknowledgeSelfClosingTag()
-		case a.Hr:
-			p.popUntil(buttonScope, a.P)
-			p.addElement()
-			p.oe.pop()
-			p.acknowledgeSelfClosingTag()
-			p.framesetOK = false
-		case a.Image:
-			p.tok.DataAtom = a.Img
-			p.tok.Data = a.Img.String()
-			return false
-		case a.Isindex:
-			if p.form != nil {
-				// Ignore the token.
-				return true
-			}
-			action := ""
-			prompt := "This is a searchable index. Enter search keywords: "
-			attr := []Attribute{{Key: "name", Val: "isindex"}}
-			for _, t := range p.tok.Attr {
-				switch t.Key {
-				case "action":
-					action = t.Val
-				case "name":
-					// Ignore the attribute.
-				case "prompt":
-					prompt = t.Val
-				default:
-					attr = append(attr, t)
-				}
-			}
-			p.acknowledgeSelfClosingTag()
-			p.popUntil(buttonScope, a.P)
-			p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
-			if action != "" {
-				p.form.Attr = []Attribute{{Key: "action", Val: action}}
-			}
-			p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
-			p.parseImpliedToken(StartTagToken, a.Label, a.Label.String())
-			p.addText(prompt)
-			p.addChild(&Node{
-				Type:     ElementNode,
-				DataAtom: a.Input,
-				Data:     a.Input.String(),
-				Attr:     attr,
-			})
-			p.oe.pop()
-			p.parseImpliedToken(EndTagToken, a.Label, a.Label.String())
-			p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
-			p.parseImpliedToken(EndTagToken, a.Form, a.Form.String())
-		case a.Textarea:
-			p.addElement()
-			p.setOriginalIM()
-			p.framesetOK = false
-			p.im = textIM
-		case a.Xmp:
-			p.popUntil(buttonScope, a.P)
-			p.reconstructActiveFormattingElements()
-			p.framesetOK = false
-			p.addElement()
-			p.setOriginalIM()
-			p.im = textIM
-		case a.Iframe:
-			p.framesetOK = false
-			p.addElement()
-			p.setOriginalIM()
-			p.im = textIM
-		case a.Noembed, a.Noscript:
-			p.addElement()
-			p.setOriginalIM()
-			p.im = textIM
-		case a.Select:
-			p.reconstructActiveFormattingElements()
-			p.addElement()
-			p.framesetOK = false
-			p.im = inSelectIM
-			return true
-		case a.Optgroup, a.Option:
-			if p.top().DataAtom == a.Option {
-				p.oe.pop()
-			}
-			p.reconstructActiveFormattingElements()
-			p.addElement()
-		case a.Rp, a.Rt:
-			if p.elementInScope(defaultScope, a.Ruby) {
-				p.generateImpliedEndTags()
-			}
-			p.addElement()
-		case a.Math, a.Svg:
-			p.reconstructActiveFormattingElements()
-			if p.tok.DataAtom == a.Math {
-				adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
-			} else {
-				adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
-			}
-			adjustForeignAttributes(p.tok.Attr)
-			p.addElement()
-			p.top().Namespace = p.tok.Data
-			if p.hasSelfClosingToken {
-				p.oe.pop()
-				p.acknowledgeSelfClosingTag()
-			}
-			return true
-		case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
-			// Ignore the token.
-		default:
-			p.reconstructActiveFormattingElements()
-			p.addElement()
-		}
-	case EndTagToken:
-		switch p.tok.DataAtom {
-		case a.Body:
-			if p.elementInScope(defaultScope, a.Body) {
-				p.im = afterBodyIM
-			}
-		case a.Html:
-			if p.elementInScope(defaultScope, a.Body) {
-				p.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
-				return false
-			}
-			return true
-		case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
-			p.popUntil(defaultScope, p.tok.DataAtom)
-		case a.Form:
-			node := p.form
-			p.form = nil
-			i := p.indexOfElementInScope(defaultScope, a.Form)
-			if node == nil || i == -1 || p.oe[i] != node {
-				// Ignore the token.
-				return true
-			}
-			p.generateImpliedEndTags()
-			p.oe.remove(node)
-		case a.P:
-			if !p.elementInScope(buttonScope, a.P) {
-				p.parseImpliedToken(StartTagToken, a.P, a.P.String())
-			}
-			p.popUntil(buttonScope, a.P)
-		case a.Li:
-			p.popUntil(listItemScope, a.Li)
-		case a.Dd, a.Dt:
-			p.popUntil(defaultScope, p.tok.DataAtom)
-		case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
-			p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
-		case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
-			p.inBodyEndTagFormatting(p.tok.DataAtom)
-		case a.Applet, a.Marquee, a.Object:
-			if p.popUntil(defaultScope, p.tok.DataAtom) {
-				p.clearActiveFormattingElements()
-			}
-		case a.Br:
-			p.tok.Type = StartTagToken
-			return false
-		default:
-			p.inBodyEndTagOther(p.tok.DataAtom)
-		}
-	case CommentToken:
-		p.addChild(&Node{
-			Type: CommentNode,
-			Data: p.tok.Data,
-		})
-	}
-
-	return true
-}
-
-func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
-	// This is the "adoption agency" algorithm, described at
-	// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#adoptionAgency
-
-	// TODO: this is a fairly literal line-by-line translation of that algorithm.
-	// Once the code successfully parses the comprehensive test suite, we should
-	// refactor this code to be more idiomatic.
-
-	// Steps 1-3. The outer loop.
-	for i := 0; i < 8; i++ {
-		// Step 4. Find the formatting element.
-		var formattingElement *Node
-		for j := len(p.afe) - 1; j >= 0; j-- {
-			if p.afe[j].Type == scopeMarkerNode {
-				break
-			}
-			if p.afe[j].DataAtom == tagAtom {
-				formattingElement = p.afe[j]
-				break
-			}
-		}
-		if formattingElement == nil {
-			p.inBodyEndTagOther(tagAtom)
-			return
-		}
-		feIndex := p.oe.index(formattingElement)
-		if feIndex == -1 {
-			p.afe.remove(formattingElement)
-			return
-		}
-		if !p.elementInScope(defaultScope, tagAtom) {
-			// Ignore the tag.
-			return
-		}
-
-		// Steps 5-6. Find the furthest block.
-		var furthestBlock *Node
-		for _, e := range p.oe[feIndex:] {
-			if isSpecialElement(e) {
-				furthestBlock = e
-				break
-			}
-		}
-		if furthestBlock == nil {
-			e := p.oe.pop()
-			for e != formattingElement {
-				e = p.oe.pop()
-			}
-			p.afe.remove(e)
-			return
-		}
-
-		// Steps 7-8. Find the common ancestor and bookmark node.
-		commonAncestor := p.oe[feIndex-1]
-		bookmark := p.afe.index(formattingElement)
-
-		// Step 9. The inner loop. Find the lastNode to reparent.
-		lastNode := furthestBlock
-		node := furthestBlock
-		x := p.oe.index(node)
-		// Steps 9.1-9.3.
-		for j := 0; j < 3; j++ {
-			// Step 9.4.
-			x--
-			node = p.oe[x]
-			// Step 9.5.
-			if p.afe.index(node) == -1 {
-				p.oe.remove(node)
-				continue
-			}
-			// Step 9.6.
-			if node == formattingElement {
-				break
-			}
-			// Step 9.7.
-			clone := node.clone()
-			p.afe[p.afe.index(node)] = clone
-			p.oe[p.oe.index(node)] = clone
-			node = clone
-			// Step 9.8.
-			if lastNode == furthestBlock {
-				bookmark = p.afe.index(node) + 1
-			}
-			// Step 9.9.
-			if lastNode.Parent != nil {
-				lastNode.Parent.RemoveChild(lastNode)
-			}
-			node.AppendChild(lastNode)
-			// Step 9.10.
-			lastNode = node
-		}
-
-		// Step 10. Reparent lastNode to the common ancestor,
-		// or for misnested table nodes, to the foster parent.
-		if lastNode.Parent != nil {
-			lastNode.Parent.RemoveChild(lastNode)
-		}
-		switch commonAncestor.DataAtom {
-		case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
-			p.fosterParent(lastNode)
-		default:
-			commonAncestor.AppendChild(lastNode)
-		}
-
-		// Steps 11-13. Reparent nodes from the furthest block's children
-		// to a clone of the formatting element.
-		clone := formattingElement.clone()
-		reparentChildren(clone, furthestBlock)
-		furthestBlock.AppendChild(clone)
-
-		// Step 14. Fix up the list of active formatting elements.
-		if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
-			// Move the bookmark with the rest of the list.
-			bookmark--
-		}
-		p.afe.remove(formattingElement)
-		p.afe.insert(bookmark, clone)
-
-		// Step 15. Fix up the stack of open elements.
-		p.oe.remove(formattingElement)
-		p.oe.insert(p.oe.index(furthestBlock)+1, clone)
-	}
-}
-
-// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
-func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
-	for i := len(p.oe) - 1; i >= 0; i-- {
-		if p.oe[i].DataAtom == tagAtom {
-			p.oe = p.oe[:i]
-			break
-		}
-		if isSpecialElement(p.oe[i]) {
-			break
-		}
-	}
-}
-
-// Section 12.2.5.4.8.
-func textIM(p *parser) bool {
-	switch p.tok.Type {
-	case ErrorToken:
-		p.oe.pop()
-	case TextToken:
-		d := p.tok.Data
-		if n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {
-			// Ignore a newline at the start of a -->
-#errors
-#document
-| 
-|   
-|   
-|     -->
-#errors
-#document
-| 
-|   
-|   
-|     
-#errors
-Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE.
-#document
-| 
-|   
-|   
-|     
-#errors
-Line: 1 Col: 9 Unexpected end tag (strong). Expected DOCTYPE.
-Line: 1 Col: 9 Unexpected end tag (strong) after the (implied) root element.
-Line: 1 Col: 13 Unexpected end tag (b) after the (implied) root element.
-Line: 1 Col: 18 Unexpected end tag (em) after the (implied) root element.
-Line: 1 Col: 22 Unexpected end tag (i) after the (implied) root element.
-Line: 1 Col: 26 Unexpected end tag (u) after the (implied) root element.
-Line: 1 Col: 35 Unexpected end tag (strike) after the (implied) root element.
-Line: 1 Col: 39 Unexpected end tag (s) after the (implied) root element.
-Line: 1 Col: 47 Unexpected end tag (blink) after the (implied) root element.
-Line: 1 Col: 52 Unexpected end tag (tt) after the (implied) root element.
-Line: 1 Col: 58 Unexpected end tag (pre) after the (implied) root element.
-Line: 1 Col: 64 Unexpected end tag (big) after the (implied) root element.
-Line: 1 Col: 72 Unexpected end tag (small) after the (implied) root element.
-Line: 1 Col: 79 Unexpected end tag (font) after the (implied) root element.
-Line: 1 Col: 88 Unexpected end tag (select) after the (implied) root element.
-Line: 1 Col: 93 Unexpected end tag (h1) after the (implied) root element.
-Line: 1 Col: 98 Unexpected end tag (h2) after the (implied) root element.
-Line: 1 Col: 103 Unexpected end tag (h3) after the (implied) root element.
-Line: 1 Col: 108 Unexpected end tag (h4) after the (implied) root element.
-Line: 1 Col: 113 Unexpected end tag (h5) after the (implied) root element.
-Line: 1 Col: 118 Unexpected end tag (h6) after the (implied) root element.
-Line: 1 Col: 125 Unexpected end tag (body) after the (implied) root element.
-Line: 1 Col: 130 Unexpected end tag (br). Treated as br element.
-Line: 1 Col: 134 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm.
-Line: 1 Col: 140 This element (img) has no end tag.
-Line: 1 Col: 148 Unexpected end tag (title). Ignored.
-Line: 1 Col: 155 Unexpected end tag (span). Ignored.
-Line: 1 Col: 163 Unexpected end tag (style). Ignored.
-Line: 1 Col: 172 Unexpected end tag (script). Ignored.
-Line: 1 Col: 180 Unexpected end tag (table). Ignored.
-Line: 1 Col: 185 Unexpected end tag (th). Ignored.
-Line: 1 Col: 190 Unexpected end tag (td). Ignored.
-Line: 1 Col: 195 Unexpected end tag (tr). Ignored.
-Line: 1 Col: 203 This element (frame) has no end tag.
-Line: 1 Col: 210 This element (area) has no end tag.
-Line: 1 Col: 217 Unexpected end tag (link). Ignored.
-Line: 1 Col: 225 This element (param) has no end tag.
-Line: 1 Col: 230 This element (hr) has no end tag.
-Line: 1 Col: 238 This element (input) has no end tag.
-Line: 1 Col: 244 Unexpected end tag (col). Ignored.
-Line: 1 Col: 251 Unexpected end tag (base). Ignored.
-Line: 1 Col: 258 Unexpected end tag (meta). Ignored.
-Line: 1 Col: 269 This element (basefont) has no end tag.
-Line: 1 Col: 279 This element (bgsound) has no end tag.
-Line: 1 Col: 287 This element (embed) has no end tag.
-Line: 1 Col: 296 This element (spacer) has no end tag.
-Line: 1 Col: 300 Unexpected end tag (p). Ignored.
-Line: 1 Col: 305 End tag (dd) seen too early. Expected other end tag.
-Line: 1 Col: 310 End tag (dt) seen too early. Expected other end tag.
-Line: 1 Col: 320 Unexpected end tag (caption). Ignored.
-Line: 1 Col: 331 Unexpected end tag (colgroup). Ignored.
-Line: 1 Col: 339 Unexpected end tag (tbody). Ignored.
-Line: 1 Col: 347 Unexpected end tag (tfoot). Ignored.
-Line: 1 Col: 355 Unexpected end tag (thead). Ignored.
-Line: 1 Col: 365 End tag (address) seen too early. Expected other end tag.
-Line: 1 Col: 378 End tag (blockquote) seen too early. Expected other end tag.
-Line: 1 Col: 387 End tag (center) seen too early. Expected other end tag.
-Line: 1 Col: 393 Unexpected end tag (dir). Ignored.
-Line: 1 Col: 399 End tag (div) seen too early. Expected other end tag.
-Line: 1 Col: 404 End tag (dl) seen too early. Expected other end tag.
-Line: 1 Col: 415 End tag (fieldset) seen too early. Expected other end tag.
-Line: 1 Col: 425 End tag (listing) seen too early. Expected other end tag.
-Line: 1 Col: 432 End tag (menu) seen too early. Expected other end tag.
-Line: 1 Col: 437 End tag (ol) seen too early. Expected other end tag.
-Line: 1 Col: 442 End tag (ul) seen too early. Expected other end tag.
-Line: 1 Col: 447 End tag (li) seen too early. Expected other end tag.
-Line: 1 Col: 454 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm.
-Line: 1 Col: 460 This element (wbr) has no end tag.
-Line: 1 Col: 476 End tag (button) seen too early. Expected other end tag.
-Line: 1 Col: 486 End tag (marquee) seen too early. Expected other end tag.
-Line: 1 Col: 495 End tag (object) seen too early. Expected other end tag.
-Line: 1 Col: 513 Unexpected end tag (html). Ignored.
-Line: 1 Col: 513 Unexpected end tag (frameset). Ignored.
-Line: 1 Col: 520 Unexpected end tag (head). Ignored.
-Line: 1 Col: 529 Unexpected end tag (iframe). Ignored.
-Line: 1 Col: 537 This element (image) has no end tag.
-Line: 1 Col: 547 This element (isindex) has no end tag.
-Line: 1 Col: 557 Unexpected end tag (noembed). Ignored.
-Line: 1 Col: 568 Unexpected end tag (noframes). Ignored.
-Line: 1 Col: 579 Unexpected end tag (noscript). Ignored.
-Line: 1 Col: 590 Unexpected end tag (optgroup). Ignored.
-Line: 1 Col: 599 Unexpected end tag (option). Ignored.
-Line: 1 Col: 611 Unexpected end tag (plaintext). Ignored.
-Line: 1 Col: 622 Unexpected end tag (textarea). Ignored.
-#document
-| 
-|   
-|   
-|     
-|

- -#data -

-#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 20 Unexpected end tag (strong) in table context caused voodoo mode. -Line: 1 Col: 20 End tag (strong) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 24 Unexpected end tag (b) in table context caused voodoo mode. -Line: 1 Col: 24 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 29 Unexpected end tag (em) in table context caused voodoo mode. -Line: 1 Col: 29 End tag (em) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 33 Unexpected end tag (i) in table context caused voodoo mode. -Line: 1 Col: 33 End tag (i) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 37 Unexpected end tag (u) in table context caused voodoo mode. -Line: 1 Col: 37 End tag (u) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 46 Unexpected end tag (strike) in table context caused voodoo mode. -Line: 1 Col: 46 End tag (strike) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 50 Unexpected end tag (s) in table context caused voodoo mode. -Line: 1 Col: 50 End tag (s) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 58 Unexpected end tag (blink) in table context caused voodoo mode. -Line: 1 Col: 58 Unexpected end tag (blink). Ignored. -Line: 1 Col: 63 Unexpected end tag (tt) in table context caused voodoo mode. -Line: 1 Col: 63 End tag (tt) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 69 Unexpected end tag (pre) in table context caused voodoo mode. -Line: 1 Col: 69 End tag (pre) seen too early. Expected other end tag. -Line: 1 Col: 75 Unexpected end tag (big) in table context caused voodoo mode. -Line: 1 Col: 75 End tag (big) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 83 Unexpected end tag (small) in table context caused voodoo mode. -Line: 1 Col: 83 End tag (small) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 90 Unexpected end tag (font) in table context caused voodoo mode. -Line: 1 Col: 90 End tag (font) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 99 Unexpected end tag (select) in table context caused voodoo mode. -Line: 1 Col: 99 Unexpected end tag (select). Ignored. -Line: 1 Col: 104 Unexpected end tag (h1) in table context caused voodoo mode. -Line: 1 Col: 104 End tag (h1) seen too early. Expected other end tag. -Line: 1 Col: 109 Unexpected end tag (h2) in table context caused voodoo mode. -Line: 1 Col: 109 End tag (h2) seen too early. Expected other end tag. -Line: 1 Col: 114 Unexpected end tag (h3) in table context caused voodoo mode. -Line: 1 Col: 114 End tag (h3) seen too early. Expected other end tag. -Line: 1 Col: 119 Unexpected end tag (h4) in table context caused voodoo mode. -Line: 1 Col: 119 End tag (h4) seen too early. Expected other end tag. -Line: 1 Col: 124 Unexpected end tag (h5) in table context caused voodoo mode. -Line: 1 Col: 124 End tag (h5) seen too early. Expected other end tag. -Line: 1 Col: 129 Unexpected end tag (h6) in table context caused voodoo mode. -Line: 1 Col: 129 End tag (h6) seen too early. Expected other end tag. -Line: 1 Col: 136 Unexpected end tag (body) in the table row phase. Ignored. -Line: 1 Col: 141 Unexpected end tag (br) in table context caused voodoo mode. -Line: 1 Col: 141 Unexpected end tag (br). Treated as br element. -Line: 1 Col: 145 Unexpected end tag (a) in table context caused voodoo mode. -Line: 1 Col: 145 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 151 Unexpected end tag (img) in table context caused voodoo mode. -Line: 1 Col: 151 This element (img) has no end tag. -Line: 1 Col: 159 Unexpected end tag (title) in table context caused voodoo mode. -Line: 1 Col: 159 Unexpected end tag (title). Ignored. -Line: 1 Col: 166 Unexpected end tag (span) in table context caused voodoo mode. -Line: 1 Col: 166 Unexpected end tag (span). Ignored. -Line: 1 Col: 174 Unexpected end tag (style) in table context caused voodoo mode. -Line: 1 Col: 174 Unexpected end tag (style). Ignored. -Line: 1 Col: 183 Unexpected end tag (script) in table context caused voodoo mode. -Line: 1 Col: 183 Unexpected end tag (script). Ignored. -Line: 1 Col: 196 Unexpected end tag (th). Ignored. -Line: 1 Col: 201 Unexpected end tag (td). Ignored. -Line: 1 Col: 206 Unexpected end tag (tr). Ignored. -Line: 1 Col: 214 This element (frame) has no end tag. -Line: 1 Col: 221 This element (area) has no end tag. -Line: 1 Col: 228 Unexpected end tag (link). Ignored. -Line: 1 Col: 236 This element (param) has no end tag. -Line: 1 Col: 241 This element (hr) has no end tag. -Line: 1 Col: 249 This element (input) has no end tag. -Line: 1 Col: 255 Unexpected end tag (col). Ignored. -Line: 1 Col: 262 Unexpected end tag (base). Ignored. -Line: 1 Col: 269 Unexpected end tag (meta). Ignored. -Line: 1 Col: 280 This element (basefont) has no end tag. -Line: 1 Col: 290 This element (bgsound) has no end tag. -Line: 1 Col: 298 This element (embed) has no end tag. -Line: 1 Col: 307 This element (spacer) has no end tag. -Line: 1 Col: 311 Unexpected end tag (p). Ignored. -Line: 1 Col: 316 End tag (dd) seen too early. Expected other end tag. -Line: 1 Col: 321 End tag (dt) seen too early. Expected other end tag. -Line: 1 Col: 331 Unexpected end tag (caption). Ignored. -Line: 1 Col: 342 Unexpected end tag (colgroup). Ignored. -Line: 1 Col: 350 Unexpected end tag (tbody). Ignored. -Line: 1 Col: 358 Unexpected end tag (tfoot). Ignored. -Line: 1 Col: 366 Unexpected end tag (thead). Ignored. -Line: 1 Col: 376 End tag (address) seen too early. Expected other end tag. -Line: 1 Col: 389 End tag (blockquote) seen too early. Expected other end tag. -Line: 1 Col: 398 End tag (center) seen too early. Expected other end tag. -Line: 1 Col: 404 Unexpected end tag (dir). Ignored. -Line: 1 Col: 410 End tag (div) seen too early. Expected other end tag. -Line: 1 Col: 415 End tag (dl) seen too early. Expected other end tag. -Line: 1 Col: 426 End tag (fieldset) seen too early. Expected other end tag. -Line: 1 Col: 436 End tag (listing) seen too early. Expected other end tag. -Line: 1 Col: 443 End tag (menu) seen too early. Expected other end tag. -Line: 1 Col: 448 End tag (ol) seen too early. Expected other end tag. -Line: 1 Col: 453 End tag (ul) seen too early. Expected other end tag. -Line: 1 Col: 458 End tag (li) seen too early. Expected other end tag. -Line: 1 Col: 465 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 471 This element (wbr) has no end tag. -Line: 1 Col: 487 End tag (button) seen too early. Expected other end tag. -Line: 1 Col: 497 End tag (marquee) seen too early. Expected other end tag. -Line: 1 Col: 506 End tag (object) seen too early. Expected other end tag. -Line: 1 Col: 524 Unexpected end tag (html). Ignored. -Line: 1 Col: 524 Unexpected end tag (frameset). Ignored. -Line: 1 Col: 531 Unexpected end tag (head). Ignored. -Line: 1 Col: 540 Unexpected end tag (iframe). Ignored. -Line: 1 Col: 548 This element (image) has no end tag. -Line: 1 Col: 558 This element (isindex) has no end tag. -Line: 1 Col: 568 Unexpected end tag (noembed). Ignored. -Line: 1 Col: 579 Unexpected end tag (noframes). Ignored. -Line: 1 Col: 590 Unexpected end tag (noscript). Ignored. -Line: 1 Col: 601 Unexpected end tag (optgroup). Ignored. -Line: 1 Col: 610 Unexpected end tag (option). Ignored. -Line: 1 Col: 622 Unexpected end tag (plaintext). Ignored. -Line: 1 Col: 633 Unexpected end tag (textarea). Ignored. -#document -| -| -| -|
-| -| -| -|

- -#data - -#errors -Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. -Line: 1 Col: 10 Expected closing tag. Unexpected end of file. -#document -| -| -| diff --git a/libgo/go/exp/html/testdata/webkit/tests10.dat b/libgo/go/exp/html/testdata/webkit/tests10.dat deleted file mode 100644 index 4f8df86f208..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests10.dat +++ /dev/null @@ -1,799 +0,0 @@ -#data - -#errors -#document -| -| -| -| -| - -#data -a -#errors -29: Bogus comment -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| - -#data - -#errors -35: Stray “svg” start tag. -42: Stray end tag “svg” -#document -| -| -| -| -| -#errors -43: Stray “svg” start tag. -50: Stray end tag “svg” -#document -| -| -| -| -|

-#errors -34: Start tag “svg” seen in “table”. -41: Stray end tag “svg”. -#document -| -| -| -| -| -| - -#data -
foo
-#errors -34: Start tag “svg” seen in “table”. -46: Stray end tag “g”. -53: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| - -#data -
foobar
-#errors -34: Start tag “svg” seen in “table”. -46: Stray end tag “g”. -58: Stray end tag “g”. -65: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -| - -#data -
foobar
-#errors -41: Start tag “svg” seen in “table”. -53: Stray end tag “g”. -65: Stray end tag “g”. -72: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -| -| - -#data -
foobar
-#errors -45: Start tag “svg” seen in “table”. -57: Stray end tag “g”. -69: Stray end tag “g”. -76: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -| -| -| - -#data -
foobar
-#errors -#document -| -| -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" - -#data -
foobar

baz

-#errors -#document -| -| -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -
foobar

baz

-#errors -#document -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -
foobar

baz

quux -#errors -70: HTML start tag “p” in a foreign namespace context. -81: “table” closed but “caption” was still open. -#document -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -|

-| "baz" -|

-| "quux" - -#data -
foobarbaz

quux -#errors -78: “table” closed but “caption” was still open. -78: Unclosed elements on stack. -#document -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -| "baz" -|

-| "quux" - -#data -foobar

baz

quux -#errors -44: Start tag “svg” seen in “table”. -56: Stray end tag “g”. -68: Stray end tag “g”. -71: HTML start tag “p” in a foreign namespace context. -71: Start tag “p” seen in “table”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -|

-| "baz" -| -| -|

-| "quux" - -#data -

quux -#errors -50: Stray “svg” start tag. -54: Stray “g” start tag. -62: Stray end tag “g” -66: Stray “g” start tag. -74: Stray end tag “g” -77: Stray “p” start tag. -88: “table” end tag with “select” open. -#document -| -| -| -| -| -| -| -|
-|

quux -#errors -36: Start tag “select” seen in “table”. -42: Stray “svg” start tag. -46: Stray “g” start tag. -54: Stray end tag “g” -58: Stray “g” start tag. -66: Stray end tag “g” -69: Stray “p” start tag. -80: “table” end tag with “select” open. -#document -| -| -| -| -| -|

-| "quux" - -#data -foobar

baz -#errors -41: Stray “svg” start tag. -68: HTML start tag “p” in a foreign namespace context. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -foobar

baz -#errors -34: Stray “svg” start tag. -61: HTML start tag “p” in a foreign namespace context. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -

-#errors -31: Stray “svg” start tag. -35: Stray “g” start tag. -40: Stray end tag “g” -44: Stray “g” start tag. -49: Stray end tag “g” -52: Stray “p” start tag. -58: Stray “span” start tag. -58: End of file seen and there were open elements. -#document -| -| -| -| - -#data -

-#errors -42: Stray “svg” start tag. -46: Stray “g” start tag. -51: Stray end tag “g” -55: Stray “g” start tag. -60: Stray end tag “g” -63: Stray “p” start tag. -69: Stray “span” start tag. -#document -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| xlink:href="foo" -| -| xlink href="foo" - -#data - -#errors -#document -| -| -| -| -| xlink:href="foo" -| xml:lang="en" -| -| -| xlink href="foo" -| xml lang="en" - -#data - -#errors -#document -| -| -| -| -| xlink:href="foo" -| xml:lang="en" -| -| -| xlink href="foo" -| xml lang="en" - -#data -bar -#errors -#document -| -| -| -| -| xlink:href="foo" -| xml:lang="en" -| -| -| xlink href="foo" -| xml lang="en" -| "bar" - -#data - -#errors -#document -| -| -| -| - -#data -

a -#errors -#document -| -| -| -|
-| -| "a" - -#data -
a -#errors -#document -| -| -| -|
-| -| -| "a" - -#data -
-#errors -#document -| -| -| -|
-| -| -| - -#data -
a -#errors -#document -| -| -| -|
-| -| -| -| -| "a" - -#data -

a -#errors -#document -| -| -| -|

-| -| -| -|

-| "a" - -#data -
    a -#errors -40: HTML start tag “ul” in a foreign namespace context. -41: End of file in a foreign namespace context. -#document -| -| -| -| -| -| -|
    -| -|
      -| "a" - -#data -
        a -#errors -35: HTML start tag “ul” in a foreign namespace context. -36: End of file in a foreign namespace context. -#document -| -| -| -| -| -| -| -|
          -| "a" - -#data -

          -#errors -#document -| -| -| -| -|

          -| -| -|

          - -#data -

          -#errors -#document -| -| -| -| -|

          -| -| -|

          - -#data -

          -#errors -#document -| -| -| -|

          -| -| -| -|

          -|

          - -#data -
          -#errors -#document -| -| -| -| -| -|
          -| -|
          -| -| - -#data -
          -#errors -#document -| -| -| -| -| -| -| -|
          -|
          -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data -

-#errors -#document -| -| -| -| -|
-| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| - -#data -
-#errors -#document -| -| -| -| -| -| -| -|
-| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| diff --git a/libgo/go/exp/html/testdata/webkit/tests11.dat b/libgo/go/exp/html/testdata/webkit/tests11.dat deleted file mode 100644 index 638cde479f7..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests11.dat +++ /dev/null @@ -1,482 +0,0 @@ -#data - -#errors -#document -| -| -| -| -| -| attributeName="" -| attributeType="" -| baseFrequency="" -| baseProfile="" -| calcMode="" -| clipPathUnits="" -| contentScriptType="" -| contentStyleType="" -| diffuseConstant="" -| edgeMode="" -| externalResourcesRequired="" -| filterRes="" -| filterUnits="" -| glyphRef="" -| gradientTransform="" -| gradientUnits="" -| kernelMatrix="" -| kernelUnitLength="" -| keyPoints="" -| keySplines="" -| keyTimes="" -| lengthAdjust="" -| limitingConeAngle="" -| markerHeight="" -| markerUnits="" -| markerWidth="" -| maskContentUnits="" -| maskUnits="" -| numOctaves="" -| pathLength="" -| patternContentUnits="" -| patternTransform="" -| patternUnits="" -| pointsAtX="" -| pointsAtY="" -| pointsAtZ="" -| preserveAlpha="" -| preserveAspectRatio="" -| primitiveUnits="" -| refX="" -| refY="" -| repeatCount="" -| repeatDur="" -| requiredExtensions="" -| requiredFeatures="" -| specularConstant="" -| specularExponent="" -| spreadMethod="" -| startOffset="" -| stdDeviation="" -| stitchTiles="" -| surfaceScale="" -| systemLanguage="" -| tableValues="" -| targetX="" -| targetY="" -| textLength="" -| viewBox="" -| viewTarget="" -| xChannelSelector="" -| yChannelSelector="" -| zoomAndPan="" - -#data - -#errors -#document -| -| -| -| -| -| attributeName="" -| attributeType="" -| baseFrequency="" -| baseProfile="" -| calcMode="" -| clipPathUnits="" -| contentScriptType="" -| contentStyleType="" -| diffuseConstant="" -| edgeMode="" -| externalResourcesRequired="" -| filterRes="" -| filterUnits="" -| glyphRef="" -| gradientTransform="" -| gradientUnits="" -| kernelMatrix="" -| kernelUnitLength="" -| keyPoints="" -| keySplines="" -| keyTimes="" -| lengthAdjust="" -| limitingConeAngle="" -| markerHeight="" -| markerUnits="" -| markerWidth="" -| maskContentUnits="" -| maskUnits="" -| numOctaves="" -| pathLength="" -| patternContentUnits="" -| patternTransform="" -| patternUnits="" -| pointsAtX="" -| pointsAtY="" -| pointsAtZ="" -| preserveAlpha="" -| preserveAspectRatio="" -| primitiveUnits="" -| refX="" -| refY="" -| repeatCount="" -| repeatDur="" -| requiredExtensions="" -| requiredFeatures="" -| specularConstant="" -| specularExponent="" -| spreadMethod="" -| startOffset="" -| stdDeviation="" -| stitchTiles="" -| surfaceScale="" -| systemLanguage="" -| tableValues="" -| targetX="" -| targetY="" -| textLength="" -| viewBox="" -| viewTarget="" -| xChannelSelector="" -| yChannelSelector="" -| zoomAndPan="" - -#data - -#errors -#document -| -| -| -| -| -| attributeName="" -| attributeType="" -| baseFrequency="" -| baseProfile="" -| calcMode="" -| clipPathUnits="" -| contentScriptType="" -| contentStyleType="" -| diffuseConstant="" -| edgeMode="" -| externalResourcesRequired="" -| filterRes="" -| filterUnits="" -| glyphRef="" -| gradientTransform="" -| gradientUnits="" -| kernelMatrix="" -| kernelUnitLength="" -| keyPoints="" -| keySplines="" -| keyTimes="" -| lengthAdjust="" -| limitingConeAngle="" -| markerHeight="" -| markerUnits="" -| markerWidth="" -| maskContentUnits="" -| maskUnits="" -| numOctaves="" -| pathLength="" -| patternContentUnits="" -| patternTransform="" -| patternUnits="" -| pointsAtX="" -| pointsAtY="" -| pointsAtZ="" -| preserveAlpha="" -| preserveAspectRatio="" -| primitiveUnits="" -| refX="" -| refY="" -| repeatCount="" -| repeatDur="" -| requiredExtensions="" -| requiredFeatures="" -| specularConstant="" -| specularExponent="" -| spreadMethod="" -| startOffset="" -| stdDeviation="" -| stitchTiles="" -| surfaceScale="" -| systemLanguage="" -| tableValues="" -| targetX="" -| targetY="" -| textLength="" -| viewBox="" -| viewTarget="" -| xChannelSelector="" -| yChannelSelector="" -| zoomAndPan="" - -#data - -#errors -#document -| -| -| -| -| -| attributename="" -| attributetype="" -| basefrequency="" -| baseprofile="" -| calcmode="" -| clippathunits="" -| contentscripttype="" -| contentstyletype="" -| diffuseconstant="" -| edgemode="" -| externalresourcesrequired="" -| filterres="" -| filterunits="" -| glyphref="" -| gradienttransform="" -| gradientunits="" -| kernelmatrix="" -| kernelunitlength="" -| keypoints="" -| keysplines="" -| keytimes="" -| lengthadjust="" -| limitingconeangle="" -| markerheight="" -| markerunits="" -| markerwidth="" -| maskcontentunits="" -| maskunits="" -| numoctaves="" -| pathlength="" -| patterncontentunits="" -| patterntransform="" -| patternunits="" -| pointsatx="" -| pointsaty="" -| pointsatz="" -| preservealpha="" -| preserveaspectratio="" -| primitiveunits="" -| refx="" -| refy="" -| repeatcount="" -| repeatdur="" -| requiredextensions="" -| requiredfeatures="" -| specularconstant="" -| specularexponent="" -| spreadmethod="" -| startoffset="" -| stddeviation="" -| stitchtiles="" -| surfacescale="" -| systemlanguage="" -| tablevalues="" -| targetx="" -| targety="" -| textlength="" -| viewbox="" -| viewtarget="" -| xchannelselector="" -| ychannelselector="" -| zoomandpan="" - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| diff --git a/libgo/go/exp/html/testdata/webkit/tests12.dat b/libgo/go/exp/html/testdata/webkit/tests12.dat deleted file mode 100644 index 63107d277b6..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests12.dat +++ /dev/null @@ -1,62 +0,0 @@ -#data -

foobazeggs

spam

quuxbar -#errors -#document -| -| -| -| -|

-| "foo" -| -| -| -| "baz" -| -| -| -| -| "eggs" -| -| -|

-| "spam" -| -| -| -|
-| -| -| "quux" -| "bar" - -#data -foobazeggs

spam
quuxbar -#errors -#document -| -| -| -| -| "foo" -| -| -| -| "baz" -| -| -| -| -| "eggs" -| -| -|

-| "spam" -| -| -| -|
-| -| -| "quux" -| "bar" diff --git a/libgo/go/exp/html/testdata/webkit/tests14.dat b/libgo/go/exp/html/testdata/webkit/tests14.dat deleted file mode 100644 index b8713f88582..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests14.dat +++ /dev/null @@ -1,74 +0,0 @@ -#data - -#errors -#document -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -15: Unexpected start tag html -#document -| -| -| abc:def="gh" -| -| -| - -#data - -#errors -15: Unexpected start tag html -#document -| -| -| xml:lang="bar" -| -| - -#data - -#errors -#document -| -| -| 123="456" -| -| - -#data - -#errors -#document -| -| -| 123="456" -| 789="012" -| -| - -#data - -#errors -#document -| -| -| -| -| 789="012" diff --git a/libgo/go/exp/html/testdata/webkit/tests15.dat b/libgo/go/exp/html/testdata/webkit/tests15.dat deleted file mode 100644 index 6ce1c0d1663..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests15.dat +++ /dev/null @@ -1,208 +0,0 @@ -#data -

X -#errors -Line: 1 Col: 31 Unexpected end tag (p). Ignored. -Line: 1 Col: 36 Expected closing tag. Unexpected end of file. -#document -| -| -| -| -|

-| -| -| -| -| -| -| " " -|

-| "X" - -#data -

-

X -#errors -Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. -Line: 1 Col: 16 Unexpected end tag (p). Ignored. -Line: 2 Col: 4 Expected closing tag. Unexpected end of file. -#document -| -| -| -|

-| -| -| -| -| -| -| " -" -|

-| "X" - -#data - -#errors -Line: 1 Col: 22 Unexpected end tag (html) after the (implied) root element. -#document -| -| -| -| -| " " - -#data - -#errors -Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element. -#document -| -| -| -| -| - -#data - -#errors -Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end tag (html) after the (implied) root element. -#document -| -| -| -| - -#data -X -#errors -Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element. -#document -| -| -| -| -| -| "X" - -#data -<!doctype html><table> X<meta></table> -#errors -Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode. -Line: 1 Col: 30 Unexpected start tag (meta) in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " X" -| <meta> -| <table> - -#data -<!doctype html><table> x</table> -#errors -Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " x" -| <table> - -#data -<!doctype html><table> x </table> -#errors -Line: 1 Col: 25 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " x " -| <table> - -#data -<!doctype html><table><tr> x</table> -#errors -Line: 1 Col: 28 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " x" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table>X<style> <tr>x </style> </table> -#errors -Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "X" -| <table> -| <style> -| " <tr>x " -| " " - -#data -<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div> -#errors -Line: 1 Col: 30 Unexpected start tag (a) in table context caused voodoo mode. -Line: 1 Col: 37 Unexpected end tag (a) in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> -| <a> -| "foo" -| <table> -| " " -| <tbody> -| <tr> -| <td> -| "bar" -| " " - -#data -<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes> -#errors -6: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. -13: Stray start tag “frame”. -21: Stray end tag “frame”. -29: Stray end tag “frame”. -39: “frameset” start tag after “body” already open. -105: End of file seen inside an [R]CDATA element. -105: End of file seen and there were open elements. -XXX: These errors are wrong, please fix me! -#document -| <html> -| <head> -| <frameset> -| <frame> -| <frameset> -| <frame> -| <noframes> -| "</frameset><noframes>" - -#data -<!DOCTYPE html><object></html> -#errors -1: Expected closing tag. Unexpected end of file -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <object> diff --git a/libgo/go/exp/html/testdata/webkit/tests16.dat b/libgo/go/exp/html/testdata/webkit/tests16.dat deleted file mode 100644 index c8ef66f0e6e..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests16.dat +++ /dev/null @@ -1,2299 +0,0 @@ -#data -<!doctype html><script> -#errors -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| <body> - -#data -<!doctype html><script>a -#errors -Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "a" -| <body> - -#data -<!doctype html><script>< -#errors -Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<" -| <body> - -#data -<!doctype html><script></ -#errors -Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</" -| <body> - -#data -<!doctype html><script></S -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</S" -| <body> - -#data -<!doctype html><script></SC -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SC" -| <body> - -#data -<!doctype html><script></SCR -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCR" -| <body> - -#data -<!doctype html><script></SCRI -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCRI" -| <body> - -#data -<!doctype html><script></SCRIP -#errors -Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCRIP" -| <body> - -#data -<!doctype html><script></SCRIPT -#errors -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCRIPT" -| <body> - -#data -<!doctype html><script></SCRIPT -#errors -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| <body> - -#data -<!doctype html><script></s -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</s" -| <body> - -#data -<!doctype html><script></sc -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</sc" -| <body> - -#data -<!doctype html><script></scr -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</scr" -| <body> - -#data -<!doctype html><script></scri -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</scri" -| <body> - -#data -<!doctype html><script></scrip -#errors -Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</scrip" -| <body> - -#data -<!doctype html><script></script -#errors -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</script" -| <body> - -#data -<!doctype html><script></script -#errors -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| <body> - -#data -<!doctype html><script><! -#errors -Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!" -| <body> - -#data -<!doctype html><script><!a -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!a" -| <body> - -#data -<!doctype html><script><!- -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!-" -| <body> - -#data -<!doctype html><script><!-a -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!-a" -| <body> - -#data -<!doctype html><script><!-- -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<!doctype html><script><!--a -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--a" -| <body> - -#data -<!doctype html><script><!--< -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<" -| <body> - -#data -<!doctype html><script><!--<a -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<a" -| <body> - -#data -<!doctype html><script><!--</ -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--</" -| <body> - -#data -<!doctype html><script><!--</script -#errors -Line: 1 Col: 35 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--</script" -| <body> - -#data -<!doctype html><script><!--</script -#errors -Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<!doctype html><script><!--<s -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<s" -| <body> - -#data -<!doctype html><script><!--<script -#errors -Line: 1 Col: 34 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script" -| <body> - -#data -<!doctype html><script><!--<script -#errors -Line: 1 Col: 35 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script " -| <body> - -#data -<!doctype html><script><!--<script < -#errors -Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script <" -| <body> - -#data -<!doctype html><script><!--<script <a -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script <a" -| <body> - -#data -<!doctype html><script><!--<script </ -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </" -| <body> - -#data -<!doctype html><script><!--<script </s -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </s" -| <body> - -#data -<!doctype html><script><!--<script </script -#errors -Line: 1 Col: 43 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script" -| <body> - -#data -<!doctype html><script><!--<script </scripta -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </scripta" -| <body> - -#data -<!doctype html><script><!--<script </script -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script </script> -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script>" -| <body> - -#data -<!doctype html><script><!--<script </script/ -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script/" -| <body> - -#data -<!doctype html><script><!--<script </script < -#errors -Line: 1 Col: 45 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script <" -| <body> - -#data -<!doctype html><script><!--<script </script <a -#errors -Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script <a" -| <body> - -#data -<!doctype html><script><!--<script </script </ -#errors -Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script </" -| <body> - -#data -<!doctype html><script><!--<script </script </script -#errors -Line: 1 Col: 52 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script </script" -| <body> - -#data -<!doctype html><script><!--<script </script </script -#errors -Line: 1 Col: 53 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script </script </script/ -#errors -Line: 1 Col: 53 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script </script </script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script - -#errors -Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -" -| <body> - -#data -<!doctype html><script><!--<script -a -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -a" -| <body> - -#data -<!doctype html><script><!--<script -< -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -<" -| <body> - -#data -<!doctype html><script><!--<script -- -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --" -| <body> - -#data -<!doctype html><script><!--<script --a -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --a" -| <body> - -#data -<!doctype html><script><!--<script --< -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --<" -| <body> - -#data -<!doctype html><script><!--<script --> -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script -->< -#errors -Line: 1 Col: 39 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --><" -| <body> - -#data -<!doctype html><script><!--<script --></ -#errors -Line: 1 Col: 40 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --></" -| <body> - -#data -<!doctype html><script><!--<script --></script -#errors -Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --></script" -| <body> - -#data -<!doctype html><script><!--<script --></script -#errors -Line: 1 Col: 47 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script --></script/ -#errors -Line: 1 Col: 47 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script --></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script><\/script>--></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script><\/script>-->" -| <body> - -#data -<!doctype html><script><!--<script></scr'+'ipt>--></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt>-->" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>--><!--</script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>--><!--" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>-- ></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>-- >" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>- -></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- ->" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>- - ></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- - >" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>-></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>->" -| <body> - -#data -<!doctype html><script><!--<script>--!></script>X -#errors -Line: 1 Col: 49 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script>--!></script>X" -| <body> - -#data -<!doctype html><script><!--<scr'+'ipt></script>--></script> -#errors -Line: 1 Col: 59 Unexpected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<scr'+'ipt>" -| <body> -| "-->" - -#data -<!doctype html><script><!--<script></scr'+'ipt></script>X -#errors -Line: 1 Col: 57 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt></script>X" -| <body> - -#data -<!doctype html><style><!--<style></style>--></style> -#errors -Line: 1 Col: 52 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--<style>" -| <body> -| "-->" - -#data -<!doctype html><style><!--</style>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--" -| <body> -| "X" - -#data -<!doctype html><style><!--...</style>...--></style> -#errors -Line: 1 Col: 51 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--..." -| <body> -| "...-->" - -#data -<!doctype html><style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>" -| <body> -| "X" - -#data -<!doctype html><style><!--...<style><!--...--!></style>--></style> -#errors -Line: 1 Col: 66 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--...<style><!--...--!>" -| <body> -| "-->" - -#data -<!doctype html><style><!--...</style><!-- --><style>@import ...</style> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--..." -| <!-- --> -| <style> -| "@import ..." -| <body> - -#data -<!doctype html><style>...<style><!--...</style><!-- --></style> -#errors -Line: 1 Col: 63 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "...<style><!--..." -| <!-- --> -| <body> - -#data -<!doctype html><style>...<!--[if IE]><style>...</style>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "...<!--[if IE]><style>..." -| <body> -| "X" - -#data -<!doctype html><title><!--<title>--> -#errors -Line: 1 Col: 52 Unexpected end tag (title). -#document -| -| -| -| -| "<!--<title>" -| <body> -| "-->" - -#data -<!doctype html><title></title> -#errors -#document -| -| -| -| -| "" -| - -#data -foo/title><link></head><body>X -#errors -Line: 1 Col: 52 Unexpected end of file. Expected end tag (title). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <title> -| "foo/title><link></head><body>X" -| <body> - -#data -<!doctype html><noscript><!--<noscript></noscript>--></noscript> -#errors -Line: 1 Col: 64 Unexpected end tag (noscript). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noscript> -| "<!--<noscript>" -| <body> -| "-->" - -#data -<!doctype html><noscript><!--</noscript>X<noscript>--></noscript> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noscript> -| "<!--" -| <body> -| "X" -| <noscript> -| "-->" - -#data -<!doctype html><noscript><iframe></noscript>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noscript> -| "<iframe>" -| <body> -| "X" - -#data -<!doctype html><noframes><!--<noframes></noframes>--></noframes> -#errors -Line: 1 Col: 64 Unexpected end tag (noframes). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noframes> -| "<!--<noframes>" -| <body> -| "-->" - -#data -<!doctype html><noframes><body><script><!--...</script></body></noframes></html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noframes> -| "<body><script><!--...</script></body>" -| <body> - -#data -<!doctype html><textarea><!--<textarea></textarea>--></textarea> -#errors -Line: 1 Col: 64 Unexpected end tag (textarea). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "<!--<textarea>" -| "-->" - -#data -<!doctype html><textarea></textarea></textarea> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "</textarea>" - -#data -<!doctype html><textarea><</textarea> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "<" - -#data -<!doctype html><textarea>a<b</textarea> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "a<b" - -#data -<!doctype html><iframe><!--<iframe></iframe>--></iframe> -#errors -Line: 1 Col: 56 Unexpected end tag (iframe). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <iframe> -| "<!--<iframe>" -| "-->" - -#data -<!doctype html><iframe>...<!--X->...<!--/X->...</iframe> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <iframe> -| "...<!--X->...<!--/X->..." - -#data -<!doctype html><xmp><!--<xmp></xmp>--></xmp> -#errors -Line: 1 Col: 44 Unexpected end tag (xmp). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <xmp> -| "<!--<xmp>" -| "-->" - -#data -<!doctype html><noembed><!--<noembed></noembed>--></noembed> -#errors -Line: 1 Col: 60 Unexpected end tag (noembed). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <noembed> -| "<!--<noembed>" -| "-->" - -#data -<script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 8 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| <body> - -#data -<script>a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 9 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "a" -| <body> - -#data -<script>< -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 9 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<" -| <body> - -#data -<script></ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 10 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</" -| <body> - -#data -<script></S -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</S" -| <body> - -#data -<script></SC -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SC" -| <body> - -#data -<script></SCR -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCR" -| <body> - -#data -<script></SCRI -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCRI" -| <body> - -#data -<script></SCRIP -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 15 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCRIP" -| <body> - -#data -<script></SCRIPT -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 16 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCRIPT" -| <body> - -#data -<script></SCRIPT -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 17 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| <body> - -#data -<script></s -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</s" -| <body> - -#data -<script></sc -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</sc" -| <body> - -#data -<script></scr -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</scr" -| <body> - -#data -<script></scri -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</scri" -| <body> - -#data -<script></scrip -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 15 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</scrip" -| <body> - -#data -<script></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 16 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</script" -| <body> - -#data -<script></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 17 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| <body> - -#data -<script><! -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 10 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!" -| <body> - -#data -<script><!a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!a" -| <body> - -#data -<script><!- -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!-" -| <body> - -#data -<script><!-a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!-a" -| <body> - -#data -<script><!-- -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<script><!--a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--a" -| <body> - -#data -<script><!--< -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<" -| <body> - -#data -<script><!--<a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<a" -| <body> - -#data -<script><!--</ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--</" -| <body> - -#data -<script><!--</script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 20 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--</script" -| <body> - -#data -<script><!--</script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<script><!--<s -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<s" -| <body> - -#data -<script><!--<script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 19 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script" -| <body> - -#data -<script><!--<script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 20 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script " -| <body> - -#data -<script><!--<script < -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script <" -| <body> - -#data -<script><!--<script <a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script <a" -| <body> - -#data -<script><!--<script </ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </" -| <body> - -#data -<script><!--<script </s -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </s" -| <body> - -#data -<script><!--<script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script" -| <body> - -#data -<script><!--<script </scripta -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </scripta" -| <body> - -#data -<script><!--<script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script </script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script>" -| <body> - -#data -<script><!--<script </script/ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script/" -| <body> - -#data -<script><!--<script </script < -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script <" -| <body> - -#data -<script><!--<script </script <a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script <a" -| <body> - -#data -<script><!--<script </script </ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script </" -| <body> - -#data -<script><!--<script </script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script </script" -| <body> - -#data -<script><!--<script </script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script </script </script/ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script </script </script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script - -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -" -| <body> - -#data -<script><!--<script -a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -a" -| <body> - -#data -<script><!--<script -- -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --" -| <body> - -#data -<script><!--<script --a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --a" -| <body> - -#data -<script><!--<script --> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script -->< -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --><" -| <body> - -#data -<script><!--<script --></ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --></" -| <body> - -#data -<script><!--<script --></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --></script" -| <body> - -#data -<script><!--<script --></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script --></script/ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script --></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script><\/script>--></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script><\/script>-->" -| <body> - -#data -<script><!--<script></scr'+'ipt>--></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt>-->" -| <body> - -#data -<script><!--<script></script><script></script></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>" -| <body> - -#data -<script><!--<script></script><script></script>--><!--</script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>--><!--" -| <body> - -#data -<script><!--<script></script><script></script>-- ></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>-- >" -| <body> - -#data -<script><!--<script></script><script></script>- -></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- ->" -| <body> - -#data -<script><!--<script></script><script></script>- - ></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- - >" -| <body> - -#data -<script><!--<script></script><script></script>-></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>->" -| <body> - -#data -<script><!--<script>--!></script>X -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 34 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script>--!></script>X" -| <body> - -#data -<script><!--<scr'+'ipt></script>--></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 44 Unexpected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<scr'+'ipt>" -| <body> -| "-->" - -#data -<script><!--<script></scr'+'ipt></script>X -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 42 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt></script>X" -| <body> - -#data -<style><!--<style></style>--></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 37 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "<!--<style>" -| <body> -| "-->" - -#data -<style><!--</style>X -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "<!--" -| <body> -| "X" - -#data -<style><!--...</style>...--></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 36 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "<!--..." -| <body> -| "...-->" - -#data -<style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>" -| <body> -| "X" - -#data -<style><!--...<style><!--...--!></style>--></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 51 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "<!--...<style><!--...--!>" -| <body> -| "-->" - -#data -<style><!--...</style><!-- --><style>@import ...</style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "<!--..." -| <!-- --> -| <style> -| "@import ..." -| <body> - -#data -<style>...<style><!--...</style><!-- --></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 48 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "...<style><!--..." -| <!-- --> -| <body> - -#data -<style>...<!--[if IE]><style>...</style>X -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "...<!--[if IE]><style>..." -| <body> -| "X" - -#data -<title><!--<title>--> -#errors -Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. -Line: 1 Col: 37 Unexpected end tag (title). -#document -| -| -| -| "<!--<title>" -| <body> -| "-->" - -#data -<title></title> -#errors -Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. -#document -| -| -| -| "" -| - -#data -foo/title><link></head><body>X -#errors -Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. -Line: 1 Col: 37 Unexpected end of file. Expected end tag (title). -#document -| <html> -| <head> -| <title> -| "foo/title><link></head><body>X" -| <body> - -#data -<noscript><!--<noscript></noscript>--></noscript> -#errors -Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. -Line: 1 Col: 49 Unexpected end tag (noscript). -#document -| <html> -| <head> -| <noscript> -| "<!--<noscript>" -| <body> -| "-->" - -#data -<noscript><!--</noscript>X<noscript>--></noscript> -#errors -Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. -#document -| <html> -| <head> -| <noscript> -| "<!--" -| <body> -| "X" -| <noscript> -| "-->" - -#data -<noscript><iframe></noscript>X -#errors -Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. -#document -| <html> -| <head> -| <noscript> -| "<iframe>" -| <body> -| "X" - -#data -<noframes><!--<noframes></noframes>--></noframes> -#errors -Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE. -Line: 1 Col: 49 Unexpected end tag (noframes). -#document -| <html> -| <head> -| <noframes> -| "<!--<noframes>" -| <body> -| "-->" - -#data -<noframes><body><script><!--...</script></body></noframes></html> -#errors -Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE. -#document -| <html> -| <head> -| <noframes> -| "<body><script><!--...</script></body>" -| <body> - -#data -<textarea><!--<textarea></textarea>--></textarea> -#errors -Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. -Line: 1 Col: 49 Unexpected end tag (textarea). -#document -| <html> -| <head> -| <body> -| <textarea> -| "<!--<textarea>" -| "-->" - -#data -<textarea></textarea></textarea> -#errors -Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| <textarea> -| "</textarea>" - -#data -<iframe><!--<iframe></iframe>--></iframe> -#errors -Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. -Line: 1 Col: 41 Unexpected end tag (iframe). -#document -| <html> -| <head> -| <body> -| <iframe> -| "<!--<iframe>" -| "-->" - -#data -<iframe>...<!--X->...<!--/X->...</iframe> -#errors -Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| <iframe> -| "...<!--X->...<!--/X->..." - -#data -<xmp><!--<xmp></xmp>--></xmp> -#errors -Line: 1 Col: 5 Unexpected start tag (xmp). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end tag (xmp). -#document -| <html> -| <head> -| <body> -| <xmp> -| "<!--<xmp>" -| "-->" - -#data -<noembed><!--<noembed></noembed>--></noembed> -#errors -Line: 1 Col: 9 Unexpected start tag (noembed). Expected DOCTYPE. -Line: 1 Col: 45 Unexpected end tag (noembed). -#document -| <html> -| <head> -| <body> -| <noembed> -| "<!--<noembed>" -| "-->" - -#data -<!doctype html><table> - -#errors -Line 2 Col 0 Unexpected end of file. Expected table content. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| " -" - -#data -<!doctype html><table><td><span><font></span><span> -#errors -Line 1 Col 26 Unexpected table cell start tag (td) in the table body phase. -Line 1 Col 45 Unexpected end tag (span). -Line 1 Col 51 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <span> -| <font> -| <font> -| <span> - -#data -<!doctype html><form><table></form><form></table></form> -#errors -35: Stray end tag “form”. -41: Start tag “form” seen in “table”. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <table> -| <form> diff --git a/libgo/go/exp/html/testdata/webkit/tests17.dat b/libgo/go/exp/html/testdata/webkit/tests17.dat deleted file mode 100644 index 7b555f888de..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests17.dat +++ /dev/null @@ -1,153 +0,0 @@ -#data -<!doctype html><table><tbody><select><tr> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><tr><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <table> -| <tbody> -| <tr> -| <td> - -#data -<!doctype html><table><tr><td><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <select> -| <td> - -#data -<!doctype html><table><tr><th><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <th> -| <select> -| <td> - -#data -<!doctype html><table><caption><select><tr> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| <select> -| <tbody> -| <tr> - -#data -<!doctype html><select><tr> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><th> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><tbody> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><thead> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><tfoot> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><caption> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><table><tr></table>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| "a" diff --git a/libgo/go/exp/html/testdata/webkit/tests18.dat b/libgo/go/exp/html/testdata/webkit/tests18.dat deleted file mode 100644 index 680e1f068a6..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests18.dat +++ /dev/null @@ -1,269 +0,0 @@ -#data -<!doctype html><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" - -#data -<!doctype html><table><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> - -#data -<!doctype html><table><tbody><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> -| <tbody> - -#data -<!doctype html><table><tbody><tr><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><tbody><tr><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><td><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <plaintext> -| "</plaintext>" - -#data -<!doctype html><table><caption><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| <plaintext> -| "</plaintext>" - -#data -<!doctype html><table><tr><style></script></style>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "abc" -| <table> -| <tbody> -| <tr> -| <style> -| "</script>" - -#data -<!doctype html><table><tr><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "abc" -| <table> -| <tbody> -| <tr> -| <script> -| "</style>" - -#data -<!doctype html><table><caption><style></script></style>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| <style> -| "</script>" -| "abc" - -#data -<!doctype html><table><td><style></script></style>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <style> -| "</script>" -| "abc" - -#data -<!doctype html><select><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <script> -| "</style>" -| "abc" - -#data -<!doctype html><table><select><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <script> -| "</style>" -| "abc" -| <table> - -#data -<!doctype html><table><tr><select><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <script> -| "</style>" -| "abc" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><frameset></frameset><noframes>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" - -#data -<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" -| <!-- abc --> - -#data -<!doctype html><frameset></frameset></html><noframes>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" - -#data -<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" -| <!-- abc --> - -#data -<!doctype html><table><tr></tbody><tfoot> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <tfoot> - -#data -<!doctype html><table><td><svg></svg>abc<td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <svg svg> -| "abc" -| <td> diff --git a/libgo/go/exp/html/testdata/webkit/tests19.dat b/libgo/go/exp/html/testdata/webkit/tests19.dat deleted file mode 100644 index 0d62f5a5b02..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests19.dat +++ /dev/null @@ -1,1237 +0,0 @@ -#data -<!doctype html><math><mn DefinitionUrl="foo"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <math math> -| <math mn> -| definitionURL="foo" - -#data -<!doctype html><html></p><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <!-- foo --> -| <head> -| <body> - -#data -<!doctype html><head></head></p><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <!-- foo --> -| <body> - -#data -<!doctype html><body><p><pre> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <pre> - -#data -<!doctype html><body><p><listing> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <listing> - -#data -<!doctype html><p><plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <plaintext> - -#data -<!doctype html><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <h1> - -#data -<!doctype html><form><isindex> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> - -#data -<!doctype html><isindex action="POST"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| action="POST" -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| <hr> - -#data -<!doctype html><isindex prompt="this is isindex"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "this is isindex" -| <input> -| name="isindex" -| <hr> - -#data -<!doctype html><isindex type="hidden"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| type="hidden" -| <hr> - -#data -<!doctype html><isindex name="foo"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| <hr> - -#data -<!doctype html><ruby><p><rp> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <p> -| <rp> - -#data -<!doctype html><ruby><div><span><rp> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <span> -| <rp> - -#data -<!doctype html><ruby><div><p><rp> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <p> -| <rp> - -#data -<!doctype html><ruby><p><rt> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <p> -| <rt> - -#data -<!doctype html><ruby><div><span><rt> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <span> -| <rt> - -#data -<!doctype html><ruby><div><p><rt> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <p> -| <rt> - -#data -<!doctype html><math/><foo> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <math math> -| <foo> - -#data -<!doctype html><svg/><foo> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <svg svg> -| <foo> - -#data -<!doctype html><div></body><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> -| <!-- foo --> - -#data -<!doctype html><h1><div><h3><span></h1>foo -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <h1> -| <div> -| <h3> -| <span> -| "foo" - -#data -<!doctype html><p></h3>foo -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| "foo" - -#data -<!doctype html><h3><li>abc</h2>foo -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <h3> -| <li> -| "abc" -| "foo" - -#data -<!doctype html><table>abc<!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "abc" -| <table> -| <!-- foo --> - -#data -<!doctype html><table> <!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| " " -| <!-- foo --> - -#data -<!doctype html><table> b <!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " b " -| <table> -| <!-- foo --> - -#data -<!doctype html><select><option><option> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> -| <option> - -#data -<!doctype html><select><option></optgroup> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> - -#data -<!doctype html><select><option></optgroup> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> - -#data -<!doctype html><p><math><mi><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mi> -| <p> -| <h1> - -#data -<!doctype html><p><math><mo><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mo> -| <p> -| <h1> - -#data -<!doctype html><p><math><mn><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mn> -| <p> -| <h1> - -#data -<!doctype html><p><math><ms><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math ms> -| <p> -| <h1> - -#data -<!doctype html><p><math><mtext><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mtext> -| <p> -| <h1> - -#data -<!doctype html><frameset></noframes> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><html c=d><body></html><html a=b> -#errors -#document -| <!DOCTYPE html> -| <html> -| a="b" -| c="d" -| <head> -| <body> - -#data -<!doctype html><html c=d><frameset></frameset></html><html a=b> -#errors -#document -| <!DOCTYPE html> -| <html> -| a="b" -| c="d" -| <head> -| <frameset> - -#data -<!doctype html><html><frameset></frameset></html><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <!-- foo --> - -#data -<!doctype html><html><frameset></frameset></html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| " " - -#data -<!doctype html><html><frameset></frameset></html>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><html><frameset></frameset></html><p> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><html><frameset></frameset></html></p> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<html><frameset></frameset></html><!doctype html> -#errors -#document -| <html> -| <head> -| <frameset> - -#data -<!doctype html><body><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> - -#data -<!doctype html><p><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><p>a<frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| "a" - -#data -<!doctype html><p> <frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><pre><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <pre> - -#data -<!doctype html><listing><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <listing> - -#data -<!doctype html><li><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <li> - -#data -<!doctype html><dd><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <dd> - -#data -<!doctype html><dt><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <dt> - -#data -<!doctype html><button><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <button> - -#data -<!doctype html><applet><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <applet> - -#data -<!doctype html><marquee><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <marquee> - -#data -<!doctype html><object><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <object> - -#data -<!doctype html><table><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> - -#data -<!doctype html><area><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <area> - -#data -<!doctype html><basefont><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <basefont> -| <frameset> - -#data -<!doctype html><bgsound><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <bgsound> -| <frameset> - -#data -<!doctype html><br><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <br> - -#data -<!doctype html><embed><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <embed> - -#data -<!doctype html><img><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <img> - -#data -<!doctype html><input><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <input> - -#data -<!doctype html><keygen><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <keygen> - -#data -<!doctype html><wbr><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <wbr> - -#data -<!doctype html><hr><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <hr> - -#data -<!doctype html><textarea></textarea><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> - -#data -<!doctype html><xmp></xmp><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <xmp> - -#data -<!doctype html><iframe></iframe><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <iframe> - -#data -<!doctype html><select></select><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><svg></svg><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><math></math><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><svg><foreignObject><div> <frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><svg>a</svg><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <svg svg> -| "a" - -#data -<!doctype html><svg> </svg><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<html>aaa<frameset></frameset> -#errors -#document -| <html> -| <head> -| <body> -| "aaa" - -#data -<html> a <frameset></frameset> -#errors -#document -| <html> -| <head> -| <body> -| "a " - -#data -<!doctype html><div><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><div><body><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> - -#data -<!doctype html><p><math></p>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| "a" - -#data -<!doctype html><p><math><mn><span></p>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mn> -| <span> -| <p> -| "a" - -#data -<!doctype html><math></html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <math math> - -#data -<!doctype html><meta charset="ascii"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <meta> -| charset="ascii" -| <body> - -#data -<!doctype html><meta http-equiv="content-type" content="text/html;charset=ascii"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <meta> -| content="text/html;charset=ascii" -| http-equiv="content-type" -| <body> - -#data -<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset="utf8"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <!-- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --> -| <meta> -| charset="utf8" -| <body> - -#data -<!doctype html><html a=b><head></head><html c=d> -#errors -#document -| <!DOCTYPE html> -| <html> -| a="b" -| c="d" -| <head> -| <body> - -#data -<!doctype html><image/> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <img> - -#data -<!doctype html>a<i>b<table>c<b>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "a" -| <i> -| "bc" -| <b> -| "de" -| "f" -| <table> - -#data -<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <b> -| <i> -| "c" -| <a> -| "d" -| <a> -| "e" -| <a> -| "f" -| <table> - -#data -<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <b> -| <i> -| "c" -| <a> -| "d" -| <a> -| "e" -| <a> -| "f" - -#data -<!doctype html><table><i>a<b>b<div>c</i> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <i> -| "c" -| <table> - -#data -<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <b> -| <i> -| "c" -| <a> -| "d" -| <a> -| "e" -| <a> -| "f" -| <table> - -#data -<!doctype html><table><i>a<div>b<tr>c<b>d</i>e -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <div> -| "b" -| <i> -| "c" -| <b> -| "d" -| <b> -| "e" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><td><table><i>a<div>b<b>c</i>d -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <i> -| "a" -| <div> -| <i> -| "b" -| <b> -| "c" -| <b> -| "d" -| <table> - -#data -<!doctype html><body><bgsound> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <bgsound> - -#data -<!doctype html><body><basefont> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <basefont> - -#data -<!doctype html><a><b></a><basefont> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <a> -| <b> -| <basefont> - -#data -<!doctype html><a><b></a><bgsound> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <a> -| <b> -| <bgsound> - -#data -<!doctype html><figcaption><article></figcaption>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <figcaption> -| <article> -| "a" - -#data -<!doctype html><summary><article></summary>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <summary> -| <article> -| "a" - -#data -<!doctype html><p><a><plaintext>b -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <a> -| <plaintext> -| <a> -| "b" - -#data -<!DOCTYPE html><div>a<a></div>b<p>c</p>d -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> -| "a" -| <a> -| <a> -| "b" -| <p> -| "c" -| "d" diff --git a/libgo/go/exp/html/testdata/webkit/tests2.dat b/libgo/go/exp/html/testdata/webkit/tests2.dat deleted file mode 100644 index 60d85922162..00000000000 --- a/libgo/go/exp/html/testdata/webkit/tests2.dat +++ /dev/null @@ -1,763 +0,0 @@ -#data -<!DOCTYPE html>Test -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "Test" - -#data -<textarea>test</div>test -#errors -Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. -Line: 1 Col: 24 Expected closing tag. Unexpected end of file. -#document -| <html> -| <head> -| <body> -| <textarea> -| "test</div>test" - -#data -<table><td> -#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase. -Line: 1 Col: 11 Expected closing tag. Unexpected end of file. -#document -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> - -#data -<table><td>test</tbody></table> -#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase. -#document -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| "test" - -#data -<frame>test -#errors -Line: 1 Col: 7 Unexpected start tag (frame). Expected DOCTYPE. -Line: 1 Col: 7 Unexpected start tag frame. Ignored. -#document -| <html> -| <head> -| <body> -| "test" - -#data -<!DOCTYPE html><frameset>test -#errors -Line: 1 Col: 29 Unepxected characters in the frameset phase. Characters ignored. -Line: 1 Col: 29 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!DOCTYPE html><frameset><!DOCTYPE html> -#errors -Line: 1 Col: 40 Unexpected DOCTYPE. Ignored. -Line: 1 Col: 40 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!DOCTYPE html><font><p><b>test</font> -#errors -Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. -Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <font> -| <p> -| <font> -| <b> -| "test" - -#data -<!DOCTYPE html><dt><div><dd> -#errors -Line: 1 Col: 28 Missing end tag (div, dt). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <dt> -| <div> -| <dd> - -#data -<script></x -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</x" -| <body> - -#data -<table><plaintext><td> -#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 18 Unexpected start tag (plaintext) in table context caused voodoo mode. -Line: 1 Col: 22 Unexpected end of file. Expected table content. -#document -| <html> -| <head> -| <body> -| <plaintext> -| "<td>" -| <table> - -#data -<plaintext></plaintext> -#errors -Line: 1 Col: 11 Unexpected start tag (plaintext). Expected DOCTYPE. -Line: 1 Col: 23 Expected closing tag. Unexpected end of file. -#document -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" - -#data -<!DOCTYPE html><table><tr>TEST -#errors -Line: 1 Col: 30 Unexpected non-space characters in table context caused voodoo mode. -Line: 1 Col: 30 Unexpected end of file. Expected table content. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "TEST" -| <table> -| <tbody> -| <tr> - -#data -<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4> -#errors -Line: 1 Col: 37 Unexpected start tag (body). -Line: 1 Col: 53 Unexpected start tag (body). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| t1="1" -| t2="2" -| t3="3" -| t4="4" - -#data -</b test -#errors -Line: 1 Col: 8 Unexpected end of file in attribute name. -Line: 1 Col: 8 End tag contains unexpected attributes. -Line: 1 Col: 8 Unexpected end tag (b). Expected DOCTYPE. -Line: 1 Col: 8 Unexpected end tag (b) after the (implied) root element. -#document -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html></b test<b &=&>X -#errors -Line: 1 Col: 32 Named entity didn't end with ';'. -Line: 1 Col: 33 End tag contains unexpected attributes. -Line: 1 Col: 33 Unexpected end tag (b) after the (implied) root element. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "X" - -#data -<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -Line: 1 Col: 54 Unexpected end of file in the tag name. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| type="text/x-foobar;baz" -| "X</SCRipt" -| <body> - -#data -& -#errors -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&" - -#data -&# -#errors -Line: 1 Col: 1 Numeric entity expected. Got end of file instead. -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&#" - -#data -&#X -#errors -Line: 1 Col: 3 Numeric entity expected but none found. -Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&#X" - -#data -&#x -#errors -Line: 1 Col: 3 Numeric entity expected but none found. -Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&#x" - -#data -- -#errors -Line: 1 Col: 4 Numeric entity didn't end with ';'. -Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "-" - -#data -&x-test -#errors -Line: 1 Col: 1 Named entity expected. Got none. -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&x-test" - -#data -<!doctypehtml><p><li> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <li> - -#data -<!doctypehtml><p><dt> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <dt> - -#data -<!doctypehtml><p><dd> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <dd> - -#data -<!doctypehtml><p><form> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -Line: 1 Col: 23 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <form> - -#data -<!DOCTYPE html><p></P>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| "X" - -#data -& -#errors -Line: 1 Col: 4 Named entity didn't end with ';'. -Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&" - -#data -&AMp; -#errors -Line: 1 Col: 1 Named entity expected. Got none. -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&AMp;" - -#data -<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY> -#errors -Line: 1 Col: 110 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <thisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly> - -#data -<!DOCTYPE html>X</body>X -#errors -Line: 1 Col: 24 Unexpected non-space characters in the after body phase. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "XX" - -#data -<!DOCTYPE html><!-- X -#errors -Line: 1 Col: 21 Unexpected end of file in comment. -#document -| <!DOCTYPE html> -| <!-- X --> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><table><caption>test TEST</caption><td>test -#errors -Line: 1 Col: 54 Unexpected table cell start tag (td) in the table body phase. -Line: 1 Col: 58 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| "test TEST" -| <tbody> -| <tr> -| <td> -| "test" - -#data -<!DOCTYPE html><select><option><optgroup> -#errors -Line: 1 Col: 41 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> -| <optgroup> - -#data -<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option> -#errors -Line: 1 Col: 68 Unexpected select start tag in the select phase treated as select end tag. -Line: 1 Col: 76 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <optgroup> -| <option> -| <option> -| <option> - -#data -<!DOCTYPE html><select><optgroup><option><optgroup> -#errors -Line: 1 Col: 51 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <optgroup> -| <option> -| <optgroup> - -#data -<!DOCTYPE html><datalist><option>foo</datalist>bar -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <datalist> -| <option> -| "foo" -| "bar" - -#data -<!DOCTYPE html><font><input><input></font> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <font> -| <input> -| <input> - -#data -<!DOCTYPE html><!-- XXX - XXX --> -#errors -#document -| <!DOCTYPE html> -| <!-- XXX - XXX --> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><!-- XXX - XXX -#errors -Line: 1 Col: 29 Unexpected end of file in comment (-) -#document -| <!DOCTYPE html> -| <!-- XXX - XXX --> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><!-- XXX - XXX - XXX --> -#errors -#document -| <!DOCTYPE html> -| <!-- XXX - XXX - XXX --> -| <html> -| <head> -| <body> - -#data -<isindex test=x name=x> -#errors -Line: 1 Col: 23 Unexpected start tag (isindex). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected start tag isindex. Don't use it! -#document -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| test="x" -| <hr> - -#data -test -test -#errors -Line: 2 Col: 4 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "test -test" - -#data -<!DOCTYPE html><body><title>test</body> -#errors -#document -| -| -| -| -| -| "test</body>" - -#data -<!DOCTYPE html><body><title>X -#errors -#document -| -| -| -| -| -| "X" -| <meta> -| name="z" -| <link> -| rel="foo" -| <style> -| " -x { content:"</style" } " - -#data -<!DOCTYPE html><select><optgroup></optgroup></select> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <optgroup> - -#data - - -#errors -Line: 2 Col: 1 Unexpected End of file. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html> <html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><script> -</script> <title>x -#errors -#document -| -| -| -| -#errors -Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected start tag (script) that can be in head. Moved. -#document -| -| -| -#errors -Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. -Line: 1 Col: 28 Unexpected start tag (style) that can be in head. Moved. -#document -| -| -| -#errors -Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. -#document -| -| -| -| -| "x" -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (style). -#document -| -| -| --> x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -|

-#errors -#document -| -| -| -| -| -| ddd -#errors -#document -| -| -| -#errors -#document -| -| -| -| -|
  • -| -| ", - "