]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libgo: Update to weekly.2012-01-27.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 1 Feb 2012 19:26:59 +0000 (19:26 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 1 Feb 2012 19:26:59 +0000 (19:26 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183810 138bc75d-0d04-0410-961f-82ee72b054a4

277 files changed:
libgo/MERGE
libgo/Makefile.am
libgo/Makefile.in
libgo/go/archive/tar/reader.go
libgo/go/archive/tar/reader_test.go
libgo/go/archive/zip/reader.go
libgo/go/archive/zip/reader_test.go
libgo/go/archive/zip/struct.go
libgo/go/archive/zip/writer.go
libgo/go/archive/zip/zip_test.go
libgo/go/bytes/buffer.go
libgo/go/compress/flate/deflate.go
libgo/go/compress/flate/deflate_test.go
libgo/go/compress/flate/huffman_bit_writer.go
libgo/go/compress/flate/huffman_code.go
libgo/go/compress/flate/util.go [deleted file]
libgo/go/compress/gzip/gunzip.go
libgo/go/compress/gzip/gunzip_test.go
libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt [new file with mode: 0644]
libgo/go/compress/zlib/reader.go
libgo/go/compress/zlib/reader_test.go
libgo/go/crypto/bcrypt/base64.go [deleted file]
libgo/go/crypto/bcrypt/bcrypt.go [deleted file]
libgo/go/crypto/bcrypt/bcrypt_test.go [deleted file]
libgo/go/crypto/blowfish/block.go [deleted file]
libgo/go/crypto/blowfish/blowfish_test.go [deleted file]
libgo/go/crypto/blowfish/cipher.go [deleted file]
libgo/go/crypto/blowfish/const.go [deleted file]
libgo/go/crypto/cast5/cast5.go [deleted file]
libgo/go/crypto/cast5/cast5_test.go [deleted file]
libgo/go/crypto/dsa/dsa.go
libgo/go/crypto/md4/md4.go [deleted file]
libgo/go/crypto/md4/md4_test.go [deleted file]
libgo/go/crypto/md4/md4block.go [deleted file]
libgo/go/crypto/ocsp/ocsp.go [deleted file]
libgo/go/crypto/ocsp/ocsp_test.go [deleted file]
libgo/go/crypto/openpgp/armor/armor.go [deleted file]
libgo/go/crypto/openpgp/armor/armor_test.go [deleted file]
libgo/go/crypto/openpgp/armor/encode.go [deleted file]
libgo/go/crypto/openpgp/canonical_text.go [deleted file]
libgo/go/crypto/openpgp/canonical_text_test.go [deleted file]
libgo/go/crypto/openpgp/elgamal/elgamal.go [deleted file]
libgo/go/crypto/openpgp/elgamal/elgamal_test.go [deleted file]
libgo/go/crypto/openpgp/errors/errors.go [deleted file]
libgo/go/crypto/openpgp/keys.go [deleted file]
libgo/go/crypto/openpgp/packet/compressed.go [deleted file]
libgo/go/crypto/openpgp/packet/compressed_test.go [deleted file]
libgo/go/crypto/openpgp/packet/encrypted_key.go [deleted file]
libgo/go/crypto/openpgp/packet/encrypted_key_test.go [deleted file]
libgo/go/crypto/openpgp/packet/literal.go [deleted file]
libgo/go/crypto/openpgp/packet/one_pass_signature.go [deleted file]
libgo/go/crypto/openpgp/packet/packet.go [deleted file]
libgo/go/crypto/openpgp/packet/packet_test.go [deleted file]
libgo/go/crypto/openpgp/packet/private_key.go [deleted file]
libgo/go/crypto/openpgp/packet/private_key_test.go [deleted file]
libgo/go/crypto/openpgp/packet/public_key.go [deleted file]
libgo/go/crypto/openpgp/packet/public_key_test.go [deleted file]
libgo/go/crypto/openpgp/packet/reader.go [deleted file]
libgo/go/crypto/openpgp/packet/signature.go [deleted file]
libgo/go/crypto/openpgp/packet/signature_test.go [deleted file]
libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go [deleted file]
libgo/go/crypto/openpgp/packet/symmetric_key_encrypted_test.go [deleted file]
libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go [deleted file]
libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go [deleted file]
libgo/go/crypto/openpgp/packet/userid.go [deleted file]
libgo/go/crypto/openpgp/packet/userid_test.go [deleted file]
libgo/go/crypto/openpgp/read.go [deleted file]
libgo/go/crypto/openpgp/read_test.go [deleted file]
libgo/go/crypto/openpgp/s2k/s2k.go [deleted file]
libgo/go/crypto/openpgp/s2k/s2k_test.go [deleted file]
libgo/go/crypto/openpgp/write.go [deleted file]
libgo/go/crypto/openpgp/write_test.go [deleted file]
libgo/go/crypto/ripemd160/ripemd160.go [deleted file]
libgo/go/crypto/ripemd160/ripemd160_test.go [deleted file]
libgo/go/crypto/ripemd160/ripemd160block.go [deleted file]
libgo/go/crypto/tls/root_stub.go
libgo/go/crypto/twofish/twofish.go [deleted file]
libgo/go/crypto/twofish/twofish_test.go [deleted file]
libgo/go/crypto/xtea/block.go [deleted file]
libgo/go/crypto/xtea/cipher.go [deleted file]
libgo/go/crypto/xtea/xtea_test.go [deleted file]
libgo/go/database/sql/convert.go
libgo/go/database/sql/fakedb_test.go
libgo/go/database/sql/sql.go
libgo/go/database/sql/sql_test.go
libgo/go/encoding/binary/varint.go
libgo/go/encoding/binary/varint_test.go
libgo/go/encoding/git85/git.go [deleted file]
libgo/go/encoding/git85/git_test.go [deleted file]
libgo/go/encoding/gob/debug.go
libgo/go/encoding/gob/decoder.go
libgo/go/encoding/gob/gobencdec_test.go
libgo/go/encoding/xml/marshal.go
libgo/go/encoding/xml/marshal_test.go
libgo/go/encoding/xml/read.go
libgo/go/encoding/xml/read_test.go
libgo/go/encoding/xml/typeinfo.go
libgo/go/encoding/xml/xml.go
libgo/go/encoding/xml/xml_test.go
libgo/go/exp/ebnflint/ebnflint.go
libgo/go/exp/ebnflint/ebnflint_test.go [new file with mode: 0644]
libgo/go/exp/html/const.go [moved from libgo/go/html/const.go with 100% similarity]
libgo/go/exp/html/doc.go [moved from libgo/go/html/doc.go with 100% similarity]
libgo/go/exp/html/doctype.go [moved from libgo/go/html/doctype.go with 100% similarity]
libgo/go/exp/html/entity.go [new file with mode: 0644]
libgo/go/exp/html/entity_test.go [new file with mode: 0644]
libgo/go/exp/html/escape.go [new file with mode: 0644]
libgo/go/exp/html/foreign.go [moved from libgo/go/html/foreign.go with 100% similarity]
libgo/go/exp/html/node.go [moved from libgo/go/html/node.go with 100% similarity]
libgo/go/exp/html/parse.go [moved from libgo/go/html/parse.go with 100% similarity]
libgo/go/exp/html/parse_test.go [moved from libgo/go/html/parse_test.go with 100% similarity]
libgo/go/exp/html/render.go [moved from libgo/go/html/render.go with 100% similarity]
libgo/go/exp/html/render_test.go [moved from libgo/go/html/render_test.go with 100% similarity]
libgo/go/exp/html/testdata/webkit/README [moved from libgo/go/html/testdata/webkit/README with 100% similarity]
libgo/go/exp/html/testdata/webkit/adoption01.dat [moved from libgo/go/html/testdata/webkit/adoption01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/adoption02.dat [moved from libgo/go/html/testdata/webkit/adoption02.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/comments01.dat [moved from libgo/go/html/testdata/webkit/comments01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/doctype01.dat [moved from libgo/go/html/testdata/webkit/doctype01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/entities01.dat [moved from libgo/go/html/testdata/webkit/entities01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/entities02.dat [moved from libgo/go/html/testdata/webkit/entities02.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/html5test-com.dat [moved from libgo/go/html/testdata/webkit/html5test-com.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/inbody01.dat [moved from libgo/go/html/testdata/webkit/inbody01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/isindex.dat [moved from libgo/go/html/testdata/webkit/isindex.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat [moved from libgo/go/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/pending-spec-changes.dat [moved from libgo/go/html/testdata/webkit/pending-spec-changes.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/plain-text-unsafe.dat [moved from libgo/go/html/testdata/webkit/plain-text-unsafe.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/scriptdata01.dat [moved from libgo/go/html/testdata/webkit/scriptdata01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/scripted/adoption01.dat [moved from libgo/go/html/testdata/webkit/scripted/adoption01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/scripted/webkit01.dat [moved from libgo/go/html/testdata/webkit/scripted/webkit01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tables01.dat [moved from libgo/go/html/testdata/webkit/tables01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests1.dat [moved from libgo/go/html/testdata/webkit/tests1.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests10.dat [moved from libgo/go/html/testdata/webkit/tests10.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests11.dat [moved from libgo/go/html/testdata/webkit/tests11.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests12.dat [moved from libgo/go/html/testdata/webkit/tests12.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests14.dat [moved from libgo/go/html/testdata/webkit/tests14.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests15.dat [moved from libgo/go/html/testdata/webkit/tests15.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests16.dat [moved from libgo/go/html/testdata/webkit/tests16.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests17.dat [moved from libgo/go/html/testdata/webkit/tests17.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests18.dat [moved from libgo/go/html/testdata/webkit/tests18.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests19.dat [moved from libgo/go/html/testdata/webkit/tests19.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests2.dat [moved from libgo/go/html/testdata/webkit/tests2.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests20.dat [moved from libgo/go/html/testdata/webkit/tests20.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests21.dat [moved from libgo/go/html/testdata/webkit/tests21.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests22.dat [moved from libgo/go/html/testdata/webkit/tests22.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests23.dat [moved from libgo/go/html/testdata/webkit/tests23.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests24.dat [moved from libgo/go/html/testdata/webkit/tests24.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests25.dat [moved from libgo/go/html/testdata/webkit/tests25.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests26.dat [moved from libgo/go/html/testdata/webkit/tests26.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests3.dat [moved from libgo/go/html/testdata/webkit/tests3.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests4.dat [moved from libgo/go/html/testdata/webkit/tests4.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests5.dat [moved from libgo/go/html/testdata/webkit/tests5.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests6.dat [moved from libgo/go/html/testdata/webkit/tests6.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests7.dat [moved from libgo/go/html/testdata/webkit/tests7.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests8.dat [moved from libgo/go/html/testdata/webkit/tests8.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests9.dat [moved from libgo/go/html/testdata/webkit/tests9.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tests_innerHTML_1.dat [moved from libgo/go/html/testdata/webkit/tests_innerHTML_1.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/tricky01.dat [moved from libgo/go/html/testdata/webkit/tricky01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/webkit01.dat [moved from libgo/go/html/testdata/webkit/webkit01.dat with 100% similarity]
libgo/go/exp/html/testdata/webkit/webkit02.dat [moved from libgo/go/html/testdata/webkit/webkit02.dat with 100% similarity]
libgo/go/exp/html/token.go [moved from libgo/go/html/token.go with 100% similarity]
libgo/go/exp/html/token_test.go [moved from libgo/go/html/token_test.go with 100% similarity]
libgo/go/exp/norm/tables.go
libgo/go/exp/norm/triegen.go
libgo/go/exp/spdy/read.go [deleted file]
libgo/go/exp/spdy/spdy_test.go [deleted file]
libgo/go/exp/spdy/types.go [deleted file]
libgo/go/exp/spdy/write.go [deleted file]
libgo/go/exp/ssh/channel.go [deleted file]
libgo/go/exp/ssh/cipher.go [deleted file]
libgo/go/exp/ssh/cipher_test.go [deleted file]
libgo/go/exp/ssh/client.go [deleted file]
libgo/go/exp/ssh/client_auth.go [deleted file]
libgo/go/exp/ssh/client_auth_test.go [deleted file]
libgo/go/exp/ssh/client_func_test.go [deleted file]
libgo/go/exp/ssh/common.go [deleted file]
libgo/go/exp/ssh/common_test.go [deleted file]
libgo/go/exp/ssh/doc.go [deleted file]
libgo/go/exp/ssh/messages.go [deleted file]
libgo/go/exp/ssh/messages_test.go [deleted file]
libgo/go/exp/ssh/server.go [deleted file]
libgo/go/exp/ssh/server_terminal.go [deleted file]
libgo/go/exp/ssh/session.go [deleted file]
libgo/go/exp/ssh/session_test.go [deleted file]
libgo/go/exp/ssh/tcpip.go [deleted file]
libgo/go/exp/ssh/tcpip_func_test.go [deleted file]
libgo/go/exp/ssh/transport.go [deleted file]
libgo/go/exp/ssh/transport_test.go [deleted file]
libgo/go/go/ast/import.go
libgo/go/go/build/build.go
libgo/go/go/build/build_test.go
libgo/go/go/build/dir.go
libgo/go/go/build/path.go
libgo/go/go/doc/doc.go
libgo/go/go/doc/doc_test.go
libgo/go/go/doc/exports.go
libgo/go/go/doc/filter.go
libgo/go/go/doc/reader.go
libgo/go/go/doc/testdata/a.0.golden [moved from libgo/go/go/doc/testdata/a.out with 100% similarity]
libgo/go/go/doc/testdata/a.1.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/b.0.golden [moved from libgo/go/go/doc/testdata/b.out with 59% similarity]
libgo/go/go/doc/testdata/b.1.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/b.go
libgo/go/go/doc/testdata/c.0.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/c.1.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/c.go [new file with mode: 0644]
libgo/go/go/doc/testdata/d.0.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/d.1.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/d1.go [new file with mode: 0644]
libgo/go/go/doc/testdata/d2.go [new file with mode: 0644]
libgo/go/go/doc/testdata/e.0.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/e.1.golden [new file with mode: 0644]
libgo/go/go/doc/testdata/e.go [new file with mode: 0644]
libgo/go/go/doc/testdata/testing.0.golden [moved from libgo/go/go/doc/testdata/testing.out with 100% similarity]
libgo/go/go/doc/testdata/testing.1.golden [new file with mode: 0644]
libgo/go/go/parser/interface.go
libgo/go/go/parser/parser.go
libgo/go/go/printer/nodes.go
libgo/go/go/printer/printer.go
libgo/go/go/printer/testdata/declarations.golden
libgo/go/go/printer/testdata/linebreaks.golden
libgo/go/go/printer/testdata/linebreaks.input
libgo/go/go/scanner/scanner.go
libgo/go/go/scanner/scanner_test.go
libgo/go/html/escape.go
libgo/go/io/ioutil/ioutil.go
libgo/go/math/big/arith.go
libgo/go/math/big/arith_decl.go
libgo/go/math/big/arith_test.go
libgo/go/net/cgo_stub.go
libgo/go/net/dial.go
libgo/go/net/dialgoogle_test.go
libgo/go/net/dict/dict.go [deleted file]
libgo/go/net/fd.go
libgo/go/net/fd_windows.go
libgo/go/net/http/client.go
libgo/go/net/http/client_test.go
libgo/go/net/http/readrequest_test.go
libgo/go/net/http/request.go
libgo/go/net/http/request_test.go
libgo/go/net/http/transport.go
libgo/go/net/http/transport_test.go
libgo/go/net/ipraw_test.go
libgo/go/net/iprawsock_plan9.go
libgo/go/net/iprawsock_posix.go
libgo/go/net/lookup_plan9.go
libgo/go/net/rpc/client.go
libgo/go/net/rpc/server_test.go
libgo/go/net/sock.go
libgo/go/net/sockopt.go
libgo/go/net/tcpsock_plan9.go
libgo/go/net/tcpsock_posix.go
libgo/go/net/timeout_test.go
libgo/go/net/udp_test.go [new file with mode: 0644]
libgo/go/net/udpsock_plan9.go
libgo/go/net/udpsock_posix.go
libgo/go/net/unixsock_posix.go
libgo/go/os/file_plan9.go
libgo/go/os/stat_plan9.go
libgo/go/os/user/lookup_stubs.go
libgo/go/patch/apply.go [deleted file]
libgo/go/patch/git.go [deleted file]
libgo/go/patch/patch.go [deleted file]
libgo/go/patch/patch_test.go [deleted file]
libgo/go/patch/textdiff.go [deleted file]
libgo/go/path/filepath/path_test.go
libgo/go/regexp/regexp.go
libgo/go/runtime/chan_test.go
libgo/go/runtime/debug.go
libgo/go/runtime/extern.go
libgo/go/websocket/client.go [deleted file]
libgo/go/websocket/hixie.go [deleted file]
libgo/go/websocket/hixie_test.go [deleted file]
libgo/go/websocket/hybi.go [deleted file]
libgo/go/websocket/hybi_test.go [deleted file]
libgo/go/websocket/server.go [deleted file]
libgo/go/websocket/websocket.go [deleted file]
libgo/go/websocket/websocket_test.go [deleted file]

index 4207948a9cb2f7b5e6c779c489fe400a46c3b019..b9b249315a6d2854301bcf9b65ae57a26701ee77 100644 (file)
@@ -1,4 +1,4 @@
-9f2be4fbbf69
+1107a7d3cb07
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
index d6578156b8d411fe86e4368fdc75b8e1ff5534fd..3f5bb2ff5b2c2ba71b2f605c6f4f730b24f9f7bd 100644 (file)
@@ -116,7 +116,6 @@ toolexeclibgo_DATA = \
        mime.gox \
        net.gox \
        os.gox \
-       patch.gox \
        path.gox \
        reflect.gox \
        regexp.gox \
@@ -128,8 +127,7 @@ toolexeclibgo_DATA = \
        syscall.gox \
        testing.gox \
        time.gox \
-       unicode.gox \
-       websocket.gox
+       unicode.gox
 
 toolexeclibgoarchivedir = $(toolexeclibgodir)/archive
 
@@ -157,40 +155,22 @@ toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
 
 toolexeclibgocrypto_DATA = \
        crypto/aes.gox \
-       crypto/bcrypt.gox \
-       crypto/blowfish.gox \
-       crypto/cast5.gox \
        crypto/cipher.gox \
        crypto/des.gox \
        crypto/dsa.gox \
        crypto/ecdsa.gox \
        crypto/elliptic.gox \
        crypto/hmac.gox \
-       crypto/md4.gox \
        crypto/md5.gox \
-       crypto/ocsp.gox \
-       crypto/openpgp.gox \
        crypto/rand.gox \
        crypto/rc4.gox \
-       crypto/ripemd160.gox \
        crypto/rsa.gox \
        crypto/sha1.gox \
        crypto/sha256.gox \
        crypto/sha512.gox \
        crypto/subtle.gox \
        crypto/tls.gox \
-       crypto/twofish.gox \
-       crypto/x509.gox \
-       crypto/xtea.gox
-
-toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
-
-toolexeclibgocryptoopenpgp_DATA = \
-       crypto/openpgp/armor.gox \
-       crypto/openpgp/elgamal.gox \
-       crypto/openpgp/errors.gox \
-       crypto/openpgp/packet.gox \
-       crypto/openpgp/s2k.gox
+       crypto/x509.gox
 
 toolexeclibgocryptox509dir = $(toolexeclibgocryptodir)/x509
 
@@ -225,7 +205,6 @@ toolexeclibgoencoding_DATA = \
        encoding/base64.gox \
        encoding/binary.gox \
        encoding/csv.gox \
-       encoding/git85.gox \
        encoding/gob.gox \
        encoding/hex.gox \
        encoding/json.gox \
@@ -243,11 +222,10 @@ toolexeclibgoexpdir = $(toolexeclibgodir)/exp
 
 toolexeclibgoexp_DATA = \
        exp/ebnf.gox \
+       exp/html.gox \
        $(exp_inotify_gox) \
        exp/norm.gox \
        exp/proxy.gox \
-       exp/spdy.gox \
-       exp/ssh.gox \
        exp/terminal.gox \
        exp/types.gox \
        exp/utf8string.gox
@@ -317,7 +295,6 @@ toolexeclibgomime_DATA = \
 toolexeclibgonetdir = $(toolexeclibgodir)/net
 
 toolexeclibgonet_DATA = \
-       net/dict.gox \
        net/http.gox \
        net/mail.gox \
        net/rpc.gox \
@@ -577,16 +554,8 @@ go_hash_files = \
        go/hash/hash.go
 
 go_html_files = \
-       go/html/const.go \
-       go/html/doc.go \
-       go/html/doctype.go \
        go/html/entity.go \
-       go/html/escape.go \
-       go/html/foreign.go \
-       go/html/node.go \
-       go/html/parse.go \
-       go/html/render.go \
-       go/html/token.go
+       go/html/escape.go
 
 go_image_files = \
        go/image/format.go \
@@ -821,12 +790,6 @@ go_os_files = \
        go/os/types.go \
        signal_unix.go
 
-go_patch_files = \
-       go/patch/apply.go \
-       go/patch/git.go \
-       go/patch/patch.go \
-       go/patch/textdiff.go
-
 go_path_files = \
        go/path/match.go \
        go/path/path.go
@@ -929,13 +892,6 @@ go_unicode_files = \
        go/unicode/letter.go \
        go/unicode/tables.go
 
-go_websocket_files = \
-       go/websocket/client.go \
-       go/websocket/hixie.go \
-       go/websocket/hybi.go \
-       go/websocket/server.go \
-       go/websocket/websocket.go
-
 
 go_archive_tar_files = \
        go/archive/tar/common.go \
@@ -959,8 +915,7 @@ go_compress_flate_files = \
        go/compress/flate/huffman_code.go \
        go/compress/flate/inflate.go \
        go/compress/flate/reverse_bits.go \
-       go/compress/flate/token.go \
-       go/compress/flate/util.go
+       go/compress/flate/token.go
 
 go_compress_gzip_files = \
        go/compress/gzip/gzip.go \
@@ -987,15 +942,6 @@ go_crypto_aes_files = \
        go/crypto/aes/block.go \
        go/crypto/aes/cipher.go \
        go/crypto/aes/const.go
-go_crypto_bcrypt_files = \
-       go/crypto/bcrypt/base64.go \
-       go/crypto/bcrypt/bcrypt.go
-go_crypto_blowfish_files = \
-       go/crypto/blowfish/block.go \
-       go/crypto/blowfish/const.go \
-       go/crypto/blowfish/cipher.go
-go_crypto_cast5_files = \
-       go/crypto/cast5/cast5.go
 go_crypto_cipher_files = \
        go/crypto/cipher/cbc.go \
        go/crypto/cipher/cfb.go \
@@ -1017,28 +963,15 @@ go_crypto_elliptic_files = \
        go/crypto/elliptic/p224.go
 go_crypto_hmac_files = \
        go/crypto/hmac/hmac.go
-go_crypto_md4_files = \
-       go/crypto/md4/md4.go \
-       go/crypto/md4/md4block.go
 go_crypto_md5_files = \
        go/crypto/md5/md5.go \
        go/crypto/md5/md5block.go
-go_crypto_ocsp_files = \
-       go/crypto/ocsp/ocsp.go
-go_crypto_openpgp_files = \
-       go/crypto/openpgp/canonical_text.go \
-       go/crypto/openpgp/keys.go \
-       go/crypto/openpgp/read.go \
-       go/crypto/openpgp/write.go
 go_crypto_rand_files = \
        go/crypto/rand/rand.go \
        go/crypto/rand/rand_unix.go \
        go/crypto/rand/util.go
 go_crypto_rc4_files = \
        go/crypto/rc4/rc4.go
-go_crypto_ripemd160_files = \
-       go/crypto/ripemd160/ripemd160.go \
-       go/crypto/ripemd160/ripemd160block.go
 go_crypto_rsa_files = \
        go/crypto/rsa/pkcs1v15.go \
        go/crypto/rsa/rsa.go
@@ -1065,40 +998,12 @@ go_crypto_tls_files = \
        go/crypto/tls/prf.go \
        go/crypto/tls/root_unix.go \
        go/crypto/tls/tls.go
-go_crypto_twofish_files = \
-       go/crypto/twofish/twofish.go
 go_crypto_x509_files = \
        go/crypto/x509/cert_pool.go \
        go/crypto/x509/pkcs1.go \
        go/crypto/x509/pkcs8.go \
        go/crypto/x509/verify.go \
        go/crypto/x509/x509.go
-go_crypto_xtea_files = \
-       go/crypto/xtea/block.go \
-       go/crypto/xtea/cipher.go
-
-go_crypto_openpgp_armor_files = \
-       go/crypto/openpgp/armor/armor.go \
-       go/crypto/openpgp/armor/encode.go
-go_crypto_openpgp_elgamal_files = \
-       go/crypto/openpgp/elgamal/elgamal.go
-go_crypto_openpgp_errors_files = \
-       go/crypto/openpgp/errors/errors.go
-go_crypto_openpgp_packet_files = \
-       go/crypto/openpgp/packet/compressed.go \
-       go/crypto/openpgp/packet/encrypted_key.go \
-       go/crypto/openpgp/packet/literal.go \
-       go/crypto/openpgp/packet/one_pass_signature.go \
-       go/crypto/openpgp/packet/packet.go \
-       go/crypto/openpgp/packet/private_key.go \
-       go/crypto/openpgp/packet/public_key.go \
-       go/crypto/openpgp/packet/reader.go \
-       go/crypto/openpgp/packet/signature.go \
-       go/crypto/openpgp/packet/symmetric_key_encrypted.go \
-       go/crypto/openpgp/packet/symmetrically_encrypted.go \
-       go/crypto/openpgp/packet/userid.go
-go_crypto_openpgp_s2k_files = \
-       go/crypto/openpgp/s2k/s2k.go
 
 go_crypto_x509_pkix_files = \
        go/crypto/x509/pkix/pkix.go
@@ -1147,8 +1052,6 @@ go_encoding_binary_files = \
 go_encoding_csv_files = \
        go/encoding/csv/reader.go \
        go/encoding/csv/writer.go
-go_encoding_git85_files = \
-       go/encoding/git85/git.go
 go_encoding_gob_files = \
        go/encoding/gob/decode.go \
        go/encoding/gob/decoder.go \
@@ -1177,6 +1080,17 @@ go_encoding_xml_files = \
 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_inotify_files = \
        go/exp/inotify/inotify_linux.go
 go_exp_norm_files = \
@@ -1192,23 +1106,6 @@ go_exp_proxy_files = \
        go/exp/proxy/per_host.go \
        go/exp/proxy/proxy.go \
        go/exp/proxy/socks5.go
-go_exp_spdy_files = \
-       go/exp/spdy/read.go \
-       go/exp/spdy/types.go \
-       go/exp/spdy/write.go
-go_exp_ssh_files = \
-       go/exp/ssh/channel.go \
-       go/exp/ssh/cipher.go \
-       go/exp/ssh/client.go \
-       go/exp/ssh/client_auth.go \
-       go/exp/ssh/common.go \
-       go/exp/ssh/doc.go \
-       go/exp/ssh/messages.go \
-       go/exp/ssh/server.go \
-       go/exp/ssh/server_terminal.go \
-       go/exp/ssh/session.go \
-       go/exp/ssh/tcpip.go \
-       go/exp/ssh/transport.go
 go_exp_terminal_files = \
        go/exp/terminal/terminal.go \
        go/exp/terminal/util.go
@@ -1351,8 +1248,6 @@ go_mime_multipart_files = \
        go/mime/multipart/multipart.go \
        go/mime/multipart/writer.go
 
-go_net_dict_files = \
-       go/net/dict/dict.go
 go_net_http_files = \
        go/net/http/chunked.go \
        go/net/http/client.go \
@@ -1717,7 +1612,6 @@ libgo_go_objs = \
        net/net.lo \
        os/exec.lo \
        os/os.lo \
-       patch/patch.lo \
        path/path.lo \
        reflect/reflect.lo \
        regexp/regexp.lo \
@@ -1728,7 +1622,6 @@ libgo_go_objs = \
        sync/sync.lo \
        time/time.lo \
        unicode/unicode.lo \
-       websocket/websocket.lo \
        archive/tar.lo \
        archive/zip.lo \
        compress/bzip2.lo \
@@ -1740,36 +1633,22 @@ libgo_go_objs = \
        container/list.lo \
        container/ring.lo \
        crypto/aes.lo \
-       crypto/bcrypt.lo \
-       crypto/blowfish.lo \
-       crypto/cast5.lo \
        crypto/cipher.lo \
        crypto/des.lo \
        crypto/dsa.lo \
        crypto/ecdsa.lo \
        crypto/elliptic.lo \
        crypto/hmac.lo \
-       crypto/md4.lo \
        crypto/md5.lo \
-       crypto/ocsp.lo \
-       crypto/openpgp.lo \
        crypto/rand.lo \
        crypto/rc4.lo \
-       crypto/ripemd160.lo \
        crypto/rsa.lo \
        crypto/sha1.lo \
        crypto/sha256.lo \
        crypto/sha512.lo \
        crypto/subtle.lo \
        crypto/tls.lo \
-       crypto/twofish.lo \
        crypto/x509.lo \
-       crypto/xtea.lo \
-       crypto/openpgp/armor.lo \
-       crypto/openpgp/elgamal.lo \
-       crypto/openpgp/errors.lo \
-       crypto/openpgp/packet.lo \
-       crypto/openpgp/s2k.lo \
        crypto/x509/pkix.lo \
        database/sql.lo \
        database/sql/driver.lo \
@@ -1784,17 +1663,15 @@ libgo_go_objs = \
        encoding/base64.lo \
        encoding/binary.lo \
        encoding/csv.lo \
-       encoding/git85.lo \
        encoding/gob.lo \
        encoding/hex.lo \
        encoding/json.lo \
        encoding/pem.lo \
        encoding/xml.lo \
        exp/ebnf.lo \
+       exp/html.lo \
        exp/norm.lo \
        exp/proxy.lo \
-       exp/spdy.lo \
-       exp/ssh.lo \
        exp/terminal.lo \
        exp/types.lo \
        exp/utf8string.lo \
@@ -1831,7 +1708,6 @@ libgo_go_objs = \
        math/rand.lo \
        mime/mime.lo \
        mime/multipart.lo \
-       net/dict.lo \
        net/http.lo \
        net/mail.lo \
        net/rpc.lo \
@@ -1946,7 +1822,6 @@ CHECK_DEPS = libgo.la libgobegin.a \
        $(toolexeclibgocompress_DATA) \
        $(toolexeclibgocontainer_DATA) \
        $(toolexeclibgocrypto_DATA) \
-       $(toolexeclibgocryptoopenpgp_DATA) \
        $(toolexeclibgodebug_DATA) \
        $(toolexeclibgoencoding_DATA) \
        $(toolexeclibgoexp_DATA) \
@@ -2120,15 +1995,6 @@ signal_unix.go: $(srcdir)/go/os/mkunixsignals.sh sysinfo.go
        $(SHELL) $(srcdir)/go/os/mkunixsignals.sh sysinfo.go > $@.tmp
        mv -f $@.tmp $@
 
-@go_include@ patch/patch.lo.dep
-patch/patch.lo.dep: $(go_patch_files)
-       $(BUILDDEPS)
-patch/patch.lo: $(go_patch_files)
-       $(BUILDPACKAGE)
-patch/check: $(CHECK_DEPS)
-       @$(CHECK)
-.PHONY: patch/check
-
 @go_include@ path/path.lo.dep
 path/path.lo.dep: $(go_path_files)
        $(BUILDDEPS)
@@ -2238,15 +2104,6 @@ unicode/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: unicode/check
 
-@go_include@ websocket/websocket.lo.dep
-websocket/websocket.lo.dep: $(go_websocket_files)
-       $(BUILDDEPS)
-websocket/websocket.lo: $(go_websocket_files)
-       $(BUILDPACKAGE)
-websocket/check: $(CHECK_DEPS)
-       @$(CHECK)
-.PHONY: websocket/check
-
 @go_include@ archive/tar.lo.dep
 archive/tar.lo.dep: $(go_archive_tar_files)
        $(BUILDDEPS)
@@ -2357,36 +2214,6 @@ crypto/aes/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/aes/check
 
-@go_include@ crypto/bcrypt.lo.dep
-crypto/bcrypt.lo.dep: $(go_crypto_bcrypt_files)
-       $(BUILDDEPS)
-crypto/bcrypt.lo: $(go_crypto_bcrypt_files)
-       $(BUILDPACKAGE)
-crypto/bcrypt/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/bcrypt
-       @$(CHECK)
-.PHONY: crypto/bcrypt/check
-
-@go_include@ crypto/blowfish.lo.dep
-crypto/blowfish.lo.dep: $(go_crypto_blowfish_files)
-       $(BUILDDEPS)
-crypto/blowfish.lo: $(go_crypto_blowfish_files)
-       $(BUILDPACKAGE)
-crypto/blowfish/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/blowfish
-       @$(CHECK)
-.PHONY: crypto/blowfish/check
-
-@go_include@ crypto/cast5.lo.dep
-crypto/cast5.lo.dep: $(go_crypto_cast5_files)
-       $(BUILDDEPS)
-crypto/cast5.lo: $(go_crypto_cast5_files)
-       $(BUILDPACKAGE)
-crypto/cast5/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/cast5
-       @$(CHECK)
-.PHONY: crypto/cast5/check
-
 @go_include@ crypto/cipher.lo.dep
 crypto/cipher.lo.dep: $(go_crypto_cipher_files)
        $(BUILDDEPS)
@@ -2447,16 +2274,6 @@ crypto/hmac/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/hmac/check
 
-@go_include@ crypto/md4.lo.dep
-crypto/md4.lo.dep: $(go_crypto_md4_files)
-       $(BUILDDEPS)
-crypto/md4.lo: $(go_crypto_md4_files)
-       $(BUILDPACKAGE)
-crypto/md4/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/md4
-       @$(CHECK)
-.PHONY: crypto/md4/check
-
 @go_include@ crypto/md5.lo.dep
 crypto/md5.lo.dep: $(go_crypto_md5_files)
        $(BUILDDEPS)
@@ -2467,26 +2284,6 @@ crypto/md5/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/md5/check
 
-@go_include@ crypto/ocsp.lo.dep
-crypto/ocsp.lo.dep: $(go_crypto_ocsp_files)
-       $(BUILDDEPS)
-crypto/ocsp.lo: $(go_crypto_ocsp_files)
-       $(BUILDPACKAGE)
-crypto/ocsp/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/ocsp
-       @$(CHECK)
-.PHONY: crypto/ocsp/check
-
-@go_include@ crypto/openpgp.lo.dep
-crypto/openpgp.lo.dep: $(go_crypto_openpgp_files)
-       $(BUILDDEPS)
-crypto/openpgp.lo: $(go_crypto_openpgp_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp
-       @$(CHECK)
-.PHONY: crypto/openpgp/check
-
 @go_include@ crypto/rand.lo.dep
 crypto/rand.lo.dep: $(go_crypto_rand_files)
        $(BUILDDEPS)
@@ -2507,16 +2304,6 @@ crypto/rc4/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/rc4/check
 
-@go_include@ crypto/ripemd160.lo.dep
-crypto/ripemd160.lo.dep: $(go_crypto_ripemd160_files)
-       $(BUILDDEPS)
-crypto/ripemd160.lo: $(go_crypto_ripemd160_files)
-       $(BUILDPACKAGE)
-crypto/ripemd160/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/ripemd160
-       @$(CHECK)
-.PHONY: crypto/ripemd160/check
-
 @go_include@ crypto/rsa.lo.dep
 crypto/rsa.lo.dep: $(go_crypto_rsa_files)
        $(BUILDDEPS)
@@ -2577,16 +2364,6 @@ crypto/tls/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/tls/check
 
-@go_include@ crypto/twofish.lo.dep
-crypto/twofish.lo.dep: $(go_crypto_twofish_files)
-       $(BUILDDEPS)
-crypto/twofish.lo: $(go_crypto_twofish_files)
-       $(BUILDPACKAGE)
-crypto/twofish/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/twofish
-       @$(CHECK)
-.PHONY: crypto/twofish/check
-
 @go_include@ crypto/x509.lo.dep
 crypto/x509.lo.dep: $(go_crypto_x509_files)
        $(BUILDDEPS)
@@ -2597,66 +2374,6 @@ crypto/x509/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/x509/check
 
-@go_include@ crypto/xtea.lo.dep
-crypto/xtea.lo.dep: $(go_crypto_xtea_files)
-       $(BUILDDEPS)
-crypto/xtea.lo: $(go_crypto_xtea_files)
-       $(BUILDPACKAGE)
-crypto/xtea/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/xtea
-       @$(CHECK)
-.PHONY: crypto/xtea/check
-
-@go_include@ crypto/openpgp/armor.lo.dep
-crypto/openpgp/armor.lo.dep: $(go_crypto_openpgp_armor_files)
-       $(BUILDDEPS)
-crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/armor/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/armor
-       @$(CHECK)
-.PHONY: crypto/openpgp/armor/check
-
-@go_include@ crypto/openpgp/elgamal.lo.dep
-crypto/openpgp/elgamal.lo.dep: $(go_crypto_openpgp_elgamal_files)
-       $(BUILDDEPS)
-crypto/openpgp/elgamal.lo: $(go_crypto_openpgp_elgamal_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/elgamal/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/elgamal
-       @$(CHECK)
-.PHONY: crypto/openpgp/elgamal/check
-
-@go_include@ crypto/openpgp/errors.lo.dep
-crypto/openpgp/errors.lo.dep: $(go_crypto_openpgp_errors_files)
-       $(BUILDDEPS)
-crypto/openpgp/errors.lo: $(go_crypto_openpgp_errors_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/errors/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/errors
-       @$(CHECK)
-.PHONY: crypto/openpgp/errors/check
-
-@go_include@ crypto/openpgp/packet.lo.dep
-crypto/openpgp/packet.lo.dep: $(go_crypto_openpgp_packet_files)
-       $(BUILDDEPS)
-crypto/openpgp/packet.lo: $(go_crypto_openpgp_packet_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/packet/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/packet
-       @$(CHECK)
-.PHONY: crypto/openpgp/packet/check
-
-@go_include@ crypto/openpgp/s2k.lo.dep
-crypto/openpgp/s2k.lo.dep: $(go_crypto_openpgp_s2k_files)
-       $(BUILDDEPS)
-crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/s2k/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/s2k
-       @$(CHECK)
-.PHONY: crypto/openpgp/s2k/check
-
 @go_include@ crypto/x509/pkix.lo.dep
 crypto/x509/pkix.lo.dep: $(go_crypto_x509_pkix_files)
        $(BUILDDEPS)
@@ -2797,16 +2514,6 @@ encoding/csv/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: encoding/csv/check
 
-@go_include@ encoding/git85.lo.dep
-encoding/git85.lo.dep: $(go_encoding_git85_files)
-       $(BUILDDEPS)
-encoding/git85.lo: $(go_encoding_git85_files)
-       $(BUILDPACKAGE)
-encoding/git85/check: $(CHECK_DEPS)
-       @$(MKDIR_P) encoding/git85
-       @$(CHECK)
-.PHONY: encoding/git85/check
-
 @go_include@ encoding/gob.lo.dep
 encoding/gob.lo.dep: $(go_encoding_gob_files)
        $(BUILDDEPS)
@@ -2867,6 +2574,16 @@ 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)
+       @$(MKDIR_P) exp/html
+       @$(CHECK)
+.PHONY: exp/html/check
+
 @go_include@ exp/norm.lo.dep
 exp/norm.lo.dep: $(go_exp_norm_files)
        $(BUILDDEPS)
@@ -2887,26 +2604,6 @@ exp/proxy/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: exp/proxy/check
 
-@go_include@ exp/spdy.lo.dep
-exp/spdy.lo.dep: $(go_exp_spdy_files)
-       $(BUILDDEPS)
-exp/spdy.lo: $(go_exp_spdy_files)
-       $(BUILDPACKAGE)
-exp/spdy/check: $(CHECK_DEPS)
-       @$(MKDIR_P) exp/spdy
-       @$(CHECK)
-.PHONY: exp/spdy/check
-
-@go_include@ exp/ssh.lo.dep
-exp/ssh.lo.dep: $(go_exp_ssh_files)
-       $(BUILDDEPS)
-exp/ssh.lo: $(go_exp_ssh_files)
-       $(BUILDPACKAGE)
-exp/ssh/check: $(CHECK_DEPS)
-       @$(MKDIR_P) exp/ssh
-       @$(CHECK)
-.PHONY: exp/ssh/check
-
 @go_include@ exp/terminal.lo.dep
 exp/terminal.lo.dep: $(go_exp_terminal_files)
        $(BUILDDEPS)
@@ -3218,12 +2915,6 @@ mime/multipart/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: mime/multipart/check
 
-@go_include@ net/dict.lo.dep
-net/dict.lo.dep: $(go_net_dict_files)
-       $(BUILDDEPS)
-net/dict.lo: $(go_net_dict_files)
-       $(BUILDPACKAGE)
-
 @go_include@ net/http.lo.dep
 net/http.lo.dep: $(go_net_http_files)
        $(BUILDDEPS)
@@ -3582,8 +3273,6 @@ net.gox: net/net.lo
        $(BUILDGOX)
 os.gox: os/os.lo
        $(BUILDGOX)
-patch.gox: patch/patch.lo
-       $(BUILDGOX)
 path.gox: path/path.lo
        $(BUILDGOX)
 reflect.gox: reflect/reflect.lo
@@ -3608,8 +3297,6 @@ time.gox: time/time.lo
        $(BUILDGOX)
 unicode.gox: unicode/unicode.lo
        $(BUILDGOX)
-websocket.gox: websocket/websocket.lo
-       $(BUILDGOX)
 
 archive/tar.gox: archive/tar.lo
        $(BUILDGOX)
@@ -3636,12 +3323,6 @@ container/ring.gox: container/ring.lo
 
 crypto/aes.gox: crypto/aes.lo
        $(BUILDGOX)
-crypto/bcrypt.gox: crypto/bcrypt.lo
-       $(BUILDGOX)
-crypto/blowfish.gox: crypto/blowfish.lo
-       $(BUILDGOX)
-crypto/cast5.gox: crypto/cast5.lo
-       $(BUILDGOX)
 crypto/cipher.gox: crypto/cipher.lo
        $(BUILDGOX)
 crypto/des.gox: crypto/des.lo
@@ -3654,20 +3335,12 @@ crypto/elliptic.gox: crypto/elliptic.lo
        $(BUILDGOX)
 crypto/hmac.gox: crypto/hmac.lo
        $(BUILDGOX)
-crypto/md4.gox: crypto/md4.lo
-       $(BUILDGOX)
 crypto/md5.gox: crypto/md5.lo
        $(BUILDGOX)
-crypto/ocsp.gox: crypto/ocsp.lo
-       $(BUILDGOX)
-crypto/openpgp.gox: crypto/openpgp.lo
-       $(BUILDGOX)
 crypto/rand.gox: crypto/rand.lo
        $(BUILDGOX)
 crypto/rc4.gox: crypto/rc4.lo
        $(BUILDGOX)
-crypto/ripemd160.gox: crypto/ripemd160.lo
-       $(BUILDGOX)
 crypto/rsa.gox: crypto/rsa.lo
        $(BUILDGOX)
 crypto/sha1.gox: crypto/sha1.lo
@@ -3680,23 +3353,8 @@ crypto/subtle.gox: crypto/subtle.lo
        $(BUILDGOX)
 crypto/tls.gox: crypto/tls.lo
        $(BUILDGOX)
-crypto/twofish.gox: crypto/twofish.lo
-       $(BUILDGOX)
 crypto/x509.gox: crypto/x509.lo
        $(BUILDGOX)
-crypto/xtea.gox: crypto/xtea.lo
-       $(BUILDGOX)
-
-crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
-       $(BUILDGOX)
-crypto/openpgp/elgamal.gox: crypto/openpgp/elgamal.lo
-       $(BUILDGOX)
-crypto/openpgp/errors.gox: crypto/openpgp/errors.lo
-       $(BUILDGOX)
-crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
-       $(BUILDGOX)
-crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo
-       $(BUILDGOX)
 
 crypto/x509/pkix.gox: crypto/x509/pkix.lo
        $(BUILDGOX)
@@ -3730,8 +3388,6 @@ encoding/binary.gox: encoding/binary.lo
        $(BUILDGOX)
 encoding/csv.gox: encoding/csv.lo
        $(BUILDGOX)
-encoding/git85.gox: encoding/git85.lo
-       $(BUILDGOX)
 encoding/gob.gox: encoding/gob.lo
        $(BUILDGOX)
 encoding/hex.gox: encoding/hex.lo
@@ -3745,16 +3401,14 @@ encoding/xml.gox: encoding/xml.lo
 
 exp/ebnf.gox: exp/ebnf.lo
        $(BUILDGOX)
+exp/html.gox: exp/html.lo
+       $(BUILDGOX)
 exp/inotify.gox: exp/inotify.lo
        $(BUILDGOX)
 exp/norm.gox: exp/norm.lo
        $(BUILDGOX)
 exp/proxy.gox: exp/proxy.lo
        $(BUILDGOX)
-exp/spdy.gox: exp/spdy.lo
-       $(BUILDGOX)
-exp/ssh.gox: exp/ssh.lo
-       $(BUILDGOX)
 exp/terminal.gox: exp/terminal.lo
        $(BUILDGOX)
 exp/types.gox: exp/types.lo
@@ -3823,8 +3477,6 @@ math/rand.gox: math/rand.lo
 mime/multipart.gox: mime/multipart.lo
        $(BUILDGOX)
 
-net/dict.gox: net/dict.lo
-       $(BUILDGOX)
 net/http.gox: net/http.lo
        $(BUILDGOX)
 net/mail.gox: net/mail.lo
@@ -3923,7 +3575,6 @@ TEST_PACKAGES = \
        mime/check \
        net/check \
        os/check \
-       patch/check \
        path/check \
        reflect/check \
        regexp/check \
@@ -3934,7 +3585,6 @@ TEST_PACKAGES = \
        sync/check \
        time/check \
        unicode/check \
-       websocket/check \
        archive/tar/check \
        archive/zip/check \
        compress/bzip2/check \
@@ -3946,35 +3596,22 @@ TEST_PACKAGES = \
        container/list/check \
        container/ring/check \
        crypto/aes/check \
-       crypto/bcrypt/check \
-       crypto/blowfish/check \
-       crypto/cast5/check \
        crypto/cipher/check \
        crypto/des/check \
        crypto/dsa/check \
        crypto/ecdsa/check \
        crypto/elliptic/check \
        crypto/hmac/check \
-       crypto/md4/check \
        crypto/md5/check \
-       crypto/ocsp/check \
-       crypto/openpgp/check \
        crypto/rand/check \
        crypto/rc4/check \
-       crypto/ripemd160/check \
        crypto/rsa/check \
        crypto/sha1/check \
        crypto/sha256/check \
        crypto/sha512/check \
        crypto/subtle/check \
        crypto/tls/check \
-       crypto/twofish/check \
        crypto/x509/check \
-       crypto/xtea/check \
-       crypto/openpgp/armor/check \
-       crypto/openpgp/elgamal/check \
-       crypto/openpgp/packet/check \
-       crypto/openpgp/s2k/check \
        database/sql/check \
        database/sql/driver/check \
        debug/dwarf/check \
@@ -3987,18 +3624,16 @@ TEST_PACKAGES = \
        encoding/base64/check \
        encoding/binary/check \
        encoding/csv/check \
-       encoding/git85/check \
        encoding/gob/check \
        encoding/hex/check \
        encoding/json/check \
        encoding/pem/check \
        encoding/xml/check \
        exp/ebnf/check \
+       exp/html/check \
        $(exp_inotify_check) \
        exp/norm/check \
        exp/proxy/check \
-       exp/spdy/check \
-       exp/ssh/check \
        exp/terminal/check \
        exp/utf8string/check \
        html/template/check \
index 6e0cea813f8aecd5b092b2aac81b03dc6a53c887..4aebb2d6fd7dfecb31a2657c5983c99b329a1bbd 100644 (file)
@@ -97,7 +97,6 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
        "$(DESTDIR)$(toolexeclibgocompressdir)" \
        "$(DESTDIR)$(toolexeclibgocontainerdir)" \
        "$(DESTDIR)$(toolexeclibgocryptodir)" \
-       "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" \
        "$(DESTDIR)$(toolexeclibgocryptox509dir)" \
        "$(DESTDIR)$(toolexeclibgodatabasedir)" \
        "$(DESTDIR)$(toolexeclibgodatabasesqldir)" \
@@ -138,31 +137,24 @@ am__DEPENDENCIES_2 = bufio/bufio.lo bytes/bytes.lo bytes/index.lo \
        crypto/crypto.lo errors/errors.lo expvar/expvar.lo \
        flag/flag.lo fmt/fmt.lo hash/hash.lo html/html.lo \
        image/image.lo io/io.lo log/log.lo math/math.lo net/net.lo \
-       os/exec.lo os/os.lo patch/patch.lo path/path.lo \
-       reflect/reflect.lo regexp/regexp.lo runtime/runtime.lo \
-       sort/sort.lo strconv/strconv.lo strings/strings.lo \
-       sync/sync.lo time/time.lo unicode/unicode.lo \
-       websocket/websocket.lo archive/tar.lo archive/zip.lo \
+       os/exec.lo os/os.lo path/path.lo reflect/reflect.lo \
+       regexp/regexp.lo runtime/runtime.lo sort/sort.lo \
+       strconv/strconv.lo strings/strings.lo sync/sync.lo \
+       time/time.lo unicode/unicode.lo archive/tar.lo archive/zip.lo \
        compress/bzip2.lo compress/flate.lo compress/gzip.lo \
        compress/lzw.lo compress/zlib.lo container/heap.lo \
        container/list.lo container/ring.lo crypto/aes.lo \
-       crypto/bcrypt.lo crypto/blowfish.lo crypto/cast5.lo \
        crypto/cipher.lo crypto/des.lo crypto/dsa.lo crypto/ecdsa.lo \
-       crypto/elliptic.lo crypto/hmac.lo crypto/md4.lo crypto/md5.lo \
-       crypto/ocsp.lo crypto/openpgp.lo crypto/rand.lo crypto/rc4.lo \
-       crypto/ripemd160.lo crypto/rsa.lo crypto/sha1.lo \
-       crypto/sha256.lo crypto/sha512.lo crypto/subtle.lo \
-       crypto/tls.lo crypto/twofish.lo crypto/x509.lo crypto/xtea.lo \
-       crypto/openpgp/armor.lo crypto/openpgp/elgamal.lo \
-       crypto/openpgp/errors.lo crypto/openpgp/packet.lo \
-       crypto/openpgp/s2k.lo crypto/x509/pkix.lo database/sql.lo \
-       database/sql/driver.lo debug/dwarf.lo debug/elf.lo \
-       debug/gosym.lo debug/macho.lo debug/pe.lo encoding/ascii85.lo \
-       encoding/asn1.lo encoding/base32.lo encoding/base64.lo \
-       encoding/binary.lo encoding/csv.lo encoding/git85.lo \
-       encoding/gob.lo encoding/hex.lo encoding/json.lo \
-       encoding/pem.lo encoding/xml.lo exp/ebnf.lo exp/norm.lo \
-       exp/proxy.lo exp/spdy.lo exp/ssh.lo exp/terminal.lo \
+       crypto/elliptic.lo crypto/hmac.lo crypto/md5.lo crypto/rand.lo \
+       crypto/rc4.lo crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo \
+       crypto/sha512.lo crypto/subtle.lo crypto/tls.lo crypto/x509.lo \
+       crypto/x509/pkix.lo database/sql.lo database/sql/driver.lo \
+       debug/dwarf.lo debug/elf.lo debug/gosym.lo debug/macho.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/ebnf.lo \
+       exp/html.lo exp/norm.lo exp/proxy.lo exp/terminal.lo \
        exp/types.lo exp/utf8string.lo html/template.lo go/ast.lo \
        go/build.lo go/doc.lo go/parser.lo go/printer.lo go/scanner.lo \
        go/token.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
@@ -172,7 +164,7 @@ am__DEPENDENCIES_2 = bufio/bufio.lo bytes/bytes.lo bytes/index.lo \
        image/jpeg.lo image/png.lo image/tiff.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/mime.lo mime/multipart.lo \
-       net/dict.lo net/http.lo net/mail.lo net/rpc.lo net/smtp.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 $(am__DEPENDENCIES_1) os/user.lo os/signal.lo \
        path/filepath.lo regexp/syntax.lo net/rpc/jsonrpc.lo \
@@ -289,21 +281,21 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
        ps-recursive uninstall-recursive
 DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
        $(toolexeclibgocompress_DATA) $(toolexeclibgocontainer_DATA) \
-       $(toolexeclibgocrypto_DATA) $(toolexeclibgocryptoopenpgp_DATA) \
-       $(toolexeclibgocryptox509_DATA) $(toolexeclibgodatabase_DATA) \
-       $(toolexeclibgodatabasesql_DATA) $(toolexeclibgodebug_DATA) \
-       $(toolexeclibgoencoding_DATA) $(toolexeclibgoexp_DATA) \
-       $(toolexeclibgogo_DATA) $(toolexeclibgohash_DATA) \
-       $(toolexeclibgohtml_DATA) $(toolexeclibgoimage_DATA) \
-       $(toolexeclibgoindex_DATA) $(toolexeclibgoio_DATA) \
-       $(toolexeclibgolog_DATA) $(toolexeclibgomath_DATA) \
-       $(toolexeclibgomime_DATA) $(toolexeclibgonet_DATA) \
-       $(toolexeclibgonethttp_DATA) $(toolexeclibgonetrpc_DATA) \
-       $(toolexeclibgoold_DATA) $(toolexeclibgoos_DATA) \
-       $(toolexeclibgopath_DATA) $(toolexeclibgoregexp_DATA) \
-       $(toolexeclibgoruntime_DATA) $(toolexeclibgosync_DATA) \
-       $(toolexeclibgotesting_DATA) $(toolexeclibgotext_DATA) \
-       $(toolexeclibgotexttemplate_DATA) $(toolexeclibgounicode_DATA)
+       $(toolexeclibgocrypto_DATA) $(toolexeclibgocryptox509_DATA) \
+       $(toolexeclibgodatabase_DATA) $(toolexeclibgodatabasesql_DATA) \
+       $(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \
+       $(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \
+       $(toolexeclibgohash_DATA) $(toolexeclibgohtml_DATA) \
+       $(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \
+       $(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \
+       $(toolexeclibgomath_DATA) $(toolexeclibgomime_DATA) \
+       $(toolexeclibgonet_DATA) $(toolexeclibgonethttp_DATA) \
+       $(toolexeclibgonetrpc_DATA) $(toolexeclibgoold_DATA) \
+       $(toolexeclibgoos_DATA) $(toolexeclibgopath_DATA) \
+       $(toolexeclibgoregexp_DATA) $(toolexeclibgoruntime_DATA) \
+       $(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \
+       $(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \
+       $(toolexeclibgounicode_DATA)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
   distclean-recursive maintainer-clean-recursive
 AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -587,7 +579,6 @@ toolexeclibgo_DATA = \
        mime.gox \
        net.gox \
        os.gox \
-       patch.gox \
        path.gox \
        reflect.gox \
        regexp.gox \
@@ -599,8 +590,7 @@ toolexeclibgo_DATA = \
        syscall.gox \
        testing.gox \
        time.gox \
-       unicode.gox \
-       websocket.gox
+       unicode.gox
 
 toolexeclibgoarchivedir = $(toolexeclibgodir)/archive
 toolexeclibgoarchive_DATA = \
@@ -624,39 +614,22 @@ toolexeclibgocontainer_DATA = \
 toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
 toolexeclibgocrypto_DATA = \
        crypto/aes.gox \
-       crypto/bcrypt.gox \
-       crypto/blowfish.gox \
-       crypto/cast5.gox \
        crypto/cipher.gox \
        crypto/des.gox \
        crypto/dsa.gox \
        crypto/ecdsa.gox \
        crypto/elliptic.gox \
        crypto/hmac.gox \
-       crypto/md4.gox \
        crypto/md5.gox \
-       crypto/ocsp.gox \
-       crypto/openpgp.gox \
        crypto/rand.gox \
        crypto/rc4.gox \
-       crypto/ripemd160.gox \
        crypto/rsa.gox \
        crypto/sha1.gox \
        crypto/sha256.gox \
        crypto/sha512.gox \
        crypto/subtle.gox \
        crypto/tls.gox \
-       crypto/twofish.gox \
-       crypto/x509.gox \
-       crypto/xtea.gox
-
-toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
-toolexeclibgocryptoopenpgp_DATA = \
-       crypto/openpgp/armor.gox \
-       crypto/openpgp/elgamal.gox \
-       crypto/openpgp/errors.gox \
-       crypto/openpgp/packet.gox \
-       crypto/openpgp/s2k.gox
+       crypto/x509.gox
 
 toolexeclibgocryptox509dir = $(toolexeclibgocryptodir)/x509
 toolexeclibgocryptox509_DATA = \
@@ -686,7 +659,6 @@ toolexeclibgoencoding_DATA = \
        encoding/base64.gox \
        encoding/binary.gox \
        encoding/csv.gox \
-       encoding/git85.gox \
        encoding/gob.gox \
        encoding/hex.gox \
        encoding/json.gox \
@@ -700,11 +672,10 @@ toolexeclibgoencoding_DATA = \
 toolexeclibgoexpdir = $(toolexeclibgodir)/exp
 toolexeclibgoexp_DATA = \
        exp/ebnf.gox \
+       exp/html.gox \
        $(exp_inotify_gox) \
        exp/norm.gox \
        exp/proxy.gox \
-       exp/spdy.gox \
-       exp/ssh.gox \
        exp/terminal.gox \
        exp/types.gox \
        exp/utf8string.gox
@@ -764,7 +735,6 @@ toolexeclibgomime_DATA = \
 
 toolexeclibgonetdir = $(toolexeclibgodir)/net
 toolexeclibgonet_DATA = \
-       net/dict.gox \
        net/http.gox \
        net/mail.gox \
        net/rpc.gox \
@@ -963,16 +933,8 @@ go_hash_files = \
        go/hash/hash.go
 
 go_html_files = \
-       go/html/const.go \
-       go/html/doc.go \
-       go/html/doctype.go \
        go/html/entity.go \
-       go/html/escape.go \
-       go/html/foreign.go \
-       go/html/node.go \
-       go/html/parse.go \
-       go/html/render.go \
-       go/html/token.go
+       go/html/escape.go
 
 go_image_files = \
        go/image/format.go \
@@ -1146,12 +1108,6 @@ go_os_files = \
        go/os/types.go \
        signal_unix.go
 
-go_patch_files = \
-       go/patch/apply.go \
-       go/patch/git.go \
-       go/patch/patch.go \
-       go/patch/textdiff.go
-
 go_path_files = \
        go/path/match.go \
        go/path/path.go
@@ -1237,13 +1193,6 @@ go_unicode_files = \
        go/unicode/letter.go \
        go/unicode/tables.go
 
-go_websocket_files = \
-       go/websocket/client.go \
-       go/websocket/hixie.go \
-       go/websocket/hybi.go \
-       go/websocket/server.go \
-       go/websocket/websocket.go
-
 go_archive_tar_files = \
        go/archive/tar/common.go \
        go/archive/tar/reader.go \
@@ -1266,8 +1215,7 @@ go_compress_flate_files = \
        go/compress/flate/huffman_code.go \
        go/compress/flate/inflate.go \
        go/compress/flate/reverse_bits.go \
-       go/compress/flate/token.go \
-       go/compress/flate/util.go
+       go/compress/flate/token.go
 
 go_compress_gzip_files = \
        go/compress/gzip/gzip.go \
@@ -1295,18 +1243,6 @@ go_crypto_aes_files = \
        go/crypto/aes/cipher.go \
        go/crypto/aes/const.go
 
-go_crypto_bcrypt_files = \
-       go/crypto/bcrypt/base64.go \
-       go/crypto/bcrypt/bcrypt.go
-
-go_crypto_blowfish_files = \
-       go/crypto/blowfish/block.go \
-       go/crypto/blowfish/const.go \
-       go/crypto/blowfish/cipher.go
-
-go_crypto_cast5_files = \
-       go/crypto/cast5/cast5.go
-
 go_crypto_cipher_files = \
        go/crypto/cipher/cbc.go \
        go/crypto/cipher/cfb.go \
@@ -1334,23 +1270,10 @@ go_crypto_elliptic_files = \
 go_crypto_hmac_files = \
        go/crypto/hmac/hmac.go
 
-go_crypto_md4_files = \
-       go/crypto/md4/md4.go \
-       go/crypto/md4/md4block.go
-
 go_crypto_md5_files = \
        go/crypto/md5/md5.go \
        go/crypto/md5/md5block.go
 
-go_crypto_ocsp_files = \
-       go/crypto/ocsp/ocsp.go
-
-go_crypto_openpgp_files = \
-       go/crypto/openpgp/canonical_text.go \
-       go/crypto/openpgp/keys.go \
-       go/crypto/openpgp/read.go \
-       go/crypto/openpgp/write.go
-
 go_crypto_rand_files = \
        go/crypto/rand/rand.go \
        go/crypto/rand/rand_unix.go \
@@ -1359,10 +1282,6 @@ go_crypto_rand_files = \
 go_crypto_rc4_files = \
        go/crypto/rc4/rc4.go
 
-go_crypto_ripemd160_files = \
-       go/crypto/ripemd160/ripemd160.go \
-       go/crypto/ripemd160/ripemd160block.go
-
 go_crypto_rsa_files = \
        go/crypto/rsa/pkcs1v15.go \
        go/crypto/rsa/rsa.go
@@ -1395,9 +1314,6 @@ go_crypto_tls_files = \
        go/crypto/tls/root_unix.go \
        go/crypto/tls/tls.go
 
-go_crypto_twofish_files = \
-       go/crypto/twofish/twofish.go
-
 go_crypto_x509_files = \
        go/crypto/x509/cert_pool.go \
        go/crypto/x509/pkcs1.go \
@@ -1405,37 +1321,6 @@ go_crypto_x509_files = \
        go/crypto/x509/verify.go \
        go/crypto/x509/x509.go
 
-go_crypto_xtea_files = \
-       go/crypto/xtea/block.go \
-       go/crypto/xtea/cipher.go
-
-go_crypto_openpgp_armor_files = \
-       go/crypto/openpgp/armor/armor.go \
-       go/crypto/openpgp/armor/encode.go
-
-go_crypto_openpgp_elgamal_files = \
-       go/crypto/openpgp/elgamal/elgamal.go
-
-go_crypto_openpgp_errors_files = \
-       go/crypto/openpgp/errors/errors.go
-
-go_crypto_openpgp_packet_files = \
-       go/crypto/openpgp/packet/compressed.go \
-       go/crypto/openpgp/packet/encrypted_key.go \
-       go/crypto/openpgp/packet/literal.go \
-       go/crypto/openpgp/packet/one_pass_signature.go \
-       go/crypto/openpgp/packet/packet.go \
-       go/crypto/openpgp/packet/private_key.go \
-       go/crypto/openpgp/packet/public_key.go \
-       go/crypto/openpgp/packet/reader.go \
-       go/crypto/openpgp/packet/signature.go \
-       go/crypto/openpgp/packet/symmetric_key_encrypted.go \
-       go/crypto/openpgp/packet/symmetrically_encrypted.go \
-       go/crypto/openpgp/packet/userid.go
-
-go_crypto_openpgp_s2k_files = \
-       go/crypto/openpgp/s2k/s2k.go
-
 go_crypto_x509_pkix_files = \
        go/crypto/x509/pkix/pkix.go
 
@@ -1493,9 +1378,6 @@ go_encoding_csv_files = \
        go/encoding/csv/reader.go \
        go/encoding/csv/writer.go
 
-go_encoding_git85_files = \
-       go/encoding/git85/git.go
-
 go_encoding_gob_files = \
        go/encoding/gob/decode.go \
        go/encoding/gob/decoder.go \
@@ -1529,6 +1411,18 @@ 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_inotify_files = \
        go/exp/inotify/inotify_linux.go
 
@@ -1547,25 +1441,6 @@ go_exp_proxy_files = \
        go/exp/proxy/proxy.go \
        go/exp/proxy/socks5.go
 
-go_exp_spdy_files = \
-       go/exp/spdy/read.go \
-       go/exp/spdy/types.go \
-       go/exp/spdy/write.go
-
-go_exp_ssh_files = \
-       go/exp/ssh/channel.go \
-       go/exp/ssh/cipher.go \
-       go/exp/ssh/client.go \
-       go/exp/ssh/client_auth.go \
-       go/exp/ssh/common.go \
-       go/exp/ssh/doc.go \
-       go/exp/ssh/messages.go \
-       go/exp/ssh/server.go \
-       go/exp/ssh/server_terminal.go \
-       go/exp/ssh/session.go \
-       go/exp/ssh/tcpip.go \
-       go/exp/ssh/transport.go
-
 go_exp_terminal_files = \
        go/exp/terminal/terminal.go \
        go/exp/terminal/util.go
@@ -1721,9 +1596,6 @@ go_mime_multipart_files = \
        go/mime/multipart/multipart.go \
        go/mime/multipart/writer.go
 
-go_net_dict_files = \
-       go/net/dict/dict.go
-
 go_net_http_files = \
        go/net/http/chunked.go \
        go/net/http/client.go \
@@ -1988,7 +1860,6 @@ libgo_go_objs = \
        net/net.lo \
        os/exec.lo \
        os/os.lo \
-       patch/patch.lo \
        path/path.lo \
        reflect/reflect.lo \
        regexp/regexp.lo \
@@ -1999,7 +1870,6 @@ libgo_go_objs = \
        sync/sync.lo \
        time/time.lo \
        unicode/unicode.lo \
-       websocket/websocket.lo \
        archive/tar.lo \
        archive/zip.lo \
        compress/bzip2.lo \
@@ -2011,36 +1881,22 @@ libgo_go_objs = \
        container/list.lo \
        container/ring.lo \
        crypto/aes.lo \
-       crypto/bcrypt.lo \
-       crypto/blowfish.lo \
-       crypto/cast5.lo \
        crypto/cipher.lo \
        crypto/des.lo \
        crypto/dsa.lo \
        crypto/ecdsa.lo \
        crypto/elliptic.lo \
        crypto/hmac.lo \
-       crypto/md4.lo \
        crypto/md5.lo \
-       crypto/ocsp.lo \
-       crypto/openpgp.lo \
        crypto/rand.lo \
        crypto/rc4.lo \
-       crypto/ripemd160.lo \
        crypto/rsa.lo \
        crypto/sha1.lo \
        crypto/sha256.lo \
        crypto/sha512.lo \
        crypto/subtle.lo \
        crypto/tls.lo \
-       crypto/twofish.lo \
        crypto/x509.lo \
-       crypto/xtea.lo \
-       crypto/openpgp/armor.lo \
-       crypto/openpgp/elgamal.lo \
-       crypto/openpgp/errors.lo \
-       crypto/openpgp/packet.lo \
-       crypto/openpgp/s2k.lo \
        crypto/x509/pkix.lo \
        database/sql.lo \
        database/sql/driver.lo \
@@ -2055,17 +1911,15 @@ libgo_go_objs = \
        encoding/base64.lo \
        encoding/binary.lo \
        encoding/csv.lo \
-       encoding/git85.lo \
        encoding/gob.lo \
        encoding/hex.lo \
        encoding/json.lo \
        encoding/pem.lo \
        encoding/xml.lo \
        exp/ebnf.lo \
+       exp/html.lo \
        exp/norm.lo \
        exp/proxy.lo \
-       exp/spdy.lo \
-       exp/ssh.lo \
        exp/terminal.lo \
        exp/types.lo \
        exp/utf8string.lo \
@@ -2102,7 +1956,6 @@ libgo_go_objs = \
        math/rand.lo \
        mime/mime.lo \
        mime/multipart.lo \
-       net/dict.lo \
        net/http.lo \
        net/mail.lo \
        net/rpc.lo \
@@ -2211,7 +2064,6 @@ CHECK_DEPS = libgo.la libgobegin.a \
        $(toolexeclibgocompress_DATA) \
        $(toolexeclibgocontainer_DATA) \
        $(toolexeclibgocrypto_DATA) \
-       $(toolexeclibgocryptoopenpgp_DATA) \
        $(toolexeclibgodebug_DATA) \
        $(toolexeclibgoencoding_DATA) \
        $(toolexeclibgoexp_DATA) \
@@ -2260,7 +2112,6 @@ TEST_PACKAGES = \
        mime/check \
        net/check \
        os/check \
-       patch/check \
        path/check \
        reflect/check \
        regexp/check \
@@ -2271,7 +2122,6 @@ TEST_PACKAGES = \
        sync/check \
        time/check \
        unicode/check \
-       websocket/check \
        archive/tar/check \
        archive/zip/check \
        compress/bzip2/check \
@@ -2283,35 +2133,22 @@ TEST_PACKAGES = \
        container/list/check \
        container/ring/check \
        crypto/aes/check \
-       crypto/bcrypt/check \
-       crypto/blowfish/check \
-       crypto/cast5/check \
        crypto/cipher/check \
        crypto/des/check \
        crypto/dsa/check \
        crypto/ecdsa/check \
        crypto/elliptic/check \
        crypto/hmac/check \
-       crypto/md4/check \
        crypto/md5/check \
-       crypto/ocsp/check \
-       crypto/openpgp/check \
        crypto/rand/check \
        crypto/rc4/check \
-       crypto/ripemd160/check \
        crypto/rsa/check \
        crypto/sha1/check \
        crypto/sha256/check \
        crypto/sha512/check \
        crypto/subtle/check \
        crypto/tls/check \
-       crypto/twofish/check \
        crypto/x509/check \
-       crypto/xtea/check \
-       crypto/openpgp/armor/check \
-       crypto/openpgp/elgamal/check \
-       crypto/openpgp/packet/check \
-       crypto/openpgp/s2k/check \
        database/sql/check \
        database/sql/driver/check \
        debug/dwarf/check \
@@ -2324,18 +2161,16 @@ TEST_PACKAGES = \
        encoding/base64/check \
        encoding/binary/check \
        encoding/csv/check \
-       encoding/git85/check \
        encoding/gob/check \
        encoding/hex/check \
        encoding/json/check \
        encoding/pem/check \
        encoding/xml/check \
        exp/ebnf/check \
+       exp/html/check \
        $(exp_inotify_check) \
        exp/norm/check \
        exp/proxy/check \
-       exp/spdy/check \
-       exp/ssh/check \
        exp/terminal/check \
        exp/utf8string/check \
        html/template/check \
@@ -3353,26 +3188,6 @@ uninstall-toolexeclibgocryptoDATA:
        test -n "$$files" || exit 0; \
        echo " ( cd '$(DESTDIR)$(toolexeclibgocryptodir)' && rm -f" $$files ")"; \
        cd "$(DESTDIR)$(toolexeclibgocryptodir)" && rm -f $$files
-install-toolexeclibgocryptoopenpgpDATA: $(toolexeclibgocryptoopenpgp_DATA)
-       @$(NORMAL_INSTALL)
-       test -z "$(toolexeclibgocryptoopenpgpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)"
-       @list='$(toolexeclibgocryptoopenpgp_DATA)'; test -n "$(toolexeclibgocryptoopenpgpdir)" || 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)$(toolexeclibgocryptoopenpgpdir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" || exit $$?; \
-       done
-
-uninstall-toolexeclibgocryptoopenpgpDATA:
-       @$(NORMAL_UNINSTALL)
-       @list='$(toolexeclibgocryptoopenpgp_DATA)'; test -n "$(toolexeclibgocryptoopenpgpdir)" || list=; \
-       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-       test -n "$$files" || exit 0; \
-       echo " ( cd '$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)' && rm -f" $$files ")"; \
-       cd "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" && rm -f $$files
 install-toolexeclibgocryptox509DATA: $(toolexeclibgocryptox509_DATA)
        @$(NORMAL_INSTALL)
        test -z "$(toolexeclibgocryptox509dir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgocryptox509dir)"
@@ -4250,7 +4065,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)$(toolexeclibgocryptoopenpgpdir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
+       for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(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
@@ -4316,7 +4131,6 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
        install-toolexeclibgocompressDATA \
        install-toolexeclibgocontainerDATA \
        install-toolexeclibgocryptoDATA \
-       install-toolexeclibgocryptoopenpgpDATA \
        install-toolexeclibgocryptox509DATA \
        install-toolexeclibgodatabaseDATA \
        install-toolexeclibgodatabasesqlDATA \
@@ -4382,7 +4196,6 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
        uninstall-toolexeclibgocompressDATA \
        uninstall-toolexeclibgocontainerDATA \
        uninstall-toolexeclibgocryptoDATA \
-       uninstall-toolexeclibgocryptoopenpgpDATA \
        uninstall-toolexeclibgocryptox509DATA \
        uninstall-toolexeclibgodatabaseDATA \
        uninstall-toolexeclibgodatabasesqlDATA \
@@ -4431,7 +4244,6 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
        install-toolexeclibgocompressDATA \
        install-toolexeclibgocontainerDATA \
        install-toolexeclibgocryptoDATA \
-       install-toolexeclibgocryptoopenpgpDATA \
        install-toolexeclibgocryptox509DATA \
        install-toolexeclibgodatabaseDATA \
        install-toolexeclibgodatabasesqlDATA \
@@ -4461,7 +4273,6 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
        uninstall-toolexeclibgocompressDATA \
        uninstall-toolexeclibgocontainerDATA \
        uninstall-toolexeclibgocryptoDATA \
-       uninstall-toolexeclibgocryptoopenpgpDATA \
        uninstall-toolexeclibgocryptox509DATA \
        uninstall-toolexeclibgodatabaseDATA \
        uninstall-toolexeclibgodatabasesqlDATA \
@@ -4737,15 +4548,6 @@ signal_unix.go: $(srcdir)/go/os/mkunixsignals.sh sysinfo.go
        $(SHELL) $(srcdir)/go/os/mkunixsignals.sh sysinfo.go > $@.tmp
        mv -f $@.tmp $@
 
-@go_include@ patch/patch.lo.dep
-patch/patch.lo.dep: $(go_patch_files)
-       $(BUILDDEPS)
-patch/patch.lo: $(go_patch_files)
-       $(BUILDPACKAGE)
-patch/check: $(CHECK_DEPS)
-       @$(CHECK)
-.PHONY: patch/check
-
 @go_include@ path/path.lo.dep
 path/path.lo.dep: $(go_path_files)
        $(BUILDDEPS)
@@ -4855,15 +4657,6 @@ unicode/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: unicode/check
 
-@go_include@ websocket/websocket.lo.dep
-websocket/websocket.lo.dep: $(go_websocket_files)
-       $(BUILDDEPS)
-websocket/websocket.lo: $(go_websocket_files)
-       $(BUILDPACKAGE)
-websocket/check: $(CHECK_DEPS)
-       @$(CHECK)
-.PHONY: websocket/check
-
 @go_include@ archive/tar.lo.dep
 archive/tar.lo.dep: $(go_archive_tar_files)
        $(BUILDDEPS)
@@ -4974,36 +4767,6 @@ crypto/aes/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/aes/check
 
-@go_include@ crypto/bcrypt.lo.dep
-crypto/bcrypt.lo.dep: $(go_crypto_bcrypt_files)
-       $(BUILDDEPS)
-crypto/bcrypt.lo: $(go_crypto_bcrypt_files)
-       $(BUILDPACKAGE)
-crypto/bcrypt/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/bcrypt
-       @$(CHECK)
-.PHONY: crypto/bcrypt/check
-
-@go_include@ crypto/blowfish.lo.dep
-crypto/blowfish.lo.dep: $(go_crypto_blowfish_files)
-       $(BUILDDEPS)
-crypto/blowfish.lo: $(go_crypto_blowfish_files)
-       $(BUILDPACKAGE)
-crypto/blowfish/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/blowfish
-       @$(CHECK)
-.PHONY: crypto/blowfish/check
-
-@go_include@ crypto/cast5.lo.dep
-crypto/cast5.lo.dep: $(go_crypto_cast5_files)
-       $(BUILDDEPS)
-crypto/cast5.lo: $(go_crypto_cast5_files)
-       $(BUILDPACKAGE)
-crypto/cast5/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/cast5
-       @$(CHECK)
-.PHONY: crypto/cast5/check
-
 @go_include@ crypto/cipher.lo.dep
 crypto/cipher.lo.dep: $(go_crypto_cipher_files)
        $(BUILDDEPS)
@@ -5064,16 +4827,6 @@ crypto/hmac/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/hmac/check
 
-@go_include@ crypto/md4.lo.dep
-crypto/md4.lo.dep: $(go_crypto_md4_files)
-       $(BUILDDEPS)
-crypto/md4.lo: $(go_crypto_md4_files)
-       $(BUILDPACKAGE)
-crypto/md4/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/md4
-       @$(CHECK)
-.PHONY: crypto/md4/check
-
 @go_include@ crypto/md5.lo.dep
 crypto/md5.lo.dep: $(go_crypto_md5_files)
        $(BUILDDEPS)
@@ -5084,26 +4837,6 @@ crypto/md5/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/md5/check
 
-@go_include@ crypto/ocsp.lo.dep
-crypto/ocsp.lo.dep: $(go_crypto_ocsp_files)
-       $(BUILDDEPS)
-crypto/ocsp.lo: $(go_crypto_ocsp_files)
-       $(BUILDPACKAGE)
-crypto/ocsp/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/ocsp
-       @$(CHECK)
-.PHONY: crypto/ocsp/check
-
-@go_include@ crypto/openpgp.lo.dep
-crypto/openpgp.lo.dep: $(go_crypto_openpgp_files)
-       $(BUILDDEPS)
-crypto/openpgp.lo: $(go_crypto_openpgp_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp
-       @$(CHECK)
-.PHONY: crypto/openpgp/check
-
 @go_include@ crypto/rand.lo.dep
 crypto/rand.lo.dep: $(go_crypto_rand_files)
        $(BUILDDEPS)
@@ -5124,16 +4857,6 @@ crypto/rc4/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/rc4/check
 
-@go_include@ crypto/ripemd160.lo.dep
-crypto/ripemd160.lo.dep: $(go_crypto_ripemd160_files)
-       $(BUILDDEPS)
-crypto/ripemd160.lo: $(go_crypto_ripemd160_files)
-       $(BUILDPACKAGE)
-crypto/ripemd160/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/ripemd160
-       @$(CHECK)
-.PHONY: crypto/ripemd160/check
-
 @go_include@ crypto/rsa.lo.dep
 crypto/rsa.lo.dep: $(go_crypto_rsa_files)
        $(BUILDDEPS)
@@ -5194,16 +4917,6 @@ crypto/tls/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/tls/check
 
-@go_include@ crypto/twofish.lo.dep
-crypto/twofish.lo.dep: $(go_crypto_twofish_files)
-       $(BUILDDEPS)
-crypto/twofish.lo: $(go_crypto_twofish_files)
-       $(BUILDPACKAGE)
-crypto/twofish/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/twofish
-       @$(CHECK)
-.PHONY: crypto/twofish/check
-
 @go_include@ crypto/x509.lo.dep
 crypto/x509.lo.dep: $(go_crypto_x509_files)
        $(BUILDDEPS)
@@ -5214,66 +4927,6 @@ crypto/x509/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/x509/check
 
-@go_include@ crypto/xtea.lo.dep
-crypto/xtea.lo.dep: $(go_crypto_xtea_files)
-       $(BUILDDEPS)
-crypto/xtea.lo: $(go_crypto_xtea_files)
-       $(BUILDPACKAGE)
-crypto/xtea/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/xtea
-       @$(CHECK)
-.PHONY: crypto/xtea/check
-
-@go_include@ crypto/openpgp/armor.lo.dep
-crypto/openpgp/armor.lo.dep: $(go_crypto_openpgp_armor_files)
-       $(BUILDDEPS)
-crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/armor/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/armor
-       @$(CHECK)
-.PHONY: crypto/openpgp/armor/check
-
-@go_include@ crypto/openpgp/elgamal.lo.dep
-crypto/openpgp/elgamal.lo.dep: $(go_crypto_openpgp_elgamal_files)
-       $(BUILDDEPS)
-crypto/openpgp/elgamal.lo: $(go_crypto_openpgp_elgamal_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/elgamal/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/elgamal
-       @$(CHECK)
-.PHONY: crypto/openpgp/elgamal/check
-
-@go_include@ crypto/openpgp/errors.lo.dep
-crypto/openpgp/errors.lo.dep: $(go_crypto_openpgp_errors_files)
-       $(BUILDDEPS)
-crypto/openpgp/errors.lo: $(go_crypto_openpgp_errors_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/errors/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/errors
-       @$(CHECK)
-.PHONY: crypto/openpgp/errors/check
-
-@go_include@ crypto/openpgp/packet.lo.dep
-crypto/openpgp/packet.lo.dep: $(go_crypto_openpgp_packet_files)
-       $(BUILDDEPS)
-crypto/openpgp/packet.lo: $(go_crypto_openpgp_packet_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/packet/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/packet
-       @$(CHECK)
-.PHONY: crypto/openpgp/packet/check
-
-@go_include@ crypto/openpgp/s2k.lo.dep
-crypto/openpgp/s2k.lo.dep: $(go_crypto_openpgp_s2k_files)
-       $(BUILDDEPS)
-crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files)
-       $(BUILDPACKAGE)
-crypto/openpgp/s2k/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/openpgp/s2k
-       @$(CHECK)
-.PHONY: crypto/openpgp/s2k/check
-
 @go_include@ crypto/x509/pkix.lo.dep
 crypto/x509/pkix.lo.dep: $(go_crypto_x509_pkix_files)
        $(BUILDDEPS)
@@ -5414,16 +5067,6 @@ encoding/csv/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: encoding/csv/check
 
-@go_include@ encoding/git85.lo.dep
-encoding/git85.lo.dep: $(go_encoding_git85_files)
-       $(BUILDDEPS)
-encoding/git85.lo: $(go_encoding_git85_files)
-       $(BUILDPACKAGE)
-encoding/git85/check: $(CHECK_DEPS)
-       @$(MKDIR_P) encoding/git85
-       @$(CHECK)
-.PHONY: encoding/git85/check
-
 @go_include@ encoding/gob.lo.dep
 encoding/gob.lo.dep: $(go_encoding_gob_files)
        $(BUILDDEPS)
@@ -5484,6 +5127,16 @@ 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)
+       @$(MKDIR_P) exp/html
+       @$(CHECK)
+.PHONY: exp/html/check
+
 @go_include@ exp/norm.lo.dep
 exp/norm.lo.dep: $(go_exp_norm_files)
        $(BUILDDEPS)
@@ -5504,26 +5157,6 @@ exp/proxy/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: exp/proxy/check
 
-@go_include@ exp/spdy.lo.dep
-exp/spdy.lo.dep: $(go_exp_spdy_files)
-       $(BUILDDEPS)
-exp/spdy.lo: $(go_exp_spdy_files)
-       $(BUILDPACKAGE)
-exp/spdy/check: $(CHECK_DEPS)
-       @$(MKDIR_P) exp/spdy
-       @$(CHECK)
-.PHONY: exp/spdy/check
-
-@go_include@ exp/ssh.lo.dep
-exp/ssh.lo.dep: $(go_exp_ssh_files)
-       $(BUILDDEPS)
-exp/ssh.lo: $(go_exp_ssh_files)
-       $(BUILDPACKAGE)
-exp/ssh/check: $(CHECK_DEPS)
-       @$(MKDIR_P) exp/ssh
-       @$(CHECK)
-.PHONY: exp/ssh/check
-
 @go_include@ exp/terminal.lo.dep
 exp/terminal.lo.dep: $(go_exp_terminal_files)
        $(BUILDDEPS)
@@ -5835,12 +5468,6 @@ mime/multipart/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: mime/multipart/check
 
-@go_include@ net/dict.lo.dep
-net/dict.lo.dep: $(go_net_dict_files)
-       $(BUILDDEPS)
-net/dict.lo: $(go_net_dict_files)
-       $(BUILDPACKAGE)
-
 @go_include@ net/http.lo.dep
 net/http.lo.dep: $(go_net_http_files)
        $(BUILDDEPS)
@@ -6194,8 +5821,6 @@ net.gox: net/net.lo
        $(BUILDGOX)
 os.gox: os/os.lo
        $(BUILDGOX)
-patch.gox: patch/patch.lo
-       $(BUILDGOX)
 path.gox: path/path.lo
        $(BUILDGOX)
 reflect.gox: reflect/reflect.lo
@@ -6220,8 +5845,6 @@ time.gox: time/time.lo
        $(BUILDGOX)
 unicode.gox: unicode/unicode.lo
        $(BUILDGOX)
-websocket.gox: websocket/websocket.lo
-       $(BUILDGOX)
 
 archive/tar.gox: archive/tar.lo
        $(BUILDGOX)
@@ -6248,12 +5871,6 @@ container/ring.gox: container/ring.lo
 
 crypto/aes.gox: crypto/aes.lo
        $(BUILDGOX)
-crypto/bcrypt.gox: crypto/bcrypt.lo
-       $(BUILDGOX)
-crypto/blowfish.gox: crypto/blowfish.lo
-       $(BUILDGOX)
-crypto/cast5.gox: crypto/cast5.lo
-       $(BUILDGOX)
 crypto/cipher.gox: crypto/cipher.lo
        $(BUILDGOX)
 crypto/des.gox: crypto/des.lo
@@ -6266,20 +5883,12 @@ crypto/elliptic.gox: crypto/elliptic.lo
        $(BUILDGOX)
 crypto/hmac.gox: crypto/hmac.lo
        $(BUILDGOX)
-crypto/md4.gox: crypto/md4.lo
-       $(BUILDGOX)
 crypto/md5.gox: crypto/md5.lo
        $(BUILDGOX)
-crypto/ocsp.gox: crypto/ocsp.lo
-       $(BUILDGOX)
-crypto/openpgp.gox: crypto/openpgp.lo
-       $(BUILDGOX)
 crypto/rand.gox: crypto/rand.lo
        $(BUILDGOX)
 crypto/rc4.gox: crypto/rc4.lo
        $(BUILDGOX)
-crypto/ripemd160.gox: crypto/ripemd160.lo
-       $(BUILDGOX)
 crypto/rsa.gox: crypto/rsa.lo
        $(BUILDGOX)
 crypto/sha1.gox: crypto/sha1.lo
@@ -6292,23 +5901,8 @@ crypto/subtle.gox: crypto/subtle.lo
        $(BUILDGOX)
 crypto/tls.gox: crypto/tls.lo
        $(BUILDGOX)
-crypto/twofish.gox: crypto/twofish.lo
-       $(BUILDGOX)
 crypto/x509.gox: crypto/x509.lo
        $(BUILDGOX)
-crypto/xtea.gox: crypto/xtea.lo
-       $(BUILDGOX)
-
-crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
-       $(BUILDGOX)
-crypto/openpgp/elgamal.gox: crypto/openpgp/elgamal.lo
-       $(BUILDGOX)
-crypto/openpgp/errors.gox: crypto/openpgp/errors.lo
-       $(BUILDGOX)
-crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
-       $(BUILDGOX)
-crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo
-       $(BUILDGOX)
 
 crypto/x509/pkix.gox: crypto/x509/pkix.lo
        $(BUILDGOX)
@@ -6342,8 +5936,6 @@ encoding/binary.gox: encoding/binary.lo
        $(BUILDGOX)
 encoding/csv.gox: encoding/csv.lo
        $(BUILDGOX)
-encoding/git85.gox: encoding/git85.lo
-       $(BUILDGOX)
 encoding/gob.gox: encoding/gob.lo
        $(BUILDGOX)
 encoding/hex.gox: encoding/hex.lo
@@ -6357,16 +5949,14 @@ encoding/xml.gox: encoding/xml.lo
 
 exp/ebnf.gox: exp/ebnf.lo
        $(BUILDGOX)
+exp/html.gox: exp/html.lo
+       $(BUILDGOX)
 exp/inotify.gox: exp/inotify.lo
        $(BUILDGOX)
 exp/norm.gox: exp/norm.lo
        $(BUILDGOX)
 exp/proxy.gox: exp/proxy.lo
        $(BUILDGOX)
-exp/spdy.gox: exp/spdy.lo
-       $(BUILDGOX)
-exp/ssh.gox: exp/ssh.lo
-       $(BUILDGOX)
 exp/terminal.gox: exp/terminal.lo
        $(BUILDGOX)
 exp/types.gox: exp/types.lo
@@ -6435,8 +6025,6 @@ math/rand.gox: math/rand.lo
 mime/multipart.gox: mime/multipart.lo
        $(BUILDGOX)
 
-net/dict.gox: net/dict.lo
-       $(BUILDGOX)
 net/http.gox: net/http.lo
        $(BUILDGOX)
 net/mail.gox: net/mail.lo
index 13fe2700f9bf1603b80fe40c2dc91b32cbbbc4cd..755a730c8b4f98ddca28cc18c3a9c3c4199d62ca 100644 (file)
@@ -18,7 +18,7 @@ import (
 )
 
 var (
-       HeaderError = errors.New("invalid tar header")
+       ErrHeader = errors.New("invalid tar header")
 )
 
 // A Reader provides sequential access to the contents of a tar archive.
@@ -123,13 +123,13 @@ func (tr *Reader) readHeader() *Header {
                if bytes.Equal(header, zeroBlock[0:blockSize]) {
                        tr.err = io.EOF
                } else {
-                       tr.err = HeaderError // zero block and then non-zero block
+                       tr.err = ErrHeader // zero block and then non-zero block
                }
                return nil
        }
 
        if !tr.verifyChecksum(header) {
-               tr.err = HeaderError
+               tr.err = ErrHeader
                return nil
        }
 
@@ -188,7 +188,7 @@ func (tr *Reader) readHeader() *Header {
        }
 
        if tr.err != nil {
-               tr.err = HeaderError
+               tr.err = ErrHeader
                return nil
        }
 
index 0a6513d0cac01a8bf6cb8d9bef16db439e47b959..0a8646c393fdc3cc85bc9193a18d46f0aa1dc33b 100644 (file)
@@ -240,31 +240,20 @@ func TestNonSeekable(t *testing.T) {
        }
        defer f.Close()
 
-       // pipe the data in
-       r, w, err := os.Pipe()
-       if err != nil {
-               t.Fatalf("Unexpected error %s", err)
+       type readerOnly struct {
+               io.Reader
        }
-       go func() {
-               rdbuf := make([]uint8, 1<<16)
-               for {
-                       nr, err := f.Read(rdbuf)
-                       w.Write(rdbuf[0:nr])
-                       if err == io.EOF {
-                               break
-                       }
-               }
-               w.Close()
-       }()
-
-       tr := NewReader(r)
+       tr := NewReader(readerOnly{f})
        nread := 0
 
        for ; ; nread++ {
-               hdr, err := tr.Next()
-               if hdr == nil || err == io.EOF {
+               _, err := tr.Next()
+               if err == io.EOF {
                        break
                }
+               if err != nil {
+                       t.Fatalf("Unexpected error: %v", err)
+               }
        }
 
        if nread != len(test.headers) {
index 4365009a308f386a843c3eb1f6fddcdad9f1aa0f..4dd0f4f434421a8d8b1f473ffa1086e4a0f1c0c0 100644 (file)
@@ -17,9 +17,9 @@ import (
 )
 
 var (
-       FormatError       = errors.New("zip: not a valid zip file")
-       UnsupportedMethod = errors.New("zip: unsupported compression algorithm")
-       ChecksumError     = errors.New("zip: checksum error")
+       ErrFormat    = errors.New("zip: not a valid zip file")
+       ErrAlgorithm = errors.New("zip: unsupported compression algorithm")
+       ErrChecksum  = errors.New("zip: checksum error")
 )
 
 type Reader struct {
@@ -90,12 +90,12 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
 
        // The count of files inside a zip is truncated to fit in a uint16.
        // Gloss over this by reading headers until we encounter
-       // a bad one, and then only report a FormatError or UnexpectedEOF if
+       // a bad one, and then only report a ErrFormat or UnexpectedEOF if
        // the file count modulo 65536 is incorrect.
        for {
                f := &File{zipr: r, zipsize: size}
                err = readDirectoryHeader(f, buf)
-               if err == FormatError || err == io.ErrUnexpectedEOF {
+               if err == ErrFormat || err == io.ErrUnexpectedEOF {
                        break
                }
                if err != nil {
@@ -135,7 +135,7 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
        case Deflate:
                rc = flate.NewReader(r)
        default:
-               err = UnsupportedMethod
+               err = ErrAlgorithm
        }
        if rc != nil {
                rc = &checksumReader{rc, crc32.NewIEEE(), f, r}
@@ -162,7 +162,7 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
                }
        }
        if r.hash.Sum32() != r.f.CRC32 {
-               err = ChecksumError
+               err = ErrChecksum
        }
        return
 }
@@ -176,7 +176,7 @@ func readFileHeader(f *File, r io.Reader) error {
        }
        c := binary.LittleEndian
        if sig := c.Uint32(b[:4]); sig != fileHeaderSignature {
-               return FormatError
+               return ErrFormat
        }
        f.ReaderVersion = c.Uint16(b[4:6])
        f.Flags = c.Uint16(b[6:8])
@@ -207,7 +207,7 @@ func (f *File) findBodyOffset() (int64, error) {
        }
        c := binary.LittleEndian
        if sig := c.Uint32(b[:4]); sig != fileHeaderSignature {
-               return 0, FormatError
+               return 0, ErrFormat
        }
        filenameLen := int(c.Uint16(b[26:28]))
        extraLen := int(c.Uint16(b[28:30]))
@@ -216,7 +216,7 @@ func (f *File) findBodyOffset() (int64, error) {
 
 // readDirectoryHeader attempts to read a directory header from r.
 // It returns io.ErrUnexpectedEOF if it cannot read a complete header,
-// and FormatError if it doesn't find a valid header signature.
+// and ErrFormat if it doesn't find a valid header signature.
 func readDirectoryHeader(f *File, r io.Reader) error {
        var b [directoryHeaderLen]byte
        if _, err := io.ReadFull(r, b[:]); err != nil {
@@ -224,7 +224,7 @@ func readDirectoryHeader(f *File, r io.Reader) error {
        }
        c := binary.LittleEndian
        if sig := c.Uint32(b[:4]); sig != directoryHeaderSignature {
-               return FormatError
+               return ErrFormat
        }
        f.CreatorVersion = c.Uint16(b[4:6])
        f.ReaderVersion = c.Uint16(b[6:8])
@@ -280,7 +280,7 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
                        break
                }
                if i == 1 || bLen == size {
-                       return nil, FormatError
+                       return nil, ErrFormat
                }
        }
 
index 0e40268c2f8c5475733ebf2a1995f904f1f28c5e..9407e35d5c08ce4a7bbacfad0e3ec7ed2bde02c9 100644 (file)
@@ -70,7 +70,7 @@ var tests = []ZipTest{
                },
        },
        {Name: "readme.zip"},
-       {Name: "readme.notzip", Error: FormatError},
+       {Name: "readme.notzip", Error: ErrFormat},
        {
                Name: "dd.zip",
                File: []ZipTestFile{
@@ -131,7 +131,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
        }
 
        // bail if file is not zip
-       if err == FormatError {
+       if err == ErrFormat {
                return
        }
        defer func() {
@@ -184,8 +184,8 @@ func readTestZip(t *testing.T, zt ZipTest) {
                }
                var b bytes.Buffer
                _, err = io.Copy(&b, r)
-               if err != ChecksumError {
-                       t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
+               if err != ErrChecksum {
+                       t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ErrChecksum)
                }
        }
 }
@@ -250,13 +250,9 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
 }
 
 func testFileMode(t *testing.T, f *File, want os.FileMode) {
-       mode, err := f.Mode()
+       mode := f.Mode()
        if want == 0 {
-               if err == nil {
-                       t.Errorf("%s mode: got %v, want none", f.Name, mode)
-               }
-       } else if err != nil {
-               t.Errorf("%s mode: %s", f.Name, err)
+               t.Errorf("%s mode: got %v, want none", f.Name, mode)
        } else if mode != want {
                t.Errorf("%s mode: want %v, got %v", f.Name, want, mode)
        }
@@ -268,8 +264,8 @@ func TestInvalidFiles(t *testing.T) {
 
        // zeroes
        _, err := NewReader(sliceReaderAt(b), size)
-       if err != FormatError {
-               t.Errorf("zeroes: error=%v, want %v", err, FormatError)
+       if err != ErrFormat {
+               t.Errorf("zeroes: error=%v, want %v", err, ErrFormat)
        }
 
        // repeated directoryEndSignatures
@@ -279,8 +275,8 @@ func TestInvalidFiles(t *testing.T) {
                copy(b[i:i+4], sig)
        }
        _, err = NewReader(sliceReaderAt(b), size)
-       if err != FormatError {
-               t.Errorf("sigs: error=%v, want %v", err, FormatError)
+       if err != ErrFormat {
+               t.Errorf("sigs: error=%v, want %v", err, ErrFormat)
        }
 }
 
index 34a87fae5b330596cf05d7221b939a7c8078fee6..67e9658629419a06bdbf064254735012fdd71372 100644 (file)
@@ -12,6 +12,7 @@ This package does not support ZIP64 or disk spanning.
 package zip
 
 import (
+       "errors"
        "os"
        "time"
 )
@@ -55,6 +56,38 @@ type FileHeader struct {
        Comment          string
 }
 
+// FileInfo returns an os.FileInfo for the FileHeader.
+func (fh *FileHeader) FileInfo() os.FileInfo {
+       return headerFileInfo{fh}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+       fh *FileHeader
+}
+
+func (fi headerFileInfo) Name() string       { return fi.fh.Name }
+func (fi headerFileInfo) Size() int64        { return int64(fi.fh.UncompressedSize) }
+func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
+func (fi headerFileInfo) Mode() os.FileMode  { return fi.fh.Mode() }
+
+// FileInfoHeader creates a partially-populated FileHeader from an
+// os.FileInfo.
+func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
+       size := fi.Size()
+       if size > (1<<32 - 1) {
+               return nil, errors.New("zip: file over 4GB")
+       }
+       fh := &FileHeader{
+               Name:             fi.Name(),
+               UncompressedSize: uint32(size),
+       }
+       fh.SetModTime(fi.ModTime())
+       fh.SetMode(fi.Mode())
+       return fh, nil
+}
+
 type directoryEnd struct {
        diskNbr            uint16 // unused
        dirDiskNbr         uint16 // unused
@@ -131,8 +164,7 @@ const (
 )
 
 // Mode returns the permission and mode bits for the FileHeader.
-// An error is returned in case the information is not available.
-func (h *FileHeader) Mode() (mode os.FileMode, err error) {
+func (h *FileHeader) Mode() (mode os.FileMode) {
        switch h.CreatorVersion >> 8 {
        case creatorUnix, creatorMacOSX:
                mode = unixModeToFileMode(h.ExternalAttrs >> 16)
@@ -142,7 +174,7 @@ func (h *FileHeader) Mode() (mode os.FileMode, err error) {
        if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
                mode |= os.ModeDir
        }
-       return mode, nil
+       return mode
 }
 
 // SetMode changes the permission and mode bits for the FileHeader.
index a1530644eee64d6e222ba5f3e4f9abd51841bfe4..b1b128e2a7da406c7ef11d91e5ba9734a71b2859 100644 (file)
@@ -129,7 +129,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
        case Deflate:
                fw.comp = flate.NewWriter(fw.compCount, 5)
        default:
-               return nil, UnsupportedMethod
+               return nil, ErrAlgorithm
        }
        fw.rawCount = &countWriter{w: fw.comp}
 
index 8aab2b68123f704c4e1a255f99a3daf8f49d59b2..acd3d938218eddb9399408320a7e6a694d9e9e4a 100644 (file)
@@ -10,6 +10,7 @@ import (
        "bytes"
        "fmt"
        "io"
+       "reflect"
        "testing"
        "time"
 )
@@ -66,3 +67,22 @@ func TestModTime(t *testing.T) {
                t.Errorf("times don't match: got %s, want %s", outTime, testTime)
        }
 }
+
+func TestFileHeaderRoundTrip(t *testing.T) {
+       fh := &FileHeader{
+               Name:             "foo.txt",
+               UncompressedSize: 987654321,
+               ModifiedTime:     1234,
+               ModifiedDate:     5678,
+       }
+       fi := fh.FileInfo()
+       fh2, err := FileInfoHeader(fi)
+
+       // Ignore these fields:
+       fh2.CreatorVersion = 0
+       fh2.ExternalAttrs = 0
+
+       if !reflect.DeepEqual(fh, fh2) {
+               t.Errorf("mismatch\n input=%#v\noutput=%#v\nerr=%v", fh, fh2, err)
+       }
+}
index 77757af1d804fc501693ff416ac92c65ce425284..2c3eb6a596bb8e57dc95d5bb15497a6882d66dce 100644 (file)
@@ -33,6 +33,9 @@ const (
        opRead                   // Any other read operation.
 )
 
+// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
+var ErrTooLarge = errors.New("bytes.Buffer: too large")
+
 // Bytes returns a slice of the contents of the unread portion of the buffer;
 // len(b.Bytes()) == b.Len().  If the caller changes the contents of the
 // returned slice, the contents of the buffer will change provided there
@@ -68,8 +71,9 @@ func (b *Buffer) Truncate(n int) {
 // b.Reset() is the same as b.Truncate(0).
 func (b *Buffer) Reset() { b.Truncate(0) }
 
-// Grow buffer to guarantee space for n more bytes.
-// Return index where bytes should be written.
+// grow grows the buffer to guarantee space for n more bytes.
+// It returns the index where bytes should be written.
+// If the buffer can't grow it will panic with ErrTooLarge.
 func (b *Buffer) grow(n int) int {
        m := b.Len()
        // If buffer is empty, reset to recover space.
@@ -82,7 +86,7 @@ func (b *Buffer) grow(n int) int {
                        buf = b.bootstrap[0:]
                } else {
                        // not enough space anywhere
-                       buf = make([]byte, 2*cap(b.buf)+n)
+                       buf = makeSlice(2*cap(b.buf) + n)
                        copy(buf, b.buf[b.off:])
                }
                b.buf = buf
@@ -94,6 +98,8 @@ func (b *Buffer) grow(n int) int {
 
 // 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.
 func (b *Buffer) Write(p []byte) (n int, err error) {
        b.lastRead = opInvalid
        m := b.grow(len(p))
@@ -102,6 +108,8 @@ func (b *Buffer) Write(p []byte) (n int, err error) {
 
 // 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.
 func (b *Buffer) WriteString(s string) (n int, err error) {
        b.lastRead = opInvalid
        m := b.grow(len(s))
@@ -118,6 +126,8 @@ const MinRead = 512
 // 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.
@@ -125,18 +135,16 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
                b.Truncate(0)
        }
        for {
-               if cap(b.buf)-len(b.buf) < MinRead {
-                       var newBuf []byte
-                       // can we get space without allocation?
-                       if b.off+cap(b.buf)-len(b.buf) >= MinRead {
-                               // reuse beginning of buffer
-                               newBuf = b.buf[0 : len(b.buf)-b.off]
-                       } else {
-                               // not enough space at end; put space on end
-                               newBuf = make([]byte, len(b.buf)-b.off, 2*(cap(b.buf)-b.off)+MinRead)
+               if free := cap(b.buf) - len(b.buf); free < MinRead {
+                       // not enough space at end
+                       newBuf := b.buf
+                       if b.off+free < MinRead {
+                               // not enough space using beginning of buffer;
+                               // double buffer capacity
+                               newBuf = makeSlice(2*cap(b.buf) + MinRead)
                        }
                        copy(newBuf, b.buf[b.off:])
-                       b.buf = newBuf
+                       b.buf = newBuf[:len(b.buf)-b.off]
                        b.off = 0
                }
                m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
@@ -152,6 +160,18 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
        return n, nil // err is EOF, so return nil explicitly
 }
 
+// makeSlice allocates a slice of size n. If the allocation fails, it panics
+// with ErrTooLarge.
+func makeSlice(n int) []byte {
+       // If the make fails, give a known error.
+       defer func() {
+               if recover() != nil {
+                       panic(ErrTooLarge)
+               }
+       }()
+       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.
@@ -176,6 +196,8 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
 // 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
+// ErrTooLarge.
 func (b *Buffer) WriteByte(c byte) error {
        b.lastRead = opInvalid
        m := b.grow(1)
@@ -187,6 +209,8 @@ func (b *Buffer) WriteByte(c byte) error {
 // 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.
 func (b *Buffer) WriteRune(r rune) (n int, err error) {
        if r < utf8.RuneSelf {
                b.WriteByte(byte(r))
index 4f744457dd7e0fc0ad4de36137eaedef2f4ba437..1e725890b731e555fbdfd8dce9733b16a771bc7e 100644 (file)
@@ -27,10 +27,12 @@ const (
        // stop things from getting too large.
        maxFlateBlockTokens = 1 << 14
        maxStoreBlockSize   = 65535
-       hashBits            = 15
+       hashBits            = 17
        hashSize            = 1 << hashBits
        hashMask            = (1 << hashBits) - 1
        hashShift           = (hashBits + minMatchLength - 1) / minMatchLength
+
+       skipNever = math.MaxInt32
 )
 
 type compressionLevel struct {
@@ -45,12 +47,12 @@ var levels = []compressionLevel{
        {3, 0, 32, 32, 6},
        // Levels 4-9 use increasingly more lazy matching
        // and increasingly stringent conditions for "good enough".
-       {4, 4, 16, 16, math.MaxInt32},
-       {8, 16, 32, 32, math.MaxInt32},
-       {8, 16, 128, 128, math.MaxInt32},
-       {8, 32, 128, 256, math.MaxInt32},
-       {32, 128, 258, 1024, math.MaxInt32},
-       {32, 258, 258, 4096, math.MaxInt32},
+       {4, 4, 16, 16, skipNever},
+       {8, 16, 32, 32, skipNever},
+       {8, 16, 128, 128, skipNever},
+       {8, 32, 128, 256, skipNever},
+       {32, 128, 258, 1024, skipNever},
+       {32, 258, 258, 4096, skipNever},
 }
 
 type compressor struct {
@@ -68,9 +70,10 @@ type compressor struct {
        // If hashHead[hashValue] is within the current window, then
        // hashPrev[hashHead[hashValue] & windowMask] contains the previous index
        // with the same hash value.
-       chainHead int
-       hashHead  []int
-       hashPrev  []int
+       chainHead  int
+       hashHead   []int
+       hashPrev   []int
+       hashOffset int
 
        // input window: unprocessed data is window[index:windowEnd]
        index         int
@@ -79,9 +82,8 @@ type compressor struct {
        blockStart    int  // window index where current tokens start
        byteAvailable bool // if true, still need to process window[index-1].
 
-       // queued output tokens: tokens[:ti]
+       // queued output tokens
        tokens []token
-       ti     int
 
        // deflate state
        length         int
@@ -100,22 +102,9 @@ func (d *compressor) fillDeflate(b []byte) int {
                if d.blockStart >= windowSize {
                        d.blockStart -= windowSize
                } else {
-                       d.blockStart = math.MaxInt32
-               }
-               for i, h := range d.hashHead {
-                       v := h - windowSize
-                       if v < -1 {
-                               v = -1
-                       }
-                       d.hashHead[i] = v
-               }
-               for i, h := range d.hashPrev {
-                       v := -h - windowSize
-                       if v < -1 {
-                               v = -1
-                       }
-                       d.hashPrev[i] = v
+                       d.blockStart = skipNever
                }
+               d.hashOffset += windowSize
        }
        n := copy(d.window[d.windowEnd:], b)
        d.windowEnd += n
@@ -186,7 +175,7 @@ func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead
                        // hashPrev[i & windowMask] has already been overwritten, so stop now.
                        break
                }
-               if i = d.hashPrev[i&windowMask]; i < minIndex || i < 0 {
+               if i = d.hashPrev[i&windowMask] - d.hashOffset; i < minIndex || i < 0 {
                        break
                }
        }
@@ -205,13 +194,12 @@ func (d *compressor) initDeflate() {
        d.hashHead = make([]int, hashSize)
        d.hashPrev = make([]int, windowSize)
        d.window = make([]byte, 2*windowSize)
-       fillInts(d.hashHead, -1)
-       d.tokens = make([]token, maxFlateBlockTokens, maxFlateBlockTokens+1)
+       d.hashOffset = 1
+       d.tokens = make([]token, 0, maxFlateBlockTokens+1)
        d.length = minMatchLength - 1
        d.offset = 0
        d.byteAvailable = false
        d.index = 0
-       d.ti = 0
        d.hash = 0
        d.chainHead = -1
 }
@@ -243,15 +231,14 @@ Loop:
                                // Flush current output block if any.
                                if d.byteAvailable {
                                        // There is still one pending token that needs to be flushed
-                                       d.tokens[d.ti] = literalToken(uint32(d.window[d.index-1]))
-                                       d.ti++
+                                       d.tokens = append(d.tokens, literalToken(uint32(d.window[d.index-1])))
                                        d.byteAvailable = false
                                }
-                               if d.ti > 0 {
-                                       if d.err = d.writeBlock(d.tokens[0:d.ti], d.index, false); d.err != nil {
+                               if len(d.tokens) > 0 {
+                                       if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
                                                return
                                        }
-                                       d.ti = 0
+                                       d.tokens = d.tokens[:0]
                                }
                                break Loop
                        }
@@ -261,7 +248,7 @@ Loop:
                        d.hash = (d.hash<<hashShift + int(d.window[d.index+2])) & hashMask
                        d.chainHead = d.hashHead[d.hash]
                        d.hashPrev[d.index&windowMask] = d.chainHead
-                       d.hashHead[d.hash] = d.index
+                       d.hashHead[d.hash] = d.index + d.hashOffset
                }
                prevLength := d.length
                prevOffset := d.offset
@@ -272,34 +259,33 @@ Loop:
                        minIndex = 0
                }
 
-               if d.chainHead >= minIndex &&
-                       (d.fastSkipHashing != 0 && lookahead > minMatchLength-1 ||
-                               d.fastSkipHashing == 0 && lookahead > prevLength && prevLength < d.lazy) {
-                       if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead, minMatchLength-1, lookahead); ok {
+               if d.chainHead-d.hashOffset >= minIndex &&
+                       (d.fastSkipHashing != skipNever && lookahead > minMatchLength-1 ||
+                               d.fastSkipHashing == skipNever && lookahead > prevLength && prevLength < d.lazy) {
+                       if newLength, newOffset, ok := d.findMatch(d.index, d.chainHead-d.hashOffset, minMatchLength-1, lookahead); ok {
                                d.length = newLength
                                d.offset = newOffset
                        }
                }
-               if d.fastSkipHashing != 0 && d.length >= minMatchLength ||
-                       d.fastSkipHashing == 0 && prevLength >= minMatchLength && d.length <= prevLength {
+               if d.fastSkipHashing != skipNever && d.length >= minMatchLength ||
+                       d.fastSkipHashing == skipNever && prevLength >= minMatchLength && d.length <= prevLength {
                        // There was a match at the previous step, and the current match is
                        // not better. Output the previous match.
-                       if d.fastSkipHashing != 0 {
-                               d.tokens[d.ti] = matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize))
+                       if d.fastSkipHashing != skipNever {
+                               d.tokens = append(d.tokens, matchToken(uint32(d.length-minMatchLength), uint32(d.offset-minOffsetSize)))
                        } else {
-                               d.tokens[d.ti] = matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize))
+                               d.tokens = append(d.tokens, matchToken(uint32(prevLength-minMatchLength), uint32(prevOffset-minOffsetSize)))
                        }
-                       d.ti++
                        // Insert in the hash table all strings up to the end of the match.
                        // index and index-1 are already inserted. If there is not enough
                        // lookahead, the last two strings are not inserted into the hash
                        // table.
                        if d.length <= d.fastSkipHashing {
                                var newIndex int
-                               if d.fastSkipHashing != 0 {
+                               if d.fastSkipHashing != skipNever {
                                        newIndex = d.index + d.length
                                } else {
-                                       newIndex = prevLength - 1
+                                       newIndex = d.index + prevLength - 1
                                }
                                for d.index++; d.index < newIndex; d.index++ {
                                        if d.index < d.maxInsertIndex {
@@ -308,10 +294,10 @@ Loop:
                                                // Our chain should point to the previous value.
                                                d.hashPrev[d.index&windowMask] = d.hashHead[d.hash]
                                                // Set the head of the hash chain to us.
-                                               d.hashHead[d.hash] = d.index
+                                               d.hashHead[d.hash] = d.index + d.hashOffset
                                        }
                                }
-                               if d.fastSkipHashing == 0 {
+                               if d.fastSkipHashing == skipNever {
                                        d.byteAvailable = false
                                        d.length = minMatchLength - 1
                                }
@@ -323,30 +309,29 @@ Loop:
                                        d.hash = (int(d.window[d.index])<<hashShift + int(d.window[d.index+1]))
                                }
                        }
-                       if d.ti == maxFlateBlockTokens {
+                       if len(d.tokens) == maxFlateBlockTokens {
                                // The block includes the current character
                                if d.err = d.writeBlock(d.tokens, d.index, false); d.err != nil {
                                        return
                                }
-                               d.ti = 0
+                               d.tokens = d.tokens[:0]
                        }
                } else {
-                       if d.fastSkipHashing != 0 || d.byteAvailable {
+                       if d.fastSkipHashing != skipNever || d.byteAvailable {
                                i := d.index - 1
-                               if d.fastSkipHashing != 0 {
+                               if d.fastSkipHashing != skipNever {
                                        i = d.index
                                }
-                               d.tokens[d.ti] = literalToken(uint32(d.window[i]))
-                               d.ti++
-                               if d.ti == maxFlateBlockTokens {
+                               d.tokens = append(d.tokens, literalToken(uint32(d.window[i])))
+                               if len(d.tokens) == maxFlateBlockTokens {
                                        if d.err = d.writeBlock(d.tokens, i+1, false); d.err != nil {
                                                return
                                        }
-                                       d.ti = 0
+                                       d.tokens = d.tokens[:0]
                                }
                        }
                        d.index++
-                       if d.fastSkipHashing == 0 {
+                       if d.fastSkipHashing == skipNever {
                                d.byteAvailable = true
                        }
                }
index bae5c82305ae0c25e78d74410ec6332a04341190..24881d31c069ff7e5f9fd72c6ffee29e21f4597f 100644 (file)
@@ -225,10 +225,17 @@ func testSync(t *testing.T, level int, input []byte, name string) {
 }
 
 func testToFromWithLevel(t *testing.T, level int, input []byte, name string) error {
+       return testToFromWithLevelAndLimit(t, level, input, name, -1)
+}
+
+func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name string, limit int) error {
        buffer := bytes.NewBuffer(nil)
        w := NewWriter(buffer, level)
        w.Write(input)
        w.Close()
+       if limit > 0 && buffer.Len() > limit {
+               t.Errorf("level: %d, len(compress(data)) = %d > limit = %d", level, buffer.Len(), limit)
+       }
        r := NewReader(buffer)
        out, err := ioutil.ReadAll(r)
        if err != nil {
@@ -244,12 +251,16 @@ func testToFromWithLevel(t *testing.T, level int, input []byte, name string) err
        return nil
 }
 
-func testToFrom(t *testing.T, input []byte, name string) {
+func testToFromWithLimit(t *testing.T, input []byte, name string, limit [10]int) {
        for i := 0; i < 10; i++ {
-               testToFromWithLevel(t, i, input, name)
+               testToFromWithLevelAndLimit(t, i, input, name, limit[i])
        }
 }
 
+func testToFrom(t *testing.T, input []byte, name string) {
+       testToFromWithLimit(t, input, name, [10]int{})
+}
+
 func TestDeflateInflate(t *testing.T) {
        for i, h := range deflateInflateTests {
                testToFrom(t, h.in, fmt.Sprintf("#%d", i))
@@ -265,12 +276,33 @@ func TestReverseBits(t *testing.T) {
        }
 }
 
+type deflateInflateStringTest struct {
+       filename string
+       label    string
+       limit    [10]int
+}
+
+var deflateInflateStringTests = []deflateInflateStringTest{
+       {
+               "../testdata/e.txt",
+               "2.718281828...",
+               [...]int{10013, 5065, 5096, 5115, 5093, 5079, 5079, 5079, 5079, 5079},
+       },
+       {
+               "../testdata/Mark.Twain-Tom.Sawyer.txt",
+               "Mark.Twain-Tom.Sawyer",
+               [...]int{407330, 187598, 180361, 172974, 169160, 163476, 160936, 160506, 160295, 160295},
+       },
+}
+
 func TestDeflateInflateString(t *testing.T) {
-       gold, err := ioutil.ReadFile("../testdata/e.txt")
-       if err != nil {
-               t.Error(err)
+       for _, test := range deflateInflateStringTests {
+               gold, err := ioutil.ReadFile(test.filename)
+               if err != nil {
+                       t.Error(err)
+               }
+               testToFromWithLimit(t, gold, test.label, test.limit)
        }
-       testToFromWithLevel(t, 1, gold, "2.718281828...")
 }
 
 func TestReaderDict(t *testing.T) {
index 8d0b4f9c1e8d8f3f1757cba9d1daee6085b3be3d..57b56b5c96d5ff6fbb2b61fbb18ef29f12c521c2 100644 (file)
@@ -193,15 +193,17 @@ func (w *huffmanBitWriter) writeBytes(bytes []byte) {
 //  numLiterals      The number of literals in literalEncoding
 //  numOffsets       The number of offsets in offsetEncoding
 func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
-       fillInt32s(w.codegenFreq, 0)
+       for i := range w.codegenFreq {
+               w.codegenFreq[i] = 0
+       }
        // Note that we are using codegen both as a temporary variable for holding
        // a copy of the frequencies, and as the place where we put the result.
        // This is fine because the output is always shorter than the input used
        // so far.
        codegen := w.codegen // cache
        // Copy the concatenated code sizes to codegen.  Put a marker at the end.
-       copyUint8s(codegen[0:numLiterals], w.literalEncoding.codeBits)
-       copyUint8s(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits)
+       copy(codegen[0:numLiterals], w.literalEncoding.codeBits)
+       copy(codegen[numLiterals:numLiterals+numOffsets], w.offsetEncoding.codeBits)
        codegen[numLiterals+numOffsets] = badCode
 
        size := codegen[0]
@@ -222,7 +224,10 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
                        w.codegenFreq[size]++
                        count--
                        for count >= 3 {
-                               n := min(count, 6)
+                               n := 6
+                               if n > count {
+                                       n = count
+                               }
                                codegen[outIndex] = 16
                                outIndex++
                                codegen[outIndex] = uint8(n - 3)
@@ -232,7 +237,10 @@ func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int) {
                        }
                } else {
                        for count >= 11 {
-                               n := min(count, 138)
+                               n := 138
+                               if n > count {
+                                       n = count
+                               }
                                codegen[outIndex] = 18
                                outIndex++
                                codegen[outIndex] = uint8(n - 11)
@@ -351,8 +359,12 @@ func (w *huffmanBitWriter) writeBlock(tokens []token, eof bool, input []byte) {
        if w.err != nil {
                return
        }
-       fillInt32s(w.literalFreq, 0)
-       fillInt32s(w.offsetFreq, 0)
+       for i := range w.literalFreq {
+               w.literalFreq[i] = 0
+       }
+       for i := range w.offsetFreq {
+               w.offsetFreq[i] = 0
+       }
 
        n := len(tokens)
        tokens = tokens[0 : n+1]
index 7ed603a4f43361c4b1d34ad4cc2c7df8bcb8dbbe..4873b0fce36ed8be4f3a30c6f26c8d25d2c27125 100644 (file)
@@ -195,7 +195,9 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
 
        // The tree can't have greater depth than n - 1, no matter what.  This
        // saves a little bit of work in some small cases
-       maxBits = minInt32(maxBits, n-1)
+       if maxBits > n-1 {
+               maxBits = n - 1
+       }
 
        // Create information about each of the levels.
        // A bogus "Level 0" whose sole purpose is so that
diff --git a/libgo/go/compress/flate/util.go b/libgo/go/compress/flate/util.go
deleted file mode 100644 (file)
index aca5c78..0000000
+++ /dev/null
@@ -1,72 +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 flate
-
-func min(left int, right int) int {
-       if left < right {
-               return left
-       }
-       return right
-}
-
-func minInt32(left int32, right int32) int32 {
-       if left < right {
-               return left
-       }
-       return right
-}
-
-func max(left int, right int) int {
-       if left > right {
-               return left
-       }
-       return right
-}
-
-func fillInts(a []int, value int) {
-       for i := range a {
-               a[i] = value
-       }
-}
-
-func fillInt32s(a []int32, value int32) {
-       for i := range a {
-               a[i] = value
-       }
-}
-
-func fillBytes(a []byte, value byte) {
-       for i := range a {
-               a[i] = value
-       }
-}
-
-func fillInt8s(a []int8, value int8) {
-       for i := range a {
-               a[i] = value
-       }
-}
-
-func fillUint8s(a []uint8, value uint8) {
-       for i := range a {
-               a[i] = value
-       }
-}
-
-func copyInt8s(dst []int8, src []int8) int {
-       cnt := min(len(dst), len(src))
-       for i := 0; i < cnt; i++ {
-               dst[i] = src[i]
-       }
-       return cnt
-}
-
-func copyUint8s(dst []uint8, src []uint8) int {
-       cnt := min(len(dst), len(src))
-       for i := 0; i < cnt; i++ {
-               dst[i] = src[i]
-       }
-       return cnt
-}
index 6d60fdd0ff360c7b75d28b14634fab81d4d59b5f..d3743105d187abb6e2bcd39387ba9278aa359b9f 100644 (file)
@@ -37,8 +37,8 @@ func makeReader(r io.Reader) flate.Reader {
        return bufio.NewReader(r)
 }
 
-var HeaderError = errors.New("invalid gzip header")
-var ChecksumError = errors.New("gzip checksum error")
+var ErrHeader = errors.New("invalid gzip header")
+var ErrChecksum = errors.New("gzip checksum error")
 
 // The gzip file stores a header giving metadata about the compressed file.
 // That header is exposed as the fields of the Compressor and Decompressor structs.
@@ -59,7 +59,7 @@ type Header struct {
 // Only the first header is recorded in the Decompressor fields.
 //
 // Gzip files store a length and checksum of the uncompressed data.
-// The Decompressor will return a ChecksumError when Read
+// The Decompressor will return a ErrChecksum when Read
 // reaches the end of the uncompressed data if it does not
 // have the expected length or checksum.  Clients should treat data
 // returned by Read as tentative until they receive the successful
@@ -99,7 +99,7 @@ func (z *Decompressor) readString() (string, error) {
        needconv := false
        for i := 0; ; i++ {
                if i >= len(z.buf) {
-                       return "", HeaderError
+                       return "", ErrHeader
                }
                z.buf[i], err = z.r.ReadByte()
                if err != nil {
@@ -137,7 +137,7 @@ func (z *Decompressor) readHeader(save bool) error {
                return err
        }
        if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
-               return HeaderError
+               return ErrHeader
        }
        z.flg = z.buf[3]
        if save {
@@ -188,7 +188,7 @@ func (z *Decompressor) readHeader(save bool) error {
                }
                sum := z.digest.Sum32() & 0xFFFF
                if n != sum {
-                       return HeaderError
+                       return ErrHeader
                }
        }
 
@@ -221,7 +221,7 @@ func (z *Decompressor) Read(p []byte) (n int, err error) {
        crc32, isize := get4(z.buf[0:4]), get4(z.buf[4:8])
        sum := z.digest.Sum32()
        if sum != crc32 || isize != z.size {
-               z.err = ChecksumError
+               z.err = ErrChecksum
                return 0, z.err
        }
 
index 771b0b6a1b4ddc42d74e02446db715bcccdda9cc..a1333580dc006c62fb6589e608b2a97e28fcfa75 100644 (file)
@@ -232,7 +232,7 @@ var gunzipTests = []gunzipTest{
                        0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00,
                        0x00, 0x00, 'g', 'a', 'r', 'b', 'a', 'g', 'e', '!', '!', '!',
                },
-               HeaderError,
+               ErrHeader,
        },
        { // has 1 non-empty fixed huffman block not enough header
                "hello.txt",
@@ -260,7 +260,7 @@ var gunzipTests = []gunzipTest{
                        0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x00,
                        0x00, 0x00,
                },
-               ChecksumError,
+               ErrChecksum,
        },
        { // has 1 non-empty fixed huffman block but corrupt size
                "hello.txt",
@@ -274,7 +274,7 @@ var gunzipTests = []gunzipTest{
                        0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0xff, 0x00,
                        0x00, 0x00,
                },
-               ChecksumError,
+               ErrChecksum,
        },
 }
 
diff --git a/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/libgo/go/compress/testdata/Mark.Twain-Tom.Sawyer.txt
new file mode 100644 (file)
index 0000000..8d0ff4e
--- /dev/null
@@ -0,0 +1,8858 @@
+The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+
+Title: The Adventures of Tom Sawyer, Complete
+
+Author: Mark Twain (Samuel Clemens)
+
+Release Date: August 20, 2006 [EBook #74]
+[Last updated: May 3, 2011]
+
+Language: English
+
+
+*** START OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+
+
+
+Produced by David Widger. The previous edition was updated by Jose
+Menendez.
+
+
+
+
+
+                   THE ADVENTURES OF TOM SAWYER
+                                BY
+                            MARK TWAIN
+                     (Samuel Langhorne Clemens)
+
+
+
+
+                           P R E F A C E
+
+MOST of the adventures recorded in this book really occurred; one or
+two were experiences of my own, the rest those of boys who were
+schoolmates of mine. Huck Finn is drawn from life; Tom Sawyer also, but
+not from an individual--he is a combination of the characteristics of
+three boys whom I knew, and therefore belongs to the composite order of
+architecture.
+
+The odd superstitions touched upon were all prevalent among children
+and slaves in the West at the period of this story--that is to say,
+thirty or forty years ago.
+
+Although my book is intended mainly for the entertainment of boys and
+girls, I hope it will not be shunned by men and women on that account,
+for part of my plan has been to try to pleasantly remind adults of what
+they once were themselves, and of how they felt and thought and talked,
+and what queer enterprises they sometimes engaged in.
+
+                                                            THE AUTHOR.
+
+HARTFORD, 1876.
+
+
+
+                          T O M   S A W Y E R
+
+
+
+CHAPTER I
+
+"TOM!"
+
+No answer.
+
+"TOM!"
+
+No answer.
+
+"What's gone with that boy,  I wonder? You TOM!"
+
+No answer.
+
+The old lady pulled her spectacles down and looked over them about the
+room; then she put them up and looked out under them. She seldom or
+never looked THROUGH them for so small a thing as a boy; they were her
+state pair, the pride of her heart, and were built for "style," not
+service--she could have seen through a pair of stove-lids just as well.
+She looked perplexed for a moment, and then said, not fiercely, but
+still loud enough for the furniture to hear:
+
+"Well, I lay if I get hold of you I'll--"
+
+She did not finish, for by this time she was bending down and punching
+under the bed with the broom, and so she needed breath to punctuate the
+punches with. She resurrected nothing but the cat.
+
+"I never did see the beat of that boy!"
+
+She went to the open door and stood in it and looked out among the
+tomato vines and "jimpson" weeds that constituted the garden. No Tom.
+So she lifted up her voice at an angle calculated for distance and
+shouted:
+
+"Y-o-u-u TOM!"
+
+There was a slight noise behind her and she turned just in time to
+seize a small boy by the slack of his roundabout and arrest his flight.
+
+"There! I might 'a' thought of that closet. What you been doing in
+there?"
+
+"Nothing."
+
+"Nothing! Look at your hands. And look at your mouth. What IS that
+truck?"
+
+"I don't know, aunt."
+
+"Well, I know. It's jam--that's what it is. Forty times I've said if
+you didn't let that jam alone I'd skin you. Hand me that switch."
+
+The switch hovered in the air--the peril was desperate--
+
+"My! Look behind you, aunt!"
+
+The old lady whirled round, and snatched her skirts out of danger. The
+lad fled on the instant, scrambled up the high board-fence, and
+disappeared over it.
+
+His aunt Polly stood surprised a moment, and then broke into a gentle
+laugh.
+
+"Hang the boy, can't I never learn anything? Ain't he played me tricks
+enough like that for me to be looking out for him by this time? But old
+fools is the biggest fools there is. Can't learn an old dog new tricks,
+as the saying is. But my goodness, he never plays them alike, two days,
+and how is a body to know what's coming? He 'pears to know just how
+long he can torment me before I get my dander up, and he knows if he
+can make out to put me off for a minute or make me laugh, it's all down
+again and I can't hit him a lick. I ain't doing my duty by that boy,
+and that's the Lord's truth, goodness knows. Spare the rod and spile
+the child, as the Good Book says. I'm a laying up sin and suffering for
+us both, I know. He's full of the Old Scratch, but laws-a-me! he's my
+own dead sister's boy, poor thing, and I ain't got the heart to lash
+him, somehow. Every time I let him off, my conscience does hurt me so,
+and every time I hit him my old heart most breaks. Well-a-well, man
+that is born of woman is of few days and full of trouble, as the
+Scripture says, and I reckon it's so. He'll play hookey this evening, *
+and [* Southwestern for "afternoon"] I'll just be obleeged to make him
+work, to-morrow, to punish him. It's mighty hard to make him work
+Saturdays, when all the boys is having holiday, but he hates work more
+than he hates anything else, and I've GOT to do some of my duty by him,
+or I'll be the ruination of the child."
+
+Tom did play hookey, and he had a very good time. He got back home
+barely in season to help Jim, the small colored boy, saw next-day's
+wood and split the kindlings before supper--at least he was there in
+time to tell his adventures to Jim while Jim did three-fourths of the
+work. Tom's younger brother (or rather half-brother) Sid was already
+through with his part of the work (picking up chips), for he was a
+quiet boy, and had no adventurous, troublesome ways.
+
+While Tom was eating his supper, and stealing sugar as opportunity
+offered, Aunt Polly asked him questions that were full of guile, and
+very deep--for she wanted to trap him into damaging revealments. Like
+many other simple-hearted souls, it was her pet vanity to believe she
+was endowed with a talent for dark and mysterious diplomacy, and she
+loved to contemplate her most transparent devices as marvels of low
+cunning. Said she:
+
+"Tom, it was middling warm in school, warn't it?"
+
+"Yes'm."
+
+"Powerful warm, warn't it?"
+
+"Yes'm."
+
+"Didn't you want to go in a-swimming, Tom?"
+
+A bit of a scare shot through Tom--a touch of uncomfortable suspicion.
+He searched Aunt Polly's face, but it told him nothing. So he said:
+
+"No'm--well, not very much."
+
+The old lady reached out her hand and felt Tom's shirt, and said:
+
+"But you ain't too warm now, though." And it flattered her to reflect
+that she had discovered that the shirt was dry without anybody knowing
+that that was what she had in her mind. But in spite of her, Tom knew
+where the wind lay, now. So he forestalled what might be the next move:
+
+"Some of us pumped on our heads--mine's damp yet. See?"
+
+Aunt Polly was vexed to think she had overlooked that bit of
+circumstantial evidence, and missed a trick. Then she had a new
+inspiration:
+
+"Tom, you didn't have to undo your shirt collar where I sewed it, to
+pump on your head, did you? Unbutton your jacket!"
+
+The trouble vanished out of Tom's face. He opened his jacket. His
+shirt collar was securely sewed.
+
+"Bother! Well, go 'long with you. I'd made sure you'd played hookey
+and been a-swimming. But I forgive ye, Tom. I reckon you're a kind of a
+singed cat, as the saying is--better'n you look. THIS time."
+
+She was half sorry her sagacity had miscarried, and half glad that Tom
+had stumbled into obedient conduct for once.
+
+But Sidney said:
+
+"Well, now, if I didn't think you sewed his collar with white thread,
+but it's black."
+
+"Why, I did sew it with white! Tom!"
+
+But Tom did not wait for the rest. As he went out at the door he said:
+
+"Siddy, I'll lick you for that."
+
+In a safe place Tom examined two large needles which were thrust into
+the lapels of his jacket, and had thread bound about them--one needle
+carried white thread and the other black. He said:
+
+"She'd never noticed if it hadn't been for Sid. Confound it! sometimes
+she sews it with white, and sometimes she sews it with black. I wish to
+geeminy she'd stick to one or t'other--I can't keep the run of 'em. But
+I bet you I'll lam Sid for that. I'll learn him!"
+
+He was not the Model Boy of the village. He knew the model boy very
+well though--and loathed him.
+
+Within two minutes, or even less, he had forgotten all his troubles.
+Not because his troubles were one whit less heavy and bitter to him
+than a man's are to a man, but because a new and powerful interest bore
+them down and drove them out of his mind for the time--just as men's
+misfortunes are forgotten in the excitement of new enterprises. This
+new interest was a valued novelty in whistling, which he had just
+acquired from a negro, and he was suffering to practise it undisturbed.
+It consisted in a peculiar bird-like turn, a sort of liquid warble,
+produced by touching the tongue to the roof of the mouth at short
+intervals in the midst of the music--the reader probably remembers how
+to do it, if he has ever been a boy. Diligence and attention soon gave
+him the knack of it, and he strode down the street with his mouth full
+of harmony and his soul full of gratitude. He felt much as an
+astronomer feels who has discovered a new planet--no doubt, as far as
+strong, deep, unalloyed pleasure is concerned, the advantage was with
+the boy, not the astronomer.
+
+The summer evenings were long. It was not dark, yet. Presently Tom
+checked his whistle. A stranger was before him--a boy a shade larger
+than himself. A new-comer of any age or either sex was an impressive
+curiosity in the poor little shabby village of St. Petersburg. This boy
+was well dressed, too--well dressed on a week-day. This was simply
+astounding. His cap was a dainty thing, his close-buttoned blue cloth
+roundabout was new and natty, and so were his pantaloons. He had shoes
+on--and it was only Friday. He even wore a necktie, a bright bit of
+ribbon. He had a citified air about him that ate into Tom's vitals. The
+more Tom stared at the splendid marvel, the higher he turned up his
+nose at his finery and the shabbier and shabbier his own outfit seemed
+to him to grow. Neither boy spoke. If one moved, the other moved--but
+only sidewise, in a circle; they kept face to face and eye to eye all
+the time. Finally Tom said:
+
+"I can lick you!"
+
+"I'd like to see you try it."
+
+"Well, I can do it."
+
+"No you can't, either."
+
+"Yes I can."
+
+"No you can't."
+
+"I can."
+
+"You can't."
+
+"Can!"
+
+"Can't!"
+
+An uncomfortable pause. Then Tom said:
+
+"What's your name?"
+
+"'Tisn't any of your business, maybe."
+
+"Well I 'low I'll MAKE it my business."
+
+"Well why don't you?"
+
+"If you say much, I will."
+
+"Much--much--MUCH. There now."
+
+"Oh, you think you're mighty smart, DON'T you? I could lick you with
+one hand tied behind me, if I wanted to."
+
+"Well why don't you DO it? You SAY you can do it."
+
+"Well I WILL, if you fool with me."
+
+"Oh yes--I've seen whole families in the same fix."
+
+"Smarty! You think you're SOME, now, DON'T you? Oh, what a hat!"
+
+"You can lump that hat if you don't like it. I dare you to knock it
+off--and anybody that'll take a dare will suck eggs."
+
+"You're a liar!"
+
+"You're another."
+
+"You're a fighting liar and dasn't take it up."
+
+"Aw--take a walk!"
+
+"Say--if you give me much more of your sass I'll take and bounce a
+rock off'n your head."
+
+"Oh, of COURSE you will."
+
+"Well I WILL."
+
+"Well why don't you DO it then? What do you keep SAYING you will for?
+Why don't you DO it? It's because you're afraid."
+
+"I AIN'T afraid."
+
+"You are."
+
+"I ain't."
+
+"You are."
+
+Another pause, and more eying and sidling around each other. Presently
+they were shoulder to shoulder. Tom said:
+
+"Get away from here!"
+
+"Go away yourself!"
+
+"I won't."
+
+"I won't either."
+
+So they stood, each with a foot placed at an angle as a brace, and
+both shoving with might and main, and glowering at each other with
+hate. But neither could get an advantage. After struggling till both
+were hot and flushed, each relaxed his strain with watchful caution,
+and Tom said:
+
+"You're a coward and a pup. I'll tell my big brother on you, and he
+can thrash you with his little finger, and I'll make him do it, too."
+
+"What do I care for your big brother? I've got a brother that's bigger
+than he is--and what's more, he can throw him over that fence, too."
+[Both brothers were imaginary.]
+
+"That's a lie."
+
+"YOUR saying so don't make it so."
+
+Tom drew a line in the dust with his big toe, and said:
+
+"I dare you to step over that, and I'll lick you till you can't stand
+up. Anybody that'll take a dare will steal sheep."
+
+The new boy stepped over promptly, and said:
+
+"Now you said you'd do it, now let's see you do it."
+
+"Don't you crowd me now; you better look out."
+
+"Well, you SAID you'd do it--why don't you do it?"
+
+"By jingo! for two cents I WILL do it."
+
+The new boy took two broad coppers out of his pocket and held them out
+with derision. Tom struck them to the ground. In an instant both boys
+were rolling and tumbling in the dirt, gripped together like cats; and
+for the space of a minute they tugged and tore at each other's hair and
+clothes, punched and scratched each other's nose, and covered
+themselves with dust and glory. Presently the confusion took form, and
+through the fog of battle Tom appeared, seated astride the new boy, and
+pounding him with his fists. "Holler 'nuff!" said he.
+
+The boy only struggled to free himself. He was crying--mainly from rage.
+
+"Holler 'nuff!"--and the pounding went on.
+
+At last the stranger got out a smothered "'Nuff!" and Tom let him up
+and said:
+
+"Now that'll learn you. Better look out who you're fooling with next
+time."
+
+The new boy went off brushing the dust from his clothes, sobbing,
+snuffling, and occasionally looking back and shaking his head and
+threatening what he would do to Tom the "next time he caught him out."
+To which Tom responded with jeers, and started off in high feather, and
+as soon as his back was turned the new boy snatched up a stone, threw
+it and hit him between the shoulders and then turned tail and ran like
+an antelope. Tom chased the traitor home, and thus found out where he
+lived. He then held a position at the gate for some time, daring the
+enemy to come outside, but the enemy only made faces at him through the
+window and declined. At last the enemy's mother appeared, and called
+Tom a bad, vicious, vulgar child, and ordered him away. So he went
+away; but he said he "'lowed" to "lay" for that boy.
+
+He got home pretty late that night, and when he climbed cautiously in
+at the window, he uncovered an ambuscade, in the person of his aunt;
+and when she saw the state his clothes were in her resolution to turn
+his Saturday holiday into captivity at hard labor became adamantine in
+its firmness.
+
+
+
+CHAPTER II
+
+SATURDAY morning was come, and all the summer world was bright and
+fresh, and brimming with life. There was a song in every heart; and if
+the heart was young the music issued at the lips. There was cheer in
+every face and a spring in every step. The locust-trees were in bloom
+and the fragrance of the blossoms filled the air. Cardiff Hill, beyond
+the village and above it, was green with vegetation and it lay just far
+enough away to seem a Delectable Land, dreamy, reposeful, and inviting.
+
+Tom appeared on the sidewalk with a bucket of whitewash and a
+long-handled brush. He surveyed the fence, and all gladness left him and
+a deep melancholy settled down upon his spirit. Thirty yards of board
+fence nine feet high. Life to him seemed hollow, and existence but a
+burden. Sighing, he dipped his brush and passed it along the topmost
+plank; repeated the operation; did it again; compared the insignificant
+whitewashed streak with the far-reaching continent of unwhitewashed
+fence, and sat down on a tree-box discouraged. Jim came skipping out at
+the gate with a tin pail, and singing Buffalo Gals. Bringing water from
+the town pump had always been hateful work in Tom's eyes, before, but
+now it did not strike him so. He remembered that there was company at
+the pump. White, mulatto, and negro boys and girls were always there
+waiting their turns, resting, trading playthings, quarrelling,
+fighting, skylarking. And he remembered that although the pump was only
+a hundred and fifty yards off, Jim never got back with a bucket of
+water under an hour--and even then somebody generally had to go after
+him. Tom said:
+
+"Say, Jim, I'll fetch the water if you'll whitewash some."
+
+Jim shook his head and said:
+
+"Can't, Mars Tom. Ole missis, she tole me I got to go an' git dis
+water an' not stop foolin' roun' wid anybody. She say she spec' Mars
+Tom gwine to ax me to whitewash, an' so she tole me go 'long an' 'tend
+to my own business--she 'lowed SHE'D 'tend to de whitewashin'."
+
+"Oh, never you mind what she said, Jim. That's the way she always
+talks. Gimme the bucket--I won't be gone only a a minute. SHE won't
+ever know."
+
+"Oh, I dasn't, Mars Tom. Ole missis she'd take an' tar de head off'n
+me. 'Deed she would."
+
+"SHE! She never licks anybody--whacks 'em over the head with her
+thimble--and who cares for that, I'd like to know. She talks awful, but
+talk don't hurt--anyways it don't if she don't cry. Jim, I'll give you
+a marvel. I'll give you a white alley!"
+
+Jim began to waver.
+
+"White alley, Jim! And it's a bully taw."
+
+"My! Dat's a mighty gay marvel, I tell you! But Mars Tom I's powerful
+'fraid ole missis--"
+
+"And besides, if you will I'll show you my sore toe."
+
+Jim was only human--this attraction was too much for him. He put down
+his pail, took the white alley, and bent over the toe with absorbing
+interest while the bandage was being unwound. In another moment he was
+flying down the street with his pail and a tingling rear, Tom was
+whitewashing with vigor, and Aunt Polly was retiring from the field
+with a slipper in her hand and triumph in her eye.
+
+But Tom's energy did not last. He began to think of the fun he had
+planned for this day, and his sorrows multiplied. Soon the free boys
+would come tripping along on all sorts of delicious expeditions, and
+they would make a world of fun of him for having to work--the very
+thought of it burnt him like fire. He got out his worldly wealth and
+examined it--bits of toys, marbles, and trash; enough to buy an
+exchange of WORK, maybe, but not half enough to buy so much as half an
+hour of pure freedom. So he returned his straitened means to his
+pocket, and gave up the idea of trying to buy the boys. At this dark
+and hopeless moment an inspiration burst upon him! Nothing less than a
+great, magnificent inspiration.
+
+He took up his brush and went tranquilly to work. Ben Rogers hove in
+sight presently--the very boy, of all boys, whose ridicule he had been
+dreading. Ben's gait was the hop-skip-and-jump--proof enough that his
+heart was light and his anticipations high. He was eating an apple, and
+giving a long, melodious whoop, at intervals, followed by a deep-toned
+ding-dong-dong, ding-dong-dong, for he was personating a steamboat. As
+he drew near, he slackened speed, took the middle of the street, leaned
+far over to starboard and rounded to ponderously and with laborious
+pomp and circumstance--for he was personating the Big Missouri, and
+considered himself to be drawing nine feet of water. He was boat and
+captain and engine-bells combined, so he had to imagine himself
+standing on his own hurricane-deck giving the orders and executing them:
+
+"Stop her, sir! Ting-a-ling-ling!" The headway ran almost out, and he
+drew up slowly toward the sidewalk.
+
+"Ship up to back! Ting-a-ling-ling!" His arms straightened and
+stiffened down his sides.
+
+"Set her back on the stabboard! Ting-a-ling-ling! Chow! ch-chow-wow!
+Chow!" His right hand, meantime, describing stately circles--for it was
+representing a forty-foot wheel.
+
+"Let her go back on the labboard! Ting-a-lingling! Chow-ch-chow-chow!"
+The left hand began to describe circles.
+
+"Stop the stabboard! Ting-a-ling-ling! Stop the labboard! Come ahead
+on the stabboard! Stop her! Let your outside turn over slow!
+Ting-a-ling-ling! Chow-ow-ow! Get out that head-line! LIVELY now!
+Come--out with your spring-line--what're you about there! Take a turn
+round that stump with the bight of it! Stand by that stage, now--let her
+go! Done with the engines, sir! Ting-a-ling-ling! SH'T! S'H'T! SH'T!"
+(trying the gauge-cocks).
+
+Tom went on whitewashing--paid no attention to the steamboat. Ben
+stared a moment and then said: "Hi-YI! YOU'RE up a stump, ain't you!"
+
+No answer. Tom surveyed his last touch with the eye of an artist, then
+he gave his brush another gentle sweep and surveyed the result, as
+before. Ben ranged up alongside of him. Tom's mouth watered for the
+apple, but he stuck to his work. Ben said:
+
+"Hello, old chap, you got to work, hey?"
+
+Tom wheeled suddenly and said:
+
+"Why, it's you, Ben! I warn't noticing."
+
+"Say--I'm going in a-swimming, I am. Don't you wish you could? But of
+course you'd druther WORK--wouldn't you? Course you would!"
+
+Tom contemplated the boy a bit, and said:
+
+"What do you call work?"
+
+"Why, ain't THAT work?"
+
+Tom resumed his whitewashing, and answered carelessly:
+
+"Well, maybe it is, and maybe it ain't. All I know, is, it suits Tom
+Sawyer."
+
+"Oh come, now, you don't mean to let on that you LIKE it?"
+
+The brush continued to move.
+
+"Like it? Well, I don't see why I oughtn't to like it. Does a boy get
+a chance to whitewash a fence every day?"
+
+That put the thing in a new light. Ben stopped nibbling his apple. Tom
+swept his brush daintily back and forth--stepped back to note the
+effect--added a touch here and there--criticised the effect again--Ben
+watching every move and getting more and more interested, more and more
+absorbed. Presently he said:
+
+"Say, Tom, let ME whitewash a little."
+
+Tom considered, was about to consent; but he altered his mind:
+
+"No--no--I reckon it wouldn't hardly do, Ben. You see, Aunt Polly's
+awful particular about this fence--right here on the street, you know
+--but if it was the back fence I wouldn't mind and SHE wouldn't. Yes,
+she's awful particular about this fence; it's got to be done very
+careful; I reckon there ain't one boy in a thousand, maybe two
+thousand, that can do it the way it's got to be done."
+
+"No--is that so? Oh come, now--lemme just try. Only just a little--I'd
+let YOU, if you was me, Tom."
+
+"Ben, I'd like to, honest injun; but Aunt Polly--well, Jim wanted to
+do it, but she wouldn't let him; Sid wanted to do it, and she wouldn't
+let Sid. Now don't you see how I'm fixed? If you was to tackle this
+fence and anything was to happen to it--"
+
+"Oh, shucks, I'll be just as careful. Now lemme try. Say--I'll give
+you the core of my apple."
+
+"Well, here--No, Ben, now don't. I'm afeard--"
+
+"I'll give you ALL of it!"
+
+Tom gave up the brush with reluctance in his face, but alacrity in his
+heart. And while the late steamer Big Missouri worked and sweated in
+the sun, the retired artist sat on a barrel in the shade close by,
+dangled his legs, munched his apple, and planned the slaughter of more
+innocents. There was no lack of material; boys happened along every
+little while; they came to jeer, but remained to whitewash. By the time
+Ben was fagged out, Tom had traded the next chance to Billy Fisher for
+a kite, in good repair; and when he played out, Johnny Miller bought in
+for a dead rat and a string to swing it with--and so on, and so on,
+hour after hour. And when the middle of the afternoon came, from being
+a poor poverty-stricken boy in the morning, Tom was literally rolling
+in wealth. He had besides the things before mentioned, twelve marbles,
+part of a jews-harp, a piece of blue bottle-glass to look through, a
+spool cannon, a key that wouldn't unlock anything, a fragment of chalk,
+a glass stopper of a decanter, a tin soldier, a couple of tadpoles, six
+fire-crackers, a kitten with only one eye, a brass doorknob, a
+dog-collar--but no dog--the handle of a knife, four pieces of
+orange-peel, and a dilapidated old window sash.
+
+He had had a nice, good, idle time all the while--plenty of company
+--and the fence had three coats of whitewash on it! If he hadn't run out
+of whitewash he would have bankrupted every boy in the village.
+
+Tom said to himself that it was not such a hollow world, after all. He
+had discovered a great law of human action, without knowing it--namely,
+that in order to make a man or a boy covet a thing, it is only
+necessary to make the thing difficult to attain. If he had been a great
+and wise philosopher, like the writer of this book, he would now have
+comprehended that Work consists of whatever a body is OBLIGED to do,
+and that Play consists of whatever a body is not obliged to do. And
+this would help him to understand why constructing artificial flowers
+or performing on a tread-mill is work, while rolling ten-pins or
+climbing Mont Blanc is only amusement. There are wealthy gentlemen in
+England who drive four-horse passenger-coaches twenty or thirty miles
+on a daily line, in the summer, because the privilege costs them
+considerable money; but if they were offered wages for the service,
+that would turn it into work and then they would resign.
+
+The boy mused awhile over the substantial change which had taken place
+in his worldly circumstances, and then wended toward headquarters to
+report.
+
+
+
+CHAPTER III
+
+TOM presented himself before Aunt Polly, who was sitting by an open
+window in a pleasant rearward apartment, which was bedroom,
+breakfast-room, dining-room, and library, combined. The balmy summer
+air, the restful quiet, the odor of the flowers, and the drowsing murmur
+of the bees had had their effect, and she was nodding over her knitting
+--for she had no company but the cat, and it was asleep in her lap. Her
+spectacles were propped up on her gray head for safety. She had thought
+that of course Tom had deserted long ago, and she wondered at seeing him
+place himself in her power again in this intrepid way. He said: "Mayn't
+I go and play now, aunt?"
+
+"What, a'ready? How much have you done?"
+
+"It's all done, aunt."
+
+"Tom, don't lie to me--I can't bear it."
+
+"I ain't, aunt; it IS all done."
+
+Aunt Polly placed small trust in such evidence. She went out to see
+for herself; and she would have been content to find twenty per cent.
+of Tom's statement true. When she found the entire fence whitewashed,
+and not only whitewashed but elaborately coated and recoated, and even
+a streak added to the ground, her astonishment was almost unspeakable.
+She said:
+
+"Well, I never! There's no getting round it, you can work when you're
+a mind to, Tom." And then she diluted the compliment by adding, "But
+it's powerful seldom you're a mind to, I'm bound to say. Well, go 'long
+and play; but mind you get back some time in a week, or I'll tan you."
+
+She was so overcome by the splendor of his achievement that she took
+him into the closet and selected a choice apple and delivered it to
+him, along with an improving lecture upon the added value and flavor a
+treat took to itself when it came without sin through virtuous effort.
+And while she closed with a happy Scriptural flourish, he "hooked" a
+doughnut.
+
+Then he skipped out, and saw Sid just starting up the outside stairway
+that led to the back rooms on the second floor. Clods were handy and
+the air was full of them in a twinkling. They raged around Sid like a
+hail-storm; and before Aunt Polly could collect her surprised faculties
+and sally to the rescue, six or seven clods had taken personal effect,
+and Tom was over the fence and gone. There was a gate, but as a general
+thing he was too crowded for time to make use of it. His soul was at
+peace, now that he had settled with Sid for calling attention to his
+black thread and getting him into trouble.
+
+Tom skirted the block, and came round into a muddy alley that led by
+the back of his aunt's cow-stable. He presently got safely beyond the
+reach of capture and punishment, and hastened toward the public square
+of the village, where two "military" companies of boys had met for
+conflict, according to previous appointment. Tom was General of one of
+these armies, Joe Harper (a bosom friend) General of the other. These
+two great commanders did not condescend to fight in person--that being
+better suited to the still smaller fry--but sat together on an eminence
+and conducted the field operations by orders delivered through
+aides-de-camp. Tom's army won a great victory, after a long and
+hard-fought battle. Then the dead were counted, prisoners exchanged,
+the terms of the next disagreement agreed upon, and the day for the
+necessary battle appointed; after which the armies fell into line and
+marched away, and Tom turned homeward alone.
+
+As he was passing by the house where Jeff Thatcher lived, he saw a new
+girl in the garden--a lovely little blue-eyed creature with yellow hair
+plaited into two long-tails, white summer frock and embroidered
+pantalettes. The fresh-crowned hero fell without firing a shot. A
+certain Amy Lawrence vanished out of his heart and left not even a
+memory of herself behind. He had thought he loved her to distraction;
+he had regarded his passion as adoration; and behold it was only a poor
+little evanescent partiality. He had been months winning her; she had
+confessed hardly a week ago; he had been the happiest and the proudest
+boy in the world only seven short days, and here in one instant of time
+she had gone out of his heart like a casual stranger whose visit is
+done.
+
+He worshipped this new angel with furtive eye, till he saw that she
+had discovered him; then he pretended he did not know she was present,
+and began to "show off" in all sorts of absurd boyish ways, in order to
+win her admiration. He kept up this grotesque foolishness for some
+time; but by-and-by, while he was in the midst of some dangerous
+gymnastic performances, he glanced aside and saw that the little girl
+was wending her way toward the house. Tom came up to the fence and
+leaned on it, grieving, and hoping she would tarry yet awhile longer.
+She halted a moment on the steps and then moved toward the door. Tom
+heaved a great sigh as she put her foot on the threshold. But his face
+lit up, right away, for she tossed a pansy over the fence a moment
+before she disappeared.
+
+The boy ran around and stopped within a foot or two of the flower, and
+then shaded his eyes with his hand and began to look down street as if
+he had discovered something of interest going on in that direction.
+Presently he picked up a straw and began trying to balance it on his
+nose, with his head tilted far back; and as he moved from side to side,
+in his efforts, he edged nearer and nearer toward the pansy; finally
+his bare foot rested upon it, his pliant toes closed upon it, and he
+hopped away with the treasure and disappeared round the corner. But
+only for a minute--only while he could button the flower inside his
+jacket, next his heart--or next his stomach, possibly, for he was not
+much posted in anatomy, and not hypercritical, anyway.
+
+He returned, now, and hung about the fence till nightfall, "showing
+off," as before; but the girl never exhibited herself again, though Tom
+comforted himself a little with the hope that she had been near some
+window, meantime, and been aware of his attentions. Finally he strode
+home reluctantly, with his poor head full of visions.
+
+All through supper his spirits were so high that his aunt wondered
+"what had got into the child." He took a good scolding about clodding
+Sid, and did not seem to mind it in the least. He tried to steal sugar
+under his aunt's very nose, and got his knuckles rapped for it. He said:
+
+"Aunt, you don't whack Sid when he takes it."
+
+"Well, Sid don't torment a body the way you do. You'd be always into
+that sugar if I warn't watching you."
+
+Presently she stepped into the kitchen, and Sid, happy in his
+immunity, reached for the sugar-bowl--a sort of glorying over Tom which
+was wellnigh unbearable. But Sid's fingers slipped and the bowl dropped
+and broke. Tom was in ecstasies. In such ecstasies that he even
+controlled his tongue and was silent. He said to himself that he would
+not speak a word, even when his aunt came in, but would sit perfectly
+still till she asked who did the mischief; and then he would tell, and
+there would be nothing so good in the world as to see that pet model
+"catch it." He was so brimful of exultation that he could hardly hold
+himself when the old lady came back and stood above the wreck
+discharging lightnings of wrath from over her spectacles. He said to
+himself, "Now it's coming!" And the next instant he was sprawling on
+the floor! The potent palm was uplifted to strike again when Tom cried
+out:
+
+"Hold on, now, what 'er you belting ME for?--Sid broke it!"
+
+Aunt Polly paused, perplexed, and Tom looked for healing pity. But
+when she got her tongue again, she only said:
+
+"Umf! Well, you didn't get a lick amiss, I reckon. You been into some
+other audacious mischief when I wasn't around, like enough."
+
+Then her conscience reproached her, and she yearned to say something
+kind and loving; but she judged that this would be construed into a
+confession that she had been in the wrong, and discipline forbade that.
+So she kept silence, and went about her affairs with a troubled heart.
+Tom sulked in a corner and exalted his woes. He knew that in her heart
+his aunt was on her knees to him, and he was morosely gratified by the
+consciousness of it. He would hang out no signals, he would take notice
+of none. He knew that a yearning glance fell upon him, now and then,
+through a film of tears, but he refused recognition of it. He pictured
+himself lying sick unto death and his aunt bending over him beseeching
+one little forgiving word, but he would turn his face to the wall, and
+die with that word unsaid. Ah, how would she feel then? And he pictured
+himself brought home from the river, dead, with his curls all wet, and
+his sore heart at rest. How she would throw herself upon him, and how
+her tears would fall like rain, and her lips pray God to give her back
+her boy and she would never, never abuse him any more! But he would lie
+there cold and white and make no sign--a poor little sufferer, whose
+griefs were at an end. He so worked upon his feelings with the pathos
+of these dreams, that he had to keep swallowing, he was so like to
+choke; and his eyes swam in a blur of water, which overflowed when he
+winked, and ran down and trickled from the end of his nose. And such a
+luxury to him was this petting of his sorrows, that he could not bear
+to have any worldly cheeriness or any grating delight intrude upon it;
+it was too sacred for such contact; and so, presently, when his cousin
+Mary danced in, all alive with the joy of seeing home again after an
+age-long visit of one week to the country, he got up and moved in
+clouds and darkness out at one door as she brought song and sunshine in
+at the other.
+
+He wandered far from the accustomed haunts of boys, and sought
+desolate places that were in harmony with his spirit. A log raft in the
+river invited him, and he seated himself on its outer edge and
+contemplated the dreary vastness of the stream, wishing, the while,
+that he could only be drowned, all at once and unconsciously, without
+undergoing the uncomfortable routine devised by nature. Then he thought
+of his flower. He got it out, rumpled and wilted, and it mightily
+increased his dismal felicity. He wondered if she would pity him if she
+knew? Would she cry, and wish that she had a right to put her arms
+around his neck and comfort him? Or would she turn coldly away like all
+the hollow world? This picture brought such an agony of pleasurable
+suffering that he worked it over and over again in his mind and set it
+up in new and varied lights, till he wore it threadbare. At last he
+rose up sighing and departed in the darkness.
+
+About half-past nine or ten o'clock he came along the deserted street
+to where the Adored Unknown lived; he paused a moment; no sound fell
+upon his listening ear; a candle was casting a dull glow upon the
+curtain of a second-story window. Was the sacred presence there? He
+climbed the fence, threaded his stealthy way through the plants, till
+he stood under that window; he looked up at it long, and with emotion;
+then he laid him down on the ground under it, disposing himself upon
+his back, with his hands clasped upon his breast and holding his poor
+wilted flower. And thus he would die--out in the cold world, with no
+shelter over his homeless head, no friendly hand to wipe the
+death-damps from his brow, no loving face to bend pityingly over him
+when the great agony came. And thus SHE would see him when she looked
+out upon the glad morning, and oh! would she drop one little tear upon
+his poor, lifeless form, would she heave one little sigh to see a bright
+young life so rudely blighted, so untimely cut down?
+
+The window went up, a maid-servant's discordant voice profaned the
+holy calm, and a deluge of water drenched the prone martyr's remains!
+
+The strangling hero sprang up with a relieving snort. There was a whiz
+as of a missile in the air, mingled with the murmur of a curse, a sound
+as of shivering glass followed, and a small, vague form went over the
+fence and shot away in the gloom.
+
+Not long after, as Tom, all undressed for bed, was surveying his
+drenched garments by the light of a tallow dip, Sid woke up; but if he
+had any dim idea of making any "references to allusions," he thought
+better of it and held his peace, for there was danger in Tom's eye.
+
+Tom turned in without the added vexation of prayers, and Sid made
+mental note of the omission.
+
+
+
+CHAPTER IV
+
+THE sun rose upon a tranquil world, and beamed down upon the peaceful
+village like a benediction. Breakfast over, Aunt Polly had family
+worship: it began with a prayer built from the ground up of solid
+courses of Scriptural quotations, welded together with a thin mortar of
+originality; and from the summit of this she delivered a grim chapter
+of the Mosaic Law, as from Sinai.
+
+Then Tom girded up his loins, so to speak, and went to work to "get
+his verses." Sid had learned his lesson days before. Tom bent all his
+energies to the memorizing of five verses, and he chose part of the
+Sermon on the Mount, because he could find no verses that were shorter.
+At the end of half an hour Tom had a vague general idea of his lesson,
+but no more, for his mind was traversing the whole field of human
+thought, and his hands were busy with distracting recreations. Mary
+took his book to hear him recite, and he tried to find his way through
+the fog:
+
+"Blessed are the--a--a--"
+
+"Poor"--
+
+"Yes--poor; blessed are the poor--a--a--"
+
+"In spirit--"
+
+"In spirit; blessed are the poor in spirit, for they--they--"
+
+"THEIRS--"
+
+"For THEIRS. Blessed are the poor in spirit, for theirs is the kingdom
+of heaven. Blessed are they that mourn, for they--they--"
+
+"Sh--"
+
+"For they--a--"
+
+"S, H, A--"
+
+"For they S, H--Oh, I don't know what it is!"
+
+"SHALL!"
+
+"Oh, SHALL! for they shall--for they shall--a--a--shall mourn--a--a--
+blessed are they that shall--they that--a--they that shall mourn, for
+they shall--a--shall WHAT? Why don't you tell me, Mary?--what do you
+want to be so mean for?"
+
+"Oh, Tom, you poor thick-headed thing, I'm not teasing you. I wouldn't
+do that. You must go and learn it again. Don't you be discouraged, Tom,
+you'll manage it--and if you do, I'll give you something ever so nice.
+There, now, that's a good boy."
+
+"All right! What is it, Mary, tell me what it is."
+
+"Never you mind, Tom. You know if I say it's nice, it is nice."
+
+"You bet you that's so, Mary. All right, I'll tackle it again."
+
+And he did "tackle it again"--and under the double pressure of
+curiosity and prospective gain he did it with such spirit that he
+accomplished a shining success. Mary gave him a brand-new "Barlow"
+knife worth twelve and a half cents; and the convulsion of delight that
+swept his system shook him to his foundations. True, the knife would
+not cut anything, but it was a "sure-enough" Barlow, and there was
+inconceivable grandeur in that--though where the Western boys ever got
+the idea that such a weapon could possibly be counterfeited to its
+injury is an imposing mystery and will always remain so, perhaps. Tom
+contrived to scarify the cupboard with it, and was arranging to begin
+on the bureau, when he was called off to dress for Sunday-school.
+
+Mary gave him a tin basin of water and a piece of soap, and he went
+outside the door and set the basin on a little bench there; then he
+dipped the soap in the water and laid it down; turned up his sleeves;
+poured out the water on the ground, gently, and then entered the
+kitchen and began to wipe his face diligently on the towel behind the
+door. But Mary removed the towel and said:
+
+"Now ain't you ashamed, Tom. You mustn't be so bad. Water won't hurt
+you."
+
+Tom was a trifle disconcerted. The basin was refilled, and this time
+he stood over it a little while, gathering resolution; took in a big
+breath and began. When he entered the kitchen presently, with both eyes
+shut and groping for the towel with his hands, an honorable testimony
+of suds and water was dripping from his face. But when he emerged from
+the towel, he was not yet satisfactory, for the clean territory stopped
+short at his chin and his jaws, like a mask; below and beyond this line
+there was a dark expanse of unirrigated soil that spread downward in
+front and backward around his neck. Mary took him in hand, and when she
+was done with him he was a man and a brother, without distinction of
+color, and his saturated hair was neatly brushed, and its short curls
+wrought into a dainty and symmetrical general effect. [He privately
+smoothed out the curls, with labor and difficulty, and plastered his
+hair close down to his head; for he held curls to be effeminate, and
+his own filled his life with bitterness.] Then Mary got out a suit of
+his clothing that had been used only on Sundays during two years--they
+were simply called his "other clothes"--and so by that we know the
+size of his wardrobe. The girl "put him to rights" after he had dressed
+himself; she buttoned his neat roundabout up to his chin, turned his
+vast shirt collar down over his shoulders, brushed him off and crowned
+him with his speckled straw hat. He now looked exceedingly improved and
+uncomfortable. He was fully as uncomfortable as he looked; for there
+was a restraint about whole clothes and cleanliness that galled him. He
+hoped that Mary would forget his shoes, but the hope was blighted; she
+coated them thoroughly with tallow, as was the custom, and brought them
+out. He lost his temper and said he was always being made to do
+everything he didn't want to do. But Mary said, persuasively:
+
+"Please, Tom--that's a good boy."
+
+So he got into the shoes snarling. Mary was soon ready, and the three
+children set out for Sunday-school--a place that Tom hated with his
+whole heart; but Sid and Mary were fond of it.
+
+Sabbath-school hours were from nine to half-past ten; and then church
+service. Two of the children always remained for the sermon
+voluntarily, and the other always remained too--for stronger reasons.
+The church's high-backed, uncushioned pews would seat about three
+hundred persons; the edifice was but a small, plain affair, with a sort
+of pine board tree-box on top of it for a steeple. At the door Tom
+dropped back a step and accosted a Sunday-dressed comrade:
+
+"Say, Billy, got a yaller ticket?"
+
+"Yes."
+
+"What'll you take for her?"
+
+"What'll you give?"
+
+"Piece of lickrish and a fish-hook."
+
+"Less see 'em."
+
+Tom exhibited. They were satisfactory, and the property changed hands.
+Then Tom traded a couple of white alleys for three red tickets, and
+some small trifle or other for a couple of blue ones. He waylaid other
+boys as they came, and went on buying tickets of various colors ten or
+fifteen minutes longer. He entered the church, now, with a swarm of
+clean and noisy boys and girls, proceeded to his seat and started a
+quarrel with the first boy that came handy. The teacher, a grave,
+elderly man, interfered; then turned his back a moment and Tom pulled a
+boy's hair in the next bench, and was absorbed in his book when the boy
+turned around; stuck a pin in another boy, presently, in order to hear
+him say "Ouch!" and got a new reprimand from his teacher. Tom's whole
+class were of a pattern--restless, noisy, and troublesome. When they
+came to recite their lessons, not one of them knew his verses
+perfectly, but had to be prompted all along. However, they worried
+through, and each got his reward--in small blue tickets, each with a
+passage of Scripture on it; each blue ticket was pay for two verses of
+the recitation. Ten blue tickets equalled a red one, and could be
+exchanged for it; ten red tickets equalled a yellow one; for ten yellow
+tickets the superintendent gave a very plainly bound Bible (worth forty
+cents in those easy times) to the pupil. How many of my readers would
+have the industry and application to memorize two thousand verses, even
+for a Dore Bible? And yet Mary had acquired two Bibles in this way--it
+was the patient work of two years--and a boy of German parentage had
+won four or five. He once recited three thousand verses without
+stopping; but the strain upon his mental faculties was too great, and
+he was little better than an idiot from that day forth--a grievous
+misfortune for the school, for on great occasions, before company, the
+superintendent (as Tom expressed it) had always made this boy come out
+and "spread himself." Only the older pupils managed to keep their
+tickets and stick to their tedious work long enough to get a Bible, and
+so the delivery of one of these prizes was a rare and noteworthy
+circumstance; the successful pupil was so great and conspicuous for
+that day that on the spot every scholar's heart was fired with a fresh
+ambition that often lasted a couple of weeks. It is possible that Tom's
+mental stomach had never really hungered for one of those prizes, but
+unquestionably his entire being had for many a day longed for the glory
+and the eclat that came with it.
+
+In due course the superintendent stood up in front of the pulpit, with
+a closed hymn-book in his hand and his forefinger inserted between its
+leaves, and commanded attention. When a Sunday-school superintendent
+makes his customary little speech, a hymn-book in the hand is as
+necessary as is the inevitable sheet of music in the hand of a singer
+who stands forward on the platform and sings a solo at a concert
+--though why, is a mystery: for neither the hymn-book nor the sheet of
+music is ever referred to by the sufferer. This superintendent was a
+slim creature of thirty-five, with a sandy goatee and short sandy hair;
+he wore a stiff standing-collar whose upper edge almost reached his
+ears and whose sharp points curved forward abreast the corners of his
+mouth--a fence that compelled a straight lookout ahead, and a turning
+of the whole body when a side view was required; his chin was propped
+on a spreading cravat which was as broad and as long as a bank-note,
+and had fringed ends; his boot toes were turned sharply up, in the
+fashion of the day, like sleigh-runners--an effect patiently and
+laboriously produced by the young men by sitting with their toes
+pressed against a wall for hours together. Mr. Walters was very earnest
+of mien, and very sincere and honest at heart; and he held sacred
+things and places in such reverence, and so separated them from worldly
+matters, that unconsciously to himself his Sunday-school voice had
+acquired a peculiar intonation which was wholly absent on week-days. He
+began after this fashion:
+
+"Now, children, I want you all to sit up just as straight and pretty
+as you can and give me all your attention for a minute or two. There
+--that is it. That is the way good little boys and girls should do. I see
+one little girl who is looking out of the window--I am afraid she
+thinks I am out there somewhere--perhaps up in one of the trees making
+a speech to the little birds. [Applausive titter.] I want to tell you
+how good it makes me feel to see so many bright, clean little faces
+assembled in a place like this, learning to do right and be good." And
+so forth and so on. It is not necessary to set down the rest of the
+oration. It was of a pattern which does not vary, and so it is familiar
+to us all.
+
+The latter third of the speech was marred by the resumption of fights
+and other recreations among certain of the bad boys, and by fidgetings
+and whisperings that extended far and wide, washing even to the bases
+of isolated and incorruptible rocks like Sid and Mary. But now every
+sound ceased suddenly, with the subsidence of Mr. Walters' voice, and
+the conclusion of the speech was received with a burst of silent
+gratitude.
+
+A good part of the whispering had been occasioned by an event which
+was more or less rare--the entrance of visitors: lawyer Thatcher,
+accompanied by a very feeble and aged man; a fine, portly, middle-aged
+gentleman with iron-gray hair; and a dignified lady who was doubtless
+the latter's wife. The lady was leading a child. Tom had been restless
+and full of chafings and repinings; conscience-smitten, too--he could
+not meet Amy Lawrence's eye, he could not brook her loving gaze. But
+when he saw this small new-comer his soul was all ablaze with bliss in
+a moment. The next moment he was "showing off" with all his might
+--cuffing boys, pulling hair, making faces--in a word, using every art
+that seemed likely to fascinate a girl and win her applause. His
+exaltation had but one alloy--the memory of his humiliation in this
+angel's garden--and that record in sand was fast washing out, under
+the waves of happiness that were sweeping over it now.
+
+The visitors were given the highest seat of honor, and as soon as Mr.
+Walters' speech was finished, he introduced them to the school. The
+middle-aged man turned out to be a prodigious personage--no less a one
+than the county judge--altogether the most august creation these
+children had ever looked upon--and they wondered what kind of material
+he was made of--and they half wanted to hear him roar, and were half
+afraid he might, too. He was from Constantinople, twelve miles away--so
+he had travelled, and seen the world--these very eyes had looked upon
+the county court-house--which was said to have a tin roof. The awe
+which these reflections inspired was attested by the impressive silence
+and the ranks of staring eyes. This was the great Judge Thatcher,
+brother of their own lawyer. Jeff Thatcher immediately went forward, to
+be familiar with the great man and be envied by the school. It would
+have been music to his soul to hear the whisperings:
+
+"Look at him, Jim! He's a going up there. Say--look! he's a going to
+shake hands with him--he IS shaking hands with him! By jings, don't you
+wish you was Jeff?"
+
+Mr. Walters fell to "showing off," with all sorts of official
+bustlings and activities, giving orders, delivering judgments,
+discharging directions here, there, everywhere that he could find a
+target. The librarian "showed off"--running hither and thither with his
+arms full of books and making a deal of the splutter and fuss that
+insect authority delights in. The young lady teachers "showed off"
+--bending sweetly over pupils that were lately being boxed, lifting
+pretty warning fingers at bad little boys and patting good ones
+lovingly. The young gentlemen teachers "showed off" with small
+scoldings and other little displays of authority and fine attention to
+discipline--and most of the teachers, of both sexes, found business up
+at the library, by the pulpit; and it was business that frequently had
+to be done over again two or three times (with much seeming vexation).
+The little girls "showed off" in various ways, and the little boys
+"showed off" with such diligence that the air was thick with paper wads
+and the murmur of scufflings. And above it all the great man sat and
+beamed a majestic judicial smile upon all the house, and warmed himself
+in the sun of his own grandeur--for he was "showing off," too.
+
+There was only one thing wanting to make Mr. Walters' ecstasy
+complete, and that was a chance to deliver a Bible-prize and exhibit a
+prodigy. Several pupils had a few yellow tickets, but none had enough
+--he had been around among the star pupils inquiring. He would have given
+worlds, now, to have that German lad back again with a sound mind.
+
+And now at this moment, when hope was dead, Tom Sawyer came forward
+with nine yellow tickets, nine red tickets, and ten blue ones, and
+demanded a Bible. This was a thunderbolt out of a clear sky. Walters
+was not expecting an application from this source for the next ten
+years. But there was no getting around it--here were the certified
+checks, and they were good for their face. Tom was therefore elevated
+to a place with the Judge and the other elect, and the great news was
+announced from headquarters. It was the most stunning surprise of the
+decade, and so profound was the sensation that it lifted the new hero
+up to the judicial one's altitude, and the school had two marvels to
+gaze upon in place of one. The boys were all eaten up with envy--but
+those that suffered the bitterest pangs were those who perceived too
+late that they themselves had contributed to this hated splendor by
+trading tickets to Tom for the wealth he had amassed in selling
+whitewashing privileges. These despised themselves, as being the dupes
+of a wily fraud, a guileful snake in the grass.
+
+The prize was delivered to Tom with as much effusion as the
+superintendent could pump up under the circumstances; but it lacked
+somewhat of the true gush, for the poor fellow's instinct taught him
+that there was a mystery here that could not well bear the light,
+perhaps; it was simply preposterous that this boy had warehoused two
+thousand sheaves of Scriptural wisdom on his premises--a dozen would
+strain his capacity, without a doubt.
+
+Amy Lawrence was proud and glad, and she tried to make Tom see it in
+her face--but he wouldn't look. She wondered; then she was just a grain
+troubled; next a dim suspicion came and went--came again; she watched;
+a furtive glance told her worlds--and then her heart broke, and she was
+jealous, and angry, and the tears came and she hated everybody. Tom
+most of all (she thought).
+
+Tom was introduced to the Judge; but his tongue was tied, his breath
+would hardly come, his heart quaked--partly because of the awful
+greatness of the man, but mainly because he was her parent. He would
+have liked to fall down and worship him, if it were in the dark. The
+Judge put his hand on Tom's head and called him a fine little man, and
+asked him what his name was. The boy stammered, gasped, and got it out:
+
+"Tom."
+
+"Oh, no, not Tom--it is--"
+
+"Thomas."
+
+"Ah, that's it. I thought there was more to it, maybe. That's very
+well. But you've another one I daresay, and you'll tell it to me, won't
+you?"
+
+"Tell the gentleman your other name, Thomas," said Walters, "and say
+sir. You mustn't forget your manners."
+
+"Thomas Sawyer--sir."
+
+"That's it! That's a good boy. Fine boy. Fine, manly little fellow.
+Two thousand verses is a great many--very, very great many. And you
+never can be sorry for the trouble you took to learn them; for
+knowledge is worth more than anything there is in the world; it's what
+makes great men and good men; you'll be a great man and a good man
+yourself, some day, Thomas, and then you'll look back and say, It's all
+owing to the precious Sunday-school privileges of my boyhood--it's all
+owing to my dear teachers that taught me to learn--it's all owing to
+the good superintendent, who encouraged me, and watched over me, and
+gave me a beautiful Bible--a splendid elegant Bible--to keep and have
+it all for my own, always--it's all owing to right bringing up! That is
+what you will say, Thomas--and you wouldn't take any money for those
+two thousand verses--no indeed you wouldn't. And now you wouldn't mind
+telling me and this lady some of the things you've learned--no, I know
+you wouldn't--for we are proud of little boys that learn. Now, no
+doubt you know the names of all the twelve disciples. Won't you tell us
+the names of the first two that were appointed?"
+
+Tom was tugging at a button-hole and looking sheepish. He blushed,
+now, and his eyes fell. Mr. Walters' heart sank within him. He said to
+himself, it is not possible that the boy can answer the simplest
+question--why DID the Judge ask him? Yet he felt obliged to speak up
+and say:
+
+"Answer the gentleman, Thomas--don't be afraid."
+
+Tom still hung fire.
+
+"Now I know you'll tell me," said the lady. "The names of the first
+two disciples were--"
+
+"DAVID AND GOLIAH!"
+
+Let us draw the curtain of charity over the rest of the scene.
+
+
+
+CHAPTER V
+
+ABOUT half-past ten the cracked bell of the small church began to
+ring, and presently the people began to gather for the morning sermon.
+The Sunday-school children distributed themselves about the house and
+occupied pews with their parents, so as to be under supervision. Aunt
+Polly came, and Tom and Sid and Mary sat with her--Tom being placed
+next the aisle, in order that he might be as far away from the open
+window and the seductive outside summer scenes as possible. The crowd
+filed up the aisles: the aged and needy postmaster, who had seen better
+days; the mayor and his wife--for they had a mayor there, among other
+unnecessaries; the justice of the peace; the widow Douglass, fair,
+smart, and forty, a generous, good-hearted soul and well-to-do, her
+hill mansion the only palace in the town, and the most hospitable and
+much the most lavish in the matter of festivities that St. Petersburg
+could boast; the bent and venerable Major and Mrs. Ward; lawyer
+Riverson, the new notable from a distance; next the belle of the
+village, followed by a troop of lawn-clad and ribbon-decked young
+heart-breakers; then all the young clerks in town in a body--for they
+had stood in the vestibule sucking their cane-heads, a circling wall of
+oiled and simpering admirers, till the last girl had run their gantlet;
+and last of all came the Model Boy, Willie Mufferson, taking as heedful
+care of his mother as if she were cut glass. He always brought his
+mother to church, and was the pride of all the matrons. The boys all
+hated him, he was so good. And besides, he had been "thrown up to them"
+so much. His white handkerchief was hanging out of his pocket behind, as
+usual on Sundays--accidentally. Tom had no handkerchief, and he looked
+upon boys who had as snobs.
+
+The congregation being fully assembled, now, the bell rang once more,
+to warn laggards and stragglers, and then a solemn hush fell upon the
+church which was only broken by the tittering and whispering of the
+choir in the gallery. The choir always tittered and whispered all
+through service. There was once a church choir that was not ill-bred,
+but I have forgotten where it was, now. It was a great many years ago,
+and I can scarcely remember anything about it, but I think it was in
+some foreign country.
+
+The minister gave out the hymn, and read it through with a relish, in
+a peculiar style which was much admired in that part of the country.
+His voice began on a medium key and climbed steadily up till it reached
+a certain point, where it bore with strong emphasis upon the topmost
+word and then plunged down as if from a spring-board:
+
+  Shall I be car-ri-ed toe the skies, on flow'ry BEDS of ease,
+
+  Whilst others fight to win the prize, and sail thro' BLOODY seas?
+
+He was regarded as a wonderful reader. At church "sociables" he was
+always called upon to read poetry; and when he was through, the ladies
+would lift up their hands and let them fall helplessly in their laps,
+and "wall" their eyes, and shake their heads, as much as to say, "Words
+cannot express it; it is too beautiful, TOO beautiful for this mortal
+earth."
+
+After the hymn had been sung, the Rev. Mr. Sprague turned himself into
+a bulletin-board, and read off "notices" of meetings and societies and
+things till it seemed that the list would stretch out to the crack of
+doom--a queer custom which is still kept up in America, even in cities,
+away here in this age of abundant newspapers. Often, the less there is
+to justify a traditional custom, the harder it is to get rid of it.
+
+And now the minister prayed. A good, generous prayer it was, and went
+into details: it pleaded for the church, and the little children of the
+church; for the other churches of the village; for the village itself;
+for the county; for the State; for the State officers; for the United
+States; for the churches of the United States; for Congress; for the
+President; for the officers of the Government; for poor sailors, tossed
+by stormy seas; for the oppressed millions groaning under the heel of
+European monarchies and Oriental despotisms; for such as have the light
+and the good tidings, and yet have not eyes to see nor ears to hear
+withal; for the heathen in the far islands of the sea; and closed with
+a supplication that the words he was about to speak might find grace
+and favor, and be as seed sown in fertile ground, yielding in time a
+grateful harvest of good. Amen.
+
+There was a rustling of dresses, and the standing congregation sat
+down. The boy whose history this book relates did not enjoy the prayer,
+he only endured it--if he even did that much. He was restive all
+through it; he kept tally of the details of the prayer, unconsciously
+--for he was not listening, but he knew the ground of old, and the
+clergyman's regular route over it--and when a little trifle of new
+matter was interlarded, his ear detected it and his whole nature
+resented it; he considered additions unfair, and scoundrelly. In the
+midst of the prayer a fly had lit on the back of the pew in front of
+him and tortured his spirit by calmly rubbing its hands together,
+embracing its head with its arms, and polishing it so vigorously that
+it seemed to almost part company with the body, and the slender thread
+of a neck was exposed to view; scraping its wings with its hind legs
+and smoothing them to its body as if they had been coat-tails; going
+through its whole toilet as tranquilly as if it knew it was perfectly
+safe. As indeed it was; for as sorely as Tom's hands itched to grab for
+it they did not dare--he believed his soul would be instantly destroyed
+if he did such a thing while the prayer was going on. But with the
+closing sentence his hand began to curve and steal forward; and the
+instant the "Amen" was out the fly was a prisoner of war. His aunt
+detected the act and made him let it go.
+
+The minister gave out his text and droned along monotonously through
+an argument that was so prosy that many a head by and by began to nod
+--and yet it was an argument that dealt in limitless fire and brimstone
+and thinned the predestined elect down to a company so small as to be
+hardly worth the saving. Tom counted the pages of the sermon; after
+church he always knew how many pages there had been, but he seldom knew
+anything else about the discourse. However, this time he was really
+interested for a little while. The minister made a grand and moving
+picture of the assembling together of the world's hosts at the
+millennium when the lion and the lamb should lie down together and a
+little child should lead them. But the pathos, the lesson, the moral of
+the great spectacle were lost upon the boy; he only thought of the
+conspicuousness of the principal character before the on-looking
+nations; his face lit with the thought, and he said to himself that he
+wished he could be that child, if it was a tame lion.
+
+Now he lapsed into suffering again, as the dry argument was resumed.
+Presently he bethought him of a treasure he had and got it out. It was
+a large black beetle with formidable jaws--a "pinchbug," he called it.
+It was in a percussion-cap box. The first thing the beetle did was to
+take him by the finger. A natural fillip followed, the beetle went
+floundering into the aisle and lit on its back, and the hurt finger
+went into the boy's mouth. The beetle lay there working its helpless
+legs, unable to turn over. Tom eyed it, and longed for it; but it was
+safe out of his reach. Other people uninterested in the sermon found
+relief in the beetle, and they eyed it too. Presently a vagrant poodle
+dog came idling along, sad at heart, lazy with the summer softness and
+the quiet, weary of captivity, sighing for change. He spied the beetle;
+the drooping tail lifted and wagged. He surveyed the prize; walked
+around it; smelt at it from a safe distance; walked around it again;
+grew bolder, and took a closer smell; then lifted his lip and made a
+gingerly snatch at it, just missing it; made another, and another;
+began to enjoy the diversion; subsided to his stomach with the beetle
+between his paws, and continued his experiments; grew weary at last,
+and then indifferent and absent-minded. His head nodded, and little by
+little his chin descended and touched the enemy, who seized it. There
+was a sharp yelp, a flirt of the poodle's head, and the beetle fell a
+couple of yards away, and lit on its back once more. The neighboring
+spectators shook with a gentle inward joy, several faces went behind
+fans and handkerchiefs, and Tom was entirely happy. The dog looked
+foolish, and probably felt so; but there was resentment in his heart,
+too, and a craving for revenge. So he went to the beetle and began a
+wary attack on it again; jumping at it from every point of a circle,
+lighting with his fore-paws within an inch of the creature, making even
+closer snatches at it with his teeth, and jerking his head till his
+ears flapped again. But he grew tired once more, after a while; tried
+to amuse himself with a fly but found no relief; followed an ant
+around, with his nose close to the floor, and quickly wearied of that;
+yawned, sighed, forgot the beetle entirely, and sat down on it. Then
+there was a wild yelp of agony and the poodle went sailing up the
+aisle; the yelps continued, and so did the dog; he crossed the house in
+front of the altar; he flew down the other aisle; he crossed before the
+doors; he clamored up the home-stretch; his anguish grew with his
+progress, till presently he was but a woolly comet moving in its orbit
+with the gleam and the speed of light. At last the frantic sufferer
+sheered from its course, and sprang into its master's lap; he flung it
+out of the window, and the voice of distress quickly thinned away and
+died in the distance.
+
+By this time the whole church was red-faced and suffocating with
+suppressed laughter, and the sermon had come to a dead standstill. The
+discourse was resumed presently, but it went lame and halting, all
+possibility of impressiveness being at an end; for even the gravest
+sentiments were constantly being received with a smothered burst of
+unholy mirth, under cover of some remote pew-back, as if the poor
+parson had said a rarely facetious thing. It was a genuine relief to
+the whole congregation when the ordeal was over and the benediction
+pronounced.
+
+Tom Sawyer went home quite cheerful, thinking to himself that there
+was some satisfaction about divine service when there was a bit of
+variety in it. He had but one marring thought; he was willing that the
+dog should play with his pinchbug, but he did not think it was upright
+in him to carry it off.
+
+
+
+CHAPTER VI
+
+MONDAY morning found Tom Sawyer miserable. Monday morning always found
+him so--because it began another week's slow suffering in school. He
+generally began that day with wishing he had had no intervening
+holiday, it made the going into captivity and fetters again so much
+more odious.
+
+Tom lay thinking. Presently it occurred to him that he wished he was
+sick; then he could stay home from school. Here was a vague
+possibility. He canvassed his system. No ailment was found, and he
+investigated again. This time he thought he could detect colicky
+symptoms, and he began to encourage them with considerable hope. But
+they soon grew feeble, and presently died wholly away. He reflected
+further. Suddenly he discovered something. One of his upper front teeth
+was loose. This was lucky; he was about to begin to groan, as a
+"starter," as he called it, when it occurred to him that if he came
+into court with that argument, his aunt would pull it out, and that
+would hurt. So he thought he would hold the tooth in reserve for the
+present, and seek further. Nothing offered for some little time, and
+then he remembered hearing the doctor tell about a certain thing that
+laid up a patient for two or three weeks and threatened to make him
+lose a finger. So the boy eagerly drew his sore toe from under the
+sheet and held it up for inspection. But now he did not know the
+necessary symptoms. However, it seemed well worth while to chance it,
+so he fell to groaning with considerable spirit.
+
+But Sid slept on unconscious.
+
+Tom groaned louder, and fancied that he began to feel pain in the toe.
+
+No result from Sid.
+
+Tom was panting with his exertions by this time. He took a rest and
+then swelled himself up and fetched a succession of admirable groans.
+
+Sid snored on.
+
+Tom was aggravated. He said, "Sid, Sid!" and shook him. This course
+worked well, and Tom began to groan again. Sid yawned, stretched, then
+brought himself up on his elbow with a snort, and began to stare at
+Tom. Tom went on groaning. Sid said:
+
+"Tom! Say, Tom!" [No response.] "Here, Tom! TOM! What is the matter,
+Tom?" And he shook him and looked in his face anxiously.
+
+Tom moaned out:
+
+"Oh, don't, Sid. Don't joggle me."
+
+"Why, what's the matter, Tom? I must call auntie."
+
+"No--never mind. It'll be over by and by, maybe. Don't call anybody."
+
+"But I must! DON'T groan so, Tom, it's awful. How long you been this
+way?"
+
+"Hours. Ouch! Oh, don't stir so, Sid, you'll kill me."
+
+"Tom, why didn't you wake me sooner? Oh, Tom, DON'T! It makes my
+flesh crawl to hear you. Tom, what is the matter?"
+
+"I forgive you everything, Sid. [Groan.] Everything you've ever done
+to me. When I'm gone--"
+
+"Oh, Tom, you ain't dying, are you? Don't, Tom--oh, don't. Maybe--"
+
+"I forgive everybody, Sid. [Groan.] Tell 'em so, Sid. And Sid, you
+give my window-sash and my cat with one eye to that new girl that's
+come to town, and tell her--"
+
+But Sid had snatched his clothes and gone. Tom was suffering in
+reality, now, so handsomely was his imagination working, and so his
+groans had gathered quite a genuine tone.
+
+Sid flew down-stairs and said:
+
+"Oh, Aunt Polly, come! Tom's dying!"
+
+"Dying!"
+
+"Yes'm. Don't wait--come quick!"
+
+"Rubbage! I don't believe it!"
+
+But she fled up-stairs, nevertheless, with Sid and Mary at her heels.
+And her face grew white, too, and her lip trembled. When she reached
+the bedside she gasped out:
+
+"You, Tom! Tom, what's the matter with you?"
+
+"Oh, auntie, I'm--"
+
+"What's the matter with you--what is the matter with you, child?"
+
+"Oh, auntie, my sore toe's mortified!"
+
+The old lady sank down into a chair and laughed a little, then cried a
+little, then did both together. This restored her and she said:
+
+"Tom, what a turn you did give me. Now you shut up that nonsense and
+climb out of this."
+
+The groans ceased and the pain vanished from the toe. The boy felt a
+little foolish, and he said:
+
+"Aunt Polly, it SEEMED mortified, and it hurt so I never minded my
+tooth at all."
+
+"Your tooth, indeed! What's the matter with your tooth?"
+
+"One of them's loose, and it aches perfectly awful."
+
+"There, there, now, don't begin that groaning again. Open your mouth.
+Well--your tooth IS loose, but you're not going to die about that.
+Mary, get me a silk thread, and a chunk of fire out of the kitchen."
+
+Tom said:
+
+"Oh, please, auntie, don't pull it out. It don't hurt any more. I wish
+I may never stir if it does. Please don't, auntie. I don't want to stay
+home from school."
+
+"Oh, you don't, don't you? So all this row was because you thought
+you'd get to stay home from school and go a-fishing? Tom, Tom, I love
+you so, and you seem to try every way you can to break my old heart
+with your outrageousness." By this time the dental instruments were
+ready. The old lady made one end of the silk thread fast to Tom's tooth
+with a loop and tied the other to the bedpost. Then she seized the
+chunk of fire and suddenly thrust it almost into the boy's face. The
+tooth hung dangling by the bedpost, now.
+
+But all trials bring their compensations. As Tom wended to school
+after breakfast, he was the envy of every boy he met because the gap in
+his upper row of teeth enabled him to expectorate in a new and
+admirable way. He gathered quite a following of lads interested in the
+exhibition; and one that had cut his finger and had been a centre of
+fascination and homage up to this time, now found himself suddenly
+without an adherent, and shorn of his glory. His heart was heavy, and
+he said with a disdain which he did not feel that it wasn't anything to
+spit like Tom Sawyer; but another boy said, "Sour grapes!" and he
+wandered away a dismantled hero.
+
+Shortly Tom came upon the juvenile pariah of the village, Huckleberry
+Finn, son of the town drunkard. Huckleberry was cordially hated and
+dreaded by all the mothers of the town, because he was idle and lawless
+and vulgar and bad--and because all their children admired him so, and
+delighted in his forbidden society, and wished they dared to be like
+him. Tom was like the rest of the respectable boys, in that he envied
+Huckleberry his gaudy outcast condition, and was under strict orders
+not to play with him. So he played with him every time he got a chance.
+Huckleberry was always dressed in the cast-off clothes of full-grown
+men, and they were in perennial bloom and fluttering with rags. His hat
+was a vast ruin with a wide crescent lopped out of its brim; his coat,
+when he wore one, hung nearly to his heels and had the rearward buttons
+far down the back; but one suspender supported his trousers; the seat
+of the trousers bagged low and contained nothing, the fringed legs
+dragged in the dirt when not rolled up.
+
+Huckleberry came and went, at his own free will. He slept on doorsteps
+in fine weather and in empty hogsheads in wet; he did not have to go to
+school or to church, or call any being master or obey anybody; he could
+go fishing or swimming when and where he chose, and stay as long as it
+suited him; nobody forbade him to fight; he could sit up as late as he
+pleased; he was always the first boy that went barefoot in the spring
+and the last to resume leather in the fall; he never had to wash, nor
+put on clean clothes; he could swear wonderfully. In a word, everything
+that goes to make life precious that boy had. So thought every
+harassed, hampered, respectable boy in St. Petersburg.
+
+Tom hailed the romantic outcast:
+
+"Hello, Huckleberry!"
+
+"Hello yourself, and see how you like it."
+
+"What's that you got?"
+
+"Dead cat."
+
+"Lemme see him, Huck. My, he's pretty stiff. Where'd you get him?"
+
+"Bought him off'n a boy."
+
+"What did you give?"
+
+"I give a blue ticket and a bladder that I got at the slaughter-house."
+
+"Where'd you get the blue ticket?"
+
+"Bought it off'n Ben Rogers two weeks ago for a hoop-stick."
+
+"Say--what is dead cats good for, Huck?"
+
+"Good for? Cure warts with."
+
+"No! Is that so? I know something that's better."
+
+"I bet you don't. What is it?"
+
+"Why, spunk-water."
+
+"Spunk-water! I wouldn't give a dern for spunk-water."
+
+"You wouldn't, wouldn't you? D'you ever try it?"
+
+"No, I hain't. But Bob Tanner did."
+
+"Who told you so!"
+
+"Why, he told Jeff Thatcher, and Jeff told Johnny Baker, and Johnny
+told Jim Hollis, and Jim told Ben Rogers, and Ben told a nigger, and
+the nigger told me. There now!"
+
+"Well, what of it? They'll all lie. Leastways all but the nigger. I
+don't know HIM. But I never see a nigger that WOULDN'T lie. Shucks! Now
+you tell me how Bob Tanner done it, Huck."
+
+"Why, he took and dipped his hand in a rotten stump where the
+rain-water was."
+
+"In the daytime?"
+
+"Certainly."
+
+"With his face to the stump?"
+
+"Yes. Least I reckon so."
+
+"Did he say anything?"
+
+"I don't reckon he did. I don't know."
+
+"Aha! Talk about trying to cure warts with spunk-water such a blame
+fool way as that! Why, that ain't a-going to do any good. You got to go
+all by yourself, to the middle of the woods, where you know there's a
+spunk-water stump, and just as it's midnight you back up against the
+stump and jam your hand in and say:
+
+  'Barley-corn, barley-corn, injun-meal shorts,
+   Spunk-water, spunk-water, swaller these warts,'
+
+and then walk away quick, eleven steps, with your eyes shut, and then
+turn around three times and walk home without speaking to anybody.
+Because if you speak the charm's busted."
+
+"Well, that sounds like a good way; but that ain't the way Bob Tanner
+done."
+
+"No, sir, you can bet he didn't, becuz he's the wartiest boy in this
+town; and he wouldn't have a wart on him if he'd knowed how to work
+spunk-water. I've took off thousands of warts off of my hands that way,
+Huck. I play with frogs so much that I've always got considerable many
+warts. Sometimes I take 'em off with a bean."
+
+"Yes, bean's good. I've done that."
+
+"Have you? What's your way?"
+
+"You take and split the bean, and cut the wart so as to get some
+blood, and then you put the blood on one piece of the bean and take and
+dig a hole and bury it 'bout midnight at the crossroads in the dark of
+the moon, and then you burn up the rest of the bean. You see that piece
+that's got the blood on it will keep drawing and drawing, trying to
+fetch the other piece to it, and so that helps the blood to draw the
+wart, and pretty soon off she comes."
+
+"Yes, that's it, Huck--that's it; though when you're burying it if you
+say 'Down bean; off wart; come no more to bother me!' it's better.
+That's the way Joe Harper does, and he's been nearly to Coonville and
+most everywheres. But say--how do you cure 'em with dead cats?"
+
+"Why, you take your cat and go and get in the graveyard 'long about
+midnight when somebody that was wicked has been buried; and when it's
+midnight a devil will come, or maybe two or three, but you can't see
+'em, you can only hear something like the wind, or maybe hear 'em talk;
+and when they're taking that feller away, you heave your cat after 'em
+and say, 'Devil follow corpse, cat follow devil, warts follow cat, I'm
+done with ye!' That'll fetch ANY wart."
+
+"Sounds right. D'you ever try it, Huck?"
+
+"No, but old Mother Hopkins told me."
+
+"Well, I reckon it's so, then. Becuz they say she's a witch."
+
+"Say! Why, Tom, I KNOW she is. She witched pap. Pap says so his own
+self. He come along one day, and he see she was a-witching him, so he
+took up a rock, and if she hadn't dodged, he'd a got her. Well, that
+very night he rolled off'n a shed wher' he was a layin drunk, and broke
+his arm."
+
+"Why, that's awful. How did he know she was a-witching him?"
+
+"Lord, pap can tell, easy. Pap says when they keep looking at you
+right stiddy, they're a-witching you. Specially if they mumble. Becuz
+when they mumble they're saying the Lord's Prayer backards."
+
+"Say, Hucky, when you going to try the cat?"
+
+"To-night. I reckon they'll come after old Hoss Williams to-night."
+
+"But they buried him Saturday. Didn't they get him Saturday night?"
+
+"Why, how you talk! How could their charms work till midnight?--and
+THEN it's Sunday. Devils don't slosh around much of a Sunday, I don't
+reckon."
+
+"I never thought of that. That's so. Lemme go with you?"
+
+"Of course--if you ain't afeard."
+
+"Afeard! 'Tain't likely. Will you meow?"
+
+"Yes--and you meow back, if you get a chance. Last time, you kep' me
+a-meowing around till old Hays went to throwing rocks at me and says
+'Dern that cat!' and so I hove a brick through his window--but don't
+you tell."
+
+"I won't. I couldn't meow that night, becuz auntie was watching me,
+but I'll meow this time. Say--what's that?"
+
+"Nothing but a tick."
+
+"Where'd you get him?"
+
+"Out in the woods."
+
+"What'll you take for him?"
+
+"I don't know. I don't want to sell him."
+
+"All right. It's a mighty small tick, anyway."
+
+"Oh, anybody can run a tick down that don't belong to them. I'm
+satisfied with it. It's a good enough tick for me."
+
+"Sho, there's ticks a plenty. I could have a thousand of 'em if I
+wanted to."
+
+"Well, why don't you? Becuz you know mighty well you can't. This is a
+pretty early tick, I reckon. It's the first one I've seen this year."
+
+"Say, Huck--I'll give you my tooth for him."
+
+"Less see it."
+
+Tom got out a bit of paper and carefully unrolled it. Huckleberry
+viewed it wistfully. The temptation was very strong. At last he said:
+
+"Is it genuwyne?"
+
+Tom lifted his lip and showed the vacancy.
+
+"Well, all right," said Huckleberry, "it's a trade."
+
+Tom enclosed the tick in the percussion-cap box that had lately been
+the pinchbug's prison, and the boys separated, each feeling wealthier
+than before.
+
+When Tom reached the little isolated frame schoolhouse, he strode in
+briskly, with the manner of one who had come with all honest speed.
+He hung his hat on a peg and flung himself into his seat with
+business-like alacrity. The master, throned on high in his great
+splint-bottom arm-chair, was dozing, lulled by the drowsy hum of study.
+The interruption roused him.
+
+"Thomas Sawyer!"
+
+Tom knew that when his name was pronounced in full, it meant trouble.
+
+"Sir!"
+
+"Come up here. Now, sir, why are you late again, as usual?"
+
+Tom was about to take refuge in a lie, when he saw two long tails of
+yellow hair hanging down a back that he recognized by the electric
+sympathy of love; and by that form was THE ONLY VACANT PLACE on the
+girls' side of the schoolhouse. He instantly said:
+
+"I STOPPED TO TALK WITH HUCKLEBERRY FINN!"
+
+The master's pulse stood still, and he stared helplessly. The buzz of
+study ceased. The pupils wondered if this foolhardy boy had lost his
+mind. The master said:
+
+"You--you did what?"
+
+"Stopped to talk with Huckleberry Finn."
+
+There was no mistaking the words.
+
+"Thomas Sawyer, this is the most astounding confession I have ever
+listened to. No mere ferule will answer for this offence. Take off your
+jacket."
+
+The master's arm performed until it was tired and the stock of
+switches notably diminished. Then the order followed:
+
+"Now, sir, go and sit with the girls! And let this be a warning to you."
+
+The titter that rippled around the room appeared to abash the boy, but
+in reality that result was caused rather more by his worshipful awe of
+his unknown idol and the dread pleasure that lay in his high good
+fortune. He sat down upon the end of the pine bench and the girl
+hitched herself away from him with a toss of her head. Nudges and winks
+and whispers traversed the room, but Tom sat still, with his arms upon
+the long, low desk before him, and seemed to study his book.
+
+By and by attention ceased from him, and the accustomed school murmur
+rose upon the dull air once more. Presently the boy began to steal
+furtive glances at the girl. She observed it, "made a mouth" at him and
+gave him the back of her head for the space of a minute. When she
+cautiously faced around again, a peach lay before her. She thrust it
+away. Tom gently put it back. She thrust it away again, but with less
+animosity. Tom patiently returned it to its place. Then she let it
+remain. Tom scrawled on his slate, "Please take it--I got more." The
+girl glanced at the words, but made no sign. Now the boy began to draw
+something on the slate, hiding his work with his left hand. For a time
+the girl refused to notice; but her human curiosity presently began to
+manifest itself by hardly perceptible signs. The boy worked on,
+apparently unconscious. The girl made a sort of noncommittal attempt to
+see, but the boy did not betray that he was aware of it. At last she
+gave in and hesitatingly whispered:
+
+"Let me see it."
+
+Tom partly uncovered a dismal caricature of a house with two gable
+ends to it and a corkscrew of smoke issuing from the chimney. Then the
+girl's interest began to fasten itself upon the work and she forgot
+everything else. When it was finished, she gazed a moment, then
+whispered:
+
+"It's nice--make a man."
+
+The artist erected a man in the front yard, that resembled a derrick.
+He could have stepped over the house; but the girl was not
+hypercritical; she was satisfied with the monster, and whispered:
+
+"It's a beautiful man--now make me coming along."
+
+Tom drew an hour-glass with a full moon and straw limbs to it and
+armed the spreading fingers with a portentous fan. The girl said:
+
+"It's ever so nice--I wish I could draw."
+
+"It's easy," whispered Tom, "I'll learn you."
+
+"Oh, will you? When?"
+
+"At noon. Do you go home to dinner?"
+
+"I'll stay if you will."
+
+"Good--that's a whack. What's your name?"
+
+"Becky Thatcher. What's yours? Oh, I know. It's Thomas Sawyer."
+
+"That's the name they lick me by. I'm Tom when I'm good. You call me
+Tom, will you?"
+
+"Yes."
+
+Now Tom began to scrawl something on the slate, hiding the words from
+the girl. But she was not backward this time. She begged to see. Tom
+said:
+
+"Oh, it ain't anything."
+
+"Yes it is."
+
+"No it ain't. You don't want to see."
+
+"Yes I do, indeed I do. Please let me."
+
+"You'll tell."
+
+"No I won't--deed and deed and double deed won't."
+
+"You won't tell anybody at all? Ever, as long as you live?"
+
+"No, I won't ever tell ANYbody. Now let me."
+
+"Oh, YOU don't want to see!"
+
+"Now that you treat me so, I WILL see." And she put her small hand
+upon his and a little scuffle ensued, Tom pretending to resist in
+earnest but letting his hand slip by degrees till these words were
+revealed: "I LOVE YOU."
+
+"Oh, you bad thing!" And she hit his hand a smart rap, but reddened
+and looked pleased, nevertheless.
+
+Just at this juncture the boy felt a slow, fateful grip closing on his
+ear, and a steady lifting impulse. In that wise he was borne across the
+house and deposited in his own seat, under a peppering fire of giggles
+from the whole school. Then the master stood over him during a few
+awful moments, and finally moved away to his throne without saying a
+word. But although Tom's ear tingled, his heart was jubilant.
+
+As the school quieted down Tom made an honest effort to study, but the
+turmoil within him was too great. In turn he took his place in the
+reading class and made a botch of it; then in the geography class and
+turned lakes into mountains, mountains into rivers, and rivers into
+continents, till chaos was come again; then in the spelling class, and
+got "turned down," by a succession of mere baby words, till he brought
+up at the foot and yielded up the pewter medal which he had worn with
+ostentation for months.
+
+
+
+CHAPTER VII
+
+THE harder Tom tried to fasten his mind on his book, the more his
+ideas wandered. So at last, with a sigh and a yawn, he gave it up. It
+seemed to him that the noon recess would never come. The air was
+utterly dead. There was not a breath stirring. It was the sleepiest of
+sleepy days. The drowsing murmur of the five and twenty studying
+scholars soothed the soul like the spell that is in the murmur of bees.
+Away off in the flaming sunshine, Cardiff Hill lifted its soft green
+sides through a shimmering veil of heat, tinted with the purple of
+distance; a few birds floated on lazy wing high in the air; no other
+living thing was visible but some cows, and they were asleep. Tom's
+heart ached to be free, or else to have something of interest to do to
+pass the dreary time. His hand wandered into his pocket and his face
+lit up with a glow of gratitude that was prayer, though he did not know
+it. Then furtively the percussion-cap box came out. He released the
+tick and put him on the long flat desk. The creature probably glowed
+with a gratitude that amounted to prayer, too, at this moment, but it
+was premature: for when he started thankfully to travel off, Tom turned
+him aside with a pin and made him take a new direction.
+
+Tom's bosom friend sat next him, suffering just as Tom had been, and
+now he was deeply and gratefully interested in this entertainment in an
+instant. This bosom friend was Joe Harper. The two boys were sworn
+friends all the week, and embattled enemies on Saturdays. Joe took a
+pin out of his lapel and began to assist in exercising the prisoner.
+The sport grew in interest momently. Soon Tom said that they were
+interfering with each other, and neither getting the fullest benefit of
+the tick. So he put Joe's slate on the desk and drew a line down the
+middle of it from top to bottom.
+
+"Now," said he, "as long as he is on your side you can stir him up and
+I'll let him alone; but if you let him get away and get on my side,
+you're to leave him alone as long as I can keep him from crossing over."
+
+"All right, go ahead; start him up."
+
+The tick escaped from Tom, presently, and crossed the equator. Joe
+harassed him awhile, and then he got away and crossed back again. This
+change of base occurred often. While one boy was worrying the tick with
+absorbing interest, the other would look on with interest as strong,
+the two heads bowed together over the slate, and the two souls dead to
+all things else. At last luck seemed to settle and abide with Joe. The
+tick tried this, that, and the other course, and got as excited and as
+anxious as the boys themselves, but time and again just as he would
+have victory in his very grasp, so to speak, and Tom's fingers would be
+twitching to begin, Joe's pin would deftly head him off, and keep
+possession. At last Tom could stand it no longer. The temptation was
+too strong. So he reached out and lent a hand with his pin. Joe was
+angry in a moment. Said he:
+
+"Tom, you let him alone."
+
+"I only just want to stir him up a little, Joe."
+
+"No, sir, it ain't fair; you just let him alone."
+
+"Blame it, I ain't going to stir him much."
+
+"Let him alone, I tell you."
+
+"I won't!"
+
+"You shall--he's on my side of the line."
+
+"Look here, Joe Harper, whose is that tick?"
+
+"I don't care whose tick he is--he's on my side of the line, and you
+sha'n't touch him."
+
+"Well, I'll just bet I will, though. He's my tick and I'll do what I
+blame please with him, or die!"
+
+A tremendous whack came down on Tom's shoulders, and its duplicate on
+Joe's; and for the space of two minutes the dust continued to fly from
+the two jackets and the whole school to enjoy it. The boys had been too
+absorbed to notice the hush that had stolen upon the school awhile
+before when the master came tiptoeing down the room and stood over
+them. He had contemplated a good part of the performance before he
+contributed his bit of variety to it.
+
+When school broke up at noon, Tom flew to Becky Thatcher, and
+whispered in her ear:
+
+"Put on your bonnet and let on you're going home; and when you get to
+the corner, give the rest of 'em the slip, and turn down through the
+lane and come back. I'll go the other way and come it over 'em the same
+way."
+
+So the one went off with one group of scholars, and the other with
+another. In a little while the two met at the bottom of the lane, and
+when they reached the school they had it all to themselves. Then they
+sat together, with a slate before them, and Tom gave Becky the pencil
+and held her hand in his, guiding it, and so created another surprising
+house. When the interest in art began to wane, the two fell to talking.
+Tom was swimming in bliss. He said:
+
+"Do you love rats?"
+
+"No! I hate them!"
+
+"Well, I do, too--LIVE ones. But I mean dead ones, to swing round your
+head with a string."
+
+"No, I don't care for rats much, anyway. What I like is chewing-gum."
+
+"Oh, I should say so! I wish I had some now."
+
+"Do you? I've got some. I'll let you chew it awhile, but you must give
+it back to me."
+
+That was agreeable, so they chewed it turn about, and dangled their
+legs against the bench in excess of contentment.
+
+"Was you ever at a circus?" said Tom.
+
+"Yes, and my pa's going to take me again some time, if I'm good."
+
+"I been to the circus three or four times--lots of times. Church ain't
+shucks to a circus. There's things going on at a circus all the time.
+I'm going to be a clown in a circus when I grow up."
+
+"Oh, are you! That will be nice. They're so lovely, all spotted up."
+
+"Yes, that's so. And they get slathers of money--most a dollar a day,
+Ben Rogers says. Say, Becky, was you ever engaged?"
+
+"What's that?"
+
+"Why, engaged to be married."
+
+"No."
+
+"Would you like to?"
+
+"I reckon so. I don't know. What is it like?"
+
+"Like? Why it ain't like anything. You only just tell a boy you won't
+ever have anybody but him, ever ever ever, and then you kiss and that's
+all. Anybody can do it."
+
+"Kiss? What do you kiss for?"
+
+"Why, that, you know, is to--well, they always do that."
+
+"Everybody?"
+
+"Why, yes, everybody that's in love with each other. Do you remember
+what I wrote on the slate?"
+
+"Ye--yes."
+
+"What was it?"
+
+"I sha'n't tell you."
+
+"Shall I tell YOU?"
+
+"Ye--yes--but some other time."
+
+"No, now."
+
+"No, not now--to-morrow."
+
+"Oh, no, NOW. Please, Becky--I'll whisper it, I'll whisper it ever so
+easy."
+
+Becky hesitating, Tom took silence for consent, and passed his arm
+about her waist and whispered the tale ever so softly, with his mouth
+close to her ear. And then he added:
+
+"Now you whisper it to me--just the same."
+
+She resisted, for a while, and then said:
+
+"You turn your face away so you can't see, and then I will. But you
+mustn't ever tell anybody--WILL you, Tom? Now you won't, WILL you?"
+
+"No, indeed, indeed I won't. Now, Becky."
+
+He turned his face away. She bent timidly around till her breath
+stirred his curls and whispered, "I--love--you!"
+
+Then she sprang away and ran around and around the desks and benches,
+with Tom after her, and took refuge in a corner at last, with her
+little white apron to her face. Tom clasped her about her neck and
+pleaded:
+
+"Now, Becky, it's all done--all over but the kiss. Don't you be afraid
+of that--it ain't anything at all. Please, Becky." And he tugged at her
+apron and the hands.
+
+By and by she gave up, and let her hands drop; her face, all glowing
+with the struggle, came up and submitted. Tom kissed the red lips and
+said:
+
+"Now it's all done, Becky. And always after this, you know, you ain't
+ever to love anybody but me, and you ain't ever to marry anybody but
+me, ever never and forever. Will you?"
+
+"No, I'll never love anybody but you, Tom, and I'll never marry
+anybody but you--and you ain't to ever marry anybody but me, either."
+
+"Certainly. Of course. That's PART of it. And always coming to school
+or when we're going home, you're to walk with me, when there ain't
+anybody looking--and you choose me and I choose you at parties, because
+that's the way you do when you're engaged."
+
+"It's so nice. I never heard of it before."
+
+"Oh, it's ever so gay! Why, me and Amy Lawrence--"
+
+The big eyes told Tom his blunder and he stopped, confused.
+
+"Oh, Tom! Then I ain't the first you've ever been engaged to!"
+
+The child began to cry. Tom said:
+
+"Oh, don't cry, Becky, I don't care for her any more."
+
+"Yes, you do, Tom--you know you do."
+
+Tom tried to put his arm about her neck, but she pushed him away and
+turned her face to the wall, and went on crying. Tom tried again, with
+soothing words in his mouth, and was repulsed again. Then his pride was
+up, and he strode away and went outside. He stood about, restless and
+uneasy, for a while, glancing at the door, every now and then, hoping
+she would repent and come to find him. But she did not. Then he began
+to feel badly and fear that he was in the wrong. It was a hard struggle
+with him to make new advances, now, but he nerved himself to it and
+entered. She was still standing back there in the corner, sobbing, with
+her face to the wall. Tom's heart smote him. He went to her and stood a
+moment, not knowing exactly how to proceed. Then he said hesitatingly:
+
+"Becky, I--I don't care for anybody but you."
+
+No reply--but sobs.
+
+"Becky"--pleadingly. "Becky, won't you say something?"
+
+More sobs.
+
+Tom got out his chiefest jewel, a brass knob from the top of an
+andiron, and passed it around her so that she could see it, and said:
+
+"Please, Becky, won't you take it?"
+
+She struck it to the floor. Then Tom marched out of the house and over
+the hills and far away, to return to school no more that day. Presently
+Becky began to suspect. She ran to the door; he was not in sight; she
+flew around to the play-yard; he was not there. Then she called:
+
+"Tom! Come back, Tom!"
+
+She listened intently, but there was no answer. She had no companions
+but silence and loneliness. So she sat down to cry again and upbraid
+herself; and by this time the scholars began to gather again, and she
+had to hide her griefs and still her broken heart and take up the cross
+of a long, dreary, aching afternoon, with none among the strangers
+about her to exchange sorrows with.
+
+
+
+CHAPTER VIII
+
+TOM dodged hither and thither through lanes until he was well out of
+the track of returning scholars, and then fell into a moody jog. He
+crossed a small "branch" two or three times, because of a prevailing
+juvenile superstition that to cross water baffled pursuit. Half an hour
+later he was disappearing behind the Douglas mansion on the summit of
+Cardiff Hill, and the schoolhouse was hardly distinguishable away off
+in the valley behind him. He entered a dense wood, picked his pathless
+way to the centre of it, and sat down on a mossy spot under a spreading
+oak. There was not even a zephyr stirring; the dead noonday heat had
+even stilled the songs of the birds; nature lay in a trance that was
+broken by no sound but the occasional far-off hammering of a
+woodpecker, and this seemed to render the pervading silence and sense
+of loneliness the more profound. The boy's soul was steeped in
+melancholy; his feelings were in happy accord with his surroundings. He
+sat long with his elbows on his knees and his chin in his hands,
+meditating. It seemed to him that life was but a trouble, at best, and
+he more than half envied Jimmy Hodges, so lately released; it must be
+very peaceful, he thought, to lie and slumber and dream forever and
+ever, with the wind whispering through the trees and caressing the
+grass and the flowers over the grave, and nothing to bother and grieve
+about, ever any more. If he only had a clean Sunday-school record he
+could be willing to go, and be done with it all. Now as to this girl.
+What had he done? Nothing. He had meant the best in the world, and been
+treated like a dog--like a very dog. She would be sorry some day--maybe
+when it was too late. Ah, if he could only die TEMPORARILY!
+
+But the elastic heart of youth cannot be compressed into one
+constrained shape long at a time. Tom presently began to drift
+insensibly back into the concerns of this life again. What if he turned
+his back, now, and disappeared mysteriously? What if he went away--ever
+so far away, into unknown countries beyond the seas--and never came
+back any more! How would she feel then! The idea of being a clown
+recurred to him now, only to fill him with disgust. For frivolity and
+jokes and spotted tights were an offense, when they intruded themselves
+upon a spirit that was exalted into the vague august realm of the
+romantic. No, he would be a soldier, and return after long years, all
+war-worn and illustrious. No--better still, he would join the Indians,
+and hunt buffaloes and go on the warpath in the mountain ranges and the
+trackless great plains of the Far West, and away in the future come
+back a great chief, bristling with feathers, hideous with paint, and
+prance into Sunday-school, some drowsy summer morning, with a
+bloodcurdling war-whoop, and sear the eyeballs of all his companions
+with unappeasable envy. But no, there was something gaudier even than
+this. He would be a pirate! That was it! NOW his future lay plain
+before him, and glowing with unimaginable splendor. How his name would
+fill the world, and make people shudder! How gloriously he would go
+plowing the dancing seas, in his long, low, black-hulled racer, the
+Spirit of the Storm, with his grisly flag flying at the fore! And at
+the zenith of his fame, how he would suddenly appear at the old village
+and stalk into church, brown and weather-beaten, in his black velvet
+doublet and trunks, his great jack-boots, his crimson sash, his belt
+bristling with horse-pistols, his crime-rusted cutlass at his side, his
+slouch hat with waving plumes, his black flag unfurled, with the skull
+and crossbones on it, and hear with swelling ecstasy the whisperings,
+"It's Tom Sawyer the Pirate!--the Black Avenger of the Spanish Main!"
+
+Yes, it was settled; his career was determined. He would run away from
+home and enter upon it. He would start the very next morning. Therefore
+he must now begin to get ready. He would collect his resources
+together. He went to a rotten log near at hand and began to dig under
+one end of it with his Barlow knife. He soon struck wood that sounded
+hollow. He put his hand there and uttered this incantation impressively:
+
+"What hasn't come here, come! What's here, stay here!"
+
+Then he scraped away the dirt, and exposed a pine shingle. He took it
+up and disclosed a shapely little treasure-house whose bottom and sides
+were of shingles. In it lay a marble. Tom's astonishment was boundless!
+He scratched his head with a perplexed air, and said:
+
+"Well, that beats anything!"
+
+Then he tossed the marble away pettishly, and stood cogitating. The
+truth was, that a superstition of his had failed, here, which he and
+all his comrades had always looked upon as infallible. If you buried a
+marble with certain necessary incantations, and left it alone a
+fortnight, and then opened the place with the incantation he had just
+used, you would find that all the marbles you had ever lost had
+gathered themselves together there, meantime, no matter how widely they
+had been separated. But now, this thing had actually and unquestionably
+failed. Tom's whole structure of faith was shaken to its foundations.
+He had many a time heard of this thing succeeding but never of its
+failing before. It did not occur to him that he had tried it several
+times before, himself, but could never find the hiding-places
+afterward. He puzzled over the matter some time, and finally decided
+that some witch had interfered and broken the charm. He thought he
+would satisfy himself on that point; so he searched around till he
+found a small sandy spot with a little funnel-shaped depression in it.
+He laid himself down and put his mouth close to this depression and
+called--
+
+"Doodle-bug, doodle-bug, tell me what I want to know! Doodle-bug,
+doodle-bug, tell me what I want to know!"
+
+The sand began to work, and presently a small black bug appeared for a
+second and then darted under again in a fright.
+
+"He dasn't tell! So it WAS a witch that done it. I just knowed it."
+
+He well knew the futility of trying to contend against witches, so he
+gave up discouraged. But it occurred to him that he might as well have
+the marble he had just thrown away, and therefore he went and made a
+patient search for it. But he could not find it. Now he went back to
+his treasure-house and carefully placed himself just as he had been
+standing when he tossed the marble away; then he took another marble
+from his pocket and tossed it in the same way, saying:
+
+"Brother, go find your brother!"
+
+He watched where it stopped, and went there and looked. But it must
+have fallen short or gone too far; so he tried twice more. The last
+repetition was successful. The two marbles lay within a foot of each
+other.
+
+Just here the blast of a toy tin trumpet came faintly down the green
+aisles of the forest. Tom flung off his jacket and trousers, turned a
+suspender into a belt, raked away some brush behind the rotten log,
+disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in
+a moment had seized these things and bounded away, barelegged, with
+fluttering shirt. He presently halted under a great elm, blew an
+answering blast, and then began to tiptoe and look warily out, this way
+and that. He said cautiously--to an imaginary company:
+
+"Hold, my merry men! Keep hid till I blow."
+
+Now appeared Joe Harper, as airily clad and elaborately armed as Tom.
+Tom called:
+
+"Hold! Who comes here into Sherwood Forest without my pass?"
+
+"Guy of Guisborne wants no man's pass. Who art thou that--that--"
+
+"Dares to hold such language," said Tom, prompting--for they talked
+"by the book," from memory.
+
+"Who art thou that dares to hold such language?"
+
+"I, indeed! I am Robin Hood, as thy caitiff carcase soon shall know."
+
+"Then art thou indeed that famous outlaw? Right gladly will I dispute
+with thee the passes of the merry wood. Have at thee!"
+
+They took their lath swords, dumped their other traps on the ground,
+struck a fencing attitude, foot to foot, and began a grave, careful
+combat, "two up and two down." Presently Tom said:
+
+"Now, if you've got the hang, go it lively!"
+
+So they "went it lively," panting and perspiring with the work. By and
+by Tom shouted:
+
+"Fall! fall! Why don't you fall?"
+
+"I sha'n't! Why don't you fall yourself? You're getting the worst of
+it."
+
+"Why, that ain't anything. I can't fall; that ain't the way it is in
+the book. The book says, 'Then with one back-handed stroke he slew poor
+Guy of Guisborne.' You're to turn around and let me hit you in the
+back."
+
+There was no getting around the authorities, so Joe turned, received
+the whack and fell.
+
+"Now," said Joe, getting up, "you got to let me kill YOU. That's fair."
+
+"Why, I can't do that, it ain't in the book."
+
+"Well, it's blamed mean--that's all."
+
+"Well, say, Joe, you can be Friar Tuck or Much the miller's son, and
+lam me with a quarter-staff; or I'll be the Sheriff of Nottingham and
+you be Robin Hood a little while and kill me."
+
+This was satisfactory, and so these adventures were carried out. Then
+Tom became Robin Hood again, and was allowed by the treacherous nun to
+bleed his strength away through his neglected wound. And at last Joe,
+representing a whole tribe of weeping outlaws, dragged him sadly forth,
+gave his bow into his feeble hands, and Tom said, "Where this arrow
+falls, there bury poor Robin Hood under the greenwood tree." Then he
+shot the arrow and fell back and would have died, but he lit on a
+nettle and sprang up too gaily for a corpse.
+
+The boys dressed themselves, hid their accoutrements, and went off
+grieving that there were no outlaws any more, and wondering what modern
+civilization could claim to have done to compensate for their loss.
+They said they would rather be outlaws a year in Sherwood Forest than
+President of the United States forever.
+
+
+
+CHAPTER IX
+
+AT half-past nine, that night, Tom and Sid were sent to bed, as usual.
+They said their prayers, and Sid was soon asleep. Tom lay awake and
+waited, in restless impatience. When it seemed to him that it must be
+nearly daylight, he heard the clock strike ten! This was despair. He
+would have tossed and fidgeted, as his nerves demanded, but he was
+afraid he might wake Sid. So he lay still, and stared up into the dark.
+Everything was dismally still. By and by, out of the stillness, little,
+scarcely perceptible noises began to emphasize themselves. The ticking
+of the clock began to bring itself into notice. Old beams began to
+crack mysteriously. The stairs creaked faintly. Evidently spirits were
+abroad. A measured, muffled snore issued from Aunt Polly's chamber. And
+now the tiresome chirping of a cricket that no human ingenuity could
+locate, began. Next the ghastly ticking of a deathwatch in the wall at
+the bed's head made Tom shudder--it meant that somebody's days were
+numbered. Then the howl of a far-off dog rose on the night air, and was
+answered by a fainter howl from a remoter distance. Tom was in an
+agony. At last he was satisfied that time had ceased and eternity
+begun; he began to doze, in spite of himself; the clock chimed eleven,
+but he did not hear it. And then there came, mingling with his
+half-formed dreams, a most melancholy caterwauling. The raising of a
+neighboring window disturbed him. A cry of "Scat! you devil!" and the
+crash of an empty bottle against the back of his aunt's woodshed
+brought him wide awake, and a single minute later he was dressed and
+out of the window and creeping along the roof of the "ell" on all
+fours. He "meow'd" with caution once or twice, as he went; then jumped
+to the roof of the woodshed and thence to the ground. Huckleberry Finn
+was there, with his dead cat. The boys moved off and disappeared in the
+gloom. At the end of half an hour they were wading through the tall
+grass of the graveyard.
+
+It was a graveyard of the old-fashioned Western kind. It was on a
+hill, about a mile and a half from the village. It had a crazy board
+fence around it, which leaned inward in places, and outward the rest of
+the time, but stood upright nowhere. Grass and weeds grew rank over the
+whole cemetery. All the old graves were sunken in, there was not a
+tombstone on the place; round-topped, worm-eaten boards staggered over
+the graves, leaning for support and finding none. "Sacred to the memory
+of" So-and-So had been painted on them once, but it could no longer
+have been read, on the most of them, now, even if there had been light.
+
+A faint wind moaned through the trees, and Tom feared it might be the
+spirits of the dead, complaining at being disturbed. The boys talked
+little, and only under their breath, for the time and the place and the
+pervading solemnity and silence oppressed their spirits. They found the
+sharp new heap they were seeking, and ensconced themselves within the
+protection of three great elms that grew in a bunch within a few feet
+of the grave.
+
+Then they waited in silence for what seemed a long time. The hooting
+of a distant owl was all the sound that troubled the dead stillness.
+Tom's reflections grew oppressive. He must force some talk. So he said
+in a whisper:
+
+"Hucky, do you believe the dead people like it for us to be here?"
+
+Huckleberry whispered:
+
+"I wisht I knowed. It's awful solemn like, AIN'T it?"
+
+"I bet it is."
+
+There was a considerable pause, while the boys canvassed this matter
+inwardly. Then Tom whispered:
+
+"Say, Hucky--do you reckon Hoss Williams hears us talking?"
+
+"O' course he does. Least his sperrit does."
+
+Tom, after a pause:
+
+"I wish I'd said Mister Williams. But I never meant any harm.
+Everybody calls him Hoss."
+
+"A body can't be too partic'lar how they talk 'bout these-yer dead
+people, Tom."
+
+This was a damper, and conversation died again.
+
+Presently Tom seized his comrade's arm and said:
+
+"Sh!"
+
+"What is it, Tom?" And the two clung together with beating hearts.
+
+"Sh! There 'tis again! Didn't you hear it?"
+
+"I--"
+
+"There! Now you hear it."
+
+"Lord, Tom, they're coming! They're coming, sure. What'll we do?"
+
+"I dono. Think they'll see us?"
+
+"Oh, Tom, they can see in the dark, same as cats. I wisht I hadn't
+come."
+
+"Oh, don't be afeard. I don't believe they'll bother us. We ain't
+doing any harm. If we keep perfectly still, maybe they won't notice us
+at all."
+
+"I'll try to, Tom, but, Lord, I'm all of a shiver."
+
+"Listen!"
+
+The boys bent their heads together and scarcely breathed. A muffled
+sound of voices floated up from the far end of the graveyard.
+
+"Look! See there!" whispered Tom. "What is it?"
+
+"It's devil-fire. Oh, Tom, this is awful."
+
+Some vague figures approached through the gloom, swinging an
+old-fashioned tin lantern that freckled the ground with innumerable
+little spangles of light. Presently Huckleberry whispered with a
+shudder:
+
+"It's the devils sure enough. Three of 'em! Lordy, Tom, we're goners!
+Can you pray?"
+
+"I'll try, but don't you be afeard. They ain't going to hurt us. 'Now
+I lay me down to sleep, I--'"
+
+"Sh!"
+
+"What is it, Huck?"
+
+"They're HUMANS! One of 'em is, anyway. One of 'em's old Muff Potter's
+voice."
+
+"No--'tain't so, is it?"
+
+"I bet I know it. Don't you stir nor budge. He ain't sharp enough to
+notice us. Drunk, the same as usual, likely--blamed old rip!"
+
+"All right, I'll keep still. Now they're stuck. Can't find it. Here
+they come again. Now they're hot. Cold again. Hot again. Red hot!
+They're p'inted right, this time. Say, Huck, I know another o' them
+voices; it's Injun Joe."
+
+"That's so--that murderin' half-breed! I'd druther they was devils a
+dern sight. What kin they be up to?"
+
+The whisper died wholly out, now, for the three men had reached the
+grave and stood within a few feet of the boys' hiding-place.
+
+"Here it is," said the third voice; and the owner of it held the
+lantern up and revealed the face of young Doctor Robinson.
+
+Potter and Injun Joe were carrying a handbarrow with a rope and a
+couple of shovels on it. They cast down their load and began to open
+the grave. The doctor put the lantern at the head of the grave and came
+and sat down with his back against one of the elm trees. He was so
+close the boys could have touched him.
+
+"Hurry, men!" he said, in a low voice; "the moon might come out at any
+moment."
+
+They growled a response and went on digging. For some time there was
+no noise but the grating sound of the spades discharging their freight
+of mould and gravel. It was very monotonous. Finally a spade struck
+upon the coffin with a dull woody accent, and within another minute or
+two the men had hoisted it out on the ground. They pried off the lid
+with their shovels, got out the body and dumped it rudely on the
+ground. The moon drifted from behind the clouds and exposed the pallid
+face. The barrow was got ready and the corpse placed on it, covered
+with a blanket, and bound to its place with the rope. Potter took out a
+large spring-knife and cut off the dangling end of the rope and then
+said:
+
+"Now the cussed thing's ready, Sawbones, and you'll just out with
+another five, or here she stays."
+
+"That's the talk!" said Injun Joe.
+
+"Look here, what does this mean?" said the doctor. "You required your
+pay in advance, and I've paid you."
+
+"Yes, and you done more than that," said Injun Joe, approaching the
+doctor, who was now standing. "Five years ago you drove me away from
+your father's kitchen one night, when I come to ask for something to
+eat, and you said I warn't there for any good; and when I swore I'd get
+even with you if it took a hundred years, your father had me jailed for
+a vagrant. Did you think I'd forget? The Injun blood ain't in me for
+nothing. And now I've GOT you, and you got to SETTLE, you know!"
+
+He was threatening the doctor, with his fist in his face, by this
+time. The doctor struck out suddenly and stretched the ruffian on the
+ground. Potter dropped his knife, and exclaimed:
+
+"Here, now, don't you hit my pard!" and the next moment he had
+grappled with the doctor and the two were struggling with might and
+main, trampling the grass and tearing the ground with their heels.
+Injun Joe sprang to his feet, his eyes flaming with passion, snatched
+up Potter's knife, and went creeping, catlike and stooping, round and
+round about the combatants, seeking an opportunity. All at once the
+doctor flung himself free, seized the heavy headboard of Williams'
+grave and felled Potter to the earth with it--and in the same instant
+the half-breed saw his chance and drove the knife to the hilt in the
+young man's breast. He reeled and fell partly upon Potter, flooding him
+with his blood, and in the same moment the clouds blotted out the
+dreadful spectacle and the two frightened boys went speeding away in
+the dark.
+
+Presently, when the moon emerged again, Injun Joe was standing over
+the two forms, contemplating them. The doctor murmured inarticulately,
+gave a long gasp or two and was still. The half-breed muttered:
+
+"THAT score is settled--damn you."
+
+Then he robbed the body. After which he put the fatal knife in
+Potter's open right hand, and sat down on the dismantled coffin. Three
+--four--five minutes passed, and then Potter began to stir and moan. His
+hand closed upon the knife; he raised it, glanced at it, and let it
+fall, with a shudder. Then he sat up, pushing the body from him, and
+gazed at it, and then around him, confusedly. His eyes met Joe's.
+
+"Lord, how is this, Joe?" he said.
+
+"It's a dirty business," said Joe, without moving.
+
+"What did you do it for?"
+
+"I! I never done it!"
+
+"Look here! That kind of talk won't wash."
+
+Potter trembled and grew white.
+
+"I thought I'd got sober. I'd no business to drink to-night. But it's
+in my head yet--worse'n when we started here. I'm all in a muddle;
+can't recollect anything of it, hardly. Tell me, Joe--HONEST, now, old
+feller--did I do it? Joe, I never meant to--'pon my soul and honor, I
+never meant to, Joe. Tell me how it was, Joe. Oh, it's awful--and him
+so young and promising."
+
+"Why, you two was scuffling, and he fetched you one with the headboard
+and you fell flat; and then up you come, all reeling and staggering
+like, and snatched the knife and jammed it into him, just as he fetched
+you another awful clip--and here you've laid, as dead as a wedge til
+now."
+
+"Oh, I didn't know what I was a-doing. I wish I may die this minute if
+I did. It was all on account of the whiskey and the excitement, I
+reckon. I never used a weepon in my life before, Joe. I've fought, but
+never with weepons. They'll all say that. Joe, don't tell! Say you
+won't tell, Joe--that's a good feller. I always liked you, Joe, and
+stood up for you, too. Don't you remember? You WON'T tell, WILL you,
+Joe?" And the poor creature dropped on his knees before the stolid
+murderer, and clasped his appealing hands.
+
+"No, you've always been fair and square with me, Muff Potter, and I
+won't go back on you. There, now, that's as fair as a man can say."
+
+"Oh, Joe, you're an angel. I'll bless you for this the longest day I
+live." And Potter began to cry.
+
+"Come, now, that's enough of that. This ain't any time for blubbering.
+You be off yonder way and I'll go this. Move, now, and don't leave any
+tracks behind you."
+
+Potter started on a trot that quickly increased to a run. The
+half-breed stood looking after him. He muttered:
+
+"If he's as much stunned with the lick and fuddled with the rum as he
+had the look of being, he won't think of the knife till he's gone so
+far he'll be afraid to come back after it to such a place by himself
+--chicken-heart!"
+
+Two or three minutes later the murdered man, the blanketed corpse, the
+lidless coffin, and the open grave were under no inspection but the
+moon's. The stillness was complete again, too.
+
+
+
+CHAPTER X
+
+THE two boys flew on and on, toward the village, speechless with
+horror. They glanced backward over their shoulders from time to time,
+apprehensively, as if they feared they might be followed. Every stump
+that started up in their path seemed a man and an enemy, and made them
+catch their breath; and as they sped by some outlying cottages that lay
+near the village, the barking of the aroused watch-dogs seemed to give
+wings to their feet.
+
+"If we can only get to the old tannery before we break down!"
+whispered Tom, in short catches between breaths. "I can't stand it much
+longer."
+
+Huckleberry's hard pantings were his only reply, and the boys fixed
+their eyes on the goal of their hopes and bent to their work to win it.
+They gained steadily on it, and at last, breast to breast, they burst
+through the open door and fell grateful and exhausted in the sheltering
+shadows beyond. By and by their pulses slowed down, and Tom whispered:
+
+"Huckleberry, what do you reckon'll come of this?"
+
+"If Doctor Robinson dies, I reckon hanging'll come of it."
+
+"Do you though?"
+
+"Why, I KNOW it, Tom."
+
+Tom thought a while, then he said:
+
+"Who'll tell? We?"
+
+"What are you talking about? S'pose something happened and Injun Joe
+DIDN'T hang? Why, he'd kill us some time or other, just as dead sure as
+we're a laying here."
+
+"That's just what I was thinking to myself, Huck."
+
+"If anybody tells, let Muff Potter do it, if he's fool enough. He's
+generally drunk enough."
+
+Tom said nothing--went on thinking. Presently he whispered:
+
+"Huck, Muff Potter don't know it. How can he tell?"
+
+"What's the reason he don't know it?"
+
+"Because he'd just got that whack when Injun Joe done it. D'you reckon
+he could see anything? D'you reckon he knowed anything?"
+
+"By hokey, that's so, Tom!"
+
+"And besides, look-a-here--maybe that whack done for HIM!"
+
+"No, 'taint likely, Tom. He had liquor in him; I could see that; and
+besides, he always has. Well, when pap's full, you might take and belt
+him over the head with a church and you couldn't phase him. He says so,
+his own self. So it's the same with Muff Potter, of course. But if a
+man was dead sober, I reckon maybe that whack might fetch him; I dono."
+
+After another reflective silence, Tom said:
+
+"Hucky, you sure you can keep mum?"
+
+"Tom, we GOT to keep mum. You know that. That Injun devil wouldn't
+make any more of drownding us than a couple of cats, if we was to
+squeak 'bout this and they didn't hang him. Now, look-a-here, Tom, less
+take and swear to one another--that's what we got to do--swear to keep
+mum."
+
+"I'm agreed. It's the best thing. Would you just hold hands and swear
+that we--"
+
+"Oh no, that wouldn't do for this. That's good enough for little
+rubbishy common things--specially with gals, cuz THEY go back on you
+anyway, and blab if they get in a huff--but there orter be writing
+'bout a big thing like this. And blood."
+
+Tom's whole being applauded this idea. It was deep, and dark, and
+awful; the hour, the circumstances, the surroundings, were in keeping
+with it. He picked up a clean pine shingle that lay in the moonlight,
+took a little fragment of "red keel" out of his pocket, got the moon on
+his work, and painfully scrawled these lines, emphasizing each slow
+down-stroke by clamping his tongue between his teeth, and letting up
+the pressure on the up-strokes. [See next page.]
+
+   "Huck Finn and
+    Tom Sawyer swears
+    they will keep mum
+    about This and They
+    wish They may Drop
+    down dead in Their
+    Tracks if They ever
+    Tell and Rot."
+
+Huckleberry was filled with admiration of Tom's facility in writing,
+and the sublimity of his language. He at once took a pin from his lapel
+and was going to prick his flesh, but Tom said:
+
+"Hold on! Don't do that. A pin's brass. It might have verdigrease on
+it."
+
+"What's verdigrease?"
+
+"It's p'ison. That's what it is. You just swaller some of it once
+--you'll see."
+
+So Tom unwound the thread from one of his needles, and each boy
+pricked the ball of his thumb and squeezed out a drop of blood. In
+time, after many squeezes, Tom managed to sign his initials, using the
+ball of his little finger for a pen. Then he showed Huckleberry how to
+make an H and an F, and the oath was complete. They buried the shingle
+close to the wall, with some dismal ceremonies and incantations, and
+the fetters that bound their tongues were considered to be locked and
+the key thrown away.
+
+A figure crept stealthily through a break in the other end of the
+ruined building, now, but they did not notice it.
+
+"Tom," whispered Huckleberry, "does this keep us from EVER telling
+--ALWAYS?"
+
+"Of course it does. It don't make any difference WHAT happens, we got
+to keep mum. We'd drop down dead--don't YOU know that?"
+
+"Yes, I reckon that's so."
+
+They continued to whisper for some little time. Presently a dog set up
+a long, lugubrious howl just outside--within ten feet of them. The boys
+clasped each other suddenly, in an agony of fright.
+
+"Which of us does he mean?" gasped Huckleberry.
+
+"I dono--peep through the crack. Quick!"
+
+"No, YOU, Tom!"
+
+"I can't--I can't DO it, Huck!"
+
+"Please, Tom. There 'tis again!"
+
+"Oh, lordy, I'm thankful!" whispered Tom. "I know his voice. It's Bull
+Harbison." *
+
+[* If Mr. Harbison owned a slave named Bull, Tom would have spoken of
+him as "Harbison's Bull," but a son or a dog of that name was "Bull
+Harbison."]
+
+"Oh, that's good--I tell you, Tom, I was most scared to death; I'd a
+bet anything it was a STRAY dog."
+
+The dog howled again. The boys' hearts sank once more.
+
+"Oh, my! that ain't no Bull Harbison!" whispered Huckleberry. "DO, Tom!"
+
+Tom, quaking with fear, yielded, and put his eye to the crack. His
+whisper was hardly audible when he said:
+
+"Oh, Huck, IT S A STRAY DOG!"
+
+"Quick, Tom, quick! Who does he mean?"
+
+"Huck, he must mean us both--we're right together."
+
+"Oh, Tom, I reckon we're goners. I reckon there ain't no mistake 'bout
+where I'LL go to. I been so wicked."
+
+"Dad fetch it! This comes of playing hookey and doing everything a
+feller's told NOT to do. I might a been good, like Sid, if I'd a tried
+--but no, I wouldn't, of course. But if ever I get off this time, I lay
+I'll just WALLER in Sunday-schools!" And Tom began to snuffle a little.
+
+"YOU bad!" and Huckleberry began to snuffle too. "Consound it, Tom
+Sawyer, you're just old pie, 'longside o' what I am. Oh, LORDY, lordy,
+lordy, I wisht I only had half your chance."
+
+Tom choked off and whispered:
+
+"Look, Hucky, look! He's got his BACK to us!"
+
+Hucky looked, with joy in his heart.
+
+"Well, he has, by jingoes! Did he before?"
+
+"Yes, he did. But I, like a fool, never thought. Oh, this is bully,
+you know. NOW who can he mean?"
+
+The howling stopped. Tom pricked up his ears.
+
+"Sh! What's that?" he whispered.
+
+"Sounds like--like hogs grunting. No--it's somebody snoring, Tom."
+
+"That IS it! Where 'bouts is it, Huck?"
+
+"I bleeve it's down at 'tother end. Sounds so, anyway. Pap used to
+sleep there, sometimes, 'long with the hogs, but laws bless you, he
+just lifts things when HE snores. Besides, I reckon he ain't ever
+coming back to this town any more."
+
+The spirit of adventure rose in the boys' souls once more.
+
+"Hucky, do you das't to go if I lead?"
+
+"I don't like to, much. Tom, s'pose it's Injun Joe!"
+
+Tom quailed. But presently the temptation rose up strong again and the
+boys agreed to try, with the understanding that they would take to
+their heels if the snoring stopped. So they went tiptoeing stealthily
+down, the one behind the other. When they had got to within five steps
+of the snorer, Tom stepped on a stick, and it broke with a sharp snap.
+The man moaned, writhed a little, and his face came into the moonlight.
+It was Muff Potter. The boys' hearts had stood still, and their hopes
+too, when the man moved, but their fears passed away now. They tiptoed
+out, through the broken weather-boarding, and stopped at a little
+distance to exchange a parting word. That long, lugubrious howl rose on
+the night air again! They turned and saw the strange dog standing
+within a few feet of where Potter was lying, and FACING Potter, with
+his nose pointing heavenward.
+
+"Oh, geeminy, it's HIM!" exclaimed both boys, in a breath.
+
+"Say, Tom--they say a stray dog come howling around Johnny Miller's
+house, 'bout midnight, as much as two weeks ago; and a whippoorwill
+come in and lit on the banisters and sung, the very same evening; and
+there ain't anybody dead there yet."
+
+"Well, I know that. And suppose there ain't. Didn't Gracie Miller fall
+in the kitchen fire and burn herself terrible the very next Saturday?"
+
+"Yes, but she ain't DEAD. And what's more, she's getting better, too."
+
+"All right, you wait and see. She's a goner, just as dead sure as Muff
+Potter's a goner. That's what the niggers say, and they know all about
+these kind of things, Huck."
+
+Then they separated, cogitating. When Tom crept in at his bedroom
+window the night was almost spent. He undressed with excessive caution,
+and fell asleep congratulating himself that nobody knew of his
+escapade. He was not aware that the gently-snoring Sid was awake, and
+had been so for an hour.
+
+When Tom awoke, Sid was dressed and gone. There was a late look in the
+light, a late sense in the atmosphere. He was startled. Why had he not
+been called--persecuted till he was up, as usual? The thought filled
+him with bodings. Within five minutes he was dressed and down-stairs,
+feeling sore and drowsy. The family were still at table, but they had
+finished breakfast. There was no voice of rebuke; but there were
+averted eyes; there was a silence and an air of solemnity that struck a
+chill to the culprit's heart. He sat down and tried to seem gay, but it
+was up-hill work; it roused no smile, no response, and he lapsed into
+silence and let his heart sink down to the depths.
+
+After breakfast his aunt took him aside, and Tom almost brightened in
+the hope that he was going to be flogged; but it was not so. His aunt
+wept over him and asked him how he could go and break her old heart so;
+and finally told him to go on, and ruin himself and bring her gray
+hairs with sorrow to the grave, for it was no use for her to try any
+more. This was worse than a thousand whippings, and Tom's heart was
+sorer now than his body. He cried, he pleaded for forgiveness, promised
+to reform over and over again, and then received his dismissal, feeling
+that he had won but an imperfect forgiveness and established but a
+feeble confidence.
+
+He left the presence too miserable to even feel revengeful toward Sid;
+and so the latter's prompt retreat through the back gate was
+unnecessary. He moped to school gloomy and sad, and took his flogging,
+along with Joe Harper, for playing hookey the day before, with the air
+of one whose heart was busy with heavier woes and wholly dead to
+trifles. Then he betook himself to his seat, rested his elbows on his
+desk and his jaws in his hands, and stared at the wall with the stony
+stare of suffering that has reached the limit and can no further go.
+His elbow was pressing against some hard substance. After a long time
+he slowly and sadly changed his position, and took up this object with
+a sigh. It was in a paper. He unrolled it. A long, lingering, colossal
+sigh followed, and his heart broke. It was his brass andiron knob!
+
+This final feather broke the camel's back.
+
+
+
+CHAPTER XI
+
+CLOSE upon the hour of noon the whole village was suddenly electrified
+with the ghastly news. No need of the as yet undreamed-of telegraph;
+the tale flew from man to man, from group to group, from house to
+house, with little less than telegraphic speed. Of course the
+schoolmaster gave holiday for that afternoon; the town would have
+thought strangely of him if he had not.
+
+A gory knife had been found close to the murdered man, and it had been
+recognized by somebody as belonging to Muff Potter--so the story ran.
+And it was said that a belated citizen had come upon Potter washing
+himself in the "branch" about one or two o'clock in the morning, and
+that Potter had at once sneaked off--suspicious circumstances,
+especially the washing which was not a habit with Potter. It was also
+said that the town had been ransacked for this "murderer" (the public
+are not slow in the matter of sifting evidence and arriving at a
+verdict), but that he could not be found. Horsemen had departed down
+all the roads in every direction, and the Sheriff "was confident" that
+he would be captured before night.
+
+All the town was drifting toward the graveyard. Tom's heartbreak
+vanished and he joined the procession, not because he would not a
+thousand times rather go anywhere else, but because an awful,
+unaccountable fascination drew him on. Arrived at the dreadful place,
+he wormed his small body through the crowd and saw the dismal
+spectacle. It seemed to him an age since he was there before. Somebody
+pinched his arm. He turned, and his eyes met Huckleberry's. Then both
+looked elsewhere at once, and wondered if anybody had noticed anything
+in their mutual glance. But everybody was talking, and intent upon the
+grisly spectacle before them.
+
+"Poor fellow!" "Poor young fellow!" "This ought to be a lesson to
+grave robbers!" "Muff Potter'll hang for this if they catch him!" This
+was the drift of remark; and the minister said, "It was a judgment; His
+hand is here."
+
+Now Tom shivered from head to heel; for his eye fell upon the stolid
+face of Injun Joe. At this moment the crowd began to sway and struggle,
+and voices shouted, "It's him! it's him! he's coming himself!"
+
+"Who? Who?" from twenty voices.
+
+"Muff Potter!"
+
+"Hallo, he's stopped!--Look out, he's turning! Don't let him get away!"
+
+People in the branches of the trees over Tom's head said he wasn't
+trying to get away--he only looked doubtful and perplexed.
+
+"Infernal impudence!" said a bystander; "wanted to come and take a
+quiet look at his work, I reckon--didn't expect any company."
+
+The crowd fell apart, now, and the Sheriff came through,
+ostentatiously leading Potter by the arm. The poor fellow's face was
+haggard, and his eyes showed the fear that was upon him. When he stood
+before the murdered man, he shook as with a palsy, and he put his face
+in his hands and burst into tears.
+
+"I didn't do it, friends," he sobbed; "'pon my word and honor I never
+done it."
+
+"Who's accused you?" shouted a voice.
+
+This shot seemed to carry home. Potter lifted his face and looked
+around him with a pathetic hopelessness in his eyes. He saw Injun Joe,
+and exclaimed:
+
+"Oh, Injun Joe, you promised me you'd never--"
+
+"Is that your knife?" and it was thrust before him by the Sheriff.
+
+Potter would have fallen if they had not caught him and eased him to
+the ground. Then he said:
+
+"Something told me 't if I didn't come back and get--" He shuddered;
+then waved his nerveless hand with a vanquished gesture and said, "Tell
+'em, Joe, tell 'em--it ain't any use any more."
+
+Then Huckleberry and Tom stood dumb and staring, and heard the
+stony-hearted liar reel off his serene statement, they expecting every
+moment that the clear sky would deliver God's lightnings upon his head,
+and wondering to see how long the stroke was delayed. And when he had
+finished and still stood alive and whole, their wavering impulse to
+break their oath and save the poor betrayed prisoner's life faded and
+vanished away, for plainly this miscreant had sold himself to Satan and
+it would be fatal to meddle with the property of such a power as that.
+
+"Why didn't you leave? What did you want to come here for?" somebody
+said.
+
+"I couldn't help it--I couldn't help it," Potter moaned. "I wanted to
+run away, but I couldn't seem to come anywhere but here." And he fell
+to sobbing again.
+
+Injun Joe repeated his statement, just as calmly, a few minutes
+afterward on the inquest, under oath; and the boys, seeing that the
+lightnings were still withheld, were confirmed in their belief that Joe
+had sold himself to the devil. He was now become, to them, the most
+balefully interesting object they had ever looked upon, and they could
+not take their fascinated eyes from his face.
+
+They inwardly resolved to watch him nights, when opportunity should
+offer, in the hope of getting a glimpse of his dread master.
+
+Injun Joe helped to raise the body of the murdered man and put it in a
+wagon for removal; and it was whispered through the shuddering crowd
+that the wound bled a little! The boys thought that this happy
+circumstance would turn suspicion in the right direction; but they were
+disappointed, for more than one villager remarked:
+
+"It was within three feet of Muff Potter when it done it."
+
+Tom's fearful secret and gnawing conscience disturbed his sleep for as
+much as a week after this; and at breakfast one morning Sid said:
+
+"Tom, you pitch around and talk in your sleep so much that you keep me
+awake half the time."
+
+Tom blanched and dropped his eyes.
+
+"It's a bad sign," said Aunt Polly, gravely. "What you got on your
+mind, Tom?"
+
+"Nothing. Nothing 't I know of." But the boy's hand shook so that he
+spilled his coffee.
+
+"And you do talk such stuff," Sid said. "Last night you said, 'It's
+blood, it's blood, that's what it is!' You said that over and over. And
+you said, 'Don't torment me so--I'll tell!' Tell WHAT? What is it
+you'll tell?"
+
+Everything was swimming before Tom. There is no telling what might
+have happened, now, but luckily the concern passed out of Aunt Polly's
+face and she came to Tom's relief without knowing it. She said:
+
+"Sho! It's that dreadful murder. I dream about it most every night
+myself. Sometimes I dream it's me that done it."
+
+Mary said she had been affected much the same way. Sid seemed
+satisfied. Tom got out of the presence as quick as he plausibly could,
+and after that he complained of toothache for a week, and tied up his
+jaws every night. He never knew that Sid lay nightly watching, and
+frequently slipped the bandage free and then leaned on his elbow
+listening a good while at a time, and afterward slipped the bandage
+back to its place again. Tom's distress of mind wore off gradually and
+the toothache grew irksome and was discarded. If Sid really managed to
+make anything out of Tom's disjointed mutterings, he kept it to himself.
+
+It seemed to Tom that his schoolmates never would get done holding
+inquests on dead cats, and thus keeping his trouble present to his
+mind. Sid noticed that Tom never was coroner at one of these inquiries,
+though it had been his habit to take the lead in all new enterprises;
+he noticed, too, that Tom never acted as a witness--and that was
+strange; and Sid did not overlook the fact that Tom even showed a
+marked aversion to these inquests, and always avoided them when he
+could. Sid marvelled, but said nothing. However, even inquests went out
+of vogue at last, and ceased to torture Tom's conscience.
+
+Every day or two, during this time of sorrow, Tom watched his
+opportunity and went to the little grated jail-window and smuggled such
+small comforts through to the "murderer" as he could get hold of. The
+jail was a trifling little brick den that stood in a marsh at the edge
+of the village, and no guards were afforded for it; indeed, it was
+seldom occupied. These offerings greatly helped to ease Tom's
+conscience.
+
+The villagers had a strong desire to tar-and-feather Injun Joe and
+ride him on a rail, for body-snatching, but so formidable was his
+character that nobody could be found who was willing to take the lead
+in the matter, so it was dropped. He had been careful to begin both of
+his inquest-statements with the fight, without confessing the
+grave-robbery that preceded it; therefore it was deemed wisest not
+to try the case in the courts at present.
+
+
+
+CHAPTER XII
+
+ONE of the reasons why Tom's mind had drifted away from its secret
+troubles was, that it had found a new and weighty matter to interest
+itself about. Becky Thatcher had stopped coming to school. Tom had
+struggled with his pride a few days, and tried to "whistle her down the
+wind," but failed. He began to find himself hanging around her father's
+house, nights, and feeling very miserable. She was ill. What if she
+should die! There was distraction in the thought. He no longer took an
+interest in war, nor even in piracy. The charm of life was gone; there
+was nothing but dreariness left. He put his hoop away, and his bat;
+there was no joy in them any more. His aunt was concerned. She began to
+try all manner of remedies on him. She was one of those people who are
+infatuated with patent medicines and all new-fangled methods of
+producing health or mending it. She was an inveterate experimenter in
+these things. When something fresh in this line came out she was in a
+fever, right away, to try it; not on herself, for she was never ailing,
+but on anybody else that came handy. She was a subscriber for all the
+"Health" periodicals and phrenological frauds; and the solemn ignorance
+they were inflated with was breath to her nostrils. All the "rot" they
+contained about ventilation, and how to go to bed, and how to get up,
+and what to eat, and what to drink, and how much exercise to take, and
+what frame of mind to keep one's self in, and what sort of clothing to
+wear, was all gospel to her, and she never observed that her
+health-journals of the current month customarily upset everything they
+had recommended the month before. She was as simple-hearted and honest
+as the day was long, and so she was an easy victim. She gathered
+together her quack periodicals and her quack medicines, and thus armed
+with death, went about on her pale horse, metaphorically speaking, with
+"hell following after." But she never suspected that she was not an
+angel of healing and the balm of Gilead in disguise, to the suffering
+neighbors.
+
+The water treatment was new, now, and Tom's low condition was a
+windfall to her. She had him out at daylight every morning, stood him
+up in the woodshed and drowned him with a deluge of cold water; then
+she scrubbed him down with a towel like a file, and so brought him to;
+then she rolled him up in a wet sheet and put him away under blankets
+till she sweated his soul clean and "the yellow stains of it came
+through his pores"--as Tom said.
+
+Yet notwithstanding all this, the boy grew more and more melancholy
+and pale and dejected. She added hot baths, sitz baths, shower baths,
+and plunges. The boy remained as dismal as a hearse. She began to
+assist the water with a slim oatmeal diet and blister-plasters. She
+calculated his capacity as she would a jug's, and filled him up every
+day with quack cure-alls.
+
+Tom had become indifferent to persecution by this time. This phase
+filled the old lady's heart with consternation. This indifference must
+be broken up at any cost. Now she heard of Pain-killer for the first
+time. She ordered a lot at once. She tasted it and was filled with
+gratitude. It was simply fire in a liquid form. She dropped the water
+treatment and everything else, and pinned her faith to Pain-killer. She
+gave Tom a teaspoonful and watched with the deepest anxiety for the
+result. Her troubles were instantly at rest, her soul at peace again;
+for the "indifference" was broken up. The boy could not have shown a
+wilder, heartier interest, if she had built a fire under him.
+
+Tom felt that it was time to wake up; this sort of life might be
+romantic enough, in his blighted condition, but it was getting to have
+too little sentiment and too much distracting variety about it. So he
+thought over various plans for relief, and finally hit pon that of
+professing to be fond of Pain-killer. He asked for it so often that he
+became a nuisance, and his aunt ended by telling him to help himself
+and quit bothering her. If it had been Sid, she would have had no
+misgivings to alloy her delight; but since it was Tom, she watched the
+bottle clandestinely. She found that the medicine did really diminish,
+but it did not occur to her that the boy was mending the health of a
+crack in the sitting-room floor with it.
+
+One day Tom was in the act of dosing the crack when his aunt's yellow
+cat came along, purring, eying the teaspoon avariciously, and begging
+for a taste. Tom said:
+
+"Don't ask for it unless you want it, Peter."
+
+But Peter signified that he did want it.
+
+"You better make sure."
+
+Peter was sure.
+
+"Now you've asked for it, and I'll give it to you, because there ain't
+anything mean about me; but if you find you don't like it, you mustn't
+blame anybody but your own self."
+
+Peter was agreeable. So Tom pried his mouth open and poured down the
+Pain-killer. Peter sprang a couple of yards in the air, and then
+delivered a war-whoop and set off round and round the room, banging
+against furniture, upsetting flower-pots, and making general havoc.
+Next he rose on his hind feet and pranced around, in a frenzy of
+enjoyment, with his head over his shoulder and his voice proclaiming
+his unappeasable happiness. Then he went tearing around the house again
+spreading chaos and destruction in his path. Aunt Polly entered in time
+to see him throw a few double summersets, deliver a final mighty
+hurrah, and sail through the open window, carrying the rest of the
+flower-pots with him. The old lady stood petrified with astonishment,
+peering over her glasses; Tom lay on the floor expiring with laughter.
+
+"Tom, what on earth ails that cat?"
+
+"I don't know, aunt," gasped the boy.
+
+"Why, I never see anything like it. What did make him act so?"
+
+"Deed I don't know, Aunt Polly; cats always act so when they're having
+a good time."
+
+"They do, do they?" There was something in the tone that made Tom
+apprehensive.
+
+"Yes'm. That is, I believe they do."
+
+"You DO?"
+
+"Yes'm."
+
+The old lady was bending down, Tom watching, with interest emphasized
+by anxiety. Too late he divined her "drift." The handle of the telltale
+teaspoon was visible under the bed-valance. Aunt Polly took it, held it
+up. Tom winced, and dropped his eyes. Aunt Polly raised him by the
+usual handle--his ear--and cracked his head soundly with her thimble.
+
+"Now, sir, what did you want to treat that poor dumb beast so, for?"
+
+"I done it out of pity for him--because he hadn't any aunt."
+
+"Hadn't any aunt!--you numskull. What has that got to do with it?"
+
+"Heaps. Because if he'd had one she'd a burnt him out herself! She'd a
+roasted his bowels out of him 'thout any more feeling than if he was a
+human!"
+
+Aunt Polly felt a sudden pang of remorse. This was putting the thing
+in a new light; what was cruelty to a cat MIGHT be cruelty to a boy,
+too. She began to soften; she felt sorry. Her eyes watered a little,
+and she put her hand on Tom's head and said gently:
+
+"I was meaning for the best, Tom. And, Tom, it DID do you good."
+
+Tom looked up in her face with just a perceptible twinkle peeping
+through his gravity.
+
+"I know you was meaning for the best, aunty, and so was I with Peter.
+It done HIM good, too. I never see him get around so since--"
+
+"Oh, go 'long with you, Tom, before you aggravate me again. And you
+try and see if you can't be a good boy, for once, and you needn't take
+any more medicine."
+
+Tom reached school ahead of time. It was noticed that this strange
+thing had been occurring every day latterly. And now, as usual of late,
+he hung about the gate of the schoolyard instead of playing with his
+comrades. He was sick, he said, and he looked it. He tried to seem to
+be looking everywhere but whither he really was looking--down the road.
+Presently Jeff Thatcher hove in sight, and Tom's face lighted; he gazed
+a moment, and then turned sorrowfully away. When Jeff arrived, Tom
+accosted him; and "led up" warily to opportunities for remark about
+Becky, but the giddy lad never could see the bait. Tom watched and
+watched, hoping whenever a frisking frock came in sight, and hating the
+owner of it as soon as he saw she was not the right one. At last frocks
+ceased to appear, and he dropped hopelessly into the dumps; he entered
+the empty schoolhouse and sat down to suffer. Then one more frock
+passed in at the gate, and Tom's heart gave a great bound. The next
+instant he was out, and "going on" like an Indian; yelling, laughing,
+chasing boys, jumping over the fence at risk of life and limb, throwing
+handsprings, standing on his head--doing all the heroic things he could
+conceive of, and keeping a furtive eye out, all the while, to see if
+Becky Thatcher was noticing. But she seemed to be unconscious of it
+all; she never looked. Could it be possible that she was not aware that
+he was there? He carried his exploits to her immediate vicinity; came
+war-whooping around, snatched a boy's cap, hurled it to the roof of the
+schoolhouse, broke through a group of boys, tumbling them in every
+direction, and fell sprawling, himself, under Becky's nose, almost
+upsetting her--and she turned, with her nose in the air, and he heard
+her say: "Mf! some people think they're mighty smart--always showing
+off!"
+
+Tom's cheeks burned. He gathered himself up and sneaked off, crushed
+and crestfallen.
+
+
+
+CHAPTER XIII
+
+TOM'S mind was made up now. He was gloomy and desperate. He was a
+forsaken, friendless boy, he said; nobody loved him; when they found
+out what they had driven him to, perhaps they would be sorry; he had
+tried to do right and get along, but they would not let him; since
+nothing would do them but to be rid of him, let it be so; and let them
+blame HIM for the consequences--why shouldn't they? What right had the
+friendless to complain? Yes, they had forced him to it at last: he
+would lead a life of crime. There was no choice.
+
+By this time he was far down Meadow Lane, and the bell for school to
+"take up" tinkled faintly upon his ear. He sobbed, now, to think he
+should never, never hear that old familiar sound any more--it was very
+hard, but it was forced on him; since he was driven out into the cold
+world, he must submit--but he forgave them. Then the sobs came thick
+and fast.
+
+Just at this point he met his soul's sworn comrade, Joe Harper
+--hard-eyed, and with evidently a great and dismal purpose in his heart.
+Plainly here were "two souls with but a single thought." Tom, wiping
+his eyes with his sleeve, began to blubber out something about a
+resolution to escape from hard usage and lack of sympathy at home by
+roaming abroad into the great world never to return; and ended by
+hoping that Joe would not forget him.
+
+But it transpired that this was a request which Joe had just been
+going to make of Tom, and had come to hunt him up for that purpose. His
+mother had whipped him for drinking some cream which he had never
+tasted and knew nothing about; it was plain that she was tired of him
+and wished him to go; if she felt that way, there was nothing for him
+to do but succumb; he hoped she would be happy, and never regret having
+driven her poor boy out into the unfeeling world to suffer and die.
+
+As the two boys walked sorrowing along, they made a new compact to
+stand by each other and be brothers and never separate till death
+relieved them of their troubles. Then they began to lay their plans.
+Joe was for being a hermit, and living on crusts in a remote cave, and
+dying, some time, of cold and want and grief; but after listening to
+Tom, he conceded that there were some conspicuous advantages about a
+life of crime, and so he consented to be a pirate.
+
+Three miles below St. Petersburg, at a point where the Mississippi
+River was a trifle over a mile wide, there was a long, narrow, wooded
+island, with a shallow bar at the head of it, and this offered well as
+a rendezvous. It was not inhabited; it lay far over toward the further
+shore, abreast a dense and almost wholly unpeopled forest. So Jackson's
+Island was chosen. Who were to be the subjects of their piracies was a
+matter that did not occur to them. Then they hunted up Huckleberry
+Finn, and he joined them promptly, for all careers were one to him; he
+was indifferent. They presently separated to meet at a lonely spot on
+the river-bank two miles above the village at the favorite hour--which
+was midnight. There was a small log raft there which they meant to
+capture. Each would bring hooks and lines, and such provision as he
+could steal in the most dark and mysterious way--as became outlaws. And
+before the afternoon was done, they had all managed to enjoy the sweet
+glory of spreading the fact that pretty soon the town would "hear
+something." All who got this vague hint were cautioned to "be mum and
+wait."
+
+About midnight Tom arrived with a boiled ham and a few trifles,
+and stopped in a dense undergrowth on a small bluff overlooking the
+meeting-place. It was starlight, and very still. The mighty river lay
+like an ocean at rest. Tom listened a moment, but no sound disturbed the
+quiet. Then he gave a low, distinct whistle. It was answered from under
+the bluff. Tom whistled twice more; these signals were answered in the
+same way. Then a guarded voice said:
+
+"Who goes there?"
+
+"Tom Sawyer, the Black Avenger of the Spanish Main. Name your names."
+
+"Huck Finn the Red-Handed, and Joe Harper the Terror of the Seas." Tom
+had furnished these titles, from his favorite literature.
+
+"'Tis well. Give the countersign."
+
+Two hoarse whispers delivered the same awful word simultaneously to
+the brooding night:
+
+"BLOOD!"
+
+Then Tom tumbled his ham over the bluff and let himself down after it,
+tearing both skin and clothes to some extent in the effort. There was
+an easy, comfortable path along the shore under the bluff, but it
+lacked the advantages of difficulty and danger so valued by a pirate.
+
+The Terror of the Seas had brought a side of bacon, and had about worn
+himself out with getting it there. Finn the Red-Handed had stolen a
+skillet and a quantity of half-cured leaf tobacco, and had also brought
+a few corn-cobs to make pipes with. But none of the pirates smoked or
+"chewed" but himself. The Black Avenger of the Spanish Main said it
+would never do to start without some fire. That was a wise thought;
+matches were hardly known there in that day. They saw a fire
+smouldering upon a great raft a hundred yards above, and they went
+stealthily thither and helped themselves to a chunk. They made an
+imposing adventure of it, saying, "Hist!" every now and then, and
+suddenly halting with finger on lip; moving with hands on imaginary
+dagger-hilts; and giving orders in dismal whispers that if "the foe"
+stirred, to "let him have it to the hilt," because "dead men tell no
+tales." They knew well enough that the raftsmen were all down at the
+village laying in stores or having a spree, but still that was no
+excuse for their conducting this thing in an unpiratical way.
+
+They shoved off, presently, Tom in command, Huck at the after oar and
+Joe at the forward. Tom stood amidships, gloomy-browed, and with folded
+arms, and gave his orders in a low, stern whisper:
+
+"Luff, and bring her to the wind!"
+
+"Aye-aye, sir!"
+
+"Steady, steady-y-y-y!"
+
+"Steady it is, sir!"
+
+"Let her go off a point!"
+
+"Point it is, sir!"
+
+As the boys steadily and monotonously drove the raft toward mid-stream
+it was no doubt understood that these orders were given only for
+"style," and were not intended to mean anything in particular.
+
+"What sail's she carrying?"
+
+"Courses, tops'ls, and flying-jib, sir."
+
+"Send the r'yals up! Lay out aloft, there, half a dozen of ye
+--foretopmaststuns'l! Lively, now!"
+
+"Aye-aye, sir!"
+
+"Shake out that maintogalans'l! Sheets and braces! NOW my hearties!"
+
+"Aye-aye, sir!"
+
+"Hellum-a-lee--hard a port! Stand by to meet her when she comes! Port,
+port! NOW, men! With a will! Stead-y-y-y!"
+
+"Steady it is, sir!"
+
+The raft drew beyond the middle of the river; the boys pointed her
+head right, and then lay on their oars. The river was not high, so
+there was not more than a two or three mile current. Hardly a word was
+said during the next three-quarters of an hour. Now the raft was
+passing before the distant town. Two or three glimmering lights showed
+where it lay, peacefully sleeping, beyond the vague vast sweep of
+star-gemmed water, unconscious of the tremendous event that was happening.
+The Black Avenger stood still with folded arms, "looking his last" upon
+the scene of his former joys and his later sufferings, and wishing
+"she" could see him now, abroad on the wild sea, facing peril and death
+with dauntless heart, going to his doom with a grim smile on his lips.
+It was but a small strain on his imagination to remove Jackson's Island
+beyond eyeshot of the village, and so he "looked his last" with a
+broken and satisfied heart. The other pirates were looking their last,
+too; and they all looked so long that they came near letting the
+current drift them out of the range of the island. But they discovered
+the danger in time, and made shift to avert it. About two o'clock in
+the morning the raft grounded on the bar two hundred yards above the
+head of the island, and they waded back and forth until they had landed
+their freight. Part of the little raft's belongings consisted of an old
+sail, and this they spread over a nook in the bushes for a tent to
+shelter their provisions; but they themselves would sleep in the open
+air in good weather, as became outlaws.
+
+They built a fire against the side of a great log twenty or thirty
+steps within the sombre depths of the forest, and then cooked some
+bacon in the frying-pan for supper, and used up half of the corn "pone"
+stock they had brought. It seemed glorious sport to be feasting in that
+wild, free way in the virgin forest of an unexplored and uninhabited
+island, far from the haunts of men, and they said they never would
+return to civilization. The climbing fire lit up their faces and threw
+its ruddy glare upon the pillared tree-trunks of their forest temple,
+and upon the varnished foliage and festooning vines.
+
+When the last crisp slice of bacon was gone, and the last allowance of
+corn pone devoured, the boys stretched themselves out on the grass,
+filled with contentment. They could have found a cooler place, but they
+would not deny themselves such a romantic feature as the roasting
+camp-fire.
+
+"AIN'T it gay?" said Joe.
+
+"It's NUTS!" said Tom. "What would the boys say if they could see us?"
+
+"Say? Well, they'd just die to be here--hey, Hucky!"
+
+"I reckon so," said Huckleberry; "anyways, I'm suited. I don't want
+nothing better'n this. I don't ever get enough to eat, gen'ally--and
+here they can't come and pick at a feller and bullyrag him so."
+
+"It's just the life for me," said Tom. "You don't have to get up,
+mornings, and you don't have to go to school, and wash, and all that
+blame foolishness. You see a pirate don't have to do ANYTHING, Joe,
+when he's ashore, but a hermit HE has to be praying considerable, and
+then he don't have any fun, anyway, all by himself that way."
+
+"Oh yes, that's so," said Joe, "but I hadn't thought much about it,
+you know. I'd a good deal rather be a pirate, now that I've tried it."
+
+"You see," said Tom, "people don't go much on hermits, nowadays, like
+they used to in old times, but a pirate's always respected. And a
+hermit's got to sleep on the hardest place he can find, and put
+sackcloth and ashes on his head, and stand out in the rain, and--"
+
+"What does he put sackcloth and ashes on his head for?" inquired Huck.
+
+"I dono. But they've GOT to do it. Hermits always do. You'd have to do
+that if you was a hermit."
+
+"Dern'd if I would," said Huck.
+
+"Well, what would you do?"
+
+"I dono. But I wouldn't do that."
+
+"Why, Huck, you'd HAVE to. How'd you get around it?"
+
+"Why, I just wouldn't stand it. I'd run away."
+
+"Run away! Well, you WOULD be a nice old slouch of a hermit. You'd be
+a disgrace."
+
+The Red-Handed made no response, being better employed. He had
+finished gouging out a cob, and now he fitted a weed stem to it, loaded
+it with tobacco, and was pressing a coal to the charge and blowing a
+cloud of fragrant smoke--he was in the full bloom of luxurious
+contentment. The other pirates envied him this majestic vice, and
+secretly resolved to acquire it shortly. Presently Huck said:
+
+"What does pirates have to do?"
+
+Tom said:
+
+"Oh, they have just a bully time--take ships and burn them, and get
+the money and bury it in awful places in their island where there's
+ghosts and things to watch it, and kill everybody in the ships--make
+'em walk a plank."
+
+"And they carry the women to the island," said Joe; "they don't kill
+the women."
+
+"No," assented Tom, "they don't kill the women--they're too noble. And
+the women's always beautiful, too.
+
+"And don't they wear the bulliest clothes! Oh no! All gold and silver
+and di'monds," said Joe, with enthusiasm.
+
+"Who?" said Huck.
+
+"Why, the pirates."
+
+Huck scanned his own clothing forlornly.
+
+"I reckon I ain't dressed fitten for a pirate," said he, with a
+regretful pathos in his voice; "but I ain't got none but these."
+
+But the other boys told him the fine clothes would come fast enough,
+after they should have begun their adventures. They made him understand
+that his poor rags would do to begin with, though it was customary for
+wealthy pirates to start with a proper wardrobe.
+
+Gradually their talk died out and drowsiness began to steal upon the
+eyelids of the little waifs. The pipe dropped from the fingers of the
+Red-Handed, and he slept the sleep of the conscience-free and the
+weary. The Terror of the Seas and the Black Avenger of the Spanish Main
+had more difficulty in getting to sleep. They said their prayers
+inwardly, and lying down, since there was nobody there with authority
+to make them kneel and recite aloud; in truth, they had a mind not to
+say them at all, but they were afraid to proceed to such lengths as
+that, lest they might call down a sudden and special thunderbolt from
+heaven. Then at once they reached and hovered upon the imminent verge
+of sleep--but an intruder came, now, that would not "down." It was
+conscience. They began to feel a vague fear that they had been doing
+wrong to run away; and next they thought of the stolen meat, and then
+the real torture came. They tried to argue it away by reminding
+conscience that they had purloined sweetmeats and apples scores of
+times; but conscience was not to be appeased by such thin
+plausibilities; it seemed to them, in the end, that there was no
+getting around the stubborn fact that taking sweetmeats was only
+"hooking," while taking bacon and hams and such valuables was plain
+simple stealing--and there was a command against that in the Bible. So
+they inwardly resolved that so long as they remained in the business,
+their piracies should not again be sullied with the crime of stealing.
+Then conscience granted a truce, and these curiously inconsistent
+pirates fell peacefully to sleep.
+
+
+
+CHAPTER XIV
+
+WHEN Tom awoke in the morning, he wondered where he was. He sat up and
+rubbed his eyes and looked around. Then he comprehended. It was the
+cool gray dawn, and there was a delicious sense of repose and peace in
+the deep pervading calm and silence of the woods. Not a leaf stirred;
+not a sound obtruded upon great Nature's meditation. Beaded dewdrops
+stood upon the leaves and grasses. A white layer of ashes covered the
+fire, and a thin blue breath of smoke rose straight into the air. Joe
+and Huck still slept.
+
+Now, far away in the woods a bird called; another answered; presently
+the hammering of a woodpecker was heard. Gradually the cool dim gray of
+the morning whitened, and as gradually sounds multiplied and life
+manifested itself. The marvel of Nature shaking off sleep and going to
+work unfolded itself to the musing boy. A little green worm came
+crawling over a dewy leaf, lifting two-thirds of his body into the air
+from time to time and "sniffing around," then proceeding again--for he
+was measuring, Tom said; and when the worm approached him, of its own
+accord, he sat as still as a stone, with his hopes rising and falling,
+by turns, as the creature still came toward him or seemed inclined to
+go elsewhere; and when at last it considered a painful moment with its
+curved body in the air and then came decisively down upon Tom's leg and
+began a journey over him, his whole heart was glad--for that meant that
+he was going to have a new suit of clothes--without the shadow of a
+doubt a gaudy piratical uniform. Now a procession of ants appeared,
+from nowhere in particular, and went about their labors; one struggled
+manfully by with a dead spider five times as big as itself in its arms,
+and lugged it straight up a tree-trunk. A brown spotted lady-bug
+climbed the dizzy height of a grass blade, and Tom bent down close to
+it and said, "Lady-bug, lady-bug, fly away home, your house is on fire,
+your children's alone," and she took wing and went off to see about it
+--which did not surprise the boy, for he knew of old that this insect was
+credulous about conflagrations, and he had practised upon its
+simplicity more than once. A tumblebug came next, heaving sturdily at
+its ball, and Tom touched the creature, to see it shut its legs against
+its body and pretend to be dead. The birds were fairly rioting by this
+time. A catbird, the Northern mocker, lit in a tree over Tom's head,
+and trilled out her imitations of her neighbors in a rapture of
+enjoyment; then a shrill jay swept down, a flash of blue flame, and
+stopped on a twig almost within the boy's reach, cocked his head to one
+side and eyed the strangers with a consuming curiosity; a gray squirrel
+and a big fellow of the "fox" kind came skurrying along, sitting up at
+intervals to inspect and chatter at the boys, for the wild things had
+probably never seen a human being before and scarcely knew whether to
+be afraid or not. All Nature was wide awake and stirring, now; long
+lances of sunlight pierced down through the dense foliage far and near,
+and a few butterflies came fluttering upon the scene.
+
+Tom stirred up the other pirates and they all clattered away with a
+shout, and in a minute or two were stripped and chasing after and
+tumbling over each other in the shallow limpid water of the white
+sandbar. They felt no longing for the little village sleeping in the
+distance beyond the majestic waste of water. A vagrant current or a
+slight rise in the river had carried off their raft, but this only
+gratified them, since its going was something like burning the bridge
+between them and civilization.
+
+They came back to camp wonderfully refreshed, glad-hearted, and
+ravenous; and they soon had the camp-fire blazing up again. Huck found
+a spring of clear cold water close by, and the boys made cups of broad
+oak or hickory leaves, and felt that water, sweetened with such a
+wildwood charm as that, would be a good enough substitute for coffee.
+While Joe was slicing bacon for breakfast, Tom and Huck asked him to
+hold on a minute; they stepped to a promising nook in the river-bank
+and threw in their lines; almost immediately they had reward. Joe had
+not had time to get impatient before they were back again with some
+handsome bass, a couple of sun-perch and a small catfish--provisions
+enough for quite a family. They fried the fish with the bacon, and were
+astonished; for no fish had ever seemed so delicious before. They did
+not know that the quicker a fresh-water fish is on the fire after he is
+caught the better he is; and they reflected little upon what a sauce
+open-air sleeping, open-air exercise, bathing, and a large ingredient
+of hunger make, too.
+
+They lay around in the shade, after breakfast, while Huck had a smoke,
+and then went off through the woods on an exploring expedition. They
+tramped gayly along, over decaying logs, through tangled underbrush,
+among solemn monarchs of the forest, hung from their crowns to the
+ground with a drooping regalia of grape-vines. Now and then they came
+upon snug nooks carpeted with grass and jeweled with flowers.
+
+They found plenty of things to be delighted with, but nothing to be
+astonished at. They discovered that the island was about three miles
+long and a quarter of a mile wide, and that the shore it lay closest to
+was only separated from it by a narrow channel hardly two hundred yards
+wide. They took a swim about every hour, so it was close upon the
+middle of the afternoon when they got back to camp. They were too
+hungry to stop to fish, but they fared sumptuously upon cold ham, and
+then threw themselves down in the shade to talk. But the talk soon
+began to drag, and then died. The stillness, the solemnity that brooded
+in the woods, and the sense of loneliness, began to tell upon the
+spirits of the boys. They fell to thinking. A sort of undefined longing
+crept upon them. This took dim shape, presently--it was budding
+homesickness. Even Finn the Red-Handed was dreaming of his doorsteps
+and empty hogsheads. But they were all ashamed of their weakness, and
+none was brave enough to speak his thought.
+
+For some time, now, the boys had been dully conscious of a peculiar
+sound in the distance, just as one sometimes is of the ticking of a
+clock which he takes no distinct note of. But now this mysterious sound
+became more pronounced, and forced a recognition. The boys started,
+glanced at each other, and then each assumed a listening attitude.
+There was a long silence, profound and unbroken; then a deep, sullen
+boom came floating down out of the distance.
+
+"What is it!" exclaimed Joe, under his breath.
+
+"I wonder," said Tom in a whisper.
+
+"'Tain't thunder," said Huckleberry, in an awed tone, "becuz thunder--"
+
+"Hark!" said Tom. "Listen--don't talk."
+
+They waited a time that seemed an age, and then the same muffled boom
+troubled the solemn hush.
+
+"Let's go and see."
+
+They sprang to their feet and hurried to the shore toward the town.
+They parted the bushes on the bank and peered out over the water. The
+little steam ferryboat was about a mile below the village, drifting
+with the current. Her broad deck seemed crowded with people. There were
+a great many skiffs rowing about or floating with the stream in the
+neighborhood of the ferryboat, but the boys could not determine what
+the men in them were doing. Presently a great jet of white smoke burst
+from the ferryboat's side, and as it expanded and rose in a lazy cloud,
+that same dull throb of sound was borne to the listeners again.
+
+"I know now!" exclaimed Tom; "somebody's drownded!"
+
+"That's it!" said Huck; "they done that last summer, when Bill Turner
+got drownded; they shoot a cannon over the water, and that makes him
+come up to the top. Yes, and they take loaves of bread and put
+quicksilver in 'em and set 'em afloat, and wherever there's anybody
+that's drownded, they'll float right there and stop."
+
+"Yes, I've heard about that," said Joe. "I wonder what makes the bread
+do that."
+
+"Oh, it ain't the bread, so much," said Tom; "I reckon it's mostly
+what they SAY over it before they start it out."
+
+"But they don't say anything over it," said Huck. "I've seen 'em and
+they don't."
+
+"Well, that's funny," said Tom. "But maybe they say it to themselves.
+Of COURSE they do. Anybody might know that."
+
+The other boys agreed that there was reason in what Tom said, because
+an ignorant lump of bread, uninstructed by an incantation, could not be
+expected to act very intelligently when set upon an errand of such
+gravity.
+
+"By jings, I wish I was over there, now," said Joe.
+
+"I do too" said Huck "I'd give heaps to know who it is."
+
+The boys still listened and watched. Presently a revealing thought
+flashed through Tom's mind, and he exclaimed:
+
+"Boys, I know who's drownded--it's us!"
+
+They felt like heroes in an instant. Here was a gorgeous triumph; they
+were missed; they were mourned; hearts were breaking on their account;
+tears were being shed; accusing memories of unkindness to these poor
+lost lads were rising up, and unavailing regrets and remorse were being
+indulged; and best of all, the departed were the talk of the whole
+town, and the envy of all the boys, as far as this dazzling notoriety
+was concerned. This was fine. It was worth while to be a pirate, after
+all.
+
+As twilight drew on, the ferryboat went back to her accustomed
+business and the skiffs disappeared. The pirates returned to camp. They
+were jubilant with vanity over their new grandeur and the illustrious
+trouble they were making. They caught fish, cooked supper and ate it,
+and then fell to guessing at what the village was thinking and saying
+about them; and the pictures they drew of the public distress on their
+account were gratifying to look upon--from their point of view. But
+when the shadows of night closed them in, they gradually ceased to
+talk, and sat gazing into the fire, with their minds evidently
+wandering elsewhere. The excitement was gone, now, and Tom and Joe
+could not keep back thoughts of certain persons at home who were not
+enjoying this fine frolic as much as they were. Misgivings came; they
+grew troubled and unhappy; a sigh or two escaped, unawares. By and by
+Joe timidly ventured upon a roundabout "feeler" as to how the others
+might look upon a return to civilization--not right now, but--
+
+Tom withered him with derision! Huck, being uncommitted as yet, joined
+in with Tom, and the waverer quickly "explained," and was glad to get
+out of the scrape with as little taint of chicken-hearted homesickness
+clinging to his garments as he could. Mutiny was effectually laid to
+rest for the moment.
+
+As the night deepened, Huck began to nod, and presently to snore. Joe
+followed next. Tom lay upon his elbow motionless, for some time,
+watching the two intently. At last he got up cautiously, on his knees,
+and went searching among the grass and the flickering reflections flung
+by the camp-fire. He picked up and inspected several large
+semi-cylinders of the thin white bark of a sycamore, and finally chose
+two which seemed to suit him. Then he knelt by the fire and painfully
+wrote something upon each of these with his "red keel"; one he rolled up
+and put in his jacket pocket, and the other he put in Joe's hat and
+removed it to a little distance from the owner. And he also put into the
+hat certain schoolboy treasures of almost inestimable value--among them
+a lump of chalk, an India-rubber ball, three fishhooks, and one of that
+kind of marbles known as a "sure 'nough crystal." Then he tiptoed his
+way cautiously among the trees till he felt that he was out of hearing,
+and straightway broke into a keen run in the direction of the sandbar.
+
+
+
+CHAPTER XV
+
+A FEW minutes later Tom was in the shoal water of the bar, wading
+toward the Illinois shore. Before the depth reached his middle he was
+half-way over; the current would permit no more wading, now, so he
+struck out confidently to swim the remaining hundred yards. He swam
+quartering upstream, but still was swept downward rather faster than he
+had expected. However, he reached the shore finally, and drifted along
+till he found a low place and drew himself out. He put his hand on his
+jacket pocket, found his piece of bark safe, and then struck through
+the woods, following the shore, with streaming garments. Shortly before
+ten o'clock he came out into an open place opposite the village, and
+saw the ferryboat lying in the shadow of the trees and the high bank.
+Everything was quiet under the blinking stars. He crept down the bank,
+watching with all his eyes, slipped into the water, swam three or four
+strokes and climbed into the skiff that did "yawl" duty at the boat's
+stern. He laid himself down under the thwarts and waited, panting.
+
+Presently the cracked bell tapped and a voice gave the order to "cast
+off." A minute or two later the skiff's head was standing high up,
+against the boat's swell, and the voyage was begun. Tom felt happy in
+his success, for he knew it was the boat's last trip for the night. At
+the end of a long twelve or fifteen minutes the wheels stopped, and Tom
+slipped overboard and swam ashore in the dusk, landing fifty yards
+downstream, out of danger of possible stragglers.
+
+He flew along unfrequented alleys, and shortly found himself at his
+aunt's back fence. He climbed over, approached the "ell," and looked in
+at the sitting-room window, for a light was burning there. There sat
+Aunt Polly, Sid, Mary, and Joe Harper's mother, grouped together,
+talking. They were by the bed, and the bed was between them and the
+door. Tom went to the door and began to softly lift the latch; then he
+pressed gently and the door yielded a crack; he continued pushing
+cautiously, and quaking every time it creaked, till he judged he might
+squeeze through on his knees; so he put his head through and began,
+warily.
+
+"What makes the candle blow so?" said Aunt Polly. Tom hurried up.
+"Why, that door's open, I believe. Why, of course it is. No end of
+strange things now. Go 'long and shut it, Sid."
+
+Tom disappeared under the bed just in time. He lay and "breathed"
+himself for a time, and then crept to where he could almost touch his
+aunt's foot.
+
+"But as I was saying," said Aunt Polly, "he warn't BAD, so to say
+--only mischEEvous. Only just giddy, and harum-scarum, you know. He
+warn't any more responsible than a colt. HE never meant any harm, and
+he was the best-hearted boy that ever was"--and she began to cry.
+
+"It was just so with my Joe--always full of his devilment, and up to
+every kind of mischief, but he was just as unselfish and kind as he
+could be--and laws bless me, to think I went and whipped him for taking
+that cream, never once recollecting that I throwed it out myself
+because it was sour, and I never to see him again in this world, never,
+never, never, poor abused boy!" And Mrs. Harper sobbed as if her heart
+would break.
+
+"I hope Tom's better off where he is," said Sid, "but if he'd been
+better in some ways--"
+
+"SID!" Tom felt the glare of the old lady's eye, though he could not
+see it. "Not a word against my Tom, now that he's gone! God'll take
+care of HIM--never you trouble YOURself, sir! Oh, Mrs. Harper, I don't
+know how to give him up! I don't know how to give him up! He was such a
+comfort to me, although he tormented my old heart out of me, 'most."
+
+"The Lord giveth and the Lord hath taken away--Blessed be the name of
+the Lord! But it's so hard--Oh, it's so hard! Only last Saturday my
+Joe busted a firecracker right under my nose and I knocked him
+sprawling. Little did I know then, how soon--Oh, if it was to do over
+again I'd hug him and bless him for it."
+
+"Yes, yes, yes, I know just how you feel, Mrs. Harper, I know just
+exactly how you feel. No longer ago than yesterday noon, my Tom took
+and filled the cat full of Pain-killer, and I did think the cretur
+would tear the house down. And God forgive me, I cracked Tom's head
+with my thimble, poor boy, poor dead boy. But he's out of all his
+troubles now. And the last words I ever heard him say was to reproach--"
+
+But this memory was too much for the old lady, and she broke entirely
+down. Tom was snuffling, now, himself--and more in pity of himself than
+anybody else. He could hear Mary crying, and putting in a kindly word
+for him from time to time. He began to have a nobler opinion of himself
+than ever before. Still, he was sufficiently touched by his aunt's
+grief to long to rush out from under the bed and overwhelm her with
+joy--and the theatrical gorgeousness of the thing appealed strongly to
+his nature, too, but he resisted and lay still.
+
+He went on listening, and gathered by odds and ends that it was
+conjectured at first that the boys had got drowned while taking a swim;
+then the small raft had been missed; next, certain boys said the
+missing lads had promised that the village should "hear something"
+soon; the wise-heads had "put this and that together" and decided that
+the lads had gone off on that raft and would turn up at the next town
+below, presently; but toward noon the raft had been found, lodged
+against the Missouri shore some five or six miles below the village
+--and then hope perished; they must be drowned, else hunger would have
+driven them home by nightfall if not sooner. It was believed that the
+search for the bodies had been a fruitless effort merely because the
+drowning must have occurred in mid-channel, since the boys, being good
+swimmers, would otherwise have escaped to shore. This was Wednesday
+night. If the bodies continued missing until Sunday, all hope would be
+given over, and the funerals would be preached on that morning. Tom
+shuddered.
+
+Mrs. Harper gave a sobbing good-night and turned to go. Then with a
+mutual impulse the two bereaved women flung themselves into each
+other's arms and had a good, consoling cry, and then parted. Aunt Polly
+was tender far beyond her wont, in her good-night to Sid and Mary. Sid
+snuffled a bit and Mary went off crying with all her heart.
+
+Aunt Polly knelt down and prayed for Tom so touchingly, so
+appealingly, and with such measureless love in her words and her old
+trembling voice, that he was weltering in tears again, long before she
+was through.
+
+He had to keep still long after she went to bed, for she kept making
+broken-hearted ejaculations from time to time, tossing unrestfully, and
+turning over. But at last she was still, only moaning a little in her
+sleep. Now the boy stole out, rose gradually by the bedside, shaded the
+candle-light with his hand, and stood regarding her. His heart was full
+of pity for her. He took out his sycamore scroll and placed it by the
+candle. But something occurred to him, and he lingered considering. His
+face lighted with a happy solution of his thought; he put the bark
+hastily in his pocket. Then he bent over and kissed the faded lips, and
+straightway made his stealthy exit, latching the door behind him.
+
+He threaded his way back to the ferry landing, found nobody at large
+there, and walked boldly on board the boat, for he knew she was
+tenantless except that there was a watchman, who always turned in and
+slept like a graven image. He untied the skiff at the stern, slipped
+into it, and was soon rowing cautiously upstream. When he had pulled a
+mile above the village, he started quartering across and bent himself
+stoutly to his work. He hit the landing on the other side neatly, for
+this was a familiar bit of work to him. He was moved to capture the
+skiff, arguing that it might be considered a ship and therefore
+legitimate prey for a pirate, but he knew a thorough search would be
+made for it and that might end in revelations. So he stepped ashore and
+entered the woods.
+
+He sat down and took a long rest, torturing himself meanwhile to keep
+awake, and then started warily down the home-stretch. The night was far
+spent. It was broad daylight before he found himself fairly abreast the
+island bar. He rested again until the sun was well up and gilding the
+great river with its splendor, and then he plunged into the stream. A
+little later he paused, dripping, upon the threshold of the camp, and
+heard Joe say:
+
+"No, Tom's true-blue, Huck, and he'll come back. He won't desert. He
+knows that would be a disgrace to a pirate, and Tom's too proud for
+that sort of thing. He's up to something or other. Now I wonder what?"
+
+"Well, the things is ours, anyway, ain't they?"
+
+"Pretty near, but not yet, Huck. The writing says they are if he ain't
+back here to breakfast."
+
+"Which he is!" exclaimed Tom, with fine dramatic effect, stepping
+grandly into camp.
+
+A sumptuous breakfast of bacon and fish was shortly provided, and as
+the boys set to work upon it, Tom recounted (and adorned) his
+adventures. They were a vain and boastful company of heroes when the
+tale was done. Then Tom hid himself away in a shady nook to sleep till
+noon, and the other pirates got ready to fish and explore.
+
+
+
+CHAPTER XVI
+
+AFTER dinner all the gang turned out to hunt for turtle eggs on the
+bar. They went about poking sticks into the sand, and when they found a
+soft place they went down on their knees and dug with their hands.
+Sometimes they would take fifty or sixty eggs out of one hole. They
+were perfectly round white things a trifle smaller than an English
+walnut. They had a famous fried-egg feast that night, and another on
+Friday morning.
+
+After breakfast they went whooping and prancing out on the bar, and
+chased each other round and round, shedding clothes as they went, until
+they were naked, and then continued the frolic far away up the shoal
+water of the bar, against the stiff current, which latter tripped their
+legs from under them from time to time and greatly increased the fun.
+And now and then they stooped in a group and splashed water in each
+other's faces with their palms, gradually approaching each other, with
+averted faces to avoid the strangling sprays, and finally gripping and
+struggling till the best man ducked his neighbor, and then they all
+went under in a tangle of white legs and arms and came up blowing,
+sputtering, laughing, and gasping for breath at one and the same time.
+
+When they were well exhausted, they would run out and sprawl on the
+dry, hot sand, and lie there and cover themselves up with it, and by
+and by break for the water again and go through the original
+performance once more. Finally it occurred to them that their naked
+skin represented flesh-colored "tights" very fairly; so they drew a
+ring in the sand and had a circus--with three clowns in it, for none
+would yield this proudest post to his neighbor.
+
+Next they got their marbles and played "knucks" and "ring-taw" and
+"keeps" till that amusement grew stale. Then Joe and Huck had another
+swim, but Tom would not venture, because he found that in kicking off
+his trousers he had kicked his string of rattlesnake rattles off his
+ankle, and he wondered how he had escaped cramp so long without the
+protection of this mysterious charm. He did not venture again until he
+had found it, and by that time the other boys were tired and ready to
+rest. They gradually wandered apart, dropped into the "dumps," and fell
+to gazing longingly across the wide river to where the village lay
+drowsing in the sun. Tom found himself writing "BECKY" in the sand with
+his big toe; he scratched it out, and was angry with himself for his
+weakness. But he wrote it again, nevertheless; he could not help it. He
+erased it once more and then took himself out of temptation by driving
+the other boys together and joining them.
+
+But Joe's spirits had gone down almost beyond resurrection. He was so
+homesick that he could hardly endure the misery of it. The tears lay
+very near the surface. Huck was melancholy, too. Tom was downhearted,
+but tried hard not to show it. He had a secret which he was not ready
+to tell, yet, but if this mutinous depression was not broken up soon,
+he would have to bring it out. He said, with a great show of
+cheerfulness:
+
+"I bet there's been pirates on this island before, boys. We'll explore
+it again. They've hid treasures here somewhere. How'd you feel to light
+on a rotten chest full of gold and silver--hey?"
+
+But it roused only faint enthusiasm, which faded out, with no reply.
+Tom tried one or two other seductions; but they failed, too. It was
+discouraging work. Joe sat poking up the sand with a stick and looking
+very gloomy. Finally he said:
+
+"Oh, boys, let's give it up. I want to go home. It's so lonesome."
+
+"Oh no, Joe, you'll feel better by and by," said Tom. "Just think of
+the fishing that's here."
+
+"I don't care for fishing. I want to go home."
+
+"But, Joe, there ain't such another swimming-place anywhere."
+
+"Swimming's no good. I don't seem to care for it, somehow, when there
+ain't anybody to say I sha'n't go in. I mean to go home."
+
+"Oh, shucks! Baby! You want to see your mother, I reckon."
+
+"Yes, I DO want to see my mother--and you would, too, if you had one.
+I ain't any more baby than you are." And Joe snuffled a little.
+
+"Well, we'll let the cry-baby go home to his mother, won't we, Huck?
+Poor thing--does it want to see its mother? And so it shall. You like
+it here, don't you, Huck? We'll stay, won't we?"
+
+Huck said, "Y-e-s"--without any heart in it.
+
+"I'll never speak to you again as long as I live," said Joe, rising.
+"There now!" And he moved moodily away and began to dress himself.
+
+"Who cares!" said Tom. "Nobody wants you to. Go 'long home and get
+laughed at. Oh, you're a nice pirate. Huck and me ain't cry-babies.
+We'll stay, won't we, Huck? Let him go if he wants to. I reckon we can
+get along without him, per'aps."
+
+But Tom was uneasy, nevertheless, and was alarmed to see Joe go
+sullenly on with his dressing. And then it was discomforting to see
+Huck eying Joe's preparations so wistfully, and keeping up such an
+ominous silence. Presently, without a parting word, Joe began to wade
+off toward the Illinois shore. Tom's heart began to sink. He glanced at
+Huck. Huck could not bear the look, and dropped his eyes. Then he said:
+
+"I want to go, too, Tom. It was getting so lonesome anyway, and now
+it'll be worse. Let's us go, too, Tom."
+
+"I won't! You can all go, if you want to. I mean to stay."
+
+"Tom, I better go."
+
+"Well, go 'long--who's hendering you."
+
+Huck began to pick up his scattered clothes. He said:
+
+"Tom, I wisht you'd come, too. Now you think it over. We'll wait for
+you when we get to shore."
+
+"Well, you'll wait a blame long time, that's all."
+
+Huck started sorrowfully away, and Tom stood looking after him, with a
+strong desire tugging at his heart to yield his pride and go along too.
+He hoped the boys would stop, but they still waded slowly on. It
+suddenly dawned on Tom that it was become very lonely and still. He
+made one final struggle with his pride, and then darted after his
+comrades, yelling:
+
+"Wait! Wait! I want to tell you something!"
+
+They presently stopped and turned around. When he got to where they
+were, he began unfolding his secret, and they listened moodily till at
+last they saw the "point" he was driving at, and then they set up a
+war-whoop of applause and said it was "splendid!" and said if he had
+told them at first, they wouldn't have started away. He made a plausible
+excuse; but his real reason had been the fear that not even the secret
+would keep them with him any very great length of time, and so he had
+meant to hold it in reserve as a last seduction.
+
+The lads came gayly back and went at their sports again with a will,
+chattering all the time about Tom's stupendous plan and admiring the
+genius of it. After a dainty egg and fish dinner, Tom said he wanted to
+learn to smoke, now. Joe caught at the idea and said he would like to
+try, too. So Huck made pipes and filled them. These novices had never
+smoked anything before but cigars made of grape-vine, and they "bit"
+the tongue, and were not considered manly anyway.
+
+Now they stretched themselves out on their elbows and began to puff,
+charily, and with slender confidence. The smoke had an unpleasant
+taste, and they gagged a little, but Tom said:
+
+"Why, it's just as easy! If I'd a knowed this was all, I'd a learnt
+long ago."
+
+"So would I," said Joe. "It's just nothing."
+
+"Why, many a time I've looked at people smoking, and thought well I
+wish I could do that; but I never thought I could," said Tom.
+
+"That's just the way with me, hain't it, Huck? You've heard me talk
+just that way--haven't you, Huck? I'll leave it to Huck if I haven't."
+
+"Yes--heaps of times," said Huck.
+
+"Well, I have too," said Tom; "oh, hundreds of times. Once down by the
+slaughter-house. Don't you remember, Huck? Bob Tanner was there, and
+Johnny Miller, and Jeff Thatcher, when I said it. Don't you remember,
+Huck, 'bout me saying that?"
+
+"Yes, that's so," said Huck. "That was the day after I lost a white
+alley. No, 'twas the day before."
+
+"There--I told you so," said Tom. "Huck recollects it."
+
+"I bleeve I could smoke this pipe all day," said Joe. "I don't feel
+sick."
+
+"Neither do I," said Tom. "I could smoke it all day. But I bet you
+Jeff Thatcher couldn't."
+
+"Jeff Thatcher! Why, he'd keel over just with two draws. Just let him
+try it once. HE'D see!"
+
+"I bet he would. And Johnny Miller--I wish could see Johnny Miller
+tackle it once."
+
+"Oh, don't I!" said Joe. "Why, I bet you Johnny Miller couldn't any
+more do this than nothing. Just one little snifter would fetch HIM."
+
+"'Deed it would, Joe. Say--I wish the boys could see us now."
+
+"So do I."
+
+"Say--boys, don't say anything about it, and some time when they're
+around, I'll come up to you and say, 'Joe, got a pipe? I want a smoke.'
+And you'll say, kind of careless like, as if it warn't anything, you'll
+say, 'Yes, I got my OLD pipe, and another one, but my tobacker ain't
+very good.' And I'll say, 'Oh, that's all right, if it's STRONG
+enough.' And then you'll out with the pipes, and we'll light up just as
+ca'm, and then just see 'em look!"
+
+"By jings, that'll be gay, Tom! I wish it was NOW!"
+
+"So do I! And when we tell 'em we learned when we was off pirating,
+won't they wish they'd been along?"
+
+"Oh, I reckon not! I'll just BET they will!"
+
+So the talk ran on. But presently it began to flag a trifle, and grow
+disjointed. The silences widened; the expectoration marvellously
+increased. Every pore inside the boys' cheeks became a spouting
+fountain; they could scarcely bail out the cellars under their tongues
+fast enough to prevent an inundation; little overflowings down their
+throats occurred in spite of all they could do, and sudden retchings
+followed every time. Both boys were looking very pale and miserable,
+now. Joe's pipe dropped from his nerveless fingers. Tom's followed.
+Both fountains were going furiously and both pumps bailing with might
+and main. Joe said feebly:
+
+"I've lost my knife. I reckon I better go and find it."
+
+Tom said, with quivering lips and halting utterance:
+
+"I'll help you. You go over that way and I'll hunt around by the
+spring. No, you needn't come, Huck--we can find it."
+
+So Huck sat down again, and waited an hour. Then he found it lonesome,
+and went to find his comrades. They were wide apart in the woods, both
+very pale, both fast asleep. But something informed him that if they
+had had any trouble they had got rid of it.
+
+They were not talkative at supper that night. They had a humble look,
+and when Huck prepared his pipe after the meal and was going to prepare
+theirs, they said no, they were not feeling very well--something they
+ate at dinner had disagreed with them.
+
+About midnight Joe awoke, and called the boys. There was a brooding
+oppressiveness in the air that seemed to bode something. The boys
+huddled themselves together and sought the friendly companionship of
+the fire, though the dull dead heat of the breathless atmosphere was
+stifling. They sat still, intent and waiting. The solemn hush
+continued. Beyond the light of the fire everything was swallowed up in
+the blackness of darkness. Presently there came a quivering glow that
+vaguely revealed the foliage for a moment and then vanished. By and by
+another came, a little stronger. Then another. Then a faint moan came
+sighing through the branches of the forest and the boys felt a fleeting
+breath upon their cheeks, and shuddered with the fancy that the Spirit
+of the Night had gone by. There was a pause. Now a weird flash turned
+night into day and showed every little grass-blade, separate and
+distinct, that grew about their feet. And it showed three white,
+startled faces, too. A deep peal of thunder went rolling and tumbling
+down the heavens and lost itself in sullen rumblings in the distance. A
+sweep of chilly air passed by, rustling all the leaves and snowing the
+flaky ashes broadcast about the fire. Another fierce glare lit up the
+forest and an instant crash followed that seemed to rend the tree-tops
+right over the boys' heads. They clung together in terror, in the thick
+gloom that followed. A few big rain-drops fell pattering upon the
+leaves.
+
+"Quick! boys, go for the tent!" exclaimed Tom.
+
+They sprang away, stumbling over roots and among vines in the dark, no
+two plunging in the same direction. A furious blast roared through the
+trees, making everything sing as it went. One blinding flash after
+another came, and peal on peal of deafening thunder. And now a
+drenching rain poured down and the rising hurricane drove it in sheets
+along the ground. The boys cried out to each other, but the roaring
+wind and the booming thunder-blasts drowned their voices utterly.
+However, one by one they straggled in at last and took shelter under
+the tent, cold, scared, and streaming with water; but to have company
+in misery seemed something to be grateful for. They could not talk, the
+old sail flapped so furiously, even if the other noises would have
+allowed them. The tempest rose higher and higher, and presently the
+sail tore loose from its fastenings and went winging away on the blast.
+The boys seized each others' hands and fled, with many tumblings and
+bruises, to the shelter of a great oak that stood upon the river-bank.
+Now the battle was at its highest. Under the ceaseless conflagration of
+lightning that flamed in the skies, everything below stood out in
+clean-cut and shadowless distinctness: the bending trees, the billowy
+river, white with foam, the driving spray of spume-flakes, the dim
+outlines of the high bluffs on the other side, glimpsed through the
+drifting cloud-rack and the slanting veil of rain. Every little while
+some giant tree yielded the fight and fell crashing through the younger
+growth; and the unflagging thunder-peals came now in ear-splitting
+explosive bursts, keen and sharp, and unspeakably appalling. The storm
+culminated in one matchless effort that seemed likely to tear the island
+to pieces, burn it up, drown it to the tree-tops, blow it away, and
+deafen every creature in it, all at one and the same moment. It was a
+wild night for homeless young heads to be out in.
+
+But at last the battle was done, and the forces retired with weaker
+and weaker threatenings and grumblings, and peace resumed her sway. The
+boys went back to camp, a good deal awed; but they found there was
+still something to be thankful for, because the great sycamore, the
+shelter of their beds, was a ruin, now, blasted by the lightnings, and
+they were not under it when the catastrophe happened.
+
+Everything in camp was drenched, the camp-fire as well; for they were
+but heedless lads, like their generation, and had made no provision
+against rain. Here was matter for dismay, for they were soaked through
+and chilled. They were eloquent in their distress; but they presently
+discovered that the fire had eaten so far up under the great log it had
+been built against (where it curved upward and separated itself from
+the ground), that a handbreadth or so of it had escaped wetting; so
+they patiently wrought until, with shreds and bark gathered from the
+under sides of sheltered logs, they coaxed the fire to burn again. Then
+they piled on great dead boughs till they had a roaring furnace, and
+were glad-hearted once more. They dried their boiled ham and had a
+feast, and after that they sat by the fire and expanded and glorified
+their midnight adventure until morning, for there was not a dry spot to
+sleep on, anywhere around.
+
+As the sun began to steal in upon the boys, drowsiness came over them,
+and they went out on the sandbar and lay down to sleep. They got
+scorched out by and by, and drearily set about getting breakfast. After
+the meal they felt rusty, and stiff-jointed, and a little homesick once
+more. Tom saw the signs, and fell to cheering up the pirates as well as
+he could. But they cared nothing for marbles, or circus, or swimming,
+or anything. He reminded them of the imposing secret, and raised a ray
+of cheer. While it lasted, he got them interested in a new device. This
+was to knock off being pirates, for a while, and be Indians for a
+change. They were attracted by this idea; so it was not long before
+they were stripped, and striped from head to heel with black mud, like
+so many zebras--all of them chiefs, of course--and then they went
+tearing through the woods to attack an English settlement.
+
+By and by they separated into three hostile tribes, and darted upon
+each other from ambush with dreadful war-whoops, and killed and scalped
+each other by thousands. It was a gory day. Consequently it was an
+extremely satisfactory one.
+
+They assembled in camp toward supper-time, hungry and happy; but now a
+difficulty arose--hostile Indians could not break the bread of
+hospitality together without first making peace, and this was a simple
+impossibility without smoking a pipe of peace. There was no other
+process that ever they had heard of. Two of the savages almost wished
+they had remained pirates. However, there was no other way; so with
+such show of cheerfulness as they could muster they called for the pipe
+and took their whiff as it passed, in due form.
+
+And behold, they were glad they had gone into savagery, for they had
+gained something; they found that they could now smoke a little without
+having to go and hunt for a lost knife; they did not get sick enough to
+be seriously uncomfortable. They were not likely to fool away this high
+promise for lack of effort. No, they practised cautiously, after
+supper, with right fair success, and so they spent a jubilant evening.
+They were prouder and happier in their new acquirement than they would
+have been in the scalping and skinning of the Six Nations. We will
+leave them to smoke and chatter and brag, since we have no further use
+for them at present.
+
+
+
+CHAPTER XVII
+
+BUT there was no hilarity in the little town that same tranquil
+Saturday afternoon. The Harpers, and Aunt Polly's family, were being
+put into mourning, with great grief and many tears. An unusual quiet
+possessed the village, although it was ordinarily quiet enough, in all
+conscience. The villagers conducted their concerns with an absent air,
+and talked little; but they sighed often. The Saturday holiday seemed a
+burden to the children. They had no heart in their sports, and
+gradually gave them up.
+
+In the afternoon Becky Thatcher found herself moping about the
+deserted schoolhouse yard, and feeling very melancholy. But she found
+nothing there to comfort her. She soliloquized:
+
+"Oh, if I only had a brass andiron-knob again! But I haven't got
+anything now to remember him by." And she choked back a little sob.
+
+Presently she stopped, and said to herself:
+
+"It was right here. Oh, if it was to do over again, I wouldn't say
+that--I wouldn't say it for the whole world. But he's gone now; I'll
+never, never, never see him any more."
+
+This thought broke her down, and she wandered away, with tears rolling
+down her cheeks. Then quite a group of boys and girls--playmates of
+Tom's and Joe's--came by, and stood looking over the paling fence and
+talking in reverent tones of how Tom did so-and-so the last time they
+saw him, and how Joe said this and that small trifle (pregnant with
+awful prophecy, as they could easily see now!)--and each speaker
+pointed out the exact spot where the lost lads stood at the time, and
+then added something like "and I was a-standing just so--just as I am
+now, and as if you was him--I was as close as that--and he smiled, just
+this way--and then something seemed to go all over me, like--awful, you
+know--and I never thought what it meant, of course, but I can see now!"
+
+Then there was a dispute about who saw the dead boys last in life, and
+many claimed that dismal distinction, and offered evidences, more or
+less tampered with by the witness; and when it was ultimately decided
+who DID see the departed last, and exchanged the last words with them,
+the lucky parties took upon themselves a sort of sacred importance, and
+were gaped at and envied by all the rest. One poor chap, who had no
+other grandeur to offer, said with tolerably manifest pride in the
+remembrance:
+
+"Well, Tom Sawyer he licked me once."
+
+But that bid for glory was a failure. Most of the boys could say that,
+and so that cheapened the distinction too much. The group loitered
+away, still recalling memories of the lost heroes, in awed voices.
+
+When the Sunday-school hour was finished, the next morning, the bell
+began to toll, instead of ringing in the usual way. It was a very still
+Sabbath, and the mournful sound seemed in keeping with the musing hush
+that lay upon nature. The villagers began to gather, loitering a moment
+in the vestibule to converse in whispers about the sad event. But there
+was no whispering in the house; only the funereal rustling of dresses
+as the women gathered to their seats disturbed the silence there. None
+could remember when the little church had been so full before. There
+was finally a waiting pause, an expectant dumbness, and then Aunt Polly
+entered, followed by Sid and Mary, and they by the Harper family, all
+in deep black, and the whole congregation, the old minister as well,
+rose reverently and stood until the mourners were seated in the front
+pew. There was another communing silence, broken at intervals by
+muffled sobs, and then the minister spread his hands abroad and prayed.
+A moving hymn was sung, and the text followed: "I am the Resurrection
+and the Life."
+
+As the service proceeded, the clergyman drew such pictures of the
+graces, the winning ways, and the rare promise of the lost lads that
+every soul there, thinking he recognized these pictures, felt a pang in
+remembering that he had persistently blinded himself to them always
+before, and had as persistently seen only faults and flaws in the poor
+boys. The minister related many a touching incident in the lives of the
+departed, too, which illustrated their sweet, generous natures, and the
+people could easily see, now, how noble and beautiful those episodes
+were, and remembered with grief that at the time they occurred they had
+seemed rank rascalities, well deserving of the cowhide. The
+congregation became more and more moved, as the pathetic tale went on,
+till at last the whole company broke down and joined the weeping
+mourners in a chorus of anguished sobs, the preacher himself giving way
+to his feelings, and crying in the pulpit.
+
+There was a rustle in the gallery, which nobody noticed; a moment
+later the church door creaked; the minister raised his streaming eyes
+above his handkerchief, and stood transfixed! First one and then
+another pair of eyes followed the minister's, and then almost with one
+impulse the congregation rose and stared while the three dead boys came
+marching up the aisle, Tom in the lead, Joe next, and Huck, a ruin of
+drooping rags, sneaking sheepishly in the rear! They had been hid in
+the unused gallery listening to their own funeral sermon!
+
+Aunt Polly, Mary, and the Harpers threw themselves upon their restored
+ones, smothered them with kisses and poured out thanksgivings, while
+poor Huck stood abashed and uncomfortable, not knowing exactly what to
+do or where to hide from so many unwelcoming eyes. He wavered, and
+started to slink away, but Tom seized him and said:
+
+"Aunt Polly, it ain't fair. Somebody's got to be glad to see Huck."
+
+"And so they shall. I'm glad to see him, poor motherless thing!" And
+the loving attentions Aunt Polly lavished upon him were the one thing
+capable of making him more uncomfortable than he was before.
+
+Suddenly the minister shouted at the top of his voice: "Praise God
+from whom all blessings flow--SING!--and put your hearts in it!"
+
+And they did. Old Hundred swelled up with a triumphant burst, and
+while it shook the rafters Tom Sawyer the Pirate looked around upon the
+envying juveniles about him and confessed in his heart that this was
+the proudest moment of his life.
+
+As the "sold" congregation trooped out they said they would almost be
+willing to be made ridiculous again to hear Old Hundred sung like that
+once more.
+
+Tom got more cuffs and kisses that day--according to Aunt Polly's
+varying moods--than he had earned before in a year; and he hardly knew
+which expressed the most gratefulness to God and affection for himself.
+
+
+
+CHAPTER XVIII
+
+THAT was Tom's great secret--the scheme to return home with his
+brother pirates and attend their own funerals. They had paddled over to
+the Missouri shore on a log, at dusk on Saturday, landing five or six
+miles below the village; they had slept in the woods at the edge of the
+town till nearly daylight, and had then crept through back lanes and
+alleys and finished their sleep in the gallery of the church among a
+chaos of invalided benches.
+
+At breakfast, Monday morning, Aunt Polly and Mary were very loving to
+Tom, and very attentive to his wants. There was an unusual amount of
+talk. In the course of it Aunt Polly said:
+
+"Well, I don't say it wasn't a fine joke, Tom, to keep everybody
+suffering 'most a week so you boys had a good time, but it is a pity
+you could be so hard-hearted as to let me suffer so. If you could come
+over on a log to go to your funeral, you could have come over and give
+me a hint some way that you warn't dead, but only run off."
+
+"Yes, you could have done that, Tom," said Mary; "and I believe you
+would if you had thought of it."
+
+"Would you, Tom?" said Aunt Polly, her face lighting wistfully. "Say,
+now, would you, if you'd thought of it?"
+
+"I--well, I don't know. 'Twould 'a' spoiled everything."
+
+"Tom, I hoped you loved me that much," said Aunt Polly, with a grieved
+tone that discomforted the boy. "It would have been something if you'd
+cared enough to THINK of it, even if you didn't DO it."
+
+"Now, auntie, that ain't any harm," pleaded Mary; "it's only Tom's
+giddy way--he is always in such a rush that he never thinks of
+anything."
+
+"More's the pity. Sid would have thought. And Sid would have come and
+DONE it, too. Tom, you'll look back, some day, when it's too late, and
+wish you'd cared a little more for me when it would have cost you so
+little."
+
+"Now, auntie, you know I do care for you," said Tom.
+
+"I'd know it better if you acted more like it."
+
+"I wish now I'd thought," said Tom, with a repentant tone; "but I
+dreamt about you, anyway. That's something, ain't it?"
+
+"It ain't much--a cat does that much--but it's better than nothing.
+What did you dream?"
+
+"Why, Wednesday night I dreamt that you was sitting over there by the
+bed, and Sid was sitting by the woodbox, and Mary next to him."
+
+"Well, so we did. So we always do. I'm glad your dreams could take
+even that much trouble about us."
+
+"And I dreamt that Joe Harper's mother was here."
+
+"Why, she was here! Did you dream any more?"
+
+"Oh, lots. But it's so dim, now."
+
+"Well, try to recollect--can't you?"
+
+"Somehow it seems to me that the wind--the wind blowed the--the--"
+
+"Try harder, Tom! The wind did blow something. Come!"
+
+Tom pressed his fingers on his forehead an anxious minute, and then
+said:
+
+"I've got it now! I've got it now! It blowed the candle!"
+
+"Mercy on us! Go on, Tom--go on!"
+
+"And it seems to me that you said, 'Why, I believe that that door--'"
+
+"Go ON, Tom!"
+
+"Just let me study a moment--just a moment. Oh, yes--you said you
+believed the door was open."
+
+"As I'm sitting here, I did! Didn't I, Mary! Go on!"
+
+"And then--and then--well I won't be certain, but it seems like as if
+you made Sid go and--and--"
+
+"Well? Well? What did I make him do, Tom? What did I make him do?"
+
+"You made him--you--Oh, you made him shut it."
+
+"Well, for the land's sake! I never heard the beat of that in all my
+days! Don't tell ME there ain't anything in dreams, any more. Sereny
+Harper shall know of this before I'm an hour older. I'd like to see her
+get around THIS with her rubbage 'bout superstition. Go on, Tom!"
+
+"Oh, it's all getting just as bright as day, now. Next you said I
+warn't BAD, only mischeevous and harum-scarum, and not any more
+responsible than--than--I think it was a colt, or something."
+
+"And so it was! Well, goodness gracious! Go on, Tom!"
+
+"And then you began to cry."
+
+"So I did. So I did. Not the first time, neither. And then--"
+
+"Then Mrs. Harper she began to cry, and said Joe was just the same,
+and she wished she hadn't whipped him for taking cream when she'd
+throwed it out her own self--"
+
+"Tom! The sperrit was upon you! You was a prophesying--that's what you
+was doing! Land alive, go on, Tom!"
+
+"Then Sid he said--he said--"
+
+"I don't think I said anything," said Sid.
+
+"Yes you did, Sid," said Mary.
+
+"Shut your heads and let Tom go on! What did he say, Tom?"
+
+"He said--I THINK he said he hoped I was better off where I was gone
+to, but if I'd been better sometimes--"
+
+"THERE, d'you hear that! It was his very words!"
+
+"And you shut him up sharp."
+
+"I lay I did! There must 'a' been an angel there. There WAS an angel
+there, somewheres!"
+
+"And Mrs. Harper told about Joe scaring her with a firecracker, and
+you told about Peter and the Painkiller--"
+
+"Just as true as I live!"
+
+"And then there was a whole lot of talk 'bout dragging the river for
+us, and 'bout having the funeral Sunday, and then you and old Miss
+Harper hugged and cried, and she went."
+
+"It happened just so! It happened just so, as sure as I'm a-sitting in
+these very tracks. Tom, you couldn't told it more like if you'd 'a'
+seen it! And then what? Go on, Tom!"
+
+"Then I thought you prayed for me--and I could see you and hear every
+word you said. And you went to bed, and I was so sorry that I took and
+wrote on a piece of sycamore bark, 'We ain't dead--we are only off
+being pirates,' and put it on the table by the candle; and then you
+looked so good, laying there asleep, that I thought I went and leaned
+over and kissed you on the lips."
+
+"Did you, Tom, DID you! I just forgive you everything for that!" And
+she seized the boy in a crushing embrace that made him feel like the
+guiltiest of villains.
+
+"It was very kind, even though it was only a--dream," Sid soliloquized
+just audibly.
+
+"Shut up, Sid! A body does just the same in a dream as he'd do if he
+was awake. Here's a big Milum apple I've been saving for you, Tom, if
+you was ever found again--now go 'long to school. I'm thankful to the
+good God and Father of us all I've got you back, that's long-suffering
+and merciful to them that believe on Him and keep His word, though
+goodness knows I'm unworthy of it, but if only the worthy ones got His
+blessings and had His hand to help them over the rough places, there's
+few enough would smile here or ever enter into His rest when the long
+night comes. Go 'long Sid, Mary, Tom--take yourselves off--you've
+hendered me long enough."
+
+The children left for school, and the old lady to call on Mrs. Harper
+and vanquish her realism with Tom's marvellous dream. Sid had better
+judgment than to utter the thought that was in his mind as he left the
+house. It was this: "Pretty thin--as long a dream as that, without any
+mistakes in it!"
+
+What a hero Tom was become, now! He did not go skipping and prancing,
+but moved with a dignified swagger as became a pirate who felt that the
+public eye was on him. And indeed it was; he tried not to seem to see
+the looks or hear the remarks as he passed along, but they were food
+and drink to him. Smaller boys than himself flocked at his heels, as
+proud to be seen with him, and tolerated by him, as if he had been the
+drummer at the head of a procession or the elephant leading a menagerie
+into town. Boys of his own size pretended not to know he had been away
+at all; but they were consuming with envy, nevertheless. They would
+have given anything to have that swarthy suntanned skin of his, and his
+glittering notoriety; and Tom would not have parted with either for a
+circus.
+
+At school the children made so much of him and of Joe, and delivered
+such eloquent admiration from their eyes, that the two heroes were not
+long in becoming insufferably "stuck-up." They began to tell their
+adventures to hungry listeners--but they only began; it was not a thing
+likely to have an end, with imaginations like theirs to furnish
+material. And finally, when they got out their pipes and went serenely
+puffing around, the very summit of glory was reached.
+
+Tom decided that he could be independent of Becky Thatcher now. Glory
+was sufficient. He would live for glory. Now that he was distinguished,
+maybe she would be wanting to "make up." Well, let her--she should see
+that he could be as indifferent as some other people. Presently she
+arrived. Tom pretended not to see her. He moved away and joined a group
+of boys and girls and began to talk. Soon he observed that she was
+tripping gayly back and forth with flushed face and dancing eyes,
+pretending to be busy chasing schoolmates, and screaming with laughter
+when she made a capture; but he noticed that she always made her
+captures in his vicinity, and that she seemed to cast a conscious eye
+in his direction at such times, too. It gratified all the vicious
+vanity that was in him; and so, instead of winning him, it only "set
+him up" the more and made him the more diligent to avoid betraying that
+he knew she was about. Presently she gave over skylarking, and moved
+irresolutely about, sighing once or twice and glancing furtively and
+wistfully toward Tom. Then she observed that now Tom was talking more
+particularly to Amy Lawrence than to any one else. She felt a sharp
+pang and grew disturbed and uneasy at once. She tried to go away, but
+her feet were treacherous, and carried her to the group instead. She
+said to a girl almost at Tom's elbow--with sham vivacity:
+
+"Why, Mary Austin! you bad girl, why didn't you come to Sunday-school?"
+
+"I did come--didn't you see me?"
+
+"Why, no! Did you? Where did you sit?"
+
+"I was in Miss Peters' class, where I always go. I saw YOU."
+
+"Did you? Why, it's funny I didn't see you. I wanted to tell you about
+the picnic."
+
+"Oh, that's jolly. Who's going to give it?"
+
+"My ma's going to let me have one."
+
+"Oh, goody; I hope she'll let ME come."
+
+"Well, she will. The picnic's for me. She'll let anybody come that I
+want, and I want you."
+
+"That's ever so nice. When is it going to be?"
+
+"By and by. Maybe about vacation."
+
+"Oh, won't it be fun! You going to have all the girls and boys?"
+
+"Yes, every one that's friends to me--or wants to be"; and she glanced
+ever so furtively at Tom, but he talked right along to Amy Lawrence
+about the terrible storm on the island, and how the lightning tore the
+great sycamore tree "all to flinders" while he was "standing within
+three feet of it."
+
+"Oh, may I come?" said Grace Miller.
+
+"Yes."
+
+"And me?" said Sally Rogers.
+
+"Yes."
+
+"And me, too?" said Susy Harper. "And Joe?"
+
+"Yes."
+
+And so on, with clapping of joyful hands till all the group had begged
+for invitations but Tom and Amy. Then Tom turned coolly away, still
+talking, and took Amy with him. Becky's lips trembled and the tears
+came to her eyes; she hid these signs with a forced gayety and went on
+chattering, but the life had gone out of the picnic, now, and out of
+everything else; she got away as soon as she could and hid herself and
+had what her sex call "a good cry." Then she sat moody, with wounded
+pride, till the bell rang. She roused up, now, with a vindictive cast
+in her eye, and gave her plaited tails a shake and said she knew what
+SHE'D do.
+
+At recess Tom continued his flirtation with Amy with jubilant
+self-satisfaction. And he kept drifting about to find Becky and lacerate
+her with the performance. At last he spied her, but there was a sudden
+falling of his mercury. She was sitting cosily on a little bench behind
+the schoolhouse looking at a picture-book with Alfred Temple--and so
+absorbed were they, and their heads so close together over the book,
+that they did not seem to be conscious of anything in the world besides.
+Jealousy ran red-hot through Tom's veins. He began to hate himself for
+throwing away the chance Becky had offered for a reconciliation. He
+called himself a fool, and all the hard names he could think of. He
+wanted to cry with vexation. Amy chatted happily along, as they walked,
+for her heart was singing, but Tom's tongue had lost its function. He
+did not hear what Amy was saying, and whenever she paused expectantly he
+could only stammer an awkward assent, which was as often misplaced as
+otherwise. He kept drifting to the rear of the schoolhouse, again and
+again, to sear his eyeballs with the hateful spectacle there. He could
+not help it. And it maddened him to see, as he thought he saw, that
+Becky Thatcher never once suspected that he was even in the land of the
+living. But she did see, nevertheless; and she knew she was winning her
+fight, too, and was glad to see him suffer as she had suffered.
+
+Amy's happy prattle became intolerable. Tom hinted at things he had to
+attend to; things that must be done; and time was fleeting. But in
+vain--the girl chirped on. Tom thought, "Oh, hang her, ain't I ever
+going to get rid of her?" At last he must be attending to those
+things--and she said artlessly that she would be "around" when school
+let out. And he hastened away, hating her for it.
+
+"Any other boy!" Tom thought, grating his teeth. "Any boy in the whole
+town but that Saint Louis smarty that thinks he dresses so fine and is
+aristocracy! Oh, all right, I licked you the first day you ever saw
+this town, mister, and I'll lick you again! You just wait till I catch
+you out! I'll just take and--"
+
+And he went through the motions of thrashing an imaginary boy
+--pummelling the air, and kicking and gouging. "Oh, you do, do you? You
+holler 'nough, do you? Now, then, let that learn you!" And so the
+imaginary flogging was finished to his satisfaction.
+
+Tom fled home at noon. His conscience could not endure any more of
+Amy's grateful happiness, and his jealousy could bear no more of the
+other distress. Becky resumed her picture inspections with Alfred, but
+as the minutes dragged along and no Tom came to suffer, her triumph
+began to cloud and she lost interest; gravity and absent-mindedness
+followed, and then melancholy; two or three times she pricked up her
+ear at a footstep, but it was a false hope; no Tom came. At last she
+grew entirely miserable and wished she hadn't carried it so far. When
+poor Alfred, seeing that he was losing her, he did not know how, kept
+exclaiming: "Oh, here's a jolly one! look at this!" she lost patience
+at last, and said, "Oh, don't bother me! I don't care for them!" and
+burst into tears, and got up and walked away.
+
+Alfred dropped alongside and was going to try to comfort her, but she
+said:
+
+"Go away and leave me alone, can't you! I hate you!"
+
+So the boy halted, wondering what he could have done--for she had said
+she would look at pictures all through the nooning--and she walked on,
+crying. Then Alfred went musing into the deserted schoolhouse. He was
+humiliated and angry. He easily guessed his way to the truth--the girl
+had simply made a convenience of him to vent her spite upon Tom Sawyer.
+He was far from hating Tom the less when this thought occurred to him.
+He wished there was some way to get that boy into trouble without much
+risk to himself. Tom's spelling-book fell under his eye. Here was his
+opportunity. He gratefully opened to the lesson for the afternoon and
+poured ink upon the page.
+
+Becky, glancing in at a window behind him at the moment, saw the act,
+and moved on, without discovering herself. She started homeward, now,
+intending to find Tom and tell him; Tom would be thankful and their
+troubles would be healed. Before she was half way home, however, she
+had changed her mind. The thought of Tom's treatment of her when she
+was talking about her picnic came scorching back and filled her with
+shame. She resolved to let him get whipped on the damaged
+spelling-book's account, and to hate him forever, into the bargain.
+
+
+
+CHAPTER XIX
+
+TOM arrived at home in a dreary mood, and the first thing his aunt
+said to him showed him that he had brought his sorrows to an
+unpromising market:
+
+"Tom, I've a notion to skin you alive!"
+
+"Auntie, what have I done?"
+
+"Well, you've done enough. Here I go over to Sereny Harper, like an
+old softy, expecting I'm going to make her believe all that rubbage
+about that dream, when lo and behold you she'd found out from Joe that
+you was over here and heard all the talk we had that night. Tom, I
+don't know what is to become of a boy that will act like that. It makes
+me feel so bad to think you could let me go to Sereny Harper and make
+such a fool of myself and never say a word."
+
+This was a new aspect of the thing. His smartness of the morning had
+seemed to Tom a good joke before, and very ingenious. It merely looked
+mean and shabby now. He hung his head and could not think of anything
+to say for a moment. Then he said:
+
+"Auntie, I wish I hadn't done it--but I didn't think."
+
+"Oh, child, you never think. You never think of anything but your own
+selfishness. You could think to come all the way over here from
+Jackson's Island in the night to laugh at our troubles, and you could
+think to fool me with a lie about a dream; but you couldn't ever think
+to pity us and save us from sorrow."
+
+"Auntie, I know now it was mean, but I didn't mean to be mean. I
+didn't, honest. And besides, I didn't come over here to laugh at you
+that night."
+
+"What did you come for, then?"
+
+"It was to tell you not to be uneasy about us, because we hadn't got
+drownded."
+
+"Tom, Tom, I would be the thankfullest soul in this world if I could
+believe you ever had as good a thought as that, but you know you never
+did--and I know it, Tom."
+
+"Indeed and 'deed I did, auntie--I wish I may never stir if I didn't."
+
+"Oh, Tom, don't lie--don't do it. It only makes things a hundred times
+worse."
+
+"It ain't a lie, auntie; it's the truth. I wanted to keep you from
+grieving--that was all that made me come."
+
+"I'd give the whole world to believe that--it would cover up a power
+of sins, Tom. I'd 'most be glad you'd run off and acted so bad. But it
+ain't reasonable; because, why didn't you tell me, child?"
+
+"Why, you see, when you got to talking about the funeral, I just got
+all full of the idea of our coming and hiding in the church, and I
+couldn't somehow bear to spoil it. So I just put the bark back in my
+pocket and kept mum."
+
+"What bark?"
+
+"The bark I had wrote on to tell you we'd gone pirating. I wish, now,
+you'd waked up when I kissed you--I do, honest."
+
+The hard lines in his aunt's face relaxed and a sudden tenderness
+dawned in her eyes.
+
+"DID you kiss me, Tom?"
+
+"Why, yes, I did."
+
+"Are you sure you did, Tom?"
+
+"Why, yes, I did, auntie--certain sure."
+
+"What did you kiss me for, Tom?"
+
+"Because I loved you so, and you laid there moaning and I was so sorry."
+
+The words sounded like truth. The old lady could not hide a tremor in
+her voice when she said:
+
+"Kiss me again, Tom!--and be off with you to school, now, and don't
+bother me any more."
+
+The moment he was gone, she ran to a closet and got out the ruin of a
+jacket which Tom had gone pirating in. Then she stopped, with it in her
+hand, and said to herself:
+
+"No, I don't dare. Poor boy, I reckon he's lied about it--but it's a
+blessed, blessed lie, there's such a comfort come from it. I hope the
+Lord--I KNOW the Lord will forgive him, because it was such
+goodheartedness in him to tell it. But I don't want to find out it's a
+lie. I won't look."
+
+She put the jacket away, and stood by musing a minute. Twice she put
+out her hand to take the garment again, and twice she refrained. Once
+more she ventured, and this time she fortified herself with the
+thought: "It's a good lie--it's a good lie--I won't let it grieve me."
+So she sought the jacket pocket. A moment later she was reading Tom's
+piece of bark through flowing tears and saying: "I could forgive the
+boy, now, if he'd committed a million sins!"
+
+
+
+CHAPTER XX
+
+THERE was something about Aunt Polly's manner, when she kissed Tom,
+that swept away his low spirits and made him lighthearted and happy
+again. He started to school and had the luck of coming upon Becky
+Thatcher at the head of Meadow Lane. His mood always determined his
+manner. Without a moment's hesitation he ran to her and said:
+
+"I acted mighty mean to-day, Becky, and I'm so sorry. I won't ever,
+ever do that way again, as long as ever I live--please make up, won't
+you?"
+
+The girl stopped and looked him scornfully in the face:
+
+"I'll thank you to keep yourself TO yourself, Mr. Thomas Sawyer. I'll
+never speak to you again."
+
+She tossed her head and passed on. Tom was so stunned that he had not
+even presence of mind enough to say "Who cares, Miss Smarty?" until the
+right time to say it had gone by. So he said nothing. But he was in a
+fine rage, nevertheless. He moped into the schoolyard wishing she were
+a boy, and imagining how he would trounce her if she were. He presently
+encountered her and delivered a stinging remark as he passed. She
+hurled one in return, and the angry breach was complete. It seemed to
+Becky, in her hot resentment, that she could hardly wait for school to
+"take in," she was so impatient to see Tom flogged for the injured
+spelling-book. If she had had any lingering notion of exposing Alfred
+Temple, Tom's offensive fling had driven it entirely away.
+
+Poor girl, she did not know how fast she was nearing trouble herself.
+The master, Mr. Dobbins, had reached middle age with an unsatisfied
+ambition. The darling of his desires was, to be a doctor, but poverty
+had decreed that he should be nothing higher than a village
+schoolmaster. Every day he took a mysterious book out of his desk and
+absorbed himself in it at times when no classes were reciting. He kept
+that book under lock and key. There was not an urchin in school but was
+perishing to have a glimpse of it, but the chance never came. Every boy
+and girl had a theory about the nature of that book; but no two
+theories were alike, and there was no way of getting at the facts in
+the case. Now, as Becky was passing by the desk, which stood near the
+door, she noticed that the key was in the lock! It was a precious
+moment. She glanced around; found herself alone, and the next instant
+she had the book in her hands. The title-page--Professor Somebody's
+ANATOMY--carried no information to her mind; so she began to turn the
+leaves. She came at once upon a handsomely engraved and colored
+frontispiece--a human figure, stark naked. At that moment a shadow fell
+on the page and Tom Sawyer stepped in at the door and caught a glimpse
+of the picture. Becky snatched at the book to close it, and had the
+hard luck to tear the pictured page half down the middle. She thrust
+the volume into the desk, turned the key, and burst out crying with
+shame and vexation.
+
+"Tom Sawyer, you are just as mean as you can be, to sneak up on a
+person and look at what they're looking at."
+
+"How could I know you was looking at anything?"
+
+"You ought to be ashamed of yourself, Tom Sawyer; you know you're
+going to tell on me, and oh, what shall I do, what shall I do! I'll be
+whipped, and I never was whipped in school."
+
+Then she stamped her little foot and said:
+
+"BE so mean if you want to! I know something that's going to happen.
+You just wait and you'll see! Hateful, hateful, hateful!"--and she
+flung out of the house with a new explosion of crying.
+
+Tom stood still, rather flustered by this onslaught. Presently he said
+to himself:
+
+"What a curious kind of a fool a girl is! Never been licked in school!
+Shucks! What's a licking! That's just like a girl--they're so
+thin-skinned and chicken-hearted. Well, of course I ain't going to tell
+old Dobbins on this little fool, because there's other ways of getting
+even on her, that ain't so mean; but what of it? Old Dobbins will ask
+who it was tore his book. Nobody'll answer. Then he'll do just the way
+he always does--ask first one and then t'other, and when he comes to the
+right girl he'll know it, without any telling. Girls' faces always tell
+on them. They ain't got any backbone. She'll get licked. Well, it's a
+kind of a tight place for Becky Thatcher, because there ain't any way
+out of it." Tom conned the thing a moment longer, and then added: "All
+right, though; she'd like to see me in just such a fix--let her sweat it
+out!"
+
+Tom joined the mob of skylarking scholars outside. In a few moments
+the master arrived and school "took in." Tom did not feel a strong
+interest in his studies. Every time he stole a glance at the girls'
+side of the room Becky's face troubled him. Considering all things, he
+did not want to pity her, and yet it was all he could do to help it. He
+could get up no exultation that was really worthy the name. Presently
+the spelling-book discovery was made, and Tom's mind was entirely full
+of his own matters for a while after that. Becky roused up from her
+lethargy of distress and showed good interest in the proceedings. She
+did not expect that Tom could get out of his trouble by denying that he
+spilt the ink on the book himself; and she was right. The denial only
+seemed to make the thing worse for Tom. Becky supposed she would be
+glad of that, and she tried to believe she was glad of it, but she
+found she was not certain. When the worst came to the worst, she had an
+impulse to get up and tell on Alfred Temple, but she made an effort and
+forced herself to keep still--because, said she to herself, "he'll tell
+about me tearing the picture sure. I wouldn't say a word, not to save
+his life!"
+
+Tom took his whipping and went back to his seat not at all
+broken-hearted, for he thought it was possible that he had unknowingly
+upset the ink on the spelling-book himself, in some skylarking bout--he
+had denied it for form's sake and because it was custom, and had stuck
+to the denial from principle.
+
+A whole hour drifted by, the master sat nodding in his throne, the air
+was drowsy with the hum of study. By and by, Mr. Dobbins straightened
+himself up, yawned, then unlocked his desk, and reached for his book,
+but seemed undecided whether to take it out or leave it. Most of the
+pupils glanced up languidly, but there were two among them that watched
+his movements with intent eyes. Mr. Dobbins fingered his book absently
+for a while, then took it out and settled himself in his chair to read!
+Tom shot a glance at Becky. He had seen a hunted and helpless rabbit
+look as she did, with a gun levelled at its head. Instantly he forgot
+his quarrel with her. Quick--something must be done! done in a flash,
+too! But the very imminence of the emergency paralyzed his invention.
+Good!--he had an inspiration! He would run and snatch the book, spring
+through the door and fly. But his resolution shook for one little
+instant, and the chance was lost--the master opened the volume. If Tom
+only had the wasted opportunity back again! Too late. There was no help
+for Becky now, he said. The next moment the master faced the school.
+Every eye sank under his gaze. There was that in it which smote even
+the innocent with fear. There was silence while one might count ten
+--the master was gathering his wrath. Then he spoke: "Who tore this book?"
+
+There was not a sound. One could have heard a pin drop. The stillness
+continued; the master searched face after face for signs of guilt.
+
+"Benjamin Rogers, did you tear this book?"
+
+A denial. Another pause.
+
+"Joseph Harper, did you?"
+
+Another denial. Tom's uneasiness grew more and more intense under the
+slow torture of these proceedings. The master scanned the ranks of
+boys--considered a while, then turned to the girls:
+
+"Amy Lawrence?"
+
+A shake of the head.
+
+"Gracie Miller?"
+
+The same sign.
+
+"Susan Harper, did you do this?"
+
+Another negative. The next girl was Becky Thatcher. Tom was trembling
+from head to foot with excitement and a sense of the hopelessness of
+the situation.
+
+"Rebecca Thatcher" [Tom glanced at her face--it was white with terror]
+--"did you tear--no, look me in the face" [her hands rose in appeal]
+--"did you tear this book?"
+
+A thought shot like lightning through Tom's brain. He sprang to his
+feet and shouted--"I done it!"
+
+The school stared in perplexity at this incredible folly. Tom stood a
+moment, to gather his dismembered faculties; and when he stepped
+forward to go to his punishment the surprise, the gratitude, the
+adoration that shone upon him out of poor Becky's eyes seemed pay
+enough for a hundred floggings. Inspired by the splendor of his own
+act, he took without an outcry the most merciless flaying that even Mr.
+Dobbins had ever administered; and also received with indifference the
+added cruelty of a command to remain two hours after school should be
+dismissed--for he knew who would wait for him outside till his
+captivity was done, and not count the tedious time as loss, either.
+
+Tom went to bed that night planning vengeance against Alfred Temple;
+for with shame and repentance Becky had told him all, not forgetting
+her own treachery; but even the longing for vengeance had to give way,
+soon, to pleasanter musings, and he fell asleep at last with Becky's
+latest words lingering dreamily in his ear--
+
+"Tom, how COULD you be so noble!"
+
+
+
+CHAPTER XXI
+
+VACATION was approaching. The schoolmaster, always severe, grew
+severer and more exacting than ever, for he wanted the school to make a
+good showing on "Examination" day. His rod and his ferule were seldom
+idle now--at least among the smaller pupils. Only the biggest boys, and
+young ladies of eighteen and twenty, escaped lashing. Mr. Dobbins'
+lashings were very vigorous ones, too; for although he carried, under
+his wig, a perfectly bald and shiny head, he had only reached middle
+age, and there was no sign of feebleness in his muscle. As the great
+day approached, all the tyranny that was in him came to the surface; he
+seemed to take a vindictive pleasure in punishing the least
+shortcomings. The consequence was, that the smaller boys spent their
+days in terror and suffering and their nights in plotting revenge. They
+threw away no opportunity to do the master a mischief. But he kept
+ahead all the time. The retribution that followed every vengeful
+success was so sweeping and majestic that the boys always retired from
+the field badly worsted. At last they conspired together and hit upon a
+plan that promised a dazzling victory. They swore in the sign-painter's
+boy, told him the scheme, and asked his help. He had his own reasons
+for being delighted, for the master boarded in his father's family and
+had given the boy ample cause to hate him. The master's wife would go
+on a visit to the country in a few days, and there would be nothing to
+interfere with the plan; the master always prepared himself for great
+occasions by getting pretty well fuddled, and the sign-painter's boy
+said that when the dominie had reached the proper condition on
+Examination Evening he would "manage the thing" while he napped in his
+chair; then he would have him awakened at the right time and hurried
+away to school.
+
+In the fulness of time the interesting occasion arrived. At eight in
+the evening the schoolhouse was brilliantly lighted, and adorned with
+wreaths and festoons of foliage and flowers. The master sat throned in
+his great chair upon a raised platform, with his blackboard behind him.
+He was looking tolerably mellow. Three rows of benches on each side and
+six rows in front of him were occupied by the dignitaries of the town
+and by the parents of the pupils. To his left, back of the rows of
+citizens, was a spacious temporary platform upon which were seated the
+scholars who were to take part in the exercises of the evening; rows of
+small boys, washed and dressed to an intolerable state of discomfort;
+rows of gawky big boys; snowbanks of girls and young ladies clad in
+lawn and muslin and conspicuously conscious of their bare arms, their
+grandmothers' ancient trinkets, their bits of pink and blue ribbon and
+the flowers in their hair. All the rest of the house was filled with
+non-participating scholars.
+
+The exercises began. A very little boy stood up and sheepishly
+recited, "You'd scarce expect one of my age to speak in public on the
+stage," etc.--accompanying himself with the painfully exact and
+spasmodic gestures which a machine might have used--supposing the
+machine to be a trifle out of order. But he got through safely, though
+cruelly scared, and got a fine round of applause when he made his
+manufactured bow and retired.
+
+A little shamefaced girl lisped, "Mary had a little lamb," etc.,
+performed a compassion-inspiring curtsy, got her meed of applause, and
+sat down flushed and happy.
+
+Tom Sawyer stepped forward with conceited confidence and soared into
+the unquenchable and indestructible "Give me liberty or give me death"
+speech, with fine fury and frantic gesticulation, and broke down in the
+middle of it. A ghastly stage-fright seized him, his legs quaked under
+him and he was like to choke. True, he had the manifest sympathy of the
+house but he had the house's silence, too, which was even worse than
+its sympathy. The master frowned, and this completed the disaster. Tom
+struggled awhile and then retired, utterly defeated. There was a weak
+attempt at applause, but it died early.
+
+"The Boy Stood on the Burning Deck" followed; also "The Assyrian Came
+Down," and other declamatory gems. Then there were reading exercises,
+and a spelling fight. The meagre Latin class recited with honor. The
+prime feature of the evening was in order, now--original "compositions"
+by the young ladies. Each in her turn stepped forward to the edge of
+the platform, cleared her throat, held up her manuscript (tied with
+dainty ribbon), and proceeded to read, with labored attention to
+"expression" and punctuation. The themes were the same that had been
+illuminated upon similar occasions by their mothers before them, their
+grandmothers, and doubtless all their ancestors in the female line
+clear back to the Crusades. "Friendship" was one; "Memories of Other
+Days"; "Religion in History"; "Dream Land"; "The Advantages of
+Culture"; "Forms of Political Government Compared and Contrasted";
+"Melancholy"; "Filial Love"; "Heart Longings," etc., etc.
+
+A prevalent feature in these compositions was a nursed and petted
+melancholy; another was a wasteful and opulent gush of "fine language";
+another was a tendency to lug in by the ears particularly prized words
+and phrases until they were worn entirely out; and a peculiarity that
+conspicuously marked and marred them was the inveterate and intolerable
+sermon that wagged its crippled tail at the end of each and every one
+of them. No matter what the subject might be, a brain-racking effort
+was made to squirm it into some aspect or other that the moral and
+religious mind could contemplate with edification. The glaring
+insincerity of these sermons was not sufficient to compass the
+banishment of the fashion from the schools, and it is not sufficient
+to-day; it never will be sufficient while the world stands, perhaps.
+There is no school in all our land where the young ladies do not feel
+obliged to close their compositions with a sermon; and you will find
+that the sermon of the most frivolous and the least religious girl in
+the school is always the longest and the most relentlessly pious. But
+enough of this. Homely truth is unpalatable.
+
+Let us return to the "Examination." The first composition that was
+read was one entitled "Is this, then, Life?" Perhaps the reader can
+endure an extract from it:
+
+  "In the common walks of life, with what delightful
+   emotions does the youthful mind look forward to some
+   anticipated scene of festivity! Imagination is busy
+   sketching rose-tinted pictures of joy. In fancy, the
+   voluptuous votary of fashion sees herself amid the
+   festive throng, 'the observed of all observers.' Her
+   graceful form, arrayed in snowy robes, is whirling
+   through the mazes of the joyous dance; her eye is
+   brightest, her step is lightest in the gay assembly.
+
+  "In such delicious fancies time quickly glides by,
+   and the welcome hour arrives for her entrance into
+   the Elysian world, of which she has had such bright
+   dreams. How fairy-like does everything appear to
+   her enchanted vision! Each new scene is more charming
+   than the last. But after a while she finds that
+   beneath this goodly exterior, all is vanity, the
+   flattery which once charmed her soul, now grates
+   harshly upon her ear; the ball-room has lost its
+   charms; and with wasted health and imbittered heart,
+   she turns away with the conviction that earthly
+   pleasures cannot satisfy the longings of the soul!"
+
+And so forth and so on. There was a buzz of gratification from time to
+time during the reading, accompanied by whispered ejaculations of "How
+sweet!" "How eloquent!" "So true!" etc., and after the thing had closed
+with a peculiarly afflicting sermon the applause was enthusiastic.
+
+Then arose a slim, melancholy girl, whose face had the "interesting"
+paleness that comes of pills and indigestion, and read a "poem." Two
+stanzas of it will do:
+
+   "A MISSOURI MAIDEN'S FAREWELL TO ALABAMA
+
+   "Alabama, good-bye! I love thee well!
+      But yet for a while do I leave thee now!
+    Sad, yes, sad thoughts of thee my heart doth swell,
+      And burning recollections throng my brow!
+    For I have wandered through thy flowery woods;
+      Have roamed and read near Tallapoosa's stream;
+    Have listened to Tallassee's warring floods,
+      And wooed on Coosa's side Aurora's beam.
+
+   "Yet shame I not to bear an o'er-full heart,
+      Nor blush to turn behind my tearful eyes;
+    'Tis from no stranger land I now must part,
+      'Tis to no strangers left I yield these sighs.
+    Welcome and home were mine within this State,
+      Whose vales I leave--whose spires fade fast from me
+    And cold must be mine eyes, and heart, and tete,
+      When, dear Alabama! they turn cold on thee!"
+
+There were very few there who knew what "tete" meant, but the poem was
+very satisfactory, nevertheless.
+
+Next appeared a dark-complexioned, black-eyed, black-haired young
+lady, who paused an impressive moment, assumed a tragic expression, and
+began to read in a measured, solemn tone:
+
+  "A VISION
+
+   "Dark and tempestuous was night. Around the
+   throne on high not a single star quivered; but
+   the deep intonations of the heavy thunder
+   constantly vibrated upon the ear; whilst the
+   terrific lightning revelled in angry mood
+   through the cloudy chambers of heaven, seeming
+   to scorn the power exerted over its terror by
+   the illustrious Franklin! Even the boisterous
+   winds unanimously came forth from their mystic
+   homes, and blustered about as if to enhance by
+   their aid the wildness of the scene.
+
+   "At such a time, so dark, so dreary, for human
+   sympathy my very spirit sighed; but instead thereof,
+
+   "'My dearest friend, my counsellor, my comforter
+   and guide--My joy in grief, my second bliss
+   in joy,' came to my side. She moved like one of
+   those bright beings pictured in the sunny walks
+   of fancy's Eden by the romantic and young, a
+   queen of beauty unadorned save by her own
+   transcendent loveliness. So soft was her step, it
+   failed to make even a sound, and but for the
+   magical thrill imparted by her genial touch, as
+   other unobtrusive beauties, she would have glided
+   away un-perceived--unsought. A strange sadness
+   rested upon her features, like icy tears upon
+   the robe of December, as she pointed to the
+   contending elements without, and bade me contemplate
+   the two beings presented."
+
+This nightmare occupied some ten pages of manuscript and wound up with
+a sermon so destructive of all hope to non-Presbyterians that it took
+the first prize. This composition was considered to be the very finest
+effort of the evening. The mayor of the village, in delivering the
+prize to the author of it, made a warm speech in which he said that it
+was by far the most "eloquent" thing he had ever listened to, and that
+Daniel Webster himself might well be proud of it.
+
+It may be remarked, in passing, that the number of compositions in
+which the word "beauteous" was over-fondled, and human experience
+referred to as "life's page," was up to the usual average.
+
+Now the master, mellow almost to the verge of geniality, put his chair
+aside, turned his back to the audience, and began to draw a map of
+America on the blackboard, to exercise the geography class upon. But he
+made a sad business of it with his unsteady hand, and a smothered
+titter rippled over the house. He knew what the matter was, and set
+himself to right it. He sponged out lines and remade them; but he only
+distorted them more than ever, and the tittering was more pronounced.
+He threw his entire attention upon his work, now, as if determined not
+to be put down by the mirth. He felt that all eyes were fastened upon
+him; he imagined he was succeeding, and yet the tittering continued; it
+even manifestly increased. And well it might. There was a garret above,
+pierced with a scuttle over his head; and down through this scuttle
+came a cat, suspended around the haunches by a string; she had a rag
+tied about her head and jaws to keep her from mewing; as she slowly
+descended she curved upward and clawed at the string, she swung
+downward and clawed at the intangible air. The tittering rose higher
+and higher--the cat was within six inches of the absorbed teacher's
+head--down, down, a little lower, and she grabbed his wig with her
+desperate claws, clung to it, and was snatched up into the garret in an
+instant with her trophy still in her possession! And how the light did
+blaze abroad from the master's bald pate--for the sign-painter's boy
+had GILDED it!
+
+That broke up the meeting. The boys were avenged. Vacation had come.
+
+   NOTE:--The pretended "compositions" quoted in
+   this chapter are taken without alteration from a
+   volume entitled "Prose and Poetry, by a Western
+   Lady"--but they are exactly and precisely after
+   the schoolgirl pattern, and hence are much
+   happier than any mere imitations could be.
+
+
+
+CHAPTER XXII
+
+TOM joined the new order of Cadets of Temperance, being attracted by
+the showy character of their "regalia." He promised to abstain from
+smoking, chewing, and profanity as long as he remained a member. Now he
+found out a new thing--namely, that to promise not to do a thing is the
+surest way in the world to make a body want to go and do that very
+thing. Tom soon found himself tormented with a desire to drink and
+swear; the desire grew to be so intense that nothing but the hope of a
+chance to display himself in his red sash kept him from withdrawing
+from the order. Fourth of July was coming; but he soon gave that up
+--gave it up before he had worn his shackles over forty-eight hours--and
+fixed his hopes upon old Judge Frazer, justice of the peace, who was
+apparently on his deathbed and would have a big public funeral, since
+he was so high an official. During three days Tom was deeply concerned
+about the Judge's condition and hungry for news of it. Sometimes his
+hopes ran high--so high that he would venture to get out his regalia
+and practise before the looking-glass. But the Judge had a most
+discouraging way of fluctuating. At last he was pronounced upon the
+mend--and then convalescent. Tom was disgusted; and felt a sense of
+injury, too. He handed in his resignation at once--and that night the
+Judge suffered a relapse and died. Tom resolved that he would never
+trust a man like that again.
+
+The funeral was a fine thing. The Cadets paraded in a style calculated
+to kill the late member with envy. Tom was a free boy again, however
+--there was something in that. He could drink and swear, now--but found
+to his surprise that he did not want to. The simple fact that he could,
+took the desire away, and the charm of it.
+
+Tom presently wondered to find that his coveted vacation was beginning
+to hang a little heavily on his hands.
+
+He attempted a diary--but nothing happened during three days, and so
+he abandoned it.
+
+The first of all the negro minstrel shows came to town, and made a
+sensation. Tom and Joe Harper got up a band of performers and were
+happy for two days.
+
+Even the Glorious Fourth was in some sense a failure, for it rained
+hard, there was no procession in consequence, and the greatest man in
+the world (as Tom supposed), Mr. Benton, an actual United States
+Senator, proved an overwhelming disappointment--for he was not
+twenty-five feet high, nor even anywhere in the neighborhood of it.
+
+A circus came. The boys played circus for three days afterward in
+tents made of rag carpeting--admission, three pins for boys, two for
+girls--and then circusing was abandoned.
+
+A phrenologist and a mesmerizer came--and went again and left the
+village duller and drearier than ever.
+
+There were some boys-and-girls' parties, but they were so few and so
+delightful that they only made the aching voids between ache the harder.
+
+Becky Thatcher was gone to her Constantinople home to stay with her
+parents during vacation--so there was no bright side to life anywhere.
+
+The dreadful secret of the murder was a chronic misery. It was a very
+cancer for permanency and pain.
+
+Then came the measles.
+
+During two long weeks Tom lay a prisoner, dead to the world and its
+happenings. He was very ill, he was interested in nothing. When he got
+upon his feet at last and moved feebly down-town, a melancholy change
+had come over everything and every creature. There had been a
+"revival," and everybody had "got religion," not only the adults, but
+even the boys and girls. Tom went about, hoping against hope for the
+sight of one blessed sinful face, but disappointment crossed him
+everywhere. He found Joe Harper studying a Testament, and turned sadly
+away from the depressing spectacle. He sought Ben Rogers, and found him
+visiting the poor with a basket of tracts. He hunted up Jim Hollis, who
+called his attention to the precious blessing of his late measles as a
+warning. Every boy he encountered added another ton to his depression;
+and when, in desperation, he flew for refuge at last to the bosom of
+Huckleberry Finn and was received with a Scriptural quotation, his
+heart broke and he crept home and to bed realizing that he alone of all
+the town was lost, forever and forever.
+
+And that night there came on a terrific storm, with driving rain,
+awful claps of thunder and blinding sheets of lightning. He covered his
+head with the bedclothes and waited in a horror of suspense for his
+doom; for he had not the shadow of a doubt that all this hubbub was
+about him. He believed he had taxed the forbearance of the powers above
+to the extremity of endurance and that this was the result. It might
+have seemed to him a waste of pomp and ammunition to kill a bug with a
+battery of artillery, but there seemed nothing incongruous about the
+getting up such an expensive thunderstorm as this to knock the turf
+from under an insect like himself.
+
+By and by the tempest spent itself and died without accomplishing its
+object. The boy's first impulse was to be grateful, and reform. His
+second was to wait--for there might not be any more storms.
+
+The next day the doctors were back; Tom had relapsed. The three weeks
+he spent on his back this time seemed an entire age. When he got abroad
+at last he was hardly grateful that he had been spared, remembering how
+lonely was his estate, how companionless and forlorn he was. He drifted
+listlessly down the street and found Jim Hollis acting as judge in a
+juvenile court that was trying a cat for murder, in the presence of her
+victim, a bird. He found Joe Harper and Huck Finn up an alley eating a
+stolen melon. Poor lads! they--like Tom--had suffered a relapse.
+
+
+
+CHAPTER XXIII
+
+AT last the sleepy atmosphere was stirred--and vigorously: the murder
+trial came on in the court. It became the absorbing topic of village
+talk immediately. Tom could not get away from it. Every reference to
+the murder sent a shudder to his heart, for his troubled conscience and
+fears almost persuaded him that these remarks were put forth in his
+hearing as "feelers"; he did not see how he could be suspected of
+knowing anything about the murder, but still he could not be
+comfortable in the midst of this gossip. It kept him in a cold shiver
+all the time. He took Huck to a lonely place to have a talk with him.
+It would be some relief to unseal his tongue for a little while; to
+divide his burden of distress with another sufferer. Moreover, he
+wanted to assure himself that Huck had remained discreet.
+
+"Huck, have you ever told anybody about--that?"
+
+"'Bout what?"
+
+"You know what."
+
+"Oh--'course I haven't."
+
+"Never a word?"
+
+"Never a solitary word, so help me. What makes you ask?"
+
+"Well, I was afeard."
+
+"Why, Tom Sawyer, we wouldn't be alive two days if that got found out.
+YOU know that."
+
+Tom felt more comfortable. After a pause:
+
+"Huck, they couldn't anybody get you to tell, could they?"
+
+"Get me to tell? Why, if I wanted that half-breed devil to drownd me
+they could get me to tell. They ain't no different way."
+
+"Well, that's all right, then. I reckon we're safe as long as we keep
+mum. But let's swear again, anyway. It's more surer."
+
+"I'm agreed."
+
+So they swore again with dread solemnities.
+
+"What is the talk around, Huck? I've heard a power of it."
+
+"Talk? Well, it's just Muff Potter, Muff Potter, Muff Potter all the
+time. It keeps me in a sweat, constant, so's I want to hide som'ers."
+
+"That's just the same way they go on round me. I reckon he's a goner.
+Don't you feel sorry for him, sometimes?"
+
+"Most always--most always. He ain't no account; but then he hain't
+ever done anything to hurt anybody. Just fishes a little, to get money
+to get drunk on--and loafs around considerable; but lord, we all do
+that--leastways most of us--preachers and such like. But he's kind of
+good--he give me half a fish, once, when there warn't enough for two;
+and lots of times he's kind of stood by me when I was out of luck."
+
+"Well, he's mended kites for me, Huck, and knitted hooks on to my
+line. I wish we could get him out of there."
+
+"My! we couldn't get him out, Tom. And besides, 'twouldn't do any
+good; they'd ketch him again."
+
+"Yes--so they would. But I hate to hear 'em abuse him so like the
+dickens when he never done--that."
+
+"I do too, Tom. Lord, I hear 'em say he's the bloodiest looking
+villain in this country, and they wonder he wasn't ever hung before."
+
+"Yes, they talk like that, all the time. I've heard 'em say that if he
+was to get free they'd lynch him."
+
+"And they'd do it, too."
+
+The boys had a long talk, but it brought them little comfort. As the
+twilight drew on, they found themselves hanging about the neighborhood
+of the little isolated jail, perhaps with an undefined hope that
+something would happen that might clear away their difficulties. But
+nothing happened; there seemed to be no angels or fairies interested in
+this luckless captive.
+
+The boys did as they had often done before--went to the cell grating
+and gave Potter some tobacco and matches. He was on the ground floor
+and there were no guards.
+
+His gratitude for their gifts had always smote their consciences
+before--it cut deeper than ever, this time. They felt cowardly and
+treacherous to the last degree when Potter said:
+
+"You've been mighty good to me, boys--better'n anybody else in this
+town. And I don't forget it, I don't. Often I says to myself, says I,
+'I used to mend all the boys' kites and things, and show 'em where the
+good fishin' places was, and befriend 'em what I could, and now they've
+all forgot old Muff when he's in trouble; but Tom don't, and Huck
+don't--THEY don't forget him, says I, 'and I don't forget them.' Well,
+boys, I done an awful thing--drunk and crazy at the time--that's the
+only way I account for it--and now I got to swing for it, and it's
+right. Right, and BEST, too, I reckon--hope so, anyway. Well, we won't
+talk about that. I don't want to make YOU feel bad; you've befriended
+me. But what I want to say, is, don't YOU ever get drunk--then you won't
+ever get here. Stand a litter furder west--so--that's it; it's a prime
+comfort to see faces that's friendly when a body's in such a muck of
+trouble, and there don't none come here but yourn. Good friendly
+faces--good friendly faces. Git up on one another's backs and let me
+touch 'em. That's it. Shake hands--yourn'll come through the bars, but
+mine's too big. Little hands, and weak--but they've helped Muff Potter
+a power, and they'd help him more if they could."
+
+Tom went home miserable, and his dreams that night were full of
+horrors. The next day and the day after, he hung about the court-room,
+drawn by an almost irresistible impulse to go in, but forcing himself
+to stay out. Huck was having the same experience. They studiously
+avoided each other. Each wandered away, from time to time, but the same
+dismal fascination always brought them back presently. Tom kept his
+ears open when idlers sauntered out of the court-room, but invariably
+heard distressing news--the toils were closing more and more
+relentlessly around poor Potter. At the end of the second day the
+village talk was to the effect that Injun Joe's evidence stood firm and
+unshaken, and that there was not the slightest question as to what the
+jury's verdict would be.
+
+Tom was out late, that night, and came to bed through the window. He
+was in a tremendous state of excitement. It was hours before he got to
+sleep. All the village flocked to the court-house the next morning, for
+this was to be the great day. Both sexes were about equally represented
+in the packed audience. After a long wait the jury filed in and took
+their places; shortly afterward, Potter, pale and haggard, timid and
+hopeless, was brought in, with chains upon him, and seated where all
+the curious eyes could stare at him; no less conspicuous was Injun Joe,
+stolid as ever. There was another pause, and then the judge arrived and
+the sheriff proclaimed the opening of the court. The usual whisperings
+among the lawyers and gathering together of papers followed. These
+details and accompanying delays worked up an atmosphere of preparation
+that was as impressive as it was fascinating.
+
+Now a witness was called who testified that he found Muff Potter
+washing in the brook, at an early hour of the morning that the murder
+was discovered, and that he immediately sneaked away. After some
+further questioning, counsel for the prosecution said:
+
+"Take the witness."
+
+The prisoner raised his eyes for a moment, but dropped them again when
+his own counsel said:
+
+"I have no questions to ask him."
+
+The next witness proved the finding of the knife near the corpse.
+Counsel for the prosecution said:
+
+"Take the witness."
+
+"I have no questions to ask him," Potter's lawyer replied.
+
+A third witness swore he had often seen the knife in Potter's
+possession.
+
+"Take the witness."
+
+Counsel for Potter declined to question him. The faces of the audience
+began to betray annoyance. Did this attorney mean to throw away his
+client's life without an effort?
+
+Several witnesses deposed concerning Potter's guilty behavior when
+brought to the scene of the murder. They were allowed to leave the
+stand without being cross-questioned.
+
+Every detail of the damaging circumstances that occurred in the
+graveyard upon that morning which all present remembered so well was
+brought out by credible witnesses, but none of them were cross-examined
+by Potter's lawyer. The perplexity and dissatisfaction of the house
+expressed itself in murmurs and provoked a reproof from the bench.
+Counsel for the prosecution now said:
+
+"By the oaths of citizens whose simple word is above suspicion, we
+have fastened this awful crime, beyond all possibility of question,
+upon the unhappy prisoner at the bar. We rest our case here."
+
+A groan escaped from poor Potter, and he put his face in his hands and
+rocked his body softly to and fro, while a painful silence reigned in
+the court-room. Many men were moved, and many women's compassion
+testified itself in tears. Counsel for the defence rose and said:
+
+"Your honor, in our remarks at the opening of this trial, we
+foreshadowed our purpose to prove that our client did this fearful deed
+while under the influence of a blind and irresponsible delirium
+produced by drink. We have changed our mind. We shall not offer that
+plea." [Then to the clerk:] "Call Thomas Sawyer!"
+
+A puzzled amazement awoke in every face in the house, not even
+excepting Potter's. Every eye fastened itself with wondering interest
+upon Tom as he rose and took his place upon the stand. The boy looked
+wild enough, for he was badly scared. The oath was administered.
+
+"Thomas Sawyer, where were you on the seventeenth of June, about the
+hour of midnight?"
+
+Tom glanced at Injun Joe's iron face and his tongue failed him. The
+audience listened breathless, but the words refused to come. After a
+few moments, however, the boy got a little of his strength back, and
+managed to put enough of it into his voice to make part of the house
+hear:
+
+"In the graveyard!"
+
+"A little bit louder, please. Don't be afraid. You were--"
+
+"In the graveyard."
+
+A contemptuous smile flitted across Injun Joe's face.
+
+"Were you anywhere near Horse Williams' grave?"
+
+"Yes, sir."
+
+"Speak up--just a trifle louder. How near were you?"
+
+"Near as I am to you."
+
+"Were you hidden, or not?"
+
+"I was hid."
+
+"Where?"
+
+"Behind the elms that's on the edge of the grave."
+
+Injun Joe gave a barely perceptible start.
+
+"Any one with you?"
+
+"Yes, sir. I went there with--"
+
+"Wait--wait a moment. Never mind mentioning your companion's name. We
+will produce him at the proper time. Did you carry anything there with
+you."
+
+Tom hesitated and looked confused.
+
+"Speak out, my boy--don't be diffident. The truth is always
+respectable. What did you take there?"
+
+"Only a--a--dead cat."
+
+There was a ripple of mirth, which the court checked.
+
+"We will produce the skeleton of that cat. Now, my boy, tell us
+everything that occurred--tell it in your own way--don't skip anything,
+and don't be afraid."
+
+Tom began--hesitatingly at first, but as he warmed to his subject his
+words flowed more and more easily; in a little while every sound ceased
+but his own voice; every eye fixed itself upon him; with parted lips
+and bated breath the audience hung upon his words, taking no note of
+time, rapt in the ghastly fascinations of the tale. The strain upon
+pent emotion reached its climax when the boy said:
+
+"--and as the doctor fetched the board around and Muff Potter fell,
+Injun Joe jumped with the knife and--"
+
+Crash! Quick as lightning the half-breed sprang for a window, tore his
+way through all opposers, and was gone!
+
+
+
+CHAPTER XXIV
+
+TOM was a glittering hero once more--the pet of the old, the envy of
+the young. His name even went into immortal print, for the village
+paper magnified him. There were some that believed he would be
+President, yet, if he escaped hanging.
+
+As usual, the fickle, unreasoning world took Muff Potter to its bosom
+and fondled him as lavishly as it had abused him before. But that sort
+of conduct is to the world's credit; therefore it is not well to find
+fault with it.
+
+Tom's days were days of splendor and exultation to him, but his nights
+were seasons of horror. Injun Joe infested all his dreams, and always
+with doom in his eye. Hardly any temptation could persuade the boy to
+stir abroad after nightfall. Poor Huck was in the same state of
+wretchedness and terror, for Tom had told the whole story to the lawyer
+the night before the great day of the trial, and Huck was sore afraid
+that his share in the business might leak out, yet, notwithstanding
+Injun Joe's flight had saved him the suffering of testifying in court.
+The poor fellow had got the attorney to promise secrecy, but what of
+that? Since Tom's harassed conscience had managed to drive him to the
+lawyer's house by night and wring a dread tale from lips that had been
+sealed with the dismalest and most formidable of oaths, Huck's
+confidence in the human race was well-nigh obliterated.
+
+Daily Muff Potter's gratitude made Tom glad he had spoken; but nightly
+he wished he had sealed up his tongue.
+
+Half the time Tom was afraid Injun Joe would never be captured; the
+other half he was afraid he would be. He felt sure he never could draw
+a safe breath again until that man was dead and he had seen the corpse.
+
+Rewards had been offered, the country had been scoured, but no Injun
+Joe was found. One of those omniscient and awe-inspiring marvels, a
+detective, came up from St. Louis, moused around, shook his head,
+looked wise, and made that sort of astounding success which members of
+that craft usually achieve. That is to say, he "found a clew." But you
+can't hang a "clew" for murder, and so after that detective had got
+through and gone home, Tom felt just as insecure as he was before.
+
+The slow days drifted on, and each left behind it a slightly lightened
+weight of apprehension.
+
+
+
+CHAPTER XXV
+
+THERE comes a time in every rightly-constructed boy's life when he has
+a raging desire to go somewhere and dig for hidden treasure. This
+desire suddenly came upon Tom one day. He sallied out to find Joe
+Harper, but failed of success. Next he sought Ben Rogers; he had gone
+fishing. Presently he stumbled upon Huck Finn the Red-Handed. Huck
+would answer. Tom took him to a private place and opened the matter to
+him confidentially. Huck was willing. Huck was always willing to take a
+hand in any enterprise that offered entertainment and required no
+capital, for he had a troublesome superabundance of that sort of time
+which is not money. "Where'll we dig?" said Huck.
+
+"Oh, most anywhere."
+
+"Why, is it hid all around?"
+
+"No, indeed it ain't. It's hid in mighty particular places, Huck
+--sometimes on islands, sometimes in rotten chests under the end of a
+limb of an old dead tree, just where the shadow falls at midnight; but
+mostly under the floor in ha'nted houses."
+
+"Who hides it?"
+
+"Why, robbers, of course--who'd you reckon? Sunday-school
+sup'rintendents?"
+
+"I don't know. If 'twas mine I wouldn't hide it; I'd spend it and have
+a good time."
+
+"So would I. But robbers don't do that way. They always hide it and
+leave it there."
+
+"Don't they come after it any more?"
+
+"No, they think they will, but they generally forget the marks, or
+else they die. Anyway, it lays there a long time and gets rusty; and by
+and by somebody finds an old yellow paper that tells how to find the
+marks--a paper that's got to be ciphered over about a week because it's
+mostly signs and hy'roglyphics."
+
+"Hyro--which?"
+
+"Hy'roglyphics--pictures and things, you know, that don't seem to mean
+anything."
+
+"Have you got one of them papers, Tom?"
+
+"No."
+
+"Well then, how you going to find the marks?"
+
+"I don't want any marks. They always bury it under a ha'nted house or
+on an island, or under a dead tree that's got one limb sticking out.
+Well, we've tried Jackson's Island a little, and we can try it again
+some time; and there's the old ha'nted house up the Still-House branch,
+and there's lots of dead-limb trees--dead loads of 'em."
+
+"Is it under all of them?"
+
+"How you talk! No!"
+
+"Then how you going to know which one to go for?"
+
+"Go for all of 'em!"
+
+"Why, Tom, it'll take all summer."
+
+"Well, what of that? Suppose you find a brass pot with a hundred
+dollars in it, all rusty and gray, or rotten chest full of di'monds.
+How's that?"
+
+Huck's eyes glowed.
+
+"That's bully. Plenty bully enough for me. Just you gimme the hundred
+dollars and I don't want no di'monds."
+
+"All right. But I bet you I ain't going to throw off on di'monds. Some
+of 'em's worth twenty dollars apiece--there ain't any, hardly, but's
+worth six bits or a dollar."
+
+"No! Is that so?"
+
+"Cert'nly--anybody'll tell you so. Hain't you ever seen one, Huck?"
+
+"Not as I remember."
+
+"Oh, kings have slathers of them."
+
+"Well, I don' know no kings, Tom."
+
+"I reckon you don't. But if you was to go to Europe you'd see a raft
+of 'em hopping around."
+
+"Do they hop?"
+
+"Hop?--your granny! No!"
+
+"Well, what did you say they did, for?"
+
+"Shucks, I only meant you'd SEE 'em--not hopping, of course--what do
+they want to hop for?--but I mean you'd just see 'em--scattered around,
+you know, in a kind of a general way. Like that old humpbacked Richard."
+
+"Richard? What's his other name?"
+
+"He didn't have any other name. Kings don't have any but a given name."
+
+"No?"
+
+"But they don't."
+
+"Well, if they like it, Tom, all right; but I don't want to be a king
+and have only just a given name, like a nigger. But say--where you
+going to dig first?"
+
+"Well, I don't know. S'pose we tackle that old dead-limb tree on the
+hill t'other side of Still-House branch?"
+
+"I'm agreed."
+
+So they got a crippled pick and a shovel, and set out on their
+three-mile tramp. They arrived hot and panting, and threw themselves
+down in the shade of a neighboring elm to rest and have a smoke.
+
+"I like this," said Tom.
+
+"So do I."
+
+"Say, Huck, if we find a treasure here, what you going to do with your
+share?"
+
+"Well, I'll have pie and a glass of soda every day, and I'll go to
+every circus that comes along. I bet I'll have a gay time."
+
+"Well, ain't you going to save any of it?"
+
+"Save it? What for?"
+
+"Why, so as to have something to live on, by and by."
+
+"Oh, that ain't any use. Pap would come back to thish-yer town some
+day and get his claws on it if I didn't hurry up, and I tell you he'd
+clean it out pretty quick. What you going to do with yourn, Tom?"
+
+"I'm going to buy a new drum, and a sure-'nough sword, and a red
+necktie and a bull pup, and get married."
+
+"Married!"
+
+"That's it."
+
+"Tom, you--why, you ain't in your right mind."
+
+"Wait--you'll see."
+
+"Well, that's the foolishest thing you could do. Look at pap and my
+mother. Fight! Why, they used to fight all the time. I remember, mighty
+well."
+
+"That ain't anything. The girl I'm going to marry won't fight."
+
+"Tom, I reckon they're all alike. They'll all comb a body. Now you
+better think 'bout this awhile. I tell you you better. What's the name
+of the gal?"
+
+"It ain't a gal at all--it's a girl."
+
+"It's all the same, I reckon; some says gal, some says girl--both's
+right, like enough. Anyway, what's her name, Tom?"
+
+"I'll tell you some time--not now."
+
+"All right--that'll do. Only if you get married I'll be more lonesomer
+than ever."
+
+"No you won't. You'll come and live with me. Now stir out of this and
+we'll go to digging."
+
+They worked and sweated for half an hour. No result. They toiled
+another half-hour. Still no result. Huck said:
+
+"Do they always bury it as deep as this?"
+
+"Sometimes--not always. Not generally. I reckon we haven't got the
+right place."
+
+So they chose a new spot and began again. The labor dragged a little,
+but still they made progress. They pegged away in silence for some
+time. Finally Huck leaned on his shovel, swabbed the beaded drops from
+his brow with his sleeve, and said:
+
+"Where you going to dig next, after we get this one?"
+
+"I reckon maybe we'll tackle the old tree that's over yonder on
+Cardiff Hill back of the widow's."
+
+"I reckon that'll be a good one. But won't the widow take it away from
+us, Tom? It's on her land."
+
+"SHE take it away! Maybe she'd like to try it once. Whoever finds one
+of these hid treasures, it belongs to him. It don't make any difference
+whose land it's on."
+
+That was satisfactory. The work went on. By and by Huck said:
+
+"Blame it, we must be in the wrong place again. What do you think?"
+
+"It is mighty curious, Huck. I don't understand it. Sometimes witches
+interfere. I reckon maybe that's what's the trouble now."
+
+"Shucks! Witches ain't got no power in the daytime."
+
+"Well, that's so. I didn't think of that. Oh, I know what the matter
+is! What a blamed lot of fools we are! You got to find out where the
+shadow of the limb falls at midnight, and that's where you dig!"
+
+"Then consound it, we've fooled away all this work for nothing. Now
+hang it all, we got to come back in the night. It's an awful long way.
+Can you get out?"
+
+"I bet I will. We've got to do it to-night, too, because if somebody
+sees these holes they'll know in a minute what's here and they'll go
+for it."
+
+"Well, I'll come around and maow to-night."
+
+"All right. Let's hide the tools in the bushes."
+
+The boys were there that night, about the appointed time. They sat in
+the shadow waiting. It was a lonely place, and an hour made solemn by
+old traditions. Spirits whispered in the rustling leaves, ghosts lurked
+in the murky nooks, the deep baying of a hound floated up out of the
+distance, an owl answered with his sepulchral note. The boys were
+subdued by these solemnities, and talked little. By and by they judged
+that twelve had come; they marked where the shadow fell, and began to
+dig. Their hopes commenced to rise. Their interest grew stronger, and
+their industry kept pace with it. The hole deepened and still deepened,
+but every time their hearts jumped to hear the pick strike upon
+something, they only suffered a new disappointment. It was only a stone
+or a chunk. At last Tom said:
+
+"It ain't any use, Huck, we're wrong again."
+
+"Well, but we CAN'T be wrong. We spotted the shadder to a dot."
+
+"I know it, but then there's another thing."
+
+"What's that?".
+
+"Why, we only guessed at the time. Like enough it was too late or too
+early."
+
+Huck dropped his shovel.
+
+"That's it," said he. "That's the very trouble. We got to give this
+one up. We can't ever tell the right time, and besides this kind of
+thing's too awful, here this time of night with witches and ghosts
+a-fluttering around so. I feel as if something's behind me all the time;
+and I'm afeard to turn around, becuz maybe there's others in front
+a-waiting for a chance. I been creeping all over, ever since I got here."
+
+"Well, I've been pretty much so, too, Huck. They most always put in a
+dead man when they bury a treasure under a tree, to look out for it."
+
+"Lordy!"
+
+"Yes, they do. I've always heard that."
+
+"Tom, I don't like to fool around much where there's dead people. A
+body's bound to get into trouble with 'em, sure."
+
+"I don't like to stir 'em up, either. S'pose this one here was to
+stick his skull out and say something!"
+
+"Don't Tom! It's awful."
+
+"Well, it just is. Huck, I don't feel comfortable a bit."
+
+"Say, Tom, let's give this place up, and try somewheres else."
+
+"All right, I reckon we better."
+
+"What'll it be?"
+
+Tom considered awhile; and then said:
+
+"The ha'nted house. That's it!"
+
+"Blame it, I don't like ha'nted houses, Tom. Why, they're a dern sight
+worse'n dead people. Dead people might talk, maybe, but they don't come
+sliding around in a shroud, when you ain't noticing, and peep over your
+shoulder all of a sudden and grit their teeth, the way a ghost does. I
+couldn't stand such a thing as that, Tom--nobody could."
+
+"Yes, but, Huck, ghosts don't travel around only at night. They won't
+hender us from digging there in the daytime."
+
+"Well, that's so. But you know mighty well people don't go about that
+ha'nted house in the day nor the night."
+
+"Well, that's mostly because they don't like to go where a man's been
+murdered, anyway--but nothing's ever been seen around that house except
+in the night--just some blue lights slipping by the windows--no regular
+ghosts."
+
+"Well, where you see one of them blue lights flickering around, Tom,
+you can bet there's a ghost mighty close behind it. It stands to
+reason. Becuz you know that they don't anybody but ghosts use 'em."
+
+"Yes, that's so. But anyway they don't come around in the daytime, so
+what's the use of our being afeard?"
+
+"Well, all right. We'll tackle the ha'nted house if you say so--but I
+reckon it's taking chances."
+
+They had started down the hill by this time. There in the middle of
+the moonlit valley below them stood the "ha'nted" house, utterly
+isolated, its fences gone long ago, rank weeds smothering the very
+doorsteps, the chimney crumbled to ruin, the window-sashes vacant, a
+corner of the roof caved in. The boys gazed awhile, half expecting to
+see a blue light flit past a window; then talking in a low tone, as
+befitted the time and the circumstances, they struck far off to the
+right, to give the haunted house a wide berth, and took their way
+homeward through the woods that adorned the rearward side of Cardiff
+Hill.
+
+
+
+CHAPTER XXVI
+
+ABOUT noon the next day the boys arrived at the dead tree; they had
+come for their tools. Tom was impatient to go to the haunted house;
+Huck was measurably so, also--but suddenly said:
+
+"Lookyhere, Tom, do you know what day it is?"
+
+Tom mentally ran over the days of the week, and then quickly lifted
+his eyes with a startled look in them--
+
+"My! I never once thought of it, Huck!"
+
+"Well, I didn't neither, but all at once it popped onto me that it was
+Friday."
+
+"Blame it, a body can't be too careful, Huck. We might 'a' got into an
+awful scrape, tackling such a thing on a Friday."
+
+"MIGHT! Better say we WOULD! There's some lucky days, maybe, but
+Friday ain't."
+
+"Any fool knows that. I don't reckon YOU was the first that found it
+out, Huck."
+
+"Well, I never said I was, did I? And Friday ain't all, neither. I had
+a rotten bad dream last night--dreampt about rats."
+
+"No! Sure sign of trouble. Did they fight?"
+
+"No."
+
+"Well, that's good, Huck. When they don't fight it's only a sign that
+there's trouble around, you know. All we got to do is to look mighty
+sharp and keep out of it. We'll drop this thing for to-day, and play.
+Do you know Robin Hood, Huck?"
+
+"No. Who's Robin Hood?"
+
+"Why, he was one of the greatest men that was ever in England--and the
+best. He was a robber."
+
+"Cracky, I wisht I was. Who did he rob?"
+
+"Only sheriffs and bishops and rich people and kings, and such like.
+But he never bothered the poor. He loved 'em. He always divided up with
+'em perfectly square."
+
+"Well, he must 'a' been a brick."
+
+"I bet you he was, Huck. Oh, he was the noblest man that ever was.
+They ain't any such men now, I can tell you. He could lick any man in
+England, with one hand tied behind him; and he could take his yew bow
+and plug a ten-cent piece every time, a mile and a half."
+
+"What's a YEW bow?"
+
+"I don't know. It's some kind of a bow, of course. And if he hit that
+dime only on the edge he would set down and cry--and curse. But we'll
+play Robin Hood--it's nobby fun. I'll learn you."
+
+"I'm agreed."
+
+So they played Robin Hood all the afternoon, now and then casting a
+yearning eye down upon the haunted house and passing a remark about the
+morrow's prospects and possibilities there. As the sun began to sink
+into the west they took their way homeward athwart the long shadows of
+the trees and soon were buried from sight in the forests of Cardiff
+Hill.
+
+On Saturday, shortly after noon, the boys were at the dead tree again.
+They had a smoke and a chat in the shade, and then dug a little in
+their last hole, not with great hope, but merely because Tom said there
+were so many cases where people had given up a treasure after getting
+down within six inches of it, and then somebody else had come along and
+turned it up with a single thrust of a shovel. The thing failed this
+time, however, so the boys shouldered their tools and went away feeling
+that they had not trifled with fortune, but had fulfilled all the
+requirements that belong to the business of treasure-hunting.
+
+When they reached the haunted house there was something so weird and
+grisly about the dead silence that reigned there under the baking sun,
+and something so depressing about the loneliness and desolation of the
+place, that they were afraid, for a moment, to venture in. Then they
+crept to the door and took a trembling peep. They saw a weed-grown,
+floorless room, unplastered, an ancient fireplace, vacant windows, a
+ruinous staircase; and here, there, and everywhere hung ragged and
+abandoned cobwebs. They presently entered, softly, with quickened
+pulses, talking in whispers, ears alert to catch the slightest sound,
+and muscles tense and ready for instant retreat.
+
+In a little while familiarity modified their fears and they gave the
+place a critical and interested examination, rather admiring their own
+boldness, and wondering at it, too. Next they wanted to look up-stairs.
+This was something like cutting off retreat, but they got to daring
+each other, and of course there could be but one result--they threw
+their tools into a corner and made the ascent. Up there were the same
+signs of decay. In one corner they found a closet that promised
+mystery, but the promise was a fraud--there was nothing in it. Their
+courage was up now and well in hand. They were about to go down and
+begin work when--
+
+"Sh!" said Tom.
+
+"What is it?" whispered Huck, blanching with fright.
+
+"Sh!... There!... Hear it?"
+
+"Yes!... Oh, my! Let's run!"
+
+"Keep still! Don't you budge! They're coming right toward the door."
+
+The boys stretched themselves upon the floor with their eyes to
+knot-holes in the planking, and lay waiting, in a misery of fear.
+
+"They've stopped.... No--coming.... Here they are. Don't whisper
+another word, Huck. My goodness, I wish I was out of this!"
+
+Two men entered. Each boy said to himself: "There's the old deaf and
+dumb Spaniard that's been about town once or twice lately--never saw
+t'other man before."
+
+"T'other" was a ragged, unkempt creature, with nothing very pleasant
+in his face. The Spaniard was wrapped in a serape; he had bushy white
+whiskers; long white hair flowed from under his sombrero, and he wore
+green goggles. When they came in, "t'other" was talking in a low voice;
+they sat down on the ground, facing the door, with their backs to the
+wall, and the speaker continued his remarks. His manner became less
+guarded and his words more distinct as he proceeded:
+
+"No," said he, "I've thought it all over, and I don't like it. It's
+dangerous."
+
+"Dangerous!" grunted the "deaf and dumb" Spaniard--to the vast
+surprise of the boys. "Milksop!"
+
+This voice made the boys gasp and quake. It was Injun Joe's! There was
+silence for some time. Then Joe said:
+
+"What's any more dangerous than that job up yonder--but nothing's come
+of it."
+
+"That's different. Away up the river so, and not another house about.
+'Twon't ever be known that we tried, anyway, long as we didn't succeed."
+
+"Well, what's more dangerous than coming here in the daytime!--anybody
+would suspicion us that saw us."
+
+"I know that. But there warn't any other place as handy after that
+fool of a job. I want to quit this shanty. I wanted to yesterday, only
+it warn't any use trying to stir out of here, with those infernal boys
+playing over there on the hill right in full view."
+
+"Those infernal boys" quaked again under the inspiration of this
+remark, and thought how lucky it was that they had remembered it was
+Friday and concluded to wait a day. They wished in their hearts they
+had waited a year.
+
+The two men got out some food and made a luncheon. After a long and
+thoughtful silence, Injun Joe said:
+
+"Look here, lad--you go back up the river where you belong. Wait there
+till you hear from me. I'll take the chances on dropping into this town
+just once more, for a look. We'll do that 'dangerous' job after I've
+spied around a little and think things look well for it. Then for
+Texas! We'll leg it together!"
+
+This was satisfactory. Both men presently fell to yawning, and Injun
+Joe said:
+
+"I'm dead for sleep! It's your turn to watch."
+
+He curled down in the weeds and soon began to snore. His comrade
+stirred him once or twice and he became quiet. Presently the watcher
+began to nod; his head drooped lower and lower, both men began to snore
+now.
+
+The boys drew a long, grateful breath. Tom whispered:
+
+"Now's our chance--come!"
+
+Huck said:
+
+"I can't--I'd die if they was to wake."
+
+Tom urged--Huck held back. At last Tom rose slowly and softly, and
+started alone. But the first step he made wrung such a hideous creak
+from the crazy floor that he sank down almost dead with fright. He
+never made a second attempt. The boys lay there counting the dragging
+moments till it seemed to them that time must be done and eternity
+growing gray; and then they were grateful to note that at last the sun
+was setting.
+
+Now one snore ceased. Injun Joe sat up, stared around--smiled grimly
+upon his comrade, whose head was drooping upon his knees--stirred him
+up with his foot and said:
+
+"Here! YOU'RE a watchman, ain't you! All right, though--nothing's
+happened."
+
+"My! have I been asleep?"
+
+"Oh, partly, partly. Nearly time for us to be moving, pard. What'll we
+do with what little swag we've got left?"
+
+"I don't know--leave it here as we've always done, I reckon. No use to
+take it away till we start south. Six hundred and fifty in silver's
+something to carry."
+
+"Well--all right--it won't matter to come here once more."
+
+"No--but I'd say come in the night as we used to do--it's better."
+
+"Yes: but look here; it may be a good while before I get the right
+chance at that job; accidents might happen; 'tain't in such a very good
+place; we'll just regularly bury it--and bury it deep."
+
+"Good idea," said the comrade, who walked across the room, knelt down,
+raised one of the rearward hearth-stones and took out a bag that
+jingled pleasantly. He subtracted from it twenty or thirty dollars for
+himself and as much for Injun Joe, and passed the bag to the latter,
+who was on his knees in the corner, now, digging with his bowie-knife.
+
+The boys forgot all their fears, all their miseries in an instant.
+With gloating eyes they watched every movement. Luck!--the splendor of
+it was beyond all imagination! Six hundred dollars was money enough to
+make half a dozen boys rich! Here was treasure-hunting under the
+happiest auspices--there would not be any bothersome uncertainty as to
+where to dig. They nudged each other every moment--eloquent nudges and
+easily understood, for they simply meant--"Oh, but ain't you glad NOW
+we're here!"
+
+Joe's knife struck upon something.
+
+"Hello!" said he.
+
+"What is it?" said his comrade.
+
+"Half-rotten plank--no, it's a box, I believe. Here--bear a hand and
+we'll see what it's here for. Never mind, I've broke a hole."
+
+He reached his hand in and drew it out--
+
+"Man, it's money!"
+
+The two men examined the handful of coins. They were gold. The boys
+above were as excited as themselves, and as delighted.
+
+Joe's comrade said:
+
+"We'll make quick work of this. There's an old rusty pick over amongst
+the weeds in the corner the other side of the fireplace--I saw it a
+minute ago."
+
+He ran and brought the boys' pick and shovel. Injun Joe took the pick,
+looked it over critically, shook his head, muttered something to
+himself, and then began to use it. The box was soon unearthed. It was
+not very large; it was iron bound and had been very strong before the
+slow years had injured it. The men contemplated the treasure awhile in
+blissful silence.
+
+"Pard, there's thousands of dollars here," said Injun Joe.
+
+"'Twas always said that Murrel's gang used to be around here one
+summer," the stranger observed.
+
+"I know it," said Injun Joe; "and this looks like it, I should say."
+
+"Now you won't need to do that job."
+
+The half-breed frowned. Said he:
+
+"You don't know me. Least you don't know all about that thing. 'Tain't
+robbery altogether--it's REVENGE!" and a wicked light flamed in his
+eyes. "I'll need your help in it. When it's finished--then Texas. Go
+home to your Nance and your kids, and stand by till you hear from me."
+
+"Well--if you say so; what'll we do with this--bury it again?"
+
+"Yes. [Ravishing delight overhead.] NO! by the great Sachem, no!
+[Profound distress overhead.] I'd nearly forgot. That pick had fresh
+earth on it! [The boys were sick with terror in a moment.] What
+business has a pick and a shovel here? What business with fresh earth
+on them? Who brought them here--and where are they gone? Have you heard
+anybody?--seen anybody? What! bury it again and leave them to come and
+see the ground disturbed? Not exactly--not exactly. We'll take it to my
+den."
+
+"Why, of course! Might have thought of that before. You mean Number
+One?"
+
+"No--Number Two--under the cross. The other place is bad--too common."
+
+"All right. It's nearly dark enough to start."
+
+Injun Joe got up and went about from window to window cautiously
+peeping out. Presently he said:
+
+"Who could have brought those tools here? Do you reckon they can be
+up-stairs?"
+
+The boys' breath forsook them. Injun Joe put his hand on his knife,
+halted a moment, undecided, and then turned toward the stairway. The
+boys thought of the closet, but their strength was gone. The steps came
+creaking up the stairs--the intolerable distress of the situation woke
+the stricken resolution of the lads--they were about to spring for the
+closet, when there was a crash of rotten timbers and Injun Joe landed
+on the ground amid the debris of the ruined stairway. He gathered
+himself up cursing, and his comrade said:
+
+"Now what's the use of all that? If it's anybody, and they're up
+there, let them STAY there--who cares? If they want to jump down, now,
+and get into trouble, who objects? It will be dark in fifteen minutes
+--and then let them follow us if they want to. I'm willing. In my
+opinion, whoever hove those things in here caught a sight of us and
+took us for ghosts or devils or something. I'll bet they're running
+yet."
+
+Joe grumbled awhile; then he agreed with his friend that what daylight
+was left ought to be economized in getting things ready for leaving.
+Shortly afterward they slipped out of the house in the deepening
+twilight, and moved toward the river with their precious box.
+
+Tom and Huck rose up, weak but vastly relieved, and stared after them
+through the chinks between the logs of the house. Follow? Not they.
+They were content to reach ground again without broken necks, and take
+the townward track over the hill. They did not talk much. They were too
+much absorbed in hating themselves--hating the ill luck that made them
+take the spade and the pick there. But for that, Injun Joe never would
+have suspected. He would have hidden the silver with the gold to wait
+there till his "revenge" was satisfied, and then he would have had the
+misfortune to find that money turn up missing. Bitter, bitter luck that
+the tools were ever brought there!
+
+They resolved to keep a lookout for that Spaniard when he should come
+to town spying out for chances to do his revengeful job, and follow him
+to "Number Two," wherever that might be. Then a ghastly thought
+occurred to Tom.
+
+"Revenge? What if he means US, Huck!"
+
+"Oh, don't!" said Huck, nearly fainting.
+
+They talked it all over, and as they entered town they agreed to
+believe that he might possibly mean somebody else--at least that he
+might at least mean nobody but Tom, since only Tom had testified.
+
+Very, very small comfort it was to Tom to be alone in danger! Company
+would be a palpable improvement, he thought.
+
+
+
+CHAPTER XXVII
+
+THE adventure of the day mightily tormented Tom's dreams that night.
+Four times he had his hands on that rich treasure and four times it
+wasted to nothingness in his fingers as sleep forsook him and
+wakefulness brought back the hard reality of his misfortune. As he lay
+in the early morning recalling the incidents of his great adventure, he
+noticed that they seemed curiously subdued and far away--somewhat as if
+they had happened in another world, or in a time long gone by. Then it
+occurred to him that the great adventure itself must be a dream! There
+was one very strong argument in favor of this idea--namely, that the
+quantity of coin he had seen was too vast to be real. He had never seen
+as much as fifty dollars in one mass before, and he was like all boys
+of his age and station in life, in that he imagined that all references
+to "hundreds" and "thousands" were mere fanciful forms of speech, and
+that no such sums really existed in the world. He never had supposed
+for a moment that so large a sum as a hundred dollars was to be found
+in actual money in any one's possession. If his notions of hidden
+treasure had been analyzed, they would have been found to consist of a
+handful of real dimes and a bushel of vague, splendid, ungraspable
+dollars.
+
+But the incidents of his adventure grew sensibly sharper and clearer
+under the attrition of thinking them over, and so he presently found
+himself leaning to the impression that the thing might not have been a
+dream, after all. This uncertainty must be swept away. He would snatch
+a hurried breakfast and go and find Huck. Huck was sitting on the
+gunwale of a flatboat, listlessly dangling his feet in the water and
+looking very melancholy. Tom concluded to let Huck lead up to the
+subject. If he did not do it, then the adventure would be proved to
+have been only a dream.
+
+"Hello, Huck!"
+
+"Hello, yourself."
+
+Silence, for a minute.
+
+"Tom, if we'd 'a' left the blame tools at the dead tree, we'd 'a' got
+the money. Oh, ain't it awful!"
+
+"'Tain't a dream, then, 'tain't a dream! Somehow I most wish it was.
+Dog'd if I don't, Huck."
+
+"What ain't a dream?"
+
+"Oh, that thing yesterday. I been half thinking it was."
+
+"Dream! If them stairs hadn't broke down you'd 'a' seen how much dream
+it was! I've had dreams enough all night--with that patch-eyed Spanish
+devil going for me all through 'em--rot him!"
+
+"No, not rot him. FIND him! Track the money!"
+
+"Tom, we'll never find him. A feller don't have only one chance for
+such a pile--and that one's lost. I'd feel mighty shaky if I was to see
+him, anyway."
+
+"Well, so'd I; but I'd like to see him, anyway--and track him out--to
+his Number Two."
+
+"Number Two--yes, that's it. I been thinking 'bout that. But I can't
+make nothing out of it. What do you reckon it is?"
+
+"I dono. It's too deep. Say, Huck--maybe it's the number of a house!"
+
+"Goody!... No, Tom, that ain't it. If it is, it ain't in this
+one-horse town. They ain't no numbers here."
+
+"Well, that's so. Lemme think a minute. Here--it's the number of a
+room--in a tavern, you know!"
+
+"Oh, that's the trick! They ain't only two taverns. We can find out
+quick."
+
+"You stay here, Huck, till I come."
+
+Tom was off at once. He did not care to have Huck's company in public
+places. He was gone half an hour. He found that in the best tavern, No.
+2 had long been occupied by a young lawyer, and was still so occupied.
+In the less ostentatious house, No. 2 was a mystery. The
+tavern-keeper's young son said it was kept locked all the time, and he
+never saw anybody go into it or come out of it except at night; he did
+not know any particular reason for this state of things; had had some
+little curiosity, but it was rather feeble; had made the most of the
+mystery by entertaining himself with the idea that that room was
+"ha'nted"; had noticed that there was a light in there the night before.
+
+"That's what I've found out, Huck. I reckon that's the very No. 2
+we're after."
+
+"I reckon it is, Tom. Now what you going to do?"
+
+"Lemme think."
+
+Tom thought a long time. Then he said:
+
+"I'll tell you. The back door of that No. 2 is the door that comes out
+into that little close alley between the tavern and the old rattle trap
+of a brick store. Now you get hold of all the door-keys you can find,
+and I'll nip all of auntie's, and the first dark night we'll go there
+and try 'em. And mind you, keep a lookout for Injun Joe, because he
+said he was going to drop into town and spy around once more for a
+chance to get his revenge. If you see him, you just follow him; and if
+he don't go to that No. 2, that ain't the place."
+
+"Lordy, I don't want to foller him by myself!"
+
+"Why, it'll be night, sure. He mightn't ever see you--and if he did,
+maybe he'd never think anything."
+
+"Well, if it's pretty dark I reckon I'll track him. I dono--I dono.
+I'll try."
+
+"You bet I'll follow him, if it's dark, Huck. Why, he might 'a' found
+out he couldn't get his revenge, and be going right after that money."
+
+"It's so, Tom, it's so. I'll foller him; I will, by jingoes!"
+
+"Now you're TALKING! Don't you ever weaken, Huck, and I won't."
+
+
+
+CHAPTER XXVIII
+
+THAT night Tom and Huck were ready for their adventure. They hung
+about the neighborhood of the tavern until after nine, one watching the
+alley at a distance and the other the tavern door. Nobody entered the
+alley or left it; nobody resembling the Spaniard entered or left the
+tavern door. The night promised to be a fair one; so Tom went home with
+the understanding that if a considerable degree of darkness came on,
+Huck was to come and "maow," whereupon he would slip out and try the
+keys. But the night remained clear, and Huck closed his watch and
+retired to bed in an empty sugar hogshead about twelve.
+
+Tuesday the boys had the same ill luck. Also Wednesday. But Thursday
+night promised better. Tom slipped out in good season with his aunt's
+old tin lantern, and a large towel to blindfold it with. He hid the
+lantern in Huck's sugar hogshead and the watch began. An hour before
+midnight the tavern closed up and its lights (the only ones
+thereabouts) were put out. No Spaniard had been seen. Nobody had
+entered or left the alley. Everything was auspicious. The blackness of
+darkness reigned, the perfect stillness was interrupted only by
+occasional mutterings of distant thunder.
+
+Tom got his lantern, lit it in the hogshead, wrapped it closely in the
+towel, and the two adventurers crept in the gloom toward the tavern.
+Huck stood sentry and Tom felt his way into the alley. Then there was a
+season of waiting anxiety that weighed upon Huck's spirits like a
+mountain. He began to wish he could see a flash from the lantern--it
+would frighten him, but it would at least tell him that Tom was alive
+yet. It seemed hours since Tom had disappeared. Surely he must have
+fainted; maybe he was dead; maybe his heart had burst under terror and
+excitement. In his uneasiness Huck found himself drawing closer and
+closer to the alley; fearing all sorts of dreadful things, and
+momentarily expecting some catastrophe to happen that would take away
+his breath. There was not much to take away, for he seemed only able to
+inhale it by thimblefuls, and his heart would soon wear itself out, the
+way it was beating. Suddenly there was a flash of light and Tom came
+tearing by him: "Run!" said he; "run, for your life!"
+
+He needn't have repeated it; once was enough; Huck was making thirty
+or forty miles an hour before the repetition was uttered. The boys
+never stopped till they reached the shed of a deserted slaughter-house
+at the lower end of the village. Just as they got within its shelter
+the storm burst and the rain poured down. As soon as Tom got his breath
+he said:
+
+"Huck, it was awful! I tried two of the keys, just as soft as I could;
+but they seemed to make such a power of racket that I couldn't hardly
+get my breath I was so scared. They wouldn't turn in the lock, either.
+Well, without noticing what I was doing, I took hold of the knob, and
+open comes the door! It warn't locked! I hopped in, and shook off the
+towel, and, GREAT CAESAR'S GHOST!"
+
+"What!--what'd you see, Tom?"
+
+"Huck, I most stepped onto Injun Joe's hand!"
+
+"No!"
+
+"Yes! He was lying there, sound asleep on the floor, with his old
+patch on his eye and his arms spread out."
+
+"Lordy, what did you do? Did he wake up?"
+
+"No, never budged. Drunk, I reckon. I just grabbed that towel and
+started!"
+
+"I'd never 'a' thought of the towel, I bet!"
+
+"Well, I would. My aunt would make me mighty sick if I lost it."
+
+"Say, Tom, did you see that box?"
+
+"Huck, I didn't wait to look around. I didn't see the box, I didn't
+see the cross. I didn't see anything but a bottle and a tin cup on the
+floor by Injun Joe; yes, I saw two barrels and lots more bottles in the
+room. Don't you see, now, what's the matter with that ha'nted room?"
+
+"How?"
+
+"Why, it's ha'nted with whiskey! Maybe ALL the Temperance Taverns have
+got a ha'nted room, hey, Huck?"
+
+"Well, I reckon maybe that's so. Who'd 'a' thought such a thing? But
+say, Tom, now's a mighty good time to get that box, if Injun Joe's
+drunk."
+
+"It is, that! You try it!"
+
+Huck shuddered.
+
+"Well, no--I reckon not."
+
+"And I reckon not, Huck. Only one bottle alongside of Injun Joe ain't
+enough. If there'd been three, he'd be drunk enough and I'd do it."
+
+There was a long pause for reflection, and then Tom said:
+
+"Lookyhere, Huck, less not try that thing any more till we know Injun
+Joe's not in there. It's too scary. Now, if we watch every night, we'll
+be dead sure to see him go out, some time or other, and then we'll
+snatch that box quicker'n lightning."
+
+"Well, I'm agreed. I'll watch the whole night long, and I'll do it
+every night, too, if you'll do the other part of the job."
+
+"All right, I will. All you got to do is to trot up Hooper Street a
+block and maow--and if I'm asleep, you throw some gravel at the window
+and that'll fetch me."
+
+"Agreed, and good as wheat!"
+
+"Now, Huck, the storm's over, and I'll go home. It'll begin to be
+daylight in a couple of hours. You go back and watch that long, will
+you?"
+
+"I said I would, Tom, and I will. I'll ha'nt that tavern every night
+for a year! I'll sleep all day and I'll stand watch all night."
+
+"That's all right. Now, where you going to sleep?"
+
+"In Ben Rogers' hayloft. He lets me, and so does his pap's nigger man,
+Uncle Jake. I tote water for Uncle Jake whenever he wants me to, and
+any time I ask him he gives me a little something to eat if he can
+spare it. That's a mighty good nigger, Tom. He likes me, becuz I don't
+ever act as if I was above him. Sometime I've set right down and eat
+WITH him. But you needn't tell that. A body's got to do things when
+he's awful hungry he wouldn't want to do as a steady thing."
+
+"Well, if I don't want you in the daytime, I'll let you sleep. I won't
+come bothering around. Any time you see something's up, in the night,
+just skip right around and maow."
+
+
+
+CHAPTER XXIX
+
+THE first thing Tom heard on Friday morning was a glad piece of news
+--Judge Thatcher's family had come back to town the night before. Both
+Injun Joe and the treasure sunk into secondary importance for a moment,
+and Becky took the chief place in the boy's interest. He saw her and
+they had an exhausting good time playing "hi-spy" and "gully-keeper"
+with a crowd of their school-mates. The day was completed and crowned
+in a peculiarly satisfactory way: Becky teased her mother to appoint
+the next day for the long-promised and long-delayed picnic, and she
+consented. The child's delight was boundless; and Tom's not more
+moderate. The invitations were sent out before sunset, and straightway
+the young folks of the village were thrown into a fever of preparation
+and pleasurable anticipation. Tom's excitement enabled him to keep
+awake until a pretty late hour, and he had good hopes of hearing Huck's
+"maow," and of having his treasure to astonish Becky and the picnickers
+with, next day; but he was disappointed. No signal came that night.
+
+Morning came, eventually, and by ten or eleven o'clock a giddy and
+rollicking company were gathered at Judge Thatcher's, and everything
+was ready for a start. It was not the custom for elderly people to mar
+the picnics with their presence. The children were considered safe
+enough under the wings of a few young ladies of eighteen and a few
+young gentlemen of twenty-three or thereabouts. The old steam ferryboat
+was chartered for the occasion; presently the gay throng filed up the
+main street laden with provision-baskets. Sid was sick and had to miss
+the fun; Mary remained at home to entertain him. The last thing Mrs.
+Thatcher said to Becky, was:
+
+"You'll not get back till late. Perhaps you'd better stay all night
+with some of the girls that live near the ferry-landing, child."
+
+"Then I'll stay with Susy Harper, mamma."
+
+"Very well. And mind and behave yourself and don't be any trouble."
+
+Presently, as they tripped along, Tom said to Becky:
+
+"Say--I'll tell you what we'll do. 'Stead of going to Joe Harper's
+we'll climb right up the hill and stop at the Widow Douglas'. She'll
+have ice-cream! She has it most every day--dead loads of it. And she'll
+be awful glad to have us."
+
+"Oh, that will be fun!"
+
+Then Becky reflected a moment and said:
+
+"But what will mamma say?"
+
+"How'll she ever know?"
+
+The girl turned the idea over in her mind, and said reluctantly:
+
+"I reckon it's wrong--but--"
+
+"But shucks! Your mother won't know, and so what's the harm? All she
+wants is that you'll be safe; and I bet you she'd 'a' said go there if
+she'd 'a' thought of it. I know she would!"
+
+The Widow Douglas' splendid hospitality was a tempting bait. It and
+Tom's persuasions presently carried the day. So it was decided to say
+nothing anybody about the night's programme. Presently it occurred to
+Tom that maybe Huck might come this very night and give the signal. The
+thought took a deal of the spirit out of his anticipations. Still he
+could not bear to give up the fun at Widow Douglas'. And why should he
+give it up, he reasoned--the signal did not come the night before, so
+why should it be any more likely to come to-night? The sure fun of the
+evening outweighed the uncertain treasure; and, boy-like, he determined
+to yield to the stronger inclination and not allow himself to think of
+the box of money another time that day.
+
+Three miles below town the ferryboat stopped at the mouth of a woody
+hollow and tied up. The crowd swarmed ashore and soon the forest
+distances and craggy heights echoed far and near with shoutings and
+laughter. All the different ways of getting hot and tired were gone
+through with, and by-and-by the rovers straggled back to camp fortified
+with responsible appetites, and then the destruction of the good things
+began. After the feast there was a refreshing season of rest and chat
+in the shade of spreading oaks. By-and-by somebody shouted:
+
+"Who's ready for the cave?"
+
+Everybody was. Bundles of candles were procured, and straightway there
+was a general scamper up the hill. The mouth of the cave was up the
+hillside--an opening shaped like a letter A. Its massive oaken door
+stood unbarred. Within was a small chamber, chilly as an ice-house, and
+walled by Nature with solid limestone that was dewy with a cold sweat.
+It was romantic and mysterious to stand here in the deep gloom and look
+out upon the green valley shining in the sun. But the impressiveness of
+the situation quickly wore off, and the romping began again. The moment
+a candle was lighted there was a general rush upon the owner of it; a
+struggle and a gallant defence followed, but the candle was soon
+knocked down or blown out, and then there was a glad clamor of laughter
+and a new chase. But all things have an end. By-and-by the procession
+went filing down the steep descent of the main avenue, the flickering
+rank of lights dimly revealing the lofty walls of rock almost to their
+point of junction sixty feet overhead. This main avenue was not more
+than eight or ten feet wide. Every few steps other lofty and still
+narrower crevices branched from it on either hand--for McDougal's cave
+was but a vast labyrinth of crooked aisles that ran into each other and
+out again and led nowhere. It was said that one might wander days and
+nights together through its intricate tangle of rifts and chasms, and
+never find the end of the cave; and that he might go down, and down,
+and still down, into the earth, and it was just the same--labyrinth
+under labyrinth, and no end to any of them. No man "knew" the cave.
+That was an impossible thing. Most of the young men knew a portion of
+it, and it was not customary to venture much beyond this known portion.
+Tom Sawyer knew as much of the cave as any one.
+
+The procession moved along the main avenue some three-quarters of a
+mile, and then groups and couples began to slip aside into branch
+avenues, fly along the dismal corridors, and take each other by
+surprise at points where the corridors joined again. Parties were able
+to elude each other for the space of half an hour without going beyond
+the "known" ground.
+
+By-and-by, one group after another came straggling back to the mouth
+of the cave, panting, hilarious, smeared from head to foot with tallow
+drippings, daubed with clay, and entirely delighted with the success of
+the day. Then they were astonished to find that they had been taking no
+note of time and that night was about at hand. The clanging bell had
+been calling for half an hour. However, this sort of close to the day's
+adventures was romantic and therefore satisfactory. When the ferryboat
+with her wild freight pushed into the stream, nobody cared sixpence for
+the wasted time but the captain of the craft.
+
+Huck was already upon his watch when the ferryboat's lights went
+glinting past the wharf. He heard no noise on board, for the young
+people were as subdued and still as people usually are who are nearly
+tired to death. He wondered what boat it was, and why she did not stop
+at the wharf--and then he dropped her out of his mind and put his
+attention upon his business. The night was growing cloudy and dark. Ten
+o'clock came, and the noise of vehicles ceased, scattered lights began
+to wink out, all straggling foot-passengers disappeared, the village
+betook itself to its slumbers and left the small watcher alone with the
+silence and the ghosts. Eleven o'clock came, and the tavern lights were
+put out; darkness everywhere, now. Huck waited what seemed a weary long
+time, but nothing happened. His faith was weakening. Was there any use?
+Was there really any use? Why not give it up and turn in?
+
+A noise fell upon his ear. He was all attention in an instant. The
+alley door closed softly. He sprang to the corner of the brick store.
+The next moment two men brushed by him, and one seemed to have
+something under his arm. It must be that box! So they were going to
+remove the treasure. Why call Tom now? It would be absurd--the men
+would get away with the box and never be found again. No, he would
+stick to their wake and follow them; he would trust to the darkness for
+security from discovery. So communing with himself, Huck stepped out
+and glided along behind the men, cat-like, with bare feet, allowing
+them to keep just far enough ahead not to be invisible.
+
+They moved up the river street three blocks, then turned to the left
+up a cross-street. They went straight ahead, then, until they came to
+the path that led up Cardiff Hill; this they took. They passed by the
+old Welshman's house, half-way up the hill, without hesitating, and
+still climbed upward. Good, thought Huck, they will bury it in the old
+quarry. But they never stopped at the quarry. They passed on, up the
+summit. They plunged into the narrow path between the tall sumach
+bushes, and were at once hidden in the gloom. Huck closed up and
+shortened his distance, now, for they would never be able to see him.
+He trotted along awhile; then slackened his pace, fearing he was
+gaining too fast; moved on a piece, then stopped altogether; listened;
+no sound; none, save that he seemed to hear the beating of his own
+heart. The hooting of an owl came over the hill--ominous sound! But no
+footsteps. Heavens, was everything lost! He was about to spring with
+winged feet, when a man cleared his throat not four feet from him!
+Huck's heart shot into his throat, but he swallowed it again; and then
+he stood there shaking as if a dozen agues had taken charge of him at
+once, and so weak that he thought he must surely fall to the ground. He
+knew where he was. He knew he was within five steps of the stile
+leading into Widow Douglas' grounds. Very well, he thought, let them
+bury it there; it won't be hard to find.
+
+Now there was a voice--a very low voice--Injun Joe's:
+
+"Damn her, maybe she's got company--there's lights, late as it is."
+
+"I can't see any."
+
+This was that stranger's voice--the stranger of the haunted house. A
+deadly chill went to Huck's heart--this, then, was the "revenge" job!
+His thought was, to fly. Then he remembered that the Widow Douglas had
+been kind to him more than once, and maybe these men were going to
+murder her. He wished he dared venture to warn her; but he knew he
+didn't dare--they might come and catch him. He thought all this and
+more in the moment that elapsed between the stranger's remark and Injun
+Joe's next--which was--
+
+"Because the bush is in your way. Now--this way--now you see, don't
+you?"
+
+"Yes. Well, there IS company there, I reckon. Better give it up."
+
+"Give it up, and I just leaving this country forever! Give it up and
+maybe never have another chance. I tell you again, as I've told you
+before, I don't care for her swag--you may have it. But her husband was
+rough on me--many times he was rough on me--and mainly he was the
+justice of the peace that jugged me for a vagrant. And that ain't all.
+It ain't a millionth part of it! He had me HORSEWHIPPED!--horsewhipped
+in front of the jail, like a nigger!--with all the town looking on!
+HORSEWHIPPED!--do you understand? He took advantage of me and died. But
+I'll take it out of HER."
+
+"Oh, don't kill her! Don't do that!"
+
+"Kill? Who said anything about killing? I would kill HIM if he was
+here; but not her. When you want to get revenge on a woman you don't
+kill her--bosh! you go for her looks. You slit her nostrils--you notch
+her ears like a sow!"
+
+"By God, that's--"
+
+"Keep your opinion to yourself! It will be safest for you. I'll tie
+her to the bed. If she bleeds to death, is that my fault? I'll not cry,
+if she does. My friend, you'll help me in this thing--for MY sake
+--that's why you're here--I mightn't be able alone. If you flinch, I'll
+kill you. Do you understand that? And if I have to kill you, I'll kill
+her--and then I reckon nobody'll ever know much about who done this
+business."
+
+"Well, if it's got to be done, let's get at it. The quicker the
+better--I'm all in a shiver."
+
+"Do it NOW? And company there? Look here--I'll get suspicious of you,
+first thing you know. No--we'll wait till the lights are out--there's
+no hurry."
+
+Huck felt that a silence was going to ensue--a thing still more awful
+than any amount of murderous talk; so he held his breath and stepped
+gingerly back; planted his foot carefully and firmly, after balancing,
+one-legged, in a precarious way and almost toppling over, first on one
+side and then on the other. He took another step back, with the same
+elaboration and the same risks; then another and another, and--a twig
+snapped under his foot! His breath stopped and he listened. There was
+no sound--the stillness was perfect. His gratitude was measureless. Now
+he turned in his tracks, between the walls of sumach bushes--turned
+himself as carefully as if he were a ship--and then stepped quickly but
+cautiously along. When he emerged at the quarry he felt secure, and so
+he picked up his nimble heels and flew. Down, down he sped, till he
+reached the Welshman's. He banged at the door, and presently the heads
+of the old man and his two stalwart sons were thrust from windows.
+
+"What's the row there? Who's banging? What do you want?"
+
+"Let me in--quick! I'll tell everything."
+
+"Why, who are you?"
+
+"Huckleberry Finn--quick, let me in!"
+
+"Huckleberry Finn, indeed! It ain't a name to open many doors, I
+judge! But let him in, lads, and let's see what's the trouble."
+
+"Please don't ever tell I told you," were Huck's first words when he
+got in. "Please don't--I'd be killed, sure--but the widow's been good
+friends to me sometimes, and I want to tell--I WILL tell if you'll
+promise you won't ever say it was me."
+
+"By George, he HAS got something to tell, or he wouldn't act so!"
+exclaimed the old man; "out with it and nobody here'll ever tell, lad."
+
+Three minutes later the old man and his sons, well armed, were up the
+hill, and just entering the sumach path on tiptoe, their weapons in
+their hands. Huck accompanied them no further. He hid behind a great
+bowlder and fell to listening. There was a lagging, anxious silence,
+and then all of a sudden there was an explosion of firearms and a cry.
+
+Huck waited for no particulars. He sprang away and sped down the hill
+as fast as his legs could carry him.
+
+
+
+CHAPTER XXX
+
+AS the earliest suspicion of dawn appeared on Sunday morning, Huck
+came groping up the hill and rapped gently at the old Welshman's door.
+The inmates were asleep, but it was a sleep that was set on a
+hair-trigger, on account of the exciting episode of the night. A call
+came from a window:
+
+"Who's there!"
+
+Huck's scared voice answered in a low tone:
+
+"Please let me in! It's only Huck Finn!"
+
+"It's a name that can open this door night or day, lad!--and welcome!"
+
+These were strange words to the vagabond boy's ears, and the
+pleasantest he had ever heard. He could not recollect that the closing
+word had ever been applied in his case before. The door was quickly
+unlocked, and he entered. Huck was given a seat and the old man and his
+brace of tall sons speedily dressed themselves.
+
+"Now, my boy, I hope you're good and hungry, because breakfast will be
+ready as soon as the sun's up, and we'll have a piping hot one, too
+--make yourself easy about that! I and the boys hoped you'd turn up and
+stop here last night."
+
+"I was awful scared," said Huck, "and I run. I took out when the
+pistols went off, and I didn't stop for three mile. I've come now becuz
+I wanted to know about it, you know; and I come before daylight becuz I
+didn't want to run across them devils, even if they was dead."
+
+"Well, poor chap, you do look as if you'd had a hard night of it--but
+there's a bed here for you when you've had your breakfast. No, they
+ain't dead, lad--we are sorry enough for that. You see we knew right
+where to put our hands on them, by your description; so we crept along
+on tiptoe till we got within fifteen feet of them--dark as a cellar
+that sumach path was--and just then I found I was going to sneeze. It
+was the meanest kind of luck! I tried to keep it back, but no use
+--'twas bound to come, and it did come! I was in the lead with my pistol
+raised, and when the sneeze started those scoundrels a-rustling to get
+out of the path, I sung out, 'Fire boys!' and blazed away at the place
+where the rustling was. So did the boys. But they were off in a jiffy,
+those villains, and we after them, down through the woods. I judge we
+never touched them. They fired a shot apiece as they started, but their
+bullets whizzed by and didn't do us any harm. As soon as we lost the
+sound of their feet we quit chasing, and went down and stirred up the
+constables. They got a posse together, and went off to guard the river
+bank, and as soon as it is light the sheriff and a gang are going to
+beat up the woods. My boys will be with them presently. I wish we had
+some sort of description of those rascals--'twould help a good deal.
+But you couldn't see what they were like, in the dark, lad, I suppose?"
+
+"Oh yes; I saw them down-town and follered them."
+
+"Splendid! Describe them--describe them, my boy!"
+
+"One's the old deaf and dumb Spaniard that's ben around here once or
+twice, and t'other's a mean-looking, ragged--"
+
+"That's enough, lad, we know the men! Happened on them in the woods
+back of the widow's one day, and they slunk away. Off with you, boys,
+and tell the sheriff--get your breakfast to-morrow morning!"
+
+The Welshman's sons departed at once. As they were leaving the room
+Huck sprang up and exclaimed:
+
+"Oh, please don't tell ANYbody it was me that blowed on them! Oh,
+please!"
+
+"All right if you say it, Huck, but you ought to have the credit of
+what you did."
+
+"Oh no, no! Please don't tell!"
+
+When the young men were gone, the old Welshman said:
+
+"They won't tell--and I won't. But why don't you want it known?"
+
+Huck would not explain, further than to say that he already knew too
+much about one of those men and would not have the man know that he
+knew anything against him for the whole world--he would be killed for
+knowing it, sure.
+
+The old man promised secrecy once more, and said:
+
+"How did you come to follow these fellows, lad? Were they looking
+suspicious?"
+
+Huck was silent while he framed a duly cautious reply. Then he said:
+
+"Well, you see, I'm a kind of a hard lot,--least everybody says so,
+and I don't see nothing agin it--and sometimes I can't sleep much, on
+account of thinking about it and sort of trying to strike out a new way
+of doing. That was the way of it last night. I couldn't sleep, and so I
+come along up-street 'bout midnight, a-turning it all over, and when I
+got to that old shackly brick store by the Temperance Tavern, I backed
+up agin the wall to have another think. Well, just then along comes
+these two chaps slipping along close by me, with something under their
+arm, and I reckoned they'd stole it. One was a-smoking, and t'other one
+wanted a light; so they stopped right before me and the cigars lit up
+their faces and I see that the big one was the deaf and dumb Spaniard,
+by his white whiskers and the patch on his eye, and t'other one was a
+rusty, ragged-looking devil."
+
+"Could you see the rags by the light of the cigars?"
+
+This staggered Huck for a moment. Then he said:
+
+"Well, I don't know--but somehow it seems as if I did."
+
+"Then they went on, and you--"
+
+"Follered 'em--yes. That was it. I wanted to see what was up--they
+sneaked along so. I dogged 'em to the widder's stile, and stood in the
+dark and heard the ragged one beg for the widder, and the Spaniard
+swear he'd spile her looks just as I told you and your two--"
+
+"What! The DEAF AND DUMB man said all that!"
+
+Huck had made another terrible mistake! He was trying his best to keep
+the old man from getting the faintest hint of who the Spaniard might
+be, and yet his tongue seemed determined to get him into trouble in
+spite of all he could do. He made several efforts to creep out of his
+scrape, but the old man's eye was upon him and he made blunder after
+blunder. Presently the Welshman said:
+
+"My boy, don't be afraid of me. I wouldn't hurt a hair of your head
+for all the world. No--I'd protect you--I'd protect you. This Spaniard
+is not deaf and dumb; you've let that slip without intending it; you
+can't cover that up now. You know something about that Spaniard that
+you want to keep dark. Now trust me--tell me what it is, and trust me
+--I won't betray you."
+
+Huck looked into the old man's honest eyes a moment, then bent over
+and whispered in his ear:
+
+"'Tain't a Spaniard--it's Injun Joe!"
+
+The Welshman almost jumped out of his chair. In a moment he said:
+
+"It's all plain enough, now. When you talked about notching ears and
+slitting noses I judged that that was your own embellishment, because
+white men don't take that sort of revenge. But an Injun! That's a
+different matter altogether."
+
+During breakfast the talk went on, and in the course of it the old man
+said that the last thing which he and his sons had done, before going
+to bed, was to get a lantern and examine the stile and its vicinity for
+marks of blood. They found none, but captured a bulky bundle of--
+
+"Of WHAT?"
+
+If the words had been lightning they could not have leaped with a more
+stunning suddenness from Huck's blanched lips. His eyes were staring
+wide, now, and his breath suspended--waiting for the answer. The
+Welshman started--stared in return--three seconds--five seconds--ten
+--then replied:
+
+"Of burglar's tools. Why, what's the MATTER with you?"
+
+Huck sank back, panting gently, but deeply, unutterably grateful. The
+Welshman eyed him gravely, curiously--and presently said:
+
+"Yes, burglar's tools. That appears to relieve you a good deal. But
+what did give you that turn? What were YOU expecting we'd found?"
+
+Huck was in a close place--the inquiring eye was upon him--he would
+have given anything for material for a plausible answer--nothing
+suggested itself--the inquiring eye was boring deeper and deeper--a
+senseless reply offered--there was no time to weigh it, so at a venture
+he uttered it--feebly:
+
+"Sunday-school books, maybe."
+
+Poor Huck was too distressed to smile, but the old man laughed loud
+and joyously, shook up the details of his anatomy from head to foot,
+and ended by saying that such a laugh was money in a-man's pocket,
+because it cut down the doctor's bill like everything. Then he added:
+
+"Poor old chap, you're white and jaded--you ain't well a bit--no
+wonder you're a little flighty and off your balance. But you'll come
+out of it. Rest and sleep will fetch you out all right, I hope."
+
+Huck was irritated to think he had been such a goose and betrayed such
+a suspicious excitement, for he had dropped the idea that the parcel
+brought from the tavern was the treasure, as soon as he had heard the
+talk at the widow's stile. He had only thought it was not the treasure,
+however--he had not known that it wasn't--and so the suggestion of a
+captured bundle was too much for his self-possession. But on the whole
+he felt glad the little episode had happened, for now he knew beyond
+all question that that bundle was not THE bundle, and so his mind was
+at rest and exceedingly comfortable. In fact, everything seemed to be
+drifting just in the right direction, now; the treasure must be still
+in No. 2, the men would be captured and jailed that day, and he and Tom
+could seize the gold that night without any trouble or any fear of
+interruption.
+
+Just as breakfast was completed there was a knock at the door. Huck
+jumped for a hiding-place, for he had no mind to be connected even
+remotely with the late event. The Welshman admitted several ladies and
+gentlemen, among them the Widow Douglas, and noticed that groups of
+citizens were climbing up the hill--to stare at the stile. So the news
+had spread. The Welshman had to tell the story of the night to the
+visitors. The widow's gratitude for her preservation was outspoken.
+
+"Don't say a word about it, madam. There's another that you're more
+beholden to than you are to me and my boys, maybe, but he don't allow
+me to tell his name. We wouldn't have been there but for him."
+
+Of course this excited a curiosity so vast that it almost belittled
+the main matter--but the Welshman allowed it to eat into the vitals of
+his visitors, and through them be transmitted to the whole town, for he
+refused to part with his secret. When all else had been learned, the
+widow said:
+
+"I went to sleep reading in bed and slept straight through all that
+noise. Why didn't you come and wake me?"
+
+"We judged it warn't worth while. Those fellows warn't likely to come
+again--they hadn't any tools left to work with, and what was the use of
+waking you up and scaring you to death? My three negro men stood guard
+at your house all the rest of the night. They've just come back."
+
+More visitors came, and the story had to be told and retold for a
+couple of hours more.
+
+There was no Sabbath-school during day-school vacation, but everybody
+was early at church. The stirring event was well canvassed. News came
+that not a sign of the two villains had been yet discovered. When the
+sermon was finished, Judge Thatcher's wife dropped alongside of Mrs.
+Harper as she moved down the aisle with the crowd and said:
+
+"Is my Becky going to sleep all day? I just expected she would be
+tired to death."
+
+"Your Becky?"
+
+"Yes," with a startled look--"didn't she stay with you last night?"
+
+"Why, no."
+
+Mrs. Thatcher turned pale, and sank into a pew, just as Aunt Polly,
+talking briskly with a friend, passed by. Aunt Polly said:
+
+"Good-morning, Mrs. Thatcher. Good-morning, Mrs. Harper. I've got a
+boy that's turned up missing. I reckon my Tom stayed at your house last
+night--one of you. And now he's afraid to come to church. I've got to
+settle with him."
+
+Mrs. Thatcher shook her head feebly and turned paler than ever.
+
+"He didn't stay with us," said Mrs. Harper, beginning to look uneasy.
+A marked anxiety came into Aunt Polly's face.
+
+"Joe Harper, have you seen my Tom this morning?"
+
+"No'm."
+
+"When did you see him last?"
+
+Joe tried to remember, but was not sure he could say. The people had
+stopped moving out of church. Whispers passed along, and a boding
+uneasiness took possession of every countenance. Children were
+anxiously questioned, and young teachers. They all said they had not
+noticed whether Tom and Becky were on board the ferryboat on the
+homeward trip; it was dark; no one thought of inquiring if any one was
+missing. One young man finally blurted out his fear that they were
+still in the cave! Mrs. Thatcher swooned away. Aunt Polly fell to
+crying and wringing her hands.
+
+The alarm swept from lip to lip, from group to group, from street to
+street, and within five minutes the bells were wildly clanging and the
+whole town was up! The Cardiff Hill episode sank into instant
+insignificance, the burglars were forgotten, horses were saddled,
+skiffs were manned, the ferryboat ordered out, and before the horror
+was half an hour old, two hundred men were pouring down highroad and
+river toward the cave.
+
+All the long afternoon the village seemed empty and dead. Many women
+visited Aunt Polly and Mrs. Thatcher and tried to comfort them. They
+cried with them, too, and that was still better than words. All the
+tedious night the town waited for news; but when the morning dawned at
+last, all the word that came was, "Send more candles--and send food."
+Mrs. Thatcher was almost crazed; and Aunt Polly, also. Judge Thatcher
+sent messages of hope and encouragement from the cave, but they
+conveyed no real cheer.
+
+The old Welshman came home toward daylight, spattered with
+candle-grease, smeared with clay, and almost worn out. He found Huck
+still in the bed that had been provided for him, and delirious with
+fever. The physicians were all at the cave, so the Widow Douglas came
+and took charge of the patient. She said she would do her best by him,
+because, whether he was good, bad, or indifferent, he was the Lord's,
+and nothing that was the Lord's was a thing to be neglected. The
+Welshman said Huck had good spots in him, and the widow said:
+
+"You can depend on it. That's the Lord's mark. He don't leave it off.
+He never does. Puts it somewhere on every creature that comes from his
+hands."
+
+Early in the forenoon parties of jaded men began to straggle into the
+village, but the strongest of the citizens continued searching. All the
+news that could be gained was that remotenesses of the cavern were
+being ransacked that had never been visited before; that every corner
+and crevice was going to be thoroughly searched; that wherever one
+wandered through the maze of passages, lights were to be seen flitting
+hither and thither in the distance, and shoutings and pistol-shots sent
+their hollow reverberations to the ear down the sombre aisles. In one
+place, far from the section usually traversed by tourists, the names
+"BECKY & TOM" had been found traced upon the rocky wall with
+candle-smoke, and near at hand a grease-soiled bit of ribbon. Mrs.
+Thatcher recognized the ribbon and cried over it. She said it was the
+last relic she should ever have of her child; and that no other memorial
+of her could ever be so precious, because this one parted latest from
+the living body before the awful death came. Some said that now and
+then, in the cave, a far-away speck of light would glimmer, and then a
+glorious shout would burst forth and a score of men go trooping down the
+echoing aisle--and then a sickening disappointment always followed; the
+children were not there; it was only a searcher's light.
+
+Three dreadful days and nights dragged their tedious hours along, and
+the village sank into a hopeless stupor. No one had heart for anything.
+The accidental discovery, just made, that the proprietor of the
+Temperance Tavern kept liquor on his premises, scarcely fluttered the
+public pulse, tremendous as the fact was. In a lucid interval, Huck
+feebly led up to the subject of taverns, and finally asked--dimly
+dreading the worst--if anything had been discovered at the Temperance
+Tavern since he had been ill.
+
+"Yes," said the widow.
+
+Huck started up in bed, wild-eyed:
+
+"What? What was it?"
+
+"Liquor!--and the place has been shut up. Lie down, child--what a turn
+you did give me!"
+
+"Only tell me just one thing--only just one--please! Was it Tom Sawyer
+that found it?"
+
+The widow burst into tears. "Hush, hush, child, hush! I've told you
+before, you must NOT talk. You are very, very sick!"
+
+Then nothing but liquor had been found; there would have been a great
+powwow if it had been the gold. So the treasure was gone forever--gone
+forever! But what could she be crying about? Curious that she should
+cry.
+
+These thoughts worked their dim way through Huck's mind, and under the
+weariness they gave him he fell asleep. The widow said to herself:
+
+"There--he's asleep, poor wreck. Tom Sawyer find it! Pity but somebody
+could find Tom Sawyer! Ah, there ain't many left, now, that's got hope
+enough, or strength enough, either, to go on searching."
+
+
+
+CHAPTER XXXI
+
+NOW to return to Tom and Becky's share in the picnic. They tripped
+along the murky aisles with the rest of the company, visiting the
+familiar wonders of the cave--wonders dubbed with rather
+over-descriptive names, such as "The Drawing-Room," "The Cathedral,"
+"Aladdin's Palace," and so on. Presently the hide-and-seek frolicking
+began, and Tom and Becky engaged in it with zeal until the exertion
+began to grow a trifle wearisome; then they wandered down a sinuous
+avenue holding their candles aloft and reading the tangled web-work of
+names, dates, post-office addresses, and mottoes with which the rocky
+walls had been frescoed (in candle-smoke). Still drifting along and
+talking, they scarcely noticed that they were now in a part of the cave
+whose walls were not frescoed. They smoked their own names under an
+overhanging shelf and moved on. Presently they came to a place where a
+little stream of water, trickling over a ledge and carrying a limestone
+sediment with it, had, in the slow-dragging ages, formed a laced and
+ruffled Niagara in gleaming and imperishable stone. Tom squeezed his
+small body behind it in order to illuminate it for Becky's
+gratification. He found that it curtained a sort of steep natural
+stairway which was enclosed between narrow walls, and at once the
+ambition to be a discoverer seized him. Becky responded to his call,
+and they made a smoke-mark for future guidance, and started upon their
+quest. They wound this way and that, far down into the secret depths of
+the cave, made another mark, and branched off in search of novelties to
+tell the upper world about. In one place they found a spacious cavern,
+from whose ceiling depended a multitude of shining stalactites of the
+length and circumference of a man's leg; they walked all about it,
+wondering and admiring, and presently left it by one of the numerous
+passages that opened into it. This shortly brought them to a bewitching
+spring, whose basin was incrusted with a frostwork of glittering
+crystals; it was in the midst of a cavern whose walls were supported by
+many fantastic pillars which had been formed by the joining of great
+stalactites and stalagmites together, the result of the ceaseless
+water-drip of centuries. Under the roof vast knots of bats had packed
+themselves together, thousands in a bunch; the lights disturbed the
+creatures and they came flocking down by hundreds, squeaking and
+darting furiously at the candles. Tom knew their ways and the danger of
+this sort of conduct. He seized Becky's hand and hurried her into the
+first corridor that offered; and none too soon, for a bat struck
+Becky's light out with its wing while she was passing out of the
+cavern. The bats chased the children a good distance; but the fugitives
+plunged into every new passage that offered, and at last got rid of the
+perilous things. Tom found a subterranean lake, shortly, which
+stretched its dim length away until its shape was lost in the shadows.
+He wanted to explore its borders, but concluded that it would be best
+to sit down and rest awhile, first. Now, for the first time, the deep
+stillness of the place laid a clammy hand upon the spirits of the
+children. Becky said:
+
+"Why, I didn't notice, but it seems ever so long since I heard any of
+the others."
+
+"Come to think, Becky, we are away down below them--and I don't know
+how far away north, or south, or east, or whichever it is. We couldn't
+hear them here."
+
+Becky grew apprehensive.
+
+"I wonder how long we've been down here, Tom? We better start back."
+
+"Yes, I reckon we better. P'raps we better."
+
+"Can you find the way, Tom? It's all a mixed-up crookedness to me."
+
+"I reckon I could find it--but then the bats. If they put our candles
+out it will be an awful fix. Let's try some other way, so as not to go
+through there."
+
+"Well. But I hope we won't get lost. It would be so awful!" and the
+girl shuddered at the thought of the dreadful possibilities.
+
+They started through a corridor, and traversed it in silence a long
+way, glancing at each new opening, to see if there was anything
+familiar about the look of it; but they were all strange. Every time
+Tom made an examination, Becky would watch his face for an encouraging
+sign, and he would say cheerily:
+
+"Oh, it's all right. This ain't the one, but we'll come to it right
+away!"
+
+But he felt less and less hopeful with each failure, and presently
+began to turn off into diverging avenues at sheer random, in desperate
+hope of finding the one that was wanted. He still said it was "all
+right," but there was such a leaden dread at his heart that the words
+had lost their ring and sounded just as if he had said, "All is lost!"
+Becky clung to his side in an anguish of fear, and tried hard to keep
+back the tears, but they would come. At last she said:
+
+"Oh, Tom, never mind the bats, let's go back that way! We seem to get
+worse and worse off all the time."
+
+"Listen!" said he.
+
+Profound silence; silence so deep that even their breathings were
+conspicuous in the hush. Tom shouted. The call went echoing down the
+empty aisles and died out in the distance in a faint sound that
+resembled a ripple of mocking laughter.
+
+"Oh, don't do it again, Tom, it is too horrid," said Becky.
+
+"It is horrid, but I better, Becky; they might hear us, you know," and
+he shouted again.
+
+The "might" was even a chillier horror than the ghostly laughter, it
+so confessed a perishing hope. The children stood still and listened;
+but there was no result. Tom turned upon the back track at once, and
+hurried his steps. It was but a little while before a certain
+indecision in his manner revealed another fearful fact to Becky--he
+could not find his way back!
+
+"Oh, Tom, you didn't make any marks!"
+
+"Becky, I was such a fool! Such a fool! I never thought we might want
+to come back! No--I can't find the way. It's all mixed up."
+
+"Tom, Tom, we're lost! we're lost! We never can get out of this awful
+place! Oh, why DID we ever leave the others!"
+
+She sank to the ground and burst into such a frenzy of crying that Tom
+was appalled with the idea that she might die, or lose her reason. He
+sat down by her and put his arms around her; she buried her face in his
+bosom, she clung to him, she poured out her terrors, her unavailing
+regrets, and the far echoes turned them all to jeering laughter. Tom
+begged her to pluck up hope again, and she said she could not. He fell
+to blaming and abusing himself for getting her into this miserable
+situation; this had a better effect. She said she would try to hope
+again, she would get up and follow wherever he might lead if only he
+would not talk like that any more. For he was no more to blame than
+she, she said.
+
+So they moved on again--aimlessly--simply at random--all they could do
+was to move, keep moving. For a little while, hope made a show of
+reviving--not with any reason to back it, but only because it is its
+nature to revive when the spring has not been taken out of it by age
+and familiarity with failure.
+
+By-and-by Tom took Becky's candle and blew it out. This economy meant
+so much! Words were not needed. Becky understood, and her hope died
+again. She knew that Tom had a whole candle and three or four pieces in
+his pockets--yet he must economize.
+
+By-and-by, fatigue began to assert its claims; the children tried to
+pay attention, for it was dreadful to think of sitting down when time
+was grown to be so precious, moving, in some direction, in any
+direction, was at least progress and might bear fruit; but to sit down
+was to invite death and shorten its pursuit.
+
+At last Becky's frail limbs refused to carry her farther. She sat
+down. Tom rested with her, and they talked of home, and the friends
+there, and the comfortable beds and, above all, the light! Becky cried,
+and Tom tried to think of some way of comforting her, but all his
+encouragements were grown threadbare with use, and sounded like
+sarcasms. Fatigue bore so heavily upon Becky that she drowsed off to
+sleep. Tom was grateful. He sat looking into her drawn face and saw it
+grow smooth and natural under the influence of pleasant dreams; and
+by-and-by a smile dawned and rested there. The peaceful face reflected
+somewhat of peace and healing into his own spirit, and his thoughts
+wandered away to bygone times and dreamy memories. While he was deep in
+his musings, Becky woke up with a breezy little laugh--but it was
+stricken dead upon her lips, and a groan followed it.
+
+"Oh, how COULD I sleep! I wish I never, never had waked! No! No, I
+don't, Tom! Don't look so! I won't say it again."
+
+"I'm glad you've slept, Becky; you'll feel rested, now, and we'll find
+the way out."
+
+"We can try, Tom; but I've seen such a beautiful country in my dream.
+I reckon we are going there."
+
+"Maybe not, maybe not. Cheer up, Becky, and let's go on trying."
+
+They rose up and wandered along, hand in hand and hopeless. They tried
+to estimate how long they had been in the cave, but all they knew was
+that it seemed days and weeks, and yet it was plain that this could not
+be, for their candles were not gone yet. A long time after this--they
+could not tell how long--Tom said they must go softly and listen for
+dripping water--they must find a spring. They found one presently, and
+Tom said it was time to rest again. Both were cruelly tired, yet Becky
+said she thought she could go a little farther. She was surprised to
+hear Tom dissent. She could not understand it. They sat down, and Tom
+fastened his candle to the wall in front of them with some clay.
+Thought was soon busy; nothing was said for some time. Then Becky broke
+the silence:
+
+"Tom, I am so hungry!"
+
+Tom took something out of his pocket.
+
+"Do you remember this?" said he.
+
+Becky almost smiled.
+
+"It's our wedding-cake, Tom."
+
+"Yes--I wish it was as big as a barrel, for it's all we've got."
+
+"I saved it from the picnic for us to dream on, Tom, the way grown-up
+people do with wedding-cake--but it'll be our--"
+
+She dropped the sentence where it was. Tom divided the cake and Becky
+ate with good appetite, while Tom nibbled at his moiety. There was
+abundance of cold water to finish the feast with. By-and-by Becky
+suggested that they move on again. Tom was silent a moment. Then he
+said:
+
+"Becky, can you bear it if I tell you something?"
+
+Becky's face paled, but she thought she could.
+
+"Well, then, Becky, we must stay here, where there's water to drink.
+That little piece is our last candle!"
+
+Becky gave loose to tears and wailings. Tom did what he could to
+comfort her, but with little effect. At length Becky said:
+
+"Tom!"
+
+"Well, Becky?"
+
+"They'll miss us and hunt for us!"
+
+"Yes, they will! Certainly they will!"
+
+"Maybe they're hunting for us now, Tom."
+
+"Why, I reckon maybe they are. I hope they are."
+
+"When would they miss us, Tom?"
+
+"When they get back to the boat, I reckon."
+
+"Tom, it might be dark then--would they notice we hadn't come?"
+
+"I don't know. But anyway, your mother would miss you as soon as they
+got home."
+
+A frightened look in Becky's face brought Tom to his senses and he saw
+that he had made a blunder. Becky was not to have gone home that night!
+The children became silent and thoughtful. In a moment a new burst of
+grief from Becky showed Tom that the thing in his mind had struck hers
+also--that the Sabbath morning might be half spent before Mrs. Thatcher
+discovered that Becky was not at Mrs. Harper's.
+
+The children fastened their eyes upon their bit of candle and watched
+it melt slowly and pitilessly away; saw the half inch of wick stand
+alone at last; saw the feeble flame rise and fall, climb the thin
+column of smoke, linger at its top a moment, and then--the horror of
+utter darkness reigned!
+
+How long afterward it was that Becky came to a slow consciousness that
+she was crying in Tom's arms, neither could tell. All that they knew
+was, that after what seemed a mighty stretch of time, both awoke out of
+a dead stupor of sleep and resumed their miseries once more. Tom said
+it might be Sunday, now--maybe Monday. He tried to get Becky to talk,
+but her sorrows were too oppressive, all her hopes were gone. Tom said
+that they must have been missed long ago, and no doubt the search was
+going on. He would shout and maybe some one would come. He tried it;
+but in the darkness the distant echoes sounded so hideously that he
+tried it no more.
+
+The hours wasted away, and hunger came to torment the captives again.
+A portion of Tom's half of the cake was left; they divided and ate it.
+But they seemed hungrier than before. The poor morsel of food only
+whetted desire.
+
+By-and-by Tom said:
+
+"SH! Did you hear that?"
+
+Both held their breath and listened. There was a sound like the
+faintest, far-off shout. Instantly Tom answered it, and leading Becky
+by the hand, started groping down the corridor in its direction.
+Presently he listened again; again the sound was heard, and apparently
+a little nearer.
+
+"It's them!" said Tom; "they're coming! Come along, Becky--we're all
+right now!"
+
+The joy of the prisoners was almost overwhelming. Their speed was
+slow, however, because pitfalls were somewhat common, and had to be
+guarded against. They shortly came to one and had to stop. It might be
+three feet deep, it might be a hundred--there was no passing it at any
+rate. Tom got down on his breast and reached as far down as he could.
+No bottom. They must stay there and wait until the searchers came. They
+listened; evidently the distant shoutings were growing more distant! a
+moment or two more and they had gone altogether. The heart-sinking
+misery of it! Tom whooped until he was hoarse, but it was of no use. He
+talked hopefully to Becky; but an age of anxious waiting passed and no
+sounds came again.
+
+The children groped their way back to the spring. The weary time
+dragged on; they slept again, and awoke famished and woe-stricken. Tom
+believed it must be Tuesday by this time.
+
+Now an idea struck him. There were some side passages near at hand. It
+would be better to explore some of these than bear the weight of the
+heavy time in idleness. He took a kite-line from his pocket, tied it to
+a projection, and he and Becky started, Tom in the lead, unwinding the
+line as he groped along. At the end of twenty steps the corridor ended
+in a "jumping-off place." Tom got down on his knees and felt below, and
+then as far around the corner as he could reach with his hands
+conveniently; he made an effort to stretch yet a little farther to the
+right, and at that moment, not twenty yards away, a human hand, holding
+a candle, appeared from behind a rock! Tom lifted up a glorious shout,
+and instantly that hand was followed by the body it belonged to--Injun
+Joe's! Tom was paralyzed; he could not move. He was vastly gratified
+the next moment, to see the "Spaniard" take to his heels and get
+himself out of sight. Tom wondered that Joe had not recognized his
+voice and come over and killed him for testifying in court. But the
+echoes must have disguised the voice. Without doubt, that was it, he
+reasoned. Tom's fright weakened every muscle in his body. He said to
+himself that if he had strength enough to get back to the spring he
+would stay there, and nothing should tempt him to run the risk of
+meeting Injun Joe again. He was careful to keep from Becky what it was
+he had seen. He told her he had only shouted "for luck."
+
+But hunger and wretchedness rise superior to fears in the long run.
+Another tedious wait at the spring and another long sleep brought
+changes. The children awoke tortured with a raging hunger. Tom believed
+that it must be Wednesday or Thursday or even Friday or Saturday, now,
+and that the search had been given over. He proposed to explore another
+passage. He felt willing to risk Injun Joe and all other terrors. But
+Becky was very weak. She had sunk into a dreary apathy and would not be
+roused. She said she would wait, now, where she was, and die--it would
+not be long. She told Tom to go with the kite-line and explore if he
+chose; but she implored him to come back every little while and speak
+to her; and she made him promise that when the awful time came, he
+would stay by her and hold her hand until all was over.
+
+Tom kissed her, with a choking sensation in his throat, and made a
+show of being confident of finding the searchers or an escape from the
+cave; then he took the kite-line in his hand and went groping down one
+of the passages on his hands and knees, distressed with hunger and sick
+with bodings of coming doom.
+
+
+
+CHAPTER XXXII
+
+TUESDAY afternoon came, and waned to the twilight. The village of St.
+Petersburg still mourned. The lost children had not been found. Public
+prayers had been offered up for them, and many and many a private
+prayer that had the petitioner's whole heart in it; but still no good
+news came from the cave. The majority of the searchers had given up the
+quest and gone back to their daily avocations, saying that it was plain
+the children could never be found. Mrs. Thatcher was very ill, and a
+great part of the time delirious. People said it was heartbreaking to
+hear her call her child, and raise her head and listen a whole minute
+at a time, then lay it wearily down again with a moan. Aunt Polly had
+drooped into a settled melancholy, and her gray hair had grown almost
+white. The village went to its rest on Tuesday night, sad and forlorn.
+
+Away in the middle of the night a wild peal burst from the village
+bells, and in a moment the streets were swarming with frantic half-clad
+people, who shouted, "Turn out! turn out! they're found! they're
+found!" Tin pans and horns were added to the din, the population massed
+itself and moved toward the river, met the children coming in an open
+carriage drawn by shouting citizens, thronged around it, joined its
+homeward march, and swept magnificently up the main street roaring
+huzzah after huzzah!
+
+The village was illuminated; nobody went to bed again; it was the
+greatest night the little town had ever seen. During the first half-hour
+a procession of villagers filed through Judge Thatcher's house, seized
+the saved ones and kissed them, squeezed Mrs. Thatcher's hand, tried to
+speak but couldn't--and drifted out raining tears all over the place.
+
+Aunt Polly's happiness was complete, and Mrs. Thatcher's nearly so. It
+would be complete, however, as soon as the messenger dispatched with
+the great news to the cave should get the word to her husband. Tom lay
+upon a sofa with an eager auditory about him and told the history of
+the wonderful adventure, putting in many striking additions to adorn it
+withal; and closed with a description of how he left Becky and went on
+an exploring expedition; how he followed two avenues as far as his
+kite-line would reach; how he followed a third to the fullest stretch of
+the kite-line, and was about to turn back when he glimpsed a far-off
+speck that looked like daylight; dropped the line and groped toward it,
+pushed his head and shoulders through a small hole, and saw the broad
+Mississippi rolling by! And if it had only happened to be night he would
+not have seen that speck of daylight and would not have explored that
+passage any more! He told how he went back for Becky and broke the good
+news and she told him not to fret her with such stuff, for she was
+tired, and knew she was going to die, and wanted to. He described how he
+labored with her and convinced her; and how she almost died for joy when
+she had groped to where she actually saw the blue speck of daylight; how
+he pushed his way out at the hole and then helped her out; how they sat
+there and cried for gladness; how some men came along in a skiff and Tom
+hailed them and told them their situation and their famished condition;
+how the men didn't believe the wild tale at first, "because," said they,
+"you are five miles down the river below the valley the cave is in"
+--then took them aboard, rowed to a house, gave them supper, made them
+rest till two or three hours after dark and then brought them home.
+
+Before day-dawn, Judge Thatcher and the handful of searchers with him
+were tracked out, in the cave, by the twine clews they had strung
+behind them, and informed of the great news.
+
+Three days and nights of toil and hunger in the cave were not to be
+shaken off at once, as Tom and Becky soon discovered. They were
+bedridden all of Wednesday and Thursday, and seemed to grow more and
+more tired and worn, all the time. Tom got about, a little, on
+Thursday, was down-town Friday, and nearly as whole as ever Saturday;
+but Becky did not leave her room until Sunday, and then she looked as
+if she had passed through a wasting illness.
+
+Tom learned of Huck's sickness and went to see him on Friday, but
+could not be admitted to the bedroom; neither could he on Saturday or
+Sunday. He was admitted daily after that, but was warned to keep still
+about his adventure and introduce no exciting topic. The Widow Douglas
+stayed by to see that he obeyed. At home Tom learned of the Cardiff
+Hill event; also that the "ragged man's" body had eventually been found
+in the river near the ferry-landing; he had been drowned while trying
+to escape, perhaps.
+
+About a fortnight after Tom's rescue from the cave, he started off to
+visit Huck, who had grown plenty strong enough, now, to hear exciting
+talk, and Tom had some that would interest him, he thought. Judge
+Thatcher's house was on Tom's way, and he stopped to see Becky. The
+Judge and some friends set Tom to talking, and some one asked him
+ironically if he wouldn't like to go to the cave again. Tom said he
+thought he wouldn't mind it. The Judge said:
+
+"Well, there are others just like you, Tom, I've not the least doubt.
+But we have taken care of that. Nobody will get lost in that cave any
+more."
+
+"Why?"
+
+"Because I had its big door sheathed with boiler iron two weeks ago,
+and triple-locked--and I've got the keys."
+
+Tom turned as white as a sheet.
+
+"What's the matter, boy! Here, run, somebody! Fetch a glass of water!"
+
+The water was brought and thrown into Tom's face.
+
+"Ah, now you're all right. What was the matter with you, Tom?"
+
+"Oh, Judge, Injun Joe's in the cave!"
+
+
+
+CHAPTER XXXIII
+
+WITHIN a few minutes the news had spread, and a dozen skiff-loads of
+men were on their way to McDougal's cave, and the ferryboat, well
+filled with passengers, soon followed. Tom Sawyer was in the skiff that
+bore Judge Thatcher.
+
+When the cave door was unlocked, a sorrowful sight presented itself in
+the dim twilight of the place. Injun Joe lay stretched upon the ground,
+dead, with his face close to the crack of the door, as if his longing
+eyes had been fixed, to the latest moment, upon the light and the cheer
+of the free world outside. Tom was touched, for he knew by his own
+experience how this wretch had suffered. His pity was moved, but
+nevertheless he felt an abounding sense of relief and security, now,
+which revealed to him in a degree which he had not fully appreciated
+before how vast a weight of dread had been lying upon him since the day
+he lifted his voice against this bloody-minded outcast.
+
+Injun Joe's bowie-knife lay close by, its blade broken in two. The
+great foundation-beam of the door had been chipped and hacked through,
+with tedious labor; useless labor, too, it was, for the native rock
+formed a sill outside it, and upon that stubborn material the knife had
+wrought no effect; the only damage done was to the knife itself. But if
+there had been no stony obstruction there the labor would have been
+useless still, for if the beam had been wholly cut away Injun Joe could
+not have squeezed his body under the door, and he knew it. So he had
+only hacked that place in order to be doing something--in order to pass
+the weary time--in order to employ his tortured faculties. Ordinarily
+one could find half a dozen bits of candle stuck around in the crevices
+of this vestibule, left there by tourists; but there were none now. The
+prisoner had searched them out and eaten them. He had also contrived to
+catch a few bats, and these, also, he had eaten, leaving only their
+claws. The poor unfortunate had starved to death. In one place, near at
+hand, a stalagmite had been slowly growing up from the ground for ages,
+builded by the water-drip from a stalactite overhead. The captive had
+broken off the stalagmite, and upon the stump had placed a stone,
+wherein he had scooped a shallow hollow to catch the precious drop
+that fell once in every three minutes with the dreary regularity of a
+clock-tick--a dessertspoonful once in four and twenty hours. That drop
+was falling when the Pyramids were new; when Troy fell; when the
+foundations of Rome were laid; when Christ was crucified; when the
+Conqueror created the British empire; when Columbus sailed; when the
+massacre at Lexington was "news." It is falling now; it will still be
+falling when all these things shall have sunk down the afternoon of
+history, and the twilight of tradition, and been swallowed up in the
+thick night of oblivion. Has everything a purpose and a mission? Did
+this drop fall patiently during five thousand years to be ready for
+this flitting human insect's need? and has it another important object
+to accomplish ten thousand years to come? No matter. It is many and
+many a year since the hapless half-breed scooped out the stone to catch
+the priceless drops, but to this day the tourist stares longest at that
+pathetic stone and that slow-dropping water when he comes to see the
+wonders of McDougal's cave. Injun Joe's cup stands first in the list of
+the cavern's marvels; even "Aladdin's Palace" cannot rival it.
+
+Injun Joe was buried near the mouth of the cave; and people flocked
+there in boats and wagons from the towns and from all the farms and
+hamlets for seven miles around; they brought their children, and all
+sorts of provisions, and confessed that they had had almost as
+satisfactory a time at the funeral as they could have had at the
+hanging.
+
+This funeral stopped the further growth of one thing--the petition to
+the governor for Injun Joe's pardon. The petition had been largely
+signed; many tearful and eloquent meetings had been held, and a
+committee of sappy women been appointed to go in deep mourning and wail
+around the governor, and implore him to be a merciful ass and trample
+his duty under foot. Injun Joe was believed to have killed five
+citizens of the village, but what of that? If he had been Satan himself
+there would have been plenty of weaklings ready to scribble their names
+to a pardon-petition, and drip a tear on it from their permanently
+impaired and leaky water-works.
+
+The morning after the funeral Tom took Huck to a private place to have
+an important talk. Huck had learned all about Tom's adventure from the
+Welshman and the Widow Douglas, by this time, but Tom said he reckoned
+there was one thing they had not told him; that thing was what he
+wanted to talk about now. Huck's face saddened. He said:
+
+"I know what it is. You got into No. 2 and never found anything but
+whiskey. Nobody told me it was you; but I just knowed it must 'a' ben
+you, soon as I heard 'bout that whiskey business; and I knowed you
+hadn't got the money becuz you'd 'a' got at me some way or other and
+told me even if you was mum to everybody else. Tom, something's always
+told me we'd never get holt of that swag."
+
+"Why, Huck, I never told on that tavern-keeper. YOU know his tavern
+was all right the Saturday I went to the picnic. Don't you remember you
+was to watch there that night?"
+
+"Oh yes! Why, it seems 'bout a year ago. It was that very night that I
+follered Injun Joe to the widder's."
+
+"YOU followed him?"
+
+"Yes--but you keep mum. I reckon Injun Joe's left friends behind him,
+and I don't want 'em souring on me and doing me mean tricks. If it
+hadn't ben for me he'd be down in Texas now, all right."
+
+Then Huck told his entire adventure in confidence to Tom, who had only
+heard of the Welshman's part of it before.
+
+"Well," said Huck, presently, coming back to the main question,
+"whoever nipped the whiskey in No. 2, nipped the money, too, I reckon
+--anyways it's a goner for us, Tom."
+
+"Huck, that money wasn't ever in No. 2!"
+
+"What!" Huck searched his comrade's face keenly. "Tom, have you got on
+the track of that money again?"
+
+"Huck, it's in the cave!"
+
+Huck's eyes blazed.
+
+"Say it again, Tom."
+
+"The money's in the cave!"
+
+"Tom--honest injun, now--is it fun, or earnest?"
+
+"Earnest, Huck--just as earnest as ever I was in my life. Will you go
+in there with me and help get it out?"
+
+"I bet I will! I will if it's where we can blaze our way to it and not
+get lost."
+
+"Huck, we can do that without the least little bit of trouble in the
+world."
+
+"Good as wheat! What makes you think the money's--"
+
+"Huck, you just wait till we get in there. If we don't find it I'll
+agree to give you my drum and every thing I've got in the world. I
+will, by jings."
+
+"All right--it's a whiz. When do you say?"
+
+"Right now, if you say it. Are you strong enough?"
+
+"Is it far in the cave? I ben on my pins a little, three or four days,
+now, but I can't walk more'n a mile, Tom--least I don't think I could."
+
+"It's about five mile into there the way anybody but me would go,
+Huck, but there's a mighty short cut that they don't anybody but me
+know about. Huck, I'll take you right to it in a skiff. I'll float the
+skiff down there, and I'll pull it back again all by myself. You
+needn't ever turn your hand over."
+
+"Less start right off, Tom."
+
+"All right. We want some bread and meat, and our pipes, and a little
+bag or two, and two or three kite-strings, and some of these
+new-fangled things they call lucifer matches. I tell you, many's
+the time I wished I had some when I was in there before."
+
+A trifle after noon the boys borrowed a small skiff from a citizen who
+was absent, and got under way at once. When they were several miles
+below "Cave Hollow," Tom said:
+
+"Now you see this bluff here looks all alike all the way down from the
+cave hollow--no houses, no wood-yards, bushes all alike. But do you see
+that white place up yonder where there's been a landslide? Well, that's
+one of my marks. We'll get ashore, now."
+
+They landed.
+
+"Now, Huck, where we're a-standing you could touch that hole I got out
+of with a fishing-pole. See if you can find it."
+
+Huck searched all the place about, and found nothing. Tom proudly
+marched into a thick clump of sumach bushes and said:
+
+"Here you are! Look at it, Huck; it's the snuggest hole in this
+country. You just keep mum about it. All along I've been wanting to be
+a robber, but I knew I'd got to have a thing like this, and where to
+run across it was the bother. We've got it now, and we'll keep it
+quiet, only we'll let Joe Harper and Ben Rogers in--because of course
+there's got to be a Gang, or else there wouldn't be any style about it.
+Tom Sawyer's Gang--it sounds splendid, don't it, Huck?"
+
+"Well, it just does, Tom. And who'll we rob?"
+
+"Oh, most anybody. Waylay people--that's mostly the way."
+
+"And kill them?"
+
+"No, not always. Hive them in the cave till they raise a ransom."
+
+"What's a ransom?"
+
+"Money. You make them raise all they can, off'n their friends; and
+after you've kept them a year, if it ain't raised then you kill them.
+That's the general way. Only you don't kill the women. You shut up the
+women, but you don't kill them. They're always beautiful and rich, and
+awfully scared. You take their watches and things, but you always take
+your hat off and talk polite. They ain't anybody as polite as robbers
+--you'll see that in any book. Well, the women get to loving you, and
+after they've been in the cave a week or two weeks they stop crying and
+after that you couldn't get them to leave. If you drove them out they'd
+turn right around and come back. It's so in all the books."
+
+"Why, it's real bully, Tom. I believe it's better'n to be a pirate."
+
+"Yes, it's better in some ways, because it's close to home and
+circuses and all that."
+
+By this time everything was ready and the boys entered the hole, Tom
+in the lead. They toiled their way to the farther end of the tunnel,
+then made their spliced kite-strings fast and moved on. A few steps
+brought them to the spring, and Tom felt a shudder quiver all through
+him. He showed Huck the fragment of candle-wick perched on a lump of
+clay against the wall, and described how he and Becky had watched the
+flame struggle and expire.
+
+The boys began to quiet down to whispers, now, for the stillness and
+gloom of the place oppressed their spirits. They went on, and presently
+entered and followed Tom's other corridor until they reached the
+"jumping-off place." The candles revealed the fact that it was not
+really a precipice, but only a steep clay hill twenty or thirty feet
+high. Tom whispered:
+
+"Now I'll show you something, Huck."
+
+He held his candle aloft and said:
+
+"Look as far around the corner as you can. Do you see that? There--on
+the big rock over yonder--done with candle-smoke."
+
+"Tom, it's a CROSS!"
+
+"NOW where's your Number Two? 'UNDER THE CROSS,' hey? Right yonder's
+where I saw Injun Joe poke up his candle, Huck!"
+
+Huck stared at the mystic sign awhile, and then said with a shaky voice:
+
+"Tom, less git out of here!"
+
+"What! and leave the treasure?"
+
+"Yes--leave it. Injun Joe's ghost is round about there, certain."
+
+"No it ain't, Huck, no it ain't. It would ha'nt the place where he
+died--away out at the mouth of the cave--five mile from here."
+
+"No, Tom, it wouldn't. It would hang round the money. I know the ways
+of ghosts, and so do you."
+
+Tom began to fear that Huck was right. Misgivings gathered in his
+mind. But presently an idea occurred to him--
+
+"Lookyhere, Huck, what fools we're making of ourselves! Injun Joe's
+ghost ain't a going to come around where there's a cross!"
+
+The point was well taken. It had its effect.
+
+"Tom, I didn't think of that. But that's so. It's luck for us, that
+cross is. I reckon we'll climb down there and have a hunt for that box."
+
+Tom went first, cutting rude steps in the clay hill as he descended.
+Huck followed. Four avenues opened out of the small cavern which the
+great rock stood in. The boys examined three of them with no result.
+They found a small recess in the one nearest the base of the rock, with
+a pallet of blankets spread down in it; also an old suspender, some
+bacon rind, and the well-gnawed bones of two or three fowls. But there
+was no money-box. The lads searched and researched this place, but in
+vain. Tom said:
+
+"He said UNDER the cross. Well, this comes nearest to being under the
+cross. It can't be under the rock itself, because that sets solid on
+the ground."
+
+They searched everywhere once more, and then sat down discouraged.
+Huck could suggest nothing. By-and-by Tom said:
+
+"Lookyhere, Huck, there's footprints and some candle-grease on the
+clay about one side of this rock, but not on the other sides. Now,
+what's that for? I bet you the money IS under the rock. I'm going to
+dig in the clay."
+
+"That ain't no bad notion, Tom!" said Huck with animation.
+
+Tom's "real Barlow" was out at once, and he had not dug four inches
+before he struck wood.
+
+"Hey, Huck!--you hear that?"
+
+Huck began to dig and scratch now. Some boards were soon uncovered and
+removed. They had concealed a natural chasm which led under the rock.
+Tom got into this and held his candle as far under the rock as he
+could, but said he could not see to the end of the rift. He proposed to
+explore. He stooped and passed under; the narrow way descended
+gradually. He followed its winding course, first to the right, then to
+the left, Huck at his heels. Tom turned a short curve, by-and-by, and
+exclaimed:
+
+"My goodness, Huck, lookyhere!"
+
+It was the treasure-box, sure enough, occupying a snug little cavern,
+along with an empty powder-keg, a couple of guns in leather cases, two
+or three pairs of old moccasins, a leather belt, and some other rubbish
+well soaked with the water-drip.
+
+"Got it at last!" said Huck, ploughing among the tarnished coins with
+his hand. "My, but we're rich, Tom!"
+
+"Huck, I always reckoned we'd get it. It's just too good to believe,
+but we HAVE got it, sure! Say--let's not fool around here. Let's snake
+it out. Lemme see if I can lift the box."
+
+It weighed about fifty pounds. Tom could lift it, after an awkward
+fashion, but could not carry it conveniently.
+
+"I thought so," he said; "THEY carried it like it was heavy, that day
+at the ha'nted house. I noticed that. I reckon I was right to think of
+fetching the little bags along."
+
+The money was soon in the bags and the boys took it up to the cross
+rock.
+
+"Now less fetch the guns and things," said Huck.
+
+"No, Huck--leave them there. They're just the tricks to have when we
+go to robbing. We'll keep them there all the time, and we'll hold our
+orgies there, too. It's an awful snug place for orgies."
+
+"What orgies?"
+
+"I dono. But robbers always have orgies, and of course we've got to
+have them, too. Come along, Huck, we've been in here a long time. It's
+getting late, I reckon. I'm hungry, too. We'll eat and smoke when we
+get to the skiff."
+
+They presently emerged into the clump of sumach bushes, looked warily
+out, found the coast clear, and were soon lunching and smoking in the
+skiff. As the sun dipped toward the horizon they pushed out and got
+under way. Tom skimmed up the shore through the long twilight, chatting
+cheerily with Huck, and landed shortly after dark.
+
+"Now, Huck," said Tom, "we'll hide the money in the loft of the
+widow's woodshed, and I'll come up in the morning and we'll count it
+and divide, and then we'll hunt up a place out in the woods for it
+where it will be safe. Just you lay quiet here and watch the stuff till
+I run and hook Benny Taylor's little wagon; I won't be gone a minute."
+
+He disappeared, and presently returned with the wagon, put the two
+small sacks into it, threw some old rags on top of them, and started
+off, dragging his cargo behind him. When the boys reached the
+Welshman's house, they stopped to rest. Just as they were about to move
+on, the Welshman stepped out and said:
+
+"Hallo, who's that?"
+
+"Huck and Tom Sawyer."
+
+"Good! Come along with me, boys, you are keeping everybody waiting.
+Here--hurry up, trot ahead--I'll haul the wagon for you. Why, it's not
+as light as it might be. Got bricks in it?--or old metal?"
+
+"Old metal," said Tom.
+
+"I judged so; the boys in this town will take more trouble and fool
+away more time hunting up six bits' worth of old iron to sell to the
+foundry than they would to make twice the money at regular work. But
+that's human nature--hurry along, hurry along!"
+
+The boys wanted to know what the hurry was about.
+
+"Never mind; you'll see, when we get to the Widow Douglas'."
+
+Huck said with some apprehension--for he was long used to being
+falsely accused:
+
+"Mr. Jones, we haven't been doing nothing."
+
+The Welshman laughed.
+
+"Well, I don't know, Huck, my boy. I don't know about that. Ain't you
+and the widow good friends?"
+
+"Yes. Well, she's ben good friends to me, anyway."
+
+"All right, then. What do you want to be afraid for?"
+
+This question was not entirely answered in Huck's slow mind before he
+found himself pushed, along with Tom, into Mrs. Douglas' drawing-room.
+Mr. Jones left the wagon near the door and followed.
+
+The place was grandly lighted, and everybody that was of any
+consequence in the village was there. The Thatchers were there, the
+Harpers, the Rogerses, Aunt Polly, Sid, Mary, the minister, the editor,
+and a great many more, and all dressed in their best. The widow
+received the boys as heartily as any one could well receive two such
+looking beings. They were covered with clay and candle-grease. Aunt
+Polly blushed crimson with humiliation, and frowned and shook her head
+at Tom. Nobody suffered half as much as the two boys did, however. Mr.
+Jones said:
+
+"Tom wasn't at home, yet, so I gave him up; but I stumbled on him and
+Huck right at my door, and so I just brought them along in a hurry."
+
+"And you did just right," said the widow. "Come with me, boys."
+
+She took them to a bedchamber and said:
+
+"Now wash and dress yourselves. Here are two new suits of clothes
+--shirts, socks, everything complete. They're Huck's--no, no thanks,
+Huck--Mr. Jones bought one and I the other. But they'll fit both of you.
+Get into them. We'll wait--come down when you are slicked up enough."
+
+Then she left.
+
+
+
+CHAPTER XXXIV
+
+HUCK said: "Tom, we can slope, if we can find a rope. The window ain't
+high from the ground."
+
+"Shucks! what do you want to slope for?"
+
+"Well, I ain't used to that kind of a crowd. I can't stand it. I ain't
+going down there, Tom."
+
+"Oh, bother! It ain't anything. I don't mind it a bit. I'll take care
+of you."
+
+Sid appeared.
+
+"Tom," said he, "auntie has been waiting for you all the afternoon.
+Mary got your Sunday clothes ready, and everybody's been fretting about
+you. Say--ain't this grease and clay, on your clothes?"
+
+"Now, Mr. Siddy, you jist 'tend to your own business. What's all this
+blow-out about, anyway?"
+
+"It's one of the widow's parties that she's always having. This time
+it's for the Welshman and his sons, on account of that scrape they
+helped her out of the other night. And say--I can tell you something,
+if you want to know."
+
+"Well, what?"
+
+"Why, old Mr. Jones is going to try to spring something on the people
+here to-night, but I overheard him tell auntie to-day about it, as a
+secret, but I reckon it's not much of a secret now. Everybody knows
+--the widow, too, for all she tries to let on she don't. Mr. Jones was
+bound Huck should be here--couldn't get along with his grand secret
+without Huck, you know!"
+
+"Secret about what, Sid?"
+
+"About Huck tracking the robbers to the widow's. I reckon Mr. Jones
+was going to make a grand time over his surprise, but I bet you it will
+drop pretty flat."
+
+Sid chuckled in a very contented and satisfied way.
+
+"Sid, was it you that told?"
+
+"Oh, never mind who it was. SOMEBODY told--that's enough."
+
+"Sid, there's only one person in this town mean enough to do that, and
+that's you. If you had been in Huck's place you'd 'a' sneaked down the
+hill and never told anybody on the robbers. You can't do any but mean
+things, and you can't bear to see anybody praised for doing good ones.
+There--no thanks, as the widow says"--and Tom cuffed Sid's ears and
+helped him to the door with several kicks. "Now go and tell auntie if
+you dare--and to-morrow you'll catch it!"
+
+Some minutes later the widow's guests were at the supper-table, and a
+dozen children were propped up at little side-tables in the same room,
+after the fashion of that country and that day. At the proper time Mr.
+Jones made his little speech, in which he thanked the widow for the
+honor she was doing himself and his sons, but said that there was
+another person whose modesty--
+
+And so forth and so on. He sprung his secret about Huck's share in the
+adventure in the finest dramatic manner he was master of, but the
+surprise it occasioned was largely counterfeit and not as clamorous and
+effusive as it might have been under happier circumstances. However,
+the widow made a pretty fair show of astonishment, and heaped so many
+compliments and so much gratitude upon Huck that he almost forgot the
+nearly intolerable discomfort of his new clothes in the entirely
+intolerable discomfort of being set up as a target for everybody's gaze
+and everybody's laudations.
+
+The widow said she meant to give Huck a home under her roof and have
+him educated; and that when she could spare the money she would start
+him in business in a modest way. Tom's chance was come. He said:
+
+"Huck don't need it. Huck's rich."
+
+Nothing but a heavy strain upon the good manners of the company kept
+back the due and proper complimentary laugh at this pleasant joke. But
+the silence was a little awkward. Tom broke it:
+
+"Huck's got money. Maybe you don't believe it, but he's got lots of
+it. Oh, you needn't smile--I reckon I can show you. You just wait a
+minute."
+
+Tom ran out of doors. The company looked at each other with a
+perplexed interest--and inquiringly at Huck, who was tongue-tied.
+
+"Sid, what ails Tom?" said Aunt Polly. "He--well, there ain't ever any
+making of that boy out. I never--"
+
+Tom entered, struggling with the weight of his sacks, and Aunt Polly
+did not finish her sentence. Tom poured the mass of yellow coin upon
+the table and said:
+
+"There--what did I tell you? Half of it's Huck's and half of it's mine!"
+
+The spectacle took the general breath away. All gazed, nobody spoke
+for a moment. Then there was a unanimous call for an explanation. Tom
+said he could furnish it, and he did. The tale was long, but brimful of
+interest. There was scarcely an interruption from any one to break the
+charm of its flow. When he had finished, Mr. Jones said:
+
+"I thought I had fixed up a little surprise for this occasion, but it
+don't amount to anything now. This one makes it sing mighty small, I'm
+willing to allow."
+
+The money was counted. The sum amounted to a little over twelve
+thousand dollars. It was more than any one present had ever seen at one
+time before, though several persons were there who were worth
+considerably more than that in property.
+
+
+
+CHAPTER XXXV
+
+THE reader may rest satisfied that Tom's and Huck's windfall made a
+mighty stir in the poor little village of St. Petersburg. So vast a
+sum, all in actual cash, seemed next to incredible. It was talked
+about, gloated over, glorified, until the reason of many of the
+citizens tottered under the strain of the unhealthy excitement. Every
+"haunted" house in St. Petersburg and the neighboring villages was
+dissected, plank by plank, and its foundations dug up and ransacked for
+hidden treasure--and not by boys, but men--pretty grave, unromantic
+men, too, some of them. Wherever Tom and Huck appeared they were
+courted, admired, stared at. The boys were not able to remember that
+their remarks had possessed weight before; but now their sayings were
+treasured and repeated; everything they did seemed somehow to be
+regarded as remarkable; they had evidently lost the power of doing and
+saying commonplace things; moreover, their past history was raked up
+and discovered to bear marks of conspicuous originality. The village
+paper published biographical sketches of the boys.
+
+The Widow Douglas put Huck's money out at six per cent., and Judge
+Thatcher did the same with Tom's at Aunt Polly's request. Each lad had
+an income, now, that was simply prodigious--a dollar for every week-day
+in the year and half of the Sundays. It was just what the minister got
+--no, it was what he was promised--he generally couldn't collect it. A
+dollar and a quarter a week would board, lodge, and school a boy in
+those old simple days--and clothe him and wash him, too, for that
+matter.
+
+Judge Thatcher had conceived a great opinion of Tom. He said that no
+commonplace boy would ever have got his daughter out of the cave. When
+Becky told her father, in strict confidence, how Tom had taken her
+whipping at school, the Judge was visibly moved; and when she pleaded
+grace for the mighty lie which Tom had told in order to shift that
+whipping from her shoulders to his own, the Judge said with a fine
+outburst that it was a noble, a generous, a magnanimous lie--a lie that
+was worthy to hold up its head and march down through history breast to
+breast with George Washington's lauded Truth about the hatchet! Becky
+thought her father had never looked so tall and so superb as when he
+walked the floor and stamped his foot and said that. She went straight
+off and told Tom about it.
+
+Judge Thatcher hoped to see Tom a great lawyer or a great soldier some
+day. He said he meant to look to it that Tom should be admitted to the
+National Military Academy and afterward trained in the best law school
+in the country, in order that he might be ready for either career or
+both.
+
+Huck Finn's wealth and the fact that he was now under the Widow
+Douglas' protection introduced him into society--no, dragged him into
+it, hurled him into it--and his sufferings were almost more than he
+could bear. The widow's servants kept him clean and neat, combed and
+brushed, and they bedded him nightly in unsympathetic sheets that had
+not one little spot or stain which he could press to his heart and know
+for a friend. He had to eat with a knife and fork; he had to use
+napkin, cup, and plate; he had to learn his book, he had to go to
+church; he had to talk so properly that speech was become insipid in
+his mouth; whithersoever he turned, the bars and shackles of
+civilization shut him in and bound him hand and foot.
+
+He bravely bore his miseries three weeks, and then one day turned up
+missing. For forty-eight hours the widow hunted for him everywhere in
+great distress. The public were profoundly concerned; they searched
+high and low, they dragged the river for his body. Early the third
+morning Tom Sawyer wisely went poking among some old empty hogsheads
+down behind the abandoned slaughter-house, and in one of them he found
+the refugee. Huck had slept there; he had just breakfasted upon some
+stolen odds and ends of food, and was lying off, now, in comfort, with
+his pipe. He was unkempt, uncombed, and clad in the same old ruin of
+rags that had made him picturesque in the days when he was free and
+happy. Tom routed him out, told him the trouble he had been causing,
+and urged him to go home. Huck's face lost its tranquil content, and
+took a melancholy cast. He said:
+
+"Don't talk about it, Tom. I've tried it, and it don't work; it don't
+work, Tom. It ain't for me; I ain't used to it. The widder's good to
+me, and friendly; but I can't stand them ways. She makes me get up just
+at the same time every morning; she makes me wash, they comb me all to
+thunder; she won't let me sleep in the woodshed; I got to wear them
+blamed clothes that just smothers me, Tom; they don't seem to any air
+git through 'em, somehow; and they're so rotten nice that I can't set
+down, nor lay down, nor roll around anywher's; I hain't slid on a
+cellar-door for--well, it 'pears to be years; I got to go to church and
+sweat and sweat--I hate them ornery sermons! I can't ketch a fly in
+there, I can't chaw. I got to wear shoes all Sunday. The widder eats by
+a bell; she goes to bed by a bell; she gits up by a bell--everything's
+so awful reg'lar a body can't stand it."
+
+"Well, everybody does that way, Huck."
+
+"Tom, it don't make no difference. I ain't everybody, and I can't
+STAND it. It's awful to be tied up so. And grub comes too easy--I don't
+take no interest in vittles, that way. I got to ask to go a-fishing; I
+got to ask to go in a-swimming--dern'd if I hain't got to ask to do
+everything. Well, I'd got to talk so nice it wasn't no comfort--I'd got
+to go up in the attic and rip out awhile, every day, to git a taste in
+my mouth, or I'd a died, Tom. The widder wouldn't let me smoke; she
+wouldn't let me yell, she wouldn't let me gape, nor stretch, nor
+scratch, before folks--" [Then with a spasm of special irritation and
+injury]--"And dad fetch it, she prayed all the time! I never see such a
+woman! I HAD to shove, Tom--I just had to. And besides, that school's
+going to open, and I'd a had to go to it--well, I wouldn't stand THAT,
+Tom. Looky here, Tom, being rich ain't what it's cracked up to be. It's
+just worry and worry, and sweat and sweat, and a-wishing you was dead
+all the time. Now these clothes suits me, and this bar'l suits me, and
+I ain't ever going to shake 'em any more. Tom, I wouldn't ever got into
+all this trouble if it hadn't 'a' ben for that money; now you just take
+my sheer of it along with your'n, and gimme a ten-center sometimes--not
+many times, becuz I don't give a dern for a thing 'thout it's tollable
+hard to git--and you go and beg off for me with the widder."
+
+"Oh, Huck, you know I can't do that. 'Tain't fair; and besides if
+you'll try this thing just a while longer you'll come to like it."
+
+"Like it! Yes--the way I'd like a hot stove if I was to set on it long
+enough. No, Tom, I won't be rich, and I won't live in them cussed
+smothery houses. I like the woods, and the river, and hogsheads, and
+I'll stick to 'em, too. Blame it all! just as we'd got guns, and a
+cave, and all just fixed to rob, here this dern foolishness has got to
+come up and spile it all!"
+
+Tom saw his opportunity--
+
+"Lookyhere, Huck, being rich ain't going to keep me back from turning
+robber."
+
+"No! Oh, good-licks; are you in real dead-wood earnest, Tom?"
+
+"Just as dead earnest as I'm sitting here. But Huck, we can't let you
+into the gang if you ain't respectable, you know."
+
+Huck's joy was quenched.
+
+"Can't let me in, Tom? Didn't you let me go for a pirate?"
+
+"Yes, but that's different. A robber is more high-toned than what a
+pirate is--as a general thing. In most countries they're awful high up
+in the nobility--dukes and such."
+
+"Now, Tom, hain't you always ben friendly to me? You wouldn't shet me
+out, would you, Tom? You wouldn't do that, now, WOULD you, Tom?"
+
+"Huck, I wouldn't want to, and I DON'T want to--but what would people
+say? Why, they'd say, 'Mph! Tom Sawyer's Gang! pretty low characters in
+it!' They'd mean you, Huck. You wouldn't like that, and I wouldn't."
+
+Huck was silent for some time, engaged in a mental struggle. Finally
+he said:
+
+"Well, I'll go back to the widder for a month and tackle it and see if
+I can come to stand it, if you'll let me b'long to the gang, Tom."
+
+"All right, Huck, it's a whiz! Come along, old chap, and I'll ask the
+widow to let up on you a little, Huck."
+
+"Will you, Tom--now will you? That's good. If she'll let up on some of
+the roughest things, I'll smoke private and cuss private, and crowd
+through or bust. When you going to start the gang and turn robbers?"
+
+"Oh, right off. We'll get the boys together and have the initiation
+to-night, maybe."
+
+"Have the which?"
+
+"Have the initiation."
+
+"What's that?"
+
+"It's to swear to stand by one another, and never tell the gang's
+secrets, even if you're chopped all to flinders, and kill anybody and
+all his family that hurts one of the gang."
+
+"That's gay--that's mighty gay, Tom, I tell you."
+
+"Well, I bet it is. And all that swearing's got to be done at
+midnight, in the lonesomest, awfulest place you can find--a ha'nted
+house is the best, but they're all ripped up now."
+
+"Well, midnight's good, anyway, Tom."
+
+"Yes, so it is. And you've got to swear on a coffin, and sign it with
+blood."
+
+"Now, that's something LIKE! Why, it's a million times bullier than
+pirating. I'll stick to the widder till I rot, Tom; and if I git to be
+a reg'lar ripper of a robber, and everybody talking 'bout it, I reckon
+she'll be proud she snaked me in out of the wet."
+
+
+
+CONCLUSION
+
+SO endeth this chronicle. It being strictly a history of a BOY, it
+must stop here; the story could not go much further without becoming
+the history of a MAN. When one writes a novel about grown people, he
+knows exactly where to stop--that is, with a marriage; but when he
+writes of juveniles, he must stop where he best can.
+
+Most of the characters that perform in this book still live, and are
+prosperous and happy. Some day it may seem worth while to take up the
+story of the younger ones again and see what sort of men and women they
+turned out to be; therefore it will be wisest not to reveal any of that
+part of their lives at present.
+
+
+
+
+
+End of the Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
+by Mark Twain (Samuel Clemens)
+
+*** END OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
+
+***** This file should be named 74.txt or 74.zip *****
+This and all associated files of various formats will be found in:
+        http://www.gutenberg.net/7/74/
+
+Produced by David Widger. The previous edition was update by Jose
+Menendez.
+
+
+Updated editions will replace the previous one--the old editions
+will be renamed.
+
+Creating the works from public domain print editions means that no
+one owns a United States copyright in these works, so the Foundation
+(and you!) can copy and distribute it in the United States without
+permission and without paying copyright royalties.  Special rules,
+set forth in the General Terms of Use part of this license, apply to
+copying and distributing Project Gutenberg-tm electronic works to
+protect the PROJECT GUTENBERG-tm concept and trademark.  Project
+Gutenberg is a registered trademark, and may not be used if you
+charge for the eBooks, unless you receive specific permission.  If you
+do not charge anything for copies of this eBook, complying with the
+rules is very easy.  You may use this eBook for nearly any purpose
+such as creation of derivative works, reports, performances and
+research.  They may be modified and printed and given away--you may do
+practically ANYTHING with public domain eBooks.  Redistribution is
+subject to the trademark license, especially commercial
+redistribution.
+
+
+
+*** START: FULL LICENSE ***
+
+THE FULL PROJECT GUTENBERG LICENSE
+PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
+
+To protect the Project Gutenberg-tm mission of promoting the free
+distribution of electronic works, by using or distributing this work
+(or any other work associated in any way with the phrase "Project
+Gutenberg"), you agree to comply with all the terms of the Full Project
+Gutenberg-tm License (available with this file or online at
+http://gutenberg.net/license).
+
+
+Section 1.  General Terms of Use and Redistributing Project Gutenberg-tm
+electronic works
+
+1.A.  By reading or using any part of this Project Gutenberg-tm
+electronic work, you indicate that you have read, understand, agree to
+and accept all the terms of this license and intellectual property
+(trademark/copyright) agreement.  If you do not agree to abide by all
+the terms of this agreement, you must cease using and return or destroy
+all copies of Project Gutenberg-tm electronic works in your possession.
+If you paid a fee for obtaining a copy of or access to a Project
+Gutenberg-tm electronic work and you do not agree to be bound by the
+terms of this agreement, you may obtain a refund from the person or
+entity to whom you paid the fee as set forth in paragraph 1.E.8.
+
+1.B.  "Project Gutenberg" is a registered trademark.  It may only be
+used on or associated in any way with an electronic work by people who
+agree to be bound by the terms of this agreement.  There are a few
+things that you can do with most Project Gutenberg-tm electronic works
+even without complying with the full terms of this agreement.  See
+paragraph 1.C below.  There are a lot of things you can do with Project
+Gutenberg-tm electronic works if you follow the terms of this agreement
+and help preserve free future access to Project Gutenberg-tm electronic
+works.  See paragraph 1.E below.
+
+1.C.  The Project Gutenberg Literary Archive Foundation ("the Foundation"
+or PGLAF), owns a compilation copyright in the collection of Project
+Gutenberg-tm electronic works.  Nearly all the individual works in the
+collection are in the public domain in the United States.  If an
+individual work is in the public domain in the United States and you are
+located in the United States, we do not claim a right to prevent you from
+copying, distributing, performing, displaying or creating derivative
+works based on the work as long as all references to Project Gutenberg
+are removed.  Of course, we hope that you will support the Project
+Gutenberg-tm mission of promoting free access to electronic works by
+freely sharing Project Gutenberg-tm works in compliance with the terms of
+this agreement for keeping the Project Gutenberg-tm name associated with
+the work.  You can easily comply with the terms of this agreement by
+keeping this work in the same format with its attached full Project
+Gutenberg-tm License when you share it without charge with others.
+
+1.D.  The copyright laws of the place where you are located also govern
+what you can do with this work.  Copyright laws in most countries are in
+a constant state of change.  If you are outside the United States, check
+the laws of your country in addition to the terms of this agreement
+before downloading, copying, displaying, performing, distributing or
+creating derivative works based on this work or any other Project
+Gutenberg-tm work.  The Foundation makes no representations concerning
+the copyright status of any work in any country outside the United
+States.
+
+1.E.  Unless you have removed all references to Project Gutenberg:
+
+1.E.1.  The following sentence, with active links to, or other immediate
+access to, the full Project Gutenberg-tm License must appear prominently
+whenever any copy of a Project Gutenberg-tm work (any work on which the
+phrase "Project Gutenberg" appears, or with which the phrase "Project
+Gutenberg" is associated) is accessed, displayed, performed, viewed,
+copied or distributed:
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.net
+
+1.E.2.  If an individual Project Gutenberg-tm electronic work is derived
+from the public domain (does not contain a notice indicating that it is
+posted with permission of the copyright holder), the work can be copied
+and distributed to anyone in the United States without paying any fees
+or charges.  If you are redistributing or providing access to a work
+with the phrase "Project Gutenberg" associated with or appearing on the
+work, you must comply either with the requirements of paragraphs 1.E.1
+through 1.E.7 or obtain permission for the use of the work and the
+Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or
+1.E.9.
+
+1.E.3.  If an individual Project Gutenberg-tm electronic work is posted
+with the permission of the copyright holder, your use and distribution
+must comply with both paragraphs 1.E.1 through 1.E.7 and any additional
+terms imposed by the copyright holder.  Additional terms will be linked
+to the Project Gutenberg-tm License for all works posted with the
+permission of the copyright holder found at the beginning of this work.
+
+1.E.4.  Do not unlink or detach or remove the full Project Gutenberg-tm
+License terms from this work, or any files containing a part of this
+work or any other work associated with Project Gutenberg-tm.
+
+1.E.5.  Do not copy, display, perform, distribute or redistribute this
+electronic work, or any part of this electronic work, without
+prominently displaying the sentence set forth in paragraph 1.E.1 with
+active links or immediate access to the full terms of the Project
+Gutenberg-tm License.
+
+1.E.6.  You may convert to and distribute this work in any binary,
+compressed, marked up, nonproprietary or proprietary form, including any
+word processing or hypertext form.  However, if you provide access to or
+distribute copies of a Project Gutenberg-tm work in a format other than
+"Plain Vanilla ASCII" or other format used in the official version
+posted on the official Project Gutenberg-tm web site (www.gutenberg.net),
+you must, at no additional cost, fee or expense to the user, provide a
+copy, a means of exporting a copy, or a means of obtaining a copy upon
+request, of the work in its original "Plain Vanilla ASCII" or other
+form.  Any alternate format must include the full Project Gutenberg-tm
+License as specified in paragraph 1.E.1.
+
+1.E.7.  Do not charge a fee for access to, viewing, displaying,
+performing, copying or distributing any Project Gutenberg-tm works
+unless you comply with paragraph 1.E.8 or 1.E.9.
+
+1.E.8.  You may charge a reasonable fee for copies of or providing
+access to or distributing Project Gutenberg-tm electronic works provided
+that
+
+- You pay a royalty fee of 20% of the gross profits you derive from
+     the use of Project Gutenberg-tm works calculated using the method
+     you already use to calculate your applicable taxes.  The fee is
+     owed to the owner of the Project Gutenberg-tm trademark, but he
+     has agreed to donate royalties under this paragraph to the
+     Project Gutenberg Literary Archive Foundation.  Royalty payments
+     must be paid within 60 days following each date on which you
+     prepare (or are legally required to prepare) your periodic tax
+     returns.  Royalty payments should be clearly marked as such and
+     sent to the Project Gutenberg Literary Archive Foundation at the
+     address specified in Section 4, "Information about donations to
+     the Project Gutenberg Literary Archive Foundation."
+
+- You provide a full refund of any money paid by a user who notifies
+     you in writing (or by e-mail) within 30 days of receipt that s/he
+     does not agree to the terms of the full Project Gutenberg-tm
+     License.  You must require such a user to return or
+     destroy all copies of the works possessed in a physical medium
+     and discontinue all use of and all access to other copies of
+     Project Gutenberg-tm works.
+
+- You provide, in accordance with paragraph 1.F.3, a full refund of any
+     money paid for a work or a replacement copy, if a defect in the
+     electronic work is discovered and reported to you within 90 days
+     of receipt of the work.
+
+- You comply with all other terms of this agreement for free
+     distribution of Project Gutenberg-tm works.
+
+1.E.9.  If you wish to charge a fee or distribute a Project Gutenberg-tm
+electronic work or group of works on different terms than are set
+forth in this agreement, you must obtain permission in writing from
+both the Project Gutenberg Literary Archive Foundation and Michael
+Hart, the owner of the Project Gutenberg-tm trademark.  Contact the
+Foundation as set forth in Section 3 below.
+
+1.F.
+
+1.F.1.  Project Gutenberg volunteers and employees expend considerable
+effort to identify, do copyright research on, transcribe and proofread
+public domain works in creating the Project Gutenberg-tm
+collection.  Despite these efforts, Project Gutenberg-tm electronic
+works, and the medium on which they may be stored, may contain
+"Defects," such as, but not limited to, incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other intellectual
+property infringement, a defective or damaged disk or other medium, a
+computer virus, or computer codes that damage or cannot be read by
+your equipment.
+
+1.F.2.  LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right
+of Replacement or Refund" described in paragraph 1.F.3, the Project
+Gutenberg Literary Archive Foundation, the owner of the Project
+Gutenberg-tm trademark, and any other party distributing a Project
+Gutenberg-tm electronic work under this agreement, disclaim all
+liability to you for damages, costs and expenses, including legal
+fees.  YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
+LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
+PROVIDED IN PARAGRAPH F3.  YOU AGREE THAT THE FOUNDATION, THE
+TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE
+LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
+INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+1.F.3.  LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a
+defect in this electronic work within 90 days of receiving it, you can
+receive a refund of the money (if any) you paid for it by sending a
+written explanation to the person you received the work from.  If you
+received the work on a physical medium, you must return the medium with
+your written explanation.  The person or entity that provided you with
+the defective work may elect to provide a replacement copy in lieu of a
+refund.  If you received the work electronically, the person or entity
+providing it to you may choose to give you a second opportunity to
+receive the work electronically in lieu of a refund.  If the second copy
+is also defective, you may demand a refund in writing without further
+opportunities to fix the problem.
+
+1.F.4.  Except for the limited right of replacement or refund set forth
+in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.
+
+1.F.5.  Some states do not allow disclaimers of certain implied
+warranties or the exclusion or limitation of certain types of damages.
+If any disclaimer or limitation set forth in this agreement violates the
+law of the state applicable to this agreement, the agreement shall be
+interpreted to make the maximum disclaimer or limitation permitted by
+the applicable state law.  The invalidity or unenforceability of any
+provision of this agreement shall not void the remaining provisions.
+
+1.F.6.  INDEMNITY - You agree to indemnify and hold the Foundation, the
+trademark owner, any agent or employee of the Foundation, anyone
+providing copies of Project Gutenberg-tm electronic works in accordance
+with this agreement, and any volunteers associated with the production,
+promotion and distribution of Project Gutenberg-tm electronic works,
+harmless from all liability, costs and expenses, including legal fees,
+that arise directly or indirectly from any of the following which you do
+or cause to occur: (a) distribution of this or any Project Gutenberg-tm
+work, (b) alteration, modification, or additions or deletions to any
+Project Gutenberg-tm work, and (c) any Defect you cause.
+
+
+Section  2.  Information about the Mission of Project Gutenberg-tm
+
+Project Gutenberg-tm is synonymous with the free distribution of
+electronic works in formats readable by the widest variety of computers
+including obsolete, old, middle-aged and new computers.  It exists
+because of the efforts of hundreds of volunteers and donations from
+people in all walks of life.
+
+Volunteers and financial support to provide volunteers with the
+assistance they need, is critical to reaching Project Gutenberg-tm's
+goals and ensuring that the Project Gutenberg-tm collection will
+remain freely available for generations to come.  In 2001, the Project
+Gutenberg Literary Archive Foundation was created to provide a secure
+and permanent future for Project Gutenberg-tm and future generations.
+To learn more about the Project Gutenberg Literary Archive Foundation
+and how your efforts and donations can help, see Sections 3 and 4
+and the Foundation web page at http://www.pglaf.org.
+
+
+Section 3.  Information about the Project Gutenberg Literary Archive
+Foundation
+
+The Project Gutenberg Literary Archive Foundation is a non profit
+501(c)(3) educational corporation organized under the laws of the
+state of Mississippi and granted tax exempt status by the Internal
+Revenue Service.  The Foundation's EIN or federal tax identification
+number is 64-6221541.  Its 501(c)(3) letter is posted at
+http://pglaf.org/fundraising.  Contributions to the Project Gutenberg
+Literary Archive Foundation are tax deductible to the full extent
+permitted by U.S. federal laws and your state's laws.
+
+The Foundation's principal office is located at 4557 Melan Dr. S.
+Fairbanks, AK, 99712., but its volunteers and employees are scattered
+throughout numerous locations.  Its business office is located at
+809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email
+business@pglaf.org.  Email contact links and up to date contact
+information can be found at the Foundation's web site and official
+page at http://pglaf.org
+
+For additional contact information:
+     Dr. Gregory B. Newby
+     Chief Executive and Director
+     gbnewby@pglaf.org
+
+
+Section 4.  Information about Donations to the Project Gutenberg
+Literary Archive Foundation
+
+Project Gutenberg-tm depends upon and cannot survive without wide
+spread public support and donations to carry out its mission of
+increasing the number of public domain and licensed works that can be
+freely distributed in machine readable form accessible by the widest
+array of equipment including outdated equipment.  Many small donations
+($1 to $5,000) are particularly important to maintaining tax exempt
+status with the IRS.
+
+The Foundation is committed to complying with the laws regulating
+charities and charitable donations in all 50 states of the United
+States.  Compliance requirements are not uniform and it takes a
+considerable effort, much paperwork and many fees to meet and keep up
+with these requirements.  We do not solicit donations in locations
+where we have not received written confirmation of compliance.  To
+SEND DONATIONS or determine the status of compliance for any
+particular state visit http://pglaf.org
+
+While we cannot and do not solicit contributions from states where we
+have not met the solicitation requirements, we know of no prohibition
+against accepting unsolicited donations from donors in such states who
+approach us with offers to donate.
+
+International donations are gratefully accepted, but we cannot make
+any statements concerning tax treatment of donations received from
+outside the United States.  U.S. laws alone swamp our small staff.
+
+Please check the Project Gutenberg Web pages for current donation
+methods and addresses.  Donations are accepted in a number of other
+ways including including checks, online payments and credit card
+donations.  To donate, please visit: http://pglaf.org/donate
+
+
+Section 5.  General Information About Project Gutenberg-tm electronic
+works.
+
+Professor Michael S. Hart is the originator of the Project Gutenberg-tm
+concept of a library of electronic works that could be freely shared
+with anyone.  For thirty years, he produced and distributed Project
+Gutenberg-tm eBooks with only a loose network of volunteer support.
+
+
+Project Gutenberg-tm eBooks are often created from several printed
+editions, all of which are confirmed as Public Domain in the U.S.
+unless a copyright notice is included.  Thus, we do not necessarily
+keep eBooks in compliance with any particular paper edition.
+
+
+Most people start at our Web site which has the main PG search facility:
+
+     http://www.gutenberg.net
+
+This Web site includes information about Project Gutenberg-tm,
+including how to make donations to the Project Gutenberg Literary
+Archive Foundation, how to help produce our new eBooks, and how to
+subscribe to our email newsletter to hear about new eBooks.
index 50a1e6c357fca4cede2b1f31a146536ba9c140f5..4638a6548425bb44bb86db2f5682a54472a42bdb 100644 (file)
@@ -34,9 +34,9 @@ import (
 
 const zlibDeflate = 8
 
-var ChecksumError = errors.New("zlib checksum error")
-var HeaderError = errors.New("invalid zlib header")
-var DictionaryError = errors.New("invalid zlib dictionary")
+var ErrChecksum = errors.New("zlib checksum error")
+var ErrHeader = errors.New("invalid zlib header")
+var ErrDictionary = errors.New("invalid zlib dictionary")
 
 type reader struct {
        r            flate.Reader
@@ -68,7 +68,7 @@ func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
        }
        h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
        if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
-               return nil, HeaderError
+               return nil, ErrHeader
        }
        if z.scratch[1]&0x20 != 0 {
                _, err = io.ReadFull(z.r, z.scratch[0:4])
@@ -77,7 +77,7 @@ func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
                }
                checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
                if checksum != adler32.Checksum(dict) {
-                       return nil, DictionaryError
+                       return nil, ErrDictionary
                }
                z.decompressor = flate.NewReaderDict(z.r, dict)
        } else {
@@ -110,7 +110,7 @@ func (z *reader) Read(p []byte) (n int, err error) {
        // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
        checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
        if checksum != z.digest.Sum32() {
-               z.err = ChecksumError
+               z.err = ErrChecksum
                return 0, z.err
        }
        return
index d8f9f21478c35140a75902b86eb4694cdf04b7a8..3b02a086845806222e48910920b50c855092a02e 100644 (file)
@@ -45,14 +45,14 @@ var zlibTests = []zlibTest{
                "",
                []byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
                nil,
-               HeaderError,
+               ErrHeader,
        },
        {
                "bad checksum",
                "",
                []byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
                nil,
-               ChecksumError,
+               ErrChecksum,
        },
        {
                "not enough data",
@@ -95,7 +95,7 @@ var zlibTests = []zlibTest{
                []byte{
                        0x48, 0x65, 0x6c, 0x6c,
                },
-               DictionaryError,
+               ErrDictionary,
        },
 }
 
diff --git a/libgo/go/crypto/bcrypt/base64.go b/libgo/go/crypto/bcrypt/base64.go
deleted file mode 100644 (file)
index fc31160..0000000
+++ /dev/null
@@ -1,35 +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 bcrypt
-
-import "encoding/base64"
-
-const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-
-var bcEncoding = base64.NewEncoding(alphabet)
-
-func base64Encode(src []byte) []byte {
-       n := bcEncoding.EncodedLen(len(src))
-       dst := make([]byte, n)
-       bcEncoding.Encode(dst, src)
-       for dst[n-1] == '=' {
-               n--
-       }
-       return dst[:n]
-}
-
-func base64Decode(src []byte) ([]byte, error) {
-       numOfEquals := 4 - (len(src) % 4)
-       for i := 0; i < numOfEquals; i++ {
-               src = append(src, '=')
-       }
-
-       dst := make([]byte, bcEncoding.DecodedLen(len(src)))
-       n, err := bcEncoding.Decode(dst, src)
-       if err != nil {
-               return nil, err
-       }
-       return dst[:n], nil
-}
diff --git a/libgo/go/crypto/bcrypt/bcrypt.go b/libgo/go/crypto/bcrypt/bcrypt.go
deleted file mode 100644 (file)
index 362b2eb..0000000
+++ /dev/null
@@ -1,282 +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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing
-// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
-package bcrypt
-
-// The code is a port of Provos and Mazières's C implementation. 
-import (
-       "crypto/blowfish"
-       "crypto/rand"
-       "crypto/subtle"
-       "errors"
-       "fmt"
-       "io"
-       "strconv"
-)
-
-const (
-       MinCost     int = 4  // the minimum allowable cost as passed in to GenerateFromPassword
-       MaxCost     int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
-       DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
-)
-
-// The error returned from CompareHashAndPassword when a password and hash do
-// not match.
-var MismatchedHashAndPasswordError = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
-
-// The error returned from CompareHashAndPassword when a hash is too short to
-// be a bcrypt hash.
-var HashTooShortError = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
-
-// The error returned from CompareHashAndPassword when a hash was created with
-// a bcrypt algorithm newer than this implementation.
-type HashVersionTooNewError byte
-
-func (hv HashVersionTooNewError) Error() string {
-       return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
-}
-
-// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
-type InvalidHashPrefixError byte
-
-func (ih InvalidHashPrefixError) Error() string {
-       return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
-}
-
-type InvalidCostError int
-
-func (ic InvalidCostError) Error() string {
-       return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
-}
-
-const (
-       majorVersion       = '2'
-       minorVersion       = 'a'
-       maxSaltSize        = 16
-       maxCryptedHashSize = 23
-       encodedSaltSize    = 22
-       encodedHashSize    = 31
-       minHashSize        = 59
-)
-
-// magicCipherData is an IV for the 64 Blowfish encryption calls in
-// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
-var magicCipherData = []byte{
-       0x4f, 0x72, 0x70, 0x68,
-       0x65, 0x61, 0x6e, 0x42,
-       0x65, 0x68, 0x6f, 0x6c,
-       0x64, 0x65, 0x72, 0x53,
-       0x63, 0x72, 0x79, 0x44,
-       0x6f, 0x75, 0x62, 0x74,
-}
-
-type hashed struct {
-       hash  []byte
-       salt  []byte
-       cost  uint32 // allowed range is MinCost to MaxCost
-       major byte
-       minor byte
-}
-
-// GenerateFromPassword returns the bcrypt hash of the password at the given
-// cost. If the cost given is less than MinCost, the cost will be set to
-// MinCost, instead. Use CompareHashAndPassword, as defined in this package,
-// to compare the returned hashed password with its cleartext version.
-func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
-       p, err := newFromPassword(password, cost)
-       if err != nil {
-               return nil, err
-       }
-       return p.Hash(), nil
-}
-
-// CompareHashAndPassword compares a bcrypt hashed password with its possible
-// plaintext equivalent. Note: Using bytes.Equal for this job is
-// insecure. Returns nil on success, or an error on failure.
-func CompareHashAndPassword(hashedPassword, password []byte) error {
-       p, err := newFromHash(hashedPassword)
-       if err != nil {
-               return err
-       }
-
-       otherHash, err := bcrypt(password, p.cost, p.salt)
-       if err != nil {
-               return err
-       }
-
-       otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
-       if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
-               return nil
-       }
-
-       return MismatchedHashAndPasswordError
-}
-
-func newFromPassword(password []byte, cost int) (*hashed, error) {
-       if cost < MinCost {
-               cost = DefaultCost
-       }
-       p := new(hashed)
-       p.major = majorVersion
-       p.minor = minorVersion
-
-       err := checkCost(cost)
-       if err != nil {
-               return nil, err
-       }
-       p.cost = uint32(cost)
-
-       unencodedSalt := make([]byte, maxSaltSize)
-       _, err = io.ReadFull(rand.Reader, unencodedSalt)
-       if err != nil {
-               return nil, err
-       }
-
-       p.salt = base64Encode(unencodedSalt)
-       hash, err := bcrypt(password, p.cost, p.salt)
-       if err != nil {
-               return nil, err
-       }
-       p.hash = hash
-       return p, err
-}
-
-func newFromHash(hashedSecret []byte) (*hashed, error) {
-       if len(hashedSecret) < minHashSize {
-               return nil, HashTooShortError
-       }
-       p := new(hashed)
-       n, err := p.decodeVersion(hashedSecret)
-       if err != nil {
-               return nil, err
-       }
-       hashedSecret = hashedSecret[n:]
-       n, err = p.decodeCost(hashedSecret)
-       if err != nil {
-               return nil, err
-       }
-       hashedSecret = hashedSecret[n:]
-
-       // The "+2" is here because we'll have to append at most 2 '=' to the salt
-       // when base64 decoding it in expensiveBlowfishSetup().
-       p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
-       copy(p.salt, hashedSecret[:encodedSaltSize])
-
-       hashedSecret = hashedSecret[encodedSaltSize:]
-       p.hash = make([]byte, len(hashedSecret))
-       copy(p.hash, hashedSecret)
-
-       return p, nil
-}
-
-func bcrypt(password []byte, cost uint32, salt []byte) ([]byte, error) {
-       cipherData := make([]byte, len(magicCipherData))
-       copy(cipherData, magicCipherData)
-
-       c, err := expensiveBlowfishSetup(password, cost, salt)
-       if err != nil {
-               return nil, err
-       }
-
-       for i := 0; i < 24; i += 8 {
-               for j := 0; j < 64; j++ {
-                       c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
-               }
-       }
-
-       // Bug compatibility with C bcrypt implementations. We only encode 23 of
-       // the 24 bytes encrypted.
-       hsh := base64Encode(cipherData[:maxCryptedHashSize])
-       return hsh, nil
-}
-
-func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
-
-       csalt, err := base64Decode(salt)
-       if err != nil {
-               return nil, err
-       }
-
-       // Bug compatibility with C bcrypt implementations. They use the trailing
-       // NULL in the key string during expansion.
-       ckey := append(key, 0)
-
-       c, err := blowfish.NewSaltedCipher(ckey, csalt)
-       if err != nil {
-               return nil, err
-       }
-
-       rounds := 1 << cost
-       for i := 0; i < rounds; i++ {
-               blowfish.ExpandKey(ckey, c)
-               blowfish.ExpandKey(csalt, c)
-       }
-
-       return c, nil
-}
-
-func (p *hashed) Hash() []byte {
-       arr := make([]byte, 60)
-       arr[0] = '$'
-       arr[1] = p.major
-       n := 2
-       if p.minor != 0 {
-               arr[2] = p.minor
-               n = 3
-       }
-       arr[n] = '$'
-       n += 1
-       copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
-       n += 2
-       arr[n] = '$'
-       n += 1
-       copy(arr[n:], p.salt)
-       n += encodedSaltSize
-       copy(arr[n:], p.hash)
-       n += encodedHashSize
-       return arr[:n]
-}
-
-func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
-       if sbytes[0] != '$' {
-               return -1, InvalidHashPrefixError(sbytes[0])
-       }
-       if sbytes[1] > majorVersion {
-               return -1, HashVersionTooNewError(sbytes[1])
-       }
-       p.major = sbytes[1]
-       n := 3
-       if sbytes[2] != '$' {
-               p.minor = sbytes[2]
-               n++
-       }
-       return n, nil
-}
-
-// sbytes should begin where decodeVersion left off.
-func (p *hashed) decodeCost(sbytes []byte) (int, error) {
-       cost, err := strconv.Atoi(string(sbytes[0:2]))
-       if err != nil {
-               return -1, err
-       }
-       err = checkCost(cost)
-       if err != nil {
-               return -1, err
-       }
-       p.cost = uint32(cost)
-       return 3, nil
-}
-
-func (p *hashed) String() string {
-       return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
-}
-
-func checkCost(cost int) error {
-       if cost < MinCost || cost > MaxCost {
-               return InvalidCostError(cost)
-       }
-       return nil
-}
diff --git a/libgo/go/crypto/bcrypt/bcrypt_test.go b/libgo/go/crypto/bcrypt/bcrypt_test.go
deleted file mode 100644 (file)
index a3155c5..0000000
+++ /dev/null
@@ -1,194 +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 bcrypt
-
-import (
-       "bytes"
-       "testing"
-)
-
-func TestBcryptingIsEasy(t *testing.T) {
-       pass := []byte("mypassword")
-       hp, err := GenerateFromPassword(pass, 0)
-       if err != nil {
-               t.Fatalf("GenerateFromPassword error: %s", err)
-       }
-
-       if CompareHashAndPassword(hp, pass) != nil {
-               t.Errorf("%v should hash %s correctly", hp, pass)
-       }
-
-       notPass := "notthepass"
-       err = CompareHashAndPassword(hp, []byte(notPass))
-       if err != MismatchedHashAndPasswordError {
-               t.Errorf("%v and %s should be mismatched", hp, notPass)
-       }
-}
-
-func TestBcryptingIsCorrect(t *testing.T) {
-       pass := []byte("allmine")
-       salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
-       expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
-
-       hash, err := bcrypt(pass, 10, salt)
-       if err != nil {
-               t.Fatalf("bcrypt blew up: %v", err)
-       }
-       if !bytes.HasSuffix(expectedHash, hash) {
-               t.Errorf("%v should be the suffix of %v", hash, expectedHash)
-       }
-
-       h, err := newFromHash(expectedHash)
-       if err != nil {
-               t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
-       }
-
-       // This is not the safe way to compare these hashes. We do this only for
-       // testing clarity. Use bcrypt.CompareHashAndPassword()
-       if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
-               t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
-       }
-}
-
-func TestTooLongPasswordsWork(t *testing.T) {
-       salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
-       // One byte over the usual 56 byte limit that blowfish has
-       tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
-       tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
-       hash, err := bcrypt(tooLongPass, 10, salt)
-       if err != nil {
-               t.Fatalf("bcrypt blew up on long password: %v", err)
-       }
-       if !bytes.HasSuffix(tooLongExpected, hash) {
-               t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
-       }
-}
-
-type InvalidHashTest struct {
-       err  error
-       hash []byte
-}
-
-var invalidTests = []InvalidHashTest{
-       {HashTooShortError, []byte("$2a$10$fooo")},
-       {HashTooShortError, []byte("$2a")},
-       {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-       {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-       {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-}
-
-func TestInvalidHashErrors(t *testing.T) {
-       check := func(name string, expected, err error) {
-               if err == nil {
-                       t.Errorf("%s: Should have returned an error", name)
-               }
-               if err != nil && err != expected {
-                       t.Errorf("%s gave err %v but should have given %v", name, err, expected)
-               }
-       }
-       for _, iht := range invalidTests {
-               _, err := newFromHash(iht.hash)
-               check("newFromHash", iht.err, err)
-               err = CompareHashAndPassword(iht.hash, []byte("anything"))
-               check("CompareHashAndPassword", iht.err, err)
-       }
-}
-
-func TestUnpaddedBase64Encoding(t *testing.T) {
-       original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
-       encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
-
-       encoded := base64Encode(original)
-
-       if !bytes.Equal(encodedOriginal, encoded) {
-               t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
-       }
-
-       decoded, err := base64Decode(encodedOriginal)
-       if err != nil {
-               t.Fatalf("base64Decode blew up: %s", err)
-       }
-
-       if !bytes.Equal(decoded, original) {
-               t.Errorf("Decoded %v should have equaled %v", decoded, original)
-       }
-}
-
-func TestCost(t *testing.T) {
-       if testing.Short() {
-               return
-       }
-
-       pass := []byte("mypassword")
-
-       for c := 0; c < MinCost; c++ {
-               p, _ := newFromPassword(pass, c)
-               if p.cost != uint32(DefaultCost) {
-                       t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
-               }
-       }
-
-       p, _ := newFromPassword(pass, 14)
-       if p.cost != 14 {
-               t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
-       }
-
-       hp, _ := newFromHash(p.Hash())
-       if p.cost != hp.cost {
-               t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
-       }
-
-       _, err := newFromPassword(pass, 32)
-       if err == nil {
-               t.Fatalf("newFromPassword: should return a cost error")
-       }
-       if err != InvalidCostError(32) {
-               t.Errorf("newFromPassword: should return cost error, got %#v", err)
-       }
-}
-
-func TestCostReturnsWithLeadingZeroes(t *testing.T) {
-       hp, _ := newFromPassword([]byte("abcdefgh"), 7)
-       cost := hp.Hash()[4:7]
-       expected := []byte("07$")
-
-       if !bytes.Equal(expected, cost) {
-               t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
-       }
-}
-
-func TestMinorNotRequired(t *testing.T) {
-       noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
-       h, err := newFromHash(noMinorHash)
-       if err != nil {
-               t.Fatalf("No minor hash blew up: %s", err)
-       }
-       if h.minor != 0 {
-               t.Errorf("Should leave minor version at 0, but was %d", h.minor)
-       }
-
-       if !bytes.Equal(noMinorHash, h.Hash()) {
-               t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
-       }
-}
-
-func BenchmarkEqual(b *testing.B) {
-       b.StopTimer()
-       passwd := []byte("somepasswordyoulike")
-       hash, _ := GenerateFromPassword(passwd, 10)
-       b.StartTimer()
-       for i := 0; i < b.N; i++ {
-               CompareHashAndPassword(hash, passwd)
-       }
-}
-
-func BenchmarkGeneration(b *testing.B) {
-       b.StopTimer()
-       passwd := []byte("mylongpassword1234")
-       b.StartTimer()
-       for i := 0; i < b.N; i++ {
-               GenerateFromPassword(passwd, 10)
-       }
-}
diff --git a/libgo/go/crypto/blowfish/block.go b/libgo/go/crypto/blowfish/block.go
deleted file mode 100644 (file)
index 326292d..0000000
+++ /dev/null
@@ -1,192 +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 blowfish
-
-// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
-// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
-// pi and substitution tables for calls to Encrypt. This is used, primarily,
-// by the bcrypt package to reuse the Blowfish key schedule during its
-// set up. It's unlikely that you need to use this directly.
-func ExpandKey(key []byte, c *Cipher) {
-       j := 0
-       for i := 0; i < 18; i++ {
-               var d uint32
-               for k := 0; k < 4; k++ {
-                       d = d<<8 | uint32(key[j])&0x000000FF
-                       j++
-                       if j >= len(key) {
-                               j = 0
-                       }
-               }
-               c.p[i] ^= d
-       }
-
-       var l, r uint32
-       for i := 0; i < 18; i += 2 {
-               l, r = encryptBlock(l, r, c)
-               c.p[i], c.p[i+1] = l, r
-       }
-
-       for i := 0; i < 256; i += 2 {
-               l, r = encryptBlock(l, r, c)
-               c.s0[i], c.s0[i+1] = l, r
-       }
-       for i := 0; i < 256; i += 2 {
-               l, r = encryptBlock(l, r, c)
-               c.s1[i], c.s1[i+1] = l, r
-       }
-       for i := 0; i < 256; i += 2 {
-               l, r = encryptBlock(l, r, c)
-               c.s2[i], c.s2[i+1] = l, r
-       }
-       for i := 0; i < 256; i += 2 {
-               l, r = encryptBlock(l, r, c)
-               c.s3[i], c.s3[i+1] = l, r
-       }
-}
-
-// This is similar to ExpandKey, but folds the salt during the key
-// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
-// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
-// and specializing it here is useful.
-func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
-       j := 0
-       expandedKey := make([]uint32, 18)
-       for i := 0; i < 18; i++ {
-               var d uint32
-               for k := 0; k < 4; k++ {
-                       d = d<<8 | uint32(key[j])&0x000000FF
-                       j++
-                       if j >= len(key) {
-                               j = 0
-                       }
-               }
-               expandedKey[i] = d
-               c.p[i] ^= d
-       }
-
-       j = 0
-       expandedSalt := make([]uint32, 18)
-       for i := 0; i < 18; i++ {
-               var d uint32
-               for k := 0; k < 4; k++ {
-                       d = d<<8 | uint32(salt[j])&0x000000FF
-                       j++
-                       if j >= len(salt) {
-                               j = 0
-                       }
-               }
-               expandedSalt[i] = d
-       }
-
-       var l, r uint32
-       for i := 0; i < 18; i += 2 {
-               l ^= expandedSalt[i&2]
-               r ^= expandedSalt[(i&2)+1]
-               l, r = encryptBlock(l, r, c)
-               c.p[i], c.p[i+1] = l, r
-       }
-
-       for i := 0; i < 256; i += 4 {
-               l ^= expandedSalt[2]
-               r ^= expandedSalt[3]
-               l, r = encryptBlock(l, r, c)
-               c.s0[i], c.s0[i+1] = l, r
-
-               l ^= expandedSalt[0]
-               r ^= expandedSalt[1]
-               l, r = encryptBlock(l, r, c)
-               c.s0[i+2], c.s0[i+3] = l, r
-
-       }
-
-       for i := 0; i < 256; i += 4 {
-               l ^= expandedSalt[2]
-               r ^= expandedSalt[3]
-               l, r = encryptBlock(l, r, c)
-               c.s1[i], c.s1[i+1] = l, r
-
-               l ^= expandedSalt[0]
-               r ^= expandedSalt[1]
-               l, r = encryptBlock(l, r, c)
-               c.s1[i+2], c.s1[i+3] = l, r
-       }
-
-       for i := 0; i < 256; i += 4 {
-               l ^= expandedSalt[2]
-               r ^= expandedSalt[3]
-               l, r = encryptBlock(l, r, c)
-               c.s2[i], c.s2[i+1] = l, r
-
-               l ^= expandedSalt[0]
-               r ^= expandedSalt[1]
-               l, r = encryptBlock(l, r, c)
-               c.s2[i+2], c.s2[i+3] = l, r
-       }
-
-       for i := 0; i < 256; i += 4 {
-               l ^= expandedSalt[2]
-               r ^= expandedSalt[3]
-               l, r = encryptBlock(l, r, c)
-               c.s3[i], c.s3[i+1] = l, r
-
-               l ^= expandedSalt[0]
-               r ^= expandedSalt[1]
-               l, r = encryptBlock(l, r, c)
-               c.s3[i+2], c.s3[i+3] = l, r
-       }
-}
-
-func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
-       xl, xr := l, r
-       xl ^= c.p[0]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
-       xr ^= c.p[17]
-       return xr, xl
-}
-
-func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
-       xl, xr := l, r
-       xl ^= c.p[17]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
-       xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
-       xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
-       xr ^= c.p[0]
-       return xr, xl
-}
-
-func zero(x []uint32) {
-       for i := range x {
-               x[i] = 0
-       }
-}
diff --git a/libgo/go/crypto/blowfish/blowfish_test.go b/libgo/go/crypto/blowfish/blowfish_test.go
deleted file mode 100644 (file)
index 1038d2e..0000000
+++ /dev/null
@@ -1,210 +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 blowfish
-
-import (
-       "testing"
-)
-
-type CryptTest struct {
-       key []byte
-       in  []byte
-       out []byte
-}
-
-// Test vector values are from http://www.schneier.com/code/vectors.txt.
-var encryptTests = []CryptTest{
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
-       {
-               []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-               []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-               []byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
-       {
-               []byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
-               []byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
-       {
-               []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-               []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-               []byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
-
-       {
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-               []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-               []byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
-       {
-               []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-               []byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
-       {
-               []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-               []byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
-       {
-               []byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
-               []byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
-               []byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
-       {
-               []byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
-               []byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
-               []byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
-       {
-               []byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
-               []byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
-               []byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
-       {
-               []byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
-               []byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
-               []byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
-       {
-               []byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
-               []byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
-               []byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
-       {
-               []byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
-               []byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
-               []byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
-       {
-               []byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
-               []byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
-               []byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
-       {
-               []byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
-               []byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
-               []byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
-       {
-               []byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
-               []byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
-               []byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
-       {
-               []byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
-               []byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
-               []byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
-       {
-               []byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
-               []byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
-               []byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
-       {
-               []byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
-               []byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
-               []byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
-       {
-               []byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
-               []byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
-               []byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
-       {
-               []byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
-               []byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
-               []byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
-       {
-               []byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
-               []byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
-               []byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
-       {
-               []byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
-               []byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
-               []byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
-       {
-               []byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
-               []byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
-               []byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
-       {
-               []byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
-               []byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
-               []byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
-       {
-               []byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
-               []byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
-               []byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
-       {
-               []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-               []byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
-       {
-               []byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-               []byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
-       {
-               []byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-               []byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-               []byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
-       {
-               []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
-       {
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
-       {
-               []byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
-               []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
-               []byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
-}
-
-func TestCipherEncrypt(t *testing.T) {
-       for i, tt := range encryptTests {
-               c, err := NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
-                       continue
-               }
-               ct := make([]byte, len(tt.out))
-               c.Encrypt(ct, tt.in)
-               for j, v := range ct {
-                       if v != tt.out[j] {
-                               t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
-                               break
-                       }
-               }
-       }
-}
-
-func TestCipherDecrypt(t *testing.T) {
-       for i, tt := range encryptTests {
-               c, err := NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
-                       continue
-               }
-               pt := make([]byte, len(tt.in))
-               c.Decrypt(pt, tt.out)
-               for j, v := range pt {
-                       if v != tt.in[j] {
-                               t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
-                               break
-                       }
-               }
-       }
-}
-
-func TestSaltedCipherKeyLength(t *testing.T) {
-       var key []byte
-       for i := 0; i < 4; i++ {
-               _, err := NewSaltedCipher(key, []byte{'a'})
-               if err != KeySizeError(i) {
-                       t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(i))
-               }
-               key = append(key, 'a')
-       }
-
-       // A 57-byte key. One over the typical blowfish restriction.
-       key = []byte("012345678901234567890123456789012345678901234567890123456")
-       _, err := NewSaltedCipher(key, []byte{'a'})
-       if err != nil {
-               t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
-       }
-}
diff --git a/libgo/go/crypto/blowfish/cipher.go b/libgo/go/crypto/blowfish/cipher.go
deleted file mode 100644 (file)
index 94e10f0..0000000
+++ /dev/null
@@ -1,100 +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 blowfish implements Bruce Schneier's Blowfish encryption algorithm.
-package blowfish
-
-// The code is a port of Bruce Schneier's C implementation.
-// See http://www.schneier.com/blowfish.html.
-
-import "strconv"
-
-// The Blowfish block size in bytes.
-const BlockSize = 8
-
-// A Cipher is an instance of Blowfish encryption using a particular key.
-type Cipher struct {
-       p              [18]uint32
-       s0, s1, s2, s3 [256]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) Error() string {
-       return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a Cipher.
-// The key argument should be the Blowfish key, 4 to 56 bytes.
-func NewCipher(key []byte) (*Cipher, error) {
-       var result Cipher
-       k := len(key)
-       if k < 4 || k > 56 {
-               return nil, KeySizeError(k)
-       }
-       initCipher(key, &result)
-       ExpandKey(key, &result)
-       return &result, nil
-}
-
-// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
-// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
-// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
-// bytes.
-func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
-       var result Cipher
-       k := len(key)
-       if k < 4 {
-               return nil, KeySizeError(k)
-       }
-       initCipher(key, &result)
-       expandKeyWithSalt(key, salt, &result)
-       return &result, nil
-}
-
-// BlockSize returns the Blowfish block size, 8 bytes.
-// It is necessary to satisfy the Block interface in the
-// package "crypto/cipher".
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// Encrypt encrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) {
-       l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-       r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-       l, r = encryptBlock(l, r, c)
-       dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
-       dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-// Decrypt decrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-func (c *Cipher) Decrypt(dst, src []byte) {
-       l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-       r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-       l, r = decryptBlock(l, r, c)
-       dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
-       dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-// Reset zeros the key data, so that it will no longer
-// appear in the process's memory.
-func (c *Cipher) Reset() {
-       zero(c.p[0:])
-       zero(c.s0[0:])
-       zero(c.s1[0:])
-       zero(c.s2[0:])
-       zero(c.s3[0:])
-}
-
-func initCipher(key []byte, c *Cipher) {
-       copy(c.p[0:], p[0:])
-       copy(c.s0[0:], s0[0:])
-       copy(c.s1[0:], s1[0:])
-       copy(c.s2[0:], s2[0:])
-       copy(c.s3[0:], s3[0:])
-}
diff --git a/libgo/go/crypto/blowfish/const.go b/libgo/go/crypto/blowfish/const.go
deleted file mode 100644 (file)
index 8c5ee4c..0000000
+++ /dev/null
@@ -1,199 +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.
-
-// The startup permutation array and substitution boxes.
-// They are the hexadecimal digits of PI; see:
-// http://www.schneier.com/code/constants.txt.
-
-package blowfish
-
-var s0 = [256]uint32{
-       0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
-       0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
-       0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
-       0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
-       0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
-       0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
-       0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
-       0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
-       0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
-       0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
-       0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
-       0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
-       0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
-       0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
-       0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
-       0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
-       0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
-       0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
-       0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
-       0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
-       0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
-       0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
-       0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
-       0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
-       0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
-       0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
-       0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
-       0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
-       0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
-       0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
-       0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
-       0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
-       0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
-       0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
-       0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
-       0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
-       0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
-       0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
-       0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
-       0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
-       0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
-       0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-       0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
-}
-
-var s1 = [256]uint32{
-       0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
-       0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
-       0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
-       0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
-       0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
-       0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
-       0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
-       0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
-       0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
-       0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
-       0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
-       0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
-       0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
-       0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
-       0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
-       0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
-       0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
-       0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
-       0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
-       0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
-       0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
-       0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
-       0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
-       0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
-       0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
-       0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
-       0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
-       0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
-       0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
-       0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
-       0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
-       0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
-       0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
-       0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
-       0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
-       0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
-       0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
-       0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
-       0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
-       0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
-       0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
-       0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-       0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
-}
-
-var s2 = [256]uint32{
-       0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
-       0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
-       0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
-       0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
-       0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
-       0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
-       0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
-       0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
-       0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
-       0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
-       0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
-       0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
-       0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
-       0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
-       0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
-       0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
-       0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
-       0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
-       0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
-       0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
-       0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
-       0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
-       0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
-       0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
-       0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
-       0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
-       0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
-       0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
-       0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
-       0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
-       0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
-       0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
-       0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
-       0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
-       0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
-       0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
-       0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
-       0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
-       0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
-       0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
-       0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
-       0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-       0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
-}
-
-var s3 = [256]uint32{
-       0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
-       0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
-       0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
-       0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
-       0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
-       0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
-       0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
-       0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
-       0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
-       0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
-       0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
-       0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
-       0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
-       0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
-       0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
-       0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
-       0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
-       0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
-       0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
-       0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
-       0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
-       0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
-       0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
-       0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
-       0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
-       0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
-       0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
-       0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
-       0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
-       0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
-       0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
-       0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
-       0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
-       0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
-       0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
-       0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
-       0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
-       0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
-       0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
-       0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
-       0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
-       0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-       0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
-}
-
-var p = [18]uint32{
-       0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
-       0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
-       0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
-}
diff --git a/libgo/go/crypto/cast5/cast5.go b/libgo/go/crypto/cast5/cast5.go
deleted file mode 100644 (file)
index 889a13c..0000000
+++ /dev/null
@@ -1,534 +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 cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
-// OpenPGP cipher.
-package cast5
-
-import "errors"
-
-const BlockSize = 8
-const KeySize = 16
-
-type Cipher struct {
-       masking [16]uint32
-       rotate  [16]uint8
-}
-
-func NewCipher(key []byte) (c *Cipher, err error) {
-       if len(key) != KeySize {
-               return nil, errors.New("CAST5: keys must be 16 bytes")
-       }
-
-       c = new(Cipher)
-       c.keySchedule(key)
-       return
-}
-
-func (c *Cipher) BlockSize() int {
-       return BlockSize
-}
-
-// Reset zeros the key material in memory.
-func (c *Cipher) Reset() {
-       for i := 0; i < 16; i++ {
-               c.masking[i] = 0
-               c.rotate[i] = 0
-       }
-}
-
-func (c *Cipher) Encrypt(dst, src []byte) {
-       l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-       r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-
-       l, r = r, l^f1(r, c.masking[0], c.rotate[0])
-       l, r = r, l^f2(r, c.masking[1], c.rotate[1])
-       l, r = r, l^f3(r, c.masking[2], c.rotate[2])
-       l, r = r, l^f1(r, c.masking[3], c.rotate[3])
-
-       l, r = r, l^f2(r, c.masking[4], c.rotate[4])
-       l, r = r, l^f3(r, c.masking[5], c.rotate[5])
-       l, r = r, l^f1(r, c.masking[6], c.rotate[6])
-       l, r = r, l^f2(r, c.masking[7], c.rotate[7])
-
-       l, r = r, l^f3(r, c.masking[8], c.rotate[8])
-       l, r = r, l^f1(r, c.masking[9], c.rotate[9])
-       l, r = r, l^f2(r, c.masking[10], c.rotate[10])
-       l, r = r, l^f3(r, c.masking[11], c.rotate[11])
-
-       l, r = r, l^f1(r, c.masking[12], c.rotate[12])
-       l, r = r, l^f2(r, c.masking[13], c.rotate[13])
-       l, r = r, l^f3(r, c.masking[14], c.rotate[14])
-       l, r = r, l^f1(r, c.masking[15], c.rotate[15])
-
-       dst[0] = uint8(r >> 24)
-       dst[1] = uint8(r >> 16)
-       dst[2] = uint8(r >> 8)
-       dst[3] = uint8(r)
-       dst[4] = uint8(l >> 24)
-       dst[5] = uint8(l >> 16)
-       dst[6] = uint8(l >> 8)
-       dst[7] = uint8(l)
-}
-
-func (c *Cipher) Decrypt(dst, src []byte) {
-       l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-       r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-
-       l, r = r, l^f1(r, c.masking[15], c.rotate[15])
-       l, r = r, l^f3(r, c.masking[14], c.rotate[14])
-       l, r = r, l^f2(r, c.masking[13], c.rotate[13])
-       l, r = r, l^f1(r, c.masking[12], c.rotate[12])
-
-       l, r = r, l^f3(r, c.masking[11], c.rotate[11])
-       l, r = r, l^f2(r, c.masking[10], c.rotate[10])
-       l, r = r, l^f1(r, c.masking[9], c.rotate[9])
-       l, r = r, l^f3(r, c.masking[8], c.rotate[8])
-
-       l, r = r, l^f2(r, c.masking[7], c.rotate[7])
-       l, r = r, l^f1(r, c.masking[6], c.rotate[6])
-       l, r = r, l^f3(r, c.masking[5], c.rotate[5])
-       l, r = r, l^f2(r, c.masking[4], c.rotate[4])
-
-       l, r = r, l^f1(r, c.masking[3], c.rotate[3])
-       l, r = r, l^f3(r, c.masking[2], c.rotate[2])
-       l, r = r, l^f2(r, c.masking[1], c.rotate[1])
-       l, r = r, l^f1(r, c.masking[0], c.rotate[0])
-
-       dst[0] = uint8(r >> 24)
-       dst[1] = uint8(r >> 16)
-       dst[2] = uint8(r >> 8)
-       dst[3] = uint8(r)
-       dst[4] = uint8(l >> 24)
-       dst[5] = uint8(l >> 16)
-       dst[6] = uint8(l >> 8)
-       dst[7] = uint8(l)
-}
-
-type keyScheduleA [4][7]uint8
-type keyScheduleB [4][5]uint8
-
-// keyScheduleRound contains the magic values for a round of the key schedule.
-// The keyScheduleA deals with the lines like:
-//   z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
-// Conceptually, both x and z are in the same array, x first. The first
-// element describes which word of this array gets written to and the
-// second, which word gets read. So, for the line above, it's "4, 0", because
-// it's writing to the first word of z, which, being after x, is word 4, and
-// reading from the first word of x: word 0.
-//
-// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
-// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
-// that it's z that we're indexing.
-//
-// keyScheduleB deals with lines like:
-//   K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
-// "K1" is ignored because key words are always written in order. So the five
-// elements are the S-box indexes. They use the same form as in keyScheduleA,
-// above.
-
-type keyScheduleRound struct{}
-type keySchedule []keyScheduleRound
-
-var schedule = []struct {
-       a keyScheduleA
-       b keyScheduleB
-}{
-       {
-               keyScheduleA{
-                       {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
-                       {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
-                       {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
-                       {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
-               },
-               keyScheduleB{
-                       {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
-                       {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
-                       {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
-                       {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
-               },
-       },
-       {
-               keyScheduleA{
-                       {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
-                       {1, 4, 0, 2, 1, 3, 16 + 2},
-                       {2, 5, 7, 6, 5, 4, 16 + 1},
-                       {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
-               },
-               keyScheduleB{
-                       {3, 2, 0xc, 0xd, 8},
-                       {1, 0, 0xe, 0xf, 0xd},
-                       {7, 6, 8, 9, 3},
-                       {5, 4, 0xa, 0xb, 7},
-               },
-       },
-       {
-               keyScheduleA{
-                       {4, 0, 0xd, 0xf, 0xc, 0xe, 8},
-                       {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
-                       {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
-                       {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
-               },
-               keyScheduleB{
-                       {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
-                       {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
-                       {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
-                       {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
-               },
-       },
-       {
-               keyScheduleA{
-                       {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
-                       {1, 4, 0, 2, 1, 3, 16 + 2},
-                       {2, 5, 7, 6, 5, 4, 16 + 1},
-                       {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
-               },
-               keyScheduleB{
-                       {8, 9, 7, 6, 3},
-                       {0xa, 0xb, 5, 4, 7},
-                       {0xc, 0xd, 3, 2, 8},
-                       {0xe, 0xf, 1, 0, 0xd},
-               },
-       },
-}
-
-func (c *Cipher) keySchedule(in []byte) {
-       var t [8]uint32
-       var k [32]uint32
-
-       for i := 0; i < 4; i++ {
-               j := i * 4
-               t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
-       }
-
-       x := []byte{6, 7, 4, 5}
-       ki := 0
-
-       for half := 0; half < 2; half++ {
-               for _, round := range schedule {
-                       for j := 0; j < 4; j++ {
-                               var a [7]uint8
-                               copy(a[:], round.a[j][:])
-                               w := t[a[1]]
-                               w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
-                               w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
-                               w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
-                               w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
-                               w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
-                               t[a[0]] = w
-                       }
-
-                       for j := 0; j < 4; j++ {
-                               var b [5]uint8
-                               copy(b[:], round.b[j][:])
-                               w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
-                               w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
-                               w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
-                               w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
-                               w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
-                               k[ki] = w
-                               ki++
-                       }
-               }
-       }
-
-       for i := 0; i < 16; i++ {
-               c.masking[i] = k[i]
-               c.rotate[i] = uint8(k[16+i] & 0x1f)
-       }
-}
-
-// These are the three 'f' functions. See RFC 2144, section 2.2.
-func f1(d, m uint32, r uint8) uint32 {
-       t := m + d
-       I := (t << r) | (t >> (32 - r))
-       return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
-}
-
-func f2(d, m uint32, r uint8) uint32 {
-       t := m ^ d
-       I := (t << r) | (t >> (32 - r))
-       return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
-}
-
-func f3(d, m uint32, r uint8) uint32 {
-       t := m - d
-       I := (t << r) | (t >> (32 - r))
-       return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
-}
-
-var sBox = [8][256]uint32{
-       {
-               0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
-               0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-               0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-               0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
-               0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-               0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-               0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
-               0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-               0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
-               0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-               0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
-               0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
-               0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
-               0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-               0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-               0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
-               0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
-               0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
-               0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-               0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-               0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
-               0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
-               0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-               0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-               0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-               0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
-               0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-               0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
-               0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
-               0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
-               0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-               0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
-       },
-       {
-               0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
-               0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-               0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-               0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-               0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
-               0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
-               0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
-               0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-               0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-               0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
-               0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-               0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
-               0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-               0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-               0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-               0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-               0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
-               0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
-               0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
-               0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-               0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
-               0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
-               0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-               0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-               0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
-               0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-               0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
-               0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
-               0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-               0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-               0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
-               0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
-       },
-       {
-               0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
-               0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
-               0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
-               0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
-               0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-               0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-               0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
-               0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-               0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-               0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
-               0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
-               0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
-               0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
-               0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-               0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-               0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
-               0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-               0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
-               0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
-               0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
-               0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-               0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-               0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-               0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
-               0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-               0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-               0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
-               0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-               0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
-               0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
-               0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
-               0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
-       },
-       {
-               0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
-               0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
-               0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-               0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
-               0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-               0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-               0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
-               0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
-               0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
-               0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
-               0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
-               0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
-               0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-               0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
-               0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-               0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
-               0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-               0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
-               0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-               0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-               0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-               0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-               0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-               0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-               0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-               0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
-               0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-               0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-               0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
-               0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
-               0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
-               0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
-       },
-       {
-               0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
-               0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
-               0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
-               0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
-               0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
-               0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
-               0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
-               0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
-               0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
-               0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
-               0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
-               0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
-               0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
-               0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
-               0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
-               0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
-               0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
-               0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
-               0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
-               0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
-               0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
-               0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
-               0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
-               0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
-               0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
-               0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
-               0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
-               0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
-               0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
-               0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
-               0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
-               0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
-       },
-       {
-               0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
-               0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
-               0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
-               0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
-               0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
-               0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
-               0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
-               0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
-               0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
-               0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
-               0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
-               0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
-               0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
-               0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
-               0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
-               0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
-               0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
-               0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
-               0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
-               0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
-               0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
-               0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
-               0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
-               0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
-               0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
-               0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
-               0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
-               0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
-               0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
-               0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
-               0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
-               0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
-       },
-       {
-               0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
-               0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
-               0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
-               0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
-               0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
-               0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
-               0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
-               0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
-               0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
-               0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
-               0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
-               0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
-               0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
-               0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
-               0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
-               0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
-               0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
-               0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
-               0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
-               0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
-               0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
-               0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
-               0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
-               0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
-               0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
-               0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
-               0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
-               0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
-               0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
-               0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
-               0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
-               0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
-       },
-       {
-               0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
-               0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
-               0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
-               0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
-               0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
-               0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
-               0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
-               0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
-               0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
-               0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
-               0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
-               0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
-               0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
-               0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
-               0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
-               0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
-               0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
-               0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
-               0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
-               0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
-               0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
-               0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
-               0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
-               0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
-               0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
-               0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
-               0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
-               0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
-               0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
-               0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
-               0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
-               0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
-       },
-}
diff --git a/libgo/go/crypto/cast5/cast5_test.go b/libgo/go/crypto/cast5/cast5_test.go
deleted file mode 100644 (file)
index 5f7025f..0000000
+++ /dev/null
@@ -1,104 +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 cast5
-
-import (
-       "bytes"
-       "encoding/hex"
-       "testing"
-)
-
-// This test vector is taken from RFC 2144, App B.1.
-// Since the other two test vectors are for reduced-round variants, we can't
-// use them.
-var basicTests = []struct {
-       key, plainText, cipherText string
-}{
-       {
-               "0123456712345678234567893456789a",
-               "0123456789abcdef",
-               "238b4fe5847e44b2",
-       },
-}
-
-func TestBasic(t *testing.T) {
-       for i, test := range basicTests {
-               key, _ := hex.DecodeString(test.key)
-               plainText, _ := hex.DecodeString(test.plainText)
-               expected, _ := hex.DecodeString(test.cipherText)
-
-               c, err := NewCipher(key)
-               if err != nil {
-                       t.Errorf("#%d: failed to create Cipher: %s", i, err)
-                       continue
-               }
-               var cipherText [BlockSize]byte
-               c.Encrypt(cipherText[:], plainText)
-               if !bytes.Equal(cipherText[:], expected) {
-                       t.Errorf("#%d: got:%x want:%x", i, cipherText, expected)
-               }
-
-               var plainTextAgain [BlockSize]byte
-               c.Decrypt(plainTextAgain[:], cipherText[:])
-               if !bytes.Equal(plainTextAgain[:], plainText) {
-                       t.Errorf("#%d: got:%x want:%x", i, plainTextAgain, plainText)
-               }
-       }
-}
-
-// TestFull performs the test specified in RFC 2144, App B.2.
-// However, due to the length of time taken, it's disabled here and a more
-// limited version is included, below.
-func TestFull(t *testing.T) {
-       // This is too slow for normal testing
-       return
-
-       a, b := iterate(1000000)
-
-       const expectedA = "eea9d0a249fd3ba6b3436fb89d6dca92"
-       const expectedB = "b2c95eb00c31ad7180ac05b8e83d696e"
-
-       if hex.EncodeToString(a) != expectedA {
-               t.Errorf("a: got:%x want:%s", a, expectedA)
-       }
-       if hex.EncodeToString(b) != expectedB {
-               t.Errorf("b: got:%x want:%s", b, expectedB)
-       }
-}
-
-func iterate(iterations int) ([]byte, []byte) {
-       const initValueHex = "0123456712345678234567893456789a"
-
-       initValue, _ := hex.DecodeString(initValueHex)
-
-       var a, b [16]byte
-       copy(a[:], initValue)
-       copy(b[:], initValue)
-
-       for i := 0; i < iterations; i++ {
-               c, _ := NewCipher(b[:])
-               c.Encrypt(a[:8], a[:8])
-               c.Encrypt(a[8:], a[8:])
-               c, _ = NewCipher(a[:])
-               c.Encrypt(b[:8], b[:8])
-               c.Encrypt(b[8:], b[8:])
-       }
-
-       return a[:], b[:]
-}
-
-func TestLimited(t *testing.T) {
-       a, b := iterate(1000)
-
-       const expectedA = "23f73b14b02a2ad7dfb9f2c35644798d"
-       const expectedB = "e5bf37eff14c456a40b21ce369370a9f"
-
-       if hex.EncodeToString(a) != expectedA {
-               t.Errorf("a: got:%x want:%s", a, expectedA)
-       }
-       if hex.EncodeToString(b) != expectedB {
-               t.Errorf("b: got:%x want:%s", b, expectedB)
-       }
-}
index be478468455b1178b195fbf2a8186cd79c8291e5..7aaad1ca19954e53f07cebd14426795125efafeb 100644 (file)
@@ -35,11 +35,11 @@ func (invalidPublicKeyError) Error() string {
        return "crypto/dsa: invalid public key"
 }
 
-// InvalidPublicKeyError results when a public key is not usable by this code.
+// ErrInvalidPublicKey results when a public key is not usable by this code.
 // FIPS is quite strict about the format of DSA keys, but other code may be
 // less so. Thus, when using keys which may have been generated by other code,
 // this error must be handled.
-var InvalidPublicKeyError = invalidPublicKeyError(0)
+var ErrInvalidPublicKey error = invalidPublicKeyError(0)
 
 // ParameterSizes is a enumeration of the acceptable bit lengths of the primes
 // in a set of DSA parameters. See FIPS 186-3, section 4.2.
@@ -194,7 +194,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
 
        n := priv.Q.BitLen()
        if n&7 != 0 {
-               err = InvalidPublicKeyError
+               err = ErrInvalidPublicKey
                return
        }
        n >>= 3
diff --git a/libgo/go/crypto/md4/md4.go b/libgo/go/crypto/md4/md4.go
deleted file mode 100644 (file)
index c5f7c57..0000000
+++ /dev/null
@@ -1,118 +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 md4 implements the MD4 hash algorithm as defined in RFC 1320.
-package md4
-
-import (
-       "crypto"
-       "hash"
-)
-
-func init() {
-       crypto.RegisterHash(crypto.MD4, New)
-}
-
-// The size of an MD4 checksum in bytes.
-const Size = 16
-
-// The blocksize of MD4 in bytes.
-const BlockSize = 64
-
-const (
-       _Chunk = 64
-       _Init0 = 0x67452301
-       _Init1 = 0xEFCDAB89
-       _Init2 = 0x98BADCFE
-       _Init3 = 0x10325476
-)
-
-// digest represents the partial evaluation of a checksum.
-type digest struct {
-       s   [4]uint32
-       x   [_Chunk]byte
-       nx  int
-       len uint64
-}
-
-func (d *digest) Reset() {
-       d.s[0] = _Init0
-       d.s[1] = _Init1
-       d.s[2] = _Init2
-       d.s[3] = _Init3
-       d.nx = 0
-       d.len = 0
-}
-
-// New returns a new hash.Hash computing the MD4 checksum.
-func New() hash.Hash {
-       d := new(digest)
-       d.Reset()
-       return d
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) BlockSize() int { return BlockSize }
-
-func (d *digest) Write(p []byte) (nn int, err error) {
-       nn = len(p)
-       d.len += uint64(nn)
-       if d.nx > 0 {
-               n := len(p)
-               if n > _Chunk-d.nx {
-                       n = _Chunk - d.nx
-               }
-               for i := 0; i < n; i++ {
-                       d.x[d.nx+i] = p[i]
-               }
-               d.nx += n
-               if d.nx == _Chunk {
-                       _Block(d, d.x[0:])
-                       d.nx = 0
-               }
-               p = p[n:]
-       }
-       n := _Block(d, p)
-       p = p[n:]
-       if len(p) > 0 {
-               d.nx = copy(d.x[:], p)
-       }
-       return
-}
-
-func (d0 *digest) Sum(in []byte) []byte {
-       // Make a copy of d0, so that caller can keep writing and summing.
-       d := new(digest)
-       *d = *d0
-
-       // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
-       len := d.len
-       var tmp [64]byte
-       tmp[0] = 0x80
-       if len%64 < 56 {
-               d.Write(tmp[0 : 56-len%64])
-       } else {
-               d.Write(tmp[0 : 64+56-len%64])
-       }
-
-       // Length in bits.
-       len <<= 3
-       for i := uint(0); i < 8; i++ {
-               tmp[i] = byte(len >> (8 * i))
-       }
-       d.Write(tmp[0:8])
-
-       if d.nx != 0 {
-               panic("d.nx != 0")
-       }
-
-       for _, s := range d.s {
-               in = append(in, byte(s>>0))
-               in = append(in, byte(s>>8))
-               in = append(in, byte(s>>16))
-               in = append(in, byte(s>>24))
-       }
-       return in
-}
diff --git a/libgo/go/crypto/md4/md4_test.go b/libgo/go/crypto/md4/md4_test.go
deleted file mode 100644 (file)
index b56edd7..0000000
+++ /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 md4
-
-import (
-       "fmt"
-       "io"
-       "testing"
-)
-
-type md4Test struct {
-       out string
-       in  string
-}
-
-var golden = []md4Test{
-       {"31d6cfe0d16ae931b73c59d7e0c089c0", ""},
-       {"bde52cb31de33e46245e05fbdbd6fb24", "a"},
-       {"ec388dd78999dfc7cf4632465693b6bf", "ab"},
-       {"a448017aaf21d8525fc10ae87aa6729d", "abc"},
-       {"41decd8f579255c5200f86a4bb3ba740", "abcd"},
-       {"9803f4a34e8eb14f96adba49064a0c41", "abcde"},
-       {"804e7f1c2586e50b49ac65db5b645131", "abcdef"},
-       {"752f4adfe53d1da0241b5bc216d098fc", "abcdefg"},
-       {"ad9daf8d49d81988590a6f0e745d15dd", "abcdefgh"},
-       {"1e4e28b05464316b56402b3815ed2dfd", "abcdefghi"},
-       {"dc959c6f5d6f9e04e4380777cc964b3d", "abcdefghij"},
-       {"1b5701e265778898ef7de5623bbe7cc0", "Discard medicine more than two years old."},
-       {"d7f087e090fe7ad4a01cb59dacc9a572", "He who has a shady past knows that nice guys finish last."},
-       {"a6f8fd6df617c72837592fc3570595c9", "I wouldn't marry him with a ten foot pole."},
-       {"c92a84a9526da8abc240c05d6b1a1ce0", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave"},
-       {"f6013160c4dcb00847069fee3bb09803", "The days of the digital watch are numbered.  -Tom Stoppard"},
-       {"2c3bb64f50b9107ed57640fe94bec09f", "Nepal premier won't resign."},
-       {"45b7d8a32c7806f2f7f897332774d6e4", "For every action there is an equal and opposite government program."},
-       {"b5b4f9026b175c62d7654bdc3a1cd438", "His money is twice tainted: 'taint yours and 'taint mine."},
-       {"caf44e80f2c20ce19b5ba1cab766e7bd", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977"},
-       {"191fae6707f496aa54a6bce9f2ecf74d", "It's a tiny change to the code and not completely disgusting. - Bob Manchek"},
-       {"9ddc753e7a4ccee6081cd1b45b23a834", "size:  a.out:  bad magic"},
-       {"8d050f55b1cadb9323474564be08a521", "The major problem is with sendmail.  -Mark Horton"},
-       {"ad6e2587f74c3e3cc19146f6127fa2e3", "Give me a rock, paper and scissors and I will move the world.  CCFestoon"},
-       {"1d616d60a5fabe85589c3f1566ca7fca", "If the enemy is within range, then so are you."},
-       {"aec3326a4f496a2ced65a1963f84577f", "It's well we cannot hear the screams/That we create in others' dreams."},
-       {"77b4fd762d6b9245e61c50bf6ebf118b", "You remind me of a TV show, but that's all right: I watch it anyway."},
-       {"e8f48c726bae5e516f6ddb1a4fe62438", "C is as portable as Stonehedge!!"},
-       {"a3a84366e7219e887423b01f9be7166e", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley"},
-       {"a6b7aa35157e984ef5d9b7f32e5fbb52", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction.  Lewis-Randall Rule"},
-       {"75661f0545955f8f9abeeb17845f3fd6", "How can you write a big system without C++?  -Paul Glick"},
-}
-
-func TestGolden(t *testing.T) {
-       for i := 0; i < len(golden); i++ {
-               g := golden[i]
-               c := New()
-               for j := 0; j < 3; j++ {
-                       if j < 2 {
-                               io.WriteString(c, g.in)
-                       } else {
-                               io.WriteString(c, g.in[0:len(g.in)/2])
-                               c.Sum(nil)
-                               io.WriteString(c, g.in[len(g.in)/2:])
-                       }
-                       s := fmt.Sprintf("%x", c.Sum(nil))
-                       if s != g.out {
-                               t.Fatalf("md4[%d](%s) = %s want %s", j, g.in, s, g.out)
-                       }
-                       c.Reset()
-               }
-       }
-}
diff --git a/libgo/go/crypto/md4/md4block.go b/libgo/go/crypto/md4/md4block.go
deleted file mode 100644 (file)
index 3fed475..0000000
+++ /dev/null
@@ -1,89 +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.
-
-// MD4 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
-package md4
-
-var shift1 = []uint{3, 7, 11, 19}
-var shift2 = []uint{3, 5, 9, 13}
-var shift3 = []uint{3, 9, 11, 15}
-
-var xIndex2 = []uint{0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}
-var xIndex3 = []uint{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}
-
-func _Block(dig *digest, p []byte) int {
-       a := dig.s[0]
-       b := dig.s[1]
-       c := dig.s[2]
-       d := dig.s[3]
-       n := 0
-       var X [16]uint32
-       for len(p) >= _Chunk {
-               aa, bb, cc, dd := a, b, c, d
-
-               j := 0
-               for i := 0; i < 16; i++ {
-                       X[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
-                       j += 4
-               }
-
-               // If this needs to be made faster in the future,
-               // the usual trick is to unroll each of these
-               // loops by a factor of 4; that lets you replace
-               // the shift[] lookups with constants and,
-               // with suitable variable renaming in each
-               // unrolled body, delete the a, b, c, d = d, a, b, c
-               // (or you can let the optimizer do the renaming).
-               //
-               // The index variables are uint so that % by a power
-               // of two can be optimized easily by a compiler.
-
-               // Round 1.
-               for i := uint(0); i < 16; i++ {
-                       x := i
-                       s := shift1[i%4]
-                       f := ((c ^ d) & b) ^ d
-                       a += f + X[x]
-                       a = a<<s | a>>(32-s)
-                       a, b, c, d = d, a, b, c
-               }
-
-               // Round 2.
-               for i := uint(0); i < 16; i++ {
-                       x := xIndex2[i]
-                       s := shift2[i%4]
-                       g := (b & c) | (b & d) | (c & d)
-                       a += g + X[x] + 0x5a827999
-                       a = a<<s | a>>(32-s)
-                       a, b, c, d = d, a, b, c
-               }
-
-               // Round 3.
-               for i := uint(0); i < 16; i++ {
-                       x := xIndex3[i]
-                       s := shift3[i%4]
-                       h := b ^ c ^ d
-                       a += h + X[x] + 0x6ed9eba1
-                       a = a<<s | a>>(32-s)
-                       a, b, c, d = d, a, b, c
-               }
-
-               a += aa
-               b += bb
-               c += cc
-               d += dd
-
-               p = p[_Chunk:]
-               n += _Chunk
-       }
-
-       dig.s[0] = a
-       dig.s[1] = b
-       dig.s[2] = c
-       dig.s[3] = d
-       return n
-}
diff --git a/libgo/go/crypto/ocsp/ocsp.go b/libgo/go/crypto/ocsp/ocsp.go
deleted file mode 100644 (file)
index b9dfdf9..0000000
+++ /dev/null
@@ -1,191 +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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
-// are signed messages attesting to the validity of a certificate for a small
-// period of time. This is used to manage revocation for X.509 certificates.
-package ocsp
-
-import (
-       "crypto"
-       "crypto/rsa"
-       _ "crypto/sha1"
-       "crypto/x509"
-       "crypto/x509/pkix"
-       "encoding/asn1"
-       "time"
-)
-
-var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
-var idSHA1WithRSA = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 1, 5})
-
-// These are internal structures that reflect the ASN.1 structure of an OCSP
-// response. See RFC 2560, section 4.2.
-
-const (
-       ocspSuccess       = 0
-       ocspMalformed     = 1
-       ocspInternalError = 2
-       ocspTryLater      = 3
-       ocspSigRequired   = 4
-       ocspUnauthorized  = 5
-)
-
-type certID struct {
-       HashAlgorithm pkix.AlgorithmIdentifier
-       NameHash      []byte
-       IssuerKeyHash []byte
-       SerialNumber  asn1.RawValue
-}
-
-type responseASN1 struct {
-       Status   asn1.Enumerated
-       Response responseBytes `asn1:"explicit,tag:0"`
-}
-
-type responseBytes struct {
-       ResponseType asn1.ObjectIdentifier
-       Response     []byte
-}
-
-type basicResponse struct {
-       TBSResponseData    responseData
-       SignatureAlgorithm pkix.AlgorithmIdentifier
-       Signature          asn1.BitString
-       Certificates       []asn1.RawValue `asn1:"explicit,tag:0,optional"`
-}
-
-type responseData struct {
-       Raw           asn1.RawContent
-       Version       int              `asn1:"optional,default:1,explicit,tag:0"`
-       RequestorName pkix.RDNSequence `asn1:"optional,explicit,tag:1"`
-       KeyHash       []byte           `asn1:"optional,explicit,tag:2"`
-       ProducedAt    time.Time
-       Responses     []singleResponse
-}
-
-type singleResponse struct {
-       CertID     certID
-       Good       asn1.Flag   `asn1:"explicit,tag:0,optional"`
-       Revoked    revokedInfo `asn1:"explicit,tag:1,optional"`
-       Unknown    asn1.Flag   `asn1:"explicit,tag:2,optional"`
-       ThisUpdate time.Time
-       NextUpdate time.Time `asn1:"explicit,tag:0,optional"`
-}
-
-type revokedInfo struct {
-       RevocationTime time.Time
-       Reason         int `asn1:"explicit,tag:0,optional"`
-}
-
-// This is the exposed reflection of the internal OCSP structures.
-
-const (
-       // Good means that the certificate is valid.
-       Good = iota
-       // Revoked means that the certificate has been deliberately revoked.
-       Revoked = iota
-       // Unknown means that the OCSP responder doesn't know about the certificate.
-       Unknown = iota
-       // ServerFailed means that the OCSP responder failed to process the request.
-       ServerFailed = iota
-)
-
-// Response represents an OCSP response. See RFC 2560.
-type Response struct {
-       // Status is one of {Good, Revoked, Unknown, ServerFailed}
-       Status                                        int
-       SerialNumber                                  []byte
-       ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
-       RevocationReason                              int
-       Certificate                                   *x509.Certificate
-}
-
-// ParseError results from an invalid OCSP response.
-type ParseError string
-
-func (p ParseError) Error() string {
-       return string(p)
-}
-
-// ParseResponse parses an OCSP response in DER form. It only supports
-// responses for a single certificate and only those using RSA signatures.
-// Non-RSA responses will result in an x509.UnsupportedAlgorithmError.
-// Signature errors or parse failures will result in a ParseError.
-func ParseResponse(bytes []byte) (*Response, error) {
-       var resp responseASN1
-       rest, err := asn1.Unmarshal(bytes, &resp)
-       if err != nil {
-               return nil, err
-       }
-       if len(rest) > 0 {
-               return nil, ParseError("trailing data in OCSP response")
-       }
-
-       ret := new(Response)
-       if resp.Status != ocspSuccess {
-               ret.Status = ServerFailed
-               return ret, nil
-       }
-
-       if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
-               return nil, ParseError("bad OCSP response type")
-       }
-
-       var basicResp basicResponse
-       rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
-       if err != nil {
-               return nil, err
-       }
-
-       if len(basicResp.Certificates) != 1 {
-               return nil, ParseError("OCSP response contains bad number of certificates")
-       }
-
-       if len(basicResp.TBSResponseData.Responses) != 1 {
-               return nil, ParseError("OCSP response contains bad number of responses")
-       }
-
-       ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
-       if err != nil {
-               return nil, err
-       }
-
-       if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) {
-               return nil, x509.UnsupportedAlgorithmError{}
-       }
-
-       hashType := crypto.SHA1
-       h := hashType.New()
-
-       pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
-       h.Write(basicResp.TBSResponseData.Raw)
-       digest := h.Sum(nil)
-       signature := basicResp.Signature.RightAlign()
-
-       if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil {
-               return nil, ParseError("bad OCSP signature")
-       }
-
-       r := basicResp.TBSResponseData.Responses[0]
-
-       ret.SerialNumber = r.CertID.SerialNumber.Bytes
-
-       switch {
-       case bool(r.Good):
-               ret.Status = Good
-       case bool(r.Unknown):
-               ret.Status = Unknown
-       default:
-               ret.Status = Revoked
-               ret.RevokedAt = r.Revoked.RevocationTime
-               ret.RevocationReason = r.Revoked.Reason
-       }
-
-       ret.ProducedAt = basicResp.TBSResponseData.ProducedAt
-       ret.ThisUpdate = r.ThisUpdate
-       ret.NextUpdate = r.NextUpdate
-
-       return ret, nil
-}
diff --git a/libgo/go/crypto/ocsp/ocsp_test.go b/libgo/go/crypto/ocsp/ocsp_test.go
deleted file mode 100644 (file)
index f0e9f94..0000000
+++ /dev/null
@@ -1,107 +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 ocsp
-
-import (
-       "bytes"
-       "encoding/hex"
-       "reflect"
-       "testing"
-       "time"
-)
-
-func TestOCSPDecode(t *testing.T) {
-       responseBytes, _ := hex.DecodeString(ocspResponseHex)
-       resp, err := ParseResponse(responseBytes)
-       if err != nil {
-               t.Error(err)
-       }
-
-       expected := Response{
-               Status:           0,
-               SerialNumber:     []byte{0x1, 0xd0, 0xfa},
-               RevocationReason: 0,
-               ThisUpdate:       time.Date(2010, 7, 7, 15, 1, 5, 0, time.UTC),
-               NextUpdate:       time.Date(2010, 7, 7, 18, 35, 17, 0, time.UTC),
-       }
-
-       if !reflect.DeepEqual(resp.ThisUpdate, expected.ThisUpdate) {
-               t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
-       }
-
-       if !reflect.DeepEqual(resp.NextUpdate, expected.NextUpdate) {
-               t.Errorf("resp.NextUpdate: got %d, want %d", resp.NextUpdate, expected.NextUpdate)
-       }
-
-       if resp.Status != expected.Status {
-               t.Errorf("resp.Status: got %d, want %d", resp.Status, expected.Status)
-       }
-
-       if !bytes.Equal(resp.SerialNumber, expected.SerialNumber) {
-               t.Errorf("resp.SerialNumber: got %x, want %x", resp.SerialNumber, expected.SerialNumber)
-       }
-
-       if resp.RevocationReason != expected.RevocationReason {
-               t.Errorf("resp.RevocationReason: got %d, want %d", resp.RevocationReason, expected.RevocationReason)
-       }
-}
-
-// This OCSP response was taken from Thawte's public OCSP responder.
-// To recreate:
-//   $ openssl s_client -tls1 -showcerts -servername www.google.com -connect www.google.com:443
-// Copy and paste the first certificate into /tmp/cert.crt and the second into
-// /tmp/intermediate.crt
-//   $ openssl ocsp -issuer /tmp/intermediate.crt -cert /tmp/cert.crt -url http://ocsp.thawte.com -resp_text -respout /tmp/ocsp.der
-// Then hex encode the result:
-//   $ python -c 'print file("/tmp/ocsp.der", "r").read().encode("hex")'
-
-const ocspResponseHex = "308206bc0a0100a08206b5308206b106092b0601050507300101048206a23082069e3081" +
-       "c9a14e304c310b300906035504061302494c31163014060355040a130d5374617274436f" +
-       "6d204c74642e312530230603550403131c5374617274436f6d20436c6173732031204f43" +
-       "5350205369676e6572180f32303130303730373137333531375a30663064303c30090605" +
-       "2b0e03021a050004146568874f40750f016a3475625e1f5c93e5a26d580414eb4234d098" +
-       "b0ab9ff41b6b08f7cc642eef0e2c45020301d0fa8000180f323031303037303731353031" +
-       "30355aa011180f32303130303730373138333531375a300d06092a864886f70d01010505" +
-       "000382010100ab557ff070d1d7cebbb5f0ec91a15c3fed22eb2e1b8244f1b84545f013a4" +
-       "fb46214c5e3fbfbebb8a56acc2b9db19f68fd3c3201046b3824d5ba689f99864328710cb" +
-       "467195eb37d84f539e49f859316b32964dc3e47e36814ce94d6c56dd02733b1d0802f7ff" +
-       "4eebdbbd2927dcf580f16cbc290f91e81b53cb365e7223f1d6e20a88ea064104875e0145" +
-       "672b20fc14829d51ca122f5f5d77d3ad6c83889c55c7dc43680ba2fe3cef8b05dbcabdc0" +
-       "d3e09aaf9725597f8c858c2fa38c0d6aed2e6318194420dd1a1137445d13e1c97ab47896" +
-       "17a4e08925f46f867b72e3a4dc1f08cb870b2b0717f7207faa0ac512e628a029aba7457a" +
-       "e63dcf3281e2162d9349a08204ba308204b6308204b23082039aa003020102020101300d" +
-       "06092a864886f70d010105050030818c310b300906035504061302494c31163014060355" +
-       "040a130d5374617274436f6d204c74642e312b3029060355040b13225365637572652044" +
-       "69676974616c204365727469666963617465205369676e696e6731383036060355040313" +
-       "2f5374617274436f6d20436c6173732031205072696d61727920496e7465726d65646961" +
-       "746520536572766572204341301e170d3037313032353030323330365a170d3132313032" +
-       "333030323330365a304c310b300906035504061302494c31163014060355040a130d5374" +
-       "617274436f6d204c74642e312530230603550403131c5374617274436f6d20436c617373" +
-       "2031204f435350205369676e657230820122300d06092a864886f70d0101010500038201" +
-       "0f003082010a0282010100b9561b4c45318717178084e96e178df2255e18ed8d8ecc7c2b" +
-       "7b51a6c1c2e6bf0aa3603066f132fe10ae97b50e99fa24b83fc53dd2777496387d14e1c3" +
-       "a9b6a4933e2ac12413d085570a95b8147414a0bc007c7bcf222446ef7f1a156d7ea1c577" +
-       "fc5f0facdfd42eb0f5974990cb2f5cefebceef4d1bdc7ae5c1075c5a99a93171f2b0845b" +
-       "4ff0864e973fcfe32f9d7511ff87a3e943410c90a4493a306b6944359340a9ca96f02b66" +
-       "ce67f028df2980a6aaee8d5d5d452b8b0eb93f923cc1e23fcccbdbe7ffcb114d08fa7a6a" +
-       "3c404f825d1a0e715935cf623a8c7b59670014ed0622f6089a9447a7a19010f7fe58f841" +
-       "29a2765ea367824d1c3bb2fda308530203010001a382015c30820158300c0603551d1301" +
-       "01ff04023000300b0603551d0f0404030203a8301e0603551d250417301506082b060105" +
-       "0507030906092b0601050507300105301d0603551d0e0416041445e0a36695414c5dd449" +
-       "bc00e33cdcdbd2343e173081a80603551d230481a030819d8014eb4234d098b0ab9ff41b" +
-       "6b08f7cc642eef0e2c45a18181a47f307d310b300906035504061302494c311630140603" +
-       "55040a130d5374617274436f6d204c74642e312b3029060355040b132253656375726520" +
-       "4469676974616c204365727469666963617465205369676e696e67312930270603550403" +
-       "13205374617274436f6d2043657274696669636174696f6e20417574686f726974798201" +
-       "0a30230603551d12041c301a8618687474703a2f2f7777772e737461727473736c2e636f" +
-       "6d2f302c06096086480186f842010d041f161d5374617274436f6d205265766f63617469" +
-       "6f6e20417574686f72697479300d06092a864886f70d01010505000382010100182d2215" +
-       "8f0fc0291324fa8574c49bb8ff2835085adcbf7b7fc4191c397ab6951328253fffe1e5ec" +
-       "2a7da0d50fca1a404e6968481366939e666c0a6209073eca57973e2fefa9ed1718e8176f" +
-       "1d85527ff522c08db702e3b2b180f1cbff05d98128252cf0f450f7dd2772f4188047f19d" +
-       "c85317366f94bc52d60f453a550af58e308aaab00ced33040b62bf37f5b1ab2a4f7f0f80" +
-       "f763bf4d707bc8841d7ad9385ee2a4244469260b6f2bf085977af9074796048ecc2f9d48" +
-       "a1d24ce16e41a9941568fec5b42771e118f16c106a54ccc339a4b02166445a167902e75e" +
-       "6d8620b0825dcd18a069b90fd851d10fa8effd409deec02860d26d8d833f304b10669b42"
diff --git a/libgo/go/crypto/openpgp/armor/armor.go b/libgo/go/crypto/openpgp/armor/armor.go
deleted file mode 100644 (file)
index 96957ab..0000000
+++ /dev/null
@@ -1,219 +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 armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
-// very similar to PEM except that it has an additional CRC checksum.
-package armor
-
-import (
-       "bufio"
-       "bytes"
-       "crypto/openpgp/errors"
-       "encoding/base64"
-       "io"
-)
-
-// A Block represents an OpenPGP armored structure.
-//
-// The encoded form is:
-//    -----BEGIN Type-----
-//    Headers
-//
-//    base64-encoded Bytes
-//    '=' base64 encoded checksum
-//    -----END Type-----
-// where Headers is a possibly empty sequence of Key: Value lines.
-//
-// Since the armored data can be very large, this package presents a streaming
-// interface.
-type Block struct {
-       Type    string            // The type, taken from the preamble (i.e. "PGP SIGNATURE").
-       Header  map[string]string // Optional headers.
-       Body    io.Reader         // A Reader from which the contents can be read
-       lReader lineReader
-       oReader openpgpReader
-}
-
-var ArmorCorrupt error = errors.StructuralError("armor invalid")
-
-const crc24Init = 0xb704ce
-const crc24Poly = 0x1864cfb
-const crc24Mask = 0xffffff
-
-// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
-func crc24(crc uint32, d []byte) uint32 {
-       for _, b := range d {
-               crc ^= uint32(b) << 16
-               for i := 0; i < 8; i++ {
-                       crc <<= 1
-                       if crc&0x1000000 != 0 {
-                               crc ^= crc24Poly
-                       }
-               }
-       }
-       return crc
-}
-
-var armorStart = []byte("-----BEGIN ")
-var armorEnd = []byte("-----END ")
-var armorEndOfLine = []byte("-----")
-
-// lineReader wraps a line based reader. It watches for the end of an armor
-// block and records the expected CRC value.
-type lineReader struct {
-       in  *bufio.Reader
-       buf []byte
-       eof bool
-       crc uint32
-}
-
-func (l *lineReader) Read(p []byte) (n int, err error) {
-       if l.eof {
-               return 0, io.EOF
-       }
-
-       if len(l.buf) > 0 {
-               n = copy(p, l.buf)
-               l.buf = l.buf[n:]
-               return
-       }
-
-       line, isPrefix, err := l.in.ReadLine()
-       if err != nil {
-               return
-       }
-       if isPrefix {
-               return 0, ArmorCorrupt
-       }
-
-       if len(line) == 5 && line[0] == '=' {
-               // This is the checksum line
-               var expectedBytes [3]byte
-               var m int
-               m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
-               if m != 3 || err != nil {
-                       return
-               }
-               l.crc = uint32(expectedBytes[0])<<16 |
-                       uint32(expectedBytes[1])<<8 |
-                       uint32(expectedBytes[2])
-
-               line, _, err = l.in.ReadLine()
-               if err != nil && err != io.EOF {
-                       return
-               }
-               if !bytes.HasPrefix(line, armorEnd) {
-                       return 0, ArmorCorrupt
-               }
-
-               l.eof = true
-               return 0, io.EOF
-       }
-
-       if len(line) > 64 {
-               return 0, ArmorCorrupt
-       }
-
-       n = copy(p, line)
-       bytesToSave := len(line) - n
-       if bytesToSave > 0 {
-               if cap(l.buf) < bytesToSave {
-                       l.buf = make([]byte, 0, bytesToSave)
-               }
-               l.buf = l.buf[0:bytesToSave]
-               copy(l.buf, line[n:])
-       }
-
-       return
-}
-
-// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
-// a running CRC of the resulting data and checks the CRC against the value
-// found by the lineReader at EOF.
-type openpgpReader struct {
-       lReader    *lineReader
-       b64Reader  io.Reader
-       currentCRC uint32
-}
-
-func (r *openpgpReader) Read(p []byte) (n int, err error) {
-       n, err = r.b64Reader.Read(p)
-       r.currentCRC = crc24(r.currentCRC, p[:n])
-
-       if err == io.EOF {
-               if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
-                       return 0, ArmorCorrupt
-               }
-       }
-
-       return
-}
-
-// Decode reads a PGP armored block from the given Reader. It will ignore
-// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
-// given Reader is not usable after calling this function: an arbitrary amount
-// of data may have been read past the end of the block.
-func Decode(in io.Reader) (p *Block, err error) {
-       r, _ := bufio.NewReaderSize(in, 100)
-       var line []byte
-       ignoreNext := false
-
-TryNextBlock:
-       p = nil
-
-       // Skip leading garbage
-       for {
-               ignoreThis := ignoreNext
-               line, ignoreNext, err = r.ReadLine()
-               if err != nil {
-                       return
-               }
-               if ignoreNext || ignoreThis {
-                       continue
-               }
-               line = bytes.TrimSpace(line)
-               if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
-                       break
-               }
-       }
-
-       p = new(Block)
-       p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
-       p.Header = make(map[string]string)
-       nextIsContinuation := false
-       var lastKey string
-
-       // Read headers
-       for {
-               isContinuation := nextIsContinuation
-               line, nextIsContinuation, err = r.ReadLine()
-               if err != nil {
-                       p = nil
-                       return
-               }
-               if isContinuation {
-                       p.Header[lastKey] += string(line)
-                       continue
-               }
-               line = bytes.TrimSpace(line)
-               if len(line) == 0 {
-                       break
-               }
-
-               i := bytes.Index(line, []byte(": "))
-               if i == -1 {
-                       goto TryNextBlock
-               }
-               lastKey = string(line[:i])
-               p.Header[lastKey] = string(line[i+2:])
-       }
-
-       p.lReader.in = r
-       p.oReader.currentCRC = crc24Init
-       p.oReader.lReader = &p.lReader
-       p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
-       p.Body = &p.oReader
-
-       return
-}
diff --git a/libgo/go/crypto/openpgp/armor/armor_test.go b/libgo/go/crypto/openpgp/armor/armor_test.go
deleted file mode 100644 (file)
index 9334e94..0000000
+++ /dev/null
@@ -1,95 +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 armor
-
-import (
-       "bytes"
-       "hash/adler32"
-       "io/ioutil"
-       "testing"
-)
-
-func TestDecodeEncode(t *testing.T) {
-       buf := bytes.NewBuffer([]byte(armorExample1))
-       result, err := Decode(buf)
-       if err != nil {
-               t.Error(err)
-       }
-       expectedType := "PGP SIGNATURE"
-       if result.Type != expectedType {
-               t.Errorf("result.Type: got:%s want:%s", result.Type, expectedType)
-       }
-       if len(result.Header) != 1 {
-               t.Errorf("len(result.Header): got:%d want:1", len(result.Header))
-       }
-       v, ok := result.Header["Version"]
-       if !ok || v != "GnuPG v1.4.10 (GNU/Linux)" {
-               t.Errorf("result.Header: got:%#v", result.Header)
-       }
-
-       contents, err := ioutil.ReadAll(result.Body)
-       if err != nil {
-               t.Error(err)
-       }
-
-       if adler32.Checksum(contents) != 0x27b144be {
-               t.Errorf("contents: got: %x", contents)
-       }
-
-       buf = bytes.NewBuffer(nil)
-       w, err := Encode(buf, result.Type, result.Header)
-       if err != nil {
-               t.Error(err)
-       }
-       _, err = w.Write(contents)
-       if err != nil {
-               t.Error(err)
-       }
-       w.Close()
-
-       if !bytes.Equal(buf.Bytes(), []byte(armorExample1)) {
-               t.Errorf("got: %s\nwant: %s", string(buf.Bytes()), armorExample1)
-       }
-}
-
-func TestLongHeader(t *testing.T) {
-       buf := bytes.NewBuffer([]byte(armorLongLine))
-       result, err := Decode(buf)
-       if err != nil {
-               t.Error(err)
-               return
-       }
-       value, ok := result.Header["Version"]
-       if !ok {
-               t.Errorf("missing Version header")
-       }
-       if value != longValueExpected {
-               t.Errorf("got: %s want: %s", value, longValueExpected)
-       }
-}
-
-const armorExample1 = `-----BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.10 (GNU/Linux)
-
-iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
-4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
-p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
-TxRjs+fJCIFuo71xb1g=
-=/teI
------END PGP SIGNATURE-----`
-
-const armorLongLine = `-----BEGIN PGP SIGNATURE-----
-Version: 0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz
-
-iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
-kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
-cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
-byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
-WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
-okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
-=wfQG
------END PGP SIGNATURE-----`
-
-const longValueExpected = "0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz"
diff --git a/libgo/go/crypto/openpgp/armor/encode.go b/libgo/go/crypto/openpgp/armor/encode.go
deleted file mode 100644 (file)
index 6f07582..0000000
+++ /dev/null
@@ -1,160 +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 armor
-
-import (
-       "encoding/base64"
-       "io"
-)
-
-var armorHeaderSep = []byte(": ")
-var blockEnd = []byte("\n=")
-var newline = []byte("\n")
-var armorEndOfLineOut = []byte("-----\n")
-
-// writeSlices writes its arguments to the given Writer.
-func writeSlices(out io.Writer, slices ...[]byte) (err error) {
-       for _, s := range slices {
-               _, err = out.Write(s)
-               if err != nil {
-                       return err
-               }
-       }
-       return
-}
-
-// lineBreaker breaks data across several lines, all of the same byte length
-// (except possibly the last). Lines are broken with a single '\n'.
-type lineBreaker struct {
-       lineLength  int
-       line        []byte
-       used        int
-       out         io.Writer
-       haveWritten bool
-}
-
-func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
-       return &lineBreaker{
-               lineLength: lineLength,
-               line:       make([]byte, lineLength),
-               used:       0,
-               out:        out,
-       }
-}
-
-func (l *lineBreaker) Write(b []byte) (n int, err error) {
-       n = len(b)
-
-       if n == 0 {
-               return
-       }
-
-       if l.used == 0 && l.haveWritten {
-               _, err = l.out.Write([]byte{'\n'})
-               if err != nil {
-                       return
-               }
-       }
-
-       if l.used+len(b) < l.lineLength {
-               l.used += copy(l.line[l.used:], b)
-               return
-       }
-
-       l.haveWritten = true
-       _, err = l.out.Write(l.line[0:l.used])
-       if err != nil {
-               return
-       }
-       excess := l.lineLength - l.used
-       l.used = 0
-
-       _, err = l.out.Write(b[0:excess])
-       if err != nil {
-               return
-       }
-
-       _, err = l.Write(b[excess:])
-       return
-}
-
-func (l *lineBreaker) Close() (err error) {
-       if l.used > 0 {
-               _, err = l.out.Write(l.line[0:l.used])
-               if err != nil {
-                       return
-               }
-       }
-
-       return
-}
-
-// encoding keeps track of a running CRC24 over the data which has been written
-// to it and outputs a OpenPGP checksum when closed, followed by an armor
-// trailer.
-//
-// It's built into a stack of io.Writers:
-//    encoding -> base64 encoder -> lineBreaker -> out
-type encoding struct {
-       out       io.Writer
-       breaker   *lineBreaker
-       b64       io.WriteCloser
-       crc       uint32
-       blockType []byte
-}
-
-func (e *encoding) Write(data []byte) (n int, err error) {
-       e.crc = crc24(e.crc, data)
-       return e.b64.Write(data)
-}
-
-func (e *encoding) Close() (err error) {
-       err = e.b64.Close()
-       if err != nil {
-               return
-       }
-       e.breaker.Close()
-
-       var checksumBytes [3]byte
-       checksumBytes[0] = byte(e.crc >> 16)
-       checksumBytes[1] = byte(e.crc >> 8)
-       checksumBytes[2] = byte(e.crc)
-
-       var b64ChecksumBytes [4]byte
-       base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
-
-       return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
-}
-
-// Encode returns a WriteCloser which will encode the data written to it in
-// OpenPGP armor.
-func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
-       bType := []byte(blockType)
-       err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
-       if err != nil {
-               return
-       }
-
-       for k, v := range headers {
-               err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
-               if err != nil {
-                       return
-               }
-       }
-
-       _, err = out.Write(newline)
-       if err != nil {
-               return
-       }
-
-       e := &encoding{
-               out:       out,
-               breaker:   newLineBreaker(out, 64),
-               crc:       crc24Init,
-               blockType: bType,
-       }
-       e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
-       return e, nil
-}
diff --git a/libgo/go/crypto/openpgp/canonical_text.go b/libgo/go/crypto/openpgp/canonical_text.go
deleted file mode 100644 (file)
index e601e38..0000000
+++ /dev/null
@@ -1,59 +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 openpgp
-
-import "hash"
-
-// NewCanonicalTextHash reformats text written to it into the canonical
-// form and then applies the hash h.  See RFC 4880, section 5.2.1.
-func NewCanonicalTextHash(h hash.Hash) hash.Hash {
-       return &canonicalTextHash{h, 0}
-}
-
-type canonicalTextHash struct {
-       h hash.Hash
-       s int
-}
-
-var newline = []byte{'\r', '\n'}
-
-func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
-       start := 0
-
-       for i, c := range buf {
-               switch cth.s {
-               case 0:
-                       if c == '\r' {
-                               cth.s = 1
-                       } else if c == '\n' {
-                               cth.h.Write(buf[start:i])
-                               cth.h.Write(newline)
-                               start = i + 1
-                       }
-               case 1:
-                       cth.s = 0
-               }
-       }
-
-       cth.h.Write(buf[start:])
-       return len(buf), nil
-}
-
-func (cth *canonicalTextHash) Sum(in []byte) []byte {
-       return cth.h.Sum(in)
-}
-
-func (cth *canonicalTextHash) Reset() {
-       cth.h.Reset()
-       cth.s = 0
-}
-
-func (cth *canonicalTextHash) Size() int {
-       return cth.h.Size()
-}
-
-func (cth *canonicalTextHash) BlockSize() int {
-       return cth.h.BlockSize()
-}
diff --git a/libgo/go/crypto/openpgp/canonical_text_test.go b/libgo/go/crypto/openpgp/canonical_text_test.go
deleted file mode 100644 (file)
index 8f3ba2a..0000000
+++ /dev/null
@@ -1,52 +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 openpgp
-
-import (
-       "bytes"
-       "testing"
-)
-
-type recordingHash struct {
-       buf *bytes.Buffer
-}
-
-func (r recordingHash) Write(b []byte) (n int, err error) {
-       return r.buf.Write(b)
-}
-
-func (r recordingHash) Sum(in []byte) []byte {
-       return append(in, r.buf.Bytes()...)
-}
-
-func (r recordingHash) Reset() {
-       panic("shouldn't be called")
-}
-
-func (r recordingHash) Size() int {
-       panic("shouldn't be called")
-}
-
-func (r recordingHash) BlockSize() int {
-       panic("shouldn't be called")
-}
-
-func testCanonicalText(t *testing.T, input, expected string) {
-       r := recordingHash{bytes.NewBuffer(nil)}
-       c := NewCanonicalTextHash(r)
-       c.Write([]byte(input))
-       result := c.Sum(nil)
-       if expected != string(result) {
-               t.Errorf("input: %x got: %x want: %x", input, result, expected)
-       }
-}
-
-func TestCanonicalText(t *testing.T) {
-       testCanonicalText(t, "foo\n", "foo\r\n")
-       testCanonicalText(t, "foo", "foo")
-       testCanonicalText(t, "foo\r\n", "foo\r\n")
-       testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
-       testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
-}
diff --git a/libgo/go/crypto/openpgp/elgamal/elgamal.go b/libgo/go/crypto/openpgp/elgamal/elgamal.go
deleted file mode 100644 (file)
index a553bde..0000000
+++ /dev/null
@@ -1,122 +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 elgamal implements ElGamal encryption, suitable for OpenPGP,
-// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
-// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
-// n. 4, 1985, pp. 469-472.
-//
-// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
-// unsuitable for other protocols. RSA should be used in preference in any
-// case.
-package elgamal
-
-import (
-       "crypto/rand"
-       "crypto/subtle"
-       "errors"
-       "io"
-       "math/big"
-)
-
-// PublicKey represents an ElGamal public key.
-type PublicKey struct {
-       G, P, Y *big.Int
-}
-
-// PrivateKey represents an ElGamal private key.
-type PrivateKey struct {
-       PublicKey
-       X *big.Int
-}
-
-// Encrypt encrypts the given message to the given public key. The result is a
-// pair of integers. Errors can result from reading random, or because msg is
-// too large to be encrypted to the public key.
-func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
-       pLen := (pub.P.BitLen() + 7) / 8
-       if len(msg) > pLen-11 {
-               err = errors.New("elgamal: message too long")
-               return
-       }
-
-       // EM = 0x02 || PS || 0x00 || M
-       em := make([]byte, pLen-1)
-       em[0] = 2
-       ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
-       err = nonZeroRandomBytes(ps, random)
-       if err != nil {
-               return
-       }
-       em[len(em)-len(msg)-1] = 0
-       copy(mm, msg)
-
-       m := new(big.Int).SetBytes(em)
-
-       k, err := rand.Int(random, pub.P)
-       if err != nil {
-               return
-       }
-
-       c1 = new(big.Int).Exp(pub.G, k, pub.P)
-       s := new(big.Int).Exp(pub.Y, k, pub.P)
-       c2 = s.Mul(s, m)
-       c2.Mod(c2, pub.P)
-
-       return
-}
-
-// Decrypt takes two integers, resulting from an ElGamal encryption, and
-// returns the plaintext of the message. An error can result only if the
-// ciphertext is invalid. Users should keep in mind that this is a padding
-// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
-// be used to break the cryptosystem.  See ``Chosen Ciphertext Attacks
-// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
-// Bleichenbacher, Advances in Cryptology (Crypto '98),
-func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
-       s := new(big.Int).Exp(c1, priv.X, priv.P)
-       s.ModInverse(s, priv.P)
-       s.Mul(s, c2)
-       s.Mod(s, priv.P)
-       em := s.Bytes()
-
-       firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
-
-       // The remainder of the plaintext must be a string of non-zero random
-       // octets, followed by a 0, followed by the message.
-       //   lookingForIndex: 1 iff we are still looking for the zero.
-       //   index: the offset of the first zero byte.
-       var lookingForIndex, index int
-       lookingForIndex = 1
-
-       for i := 1; i < len(em); i++ {
-               equals0 := subtle.ConstantTimeByteEq(em[i], 0)
-               index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
-               lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
-       }
-
-       if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
-               return nil, errors.New("elgamal: decryption error")
-       }
-       return em[index+1:], nil
-}
-
-// nonZeroRandomBytes fills the given slice with non-zero random octets.
-func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
-       _, err = io.ReadFull(rand, s)
-       if err != nil {
-               return
-       }
-
-       for i := 0; i < len(s); i++ {
-               for s[i] == 0 {
-                       _, err = io.ReadFull(rand, s[i:i+1])
-                       if err != nil {
-                               return
-                       }
-               }
-       }
-
-       return
-}
diff --git a/libgo/go/crypto/openpgp/elgamal/elgamal_test.go b/libgo/go/crypto/openpgp/elgamal/elgamal_test.go
deleted file mode 100644 (file)
index c4f99f5..0000000
+++ /dev/null
@@ -1,49 +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 elgamal
-
-import (
-       "bytes"
-       "crypto/rand"
-       "math/big"
-       "testing"
-)
-
-// This is the 1024-bit MODP group from RFC 5114, section 2.1:
-const primeHex = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371"
-
-const generatorHex = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5"
-
-func fromHex(hex string) *big.Int {
-       n, ok := new(big.Int).SetString(hex, 16)
-       if !ok {
-               panic("failed to parse hex number")
-       }
-       return n
-}
-
-func TestEncryptDecrypt(t *testing.T) {
-       priv := &PrivateKey{
-               PublicKey: PublicKey{
-                       G: fromHex(generatorHex),
-                       P: fromHex(primeHex),
-               },
-               X: fromHex("42"),
-       }
-       priv.Y = new(big.Int).Exp(priv.G, priv.X, priv.P)
-
-       message := []byte("hello world")
-       c1, c2, err := Encrypt(rand.Reader, &priv.PublicKey, message)
-       if err != nil {
-               t.Errorf("error encrypting: %s", err)
-       }
-       message2, err := Decrypt(priv, c1, c2)
-       if err != nil {
-               t.Errorf("error decrypting: %s", err)
-       }
-       if !bytes.Equal(message2, message) {
-               t.Errorf("decryption failed, got: %x, want: %x", message2, message)
-       }
-}
diff --git a/libgo/go/crypto/openpgp/errors/errors.go b/libgo/go/crypto/openpgp/errors/errors.go
deleted file mode 100644 (file)
index c434b76..0000000
+++ /dev/null
@@ -1,64 +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 errors contains common error types for the OpenPGP packages.
-package errors
-
-import (
-       "strconv"
-)
-
-// A StructuralError is returned when OpenPGP data is found to be syntactically
-// invalid.
-type StructuralError string
-
-func (s StructuralError) Error() string {
-       return "OpenPGP data invalid: " + string(s)
-}
-
-// UnsupportedError indicates that, although the OpenPGP data is valid, it
-// makes use of currently unimplemented features.
-type UnsupportedError string
-
-func (s UnsupportedError) Error() string {
-       return "OpenPGP feature unsupported: " + string(s)
-}
-
-// InvalidArgumentError indicates that the caller is in error and passed an
-// incorrect value.
-type InvalidArgumentError string
-
-func (i InvalidArgumentError) Error() string {
-       return "OpenPGP argument invalid: " + string(i)
-}
-
-// SignatureError indicates that a syntactically valid signature failed to
-// validate.
-type SignatureError string
-
-func (b SignatureError) Error() string {
-       return "OpenPGP signature invalid: " + string(b)
-}
-
-type keyIncorrectError int
-
-func (ki keyIncorrectError) Error() string {
-       return "the given key was incorrect"
-}
-
-var KeyIncorrectError = keyIncorrectError(0)
-
-type unknownIssuerError int
-
-func (unknownIssuerError) Error() string {
-       return "signature make by unknown entity"
-}
-
-var UnknownIssuerError = unknownIssuerError(0)
-
-type UnknownPacketTypeError uint8
-
-func (upte UnknownPacketTypeError) Error() string {
-       return "unknown OpenPGP packet type: " + strconv.Itoa(int(upte))
-}
diff --git a/libgo/go/crypto/openpgp/keys.go b/libgo/go/crypto/openpgp/keys.go
deleted file mode 100644 (file)
index 624a5ea..0000000
+++ /dev/null
@@ -1,546 +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 openpgp
-
-import (
-       "crypto"
-       "crypto/openpgp/armor"
-       "crypto/openpgp/errors"
-       "crypto/openpgp/packet"
-       "crypto/rand"
-       "crypto/rsa"
-       "io"
-       "time"
-)
-
-// PublicKeyType is the armor type for a PGP public key.
-var PublicKeyType = "PGP PUBLIC KEY BLOCK"
-
-// PrivateKeyType is the armor type for a PGP private key.
-var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
-
-// An Entity represents the components of an OpenPGP key: a primary public key
-// (which must be a signing key), one or more identities claimed by that key,
-// and zero or more subkeys, which may be encryption keys.
-type Entity struct {
-       PrimaryKey *packet.PublicKey
-       PrivateKey *packet.PrivateKey
-       Identities map[string]*Identity // indexed by Identity.Name
-       Subkeys    []Subkey
-}
-
-// An Identity represents an identity claimed by an Entity and zero or more
-// assertions by other entities about that claim.
-type Identity struct {
-       Name          string // by convention, has the form "Full Name (comment) <email@example.com>"
-       UserId        *packet.UserId
-       SelfSignature *packet.Signature
-       Signatures    []*packet.Signature
-}
-
-// A Subkey is an additional public key in an Entity. Subkeys can be used for
-// encryption.
-type Subkey struct {
-       PublicKey  *packet.PublicKey
-       PrivateKey *packet.PrivateKey
-       Sig        *packet.Signature
-}
-
-// A Key identifies a specific public key in an Entity. This is either the
-// Entity's primary key or a subkey.
-type Key struct {
-       Entity        *Entity
-       PublicKey     *packet.PublicKey
-       PrivateKey    *packet.PrivateKey
-       SelfSignature *packet.Signature
-}
-
-// A KeyRing provides access to public and private keys.
-type KeyRing interface {
-       // KeysById returns the set of keys that have the given key id.
-       KeysById(id uint64) []Key
-       // DecryptionKeys returns all private keys that are valid for
-       // decryption.
-       DecryptionKeys() []Key
-}
-
-// primaryIdentity returns the Identity marked as primary or the first identity
-// if none are so marked.
-func (e *Entity) primaryIdentity() *Identity {
-       var firstIdentity *Identity
-       for _, ident := range e.Identities {
-               if firstIdentity == nil {
-                       firstIdentity = ident
-               }
-               if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
-                       return ident
-               }
-       }
-       return firstIdentity
-}
-
-// encryptionKey returns the best candidate Key for encrypting a message to the
-// given Entity.
-func (e *Entity) encryptionKey() Key {
-       candidateSubkey := -1
-
-       for i, subkey := range e.Subkeys {
-               if subkey.Sig.FlagsValid && subkey.Sig.FlagEncryptCommunications && subkey.PublicKey.PubKeyAlgo.CanEncrypt() {
-                       candidateSubkey = i
-                       break
-               }
-       }
-
-       i := e.primaryIdentity()
-
-       if e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
-               // If we don't have any candidate subkeys for encryption and
-               // the primary key doesn't have any usage metadata then we
-               // assume that the primary key is ok. Or, if the primary key is
-               // marked as ok to encrypt to, then we can obviously use it.
-               if candidateSubkey == -1 && !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && i.SelfSignature.FlagsValid {
-                       return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}
-               }
-       }
-
-       if candidateSubkey != -1 {
-               subkey := e.Subkeys[candidateSubkey]
-               return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}
-       }
-
-       // This Entity appears to be signing only.
-       return Key{}
-}
-
-// signingKey return the best candidate Key for signing a message with this
-// Entity.
-func (e *Entity) signingKey() Key {
-       candidateSubkey := -1
-
-       for i, subkey := range e.Subkeys {
-               if subkey.Sig.FlagsValid && subkey.Sig.FlagSign && subkey.PublicKey.PubKeyAlgo.CanSign() {
-                       candidateSubkey = i
-                       break
-               }
-       }
-
-       i := e.primaryIdentity()
-
-       // If we have no candidate subkey then we assume that it's ok to sign
-       // with the primary key.
-       if candidateSubkey == -1 || i.SelfSignature.FlagsValid && i.SelfSignature.FlagSign {
-               return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}
-       }
-
-       subkey := e.Subkeys[candidateSubkey]
-       return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}
-}
-
-// An EntityList contains one or more Entities.
-type EntityList []*Entity
-
-// KeysById returns the set of keys that have the given key id.
-func (el EntityList) KeysById(id uint64) (keys []Key) {
-       for _, e := range el {
-               if e.PrimaryKey.KeyId == id {
-                       var selfSig *packet.Signature
-                       for _, ident := range e.Identities {
-                               if selfSig == nil {
-                                       selfSig = ident.SelfSignature
-                               } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
-                                       selfSig = ident.SelfSignature
-                                       break
-                               }
-                       }
-                       keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
-               }
-
-               for _, subKey := range e.Subkeys {
-                       if subKey.PublicKey.KeyId == id {
-                               keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
-                       }
-               }
-       }
-       return
-}
-
-// DecryptionKeys returns all private keys that are valid for decryption.
-func (el EntityList) DecryptionKeys() (keys []Key) {
-       for _, e := range el {
-               for _, subKey := range e.Subkeys {
-                       if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
-                               keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
-                       }
-               }
-       }
-       return
-}
-
-// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
-func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
-       block, err := armor.Decode(r)
-       if err == io.EOF {
-               return nil, errors.InvalidArgumentError("no armored data found")
-       }
-       if err != nil {
-               return nil, err
-       }
-       if block.Type != PublicKeyType && block.Type != PrivateKeyType {
-               return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
-       }
-
-       return ReadKeyRing(block.Body)
-}
-
-// ReadKeyRing reads one or more public/private keys. Unsupported keys are
-// ignored as long as at least a single valid key is found.
-func ReadKeyRing(r io.Reader) (el EntityList, err error) {
-       packets := packet.NewReader(r)
-       var lastUnsupportedError error
-
-       for {
-               var e *Entity
-               e, err = readEntity(packets)
-               if err != nil {
-                       if _, ok := err.(errors.UnsupportedError); ok {
-                               lastUnsupportedError = err
-                               err = readToNextPublicKey(packets)
-                       }
-                       if err == io.EOF {
-                               err = nil
-                               break
-                       }
-                       if err != nil {
-                               el = nil
-                               break
-                       }
-               } else {
-                       el = append(el, e)
-               }
-       }
-
-       if len(el) == 0 && err == nil {
-               err = lastUnsupportedError
-       }
-       return
-}
-
-// readToNextPublicKey reads packets until the start of the entity and leaves
-// the first packet of the new entity in the Reader.
-func readToNextPublicKey(packets *packet.Reader) (err error) {
-       var p packet.Packet
-       for {
-               p, err = packets.Next()
-               if err == io.EOF {
-                       return
-               } else if err != nil {
-                       if _, ok := err.(errors.UnsupportedError); ok {
-                               err = nil
-                               continue
-                       }
-                       return
-               }
-
-               if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
-                       packets.Unread(p)
-                       return
-               }
-       }
-
-       panic("unreachable")
-}
-
-// readEntity reads an entity (public key, identities, subkeys etc) from the
-// given Reader.
-func readEntity(packets *packet.Reader) (*Entity, error) {
-       e := new(Entity)
-       e.Identities = make(map[string]*Identity)
-
-       p, err := packets.Next()
-       if err != nil {
-               return nil, err
-       }
-
-       var ok bool
-       if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
-               if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
-                       packets.Unread(p)
-                       return nil, errors.StructuralError("first packet was not a public/private key")
-               } else {
-                       e.PrimaryKey = &e.PrivateKey.PublicKey
-               }
-       }
-
-       if !e.PrimaryKey.PubKeyAlgo.CanSign() {
-               return nil, errors.StructuralError("primary key cannot be used for signatures")
-       }
-
-       var current *Identity
-EachPacket:
-       for {
-               p, err := packets.Next()
-               if err == io.EOF {
-                       break
-               } else if err != nil {
-                       return nil, err
-               }
-
-               switch pkt := p.(type) {
-               case *packet.UserId:
-                       current = new(Identity)
-                       current.Name = pkt.Id
-                       current.UserId = pkt
-                       e.Identities[pkt.Id] = current
-
-                       for {
-                               p, err = packets.Next()
-                               if err == io.EOF {
-                                       return nil, io.ErrUnexpectedEOF
-                               } else if err != nil {
-                                       return nil, err
-                               }
-
-                               sig, ok := p.(*packet.Signature)
-                               if !ok {
-                                       return nil, errors.StructuralError("user ID packet not followed by self-signature")
-                               }
-
-                               if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
-                                       if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
-                                               return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
-                                       }
-                                       current.SelfSignature = sig
-                                       break
-                               }
-                               current.Signatures = append(current.Signatures, sig)
-                       }
-               case *packet.Signature:
-                       if current == nil {
-                               return nil, errors.StructuralError("signature packet found before user id packet")
-                       }
-                       current.Signatures = append(current.Signatures, pkt)
-               case *packet.PrivateKey:
-                       if pkt.IsSubkey == false {
-                               packets.Unread(p)
-                               break EachPacket
-                       }
-                       err = addSubkey(e, packets, &pkt.PublicKey, pkt)
-                       if err != nil {
-                               return nil, err
-                       }
-               case *packet.PublicKey:
-                       if pkt.IsSubkey == false {
-                               packets.Unread(p)
-                               break EachPacket
-                       }
-                       err = addSubkey(e, packets, pkt, nil)
-                       if err != nil {
-                               return nil, err
-                       }
-               default:
-                       // we ignore unknown packets
-               }
-       }
-
-       if len(e.Identities) == 0 {
-               return nil, errors.StructuralError("entity without any identities")
-       }
-
-       return e, nil
-}
-
-func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
-       var subKey Subkey
-       subKey.PublicKey = pub
-       subKey.PrivateKey = priv
-       p, err := packets.Next()
-       if err == io.EOF {
-               return io.ErrUnexpectedEOF
-       }
-       if err != nil {
-               return errors.StructuralError("subkey signature invalid: " + err.Error())
-       }
-       var ok bool
-       subKey.Sig, ok = p.(*packet.Signature)
-       if !ok {
-               return errors.StructuralError("subkey packet not followed by signature")
-       }
-       if subKey.Sig.SigType != packet.SigTypeSubkeyBinding {
-               return errors.StructuralError("subkey signature with wrong type")
-       }
-       err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
-       if err != nil {
-               return errors.StructuralError("subkey signature invalid: " + err.Error())
-       }
-       e.Subkeys = append(e.Subkeys, subKey)
-       return nil
-}
-
-const defaultRSAKeyBits = 2048
-
-// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
-// single identity composed of the given full name, comment and email, any of
-// which may be empty but must not contain any of "()<>\x00".
-func NewEntity(rand io.Reader, currentTime time.Time, name, comment, email string) (*Entity, error) {
-       uid := packet.NewUserId(name, comment, email)
-       if uid == nil {
-               return nil, errors.InvalidArgumentError("user id field contained invalid characters")
-       }
-       signingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
-       if err != nil {
-               return nil, err
-       }
-       encryptingPriv, err := rsa.GenerateKey(rand, defaultRSAKeyBits)
-       if err != nil {
-               return nil, err
-       }
-
-       e := &Entity{
-               PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
-               PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
-               Identities: make(map[string]*Identity),
-       }
-       isPrimaryId := true
-       e.Identities[uid.Id] = &Identity{
-               Name:   uid.Name,
-               UserId: uid,
-               SelfSignature: &packet.Signature{
-                       CreationTime: currentTime,
-                       SigType:      packet.SigTypePositiveCert,
-                       PubKeyAlgo:   packet.PubKeyAlgoRSA,
-                       Hash:         crypto.SHA256,
-                       IsPrimaryId:  &isPrimaryId,
-                       FlagsValid:   true,
-                       FlagSign:     true,
-                       FlagCertify:  true,
-                       IssuerKeyId:  &e.PrimaryKey.KeyId,
-               },
-       }
-
-       e.Subkeys = make([]Subkey, 1)
-       e.Subkeys[0] = Subkey{
-               PublicKey:  packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
-               PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
-               Sig: &packet.Signature{
-                       CreationTime:              currentTime,
-                       SigType:                   packet.SigTypeSubkeyBinding,
-                       PubKeyAlgo:                packet.PubKeyAlgoRSA,
-                       Hash:                      crypto.SHA256,
-                       FlagsValid:                true,
-                       FlagEncryptStorage:        true,
-                       FlagEncryptCommunications: true,
-                       IssuerKeyId:               &e.PrimaryKey.KeyId,
-               },
-       }
-       e.Subkeys[0].PublicKey.IsSubkey = true
-       e.Subkeys[0].PrivateKey.IsSubkey = true
-
-       return e, nil
-}
-
-// SerializePrivate serializes an Entity, including private key material, to
-// the given Writer. For now, it must only be used on an Entity returned from
-// NewEntity.
-func (e *Entity) SerializePrivate(w io.Writer) (err error) {
-       err = e.PrivateKey.Serialize(w)
-       if err != nil {
-               return
-       }
-       for _, ident := range e.Identities {
-               err = ident.UserId.Serialize(w)
-               if err != nil {
-                       return
-               }
-               err = ident.SelfSignature.SignUserId(rand.Reader, ident.UserId.Id, e.PrimaryKey, e.PrivateKey)
-               if err != nil {
-                       return
-               }
-               err = ident.SelfSignature.Serialize(w)
-               if err != nil {
-                       return
-               }
-       }
-       for _, subkey := range e.Subkeys {
-               err = subkey.PrivateKey.Serialize(w)
-               if err != nil {
-                       return
-               }
-               err = subkey.Sig.SignKey(rand.Reader, subkey.PublicKey, e.PrivateKey)
-               if err != nil {
-                       return
-               }
-               err = subkey.Sig.Serialize(w)
-               if err != nil {
-                       return
-               }
-       }
-       return nil
-}
-
-// Serialize writes the public part of the given Entity to w. (No private
-// key material will be output).
-func (e *Entity) Serialize(w io.Writer) error {
-       err := e.PrimaryKey.Serialize(w)
-       if err != nil {
-               return err
-       }
-       for _, ident := range e.Identities {
-               err = ident.UserId.Serialize(w)
-               if err != nil {
-                       return err
-               }
-               err = ident.SelfSignature.Serialize(w)
-               if err != nil {
-                       return err
-               }
-               for _, sig := range ident.Signatures {
-                       err = sig.Serialize(w)
-                       if err != nil {
-                               return err
-                       }
-               }
-       }
-       for _, subkey := range e.Subkeys {
-               err = subkey.PublicKey.Serialize(w)
-               if err != nil {
-                       return err
-               }
-               err = subkey.Sig.Serialize(w)
-               if err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-// SignIdentity adds a signature to e, from signer, attesting that identity is
-// associated with e. The provided identity must already be an element of
-// e.Identities and the private key of signer must have been decrypted if
-// necessary.
-func (e *Entity) SignIdentity(identity string, signer *Entity) error {
-       if signer.PrivateKey == nil {
-               return errors.InvalidArgumentError("signing Entity must have a private key")
-       }
-       if signer.PrivateKey.Encrypted {
-               return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
-       }
-       ident, ok := e.Identities[identity]
-       if !ok {
-               return errors.InvalidArgumentError("given identity string not found in Entity")
-       }
-
-       sig := &packet.Signature{
-               SigType:      packet.SigTypeGenericCert,
-               PubKeyAlgo:   signer.PrivateKey.PubKeyAlgo,
-               Hash:         crypto.SHA256,
-               CreationTime: time.Now(),
-               IssuerKeyId:  &signer.PrivateKey.KeyId,
-       }
-       if err := sig.SignKey(rand.Reader, e.PrimaryKey, signer.PrivateKey); err != nil {
-               return err
-       }
-       ident.Signatures = append(ident.Signatures, sig)
-       return nil
-}
diff --git a/libgo/go/crypto/openpgp/packet/compressed.go b/libgo/go/crypto/openpgp/packet/compressed.go
deleted file mode 100644 (file)
index 36736e3..0000000
+++ /dev/null
@@ -1,38 +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 packet
-
-import (
-       "compress/flate"
-       "compress/zlib"
-       "crypto/openpgp/errors"
-       "io"
-       "strconv"
-)
-
-// Compressed represents a compressed OpenPGP packet. The decompressed contents
-// will contain more OpenPGP packets. See RFC 4880, section 5.6.
-type Compressed struct {
-       Body io.Reader
-}
-
-func (c *Compressed) parse(r io.Reader) error {
-       var buf [1]byte
-       _, err := readFull(r, buf[:])
-       if err != nil {
-               return err
-       }
-
-       switch buf[0] {
-       case 1:
-               c.Body = flate.NewReader(r)
-       case 2:
-               c.Body, err = zlib.NewReader(r)
-       default:
-               err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
-       }
-
-       return err
-}
diff --git a/libgo/go/crypto/openpgp/packet/compressed_test.go b/libgo/go/crypto/openpgp/packet/compressed_test.go
deleted file mode 100644 (file)
index cb2d70b..0000000
+++ /dev/null
@@ -1,41 +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 packet
-
-import (
-       "bytes"
-       "encoding/hex"
-       "io"
-       "io/ioutil"
-       "testing"
-)
-
-func TestCompressed(t *testing.T) {
-       packet, err := Read(readerFromHex(compressedHex))
-       if err != nil {
-               t.Errorf("failed to read Compressed: %s", err)
-               return
-       }
-
-       c, ok := packet.(*Compressed)
-       if !ok {
-               t.Error("didn't find Compressed packet")
-               return
-       }
-
-       contents, err := ioutil.ReadAll(c.Body)
-       if err != nil && err != io.EOF {
-               t.Error(err)
-               return
-       }
-
-       expected, _ := hex.DecodeString(compressedExpectedHex)
-       if !bytes.Equal(expected, contents) {
-               t.Errorf("got:%x want:%x", contents, expected)
-       }
-}
-
-const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
-const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"
diff --git a/libgo/go/crypto/openpgp/packet/encrypted_key.go b/libgo/go/crypto/openpgp/packet/encrypted_key.go
deleted file mode 100644 (file)
index 479a643..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
-       "crypto/openpgp/elgamal"
-       "crypto/openpgp/errors"
-       "crypto/rand"
-       "crypto/rsa"
-       "encoding/binary"
-       "io"
-       "math/big"
-       "strconv"
-)
-
-const encryptedKeyVersion = 3
-
-// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
-// section 5.1.
-type EncryptedKey struct {
-       KeyId      uint64
-       Algo       PublicKeyAlgorithm
-       CipherFunc CipherFunction // only valid after a successful Decrypt
-       Key        []byte         // only valid after a successful Decrypt
-
-       encryptedMPI1, encryptedMPI2 []byte
-}
-
-func (e *EncryptedKey) parse(r io.Reader) (err error) {
-       var buf [10]byte
-       _, err = readFull(r, buf[:])
-       if err != nil {
-               return
-       }
-       if buf[0] != encryptedKeyVersion {
-               return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
-       }
-       e.KeyId = binary.BigEndian.Uint64(buf[1:9])
-       e.Algo = PublicKeyAlgorithm(buf[9])
-       switch e.Algo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
-               e.encryptedMPI1, _, err = readMPI(r)
-       case PubKeyAlgoElGamal:
-               e.encryptedMPI1, _, err = readMPI(r)
-               if err != nil {
-                       return
-               }
-               e.encryptedMPI2, _, err = readMPI(r)
-       }
-       _, err = consumeAll(r)
-       return
-}
-
-func checksumKeyMaterial(key []byte) uint16 {
-       var checksum uint16
-       for _, v := range key {
-               checksum += uint16(v)
-       }
-       return checksum
-}
-
-// Decrypt decrypts an encrypted session key with the given private key. The
-// private key must have been decrypted first.
-func (e *EncryptedKey) Decrypt(priv *PrivateKey) error {
-       var err error
-       var b []byte
-
-       // TODO(agl): use session key decryption routines here to avoid
-       // padding oracle attacks.
-       switch priv.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
-               b, err = rsa.DecryptPKCS1v15(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
-       case PubKeyAlgoElGamal:
-               c1 := new(big.Int).SetBytes(e.encryptedMPI1)
-               c2 := new(big.Int).SetBytes(e.encryptedMPI2)
-               b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
-       default:
-               err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
-       }
-
-       if err != nil {
-               return err
-       }
-
-       e.CipherFunc = CipherFunction(b[0])
-       e.Key = b[1 : len(b)-2]
-       expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
-       checksum := checksumKeyMaterial(e.Key)
-       if checksum != expectedChecksum {
-               return errors.StructuralError("EncryptedKey checksum incorrect")
-       }
-
-       return nil
-}
-
-// SerializeEncryptedKey serializes an encrypted key packet to w that contains
-// key, encrypted to pub.
-func SerializeEncryptedKey(w io.Writer, rand io.Reader, pub *PublicKey, cipherFunc CipherFunction, key []byte) error {
-       var buf [10]byte
-       buf[0] = encryptedKeyVersion
-       binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
-       buf[9] = byte(pub.PubKeyAlgo)
-
-       keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */ )
-       keyBlock[0] = byte(cipherFunc)
-       copy(keyBlock[1:], key)
-       checksum := checksumKeyMaterial(key)
-       keyBlock[1+len(key)] = byte(checksum >> 8)
-       keyBlock[1+len(key)+1] = byte(checksum)
-
-       switch pub.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
-               return serializeEncryptedKeyRSA(w, rand, buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
-       case PubKeyAlgoElGamal:
-               return serializeEncryptedKeyElGamal(w, rand, buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
-       case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
-               return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
-       }
-
-       return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
-}
-
-func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
-       cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
-       if err != nil {
-               return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
-       }
-
-       packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
-
-       err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
-       if err != nil {
-               return err
-       }
-       _, err = w.Write(header[:])
-       if err != nil {
-               return err
-       }
-       return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
-}
-
-func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
-       c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
-       if err != nil {
-               return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
-       }
-
-       packetLen := 10 /* header length */
-       packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
-       packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
-
-       err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
-       if err != nil {
-               return err
-       }
-       _, err = w.Write(header[:])
-       if err != nil {
-               return err
-       }
-       err = writeBig(w, c1)
-       if err != nil {
-               return err
-       }
-       return writeBig(w, c2)
-}
diff --git a/libgo/go/crypto/openpgp/packet/encrypted_key_test.go b/libgo/go/crypto/openpgp/packet/encrypted_key_test.go
deleted file mode 100644 (file)
index 2b8eff7..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
-       "bytes"
-       "crypto/rand"
-       "crypto/rsa"
-       "fmt"
-       "math/big"
-       "testing"
-)
-
-func bigFromBase10(s string) *big.Int {
-       b, ok := new(big.Int).SetString(s, 10)
-       if !ok {
-               panic("bigFromBase10 failed")
-       }
-       return b
-}
-
-var encryptedKeyPub = rsa.PublicKey{
-       E: 65537,
-       N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
-}
-
-var encryptedKeyRSAPriv = &rsa.PrivateKey{
-       PublicKey: encryptedKeyPub,
-       D:         bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
-}
-
-var encryptedKeyPriv = &PrivateKey{
-       PublicKey: PublicKey{
-               PubKeyAlgo: PubKeyAlgoRSA,
-       },
-       PrivateKey: encryptedKeyRSAPriv,
-}
-
-func TestDecryptingEncryptedKey(t *testing.T) {
-       const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
-       const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"
-
-       p, err := Read(readerFromHex(encryptedKeyHex))
-       if err != nil {
-               t.Errorf("error from Read: %s", err)
-               return
-       }
-       ek, ok := p.(*EncryptedKey)
-       if !ok {
-               t.Errorf("didn't parse an EncryptedKey, got %#v", p)
-               return
-       }
-
-       if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
-               t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-               return
-       }
-
-       err = ek.Decrypt(encryptedKeyPriv)
-       if err != nil {
-               t.Errorf("error from Decrypt: %s", err)
-               return
-       }
-
-       if ek.CipherFunc != CipherAES256 {
-               t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-               return
-       }
-
-       keyHex := fmt.Sprintf("%x", ek.Key)
-       if keyHex != expectedKeyHex {
-               t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
-       }
-}
-
-func TestEncryptingEncryptedKey(t *testing.T) {
-       key := []byte{1, 2, 3, 4}
-       const expectedKeyHex = "01020304"
-       const keyId = 42
-
-       pub := &PublicKey{
-               PublicKey:  &encryptedKeyPub,
-               KeyId:      keyId,
-               PubKeyAlgo: PubKeyAlgoRSAEncryptOnly,
-       }
-
-       buf := new(bytes.Buffer)
-       err := SerializeEncryptedKey(buf, rand.Reader, pub, CipherAES128, key)
-       if err != nil {
-               t.Errorf("error writing encrypted key packet: %s", err)
-       }
-
-       p, err := Read(buf)
-       if err != nil {
-               t.Errorf("error from Read: %s", err)
-               return
-       }
-       ek, ok := p.(*EncryptedKey)
-       if !ok {
-               t.Errorf("didn't parse an EncryptedKey, got %#v", p)
-               return
-       }
-
-       if ek.KeyId != keyId || ek.Algo != PubKeyAlgoRSAEncryptOnly {
-               t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-               return
-       }
-
-       err = ek.Decrypt(encryptedKeyPriv)
-       if err != nil {
-               t.Errorf("error from Decrypt: %s", err)
-               return
-       }
-
-       if ek.CipherFunc != CipherAES128 {
-               t.Errorf("unexpected EncryptedKey contents: %#v", ek)
-               return
-       }
-
-       keyHex := fmt.Sprintf("%x", ek.Key)
-       if keyHex != expectedKeyHex {
-               t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
-       }
-}
diff --git a/libgo/go/crypto/openpgp/packet/literal.go b/libgo/go/crypto/openpgp/packet/literal.go
deleted file mode 100644 (file)
index 1a9ec6e..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package packet
-
-import (
-       "encoding/binary"
-       "io"
-)
-
-// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
-type LiteralData struct {
-       IsBinary bool
-       FileName string
-       Time     uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
-       Body     io.Reader
-}
-
-// ForEyesOnly returns whether the contents of the LiteralData have been marked
-// as especially sensitive.
-func (l *LiteralData) ForEyesOnly() bool {
-       return l.FileName == "_CONSOLE"
-}
-
-func (l *LiteralData) parse(r io.Reader) (err error) {
-       var buf [256]byte
-
-       _, err = readFull(r, buf[:2])
-       if err != nil {
-               return
-       }
-
-       l.IsBinary = buf[0] == 'b'
-       fileNameLen := int(buf[1])
-
-       _, err = readFull(r, buf[:fileNameLen])
-       if err != nil {
-               return
-       }
-
-       l.FileName = string(buf[:fileNameLen])
-
-       _, err = readFull(r, buf[:4])
-       if err != nil {
-               return
-       }
-
-       l.Time = binary.BigEndian.Uint32(buf[:4])
-       l.Body = r
-       return
-}
-
-// SerializeLiteral serializes a literal data packet to w and returns a
-// WriteCloser to which the data itself can be written and which MUST be closed
-// on completion. The fileName is truncated to 255 bytes.
-func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
-       var buf [4]byte
-       buf[0] = 't'
-       if isBinary {
-               buf[0] = 'b'
-       }
-       if len(fileName) > 255 {
-               fileName = fileName[:255]
-       }
-       buf[1] = byte(len(fileName))
-
-       inner, err := serializeStreamHeader(w, packetTypeLiteralData)
-       if err != nil {
-               return
-       }
-
-       _, err = inner.Write(buf[:2])
-       if err != nil {
-               return
-       }
-       _, err = inner.Write([]byte(fileName))
-       if err != nil {
-               return
-       }
-       binary.BigEndian.PutUint32(buf[:], time)
-       _, err = inner.Write(buf[:])
-       if err != nil {
-               return
-       }
-
-       plaintext = inner
-       return
-}
diff --git a/libgo/go/crypto/openpgp/packet/one_pass_signature.go b/libgo/go/crypto/openpgp/packet/one_pass_signature.go
deleted file mode 100644 (file)
index 822cfe9..0000000
+++ /dev/null
@@ -1,73 +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 packet
-
-import (
-       "crypto"
-       "crypto/openpgp/errors"
-       "crypto/openpgp/s2k"
-       "encoding/binary"
-       "io"
-       "strconv"
-)
-
-// OnePassSignature represents a one-pass signature packet. See RFC 4880,
-// section 5.4.
-type OnePassSignature struct {
-       SigType    SignatureType
-       Hash       crypto.Hash
-       PubKeyAlgo PublicKeyAlgorithm
-       KeyId      uint64
-       IsLast     bool
-}
-
-const onePassSignatureVersion = 3
-
-func (ops *OnePassSignature) parse(r io.Reader) (err error) {
-       var buf [13]byte
-
-       _, err = readFull(r, buf[:])
-       if err != nil {
-               return
-       }
-       if buf[0] != onePassSignatureVersion {
-               err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
-       }
-
-       var ok bool
-       ops.Hash, ok = s2k.HashIdToHash(buf[2])
-       if !ok {
-               return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
-       }
-
-       ops.SigType = SignatureType(buf[1])
-       ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
-       ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
-       ops.IsLast = buf[12] != 0
-       return
-}
-
-// Serialize marshals the given OnePassSignature to w.
-func (ops *OnePassSignature) Serialize(w io.Writer) error {
-       var buf [13]byte
-       buf[0] = onePassSignatureVersion
-       buf[1] = uint8(ops.SigType)
-       var ok bool
-       buf[2], ok = s2k.HashToHashId(ops.Hash)
-       if !ok {
-               return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
-       }
-       buf[3] = uint8(ops.PubKeyAlgo)
-       binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
-       if ops.IsLast {
-               buf[12] = 1
-       }
-
-       if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
-               return err
-       }
-       _, err := w.Write(buf[:])
-       return err
-}
diff --git a/libgo/go/crypto/openpgp/packet/packet.go b/libgo/go/crypto/openpgp/packet/packet.go
deleted file mode 100644 (file)
index f7c1964..0000000
+++ /dev/null
@@ -1,482 +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 packet implements parsing and serialization of OpenPGP packets, as
-// specified in RFC 4880.
-package packet
-
-import (
-       "crypto/aes"
-       "crypto/cast5"
-       "crypto/cipher"
-       "crypto/openpgp/errors"
-       "io"
-       "math/big"
-)
-
-// readFull is the same as io.ReadFull except that reading zero bytes returns
-// ErrUnexpectedEOF rather than EOF.
-func readFull(r io.Reader, buf []byte) (n int, err error) {
-       n, err = io.ReadFull(r, buf)
-       if err == io.EOF {
-               err = io.ErrUnexpectedEOF
-       }
-       return
-}
-
-// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
-func readLength(r io.Reader) (length int64, isPartial bool, err error) {
-       var buf [4]byte
-       _, err = readFull(r, buf[:1])
-       if err != nil {
-               return
-       }
-       switch {
-       case buf[0] < 192:
-               length = int64(buf[0])
-       case buf[0] < 224:
-               length = int64(buf[0]-192) << 8
-               _, err = readFull(r, buf[0:1])
-               if err != nil {
-                       return
-               }
-               length += int64(buf[0]) + 192
-       case buf[0] < 255:
-               length = int64(1) << (buf[0] & 0x1f)
-               isPartial = true
-       default:
-               _, err = readFull(r, buf[0:4])
-               if err != nil {
-                       return
-               }
-               length = int64(buf[0])<<24 |
-                       int64(buf[1])<<16 |
-                       int64(buf[2])<<8 |
-                       int64(buf[3])
-       }
-       return
-}
-
-// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
-// The continuation lengths are parsed and removed from the stream and EOF is
-// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
-type partialLengthReader struct {
-       r         io.Reader
-       remaining int64
-       isPartial bool
-}
-
-func (r *partialLengthReader) Read(p []byte) (n int, err error) {
-       for r.remaining == 0 {
-               if !r.isPartial {
-                       return 0, io.EOF
-               }
-               r.remaining, r.isPartial, err = readLength(r.r)
-               if err != nil {
-                       return 0, err
-               }
-       }
-
-       toRead := int64(len(p))
-       if toRead > r.remaining {
-               toRead = r.remaining
-       }
-
-       n, err = r.r.Read(p[:int(toRead)])
-       r.remaining -= int64(n)
-       if n < int(toRead) && err == io.EOF {
-               err = io.ErrUnexpectedEOF
-       }
-       return
-}
-
-// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
-// See RFC 4880, section 4.2.2.4.
-type partialLengthWriter struct {
-       w          io.WriteCloser
-       lengthByte [1]byte
-}
-
-func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
-       for len(p) > 0 {
-               for power := uint(14); power < 32; power-- {
-                       l := 1 << power
-                       if len(p) >= l {
-                               w.lengthByte[0] = 224 + uint8(power)
-                               _, err = w.w.Write(w.lengthByte[:])
-                               if err != nil {
-                                       return
-                               }
-                               var m int
-                               m, err = w.w.Write(p[:l])
-                               n += m
-                               if err != nil {
-                                       return
-                               }
-                               p = p[l:]
-                               break
-                       }
-               }
-       }
-       return
-}
-
-func (w *partialLengthWriter) Close() error {
-       w.lengthByte[0] = 0
-       _, err := w.w.Write(w.lengthByte[:])
-       if err != nil {
-               return err
-       }
-       return w.w.Close()
-}
-
-// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
-// underlying Reader returns EOF before the limit has been reached.
-type spanReader struct {
-       r io.Reader
-       n int64
-}
-
-func (l *spanReader) Read(p []byte) (n int, err error) {
-       if l.n <= 0 {
-               return 0, io.EOF
-       }
-       if int64(len(p)) > l.n {
-               p = p[0:l.n]
-       }
-       n, err = l.r.Read(p)
-       l.n -= int64(n)
-       if l.n > 0 && err == io.EOF {
-               err = io.ErrUnexpectedEOF
-       }
-       return
-}
-
-// readHeader parses a packet header and returns an io.Reader which will return
-// the contents of the packet. See RFC 4880, section 4.2.
-func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
-       var buf [4]byte
-       _, err = io.ReadFull(r, buf[:1])
-       if err != nil {
-               return
-       }
-       if buf[0]&0x80 == 0 {
-               err = errors.StructuralError("tag byte does not have MSB set")
-               return
-       }
-       if buf[0]&0x40 == 0 {
-               // Old format packet
-               tag = packetType((buf[0] & 0x3f) >> 2)
-               lengthType := buf[0] & 3
-               if lengthType == 3 {
-                       length = -1
-                       contents = r
-                       return
-               }
-               lengthBytes := 1 << lengthType
-               _, err = readFull(r, buf[0:lengthBytes])
-               if err != nil {
-                       return
-               }
-               for i := 0; i < lengthBytes; i++ {
-                       length <<= 8
-                       length |= int64(buf[i])
-               }
-               contents = &spanReader{r, length}
-               return
-       }
-
-       // New format packet
-       tag = packetType(buf[0] & 0x3f)
-       length, isPartial, err := readLength(r)
-       if err != nil {
-               return
-       }
-       if isPartial {
-               contents = &partialLengthReader{
-                       remaining: length,
-                       isPartial: true,
-                       r:         r,
-               }
-               length = -1
-       } else {
-               contents = &spanReader{r, length}
-       }
-       return
-}
-
-// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
-// 4.2.
-func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
-       var buf [6]byte
-       var n int
-
-       buf[0] = 0x80 | 0x40 | byte(ptype)
-       if length < 192 {
-               buf[1] = byte(length)
-               n = 2
-       } else if length < 8384 {
-               length -= 192
-               buf[1] = 192 + byte(length>>8)
-               buf[2] = byte(length)
-               n = 3
-       } else {
-               buf[1] = 255
-               buf[2] = byte(length >> 24)
-               buf[3] = byte(length >> 16)
-               buf[4] = byte(length >> 8)
-               buf[5] = byte(length)
-               n = 6
-       }
-
-       _, err = w.Write(buf[:n])
-       return
-}
-
-// serializeStreamHeader writes an OpenPGP packet header to w where the
-// length of the packet is unknown. It returns a io.WriteCloser which can be
-// used to write the contents of the packet. See RFC 4880, section 4.2.
-func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
-       var buf [1]byte
-       buf[0] = 0x80 | 0x40 | byte(ptype)
-       _, err = w.Write(buf[:])
-       if err != nil {
-               return
-       }
-       out = &partialLengthWriter{w: w}
-       return
-}
-
-// Packet represents an OpenPGP packet. Users are expected to try casting
-// instances of this interface to specific packet types.
-type Packet interface {
-       parse(io.Reader) error
-}
-
-// consumeAll reads from the given Reader until error, returning the number of
-// bytes read.
-func consumeAll(r io.Reader) (n int64, err error) {
-       var m int
-       var buf [1024]byte
-
-       for {
-               m, err = r.Read(buf[:])
-               n += int64(m)
-               if err == io.EOF {
-                       err = nil
-                       return
-               }
-               if err != nil {
-                       return
-               }
-       }
-
-       panic("unreachable")
-}
-
-// packetType represents the numeric ids of the different OpenPGP packet types. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
-type packetType uint8
-
-const (
-       packetTypeEncryptedKey              packetType = 1
-       packetTypeSignature                 packetType = 2
-       packetTypeSymmetricKeyEncrypted     packetType = 3
-       packetTypeOnePassSignature          packetType = 4
-       packetTypePrivateKey                packetType = 5
-       packetTypePublicKey                 packetType = 6
-       packetTypePrivateSubkey             packetType = 7
-       packetTypeCompressed                packetType = 8
-       packetTypeSymmetricallyEncrypted    packetType = 9
-       packetTypeLiteralData               packetType = 11
-       packetTypeUserId                    packetType = 13
-       packetTypePublicSubkey              packetType = 14
-       packetTypeSymmetricallyEncryptedMDC packetType = 18
-)
-
-// Read reads a single OpenPGP packet from the given io.Reader. If there is an
-// error parsing a packet, the whole packet is consumed from the input.
-func Read(r io.Reader) (p Packet, err error) {
-       tag, _, contents, err := readHeader(r)
-       if err != nil {
-               return
-       }
-
-       switch tag {
-       case packetTypeEncryptedKey:
-               p = new(EncryptedKey)
-       case packetTypeSignature:
-               p = new(Signature)
-       case packetTypeSymmetricKeyEncrypted:
-               p = new(SymmetricKeyEncrypted)
-       case packetTypeOnePassSignature:
-               p = new(OnePassSignature)
-       case packetTypePrivateKey, packetTypePrivateSubkey:
-               pk := new(PrivateKey)
-               if tag == packetTypePrivateSubkey {
-                       pk.IsSubkey = true
-               }
-               p = pk
-       case packetTypePublicKey, packetTypePublicSubkey:
-               pk := new(PublicKey)
-               if tag == packetTypePublicSubkey {
-                       pk.IsSubkey = true
-               }
-               p = pk
-       case packetTypeCompressed:
-               p = new(Compressed)
-       case packetTypeSymmetricallyEncrypted:
-               p = new(SymmetricallyEncrypted)
-       case packetTypeLiteralData:
-               p = new(LiteralData)
-       case packetTypeUserId:
-               p = new(UserId)
-       case packetTypeSymmetricallyEncryptedMDC:
-               se := new(SymmetricallyEncrypted)
-               se.MDC = true
-               p = se
-       default:
-               err = errors.UnknownPacketTypeError(tag)
-       }
-       if p != nil {
-               err = p.parse(contents)
-       }
-       if err != nil {
-               consumeAll(contents)
-       }
-       return
-}
-
-// SignatureType represents the different semantic meanings of an OpenPGP
-// signature. See RFC 4880, section 5.2.1.
-type SignatureType uint8
-
-const (
-       SigTypeBinary        SignatureType = 0
-       SigTypeText                        = 1
-       SigTypeGenericCert                 = 0x10
-       SigTypePersonaCert                 = 0x11
-       SigTypeCasualCert                  = 0x12
-       SigTypePositiveCert                = 0x13
-       SigTypeSubkeyBinding               = 0x18
-)
-
-// PublicKeyAlgorithm represents the different public key system specified for
-// OpenPGP. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
-type PublicKeyAlgorithm uint8
-
-const (
-       PubKeyAlgoRSA            PublicKeyAlgorithm = 1
-       PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
-       PubKeyAlgoRSASignOnly    PublicKeyAlgorithm = 3
-       PubKeyAlgoElGamal        PublicKeyAlgorithm = 16
-       PubKeyAlgoDSA            PublicKeyAlgorithm = 17
-)
-
-// CanEncrypt returns true if it's possible to encrypt a message to a public
-// key of the given type.
-func (pka PublicKeyAlgorithm) CanEncrypt() bool {
-       switch pka {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
-               return true
-       }
-       return false
-}
-
-// CanSign returns true if it's possible for a public key of the given type to
-// sign a message.
-func (pka PublicKeyAlgorithm) CanSign() bool {
-       switch pka {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
-               return true
-       }
-       return false
-}
-
-// CipherFunction represents the different block ciphers specified for OpenPGP. See
-// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
-type CipherFunction uint8
-
-const (
-       CipherCAST5  CipherFunction = 3
-       CipherAES128 CipherFunction = 7
-       CipherAES192 CipherFunction = 8
-       CipherAES256 CipherFunction = 9
-)
-
-// KeySize returns the key size, in bytes, of cipher.
-func (cipher CipherFunction) KeySize() int {
-       switch cipher {
-       case CipherCAST5:
-               return cast5.KeySize
-       case CipherAES128:
-               return 16
-       case CipherAES192:
-               return 24
-       case CipherAES256:
-               return 32
-       }
-       return 0
-}
-
-// blockSize returns the block size, in bytes, of cipher.
-func (cipher CipherFunction) blockSize() int {
-       switch cipher {
-       case CipherCAST5:
-               return 8
-       case CipherAES128, CipherAES192, CipherAES256:
-               return 16
-       }
-       return 0
-}
-
-// new returns a fresh instance of the given cipher.
-func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
-       switch cipher {
-       case CipherCAST5:
-               block, _ = cast5.NewCipher(key)
-       case CipherAES128, CipherAES192, CipherAES256:
-               block, _ = aes.NewCipher(key)
-       }
-       return
-}
-
-// readMPI reads a big integer from r. The bit length returned is the bit
-// length that was specified in r. This is preserved so that the integer can be
-// reserialized exactly.
-func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
-       var buf [2]byte
-       _, err = readFull(r, buf[0:])
-       if err != nil {
-               return
-       }
-       bitLength = uint16(buf[0])<<8 | uint16(buf[1])
-       numBytes := (int(bitLength) + 7) / 8
-       mpi = make([]byte, numBytes)
-       _, err = readFull(r, mpi)
-       return
-}
-
-// mpiLength returns the length of the given *big.Int when serialized as an
-// MPI.
-func mpiLength(n *big.Int) (mpiLengthInBytes int) {
-       mpiLengthInBytes = 2 /* MPI length */
-       mpiLengthInBytes += (n.BitLen() + 7) / 8
-       return
-}
-
-// writeMPI serializes a big integer to w.
-func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
-       _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
-       if err == nil {
-               _, err = w.Write(mpiBytes)
-       }
-       return
-}
-
-// writeBig serializes a *big.Int to w.
-func writeBig(w io.Writer, i *big.Int) error {
-       return writeMPI(w, uint16(i.BitLen()), i.Bytes())
-}
diff --git a/libgo/go/crypto/openpgp/packet/packet_test.go b/libgo/go/crypto/openpgp/packet/packet_test.go
deleted file mode 100644 (file)
index e4b8691..0000000
+++ /dev/null
@@ -1,255 +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 packet
-
-import (
-       "bytes"
-       "crypto/openpgp/errors"
-       "encoding/hex"
-       "fmt"
-       "io"
-       "io/ioutil"
-       "testing"
-)
-
-func TestReadFull(t *testing.T) {
-       var out [4]byte
-
-       b := bytes.NewBufferString("foo")
-       n, err := readFull(b, out[:3])
-       if n != 3 || err != nil {
-               t.Errorf("full read failed n:%d err:%s", n, err)
-       }
-
-       b = bytes.NewBufferString("foo")
-       n, err = readFull(b, out[:4])
-       if n != 3 || err != io.ErrUnexpectedEOF {
-               t.Errorf("partial read failed n:%d err:%s", n, err)
-       }
-
-       b = bytes.NewBuffer(nil)
-       n, err = readFull(b, out[:3])
-       if n != 0 || err != io.ErrUnexpectedEOF {
-               t.Errorf("empty read failed n:%d err:%s", n, err)
-       }
-}
-
-func readerFromHex(s string) io.Reader {
-       data, err := hex.DecodeString(s)
-       if err != nil {
-               panic("readerFromHex: bad input")
-       }
-       return bytes.NewBuffer(data)
-}
-
-var readLengthTests = []struct {
-       hexInput  string
-       length    int64
-       isPartial bool
-       err       error
-}{
-       {"", 0, false, io.ErrUnexpectedEOF},
-       {"1f", 31, false, nil},
-       {"c0", 0, false, io.ErrUnexpectedEOF},
-       {"c101", 256 + 1 + 192, false, nil},
-       {"e0", 1, true, nil},
-       {"e1", 2, true, nil},
-       {"e2", 4, true, nil},
-       {"ff", 0, false, io.ErrUnexpectedEOF},
-       {"ff00", 0, false, io.ErrUnexpectedEOF},
-       {"ff0000", 0, false, io.ErrUnexpectedEOF},
-       {"ff000000", 0, false, io.ErrUnexpectedEOF},
-       {"ff00000000", 0, false, nil},
-       {"ff01020304", 16909060, false, nil},
-}
-
-func TestReadLength(t *testing.T) {
-       for i, test := range readLengthTests {
-               length, isPartial, err := readLength(readerFromHex(test.hexInput))
-               if test.err != nil {
-                       if err != test.err {
-                               t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
-                       }
-                       continue
-               }
-               if err != nil {
-                       t.Errorf("%d: unexpected error: %s", i, err)
-                       continue
-               }
-               if length != test.length || isPartial != test.isPartial {
-                       t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
-               }
-       }
-}
-
-var partialLengthReaderTests = []struct {
-       hexInput  string
-       err       error
-       hexOutput string
-}{
-       {"e0", io.ErrUnexpectedEOF, ""},
-       {"e001", io.ErrUnexpectedEOF, ""},
-       {"e0010102", nil, "0102"},
-       {"ff00000000", nil, ""},
-       {"e10102e1030400", nil, "01020304"},
-       {"e101", io.ErrUnexpectedEOF, ""},
-}
-
-func TestPartialLengthReader(t *testing.T) {
-       for i, test := range partialLengthReaderTests {
-               r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
-               out, err := ioutil.ReadAll(r)
-               if test.err != nil {
-                       if err != test.err {
-                               t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
-                       }
-                       continue
-               }
-               if err != nil {
-                       t.Errorf("%d: unexpected error: %s", i, err)
-                       continue
-               }
-
-               got := fmt.Sprintf("%x", out)
-               if got != test.hexOutput {
-                       t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
-               }
-       }
-}
-
-var readHeaderTests = []struct {
-       hexInput        string
-       structuralError bool
-       unexpectedEOF   bool
-       tag             int
-       length          int64
-       hexOutput       string
-}{
-       {"", false, false, 0, 0, ""},
-       {"7f", true, false, 0, 0, ""},
-
-       // Old format headers
-       {"80", false, true, 0, 0, ""},
-       {"8001", false, true, 0, 1, ""},
-       {"800102", false, false, 0, 1, "02"},
-       {"81000102", false, false, 0, 1, "02"},
-       {"820000000102", false, false, 0, 1, "02"},
-       {"860000000102", false, false, 1, 1, "02"},
-       {"83010203", false, false, 0, -1, "010203"},
-
-       // New format headers
-       {"c0", false, true, 0, 0, ""},
-       {"c000", false, false, 0, 0, ""},
-       {"c00102", false, false, 0, 1, "02"},
-       {"c0020203", false, false, 0, 2, "0203"},
-       {"c00202", false, true, 0, 2, ""},
-       {"c3020203", false, false, 3, 2, "0203"},
-}
-
-func TestReadHeader(t *testing.T) {
-       for i, test := range readHeaderTests {
-               tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
-               if test.structuralError {
-                       if _, ok := err.(errors.StructuralError); ok {
-                               continue
-                       }
-                       t.Errorf("%d: expected StructuralError, got:%s", i, err)
-                       continue
-               }
-               if err != nil {
-                       if len(test.hexInput) == 0 && err == io.EOF {
-                               continue
-                       }
-                       if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
-                               t.Errorf("%d: unexpected error from readHeader: %s", i, err)
-                       }
-                       continue
-               }
-               if int(tag) != test.tag || length != test.length {
-                       t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
-                       continue
-               }
-
-               body, err := ioutil.ReadAll(contents)
-               if err != nil {
-                       if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
-                               t.Errorf("%d: unexpected error from contents: %s", i, err)
-                       }
-                       continue
-               }
-               if test.unexpectedEOF {
-                       t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
-                       continue
-               }
-               got := fmt.Sprintf("%x", body)
-               if got != test.hexOutput {
-                       t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
-               }
-       }
-}
-
-func TestSerializeHeader(t *testing.T) {
-       tag := packetTypePublicKey
-       lengths := []int{0, 1, 2, 64, 192, 193, 8000, 8384, 8385, 10000}
-
-       for _, length := range lengths {
-               buf := bytes.NewBuffer(nil)
-               serializeHeader(buf, tag, length)
-               tag2, length2, _, err := readHeader(buf)
-               if err != nil {
-                       t.Errorf("length %d, err: %s", length, err)
-               }
-               if tag2 != tag {
-                       t.Errorf("length %d, tag incorrect (got %d, want %d)", length, tag2, tag)
-               }
-               if int(length2) != length {
-                       t.Errorf("length %d, length incorrect (got %d)", length, length2)
-               }
-       }
-}
-
-func TestPartialLengths(t *testing.T) {
-       buf := bytes.NewBuffer(nil)
-       w := new(partialLengthWriter)
-       w.w = noOpCloser{buf}
-
-       const maxChunkSize = 64
-
-       var b [maxChunkSize]byte
-       var n uint8
-       for l := 1; l <= maxChunkSize; l++ {
-               for i := 0; i < l; i++ {
-                       b[i] = n
-                       n++
-               }
-               m, err := w.Write(b[:l])
-               if m != l {
-                       t.Errorf("short write got: %d want: %d", m, l)
-               }
-               if err != nil {
-                       t.Errorf("error from write: %s", err)
-               }
-       }
-       w.Close()
-
-       want := (maxChunkSize * (maxChunkSize + 1)) / 2
-       copyBuf := bytes.NewBuffer(nil)
-       r := &partialLengthReader{buf, 0, true}
-       m, err := io.Copy(copyBuf, r)
-       if m != int64(want) {
-               t.Errorf("short copy got: %d want: %d", m, want)
-       }
-       if err != nil {
-               t.Errorf("error from copy: %s", err)
-       }
-
-       copyBytes := copyBuf.Bytes()
-       for i := 0; i < want; i++ {
-               if copyBytes[i] != uint8(i) {
-                       t.Errorf("bad pattern in copy at %d", i)
-                       break
-               }
-       }
-}
diff --git a/libgo/go/crypto/openpgp/packet/private_key.go b/libgo/go/crypto/openpgp/packet/private_key.go
deleted file mode 100644 (file)
index 5a90d06..0000000
+++ /dev/null
@@ -1,310 +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 packet
-
-import (
-       "bytes"
-       "crypto/cipher"
-       "crypto/dsa"
-       "crypto/openpgp/elgamal"
-       "crypto/openpgp/errors"
-       "crypto/openpgp/s2k"
-       "crypto/rsa"
-       "crypto/sha1"
-       "io"
-       "io/ioutil"
-       "math/big"
-       "strconv"
-       "time"
-)
-
-// PrivateKey represents a possibly encrypted private key. See RFC 4880,
-// section 5.5.3.
-type PrivateKey struct {
-       PublicKey
-       Encrypted     bool // if true then the private key is unavailable until Decrypt has been called.
-       encryptedData []byte
-       cipher        CipherFunction
-       s2k           func(out, in []byte)
-       PrivateKey    interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
-       sha1Checksum  bool
-       iv            []byte
-}
-
-func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
-       pk := new(PrivateKey)
-       pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
-       pk.PrivateKey = priv
-       return pk
-}
-
-func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
-       pk := new(PrivateKey)
-       pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
-       pk.PrivateKey = priv
-       return pk
-}
-
-func (pk *PrivateKey) parse(r io.Reader) (err error) {
-       err = (&pk.PublicKey).parse(r)
-       if err != nil {
-               return
-       }
-       var buf [1]byte
-       _, err = readFull(r, buf[:])
-       if err != nil {
-               return
-       }
-
-       s2kType := buf[0]
-
-       switch s2kType {
-       case 0:
-               pk.s2k = nil
-               pk.Encrypted = false
-       case 254, 255:
-               _, err = readFull(r, buf[:])
-               if err != nil {
-                       return
-               }
-               pk.cipher = CipherFunction(buf[0])
-               pk.Encrypted = true
-               pk.s2k, err = s2k.Parse(r)
-               if err != nil {
-                       return
-               }
-               if s2kType == 254 {
-                       pk.sha1Checksum = true
-               }
-       default:
-               return errors.UnsupportedError("deprecated s2k function in private key")
-       }
-
-       if pk.Encrypted {
-               blockSize := pk.cipher.blockSize()
-               if blockSize == 0 {
-                       return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
-               }
-               pk.iv = make([]byte, blockSize)
-               _, err = readFull(r, pk.iv)
-               if err != nil {
-                       return
-               }
-       }
-
-       pk.encryptedData, err = ioutil.ReadAll(r)
-       if err != nil {
-               return
-       }
-
-       if !pk.Encrypted {
-               return pk.parsePrivateKey(pk.encryptedData)
-       }
-
-       return
-}
-
-func mod64kHash(d []byte) uint16 {
-       var h uint16
-       for _, b := range d {
-               h += uint16(b)
-       }
-       return h
-}
-
-func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
-       // TODO(agl): support encrypted private keys
-       buf := bytes.NewBuffer(nil)
-       err = pk.PublicKey.serializeWithoutHeaders(buf)
-       if err != nil {
-               return
-       }
-       buf.WriteByte(0 /* no encryption */ )
-
-       privateKeyBuf := bytes.NewBuffer(nil)
-
-       switch priv := pk.PrivateKey.(type) {
-       case *rsa.PrivateKey:
-               err = serializeRSAPrivateKey(privateKeyBuf, priv)
-       case *dsa.PrivateKey:
-               err = serializeDSAPrivateKey(privateKeyBuf, priv)
-       default:
-               err = errors.InvalidArgumentError("unknown private key type")
-       }
-       if err != nil {
-               return
-       }
-
-       ptype := packetTypePrivateKey
-       contents := buf.Bytes()
-       privateKeyBytes := privateKeyBuf.Bytes()
-       if pk.IsSubkey {
-               ptype = packetTypePrivateSubkey
-       }
-       err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
-       if err != nil {
-               return
-       }
-       _, err = w.Write(contents)
-       if err != nil {
-               return
-       }
-       _, err = w.Write(privateKeyBytes)
-       if err != nil {
-               return
-       }
-
-       checksum := mod64kHash(privateKeyBytes)
-       var checksumBytes [2]byte
-       checksumBytes[0] = byte(checksum >> 8)
-       checksumBytes[1] = byte(checksum)
-       _, err = w.Write(checksumBytes[:])
-
-       return
-}
-
-func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
-       err := writeBig(w, priv.D)
-       if err != nil {
-               return err
-       }
-       err = writeBig(w, priv.Primes[1])
-       if err != nil {
-               return err
-       }
-       err = writeBig(w, priv.Primes[0])
-       if err != nil {
-               return err
-       }
-       return writeBig(w, priv.Precomputed.Qinv)
-}
-
-func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
-       return writeBig(w, priv.X)
-}
-
-// Decrypt decrypts an encrypted private key using a passphrase.
-func (pk *PrivateKey) Decrypt(passphrase []byte) error {
-       if !pk.Encrypted {
-               return nil
-       }
-
-       key := make([]byte, pk.cipher.KeySize())
-       pk.s2k(key, passphrase)
-       block := pk.cipher.new(key)
-       cfb := cipher.NewCFBDecrypter(block, pk.iv)
-
-       data := pk.encryptedData
-       cfb.XORKeyStream(data, data)
-
-       if pk.sha1Checksum {
-               if len(data) < sha1.Size {
-                       return errors.StructuralError("truncated private key data")
-               }
-               h := sha1.New()
-               h.Write(data[:len(data)-sha1.Size])
-               sum := h.Sum(nil)
-               if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
-                       return errors.StructuralError("private key checksum failure")
-               }
-               data = data[:len(data)-sha1.Size]
-       } else {
-               if len(data) < 2 {
-                       return errors.StructuralError("truncated private key data")
-               }
-               var sum uint16
-               for i := 0; i < len(data)-2; i++ {
-                       sum += uint16(data[i])
-               }
-               if data[len(data)-2] != uint8(sum>>8) ||
-                       data[len(data)-1] != uint8(sum) {
-                       return errors.StructuralError("private key checksum failure")
-               }
-               data = data[:len(data)-2]
-       }
-
-       return pk.parsePrivateKey(data)
-}
-
-func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
-       switch pk.PublicKey.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
-               return pk.parseRSAPrivateKey(data)
-       case PubKeyAlgoDSA:
-               return pk.parseDSAPrivateKey(data)
-       case PubKeyAlgoElGamal:
-               return pk.parseElGamalPrivateKey(data)
-       }
-       panic("impossible")
-}
-
-func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
-       rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
-       rsaPriv := new(rsa.PrivateKey)
-       rsaPriv.PublicKey = *rsaPub
-
-       buf := bytes.NewBuffer(data)
-       d, _, err := readMPI(buf)
-       if err != nil {
-               return
-       }
-       p, _, err := readMPI(buf)
-       if err != nil {
-               return
-       }
-       q, _, err := readMPI(buf)
-       if err != nil {
-               return
-       }
-
-       rsaPriv.D = new(big.Int).SetBytes(d)
-       rsaPriv.Primes = make([]*big.Int, 2)
-       rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
-       rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
-       rsaPriv.Precompute()
-       pk.PrivateKey = rsaPriv
-       pk.Encrypted = false
-       pk.encryptedData = nil
-
-       return nil
-}
-
-func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
-       dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
-       dsaPriv := new(dsa.PrivateKey)
-       dsaPriv.PublicKey = *dsaPub
-
-       buf := bytes.NewBuffer(data)
-       x, _, err := readMPI(buf)
-       if err != nil {
-               return
-       }
-
-       dsaPriv.X = new(big.Int).SetBytes(x)
-       pk.PrivateKey = dsaPriv
-       pk.Encrypted = false
-       pk.encryptedData = nil
-
-       return nil
-}
-
-func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
-       pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
-       priv := new(elgamal.PrivateKey)
-       priv.PublicKey = *pub
-
-       buf := bytes.NewBuffer(data)
-       x, _, err := readMPI(buf)
-       if err != nil {
-               return
-       }
-
-       priv.X = new(big.Int).SetBytes(x)
-       pk.PrivateKey = priv
-       pk.Encrypted = false
-       pk.encryptedData = nil
-
-       return nil
-}
diff --git a/libgo/go/crypto/openpgp/packet/private_key_test.go b/libgo/go/crypto/openpgp/packet/private_key_test.go
deleted file mode 100644 (file)
index 35d8951..0000000
+++ /dev/null
@@ -1,58 +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 packet
-
-import (
-       "testing"
-       "time"
-)
-
-var privateKeyTests = []struct {
-       privateKeyHex string
-       creationTime  time.Time
-}{
-       {
-               privKeyRSAHex,
-               time.Unix(0x4cc349a8, 0),
-       },
-       {
-               privKeyElGamalHex,
-               time.Unix(0x4df9ee1a, 0),
-       },
-}
-
-func TestPrivateKeyRead(t *testing.T) {
-       for i, test := range privateKeyTests {
-               packet, err := Read(readerFromHex(test.privateKeyHex))
-               if err != nil {
-                       t.Errorf("#%d: failed to parse: %s", i, err)
-                       continue
-               }
-
-               privKey := packet.(*PrivateKey)
-
-               if !privKey.Encrypted {
-                       t.Errorf("#%d: private key isn't encrypted", i)
-                       continue
-               }
-
-               err = privKey.Decrypt([]byte("testing"))
-               if err != nil {
-                       t.Errorf("#%d: failed to decrypt: %s", i, err)
-                       continue
-               }
-
-               if !privKey.CreationTime.Equal(test.creationTime) || privKey.Encrypted {
-                       t.Errorf("#%d: bad result, got: %#v", i, privKey)
-               }
-       }
-}
-
-// Generated with `gpg --export-secret-keys "Test Key 2"`
-const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
-
-// Generated by `gpg --export-secret-keys` followed by a manual extraction of
-// the ElGamal subkey from the packets.
-const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
diff --git a/libgo/go/crypto/openpgp/packet/public_key.go b/libgo/go/crypto/openpgp/packet/public_key.go
deleted file mode 100644 (file)
index ba178b5..0000000
+++ /dev/null
@@ -1,414 +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 packet
-
-import (
-       "crypto/dsa"
-       "crypto/openpgp/elgamal"
-       "crypto/openpgp/errors"
-       "crypto/rsa"
-       "crypto/sha1"
-       "encoding/binary"
-       "fmt"
-       "hash"
-       "io"
-       "math/big"
-       "strconv"
-       "time"
-)
-
-// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
-type PublicKey struct {
-       CreationTime time.Time
-       PubKeyAlgo   PublicKeyAlgorithm
-       PublicKey    interface{} // Either a *rsa.PublicKey or *dsa.PublicKey
-       Fingerprint  [20]byte
-       KeyId        uint64
-       IsSubkey     bool
-
-       n, e, p, q, g, y parsedMPI
-}
-
-func fromBig(n *big.Int) parsedMPI {
-       return parsedMPI{
-               bytes:     n.Bytes(),
-               bitLength: uint16(n.BitLen()),
-       }
-}
-
-// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
-func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
-       pk := &PublicKey{
-               CreationTime: creationTime,
-               PubKeyAlgo:   PubKeyAlgoRSA,
-               PublicKey:    pub,
-               n:            fromBig(pub.N),
-               e:            fromBig(big.NewInt(int64(pub.E))),
-       }
-
-       pk.setFingerPrintAndKeyId()
-       return pk
-}
-
-// NewDSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
-func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
-       pk := &PublicKey{
-               CreationTime: creationTime,
-               PubKeyAlgo:   PubKeyAlgoDSA,
-               PublicKey:    pub,
-               p:            fromBig(pub.P),
-               q:            fromBig(pub.Q),
-               g:            fromBig(pub.G),
-               y:            fromBig(pub.Y),
-       }
-
-       pk.setFingerPrintAndKeyId()
-       return pk
-}
-
-func (pk *PublicKey) parse(r io.Reader) (err error) {
-       // RFC 4880, section 5.5.2
-       var buf [6]byte
-       _, err = readFull(r, buf[:])
-       if err != nil {
-               return
-       }
-       if buf[0] != 4 {
-               return errors.UnsupportedError("public key version")
-       }
-       pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
-       pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
-       switch pk.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-               err = pk.parseRSA(r)
-       case PubKeyAlgoDSA:
-               err = pk.parseDSA(r)
-       case PubKeyAlgoElGamal:
-               err = pk.parseElGamal(r)
-       default:
-               err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
-       }
-       if err != nil {
-               return
-       }
-
-       pk.setFingerPrintAndKeyId()
-       return
-}
-
-func (pk *PublicKey) setFingerPrintAndKeyId() {
-       // RFC 4880, section 12.2
-       fingerPrint := sha1.New()
-       pk.SerializeSignaturePrefix(fingerPrint)
-       pk.serializeWithoutHeaders(fingerPrint)
-       copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
-       pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
-}
-
-// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
-// section 5.5.2.
-func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
-       pk.n.bytes, pk.n.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-       pk.e.bytes, pk.e.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-
-       if len(pk.e.bytes) > 3 {
-               err = errors.UnsupportedError("large public exponent")
-               return
-       }
-       rsa := &rsa.PublicKey{
-               N: new(big.Int).SetBytes(pk.n.bytes),
-               E: 0,
-       }
-       for i := 0; i < len(pk.e.bytes); i++ {
-               rsa.E <<= 8
-               rsa.E |= int(pk.e.bytes[i])
-       }
-       pk.PublicKey = rsa
-       return
-}
-
-// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
-// section 5.5.2.
-func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
-       pk.p.bytes, pk.p.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-       pk.q.bytes, pk.q.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-       pk.g.bytes, pk.g.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-       pk.y.bytes, pk.y.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-
-       dsa := new(dsa.PublicKey)
-       dsa.P = new(big.Int).SetBytes(pk.p.bytes)
-       dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
-       dsa.G = new(big.Int).SetBytes(pk.g.bytes)
-       dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
-       pk.PublicKey = dsa
-       return
-}
-
-// parseElGamal parses ElGamal public key material from the given Reader. See
-// RFC 4880, section 5.5.2.
-func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
-       pk.p.bytes, pk.p.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-       pk.g.bytes, pk.g.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-       pk.y.bytes, pk.y.bitLength, err = readMPI(r)
-       if err != nil {
-               return
-       }
-
-       elgamal := new(elgamal.PublicKey)
-       elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
-       elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
-       elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
-       pk.PublicKey = elgamal
-       return
-}
-
-// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
-// The prefix is used when calculating a signature over this public key. See
-// RFC 4880, section 5.2.4.
-func (pk *PublicKey) SerializeSignaturePrefix(h hash.Hash) {
-       var pLength uint16
-       switch pk.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-               pLength += 2 + uint16(len(pk.n.bytes))
-               pLength += 2 + uint16(len(pk.e.bytes))
-       case PubKeyAlgoDSA:
-               pLength += 2 + uint16(len(pk.p.bytes))
-               pLength += 2 + uint16(len(pk.q.bytes))
-               pLength += 2 + uint16(len(pk.g.bytes))
-               pLength += 2 + uint16(len(pk.y.bytes))
-       case PubKeyAlgoElGamal:
-               pLength += 2 + uint16(len(pk.p.bytes))
-               pLength += 2 + uint16(len(pk.g.bytes))
-               pLength += 2 + uint16(len(pk.y.bytes))
-       default:
-               panic("unknown public key algorithm")
-       }
-       pLength += 6
-       h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
-       return
-}
-
-func (pk *PublicKey) Serialize(w io.Writer) (err error) {
-       length := 6 // 6 byte header
-
-       switch pk.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-               length += 2 + len(pk.n.bytes)
-               length += 2 + len(pk.e.bytes)
-       case PubKeyAlgoDSA:
-               length += 2 + len(pk.p.bytes)
-               length += 2 + len(pk.q.bytes)
-               length += 2 + len(pk.g.bytes)
-               length += 2 + len(pk.y.bytes)
-       case PubKeyAlgoElGamal:
-               length += 2 + len(pk.p.bytes)
-               length += 2 + len(pk.g.bytes)
-               length += 2 + len(pk.y.bytes)
-       default:
-               panic("unknown public key algorithm")
-       }
-
-       packetType := packetTypePublicKey
-       if pk.IsSubkey {
-               packetType = packetTypePublicSubkey
-       }
-       err = serializeHeader(w, packetType, length)
-       if err != nil {
-               return
-       }
-       return pk.serializeWithoutHeaders(w)
-}
-
-// serializeWithoutHeaders marshals the PublicKey to w in the form of an
-// OpenPGP public key packet, not including the packet header.
-func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
-       var buf [6]byte
-       buf[0] = 4
-       t := uint32(pk.CreationTime.Unix())
-       buf[1] = byte(t >> 24)
-       buf[2] = byte(t >> 16)
-       buf[3] = byte(t >> 8)
-       buf[4] = byte(t)
-       buf[5] = byte(pk.PubKeyAlgo)
-
-       _, err = w.Write(buf[:])
-       if err != nil {
-               return
-       }
-
-       switch pk.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
-               return writeMPIs(w, pk.n, pk.e)
-       case PubKeyAlgoDSA:
-               return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
-       case PubKeyAlgoElGamal:
-               return writeMPIs(w, pk.p, pk.g, pk.y)
-       }
-       return errors.InvalidArgumentError("bad public-key algorithm")
-}
-
-// CanSign returns true iff this public key can generate signatures
-func (pk *PublicKey) CanSign() bool {
-       return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
-}
-
-// VerifySignature returns nil iff sig is a valid signature, made by this
-// public key, of the data hashed into signed. signed is mutated by this call.
-func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
-       if !pk.CanSign() {
-               return errors.InvalidArgumentError("public key cannot generate signatures")
-       }
-
-       signed.Write(sig.HashSuffix)
-       hashBytes := signed.Sum(nil)
-
-       if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
-               return errors.SignatureError("hash tag doesn't match")
-       }
-
-       if pk.PubKeyAlgo != sig.PubKeyAlgo {
-               return errors.InvalidArgumentError("public key and signature use different algorithms")
-       }
-
-       switch pk.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-               rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
-               err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
-               if err != nil {
-                       return errors.SignatureError("RSA verification failure")
-               }
-               return nil
-       case PubKeyAlgoDSA:
-               dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
-               // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
-               subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
-               if len(hashBytes) > subgroupSize {
-                       hashBytes = hashBytes[:subgroupSize]
-               }
-               if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
-                       return errors.SignatureError("DSA verification failure")
-               }
-               return nil
-       default:
-               panic("shouldn't happen")
-       }
-       panic("unreachable")
-}
-
-// keySignatureHash returns a Hash of the message that needs to be signed for
-// pk to assert a subkey relationship to signed.
-func keySignatureHash(pk, signed *PublicKey, sig *Signature) (h hash.Hash, err error) {
-       h = sig.Hash.New()
-       if h == nil {
-               return nil, errors.UnsupportedError("hash function")
-       }
-
-       // RFC 4880, section 5.2.4
-       pk.SerializeSignaturePrefix(h)
-       pk.serializeWithoutHeaders(h)
-       signed.SerializeSignaturePrefix(h)
-       signed.serializeWithoutHeaders(h)
-       return
-}
-
-// VerifyKeySignature returns nil iff sig is a valid signature, made by this
-// public key, of signed.
-func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err error) {
-       h, err := keySignatureHash(pk, signed, sig)
-       if err != nil {
-               return err
-       }
-       return pk.VerifySignature(h, sig)
-}
-
-// userIdSignatureHash returns a Hash of the message that needs to be signed
-// to assert that pk is a valid key for id.
-func userIdSignatureHash(id string, pk *PublicKey, sig *Signature) (h hash.Hash, err error) {
-       h = sig.Hash.New()
-       if h == nil {
-               return nil, errors.UnsupportedError("hash function")
-       }
-
-       // RFC 4880, section 5.2.4
-       pk.SerializeSignaturePrefix(h)
-       pk.serializeWithoutHeaders(h)
-
-       var buf [5]byte
-       buf[0] = 0xb4
-       buf[1] = byte(len(id) >> 24)
-       buf[2] = byte(len(id) >> 16)
-       buf[3] = byte(len(id) >> 8)
-       buf[4] = byte(len(id))
-       h.Write(buf[:])
-       h.Write([]byte(id))
-
-       return
-}
-
-// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
-// public key, of id.
-func (pk *PublicKey) VerifyUserIdSignature(id string, sig *Signature) (err error) {
-       h, err := userIdSignatureHash(id, pk, sig)
-       if err != nil {
-               return err
-       }
-       return pk.VerifySignature(h, sig)
-}
-
-// KeyIdString returns the public key's fingerprint in capital hex
-// (e.g. "6C7EE1B8621CC013").
-func (pk *PublicKey) KeyIdString() string {
-       return fmt.Sprintf("%X", pk.Fingerprint[12:20])
-}
-
-// KeyIdShortString returns the short form of public key's fingerprint
-// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
-func (pk *PublicKey) KeyIdShortString() string {
-       return fmt.Sprintf("%X", pk.Fingerprint[16:20])
-}
-
-// A parsedMPI is used to store the contents of a big integer, along with the
-// bit length that was specified in the original input. This allows the MPI to
-// be reserialized exactly.
-type parsedMPI struct {
-       bytes     []byte
-       bitLength uint16
-}
-
-// writeMPIs is a utility function for serializing several big integers to the
-// given Writer.
-func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
-       for _, mpi := range mpis {
-               err = writeMPI(w, mpi.bitLength, mpi.bytes)
-               if err != nil {
-                       return
-               }
-       }
-       return
-}
diff --git a/libgo/go/crypto/openpgp/packet/public_key_test.go b/libgo/go/crypto/openpgp/packet/public_key_test.go
deleted file mode 100644 (file)
index 72f459f..0000000
+++ /dev/null
@@ -1,99 +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 packet
-
-import (
-       "bytes"
-       "encoding/hex"
-       "testing"
-       "time"
-)
-
-var pubKeyTests = []struct {
-       hexData        string
-       hexFingerprint string
-       creationTime   time.Time
-       pubKeyAlgo     PublicKeyAlgorithm
-       keyId          uint64
-       keyIdString    string
-       keyIdShort     string
-}{
-       {rsaPkDataHex, rsaFingerprintHex, time.Unix(0x4d3c5c10, 0), PubKeyAlgoRSA, 0xa34d7e18c20c31bb, "A34D7E18C20C31BB", "C20C31BB"},
-       {dsaPkDataHex, dsaFingerprintHex, time.Unix(0x4d432f89, 0), PubKeyAlgoDSA, 0x8e8fbe54062f19ed, "8E8FBE54062F19ED", "062F19ED"},
-}
-
-func TestPublicKeyRead(t *testing.T) {
-       for i, test := range pubKeyTests {
-               packet, err := Read(readerFromHex(test.hexData))
-               if err != nil {
-                       t.Errorf("#%d: Read error: %s", i, err)
-                       continue
-               }
-               pk, ok := packet.(*PublicKey)
-               if !ok {
-                       t.Errorf("#%d: failed to parse, got: %#v", i, packet)
-                       continue
-               }
-               if pk.PubKeyAlgo != test.pubKeyAlgo {
-                       t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
-               }
-               if !pk.CreationTime.Equal(test.creationTime) {
-                       t.Errorf("#%d: bad creation time got:%v want:%v", i, pk.CreationTime, test.creationTime)
-               }
-               expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
-               if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
-                       t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
-               }
-               if pk.KeyId != test.keyId {
-                       t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
-               }
-               if g, e := pk.KeyIdString(), test.keyIdString; g != e {
-                       t.Errorf("#%d: bad KeyIdString got:%q want:%q", i, g, e)
-               }
-               if g, e := pk.KeyIdShortString(), test.keyIdShort; g != e {
-                       t.Errorf("#%d: bad KeyIdShortString got:%q want:%q", i, g, e)
-               }
-       }
-}
-
-func TestPublicKeySerialize(t *testing.T) {
-       for i, test := range pubKeyTests {
-               packet, err := Read(readerFromHex(test.hexData))
-               if err != nil {
-                       t.Errorf("#%d: Read error: %s", i, err)
-                       continue
-               }
-               pk, ok := packet.(*PublicKey)
-               if !ok {
-                       t.Errorf("#%d: failed to parse, got: %#v", i, packet)
-                       continue
-               }
-               serializeBuf := bytes.NewBuffer(nil)
-               err = pk.Serialize(serializeBuf)
-               if err != nil {
-                       t.Errorf("#%d: failed to serialize: %s", i, err)
-                       continue
-               }
-
-               packet, err = Read(serializeBuf)
-               if err != nil {
-                       t.Errorf("#%d: Read error (from serialized data): %s", i, err)
-                       continue
-               }
-               pk, ok = packet.(*PublicKey)
-               if !ok {
-                       t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
-                       continue
-               }
-       }
-}
-
-const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
-
-const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
-
-const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
-
-const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
diff --git a/libgo/go/crypto/openpgp/packet/reader.go b/libgo/go/crypto/openpgp/packet/reader.go
deleted file mode 100644 (file)
index 1a3e8e2..0000000
+++ /dev/null
@@ -1,62 +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 packet
-
-import (
-       "crypto/openpgp/errors"
-       "io"
-)
-
-// Reader reads packets from an io.Reader and allows packets to be 'unread' so
-// that they result from the next call to Next.
-type Reader struct {
-       q       []Packet
-       readers []io.Reader
-}
-
-// Next returns the most recently unread Packet, or reads another packet from
-// the top-most io.Reader. Unknown packet types are skipped.
-func (r *Reader) Next() (p Packet, err error) {
-       if len(r.q) > 0 {
-               p = r.q[len(r.q)-1]
-               r.q = r.q[:len(r.q)-1]
-               return
-       }
-
-       for len(r.readers) > 0 {
-               p, err = Read(r.readers[len(r.readers)-1])
-               if err == nil {
-                       return
-               }
-               if err == io.EOF {
-                       r.readers = r.readers[:len(r.readers)-1]
-                       continue
-               }
-               if _, ok := err.(errors.UnknownPacketTypeError); !ok {
-                       return nil, err
-               }
-       }
-
-       return nil, io.EOF
-}
-
-// Push causes the Reader to start reading from a new io.Reader. When an EOF
-// error is seen from the new io.Reader, it is popped and the Reader continues
-// to read from the next most recent io.Reader.
-func (r *Reader) Push(reader io.Reader) {
-       r.readers = append(r.readers, reader)
-}
-
-// Unread causes the given Packet to be returned from the next call to Next.
-func (r *Reader) Unread(p Packet) {
-       r.q = append(r.q, p)
-}
-
-func NewReader(r io.Reader) *Reader {
-       return &Reader{
-               q:       nil,
-               readers: []io.Reader{r},
-       }
-}
diff --git a/libgo/go/crypto/openpgp/packet/signature.go b/libgo/go/crypto/openpgp/packet/signature.go
deleted file mode 100644 (file)
index c3ffb3a..0000000
+++ /dev/null
@@ -1,611 +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 packet
-
-import (
-       "crypto"
-       "crypto/dsa"
-       "crypto/openpgp/errors"
-       "crypto/openpgp/s2k"
-       "crypto/rsa"
-       "encoding/binary"
-       "hash"
-       "io"
-       "strconv"
-       "time"
-)
-
-// Signature represents a signature. See RFC 4880, section 5.2.
-type Signature struct {
-       SigType    SignatureType
-       PubKeyAlgo PublicKeyAlgorithm
-       Hash       crypto.Hash
-
-       // HashSuffix is extra data that is hashed in after the signed data.
-       HashSuffix []byte
-       // HashTag contains the first two bytes of the hash for fast rejection
-       // of bad signed data.
-       HashTag      [2]byte
-       CreationTime time.Time
-
-       RSASignature     parsedMPI
-       DSASigR, DSASigS parsedMPI
-
-       // rawSubpackets contains the unparsed subpackets, in order.
-       rawSubpackets []outputSubpacket
-
-       // The following are optional so are nil when not included in the
-       // signature.
-
-       SigLifetimeSecs, KeyLifetimeSecs                        *uint32
-       PreferredSymmetric, PreferredHash, PreferredCompression []uint8
-       IssuerKeyId                                             *uint64
-       IsPrimaryId                                             *bool
-
-       // FlagsValid is set if any flags were given. See RFC 4880, section
-       // 5.2.3.21 for details.
-       FlagsValid                                                           bool
-       FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
-
-       outSubpackets []outputSubpacket
-}
-
-func (sig *Signature) parse(r io.Reader) (err error) {
-       // RFC 4880, section 5.2.3
-       var buf [5]byte
-       _, err = readFull(r, buf[:1])
-       if err != nil {
-               return
-       }
-       if buf[0] != 4 {
-               err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
-               return
-       }
-
-       _, err = readFull(r, buf[:5])
-       if err != nil {
-               return
-       }
-       sig.SigType = SignatureType(buf[0])
-       sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
-       switch sig.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
-       default:
-               err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
-               return
-       }
-
-       var ok bool
-       sig.Hash, ok = s2k.HashIdToHash(buf[2])
-       if !ok {
-               return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
-       }
-
-       hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
-       l := 6 + hashedSubpacketsLength
-       sig.HashSuffix = make([]byte, l+6)
-       sig.HashSuffix[0] = 4
-       copy(sig.HashSuffix[1:], buf[:5])
-       hashedSubpackets := sig.HashSuffix[6:l]
-       _, err = readFull(r, hashedSubpackets)
-       if err != nil {
-               return
-       }
-       // See RFC 4880, section 5.2.4
-       trailer := sig.HashSuffix[l:]
-       trailer[0] = 4
-       trailer[1] = 0xff
-       trailer[2] = uint8(l >> 24)
-       trailer[3] = uint8(l >> 16)
-       trailer[4] = uint8(l >> 8)
-       trailer[5] = uint8(l)
-
-       err = parseSignatureSubpackets(sig, hashedSubpackets, true)
-       if err != nil {
-               return
-       }
-
-       _, err = readFull(r, buf[:2])
-       if err != nil {
-               return
-       }
-       unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
-       unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
-       _, err = readFull(r, unhashedSubpackets)
-       if err != nil {
-               return
-       }
-       err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
-       if err != nil {
-               return
-       }
-
-       _, err = readFull(r, sig.HashTag[:2])
-       if err != nil {
-               return
-       }
-
-       switch sig.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-               sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
-       case PubKeyAlgoDSA:
-               sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
-               if err == nil {
-                       sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
-               }
-       default:
-               panic("unreachable")
-       }
-       return
-}
-
-// parseSignatureSubpackets parses subpackets of the main signature packet. See
-// RFC 4880, section 5.2.3.1.
-func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
-       for len(subpackets) > 0 {
-               subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
-               if err != nil {
-                       return
-               }
-       }
-
-       if sig.CreationTime.IsZero() {
-               err = errors.StructuralError("no creation time in signature")
-       }
-
-       return
-}
-
-type signatureSubpacketType uint8
-
-const (
-       creationTimeSubpacket        signatureSubpacketType = 2
-       signatureExpirationSubpacket signatureSubpacketType = 3
-       keyExpirationSubpacket       signatureSubpacketType = 9
-       prefSymmetricAlgosSubpacket  signatureSubpacketType = 11
-       issuerSubpacket              signatureSubpacketType = 16
-       prefHashAlgosSubpacket       signatureSubpacketType = 21
-       prefCompressionSubpacket     signatureSubpacketType = 22
-       primaryUserIdSubpacket       signatureSubpacketType = 25
-       keyFlagsSubpacket            signatureSubpacketType = 27
-)
-
-// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
-func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
-       // RFC 4880, section 5.2.3.1
-       var (
-               length     uint32
-               packetType signatureSubpacketType
-               isCritical bool
-       )
-       switch {
-       case subpacket[0] < 192:
-               length = uint32(subpacket[0])
-               subpacket = subpacket[1:]
-       case subpacket[0] < 255:
-               if len(subpacket) < 2 {
-                       goto Truncated
-               }
-               length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
-               subpacket = subpacket[2:]
-       default:
-               if len(subpacket) < 5 {
-                       goto Truncated
-               }
-               length = uint32(subpacket[1])<<24 |
-                       uint32(subpacket[2])<<16 |
-                       uint32(subpacket[3])<<8 |
-                       uint32(subpacket[4])
-               subpacket = subpacket[5:]
-       }
-       if length > uint32(len(subpacket)) {
-               goto Truncated
-       }
-       rest = subpacket[length:]
-       subpacket = subpacket[:length]
-       if len(subpacket) == 0 {
-               err = errors.StructuralError("zero length signature subpacket")
-               return
-       }
-       packetType = signatureSubpacketType(subpacket[0] & 0x7f)
-       isCritical = subpacket[0]&0x80 == 0x80
-       subpacket = subpacket[1:]
-       sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
-       switch packetType {
-       case creationTimeSubpacket:
-               if !isHashed {
-                       err = errors.StructuralError("signature creation time in non-hashed area")
-                       return
-               }
-               if len(subpacket) != 4 {
-                       err = errors.StructuralError("signature creation time not four bytes")
-                       return
-               }
-               t := binary.BigEndian.Uint32(subpacket)
-               sig.CreationTime = time.Unix(int64(t), 0)
-       case signatureExpirationSubpacket:
-               // Signature expiration time, section 5.2.3.10
-               if !isHashed {
-                       return
-               }
-               if len(subpacket) != 4 {
-                       err = errors.StructuralError("expiration subpacket with bad length")
-                       return
-               }
-               sig.SigLifetimeSecs = new(uint32)
-               *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
-       case keyExpirationSubpacket:
-               // Key expiration time, section 5.2.3.6
-               if !isHashed {
-                       return
-               }
-               if len(subpacket) != 4 {
-                       err = errors.StructuralError("key expiration subpacket with bad length")
-                       return
-               }
-               sig.KeyLifetimeSecs = new(uint32)
-               *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
-       case prefSymmetricAlgosSubpacket:
-               // Preferred symmetric algorithms, section 5.2.3.7
-               if !isHashed {
-                       return
-               }
-               sig.PreferredSymmetric = make([]byte, len(subpacket))
-               copy(sig.PreferredSymmetric, subpacket)
-       case issuerSubpacket:
-               // Issuer, section 5.2.3.5
-               if len(subpacket) != 8 {
-                       err = errors.StructuralError("issuer subpacket with bad length")
-                       return
-               }
-               sig.IssuerKeyId = new(uint64)
-               *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
-       case prefHashAlgosSubpacket:
-               // Preferred hash algorithms, section 5.2.3.8
-               if !isHashed {
-                       return
-               }
-               sig.PreferredHash = make([]byte, len(subpacket))
-               copy(sig.PreferredHash, subpacket)
-       case prefCompressionSubpacket:
-               // Preferred compression algorithms, section 5.2.3.9
-               if !isHashed {
-                       return
-               }
-               sig.PreferredCompression = make([]byte, len(subpacket))
-               copy(sig.PreferredCompression, subpacket)
-       case primaryUserIdSubpacket:
-               // Primary User ID, section 5.2.3.19
-               if !isHashed {
-                       return
-               }
-               if len(subpacket) != 1 {
-                       err = errors.StructuralError("primary user id subpacket with bad length")
-                       return
-               }
-               sig.IsPrimaryId = new(bool)
-               if subpacket[0] > 0 {
-                       *sig.IsPrimaryId = true
-               }
-       case keyFlagsSubpacket:
-               // Key flags, section 5.2.3.21
-               if !isHashed {
-                       return
-               }
-               if len(subpacket) == 0 {
-                       err = errors.StructuralError("empty key flags subpacket")
-                       return
-               }
-               sig.FlagsValid = true
-               if subpacket[0]&1 != 0 {
-                       sig.FlagCertify = true
-               }
-               if subpacket[0]&2 != 0 {
-                       sig.FlagSign = true
-               }
-               if subpacket[0]&4 != 0 {
-                       sig.FlagEncryptCommunications = true
-               }
-               if subpacket[0]&8 != 0 {
-                       sig.FlagEncryptStorage = true
-               }
-
-       default:
-               if isCritical {
-                       err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
-                       return
-               }
-       }
-       return
-
-Truncated:
-       err = errors.StructuralError("signature subpacket truncated")
-       return
-}
-
-// subpacketLengthLength returns the length, in bytes, of an encoded length value.
-func subpacketLengthLength(length int) int {
-       if length < 192 {
-               return 1
-       }
-       if length < 16320 {
-               return 2
-       }
-       return 5
-}
-
-// serializeSubpacketLength marshals the given length into to.
-func serializeSubpacketLength(to []byte, length int) int {
-       if length < 192 {
-               to[0] = byte(length)
-               return 1
-       }
-       if length < 16320 {
-               length -= 192
-               to[0] = byte(length >> 8)
-               to[1] = byte(length)
-               return 2
-       }
-       to[0] = 255
-       to[1] = byte(length >> 24)
-       to[2] = byte(length >> 16)
-       to[3] = byte(length >> 8)
-       to[4] = byte(length)
-       return 5
-}
-
-// subpacketsLength returns the serialized length, in bytes, of the given
-// subpackets.
-func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
-       for _, subpacket := range subpackets {
-               if subpacket.hashed == hashed {
-                       length += subpacketLengthLength(len(subpacket.contents) + 1)
-                       length += 1 // type byte
-                       length += len(subpacket.contents)
-               }
-       }
-       return
-}
-
-// serializeSubpackets marshals the given subpackets into to.
-func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
-       for _, subpacket := range subpackets {
-               if subpacket.hashed == hashed {
-                       n := serializeSubpacketLength(to, len(subpacket.contents)+1)
-                       to[n] = byte(subpacket.subpacketType)
-                       to = to[1+n:]
-                       n = copy(to, subpacket.contents)
-                       to = to[n:]
-               }
-       }
-       return
-}
-
-// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
-func (sig *Signature) buildHashSuffix() (err error) {
-       hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
-
-       var ok bool
-       l := 6 + hashedSubpacketsLen
-       sig.HashSuffix = make([]byte, l+6)
-       sig.HashSuffix[0] = 4
-       sig.HashSuffix[1] = uint8(sig.SigType)
-       sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
-       sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
-       if !ok {
-               sig.HashSuffix = nil
-               return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
-       }
-       sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
-       sig.HashSuffix[5] = byte(hashedSubpacketsLen)
-       serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
-       trailer := sig.HashSuffix[l:]
-       trailer[0] = 4
-       trailer[1] = 0xff
-       trailer[2] = byte(l >> 24)
-       trailer[3] = byte(l >> 16)
-       trailer[4] = byte(l >> 8)
-       trailer[5] = byte(l)
-       return
-}
-
-func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
-       err = sig.buildHashSuffix()
-       if err != nil {
-               return
-       }
-
-       h.Write(sig.HashSuffix)
-       digest = h.Sum(nil)
-       copy(sig.HashTag[:], digest)
-       return
-}
-
-// Sign signs a message with a private key. The hash, h, must contain
-// the hash of the message to be signed and will be mutated by this function.
-// On success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) Sign(rand io.Reader, h hash.Hash, priv *PrivateKey) (err error) {
-       sig.outSubpackets = sig.buildSubpackets()
-       digest, err := sig.signPrepareHash(h)
-       if err != nil {
-               return
-       }
-
-       switch priv.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-               sig.RSASignature.bytes, err = rsa.SignPKCS1v15(rand, priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
-               sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
-       case PubKeyAlgoDSA:
-               dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
-
-               // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
-               subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
-               if len(digest) > subgroupSize {
-                       digest = digest[:subgroupSize]
-               }
-               r, s, err := dsa.Sign(rand, dsaPriv, digest)
-               if err == nil {
-                       sig.DSASigR.bytes = r.Bytes()
-                       sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
-                       sig.DSASigS.bytes = s.Bytes()
-                       sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
-               }
-       default:
-               err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
-       }
-
-       return
-}
-
-// SignUserId computes a signature from priv, asserting that pub is a valid
-// key for the identity id.  On success, the signature is stored in sig. Call
-// Serialize to write it out.
-func (sig *Signature) SignUserId(rand io.Reader, id string, pub *PublicKey, priv *PrivateKey) error {
-       h, err := userIdSignatureHash(id, pub, sig)
-       if err != nil {
-               return nil
-       }
-       return sig.Sign(rand, h, priv)
-}
-
-// SignKey computes a signature from priv, asserting that pub is a subkey.  On
-// success, the signature is stored in sig. Call Serialize to write it out.
-func (sig *Signature) SignKey(rand io.Reader, pub *PublicKey, priv *PrivateKey) error {
-       h, err := keySignatureHash(&priv.PublicKey, pub, sig)
-       if err != nil {
-               return err
-       }
-       return sig.Sign(rand, h, priv)
-}
-
-// Serialize marshals sig to w. SignRSA or SignDSA must have been called first.
-func (sig *Signature) Serialize(w io.Writer) (err error) {
-       if len(sig.outSubpackets) == 0 {
-               sig.outSubpackets = sig.rawSubpackets
-       }
-       if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
-               return errors.InvalidArgumentError("Signature: need to call SignRSA or SignDSA before Serialize")
-       }
-
-       sigLength := 0
-       switch sig.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-               sigLength = 2 + len(sig.RSASignature.bytes)
-       case PubKeyAlgoDSA:
-               sigLength = 2 + len(sig.DSASigR.bytes)
-               sigLength += 2 + len(sig.DSASigS.bytes)
-       default:
-               panic("impossible")
-       }
-
-       unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
-       length := len(sig.HashSuffix) - 6 /* trailer not included */ +
-               2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
-               2 /* hash tag */ + sigLength
-       err = serializeHeader(w, packetTypeSignature, length)
-       if err != nil {
-               return
-       }
-
-       _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
-       if err != nil {
-               return
-       }
-
-       unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
-       unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
-       unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
-       serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
-
-       _, err = w.Write(unhashedSubpackets)
-       if err != nil {
-               return
-       }
-       _, err = w.Write(sig.HashTag[:])
-       if err != nil {
-               return
-       }
-
-       switch sig.PubKeyAlgo {
-       case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
-               err = writeMPIs(w, sig.RSASignature)
-       case PubKeyAlgoDSA:
-               err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
-       default:
-               panic("impossible")
-       }
-       return
-}
-
-// outputSubpacket represents a subpacket to be marshaled.
-type outputSubpacket struct {
-       hashed        bool // true if this subpacket is in the hashed area.
-       subpacketType signatureSubpacketType
-       isCritical    bool
-       contents      []byte
-}
-
-func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
-       creationTime := make([]byte, 4)
-       binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
-       subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
-
-       if sig.IssuerKeyId != nil {
-               keyId := make([]byte, 8)
-               binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
-               subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
-       }
-
-       if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
-               sigLifetime := make([]byte, 4)
-               binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
-               subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
-       }
-
-       // Key flags may only appear in self-signatures or certification signatures.
-
-       if sig.FlagsValid {
-               var flags byte
-               if sig.FlagCertify {
-                       flags |= 1
-               }
-               if sig.FlagSign {
-                       flags |= 2
-               }
-               if sig.FlagEncryptCommunications {
-                       flags |= 4
-               }
-               if sig.FlagEncryptStorage {
-                       flags |= 8
-               }
-               subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
-       }
-
-       // The following subpackets may only appear in self-signatures
-
-       if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
-               keyLifetime := make([]byte, 4)
-               binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
-               subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
-       }
-
-       if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
-               subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
-       }
-
-       if len(sig.PreferredSymmetric) > 0 {
-               subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
-       }
-
-       if len(sig.PreferredHash) > 0 {
-               subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
-       }
-
-       if len(sig.PreferredCompression) > 0 {
-               subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
-       }
-
-       return
-}
diff --git a/libgo/go/crypto/openpgp/packet/signature_test.go b/libgo/go/crypto/openpgp/packet/signature_test.go
deleted file mode 100644 (file)
index c1bbde8..0000000
+++ /dev/null
@@ -1,42 +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 packet
-
-import (
-       "bytes"
-       "crypto"
-       "encoding/hex"
-       "testing"
-)
-
-func TestSignatureRead(t *testing.T) {
-       packet, err := Read(readerFromHex(signatureDataHex))
-       if err != nil {
-               t.Error(err)
-               return
-       }
-       sig, ok := packet.(*Signature)
-       if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
-               t.Errorf("failed to parse, got: %#v", packet)
-       }
-}
-
-func TestSignatureReserialize(t *testing.T) {
-       packet, _ := Read(readerFromHex(signatureDataHex))
-       sig := packet.(*Signature)
-       out := new(bytes.Buffer)
-       err := sig.Serialize(out)
-       if err != nil {
-               t.Errorf("error reserializing: %s", err)
-               return
-       }
-
-       expected, _ := hex.DecodeString(signatureDataHex)
-       if !bytes.Equal(expected, out.Bytes()) {
-               t.Errorf("output doesn't match input (got vs expected):\n%s\n%s", hex.Dump(out.Bytes()), hex.Dump(expected))
-       }
-}
-
-const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
diff --git a/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go b/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted.go
deleted file mode 100644 (file)
index 94e0705..0000000
+++ /dev/null
@@ -1,161 +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 packet
-
-import (
-       "bytes"
-       "crypto/cipher"
-       "crypto/openpgp/errors"
-       "crypto/openpgp/s2k"
-       "io"
-       "strconv"
-)
-
-// This is the largest session key that we'll support. Since no 512-bit cipher
-// has even been seriously used, this is comfortably large.
-const maxSessionKeySizeInBytes = 64
-
-// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
-// 4880, section 5.3.
-type SymmetricKeyEncrypted struct {
-       CipherFunc   CipherFunction
-       Encrypted    bool
-       Key          []byte // Empty unless Encrypted is false.
-       s2k          func(out, in []byte)
-       encryptedKey []byte
-}
-
-const symmetricKeyEncryptedVersion = 4
-
-func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) {
-       // RFC 4880, section 5.3.
-       var buf [2]byte
-       _, err = readFull(r, buf[:])
-       if err != nil {
-               return
-       }
-       if buf[0] != symmetricKeyEncryptedVersion {
-               return errors.UnsupportedError("SymmetricKeyEncrypted version")
-       }
-       ske.CipherFunc = CipherFunction(buf[1])
-
-       if ske.CipherFunc.KeySize() == 0 {
-               return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
-       }
-
-       ske.s2k, err = s2k.Parse(r)
-       if err != nil {
-               return
-       }
-
-       encryptedKey := make([]byte, maxSessionKeySizeInBytes)
-       // The session key may follow. We just have to try and read to find
-       // out. If it exists then we limit it to maxSessionKeySizeInBytes.
-       n, err := readFull(r, encryptedKey)
-       if err != nil && err != io.ErrUnexpectedEOF {
-               return
-       }
-       err = nil
-       if n != 0 {
-               if n == maxSessionKeySizeInBytes {
-                       return errors.UnsupportedError("oversized encrypted session key")
-               }
-               ske.encryptedKey = encryptedKey[:n]
-       }
-
-       ske.Encrypted = true
-
-       return
-}
-
-// Decrypt attempts to decrypt an encrypted session key. If it returns nil,
-// ske.Key will contain the session key.
-func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error {
-       if !ske.Encrypted {
-               return nil
-       }
-
-       key := make([]byte, ske.CipherFunc.KeySize())
-       ske.s2k(key, passphrase)
-
-       if len(ske.encryptedKey) == 0 {
-               ske.Key = key
-       } else {
-               // the IV is all zeros
-               iv := make([]byte, ske.CipherFunc.blockSize())
-               c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
-               c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
-               ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
-               if ske.CipherFunc.blockSize() == 0 {
-                       return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
-               }
-               ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
-               ske.Key = ske.encryptedKey[1:]
-               if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
-                       ske.Key = nil
-                       return errors.StructuralError("length of decrypted key not a multiple of block size")
-               }
-       }
-
-       ske.Encrypted = false
-       return nil
-}
-
-// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
-// packet contains a random session key, encrypted by a key derived from the
-// given passphrase. The session key is returned and must be passed to
-// SerializeSymmetricallyEncrypted.
-func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []byte, cipherFunc CipherFunction) (key []byte, err error) {
-       keySize := cipherFunc.KeySize()
-       if keySize == 0 {
-               return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
-       }
-
-       s2kBuf := new(bytes.Buffer)
-       keyEncryptingKey := make([]byte, keySize)
-       // s2k.Serialize salts and stretches the passphrase, and writes the
-       // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
-       err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase)
-       if err != nil {
-               return
-       }
-       s2kBytes := s2kBuf.Bytes()
-
-       packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
-       err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
-       if err != nil {
-               return
-       }
-
-       var buf [2]byte
-       buf[0] = symmetricKeyEncryptedVersion
-       buf[1] = byte(cipherFunc)
-       _, err = w.Write(buf[:])
-       if err != nil {
-               return
-       }
-       _, err = w.Write(s2kBytes)
-       if err != nil {
-               return
-       }
-
-       sessionKey := make([]byte, keySize)
-       _, err = io.ReadFull(rand, sessionKey)
-       if err != nil {
-               return
-       }
-       iv := make([]byte, cipherFunc.blockSize())
-       c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
-       encryptedCipherAndKey := make([]byte, keySize+1)
-       c.XORKeyStream(encryptedCipherAndKey, buf[1:])
-       c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
-       _, err = w.Write(encryptedCipherAndKey)
-       if err != nil {
-               return
-       }
-
-       key = sessionKey
-       return
-}
diff --git a/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted_test.go b/libgo/go/crypto/openpgp/packet/symmetric_key_encrypted_test.go
deleted file mode 100644 (file)
index 87690f0..0000000
+++ /dev/null
@@ -1,101 +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 packet
-
-import (
-       "bytes"
-       "crypto/rand"
-       "encoding/hex"
-       "io"
-       "io/ioutil"
-       "testing"
-)
-
-func TestSymmetricKeyEncrypted(t *testing.T) {
-       buf := readerFromHex(symmetricallyEncryptedHex)
-       packet, err := Read(buf)
-       if err != nil {
-               t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
-               return
-       }
-       ske, ok := packet.(*SymmetricKeyEncrypted)
-       if !ok {
-               t.Error("didn't find SymmetricKeyEncrypted packet")
-               return
-       }
-       err = ske.Decrypt([]byte("password"))
-       if err != nil {
-               t.Error(err)
-               return
-       }
-
-       packet, err = Read(buf)
-       if err != nil {
-               t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
-               return
-       }
-       se, ok := packet.(*SymmetricallyEncrypted)
-       if !ok {
-               t.Error("didn't find SymmetricallyEncrypted packet")
-               return
-       }
-       r, err := se.Decrypt(ske.CipherFunc, ske.Key)
-       if err != nil {
-               t.Error(err)
-               return
-       }
-
-       contents, err := ioutil.ReadAll(r)
-       if err != nil && err != io.EOF {
-               t.Error(err)
-               return
-       }
-
-       expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
-       if !bytes.Equal(expectedContents, contents) {
-               t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
-       }
-}
-
-const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
-const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"
-
-func TestSerializeSymmetricKeyEncrypted(t *testing.T) {
-       buf := bytes.NewBuffer(nil)
-       passphrase := []byte("testing")
-       cipherFunc := CipherAES128
-
-       key, err := SerializeSymmetricKeyEncrypted(buf, rand.Reader, passphrase, cipherFunc)
-       if err != nil {
-               t.Errorf("failed to serialize: %s", err)
-               return
-       }
-
-       p, err := Read(buf)
-       if err != nil {
-               t.Errorf("failed to reparse: %s", err)
-               return
-       }
-       ske, ok := p.(*SymmetricKeyEncrypted)
-       if !ok {
-               t.Errorf("parsed a different packet type: %#v", p)
-               return
-       }
-
-       if !ske.Encrypted {
-               t.Errorf("SKE not encrypted but should be")
-       }
-       if ske.CipherFunc != cipherFunc {
-               t.Errorf("SKE cipher function is %d (expected %d)", ske.CipherFunc, cipherFunc)
-       }
-       err = ske.Decrypt(passphrase)
-       if err != nil {
-               t.Errorf("failed to decrypt reparsed SKE: %s", err)
-               return
-       }
-       if !bytes.Equal(key, ske.Key) {
-               t.Errorf("keys don't match after Decrpyt: %x (original) vs %x (parsed)", key, ske.Key)
-       }
-}
diff --git a/libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go b/libgo/go/crypto/openpgp/packet/symmetrically_encrypted.go
deleted file mode 100644 (file)
index e99a23b..0000000
+++ /dev/null
@@ -1,289 +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 packet
-
-import (
-       "crypto/cipher"
-       "crypto/openpgp/errors"
-       "crypto/sha1"
-       "crypto/subtle"
-       "hash"
-       "io"
-       "strconv"
-)
-
-// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
-// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
-// sections 5.7 and 5.13.
-type SymmetricallyEncrypted struct {
-       MDC      bool // true iff this is a type 18 packet and thus has an embedded MAC.
-       contents io.Reader
-       prefix   []byte
-}
-
-const symmetricallyEncryptedVersion = 1
-
-func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
-       if se.MDC {
-               // See RFC 4880, section 5.13.
-               var buf [1]byte
-               _, err := readFull(r, buf[:])
-               if err != nil {
-                       return err
-               }
-               if buf[0] != symmetricallyEncryptedVersion {
-                       return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
-               }
-       }
-       se.contents = r
-       return nil
-}
-
-// Decrypt returns a ReadCloser, from which the decrypted contents of the
-// packet can be read. An incorrect key can, with high probability, be detected
-// immediately and this will result in a KeyIncorrect error being returned.
-func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
-       keySize := c.KeySize()
-       if keySize == 0 {
-               return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
-       }
-       if len(key) != keySize {
-               return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
-       }
-
-       if se.prefix == nil {
-               se.prefix = make([]byte, c.blockSize()+2)
-               _, err := readFull(se.contents, se.prefix)
-               if err != nil {
-                       return nil, err
-               }
-       } else if len(se.prefix) != c.blockSize()+2 {
-               return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
-       }
-
-       ocfbResync := cipher.OCFBResync
-       if se.MDC {
-               // MDC packets use a different form of OCFB mode.
-               ocfbResync = cipher.OCFBNoResync
-       }
-
-       s := cipher.NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
-       if s == nil {
-               return nil, errors.KeyIncorrectError
-       }
-
-       plaintext := cipher.StreamReader{S: s, R: se.contents}
-
-       if se.MDC {
-               // MDC packets have an embedded hash that we need to check.
-               h := sha1.New()
-               h.Write(se.prefix)
-               return &seMDCReader{in: plaintext, h: h}, nil
-       }
-
-       // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
-       return seReader{plaintext}, nil
-}
-
-// seReader wraps an io.Reader with a no-op Close method.
-type seReader struct {
-       in io.Reader
-}
-
-func (ser seReader) Read(buf []byte) (int, error) {
-       return ser.in.Read(buf)
-}
-
-func (ser seReader) Close() error {
-       return nil
-}
-
-const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
-
-// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
-// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
-// MDC packet containing a hash of the previous contents which is checked
-// against the running hash. See RFC 4880, section 5.13.
-type seMDCReader struct {
-       in          io.Reader
-       h           hash.Hash
-       trailer     [mdcTrailerSize]byte
-       scratch     [mdcTrailerSize]byte
-       trailerUsed int
-       error       bool
-       eof         bool
-}
-
-func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
-       if ser.error {
-               err = io.ErrUnexpectedEOF
-               return
-       }
-       if ser.eof {
-               err = io.EOF
-               return
-       }
-
-       // If we haven't yet filled the trailer buffer then we must do that
-       // first.
-       for ser.trailerUsed < mdcTrailerSize {
-               n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
-               ser.trailerUsed += n
-               if err == io.EOF {
-                       if ser.trailerUsed != mdcTrailerSize {
-                               n = 0
-                               err = io.ErrUnexpectedEOF
-                               ser.error = true
-                               return
-                       }
-                       ser.eof = true
-                       n = 0
-                       return
-               }
-
-               if err != nil {
-                       n = 0
-                       return
-               }
-       }
-
-       // If it's a short read then we read into a temporary buffer and shift
-       // the data into the caller's buffer.
-       if len(buf) <= mdcTrailerSize {
-               n, err = readFull(ser.in, ser.scratch[:len(buf)])
-               copy(buf, ser.trailer[:n])
-               ser.h.Write(buf[:n])
-               copy(ser.trailer[:], ser.trailer[n:])
-               copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
-               if n < len(buf) {
-                       ser.eof = true
-                       err = io.EOF
-               }
-               return
-       }
-
-       n, err = ser.in.Read(buf[mdcTrailerSize:])
-       copy(buf, ser.trailer[:])
-       ser.h.Write(buf[:n])
-       copy(ser.trailer[:], buf[n:])
-
-       if err == io.EOF {
-               ser.eof = true
-       }
-       return
-}
-
-// This is a new-format packet tag byte for a type 19 (MDC) packet.
-const mdcPacketTagByte = byte(0x80) | 0x40 | 19
-
-func (ser *seMDCReader) Close() error {
-       if ser.error {
-               return errors.SignatureError("error during reading")
-       }
-
-       for !ser.eof {
-               // We haven't seen EOF so we need to read to the end
-               var buf [1024]byte
-               _, err := ser.Read(buf[:])
-               if err == io.EOF {
-                       break
-               }
-               if err != nil {
-                       return errors.SignatureError("error during reading")
-               }
-       }
-
-       if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
-               return errors.SignatureError("MDC packet not found")
-       }
-       ser.h.Write(ser.trailer[:2])
-
-       final := ser.h.Sum(nil)
-       if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
-               return errors.SignatureError("hash mismatch")
-       }
-       return nil
-}
-
-// An seMDCWriter writes through to an io.WriteCloser while maintains a running
-// hash of the data written. On close, it emits an MDC packet containing the
-// running hash.
-type seMDCWriter struct {
-       w io.WriteCloser
-       h hash.Hash
-}
-
-func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
-       w.h.Write(buf)
-       return w.w.Write(buf)
-}
-
-func (w *seMDCWriter) Close() (err error) {
-       var buf [mdcTrailerSize]byte
-
-       buf[0] = mdcPacketTagByte
-       buf[1] = sha1.Size
-       w.h.Write(buf[:2])
-       digest := w.h.Sum(nil)
-       copy(buf[2:], digest)
-
-       _, err = w.w.Write(buf[:])
-       if err != nil {
-               return
-       }
-       return w.w.Close()
-}
-
-// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
-type noOpCloser struct {
-       w io.Writer
-}
-
-func (c noOpCloser) Write(data []byte) (n int, err error) {
-       return c.w.Write(data)
-}
-
-func (c noOpCloser) Close() error {
-       return nil
-}
-
-// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
-// to w and returns a WriteCloser to which the to-be-encrypted packets can be
-// written.
-func SerializeSymmetricallyEncrypted(w io.Writer, rand io.Reader, c CipherFunction, key []byte) (contents io.WriteCloser, err error) {
-       if c.KeySize() != len(key) {
-               return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
-       }
-       writeCloser := noOpCloser{w}
-       ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
-       if err != nil {
-               return
-       }
-
-       _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
-       if err != nil {
-               return
-       }
-
-       block := c.new(key)
-       blockSize := block.BlockSize()
-       iv := make([]byte, blockSize)
-       _, err = rand.Read(iv)
-       if err != nil {
-               return
-       }
-       s, prefix := cipher.NewOCFBEncrypter(block, iv, cipher.OCFBNoResync)
-       _, err = ciphertext.Write(prefix)
-       if err != nil {
-               return
-       }
-       plaintext := cipher.StreamWriter{S: s, W: ciphertext}
-
-       h := sha1.New()
-       h.Write(iv)
-       h.Write(iv[blockSize-2:])
-       contents = &seMDCWriter{w: plaintext, h: h}
-       return
-}
diff --git a/libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go b/libgo/go/crypto/openpgp/packet/symmetrically_encrypted_test.go
deleted file mode 100644 (file)
index f7d133d..0000000
+++ /dev/null
@@ -1,124 +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 packet
-
-import (
-       "bytes"
-       "crypto/openpgp/errors"
-       "crypto/rand"
-       "crypto/sha1"
-       "encoding/hex"
-       "io"
-       "io/ioutil"
-       "testing"
-)
-
-// TestReader wraps a []byte and returns reads of a specific length.
-type testReader struct {
-       data   []byte
-       stride int
-}
-
-func (t *testReader) Read(buf []byte) (n int, err error) {
-       n = t.stride
-       if n > len(t.data) {
-               n = len(t.data)
-       }
-       if n > len(buf) {
-               n = len(buf)
-       }
-       copy(buf, t.data)
-       t.data = t.data[n:]
-       if len(t.data) == 0 {
-               err = io.EOF
-       }
-       return
-}
-
-func testMDCReader(t *testing.T) {
-       mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)
-
-       for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
-               r := &testReader{data: mdcPlaintext, stride: stride}
-               mdcReader := &seMDCReader{in: r, h: sha1.New()}
-               body, err := ioutil.ReadAll(mdcReader)
-               if err != nil {
-                       t.Errorf("stride: %d, error: %s", stride, err)
-                       continue
-               }
-               if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
-                       t.Errorf("stride: %d: bad contents %x", stride, body)
-                       continue
-               }
-
-               err = mdcReader.Close()
-               if err != nil {
-                       t.Errorf("stride: %d, error on Close: %s", stride, err)
-               }
-       }
-
-       mdcPlaintext[15] ^= 80
-
-       r := &testReader{data: mdcPlaintext, stride: 2}
-       mdcReader := &seMDCReader{in: r, h: sha1.New()}
-       _, err := ioutil.ReadAll(mdcReader)
-       if err != nil {
-               t.Errorf("corruption test, error: %s", err)
-               return
-       }
-       err = mdcReader.Close()
-       if err == nil {
-               t.Error("corruption: no error")
-       } else if _, ok := err.(*errors.SignatureError); !ok {
-               t.Errorf("corruption: expected SignatureError, got: %s", err)
-       }
-}
-
-const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"
-
-func TestSerialize(t *testing.T) {
-       buf := bytes.NewBuffer(nil)
-       c := CipherAES128
-       key := make([]byte, c.KeySize())
-
-       w, err := SerializeSymmetricallyEncrypted(buf, rand.Reader, c, key)
-       if err != nil {
-               t.Errorf("error from SerializeSymmetricallyEncrypted: %s", err)
-               return
-       }
-
-       contents := []byte("hello world\n")
-
-       w.Write(contents)
-       w.Close()
-
-       p, err := Read(buf)
-       if err != nil {
-               t.Errorf("error from Read: %s", err)
-               return
-       }
-
-       se, ok := p.(*SymmetricallyEncrypted)
-       if !ok {
-               t.Errorf("didn't read a *SymmetricallyEncrypted")
-               return
-       }
-
-       r, err := se.Decrypt(c, key)
-       if err != nil {
-               t.Errorf("error from Decrypt: %s", err)
-               return
-       }
-
-       contentsCopy := bytes.NewBuffer(nil)
-       _, err = io.Copy(contentsCopy, r)
-       if err != nil {
-               t.Errorf("error from io.Copy: %s", err)
-               return
-       }
-       if !bytes.Equal(contentsCopy.Bytes(), contents) {
-               t.Errorf("contents not equal got: %x want: %x", contentsCopy.Bytes(), contents)
-       }
-}
diff --git a/libgo/go/crypto/openpgp/packet/userid.go b/libgo/go/crypto/openpgp/packet/userid.go
deleted file mode 100644 (file)
index d6bea7d..0000000
+++ /dev/null
@@ -1,160 +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 packet
-
-import (
-       "io"
-       "io/ioutil"
-       "strings"
-)
-
-// UserId contains text that is intended to represent the name and email
-// address of the key holder. See RFC 4880, section 5.11. By convention, this
-// takes the form "Full Name (Comment) <email@example.com>"
-type UserId struct {
-       Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
-
-       Name, Comment, Email string
-}
-
-func hasInvalidCharacters(s string) bool {
-       for _, c := range s {
-               switch c {
-               case '(', ')', '<', '>', 0:
-                       return true
-               }
-       }
-       return false
-}
-
-// NewUserId returns a UserId or nil if any of the arguments contain invalid
-// characters. The invalid characters are '\x00', '(', ')', '<' and '>'
-func NewUserId(name, comment, email string) *UserId {
-       // RFC 4880 doesn't deal with the structure of userid strings; the
-       // name, comment and email form is just a convention. However, there's
-       // no convention about escaping the metacharacters and GPG just refuses
-       // to create user ids where, say, the name contains a '('. We mirror
-       // this behaviour.
-
-       if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
-               return nil
-       }
-
-       uid := new(UserId)
-       uid.Name, uid.Comment, uid.Email = name, comment, email
-       uid.Id = name
-       if len(comment) > 0 {
-               if len(uid.Id) > 0 {
-                       uid.Id += " "
-               }
-               uid.Id += "("
-               uid.Id += comment
-               uid.Id += ")"
-       }
-       if len(email) > 0 {
-               if len(uid.Id) > 0 {
-                       uid.Id += " "
-               }
-               uid.Id += "<"
-               uid.Id += email
-               uid.Id += ">"
-       }
-       return uid
-}
-
-func (uid *UserId) parse(r io.Reader) (err error) {
-       // RFC 4880, section 5.11
-       b, err := ioutil.ReadAll(r)
-       if err != nil {
-               return
-       }
-       uid.Id = string(b)
-       uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
-       return
-}
-
-// Serialize marshals uid to w in the form of an OpenPGP packet, including
-// header.
-func (uid *UserId) Serialize(w io.Writer) error {
-       err := serializeHeader(w, packetTypeUserId, len(uid.Id))
-       if err != nil {
-               return err
-       }
-       _, err = w.Write([]byte(uid.Id))
-       return err
-}
-
-// parseUserId extracts the name, comment and email from a user id string that
-// is formatted as "Full Name (Comment) <email@example.com>".
-func parseUserId(id string) (name, comment, email string) {
-       var n, c, e struct {
-               start, end int
-       }
-       var state int
-
-       for offset, rune := range id {
-               switch state {
-               case 0:
-                       // Entering name
-                       n.start = offset
-                       state = 1
-                       fallthrough
-               case 1:
-                       // In name
-                       if rune == '(' {
-                               state = 2
-                               n.end = offset
-                       } else if rune == '<' {
-                               state = 5
-                               n.end = offset
-                       }
-               case 2:
-                       // Entering comment
-                       c.start = offset
-                       state = 3
-                       fallthrough
-               case 3:
-                       // In comment
-                       if rune == ')' {
-                               state = 4
-                               c.end = offset
-                       }
-               case 4:
-                       // Between comment and email
-                       if rune == '<' {
-                               state = 5
-                       }
-               case 5:
-                       // Entering email
-                       e.start = offset
-                       state = 6
-                       fallthrough
-               case 6:
-                       // In email
-                       if rune == '>' {
-                               state = 7
-                               e.end = offset
-                       }
-               default:
-                       // After email
-               }
-       }
-       switch state {
-       case 1:
-               // ended in the name
-               n.end = len(id)
-       case 3:
-               // ended in comment
-               c.end = len(id)
-       case 6:
-               // ended in email
-               e.end = len(id)
-       }
-
-       name = strings.TrimSpace(id[n.start:n.end])
-       comment = strings.TrimSpace(id[c.start:c.end])
-       email = strings.TrimSpace(id[e.start:e.end])
-       return
-}
diff --git a/libgo/go/crypto/openpgp/packet/userid_test.go b/libgo/go/crypto/openpgp/packet/userid_test.go
deleted file mode 100644 (file)
index 2968193..0000000
+++ /dev/null
@@ -1,87 +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 packet
-
-import (
-       "testing"
-)
-
-var userIdTests = []struct {
-       id                   string
-       name, comment, email string
-}{
-       {"", "", "", ""},
-       {"John Smith", "John Smith", "", ""},
-       {"John Smith ()", "John Smith", "", ""},
-       {"John Smith () <>", "John Smith", "", ""},
-       {"(comment", "", "comment", ""},
-       {"(comment)", "", "comment", ""},
-       {"<email", "", "", "email"},
-       {"<email>   sdfk", "", "", "email"},
-       {"  John Smith  (  Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"},
-       {"  John Smith  < email > lksdfj", "John Smith", "", "email"},
-       {"(<foo", "", "<foo", ""},
-       {"René Descartes (العربي)", "René Descartes", "العربي", ""},
-}
-
-func TestParseUserId(t *testing.T) {
-       for i, test := range userIdTests {
-               name, comment, email := parseUserId(test.id)
-               if name != test.name {
-                       t.Errorf("%d: name mismatch got:%s want:%s", i, name, test.name)
-               }
-               if comment != test.comment {
-                       t.Errorf("%d: comment mismatch got:%s want:%s", i, comment, test.comment)
-               }
-               if email != test.email {
-                       t.Errorf("%d: email mismatch got:%s want:%s", i, email, test.email)
-               }
-       }
-}
-
-var newUserIdTests = []struct {
-       name, comment, email, id string
-}{
-       {"foo", "", "", "foo"},
-       {"", "bar", "", "(bar)"},
-       {"", "", "baz", "<baz>"},
-       {"foo", "bar", "", "foo (bar)"},
-       {"foo", "", "baz", "foo <baz>"},
-       {"", "bar", "baz", "(bar) <baz>"},
-       {"foo", "bar", "baz", "foo (bar) <baz>"},
-}
-
-func TestNewUserId(t *testing.T) {
-       for i, test := range newUserIdTests {
-               uid := NewUserId(test.name, test.comment, test.email)
-               if uid == nil {
-                       t.Errorf("#%d: returned nil", i)
-                       continue
-               }
-               if uid.Id != test.id {
-                       t.Errorf("#%d: got '%s', want '%s'", i, uid.Id, test.id)
-               }
-       }
-}
-
-var invalidNewUserIdTests = []struct {
-       name, comment, email string
-}{
-       {"foo(", "", ""},
-       {"foo<", "", ""},
-       {"", "bar)", ""},
-       {"", "bar<", ""},
-       {"", "", "baz>"},
-       {"", "", "baz)"},
-       {"", "", "baz\x00"},
-}
-
-func TestNewUserIdWithInvalidInput(t *testing.T) {
-       for i, test := range invalidNewUserIdTests {
-               if uid := NewUserId(test.name, test.comment, test.email); uid != nil {
-                       t.Errorf("#%d: returned non-nil value: %#v", i, uid)
-               }
-       }
-}
diff --git a/libgo/go/crypto/openpgp/read.go b/libgo/go/crypto/openpgp/read.go
deleted file mode 100644 (file)
index 1d23434..0000000
+++ /dev/null
@@ -1,414 +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 openpgp implements high level operations on OpenPGP messages.
-package openpgp
-
-import (
-       "crypto"
-       "crypto/openpgp/armor"
-       "crypto/openpgp/errors"
-       "crypto/openpgp/packet"
-       _ "crypto/sha256"
-       "hash"
-       "io"
-       "strconv"
-)
-
-// SignatureType is the armor type for a PGP signature.
-var SignatureType = "PGP SIGNATURE"
-
-// readArmored reads an armored block with the given type.
-func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
-       block, err := armor.Decode(r)
-       if err != nil {
-               return
-       }
-
-       if block.Type != expectedType {
-               return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
-       }
-
-       return block.Body, nil
-}
-
-// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
-// signed message.
-type MessageDetails struct {
-       IsEncrypted              bool                // true if the message was encrypted.
-       EncryptedToKeyIds        []uint64            // the list of recipient key ids.
-       IsSymmetricallyEncrypted bool                // true if a passphrase could have decrypted the message.
-       DecryptedWith            Key                 // the private key used to decrypt the message, if any.
-       IsSigned                 bool                // true if the message is signed.
-       SignedByKeyId            uint64              // the key id of the signer, if any.
-       SignedBy                 *Key                // the key of the signer, if available.
-       LiteralData              *packet.LiteralData // the metadata of the contents
-       UnverifiedBody           io.Reader           // the contents of the message.
-
-       // If IsSigned is true and SignedBy is non-zero then the signature will
-       // be verified as UnverifiedBody is read. The signature cannot be
-       // checked until the whole of UnverifiedBody is read so UnverifiedBody
-       // must be consumed until EOF before the data can trusted. Even if a
-       // message isn't signed (or the signer is unknown) the data may contain
-       // an authentication code that is only checked once UnverifiedBody has
-       // been consumed. Once EOF has been seen, the following fields are
-       // valid. (An authentication code failure is reported as a
-       // SignatureError error when reading from UnverifiedBody.)
-       SignatureError error             // nil if the signature is good.
-       Signature      *packet.Signature // the signature packet itself.
-
-       decrypted io.ReadCloser
-}
-
-// A PromptFunction is used as a callback by functions that may need to decrypt
-// a private key, or prompt for a passphrase. It is called with a list of
-// acceptable, encrypted private keys and a boolean that indicates whether a
-// passphrase is usable. It should either decrypt a private key or return a
-// passphrase to try. If the decrypted private key or given passphrase isn't
-// correct, the function will be called again, forever. Any error returned will
-// be passed up.
-type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
-
-// A keyEnvelopePair is used to store a private key with the envelope that
-// contains a symmetric key, encrypted with that key.
-type keyEnvelopePair struct {
-       key          Key
-       encryptedKey *packet.EncryptedKey
-}
-
-// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
-// The given KeyRing should contain both public keys (for signature
-// verification) and, possibly encrypted, private keys for decrypting.
-func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction) (md *MessageDetails, err error) {
-       var p packet.Packet
-
-       var symKeys []*packet.SymmetricKeyEncrypted
-       var pubKeys []keyEnvelopePair
-       var se *packet.SymmetricallyEncrypted
-
-       packets := packet.NewReader(r)
-       md = new(MessageDetails)
-       md.IsEncrypted = true
-
-       // The message, if encrypted, starts with a number of packets
-       // containing an encrypted decryption key. The decryption key is either
-       // encrypted to a public key, or with a passphrase. This loop
-       // collects these packets.
-ParsePackets:
-       for {
-               p, err = packets.Next()
-               if err != nil {
-                       return nil, err
-               }
-               switch p := p.(type) {
-               case *packet.SymmetricKeyEncrypted:
-                       // This packet contains the decryption key encrypted with a passphrase.
-                       md.IsSymmetricallyEncrypted = true
-                       symKeys = append(symKeys, p)
-               case *packet.EncryptedKey:
-                       // This packet contains the decryption key encrypted to a public key.
-                       md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
-                       switch p.Algo {
-                       case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
-                               break
-                       default:
-                               continue
-                       }
-                       var keys []Key
-                       if p.KeyId == 0 {
-                               keys = keyring.DecryptionKeys()
-                       } else {
-                               keys = keyring.KeysById(p.KeyId)
-                       }
-                       for _, k := range keys {
-                               pubKeys = append(pubKeys, keyEnvelopePair{k, p})
-                       }
-               case *packet.SymmetricallyEncrypted:
-                       se = p
-                       break ParsePackets
-               case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
-                       // This message isn't encrypted.
-                       if len(symKeys) != 0 || len(pubKeys) != 0 {
-                               return nil, errors.StructuralError("key material not followed by encrypted message")
-                       }
-                       packets.Unread(p)
-                       return readSignedMessage(packets, nil, keyring)
-               }
-       }
-
-       var candidates []Key
-       var decrypted io.ReadCloser
-
-       // Now that we have the list of encrypted keys we need to decrypt at
-       // least one of them or, if we cannot, we need to call the prompt
-       // function so that it can decrypt a key or give us a passphrase.
-FindKey:
-       for {
-               // See if any of the keys already have a private key available
-               candidates = candidates[:0]
-               candidateFingerprints := make(map[string]bool)
-
-               for _, pk := range pubKeys {
-                       if pk.key.PrivateKey == nil {
-                               continue
-                       }
-                       if !pk.key.PrivateKey.Encrypted {
-                               if len(pk.encryptedKey.Key) == 0 {
-                                       pk.encryptedKey.Decrypt(pk.key.PrivateKey)
-                               }
-                               if len(pk.encryptedKey.Key) == 0 {
-                                       continue
-                               }
-                               decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
-                               if err != nil && err != errors.KeyIncorrectError {
-                                       return nil, err
-                               }
-                               if decrypted != nil {
-                                       md.DecryptedWith = pk.key
-                                       break FindKey
-                               }
-                       } else {
-                               fpr := string(pk.key.PublicKey.Fingerprint[:])
-                               if v := candidateFingerprints[fpr]; v {
-                                       continue
-                               }
-                               candidates = append(candidates, pk.key)
-                               candidateFingerprints[fpr] = true
-                       }
-               }
-
-               if len(candidates) == 0 && len(symKeys) == 0 {
-                       return nil, errors.KeyIncorrectError
-               }
-
-               if prompt == nil {
-                       return nil, errors.KeyIncorrectError
-               }
-
-               passphrase, err := prompt(candidates, len(symKeys) != 0)
-               if err != nil {
-                       return nil, err
-               }
-
-               // Try the symmetric passphrase first
-               if len(symKeys) != 0 && passphrase != nil {
-                       for _, s := range symKeys {
-                               err = s.Decrypt(passphrase)
-                               if err == nil && !s.Encrypted {
-                                       decrypted, err = se.Decrypt(s.CipherFunc, s.Key)
-                                       if err != nil && err != errors.KeyIncorrectError {
-                                               return nil, err
-                                       }
-                                       if decrypted != nil {
-                                               break FindKey
-                                       }
-                               }
-
-                       }
-               }
-       }
-
-       md.decrypted = decrypted
-       packets.Push(decrypted)
-       return readSignedMessage(packets, md, keyring)
-}
-
-// readSignedMessage reads a possibly signed message if mdin is non-zero then
-// that structure is updated and returned. Otherwise a fresh MessageDetails is
-// used.
-func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
-       if mdin == nil {
-               mdin = new(MessageDetails)
-       }
-       md = mdin
-
-       var p packet.Packet
-       var h hash.Hash
-       var wrappedHash hash.Hash
-FindLiteralData:
-       for {
-               p, err = packets.Next()
-               if err != nil {
-                       return nil, err
-               }
-               switch p := p.(type) {
-               case *packet.Compressed:
-                       packets.Push(p.Body)
-               case *packet.OnePassSignature:
-                       if !p.IsLast {
-                               return nil, errors.UnsupportedError("nested signatures")
-                       }
-
-                       h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
-                       if err != nil {
-                               md = nil
-                               return
-                       }
-
-                       md.IsSigned = true
-                       md.SignedByKeyId = p.KeyId
-                       keys := keyring.KeysById(p.KeyId)
-                       for i, key := range keys {
-                               if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
-                                       continue
-                               }
-                               md.SignedBy = &keys[i]
-                               break
-                       }
-               case *packet.LiteralData:
-                       md.LiteralData = p
-                       break FindLiteralData
-               }
-       }
-
-       if md.SignedBy != nil {
-               md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
-       } else if md.decrypted != nil {
-               md.UnverifiedBody = checkReader{md}
-       } else {
-               md.UnverifiedBody = md.LiteralData.Body
-       }
-
-       return md, nil
-}
-
-// hashForSignature returns a pair of hashes that can be used to verify a
-// signature. The signature may specify that the contents of the signed message
-// should be preprocessed (i.e. to normalize line endings). Thus this function
-// returns two hashes. The second should be used to hash the message itself and
-// performs any needed preprocessing.
-func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
-       h := hashId.New()
-       if h == nil {
-               return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
-       }
-
-       switch sigType {
-       case packet.SigTypeBinary:
-               return h, h, nil
-       case packet.SigTypeText:
-               return h, NewCanonicalTextHash(h), nil
-       }
-
-       return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
-}
-
-// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
-// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
-// MDC checks.
-type checkReader struct {
-       md *MessageDetails
-}
-
-func (cr checkReader) Read(buf []byte) (n int, err error) {
-       n, err = cr.md.LiteralData.Body.Read(buf)
-       if err == io.EOF {
-               mdcErr := cr.md.decrypted.Close()
-               if mdcErr != nil {
-                       err = mdcErr
-               }
-       }
-       return
-}
-
-// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
-// the data as it is read. When it sees an EOF from the underlying io.Reader
-// it parses and checks a trailing Signature packet and triggers any MDC checks.
-type signatureCheckReader struct {
-       packets        *packet.Reader
-       h, wrappedHash hash.Hash
-       md             *MessageDetails
-}
-
-func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
-       n, err = scr.md.LiteralData.Body.Read(buf)
-       scr.wrappedHash.Write(buf[:n])
-       if err == io.EOF {
-               var p packet.Packet
-               p, scr.md.SignatureError = scr.packets.Next()
-               if scr.md.SignatureError != nil {
-                       return
-               }
-
-               var ok bool
-               if scr.md.Signature, ok = p.(*packet.Signature); !ok {
-                       scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
-                       return
-               }
-
-               scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
-
-               // The SymmetricallyEncrypted packet, if any, might have an
-               // unsigned hash of its own. In order to check this we need to
-               // close that Reader.
-               if scr.md.decrypted != nil {
-                       mdcErr := scr.md.decrypted.Close()
-                       if mdcErr != nil {
-                               err = mdcErr
-                       }
-               }
-       }
-       return
-}
-
-// CheckDetachedSignature takes a signed file and a detached signature and
-// returns the signer if the signature is valid. If the signer isn't know,
-// UnknownIssuerError is returned.
-func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
-       p, err := packet.Read(signature)
-       if err != nil {
-               return
-       }
-
-       sig, ok := p.(*packet.Signature)
-       if !ok {
-               return nil, errors.StructuralError("non signature packet found")
-       }
-
-       if sig.IssuerKeyId == nil {
-               return nil, errors.StructuralError("signature doesn't have an issuer")
-       }
-
-       keys := keyring.KeysById(*sig.IssuerKeyId)
-       if len(keys) == 0 {
-               return nil, errors.UnknownIssuerError
-       }
-
-       h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
-       if err != nil {
-               return
-       }
-
-       _, err = io.Copy(wrappedHash, signed)
-       if err != nil && err != io.EOF {
-               return
-       }
-
-       for _, key := range keys {
-               if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
-                       continue
-               }
-               err = key.PublicKey.VerifySignature(h, sig)
-               if err == nil {
-                       return key.Entity, nil
-               }
-       }
-
-       if err != nil {
-               return
-       }
-
-       return nil, errors.UnknownIssuerError
-}
-
-// CheckArmoredDetachedSignature performs the same actions as
-// CheckDetachedSignature but expects the signature to be armored.
-func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
-       body, err := readArmored(signature, SignatureType)
-       if err != nil {
-               return
-       }
-
-       return CheckDetachedSignature(keyring, signed, body)
-}
diff --git a/libgo/go/crypto/openpgp/read_test.go b/libgo/go/crypto/openpgp/read_test.go
deleted file mode 100644 (file)
index d1ecad3..0000000
+++ /dev/null
@@ -1,372 +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 openpgp
-
-import (
-       "bytes"
-       "crypto/openpgp/errors"
-       _ "crypto/sha512"
-       "encoding/hex"
-       "io"
-       "io/ioutil"
-       "testing"
-)
-
-func readerFromHex(s string) io.Reader {
-       data, err := hex.DecodeString(s)
-       if err != nil {
-               panic("readerFromHex: bad input")
-       }
-       return bytes.NewBuffer(data)
-}
-
-func TestReadKeyRing(t *testing.T) {
-       kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-       if err != nil {
-               t.Error(err)
-               return
-       }
-       if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B {
-               t.Errorf("bad keyring: %#v", kring)
-       }
-}
-
-func TestRereadKeyRing(t *testing.T) {
-       kring, err := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-       if err != nil {
-               t.Errorf("error in initial parse: %s", err)
-               return
-       }
-       out := new(bytes.Buffer)
-       err = kring[0].Serialize(out)
-       if err != nil {
-               t.Errorf("error in serialization: %s", err)
-               return
-       }
-       kring, err = ReadKeyRing(out)
-       if err != nil {
-               t.Errorf("error in second parse: %s", err)
-               return
-       }
-
-       if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB {
-               t.Errorf("bad keyring: %#v", kring)
-       }
-}
-
-func TestReadPrivateKeyRing(t *testing.T) {
-       kring, err := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-       if err != nil {
-               t.Error(err)
-               return
-       }
-       if len(kring) != 2 || uint32(kring[0].PrimaryKey.KeyId) != 0xC20C31BB || uint32(kring[1].PrimaryKey.KeyId) != 0x1E35246B || kring[0].PrimaryKey == nil {
-               t.Errorf("bad keyring: %#v", kring)
-       }
-}
-
-func TestReadDSAKey(t *testing.T) {
-       kring, err := ReadKeyRing(readerFromHex(dsaTestKeyHex))
-       if err != nil {
-               t.Error(err)
-               return
-       }
-       if len(kring) != 1 || uint32(kring[0].PrimaryKey.KeyId) != 0x0CCC0360 {
-               t.Errorf("bad parse: %#v", kring)
-       }
-}
-
-func TestDSAHashTruncatation(t *testing.T) {
-       // dsaKeyWithSHA512 was generated with GnuPG and --cert-digest-algo
-       // SHA512 in order to require DSA hash truncation to verify correctly.
-       _, err := ReadKeyRing(readerFromHex(dsaKeyWithSHA512))
-       if err != nil {
-               t.Error(err)
-       }
-}
-
-func TestGetKeyById(t *testing.T) {
-       kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-
-       keys := kring.KeysById(0xa34d7e18c20c31bb)
-       if len(keys) != 1 || keys[0].Entity != kring[0] {
-               t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
-       }
-
-       keys = kring.KeysById(0xfd94408d4543314f)
-       if len(keys) != 1 || keys[0].Entity != kring[0] {
-               t.Errorf("bad result for 0xa34d7e18c20c31bb: %#v", keys)
-       }
-}
-
-func checkSignedMessage(t *testing.T, signedHex, expected string) {
-       kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-
-       md, err := ReadMessage(readerFromHex(signedHex), kring, nil)
-       if err != nil {
-               t.Error(err)
-               return
-       }
-
-       if !md.IsSigned || md.SignedByKeyId != 0xa34d7e18c20c31bb || md.SignedBy == nil || md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) != 0 || md.IsSymmetricallyEncrypted {
-               t.Errorf("bad MessageDetails: %#v", md)
-       }
-
-       contents, err := ioutil.ReadAll(md.UnverifiedBody)
-       if err != nil {
-               t.Errorf("error reading UnverifiedBody: %s", err)
-       }
-       if string(contents) != expected {
-               t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
-       }
-       if md.SignatureError != nil || md.Signature == nil {
-               t.Errorf("failed to validate: %s", md.SignatureError)
-       }
-}
-
-func TestSignedMessage(t *testing.T) {
-       checkSignedMessage(t, signedMessageHex, signedInput)
-}
-
-func TestTextSignedMessage(t *testing.T) {
-       checkSignedMessage(t, signedTextMessageHex, signedTextInput)
-}
-
-var signedEncryptedMessageTests = []struct {
-       keyRingHex       string
-       messageHex       string
-       signedByKeyId    uint64
-       encryptedToKeyId uint64
-}{
-       {
-               testKeys1And2PrivateHex,
-               signedEncryptedMessageHex,
-               0xa34d7e18c20c31bb,
-               0x2a67d68660df41c7,
-       },
-       {
-               dsaElGamalTestKeysHex,
-               signedEncryptedMessage2Hex,
-               0x33af447ccd759b09,
-               0xcf6a7abcd43e3673,
-       },
-}
-
-func TestSignedEncryptedMessage(t *testing.T) {
-       for i, test := range signedEncryptedMessageTests {
-               expected := "Signed and encrypted message\n"
-               kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
-               prompt := func(keys []Key, symmetric bool) ([]byte, error) {
-                       if symmetric {
-                               t.Errorf("prompt: message was marked as symmetrically encrypted")
-                               return nil, errors.KeyIncorrectError
-                       }
-
-                       if len(keys) == 0 {
-                               t.Error("prompt: no keys requested")
-                               return nil, errors.KeyIncorrectError
-                       }
-
-                       err := keys[0].PrivateKey.Decrypt([]byte("passphrase"))
-                       if err != nil {
-                               t.Errorf("prompt: error decrypting key: %s", err)
-                               return nil, errors.KeyIncorrectError
-                       }
-
-                       return nil, nil
-               }
-
-               md, err := ReadMessage(readerFromHex(test.messageHex), kring, prompt)
-               if err != nil {
-                       t.Errorf("#%d: error reading message: %s", i, err)
-                       return
-               }
-
-               if !md.IsSigned || md.SignedByKeyId != test.signedByKeyId || md.SignedBy == nil || !md.IsEncrypted || md.IsSymmetricallyEncrypted || len(md.EncryptedToKeyIds) == 0 || md.EncryptedToKeyIds[0] != test.encryptedToKeyId {
-                       t.Errorf("#%d: bad MessageDetails: %#v", i, md)
-               }
-
-               contents, err := ioutil.ReadAll(md.UnverifiedBody)
-               if err != nil {
-                       t.Errorf("#%d: error reading UnverifiedBody: %s", i, err)
-               }
-               if string(contents) != expected {
-                       t.Errorf("#%d: bad UnverifiedBody got:%s want:%s", i, string(contents), expected)
-               }
-
-               if md.SignatureError != nil || md.Signature == nil {
-                       t.Errorf("#%d: failed to validate: %s", i, md.SignatureError)
-               }
-       }
-}
-
-func TestUnspecifiedRecipient(t *testing.T) {
-       expected := "Recipient unspecified\n"
-       kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-
-       md, err := ReadMessage(readerFromHex(recipientUnspecifiedHex), kring, nil)
-       if err != nil {
-               t.Errorf("error reading message: %s", err)
-               return
-       }
-
-       contents, err := ioutil.ReadAll(md.UnverifiedBody)
-       if err != nil {
-               t.Errorf("error reading UnverifiedBody: %s", err)
-       }
-       if string(contents) != expected {
-               t.Errorf("bad UnverifiedBody got:%s want:%s", string(contents), expected)
-       }
-}
-
-func TestSymmetricallyEncrypted(t *testing.T) {
-       expected := "Symmetrically encrypted.\n"
-
-       prompt := func(keys []Key, symmetric bool) ([]byte, error) {
-               if len(keys) != 0 {
-                       t.Errorf("prompt: len(keys) = %d (want 0)", len(keys))
-               }
-
-               if !symmetric {
-                       t.Errorf("symmetric is not set")
-               }
-
-               return []byte("password"), nil
-       }
-
-       md, err := ReadMessage(readerFromHex(symmetricallyEncryptedCompressedHex), nil, prompt)
-       if err != nil {
-               t.Errorf("ReadMessage: %s", err)
-               return
-       }
-
-       contents, err := ioutil.ReadAll(md.UnverifiedBody)
-       if err != nil {
-               t.Errorf("ReadAll: %s", err)
-       }
-
-       expectedCreationTime := uint32(1295992998)
-       if md.LiteralData.Time != expectedCreationTime {
-               t.Errorf("LiteralData.Time is %d, want %d", md.LiteralData.Time, expectedCreationTime)
-       }
-
-       if string(contents) != expected {
-               t.Errorf("contents got: %s want: %s", string(contents), expected)
-       }
-}
-
-func testDetachedSignature(t *testing.T, kring KeyRing, signature io.Reader, sigInput, tag string, expectedSignerKeyId uint64) {
-       signed := bytes.NewBufferString(sigInput)
-       signer, err := CheckDetachedSignature(kring, signed, signature)
-       if err != nil {
-               t.Errorf("%s: signature error: %s", tag, err)
-               return
-       }
-       if signer == nil {
-               t.Errorf("%s: signer is nil", tag)
-               return
-       }
-       if signer.PrimaryKey.KeyId != expectedSignerKeyId {
-               t.Errorf("%s: wrong signer got:%x want:%x", tag, signer.PrimaryKey.KeyId, expectedSignerKeyId)
-       }
-}
-
-func TestDetachedSignature(t *testing.T) {
-       kring, _ := ReadKeyRing(readerFromHex(testKeys1And2Hex))
-       testDetachedSignature(t, kring, readerFromHex(detachedSignatureHex), signedInput, "binary", testKey1KeyId)
-       testDetachedSignature(t, kring, readerFromHex(detachedSignatureTextHex), signedInput, "text", testKey1KeyId)
-}
-
-func TestDetachedSignatureDSA(t *testing.T) {
-       kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyHex))
-       testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
-}
-
-func TestReadingArmoredPrivateKey(t *testing.T) {
-       el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
-       if err != nil {
-               t.Error(err)
-       }
-       if len(el) != 1 {
-               t.Errorf("got %d entities, wanted 1\n", len(el))
-       }
-}
-
-func TestNoArmoredData(t *testing.T) {
-       _, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
-       if _, ok := err.(errors.InvalidArgumentError); !ok {
-               t.Errorf("error was not an InvalidArgumentError: %s", err)
-       }
-}
-
-const testKey1KeyId = 0xA34D7E18C20C31BB
-const testKey3KeyId = 0x338934250CCC0360
-
-const signedInput = "Signed message\nline 2\nline 3\n"
-const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
-
-const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
-
-const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
-
-const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
-
-const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83"
-
-const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
-
-const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
-
-const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
-
-const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
-
-const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
-
-const signedEncryptedMessageHex = "848c032a67d68660df41c70103ff5789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8d2c03b018bd210b1d3791e1aba74b0f1034e122ab72e760492c192383cf5e20b5628bd043272d63df9b923f147eb6091cd897553204832aba48fec54aa447547bb16305a1024713b90e77fd0065f1918271947549205af3c74891af22ee0b56cd29bfec6d6e351901cd4ab3ece7c486f1e32a792d4e474aed98ee84b3f591c7dff37b64e0ecd68fd036d517e412dcadf85840ce184ad7921ad446c4ee28db80447aea1ca8d4f574db4d4e37688158ddd19e14ee2eab4873d46947d65d14a23e788d912cf9a19624ca7352469b72a83866b7c23cb5ace3deab3c7018061b0ba0f39ed2befe27163e5083cf9b8271e3e3d52cc7ad6e2a3bd81d4c3d7022f8d"
-
-const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3"
-
-const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f714339e13de5a79881216431925bf67ee2898ea61815f07894cd0703c50d0a76ef64d482196f47a8bc729af9b80bb6"
-
-const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
-
-const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
-
-const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
-Version: GnuPG v1.4.10 (GNU/Linux)
-
-lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
-idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
-vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
-AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
-0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
-IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
-VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
-gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
-TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
-q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
-dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
-CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
-ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
-eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
-AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
-bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
-/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
-A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
-TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
-lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
-rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
-oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
-QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
-nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
-AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
-BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
-AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
-VrM0m72/jnpKo04=
-=zNCn
------END PGP PRIVATE KEY BLOCK-----`
-
-const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
diff --git a/libgo/go/crypto/openpgp/s2k/s2k.go b/libgo/go/crypto/openpgp/s2k/s2k.go
deleted file mode 100644 (file)
index 39479a1..0000000
+++ /dev/null
@@ -1,183 +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 s2k implements the various OpenPGP string-to-key transforms as
-// specified in RFC 4800 section 3.7.1.
-package s2k
-
-import (
-       "crypto"
-       "crypto/openpgp/errors"
-       "hash"
-       "io"
-       "strconv"
-)
-
-// Simple writes to out the result of computing the Simple S2K function (RFC
-// 4880, section 3.7.1.1) using the given hash and input passphrase.
-func Simple(out []byte, h hash.Hash, in []byte) {
-       Salted(out, h, in, nil)
-}
-
-var zero [1]byte
-
-// Salted writes to out the result of computing the Salted S2K function (RFC
-// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
-func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
-       done := 0
-       var digest []byte
-
-       for i := 0; done < len(out); i++ {
-               h.Reset()
-               for j := 0; j < i; j++ {
-                       h.Write(zero[:])
-               }
-               h.Write(salt)
-               h.Write(in)
-               digest = h.Sum(digest[:0])
-               n := copy(out[done:], digest)
-               done += n
-       }
-}
-
-// Iterated writes to out the result of computing the Iterated and Salted S2K
-// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
-// salt and iteration count.
-func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
-       combined := make([]byte, len(in)+len(salt))
-       copy(combined, salt)
-       copy(combined[len(salt):], in)
-
-       if count < len(combined) {
-               count = len(combined)
-       }
-
-       done := 0
-       var digest []byte
-       for i := 0; done < len(out); i++ {
-               h.Reset()
-               for j := 0; j < i; j++ {
-                       h.Write(zero[:])
-               }
-               written := 0
-               for written < count {
-                       if written+len(combined) > count {
-                               todo := count - written
-                               h.Write(combined[:todo])
-                               written = count
-                       } else {
-                               h.Write(combined)
-                               written += len(combined)
-                       }
-               }
-               digest = h.Sum(digest[:0])
-               n := copy(out[done:], digest)
-               done += n
-       }
-}
-
-// Parse reads a binary specification for a string-to-key transformation from r
-// and returns a function which performs that transform.
-func Parse(r io.Reader) (f func(out, in []byte), err error) {
-       var buf [9]byte
-
-       _, err = io.ReadFull(r, buf[:2])
-       if err != nil {
-               return
-       }
-
-       hash, ok := HashIdToHash(buf[1])
-       if !ok {
-               return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
-       }
-       h := hash.New()
-       if h == nil {
-               return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
-       }
-
-       switch buf[0] {
-       case 1:
-               f := func(out, in []byte) {
-                       Simple(out, h, in)
-               }
-               return f, nil
-       case 2:
-               _, err = io.ReadFull(r, buf[:8])
-               if err != nil {
-                       return
-               }
-               f := func(out, in []byte) {
-                       Salted(out, h, in, buf[:8])
-               }
-               return f, nil
-       case 3:
-               _, err = io.ReadFull(r, buf[:9])
-               if err != nil {
-                       return
-               }
-               count := (16 + int(buf[8]&15)) << (uint32(buf[8]>>4) + 6)
-               f := func(out, in []byte) {
-                       Iterated(out, h, in, buf[:8], count)
-               }
-               return f, nil
-       }
-
-       return nil, errors.UnsupportedError("S2K function")
-}
-
-// Serialize salts and stretches the given passphrase and writes the resulting
-// key into key. It also serializes an S2K descriptor to w.
-func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte) error {
-       var buf [11]byte
-       buf[0] = 3 /* iterated and salted */
-       buf[1], _ = HashToHashId(crypto.SHA1)
-       salt := buf[2:10]
-       if _, err := io.ReadFull(rand, salt); err != nil {
-               return err
-       }
-       const count = 65536 // this is the default in gpg
-       buf[10] = 96        // 65536 iterations
-       if _, err := w.Write(buf[:]); err != nil {
-               return err
-       }
-
-       Iterated(key, crypto.SHA1.New(), passphrase, salt, count)
-       return nil
-}
-
-// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
-// Go's crypto.Hash type. See RFC 4880, section 9.4.
-var hashToHashIdMapping = []struct {
-       id   byte
-       hash crypto.Hash
-}{
-       {1, crypto.MD5},
-       {2, crypto.SHA1},
-       {3, crypto.RIPEMD160},
-       {8, crypto.SHA256},
-       {9, crypto.SHA384},
-       {10, crypto.SHA512},
-       {11, crypto.SHA224},
-}
-
-// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
-// hash id.
-func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
-       for _, m := range hashToHashIdMapping {
-               if m.id == id {
-                       return m.hash, true
-               }
-       }
-       return 0, false
-}
-
-// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
-func HashToHashId(h crypto.Hash) (id byte, ok bool) {
-       for _, m := range hashToHashIdMapping {
-               if m.hash == h {
-                       return m.id, true
-               }
-       }
-       return 0, false
-}
diff --git a/libgo/go/crypto/openpgp/s2k/s2k_test.go b/libgo/go/crypto/openpgp/s2k/s2k_test.go
deleted file mode 100644 (file)
index 3a094a1..0000000
+++ /dev/null
@@ -1,118 +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 s2k
-
-import (
-       "bytes"
-       "crypto/rand"
-       "crypto/sha1"
-       "encoding/hex"
-       "testing"
-)
-
-var saltedTests = []struct {
-       in, out string
-}{
-       {"hello", "10295ac1"},
-       {"world", "ac587a5e"},
-       {"foo", "4dda8077"},
-       {"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
-       {"x", "f1d3f289"},
-       {"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
-}
-
-func TestSalted(t *testing.T) {
-       h := sha1.New()
-       salt := [4]byte{1, 2, 3, 4}
-
-       for i, test := range saltedTests {
-               expected, _ := hex.DecodeString(test.out)
-               out := make([]byte, len(expected))
-               Salted(out, h, []byte(test.in), salt[:])
-               if !bytes.Equal(expected, out) {
-                       t.Errorf("#%d, got: %x want: %x", i, out, expected)
-               }
-       }
-}
-
-var iteratedTests = []struct {
-       in, out string
-}{
-       {"hello", "83126105"},
-       {"world", "6fa317f9"},
-       {"foo", "8fbc35b9"},
-       {"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
-       {"x", "5a684dfe"},
-       {"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
-}
-
-func TestIterated(t *testing.T) {
-       h := sha1.New()
-       salt := [4]byte{4, 3, 2, 1}
-
-       for i, test := range iteratedTests {
-               expected, _ := hex.DecodeString(test.out)
-               out := make([]byte, len(expected))
-               Iterated(out, h, []byte(test.in), salt[:], 31)
-               if !bytes.Equal(expected, out) {
-                       t.Errorf("#%d, got: %x want: %x", i, out, expected)
-               }
-       }
-}
-
-var parseTests = []struct {
-       spec, in, out string
-}{
-       /* Simple with SHA1 */
-       {"0102", "hello", "aaf4c61d"},
-       /* Salted with SHA1 */
-       {"02020102030405060708", "hello", "f4f7d67e"},
-       /* Iterated with SHA1 */
-       {"03020102030405060708f1", "hello", "f2a57b7c"},
-}
-
-func TestParse(t *testing.T) {
-       for i, test := range parseTests {
-               spec, _ := hex.DecodeString(test.spec)
-               buf := bytes.NewBuffer(spec)
-               f, err := Parse(buf)
-               if err != nil {
-                       t.Errorf("%d: Parse returned error: %s", i, err)
-                       continue
-               }
-
-               expected, _ := hex.DecodeString(test.out)
-               out := make([]byte, len(expected))
-               f(out, []byte(test.in))
-               if !bytes.Equal(out, expected) {
-                       t.Errorf("%d: output got: %x want: %x", i, out, expected)
-               }
-               if testing.Short() {
-                       break
-               }
-       }
-}
-
-func TestSerialize(t *testing.T) {
-       buf := bytes.NewBuffer(nil)
-       key := make([]byte, 16)
-       passphrase := []byte("testing")
-       err := Serialize(buf, key, rand.Reader, passphrase)
-       if err != nil {
-               t.Errorf("failed to serialize: %s", err)
-               return
-       }
-
-       f, err := Parse(buf)
-       if err != nil {
-               t.Errorf("failed to reparse: %s", err)
-               return
-       }
-       key2 := make([]byte, len(key))
-       f(key2, passphrase)
-       if !bytes.Equal(key2, key) {
-               t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2)
-       }
-}
diff --git a/libgo/go/crypto/openpgp/write.go b/libgo/go/crypto/openpgp/write.go
deleted file mode 100644 (file)
index 73daa11..0000000
+++ /dev/null
@@ -1,315 +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 openpgp
-
-import (
-       "crypto"
-       "crypto/openpgp/armor"
-       "crypto/openpgp/errors"
-       "crypto/openpgp/packet"
-       "crypto/openpgp/s2k"
-       "crypto/rand"
-       _ "crypto/sha256"
-       "hash"
-       "io"
-       "strconv"
-       "time"
-)
-
-// DetachSign signs message with the private key from signer (which must
-// already have been decrypted) and writes the signature to w.
-func DetachSign(w io.Writer, signer *Entity, message io.Reader) error {
-       return detachSign(w, signer, message, packet.SigTypeBinary)
-}
-
-// ArmoredDetachSign signs message with the private key from signer (which
-// must already have been decrypted) and writes an armored signature to w.
-func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader) (err error) {
-       return armoredDetachSign(w, signer, message, packet.SigTypeBinary)
-}
-
-// DetachSignText signs message (after canonicalising the line endings) with
-// the private key from signer (which must already have been decrypted) and
-// writes the signature to w.
-func DetachSignText(w io.Writer, signer *Entity, message io.Reader) error {
-       return detachSign(w, signer, message, packet.SigTypeText)
-}
-
-// ArmoredDetachSignText signs message (after canonicalising the line endings)
-// with the private key from signer (which must already have been decrypted)
-// and writes an armored signature to w.
-func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader) error {
-       return armoredDetachSign(w, signer, message, packet.SigTypeText)
-}
-
-func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err error) {
-       out, err := armor.Encode(w, SignatureType, nil)
-       if err != nil {
-               return
-       }
-       err = detachSign(out, signer, message, sigType)
-       if err != nil {
-               return
-       }
-       return out.Close()
-}
-
-func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err error) {
-       if signer.PrivateKey == nil {
-               return errors.InvalidArgumentError("signing key doesn't have a private key")
-       }
-       if signer.PrivateKey.Encrypted {
-               return errors.InvalidArgumentError("signing key is encrypted")
-       }
-
-       sig := new(packet.Signature)
-       sig.SigType = sigType
-       sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
-       sig.Hash = crypto.SHA256
-       sig.CreationTime = time.Now()
-       sig.IssuerKeyId = &signer.PrivateKey.KeyId
-
-       h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
-       if err != nil {
-               return
-       }
-       io.Copy(wrappedHash, message)
-
-       err = sig.Sign(rand.Reader, h, signer.PrivateKey)
-       if err != nil {
-               return
-       }
-
-       return sig.Serialize(w)
-}
-
-// FileHints contains metadata about encrypted files. This metadata is, itself,
-// encrypted.
-type FileHints struct {
-       // IsBinary can be set to hint that the contents are binary data.
-       IsBinary bool
-       // FileName hints at the name of the file that should be written. It's
-       // truncated to 255 bytes if longer. It may be empty to suggest that the
-       // file should not be written to disk. It may be equal to "_CONSOLE" to
-       // suggest the data should not be written to disk.
-       FileName string
-       // ModTime contains the modification time of the file, or the zero time if not applicable.
-       ModTime time.Time
-}
-
-// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
-// The resulting WriteCloser must be closed after the contents of the file have
-// been written.
-func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints) (plaintext io.WriteCloser, err error) {
-       if hints == nil {
-               hints = &FileHints{}
-       }
-
-       key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, rand.Reader, passphrase, packet.CipherAES128)
-       if err != nil {
-               return
-       }
-       w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, packet.CipherAES128, key)
-       if err != nil {
-               return
-       }
-       var epochSeconds uint32
-       if !hints.ModTime.IsZero() {
-               epochSeconds = uint32(hints.ModTime.Unix())
-       }
-       return packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
-}
-
-// intersectPreferences mutates and returns a prefix of a that contains only
-// the values in the intersection of a and b. The order of a is preserved.
-func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
-       var j int
-       for _, v := range a {
-               for _, v2 := range b {
-                       if v == v2 {
-                               a[j] = v
-                               j++
-                               break
-                       }
-               }
-       }
-
-       return a[:j]
-}
-
-func hashToHashId(h crypto.Hash) uint8 {
-       v, ok := s2k.HashToHashId(h)
-       if !ok {
-               panic("tried to convert unknown hash")
-       }
-       return v
-}
-
-// Encrypt encrypts a message to a number of recipients and, optionally, signs
-// it. hints contains optional information, that is also encrypted, that aids
-// the recipients in processing the message. The resulting WriteCloser must
-// be closed after the contents of the file have been written.
-func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints) (plaintext io.WriteCloser, err error) {
-       var signer *packet.PrivateKey
-       if signed != nil {
-               signer = signed.signingKey().PrivateKey
-               if signer == nil || signer.Encrypted {
-                       return nil, errors.InvalidArgumentError("signing key must be decrypted")
-               }
-       }
-
-       // These are the possible ciphers that we'll use for the message.
-       candidateCiphers := []uint8{
-               uint8(packet.CipherAES128),
-               uint8(packet.CipherAES256),
-               uint8(packet.CipherCAST5),
-       }
-       // These are the possible hash functions that we'll use for the signature.
-       candidateHashes := []uint8{
-               hashToHashId(crypto.SHA256),
-               hashToHashId(crypto.SHA512),
-               hashToHashId(crypto.SHA1),
-               hashToHashId(crypto.RIPEMD160),
-       }
-       // In the event that a recipient doesn't specify any supported ciphers
-       // or hash functions, these are the ones that we assume that every
-       // implementation supports.
-       defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
-       defaultHashes := candidateHashes[len(candidateHashes)-1:]
-
-       encryptKeys := make([]Key, len(to))
-       for i := range to {
-               encryptKeys[i] = to[i].encryptionKey()
-               if encryptKeys[i].PublicKey == nil {
-                       return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
-               }
-
-               sig := to[i].primaryIdentity().SelfSignature
-
-               preferredSymmetric := sig.PreferredSymmetric
-               if len(preferredSymmetric) == 0 {
-                       preferredSymmetric = defaultCiphers
-               }
-               preferredHashes := sig.PreferredHash
-               if len(preferredHashes) == 0 {
-                       preferredHashes = defaultHashes
-               }
-               candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
-               candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
-       }
-
-       if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
-               return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
-       }
-
-       cipher := packet.CipherFunction(candidateCiphers[0])
-       hash, _ := s2k.HashIdToHash(candidateHashes[0])
-       symKey := make([]byte, cipher.KeySize())
-       if _, err := io.ReadFull(rand.Reader, symKey); err != nil {
-               return nil, err
-       }
-
-       for _, key := range encryptKeys {
-               if err := packet.SerializeEncryptedKey(ciphertext, rand.Reader, key.PublicKey, cipher, symKey); err != nil {
-                       return nil, err
-               }
-       }
-
-       encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, rand.Reader, cipher, symKey)
-       if err != nil {
-               return
-       }
-
-       if signer != nil {
-               ops := &packet.OnePassSignature{
-                       SigType:    packet.SigTypeBinary,
-                       Hash:       hash,
-                       PubKeyAlgo: signer.PubKeyAlgo,
-                       KeyId:      signer.KeyId,
-                       IsLast:     true,
-               }
-               if err := ops.Serialize(encryptedData); err != nil {
-                       return nil, err
-               }
-       }
-
-       if hints == nil {
-               hints = &FileHints{}
-       }
-
-       w := encryptedData
-       if signer != nil {
-               // If we need to write a signature packet after the literal
-               // data then we need to stop literalData from closing
-               // encryptedData.
-               w = noOpCloser{encryptedData}
-
-       }
-       var epochSeconds uint32
-       if !hints.ModTime.IsZero() {
-               epochSeconds = uint32(hints.ModTime.Unix())
-       }
-       literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
-       if err != nil {
-               return nil, err
-       }
-
-       if signer != nil {
-               return signatureWriter{encryptedData, literalData, hash, hash.New(), signer}, nil
-       }
-       return literalData, nil
-}
-
-// signatureWriter hashes the contents of a message while passing it along to
-// literalData. When closed, it closes literalData, writes a signature packet
-// to encryptedData and then also closes encryptedData.
-type signatureWriter struct {
-       encryptedData io.WriteCloser
-       literalData   io.WriteCloser
-       hashType      crypto.Hash
-       h             hash.Hash
-       signer        *packet.PrivateKey
-}
-
-func (s signatureWriter) Write(data []byte) (int, error) {
-       s.h.Write(data)
-       return s.literalData.Write(data)
-}
-
-func (s signatureWriter) Close() error {
-       sig := &packet.Signature{
-               SigType:      packet.SigTypeBinary,
-               PubKeyAlgo:   s.signer.PubKeyAlgo,
-               Hash:         s.hashType,
-               CreationTime: time.Now(),
-               IssuerKeyId:  &s.signer.KeyId,
-       }
-
-       if err := sig.Sign(rand.Reader, s.h, s.signer); err != nil {
-               return err
-       }
-       if err := s.literalData.Close(); err != nil {
-               return err
-       }
-       if err := sig.Serialize(s.encryptedData); err != nil {
-               return err
-       }
-       return s.encryptedData.Close()
-}
-
-// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
-// TODO: we have two of these in OpenPGP packages alone. This probably needs
-// to be promoted somewhere more common.
-type noOpCloser struct {
-       w io.Writer
-}
-
-func (c noOpCloser) Write(data []byte) (n int, err error) {
-       return c.w.Write(data)
-}
-
-func (c noOpCloser) Close() error {
-       return nil
-}
diff --git a/libgo/go/crypto/openpgp/write_test.go b/libgo/go/crypto/openpgp/write_test.go
deleted file mode 100644 (file)
index 7df02e7..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package openpgp
-
-import (
-       "bytes"
-       "crypto/rand"
-       "io"
-       "io/ioutil"
-       "testing"
-       "time"
-)
-
-func TestSignDetached(t *testing.T) {
-       kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-       out := bytes.NewBuffer(nil)
-       message := bytes.NewBufferString(signedInput)
-       err := DetachSign(out, kring[0], message)
-       if err != nil {
-               t.Error(err)
-       }
-
-       testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
-}
-
-func TestSignTextDetached(t *testing.T) {
-       kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
-       out := bytes.NewBuffer(nil)
-       message := bytes.NewBufferString(signedInput)
-       err := DetachSignText(out, kring[0], message)
-       if err != nil {
-               t.Error(err)
-       }
-
-       testDetachedSignature(t, kring, out, signedInput, "check", testKey1KeyId)
-}
-
-func TestSignDetachedDSA(t *testing.T) {
-       kring, _ := ReadKeyRing(readerFromHex(dsaTestKeyPrivateHex))
-       out := bytes.NewBuffer(nil)
-       message := bytes.NewBufferString(signedInput)
-       err := DetachSign(out, kring[0], message)
-       if err != nil {
-               t.Error(err)
-       }
-
-       testDetachedSignature(t, kring, out, signedInput, "check", testKey3KeyId)
-}
-
-func TestNewEntity(t *testing.T) {
-       if testing.Short() {
-               return
-       }
-
-       e, err := NewEntity(rand.Reader, time.Now(), "Test User", "test", "test@example.com")
-       if err != nil {
-               t.Errorf("failed to create entity: %s", err)
-               return
-       }
-
-       w := bytes.NewBuffer(nil)
-       if err := e.SerializePrivate(w); err != nil {
-               t.Errorf("failed to serialize entity: %s", err)
-               return
-       }
-       serialized := w.Bytes()
-
-       el, err := ReadKeyRing(w)
-       if err != nil {
-               t.Errorf("failed to reparse entity: %s", err)
-               return
-       }
-
-       if len(el) != 1 {
-               t.Errorf("wrong number of entities found, got %d, want 1", len(el))
-       }
-
-       w = bytes.NewBuffer(nil)
-       if err := e.SerializePrivate(w); err != nil {
-               t.Errorf("failed to serialize entity second time: %s", err)
-               return
-       }
-
-       if !bytes.Equal(w.Bytes(), serialized) {
-               t.Errorf("results differed")
-       }
-}
-
-func TestSymmetricEncryption(t *testing.T) {
-       buf := new(bytes.Buffer)
-       plaintext, err := SymmetricallyEncrypt(buf, []byte("testing"), nil)
-       if err != nil {
-               t.Errorf("error writing headers: %s", err)
-               return
-       }
-       message := []byte("hello world\n")
-       _, err = plaintext.Write(message)
-       if err != nil {
-               t.Errorf("error writing to plaintext writer: %s", err)
-       }
-       err = plaintext.Close()
-       if err != nil {
-               t.Errorf("error closing plaintext writer: %s", err)
-       }
-
-       md, err := ReadMessage(buf, nil, func(keys []Key, symmetric bool) ([]byte, error) {
-               return []byte("testing"), nil
-       })
-       if err != nil {
-               t.Errorf("error rereading message: %s", err)
-       }
-       messageBuf := bytes.NewBuffer(nil)
-       _, err = io.Copy(messageBuf, md.UnverifiedBody)
-       if err != nil {
-               t.Errorf("error rereading message: %s", err)
-       }
-       if !bytes.Equal(message, messageBuf.Bytes()) {
-               t.Errorf("recovered message incorrect got '%s', want '%s'", messageBuf.Bytes(), message)
-       }
-}
-
-var testEncryptionTests = []struct {
-       keyRingHex string
-       isSigned   bool
-}{
-       {
-               testKeys1And2PrivateHex,
-               false,
-       },
-       {
-               testKeys1And2PrivateHex,
-               true,
-       },
-       {
-               dsaElGamalTestKeysHex,
-               false,
-       },
-       {
-               dsaElGamalTestKeysHex,
-               true,
-       },
-}
-
-func TestEncryption(t *testing.T) {
-       for i, test := range testEncryptionTests {
-               kring, _ := ReadKeyRing(readerFromHex(test.keyRingHex))
-
-               passphrase := []byte("passphrase")
-               for _, entity := range kring {
-                       if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
-                               err := entity.PrivateKey.Decrypt(passphrase)
-                               if err != nil {
-                                       t.Errorf("#%d: failed to decrypt key", i)
-                               }
-                       }
-                       for _, subkey := range entity.Subkeys {
-                               if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
-                                       err := subkey.PrivateKey.Decrypt(passphrase)
-                                       if err != nil {
-                                               t.Errorf("#%d: failed to decrypt subkey", i)
-                                       }
-                               }
-                       }
-               }
-
-               var signed *Entity
-               if test.isSigned {
-                       signed = kring[0]
-               }
-
-               buf := new(bytes.Buffer)
-               w, err := Encrypt(buf, kring[:1], signed, nil /* no hints */ )
-               if err != nil {
-                       t.Errorf("#%d: error in Encrypt: %s", i, err)
-                       continue
-               }
-
-               const message = "testing"
-               _, err = w.Write([]byte(message))
-               if err != nil {
-                       t.Errorf("#%d: error writing plaintext: %s", i, err)
-                       continue
-               }
-               err = w.Close()
-               if err != nil {
-                       t.Errorf("#%d: error closing WriteCloser: %s", i, err)
-                       continue
-               }
-
-               md, err := ReadMessage(buf, kring, nil /* no prompt */ )
-               if err != nil {
-                       t.Errorf("#%d: error reading message: %s", i, err)
-                       continue
-               }
-
-               if test.isSigned {
-                       expectedKeyId := kring[0].signingKey().PublicKey.KeyId
-                       if md.SignedByKeyId != expectedKeyId {
-                               t.Errorf("#%d: message signed by wrong key id, got: %d, want: %d", i, *md.SignedBy, expectedKeyId)
-                       }
-                       if md.SignedBy == nil {
-                               t.Errorf("#%d: failed to find the signing Entity", i)
-                       }
-               }
-
-               plaintext, err := ioutil.ReadAll(md.UnverifiedBody)
-               if err != nil {
-                       t.Errorf("#%d: error reading encrypted contents: %s", i, err)
-                       continue
-               }
-
-               expectedKeyId := kring[0].encryptionKey().PublicKey.KeyId
-               if len(md.EncryptedToKeyIds) != 1 || md.EncryptedToKeyIds[0] != expectedKeyId {
-                       t.Errorf("#%d: expected message to be encrypted to %v, but got %#v", i, expectedKeyId, md.EncryptedToKeyIds)
-               }
-
-               if string(plaintext) != message {
-                       t.Errorf("#%d: got: %s, want: %s", i, string(plaintext), message)
-               }
-
-               if test.isSigned {
-                       if md.SignatureError != nil {
-                               t.Errorf("#%d: signature error: %s", i, md.SignatureError)
-                       }
-                       if md.Signature == nil {
-                               t.Error("signature missing")
-                       }
-               }
-       }
-}
diff --git a/libgo/go/crypto/ripemd160/ripemd160.go b/libgo/go/crypto/ripemd160/ripemd160.go
deleted file mode 100644 (file)
index da690f0..0000000
+++ /dev/null
@@ -1,120 +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 ripemd160 implements the RIPEMD-160 hash algorithm.
-package ripemd160
-
-// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
-// Preneel with specifications available at:
-// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf.
-
-import (
-       "crypto"
-       "hash"
-)
-
-func init() {
-       crypto.RegisterHash(crypto.RIPEMD160, New)
-}
-
-// The size of the checksum in bytes.
-const Size = 20
-
-// The block size of the hash algorithm in bytes.
-const BlockSize = 64
-
-const (
-       _s0 = 0x67452301
-       _s1 = 0xefcdab89
-       _s2 = 0x98badcfe
-       _s3 = 0x10325476
-       _s4 = 0xc3d2e1f0
-)
-
-// digest represents the partial evaluation of a checksum.
-type digest struct {
-       s  [5]uint32       // running context
-       x  [BlockSize]byte // temporary buffer
-       nx int             // index into x
-       tc uint64          // total count of bytes processed
-}
-
-func (d *digest) Reset() {
-       d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4
-       d.nx = 0
-       d.tc = 0
-}
-
-// New returns a new hash.Hash computing the checksum.
-func New() hash.Hash {
-       result := new(digest)
-       result.Reset()
-       return result
-}
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) BlockSize() int { return BlockSize }
-
-func (d *digest) Write(p []byte) (nn int, err error) {
-       nn = len(p)
-       d.tc += uint64(nn)
-       if d.nx > 0 {
-               n := len(p)
-               if n > BlockSize-d.nx {
-                       n = BlockSize - d.nx
-               }
-               for i := 0; i < n; i++ {
-                       d.x[d.nx+i] = p[i]
-               }
-               d.nx += n
-               if d.nx == BlockSize {
-                       _Block(d, d.x[0:])
-                       d.nx = 0
-               }
-               p = p[n:]
-       }
-       n := _Block(d, p)
-       p = p[n:]
-       if len(p) > 0 {
-               d.nx = copy(d.x[:], p)
-       }
-       return
-}
-
-func (d0 *digest) Sum(in []byte) []byte {
-       // Make a copy of d0 so that caller can keep writing and summing.
-       d := *d0
-
-       // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
-       tc := d.tc
-       var tmp [64]byte
-       tmp[0] = 0x80
-       if tc%64 < 56 {
-               d.Write(tmp[0 : 56-tc%64])
-       } else {
-               d.Write(tmp[0 : 64+56-tc%64])
-       }
-
-       // Length in bits.
-       tc <<= 3
-       for i := uint(0); i < 8; i++ {
-               tmp[i] = byte(tc >> (8 * i))
-       }
-       d.Write(tmp[0:8])
-
-       if d.nx != 0 {
-               panic("d.nx != 0")
-       }
-
-       var digest [Size]byte
-       for i, s := range d.s {
-               digest[i*4] = byte(s)
-               digest[i*4+1] = byte(s >> 8)
-               digest[i*4+2] = byte(s >> 16)
-               digest[i*4+3] = byte(s >> 24)
-       }
-
-       return append(in, digest[:]...)
-}
diff --git a/libgo/go/crypto/ripemd160/ripemd160_test.go b/libgo/go/crypto/ripemd160/ripemd160_test.go
deleted file mode 100644 (file)
index 5df1b25..0000000
+++ /dev/null
@@ -1,64 +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 ripemd160
-
-// Test vectors are from:
-// http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
-
-import (
-       "fmt"
-       "io"
-       "testing"
-)
-
-type mdTest struct {
-       out string
-       in  string
-}
-
-var vectors = [...]mdTest{
-       {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""},
-       {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"},
-       {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"},
-       {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"},
-       {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"},
-       {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
-       {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"},
-       {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"},
-}
-
-func TestVectors(t *testing.T) {
-       for i := 0; i < len(vectors); i++ {
-               tv := vectors[i]
-               md := New()
-               for j := 0; j < 3; j++ {
-                       if j < 2 {
-                               io.WriteString(md, tv.in)
-                       } else {
-                               io.WriteString(md, tv.in[0:len(tv.in)/2])
-                               md.Sum(nil)
-                               io.WriteString(md, tv.in[len(tv.in)/2:])
-                       }
-                       s := fmt.Sprintf("%x", md.Sum(nil))
-                       if s != tv.out {
-                               t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out)
-                       }
-                       md.Reset()
-               }
-       }
-}
-
-func TestMillionA(t *testing.T) {
-       md := New()
-       for i := 0; i < 100000; i++ {
-               io.WriteString(md, "aaaaaaaaaa")
-       }
-       out := "52783243c1697bdbe16d37f97f68f08325dc1528"
-       s := fmt.Sprintf("%x", md.Sum(nil))
-       if s != out {
-               t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out)
-       }
-       md.Reset()
-}
diff --git a/libgo/go/crypto/ripemd160/ripemd160block.go b/libgo/go/crypto/ripemd160/ripemd160block.go
deleted file mode 100644 (file)
index 7bc8e6c..0000000
+++ /dev/null
@@ -1,161 +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.
-
-// RIPEMD-160 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
-package ripemd160
-
-// work buffer indices and roll amounts for one line
-var _n = [80]uint{
-       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-       7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
-       3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
-       1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
-       4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13,
-}
-
-var _r = [80]uint{
-       11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
-       7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
-       11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
-       11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
-       9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6,
-}
-
-// same for the other parallel one
-var n_ = [80]uint{
-       5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
-       6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
-       15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
-       8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
-       12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11,
-}
-
-var r_ = [80]uint{
-       8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
-       9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
-       9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
-       15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
-       8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11,
-}
-
-func _Block(md *digest, p []byte) int {
-       n := 0
-       var x [16]uint32
-       var alpha, beta uint32
-       for len(p) >= BlockSize {
-               a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4]
-               aa, bb, cc, dd, ee := a, b, c, d, e
-               j := 0
-               for i := 0; i < 16; i++ {
-                       x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
-                       j += 4
-               }
-
-               // round 1
-               i := 0
-               for i < 16 {
-                       alpha = a + (b ^ c ^ d) + x[_n[i]]
-                       s := _r[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + e
-                       beta = c<<10 | c>>22
-                       a, b, c, d, e = e, alpha, b, beta, d
-
-                       // parallel line
-                       alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6
-                       s = r_[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + ee
-                       beta = cc<<10 | cc>>22
-                       aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-                       i++
-               }
-
-               // round 2
-               for i < 32 {
-                       alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999
-                       s := _r[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + e
-                       beta = c<<10 | c>>22
-                       a, b, c, d, e = e, alpha, b, beta, d
-
-                       // parallel line
-                       alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124
-                       s = r_[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + ee
-                       beta = cc<<10 | cc>>22
-                       aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-                       i++
-               }
-
-               // round 3
-               for i < 48 {
-                       alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1
-                       s := _r[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + e
-                       beta = c<<10 | c>>22
-                       a, b, c, d, e = e, alpha, b, beta, d
-
-                       // parallel line
-                       alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3
-                       s = r_[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + ee
-                       beta = cc<<10 | cc>>22
-                       aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-                       i++
-               }
-
-               // round 4
-               for i < 64 {
-                       alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc
-                       s := _r[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + e
-                       beta = c<<10 | c>>22
-                       a, b, c, d, e = e, alpha, b, beta, d
-
-                       // parallel line
-                       alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9
-                       s = r_[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + ee
-                       beta = cc<<10 | cc>>22
-                       aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-                       i++
-               }
-
-               // round 5
-               for i < 80 {
-                       alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e
-                       s := _r[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + e
-                       beta = c<<10 | c>>22
-                       a, b, c, d, e = e, alpha, b, beta, d
-
-                       // parallel line
-                       alpha = aa + (bb ^ cc ^ dd) + x[n_[i]]
-                       s = r_[i]
-                       alpha = (alpha<<s | alpha>>(32-s)) + ee
-                       beta = cc<<10 | cc>>22
-                       aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd
-
-                       i++
-               }
-
-               // combine results
-               dd += c + md.s[1]
-               md.s[1] = md.s[2] + d + ee
-               md.s[2] = md.s[3] + e + aa
-               md.s[3] = md.s[4] + a + bb
-               md.s[4] = md.s[0] + b + cc
-               md.s[0] = dd
-
-               p = p[BlockSize:]
-               n += BlockSize
-       }
-       return n
-}
index d00493a5736d466291e3fc9684e5308b94db5571..ee2c3e01795677cd81c79cb9dd860002cd2d5ed7 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build plan9 darwin/nocgo
+// +build plan9 darwin,!cgo
 
 package tls
 
diff --git a/libgo/go/crypto/twofish/twofish.go b/libgo/go/crypto/twofish/twofish.go
deleted file mode 100644 (file)
index 0616e7b..0000000
+++ /dev/null
@@ -1,355 +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 twofish implements Bruce Schneier's Twofish encryption algorithm.
-package twofish
-
-// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
-
-// This code is a port of the LibTom C implementation.
-// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
-// LibTomCrypt is free for all purposes under the public domain.
-// It was heavily inspired by the go blowfish package.
-
-import "strconv"
-
-// BlockSize is the constant block size of Twofish.
-const BlockSize = 16
-
-const mdsPolynomial = 0x169 // x^8 + x^6 + x^5 + x^3 + 1, see [TWOFISH] 4.2
-const rsPolynomial = 0x14d  // x^8 + x^6 + x^3 + x^2 + 1, see [TWOFISH] 4.3
-
-// A Cipher is an instance of Twofish encryption using a particular key.
-type Cipher struct {
-       s [4][256]uint32
-       k [40]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) Error() string {
-       return "crypto/twofish: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a Cipher.
-// The key argument should be the Twofish key, 16, 24 or 32 bytes.
-func NewCipher(key []byte) (*Cipher, error) {
-       keylen := len(key)
-
-       if keylen != 16 && keylen != 24 && keylen != 32 {
-               return nil, KeySizeError(keylen)
-       }
-
-       // k is the number of 64 bit words in key
-       k := keylen / 8
-
-       // Create the S[..] words
-       var S [4 * 4]byte
-       for i := 0; i < k; i++ {
-               // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
-               for j, rsRow := range rs {
-                       for k, rsVal := range rsRow {
-                               S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
-                       }
-               }
-       }
-
-       // Calculate subkeys
-       c := new(Cipher)
-       var tmp [4]byte
-       for i := byte(0); i < 20; i++ {
-               // A = h(p * 2x, Me)
-               for j := range tmp {
-                       tmp[j] = 2 * i
-               }
-               A := h(tmp[:], key, 0)
-
-               // B = rolc(h(p * (2x + 1), Mo), 8)
-               for j := range tmp {
-                       tmp[j] = 2*i + 1
-               }
-               B := h(tmp[:], key, 1)
-               B = rol(B, 8)
-
-               c.k[2*i] = A + B
-
-               // K[2i+1] = (A + 2B) <<< 9
-               c.k[2*i+1] = rol(2*B+A, 9)
-       }
-
-       // Calculate sboxes
-       switch k {
-       case 2:
-               for i := range c.s[0] {
-                       c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
-                       c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
-                       c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
-                       c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
-               }
-       case 3:
-               for i := range c.s[0] {
-                       c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
-                       c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
-                       c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
-                       c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
-               }
-       default:
-               for i := range c.s[0] {
-                       c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
-                       c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
-                       c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
-                       c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][sbox[1][byte(i)]^S[3]]^S[7]]^S[11]]^S[15]], 3)
-               }
-       }
-
-       return c, nil
-}
-
-// Reset zeros the key data, so that it will no longer appear in the process's
-// memory.
-func (c *Cipher) Reset() {
-       for i := range c.k {
-               c.k[i] = 0
-       }
-       for i := range c.s {
-               for j := 0; j < 256; j++ {
-                       c.s[i][j] = 0
-               }
-       }
-}
-
-// BlockSize returns the Twofish block size, 16 bytes.
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// store32l stores src in dst in little-endian form.
-func store32l(dst []byte, src uint32) {
-       dst[0] = byte(src)
-       dst[1] = byte(src >> 8)
-       dst[2] = byte(src >> 16)
-       dst[3] = byte(src >> 24)
-       return
-}
-
-// load32l reads a little-endian uint32 from src.
-func load32l(src []byte) uint32 {
-       return uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24
-}
-
-// rol returns x after a left circular rotation of y bits.
-func rol(x, y uint32) uint32 {
-       return (x << (y & 31)) | (x >> (32 - (y & 31)))
-}
-
-// ror returns x after a right circular rotation of y bits.
-func ror(x, y uint32) uint32 {
-       return (x >> (y & 31)) | (x << (32 - (y & 31)))
-}
-
-// The RS matrix. See [TWOFISH] 4.3
-var rs = [4][8]byte{
-       {0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E},
-       {0xA4, 0x56, 0x82, 0xF3, 0x1E, 0xC6, 0x68, 0xE5},
-       {0x02, 0xA1, 0xFC, 0xC1, 0x47, 0xAE, 0x3D, 0x19},
-       {0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E, 0x03},
-}
-
-// sbox tables
-var sbox = [2][256]byte{
-       {
-               0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
-               0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
-               0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
-               0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
-               0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
-               0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
-               0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
-               0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
-               0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
-               0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
-               0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
-               0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
-               0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
-               0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
-               0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
-               0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0,
-       },
-       {
-               0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
-               0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
-               0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
-               0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
-               0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
-               0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
-               0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
-               0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
-               0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
-               0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
-               0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
-               0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
-               0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
-               0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
-               0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
-               0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91,
-       },
-}
-
-// gfMult returns a·b in GF(2^8)/p
-func gfMult(a, b byte, p uint32) byte {
-       B := [2]uint32{0, uint32(b)}
-       P := [2]uint32{0, p}
-       var result uint32
-
-       // branchless GF multiplier
-       for i := 0; i < 7; i++ {
-               result ^= B[a&1]
-               a >>= 1
-               B[1] = P[B[1]>>7] ^ (B[1] << 1)
-       }
-       result ^= B[a&1]
-       return byte(result)
-}
-
-// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS Â· [x0]
-func mdsColumnMult(in byte, col int) uint32 {
-       mul01 := in
-       mul5B := gfMult(in, 0x5B, mdsPolynomial)
-       mulEF := gfMult(in, 0xEF, mdsPolynomial)
-
-       switch col {
-       case 0:
-               return uint32(mul01) | uint32(mul5B)<<8 | uint32(mulEF)<<16 | uint32(mulEF)<<24
-       case 1:
-               return uint32(mulEF) | uint32(mulEF)<<8 | uint32(mul5B)<<16 | uint32(mul01)<<24
-       case 2:
-               return uint32(mul5B) | uint32(mulEF)<<8 | uint32(mul01)<<16 | uint32(mulEF)<<24
-       case 3:
-               return uint32(mul5B) | uint32(mul01)<<8 | uint32(mulEF)<<16 | uint32(mul5B)<<24
-       }
-
-       panic("unreachable")
-}
-
-// h implements the S-box generation function. See [TWOFISH] 4.3.5
-func h(in, key []byte, offset int) uint32 {
-       var y [4]byte
-       for x := range y {
-               y[x] = in[x]
-       }
-       switch len(key) / 8 {
-       case 4:
-               y[0] = sbox[1][y[0]] ^ key[4*(6+offset)+0]
-               y[1] = sbox[0][y[1]] ^ key[4*(6+offset)+1]
-               y[2] = sbox[0][y[2]] ^ key[4*(6+offset)+2]
-               y[3] = sbox[1][y[3]] ^ key[4*(6+offset)+3]
-               fallthrough
-       case 3:
-               y[0] = sbox[1][y[0]] ^ key[4*(4+offset)+0]
-               y[1] = sbox[1][y[1]] ^ key[4*(4+offset)+1]
-               y[2] = sbox[0][y[2]] ^ key[4*(4+offset)+2]
-               y[3] = sbox[0][y[3]] ^ key[4*(4+offset)+3]
-               fallthrough
-       case 2:
-               y[0] = sbox[1][sbox[0][sbox[0][y[0]]^key[4*(2+offset)+0]]^key[4*(0+offset)+0]]
-               y[1] = sbox[0][sbox[0][sbox[1][y[1]]^key[4*(2+offset)+1]]^key[4*(0+offset)+1]]
-               y[2] = sbox[1][sbox[1][sbox[0][y[2]]^key[4*(2+offset)+2]]^key[4*(0+offset)+2]]
-               y[3] = sbox[0][sbox[1][sbox[1][y[3]]^key[4*(2+offset)+3]]^key[4*(0+offset)+3]]
-       }
-       // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
-       var mdsMult uint32
-       for i := range y {
-               mdsMult ^= mdsColumnMult(y[i], i)
-       }
-       return mdsMult
-}
-
-// Encrypt encrypts a 16-byte block from src to dst, which may overlap.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) {
-       S1 := c.s[0]
-       S2 := c.s[1]
-       S3 := c.s[2]
-       S4 := c.s[3]
-
-       // Load input
-       ia := load32l(src[0:4])
-       ib := load32l(src[4:8])
-       ic := load32l(src[8:12])
-       id := load32l(src[12:16])
-
-       // Pre-whitening
-       ia ^= c.k[0]
-       ib ^= c.k[1]
-       ic ^= c.k[2]
-       id ^= c.k[3]
-
-       for i := 0; i < 8; i++ {
-               k := c.k[8+i*4 : 12+i*4]
-               t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
-               t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
-               ic = ror(ic^(t1+k[0]), 1)
-               id = rol(id, 1) ^ (t2 + t1 + k[1])
-
-               t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
-               t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
-               ia = ror(ia^(t1+k[2]), 1)
-               ib = rol(ib, 1) ^ (t2 + t1 + k[3])
-       }
-
-       // Output with "undo last swap"
-       ta := ic ^ c.k[4]
-       tb := id ^ c.k[5]
-       tc := ia ^ c.k[6]
-       td := ib ^ c.k[7]
-
-       store32l(dst[0:4], ta)
-       store32l(dst[4:8], tb)
-       store32l(dst[8:12], tc)
-       store32l(dst[12:16], td)
-}
-
-// Decrypt decrypts a 16-byte block from src to dst, which may overlap.
-func (c *Cipher) Decrypt(dst, src []byte) {
-       S1 := c.s[0]
-       S2 := c.s[1]
-       S3 := c.s[2]
-       S4 := c.s[3]
-
-       // Load input
-       ta := load32l(src[0:4])
-       tb := load32l(src[4:8])
-       tc := load32l(src[8:12])
-       td := load32l(src[12:16])
-
-       // Undo undo final swap
-       ia := tc ^ c.k[6]
-       ib := td ^ c.k[7]
-       ic := ta ^ c.k[4]
-       id := tb ^ c.k[5]
-
-       for i := 8; i > 0; i-- {
-               k := c.k[4+i*4 : 8+i*4]
-               t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
-               t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
-               ia = rol(ia, 1) ^ (t1 + k[2])
-               ib = ror(ib^(t2+t1+k[3]), 1)
-
-               t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
-               t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
-               ic = rol(ic, 1) ^ (t1 + k[0])
-               id = ror(id^(t2+t1+k[1]), 1)
-       }
-
-       // Undo pre-whitening
-       ia ^= c.k[0]
-       ib ^= c.k[1]
-       ic ^= c.k[2]
-       id ^= c.k[3]
-
-       store32l(dst[0:4], ia)
-       store32l(dst[4:8], ib)
-       store32l(dst[8:12], ic)
-       store32l(dst[12:16], id)
-}
diff --git a/libgo/go/crypto/twofish/twofish_test.go b/libgo/go/crypto/twofish/twofish_test.go
deleted file mode 100644 (file)
index 303081f..0000000
+++ /dev/null
@@ -1,129 +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 twofish
-
-import (
-       "bytes"
-       "testing"
-)
-
-var qbox = [2][4][16]byte{
-       {
-               {0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4},
-               {0xE, 0xC, 0xB, 0x8, 0x1, 0x2, 0x3, 0x5, 0xF, 0x4, 0xA, 0x6, 0x7, 0x0, 0x9, 0xD},
-               {0xB, 0xA, 0x5, 0xE, 0x6, 0xD, 0x9, 0x0, 0xC, 0x8, 0xF, 0x3, 0x2, 0x4, 0x7, 0x1},
-               {0xD, 0x7, 0xF, 0x4, 0x1, 0x2, 0x6, 0xE, 0x9, 0xB, 0x3, 0x0, 0x8, 0x5, 0xC, 0xA},
-       },
-       {
-               {0x2, 0x8, 0xB, 0xD, 0xF, 0x7, 0x6, 0xE, 0x3, 0x1, 0x9, 0x4, 0x0, 0xA, 0xC, 0x5},
-               {0x1, 0xE, 0x2, 0xB, 0x4, 0xC, 0x3, 0x7, 0x6, 0xD, 0xA, 0x5, 0xF, 0x9, 0x0, 0x8},
-               {0x4, 0xC, 0x7, 0x5, 0x1, 0x6, 0x9, 0xA, 0x0, 0xE, 0xD, 0x8, 0x2, 0xB, 0x3, 0xF},
-               {0xB, 0x9, 0x5, 0x1, 0xC, 0x3, 0xD, 0xE, 0x6, 0x4, 0x7, 0xF, 0x2, 0x0, 0x8, 0xA},
-       },
-}
-
-// genSbox generates the variable sbox
-func genSbox(qi int, x byte) byte {
-       a0, b0 := x/16, x%16
-       for i := 0; i < 2; i++ {
-               a1 := a0 ^ b0
-               b1 := (a0 ^ ((b0 << 3) | (b0 >> 1)) ^ (a0 << 3)) & 15
-               a0 = qbox[qi][2*i][a1]
-               b0 = qbox[qi][2*i+1][b1]
-       }
-       return (b0 << 4) + a0
-}
-
-func TestSbox(t *testing.T) {
-       for n := range sbox {
-               for m := range sbox[n] {
-                       if genSbox(n, byte(m)) != sbox[n][m] {
-                               t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
-                       }
-               }
-       }
-}
-
-var testVectors = []struct {
-       key []byte
-       dec []byte
-       enc []byte
-}{
-       // These tests are extracted from LibTom
-       {
-               []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
-               []byte{0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19},
-               []byte{0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3},
-       },
-       {
-               []byte{0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
-                       0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44},
-               []byte{0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2},
-               []byte{0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65},
-       },
-       {
-               []byte{0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
-                       0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F},
-               []byte{0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6},
-               []byte{0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA},
-       },
-       // These test are derived from http://www.schneier.com/code/ecb_ival.txt
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A},
-       },
-       {
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-                       0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-               },
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0xCF, 0xD1, 0xD2, 0xE5, 0xA9, 0xBE, 0x9C, 0xDF, 0x50, 0x1F, 0x13, 0xB8, 0x92, 0xBD, 0x22, 0x48},
-       },
-       {
-               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-                       0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
-               },
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8, 0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20},
-       },
-}
-
-func TestCipher(t *testing.T) {
-       for n, tt := range testVectors {
-               // Test if the plaintext (dec) is encrypts to the given
-               // ciphertext (enc) using the given key. Test also if enc can
-               // be decrypted again into dec.
-               c, err := NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("#%d: NewCipher: %v", n, err)
-                       return
-               }
-
-               buf := make([]byte, 16)
-               c.Encrypt(buf, tt.dec)
-               if !bytes.Equal(buf, tt.enc) {
-                       t.Errorf("#%d: encrypt = %x want %x", n, buf, tt.enc)
-               }
-               c.Decrypt(buf, tt.enc)
-               if !bytes.Equal(buf, tt.dec) {
-                       t.Errorf("#%d: decrypt = %x want %x", n, buf, tt.dec)
-               }
-
-               // Test that 16 zero bytes, encrypted 1000 times then decrypted
-               // 1000 times results in zero bytes again.
-               zero := make([]byte, 16)
-               buf = make([]byte, 16)
-               for i := 0; i < 1000; i++ {
-                       c.Encrypt(buf, buf)
-               }
-               for i := 0; i < 1000; i++ {
-                       c.Decrypt(buf, buf)
-               }
-               if !bytes.Equal(buf, zero) {
-                       t.Errorf("#%d: encrypt/decrypt 1000: have %x want %x", n, buf, zero)
-               }
-       }
-}
diff --git a/libgo/go/crypto/xtea/block.go b/libgo/go/crypto/xtea/block.go
deleted file mode 100644 (file)
index bf5d245..0000000
+++ /dev/null
@@ -1,66 +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.
-
-/*
-       Implementation adapted from Needham and Wheeler's paper:
-       http://www.cix.co.uk/~klockstone/xtea.pdf
-
-       A precalculated look up table is used during encryption/decryption for values that are based purely on the key.
-*/
-
-package xtea
-
-// XTEA is based on 64 rounds.
-const numRounds = 64
-
-// blockToUint32 reads an 8 byte slice into two uint32s.
-// The block is treated as big endian.
-func blockToUint32(src []byte) (uint32, uint32) {
-       r0 := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-       r1 := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-       return r0, r1
-}
-
-// uint32ToBlock writes two uint32s into an 8 byte data block.
-// Values are written as big endian.
-func uint32ToBlock(v0, v1 uint32, dst []byte) {
-       dst[0] = byte(v0 >> 24)
-       dst[1] = byte(v0 >> 16)
-       dst[2] = byte(v0 >> 8)
-       dst[3] = byte(v0)
-       dst[4] = byte(v1 >> 24)
-       dst[5] = byte(v1 >> 16)
-       dst[6] = byte(v1 >> 8)
-       dst[7] = byte(v1 >> 0)
-}
-
-// encryptBlock encrypts a single 8 byte block using XTEA.
-func encryptBlock(c *Cipher, dst, src []byte) {
-       v0, v1 := blockToUint32(src)
-
-       // Two rounds of XTEA applied per loop
-       for i := 0; i < numRounds; {
-               v0 += ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
-               i++
-               v1 += ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
-               i++
-       }
-
-       uint32ToBlock(v0, v1, dst)
-}
-
-// decryptBlock decrypt a single 8 byte block using XTEA.
-func decryptBlock(c *Cipher, dst, src []byte) {
-       v0, v1 := blockToUint32(src)
-
-       // Two rounds of XTEA applied per loop
-       for i := numRounds; i > 0; {
-               i--
-               v1 -= ((v0<<4 ^ v0>>5) + v0) ^ c.table[i]
-               i--
-               v0 -= ((v1<<4 ^ v1>>5) + v1) ^ c.table[i]
-       }
-
-       uint32ToBlock(v0, v1, dst)
-}
diff --git a/libgo/go/crypto/xtea/cipher.go b/libgo/go/crypto/xtea/cipher.go
deleted file mode 100644 (file)
index 3ed0581..0000000
+++ /dev/null
@@ -1,89 +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 xtea implements XTEA encryption, as defined in Needham and Wheeler's
-// 1997 technical report, "Tea extensions."
-package xtea
-
-// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf
-
-import "strconv"
-
-// The XTEA block size in bytes.
-const BlockSize = 8
-
-// A Cipher is an instance of an XTEA cipher using a particular key.
-// table contains a series of precalculated values that are used each round.
-type Cipher struct {
-       table [64]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) Error() string {
-       return "crypto/xtea: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a new Cipher.
-// The key argument should be the XTEA key.
-// XTEA only supports 128 bit (16 byte) keys.
-func NewCipher(key []byte) (*Cipher, error) {
-       k := len(key)
-       switch k {
-       default:
-               return nil, KeySizeError(k)
-       case 16:
-               break
-       }
-
-       c := new(Cipher)
-       initCipher(c, key)
-
-       return c, nil
-}
-
-// BlockSize returns the XTEA block size, 8 bytes.
-// It is necessary to satisfy the Block interface in the
-// package "crypto/cipher".
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// Encrypt encrypts the 8 byte buffer src using the key and stores the result in dst.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c, dst, src) }
-
-// Decrypt decrypts the 8 byte buffer src using the key k and stores the result in dst.
-func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c, dst, src) }
-
-// Reset zeros the table, so that it will no longer appear in the process's memory.
-func (c *Cipher) Reset() {
-       for i := 0; i < len(c.table); i++ {
-               c.table[i] = 0
-       }
-}
-
-// initCipher initializes the cipher context by creating a look up table
-// of precalculated values that are based on the key.
-func initCipher(c *Cipher, key []byte) {
-       // Load the key into four uint32s
-       var k [4]uint32
-       for i := 0; i < len(k); i++ {
-               j := i << 2 // Multiply by 4
-               k[i] = uint32(key[j+0])<<24 | uint32(key[j+1])<<16 | uint32(key[j+2])<<8 | uint32(key[j+3])
-       }
-
-       // Precalculate the table
-       const delta = 0x9E3779B9
-       var sum uint32 = 0
-
-       // Two rounds of XTEA applied per loop
-       for i := 0; i < numRounds; {
-               c.table[i] = sum + k[sum&3]
-               i++
-               sum += delta
-               c.table[i] = sum + k[(sum>>11)&3]
-               i++
-       }
-}
diff --git a/libgo/go/crypto/xtea/xtea_test.go b/libgo/go/crypto/xtea/xtea_test.go
deleted file mode 100644 (file)
index 217d96a..0000000
+++ /dev/null
@@ -1,246 +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 xtea
-
-import (
-       "testing"
-)
-
-// A sample test key for when we just want to initialize a cipher
-var testKey = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}
-
-// Test that the block size for XTEA is correct
-func TestBlocksize(t *testing.T) {
-       if BlockSize != 8 {
-               t.Errorf("BlockSize constant - expected 8, got %d", BlockSize)
-               return
-       }
-
-       c, err := NewCipher(testKey)
-       if err != nil {
-               t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-               return
-       }
-
-       result := c.BlockSize()
-       if result != 8 {
-               t.Errorf("BlockSize function - expected 8, got %d", result)
-               return
-       }
-}
-
-// A series of test values to confirm that the Cipher.table array was initialized correctly
-var testTable = []uint32{
-       0x00112233, 0x6B1568B8, 0xE28CE030, 0xC5089E2D, 0xC5089E2D, 0x1EFBD3A2, 0xA7845C2A, 0x78EF0917,
-       0x78EF0917, 0x172682D0, 0x5B6AC714, 0x822AC955, 0x3DE68511, 0xDC1DFECA, 0x2062430E, 0x3611343F,
-       0xF1CCEFFB, 0x900469B4, 0xD448ADF8, 0x2E3BE36D, 0xB6C46BF5, 0x994029F2, 0x994029F2, 0xF3335F67,
-       0x6AAAD6DF, 0x4D2694DC, 0x4D2694DC, 0xEB5E0E95, 0x2FA252D9, 0x4551440A, 0x121E10D6, 0xB0558A8F,
-       0xE388BDC3, 0x0A48C004, 0xC6047BC0, 0x643BF579, 0xA88039BD, 0x02736F32, 0x8AFBF7BA, 0x5C66A4A7,
-       0x5C66A4A7, 0xC76AEB2C, 0x3EE262A4, 0x215E20A1, 0x215E20A1, 0x7B515616, 0x03D9DE9E, 0x1988CFCF,
-       0xD5448B8B, 0x737C0544, 0xB7C04988, 0xDE804BC9, 0x9A3C0785, 0x3873813E, 0x7CB7C582, 0xD6AAFAF7,
-       0x4E22726F, 0x309E306C, 0x309E306C, 0x8A9165E1, 0x1319EE69, 0xF595AC66, 0xF595AC66, 0x4F88E1DB,
-}
-
-// Test that the cipher context is initialized correctly
-func TestCipherInit(t *testing.T) {
-       c, err := NewCipher(testKey)
-       if err != nil {
-               t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-               return
-       }
-
-       for i := 0; i < len(c.table); i++ {
-               if c.table[i] != testTable[i] {
-                       t.Errorf("NewCipher() failed to initialize Cipher.table[%d] correctly. Expected %08X, got %08X", i, testTable[i], c.table[i])
-                       break
-               }
-       }
-}
-
-// Test that invalid key sizes return an error
-func TestInvalidKeySize(t *testing.T) {
-       // Test a long key
-       key := []byte{
-               0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
-               0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
-       }
-
-       _, err := NewCipher(key)
-       if err == nil {
-               t.Errorf("Invalid key size %d didn't result in an error.", len(key))
-       }
-
-       // Test a short key
-       key = []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}
-
-       _, err = NewCipher(key)
-       if err == nil {
-               t.Errorf("Invalid key size %d didn't result in an error.", len(key))
-       }
-}
-
-// Test that we can correctly decode some bytes we have encoded
-func TestEncodeDecode(t *testing.T) {
-       original := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}
-       input := original
-       output := make([]byte, BlockSize)
-
-       c, err := NewCipher(testKey)
-       if err != nil {
-               t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-               return
-       }
-
-       // Encrypt the input block
-       c.Encrypt(output, input)
-
-       // Check that the output does not match the input
-       differs := false
-       for i := 0; i < len(input); i++ {
-               if output[i] != input[i] {
-                       differs = true
-                       break
-               }
-       }
-       if differs == false {
-               t.Error("Cipher.Encrypt: Failed to encrypt the input block.")
-               return
-       }
-
-       // Decrypt the block we just encrypted
-       input = output
-       output = make([]byte, BlockSize)
-       c.Decrypt(output, input)
-
-       // Check that the output from decrypt matches our initial input
-       for i := 0; i < len(input); i++ {
-               if output[i] != original[i] {
-                       t.Errorf("Decrypted byte %d differed. Expected %02X, got %02X\n", i, original[i], output[i])
-                       return
-               }
-       }
-}
-
-// Test Vectors
-type CryptTest struct {
-       key        []byte
-       plainText  []byte
-       cipherText []byte
-}
-
-var CryptTests = []CryptTest{
-       // These were sourced from http://www.freemedialibrary.com/index.php/XTEA_test_vectors
-       {
-               []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
-               []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
-               []byte{0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5},
-       },
-       {
-               []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
-               []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-               []byte{0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8},
-       },
-       {
-               []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
-               []byte{0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f},
-               []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-       },
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
-               []byte{0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5},
-       },
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-               []byte{0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d},
-       },
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55},
-               []byte{0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41},
-       },
-
-       // These vectors are from http://wiki.secondlife.com/wiki/XTEA_Strong_Encryption_Implementation#Bouncy_Castle_C.23_API
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0xDE, 0xE9, 0xD4, 0xD8, 0xF7, 0x13, 0x1E, 0xD9},
-       },
-       {
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
-               []byte{0x06, 0x5C, 0x1B, 0x89, 0x75, 0xC6, 0xA8, 0x16},
-       },
-       {
-               []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
-               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-               []byte{0x1F, 0xF9, 0xA0, 0x26, 0x1A, 0xC6, 0x42, 0x64},
-       },
-       {
-               []byte{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
-               []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
-               []byte{0x8C, 0x67, 0x15, 0x5B, 0x2E, 0xF9, 0x1E, 0xAD},
-       },
-}
-
-// Test encryption
-func TestCipherEncrypt(t *testing.T) {
-       for i, tt := range CryptTests {
-               c, err := NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
-                       continue
-               }
-
-               out := make([]byte, len(tt.plainText))
-               c.Encrypt(out, tt.plainText)
-
-               for j := 0; j < len(out); j++ {
-                       if out[j] != tt.cipherText[j] {
-                               t.Errorf("Cipher.Encrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.cipherText[j])
-                               break
-                       }
-               }
-       }
-}
-
-// Test decryption
-func TestCipherDecrypt(t *testing.T) {
-       for i, tt := range CryptTests {
-               c, err := NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("NewCipher(%d bytes), vector %d = %s", len(tt.key), i, err)
-                       continue
-               }
-
-               out := make([]byte, len(tt.cipherText))
-               c.Decrypt(out, tt.cipherText)
-
-               for j := 0; j < len(out); j++ {
-                       if out[j] != tt.plainText[j] {
-                               t.Errorf("Cipher.Decrypt %d: out[%d] = %02X, expected %02X", i, j, out[j], tt.plainText[j])
-                               break
-                       }
-               }
-       }
-}
-
-// Test resetting the cipher context
-func TestReset(t *testing.T) {
-       c, err := NewCipher(testKey)
-       if err != nil {
-               t.Errorf("NewCipher(%d bytes) = %s", len(testKey), err)
-               return
-       }
-
-       c.Reset()
-       for i := 0; i < len(c.table); i++ {
-               if c.table[i] != 0 {
-                       t.Errorf("Cipher.Reset: Failed to clear Cipher.table[%d]. expected 0, got %08X", i, c.table[i])
-                       return
-               }
-       }
-}
index 9835e38de7e24c2e806640f4ec9b26d8857c7d28..e80420e5bb3aa1726f2f031161e18865a16ca123 100644 (file)
@@ -40,6 +40,9 @@ func convertAssign(dest, src interface{}) error {
                case *string:
                        *d = s
                        return nil
+               case *[]byte:
+                       *d = []byte(s)
+                       return nil
                }
        case []byte:
                switch d := dest.(type) {
@@ -50,6 +53,12 @@ func convertAssign(dest, src interface{}) error {
                        *d = s
                        return nil
                }
+       case nil:
+               switch d := dest.(type) {
+               case *[]byte:
+                       *d = nil
+                       return nil
+               }
        }
 
        var sv reflect.Value
index b0d137cd71568d08a3c9f1bb10bdf2573dbbbeca..df25023e1273f9397ea5522ce2629991592b504c 100644 (file)
@@ -585,12 +585,26 @@ func converterForType(typ string) driver.ValueConverter {
        switch typ {
        case "bool":
                return driver.Bool
+       case "nullbool":
+               return driver.Null{driver.Bool}
        case "int32":
                return driver.Int32
        case "string":
                return driver.NotNull{driver.String}
        case "nullstring":
                return driver.Null{driver.String}
+       case "int64":
+               // TODO(coopernurse): add type-specific converter
+               return driver.NotNull{driver.DefaultParameterConverter}
+       case "nullint64":
+               // TODO(coopernurse): add type-specific converter
+               return driver.Null{driver.DefaultParameterConverter}
+       case "float64":
+               // TODO(coopernurse): add type-specific converter
+               return driver.NotNull{driver.DefaultParameterConverter}
+       case "nullfloat64":
+               // TODO(coopernurse): add type-specific converter
+               return driver.Null{driver.DefaultParameterConverter}
        case "datetime":
                return driver.DefaultParameterConverter
        }
index a8bf2a8b00c933d9963f5c82681cbaaf2823070b..34a76521050d7600b8f401839a761041eed10b71 100644 (file)
@@ -47,7 +47,6 @@ type RawBytes []byte
 //     // NULL value
 //  }
 //
-// TODO(bradfitz): add other types.
 type NullString struct {
        String string
        Valid  bool // Valid is true if String is not NULL
@@ -71,6 +70,84 @@ func (ns NullString) SubsetValue() (interface{}, error) {
        return ns.String, nil
 }
 
+// NullInt64 represents an int64 that may be null.
+// NullInt64 implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullInt64 struct {
+       Int64 int64
+       Valid bool // Valid is true if Int64 is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullInt64) ScanInto(value interface{}) error {
+       if value == nil {
+               n.Int64, n.Valid = 0, false
+               return nil
+       }
+       n.Valid = true
+       return convertAssign(&n.Int64, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullInt64) SubsetValue() (interface{}, error) {
+       if !n.Valid {
+               return nil, nil
+       }
+       return n.Int64, nil
+}
+
+// NullFloat64 represents a float64 that may be null.
+// NullFloat64 implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullFloat64 struct {
+       Float64 float64
+       Valid   bool // Valid is true if Float64 is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullFloat64) ScanInto(value interface{}) error {
+       if value == nil {
+               n.Float64, n.Valid = 0, false
+               return nil
+       }
+       n.Valid = true
+       return convertAssign(&n.Float64, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullFloat64) SubsetValue() (interface{}, error) {
+       if !n.Valid {
+               return nil, nil
+       }
+       return n.Float64, nil
+}
+
+// NullBool represents a bool that may be null.
+// NullBool implements the ScannerInto interface so
+// it can be used as a scan destination, similar to NullString.
+type NullBool struct {
+       Bool  bool
+       Valid bool // Valid is true if Bool is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (n *NullBool) ScanInto(value interface{}) error {
+       if value == nil {
+               n.Bool, n.Valid = false, false
+               return nil
+       }
+       n.Valid = true
+       return convertAssign(&n.Bool, value)
+}
+
+// SubsetValue implements the driver SubsetValuer interface.
+func (n NullBool) SubsetValue() (interface{}, error) {
+       if !n.Valid {
+               return nil, nil
+       }
+       return n.Bool, nil
+}
+
 // ScannerInto is an interface used by Scan.
 type ScannerInto interface {
        // ScanInto assigns a value from a database driver.
@@ -479,8 +556,11 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
        if err != nil {
                return nil, err
        }
-       defer stmt.Close()
-       return stmt.Query(args...)
+       rows, err := stmt.Query(args...)
+       if err == nil {
+               rows.closeStmt = stmt
+       }
+       return rows, err
 }
 
 // QueryRow executes a query that is expected to return at most one row.
@@ -824,6 +904,12 @@ func (rs *Rows) Scan(dest ...interface{}) error {
                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
                }
@@ -865,17 +951,10 @@ func (r *Row) Scan(dest ...interface{}) error {
        if r.err != nil {
                return r.err
        }
-       defer r.rows.Close()
-       if !r.rows.Next() {
-               return ErrNoRows
-       }
-       err := r.rows.Scan(dest...)
-       if err != nil {
-               return err
-       }
 
        // TODO(bradfitz): for now we need to defensively clone all
-       // []byte that the driver returned, since we're about to close
+       // []byte that the driver returned (not permitting 
+       // *RawBytes in Rows.Scan), since we're about to close
        // the Rows in our defer, when we return from this function.
        // the contract with the driver.Next(...) interface is that it
        // can return slices into read-only temporary memory that's
@@ -890,14 +969,17 @@ func (r *Row) Scan(dest ...interface{}) error {
                if _, ok := dp.(*RawBytes); ok {
                        return errors.New("sql: RawBytes isn't allowed on Row.Scan")
                }
-               b, ok := dp.(*[]byte)
-               if !ok {
-                       continue
-               }
-               clone := make([]byte, len(*b))
-               copy(clone, *b)
-               *b = clone
        }
+
+       defer r.rows.Close()
+       if !r.rows.Next() {
+               return ErrNoRows
+       }
+       err := r.rows.Scan(dest...)
+       if err != nil {
+               return err
+       }
+
        return nil
 }
 
index 3fe93986faa6d0bfaa289cde3f7c341cb8bed4c6..c5cadad84999a18c5b5d48d971352d161652796e 100644 (file)
@@ -5,6 +5,7 @@
 package sql
 
 import (
+       "fmt"
        "reflect"
        "strings"
        "testing"
@@ -310,6 +311,40 @@ func TestTxStmt(t *testing.T) {
        }
 }
 
+// Issue: http://golang.org/issue/2784
+// This test didn't fail before because we got luckly with the fakedb driver.
+// It was failing, and now not, in github.com/bradfitz/go-sql-test
+func TestTxQuery(t *testing.T) {
+       db := newTestDB(t, "")
+       defer closeDB(t, db)
+       exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+       exec(t, db, "INSERT|t1|name=Alice")
+
+       tx, err := db.Begin()
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer tx.Rollback()
+
+       r, err := tx.Query("SELECT|t1|name|")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       if !r.Next() {
+               if r.Err() != nil {
+                       t.Fatal(r.Err())
+               }
+               t.Fatal("expected one row")
+       }
+
+       var x string
+       err = r.Scan(&x)
+       if err != nil {
+               t.Fatal(err)
+       }
+}
+
 // Tests fix for issue 2542, that we release a lock when querying on
 // a closed connection.
 func TestIssue2542Deadlock(t *testing.T) {
@@ -323,6 +358,34 @@ func TestIssue2542Deadlock(t *testing.T) {
        }
 }
 
+// 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) {
+       db := newTestDB(t, "")
+       defer closeDB(t, db)
+       exec(t, db, "CREATE|t|id=int32,name=nullstring")
+       exec(t, db, "INSERT|t|id=10,name=?", nil)
+
+       var name []byte
+
+       err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
+       if err != nil {
+               t.Fatal(err)
+       }
+       if name != nil {
+               t.Fatalf("name []byte should be nil for null column value, got: %#v", name)
+       }
+
+       exec(t, db, "INSERT|t|id=11,name=?", "bob")
+       err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name)
+       if err != nil {
+               t.Fatal(err)
+       }
+       if string(name) != "bob" {
+               t.Fatalf("name []byte should be bob, got: %q", string(name))
+       }
+}
+
 func TestQueryRowClosingStmt(t *testing.T) {
        db := newTestDB(t, "people")
        defer closeDB(t, db)
@@ -341,64 +404,116 @@ func TestQueryRowClosingStmt(t *testing.T) {
        }
 }
 
+type nullTestRow struct {
+       nullParam    interface{}
+       notNullParam interface{}
+       scanNullVal  interface{}
+}
+
+type nullTestSpec struct {
+       nullType    string
+       notNullType string
+       rows        [6]nullTestRow
+}
+
 func TestNullStringParam(t *testing.T) {
+       spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
+               nullTestRow{NullString{"aqua", true}, "", NullString{"aqua", true}},
+               nullTestRow{NullString{"brown", false}, "", NullString{"", false}},
+               nullTestRow{"chartreuse", "", NullString{"chartreuse", true}},
+               nullTestRow{NullString{"darkred", true}, "", NullString{"darkred", true}},
+               nullTestRow{NullString{"eel", false}, "", NullString{"", false}},
+               nullTestRow{"foo", NullString{"black", false}, nil},
+       }}
+       nullTestRun(t, spec)
+}
+
+func TestNullInt64Param(t *testing.T) {
+       spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{
+               nullTestRow{NullInt64{31, true}, 1, NullInt64{31, true}},
+               nullTestRow{NullInt64{-22, false}, 1, NullInt64{0, false}},
+               nullTestRow{22, 1, NullInt64{22, true}},
+               nullTestRow{NullInt64{33, true}, 1, NullInt64{33, true}},
+               nullTestRow{NullInt64{222, false}, 1, NullInt64{0, false}},
+               nullTestRow{0, NullInt64{31, false}, nil},
+       }}
+       nullTestRun(t, spec)
+}
+
+func TestNullFloat64Param(t *testing.T) {
+       spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
+               nullTestRow{NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
+               nullTestRow{NullFloat64{13.1, false}, 1, NullFloat64{0, false}},
+               nullTestRow{-22.9, 1, NullFloat64{-22.9, true}},
+               nullTestRow{NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}},
+               nullTestRow{NullFloat64{222, false}, 1, NullFloat64{0, false}},
+               nullTestRow{10, NullFloat64{31.2, false}, nil},
+       }}
+       nullTestRun(t, spec)
+}
+
+func TestNullBoolParam(t *testing.T) {
+       spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{
+               nullTestRow{NullBool{false, true}, true, NullBool{false, true}},
+               nullTestRow{NullBool{true, false}, false, NullBool{false, false}},
+               nullTestRow{true, true, NullBool{true, true}},
+               nullTestRow{NullBool{true, true}, false, NullBool{true, true}},
+               nullTestRow{NullBool{true, false}, true, NullBool{false, false}},
+               nullTestRow{true, NullBool{true, false}, nil},
+       }}
+       nullTestRun(t, spec)
+}
+
+func nullTestRun(t *testing.T, spec nullTestSpec) {
        db := newTestDB(t, "")
        defer closeDB(t, db)
-       exec(t, db, "CREATE|t|id=int32,name=string,favcolor=nullstring")
+       exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType))
 
        // Inserts with db.Exec:
-       exec(t, db, "INSERT|t|id=?,name=?,favcolor=?", 1, "alice", NullString{"aqua", true})
-       exec(t, db, "INSERT|t|id=?,name=?,favcolor=?", 2, "bob", NullString{"brown", false})
-
-       _, err := db.Exec("INSERT|t|id=?,name=?,favcolor=?", 999, nil, nil)
-       if err == nil {
-               // TODO: this test fails, but it's just because
-               // fakeConn implements the optional Execer interface,
-               // so arguably this is the correct behavior.  But
-               // maybe I should flesh out the fakeConn.Exec
-               // implementation so this properly fails.
-               // t.Errorf("expected error inserting nil name with Exec")
-       }
+       exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam)
+       exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam)
 
        // Inserts with a prepared statement:
-       stmt, err := db.Prepare("INSERT|t|id=?,name=?,favcolor=?")
+       stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
        if err != nil {
                t.Fatalf("prepare: %v", err)
        }
-       if _, err := stmt.Exec(3, "chris", "chartreuse"); err != nil {
+       if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil {
                t.Errorf("exec insert chris: %v", err)
        }
-       if _, err := stmt.Exec(4, "dave", NullString{"darkred", true}); err != nil {
+       if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil {
                t.Errorf("exec insert dave: %v", err)
        }
-       if _, err := stmt.Exec(5, "eleanor", NullString{"eel", false}); err != nil {
-               t.Errorf("exec insert dave: %v", err)
+       if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil {
+               t.Errorf("exec insert eleanor: %v", err)
        }
 
-       // Can't put null name into non-nullstring column,
-       if _, err := stmt.Exec(5, NullString{"", false}, nil); err == nil {
-               t.Errorf("expected error inserting nil name with prepared statement Exec")
+       // Can't put null val into non-null col
+       if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil {
+               t.Errorf("expected error inserting nil val with prepared statement Exec")
        }
 
-       type nameColor struct {
-               name     string
-               favColor NullString
+       _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
+       if err == nil {
+               // TODO: this test fails, but it's just because
+               // fakeConn implements the optional Execer interface,
+               // so arguably this is the correct behavior.  But
+               // maybe I should flesh out the fakeConn.Exec
+               // implementation so this properly fails.
+               // t.Errorf("expected error inserting nil name with Exec")
        }
 
-       wantMap := map[int]nameColor{
-               1: nameColor{"alice", NullString{"aqua", true}},
-               2: nameColor{"bob", NullString{"", false}},
-               3: nameColor{"chris", NullString{"chartreuse", true}},
-               4: nameColor{"dave", NullString{"darkred", true}},
-               5: nameColor{"eleanor", NullString{"", false}},
-       }
-       for id, want := range wantMap {
-               var got nameColor
-               if err := db.QueryRow("SELECT|t|name,favcolor|id=?", id).Scan(&got.name, &got.favColor); err != nil {
+       paramtype := reflect.TypeOf(spec.rows[0].nullParam)
+       bindVal := reflect.New(paramtype).Interface()
+
+       for i := 0; i < 5; i++ {
+               id := i + 1
+               if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil {
                        t.Errorf("id=%d Scan: %v", id, err)
                }
-               if got != want {
-                       t.Errorf("id=%d got %#v, want %#v", id, got, want)
+               bindValDeref := reflect.ValueOf(bindVal).Elem().Interface()
+               if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) {
+                       t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal)
                }
        }
 }
index d4872eea2c5c1fd36ef0d21e86375d431773692c..b756afdd0400cccbdd839c8907490c0e42befa98 100644 (file)
@@ -37,6 +37,7 @@ const (
 )
 
 // PutUvarint encodes a uint64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutUvarint will panic.
 func PutUvarint(buf []byte, x uint64) int {
        i := 0
        for x >= 0x80 {
@@ -73,6 +74,7 @@ func Uvarint(buf []byte) (uint64, int) {
 }
 
 // PutVarint encodes an int64 into buf and returns the number of bytes written.
+// If the buffer is too small, PutVarint will panic.
 func PutVarint(buf []byte, x int64) int {
        ux := uint64(x) << 1
        if x < 0 {
@@ -98,14 +100,6 @@ func Varint(buf []byte) (int64, int) {
        return x, n
 }
 
-// WriteUvarint encodes x and writes the result to w.
-func WriteUvarint(w io.Writer, x uint64) error {
-       var buf [MaxVarintLen64]byte
-       n := PutUvarint(buf[:], x)
-       _, err := w.Write(buf[0:n])
-       return err
-}
-
 var overflow = errors.New("binary: varint overflows a 64-bit integer")
 
 // ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
@@ -129,15 +123,6 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
        panic("unreachable")
 }
 
-// WriteVarint encodes x and writes the result to w.
-func WriteVarint(w io.Writer, x int64) error {
-       ux := uint64(x) << 1
-       if x < 0 {
-               ux = ^ux
-       }
-       return WriteUvarint(w, ux)
-}
-
 // ReadVarint reads an encoded unsigned integer from r and returns it as a uint64.
 func ReadVarint(r io.ByteReader) (int64, error) {
        ux, err := ReadUvarint(r) // ok to continue in presence of error
index dc550f22f44e79c9eaee865956dd4ef0884ee29d..9476bd5fb7a6d7ac69d905895a3fbaec81a02895 100644 (file)
@@ -25,9 +25,9 @@ func TestConstants(t *testing.T) {
 }
 
 func testVarint(t *testing.T, x int64) {
-       buf1 := make([]byte, MaxVarintLen64)
-       n := PutVarint(buf1[:], x)
-       y, m := Varint(buf1[0:n])
+       buf := make([]byte, MaxVarintLen64)
+       n := PutVarint(buf, x)
+       y, m := Varint(buf[0:n])
        if x != y {
                t.Errorf("Varint(%d): got %d", x, y)
        }
@@ -35,15 +35,7 @@ func testVarint(t *testing.T, x int64) {
                t.Errorf("Varint(%d): got n = %d; want %d", x, m, n)
        }
 
-       var buf2 bytes.Buffer
-       err := WriteVarint(&buf2, x)
-       if err != nil {
-               t.Errorf("WriteVarint(%d): %s", x, err)
-       }
-       if n != buf2.Len() {
-               t.Errorf("WriteVarint(%d): got n = %d; want %d", x, buf2.Len(), n)
-       }
-       y, err = ReadVarint(&buf2)
+       y, err := ReadVarint(bytes.NewBuffer(buf))
        if err != nil {
                t.Errorf("ReadVarint(%d): %s", x, err)
        }
@@ -53,9 +45,9 @@ func testVarint(t *testing.T, x int64) {
 }
 
 func testUvarint(t *testing.T, x uint64) {
-       buf1 := make([]byte, MaxVarintLen64)
-       n := PutUvarint(buf1[:], x)
-       y, m := Uvarint(buf1[0:n])
+       buf := make([]byte, MaxVarintLen64)
+       n := PutUvarint(buf, x)
+       y, m := Uvarint(buf[0:n])
        if x != y {
                t.Errorf("Uvarint(%d): got %d", x, y)
        }
@@ -63,15 +55,7 @@ func testUvarint(t *testing.T, x uint64) {
                t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n)
        }
 
-       var buf2 bytes.Buffer
-       err := WriteUvarint(&buf2, x)
-       if err != nil {
-               t.Errorf("WriteUvarint(%d): %s", x, err)
-       }
-       if n != buf2.Len() {
-               t.Errorf("WriteUvarint(%d): got n = %d; want %d", x, buf2.Len(), n)
-       }
-       y, err = ReadUvarint(&buf2)
+       y, err := ReadUvarint(bytes.NewBuffer(buf))
        if err != nil {
                t.Errorf("ReadUvarint(%d): %s", x, err)
        }
diff --git a/libgo/go/encoding/git85/git.go b/libgo/go/encoding/git85/git.go
deleted file mode 100644 (file)
index d383213..0000000
+++ /dev/null
@@ -1,276 +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 git85 implements the radix 85 data encoding
-// used in the Git version control system.
-package git85
-
-import (
-       "bytes"
-       "io"
-       "strconv"
-)
-
-type CorruptInputError int64
-
-func (e CorruptInputError) Error() string {
-       return "illegal git85 data at input byte " + strconv.FormatInt(int64(e), 10)
-}
-
-const encode = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
-
-// The decodings are 1+ the actual value, so that the
-// default zero value can be used to mean "not valid".
-var decode = [256]uint8{
-       '0': 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
-       'A': 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
-       24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
-       'a': 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
-       50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
-       '!': 63,
-       '#': 64, 65, 66, 67,
-       '(': 68, 69, 70, 71,
-       '-': 72,
-       ';': 73,
-       '<': 74, 75, 76, 77,
-       '@': 78,
-       '^': 79, 80, 81,
-       '{': 82, 83, 84, 85,
-}
-
-// Encode encodes src into EncodedLen(len(src))
-// bytes of dst.  As a convenience, it returns the number
-// of bytes written to dst, but this value is always EncodedLen(len(src)).
-// Encode implements the radix 85 encoding used in the
-// Git version control tool.
-//
-// The encoding splits src into chunks of at most 52 bytes
-// and encodes each chunk on its own line.
-func Encode(dst, src []byte) int {
-       ndst := 0
-       for len(src) > 0 {
-               n := len(src)
-               if n > 52 {
-                       n = 52
-               }
-               if n <= 27 {
-                       dst[ndst] = byte('A' + n - 1)
-               } else {
-                       dst[ndst] = byte('a' + n - 26 - 1)
-               }
-               ndst++
-               for i := 0; i < n; i += 4 {
-                       var v uint32
-                       for j := 0; j < 4 && i+j < n; j++ {
-                               v |= uint32(src[i+j]) << uint(24-j*8)
-                       }
-                       for j := 4; j >= 0; j-- {
-                               dst[ndst+j] = encode[v%85]
-                               v /= 85
-                       }
-                       ndst += 5
-               }
-               dst[ndst] = '\n'
-               ndst++
-               src = src[n:]
-       }
-       return ndst
-}
-
-// EncodedLen returns the length of an encoding of n source bytes.
-func EncodedLen(n int) int {
-       if n == 0 {
-               return 0
-       }
-       // 5 bytes per 4 bytes of input, rounded up.
-       // 2 extra bytes for each line of 52 src bytes, rounded up.
-       return (n+3)/4*5 + (n+51)/52*2
-}
-
-var newline = []byte{'\n'}
-
-// Decode decodes src into at most MaxDecodedLen(len(src))
-// bytes, returning the actual number of bytes written to dst.
-//
-// If Decode encounters invalid input, it returns a CorruptInputError.
-//
-func Decode(dst, src []byte) (n int, err error) {
-       ndst := 0
-       nsrc := 0
-       for nsrc < len(src) {
-               var l int
-               switch ch := int(src[nsrc]); {
-               case 'A' <= ch && ch <= 'Z':
-                       l = ch - 'A' + 1
-               case 'a' <= ch && ch <= 'z':
-                       l = ch - 'a' + 26 + 1
-               default:
-                       return ndst, CorruptInputError(nsrc)
-               }
-               if nsrc+1+l > len(src) {
-                       return ndst, CorruptInputError(nsrc)
-               }
-               el := (l + 3) / 4 * 5 // encoded len
-               if nsrc+1+el+1 > len(src) || src[nsrc+1+el] != '\n' {
-                       return ndst, CorruptInputError(nsrc)
-               }
-               line := src[nsrc+1 : nsrc+1+el]
-               for i := 0; i < el; i += 5 {
-                       var v uint32
-                       for j := 0; j < 5; j++ {
-                               ch := decode[line[i+j]]
-                               if ch == 0 {
-                                       return ndst, CorruptInputError(nsrc + 1 + i + j)
-                               }
-                               v = v*85 + uint32(ch-1)
-                       }
-                       for j := 0; j < 4; j++ {
-                               dst[ndst] = byte(v >> 24)
-                               v <<= 8
-                               ndst++
-                       }
-               }
-               // Last fragment may have run too far (but there was room in dst).
-               // Back up.
-               if l%4 != 0 {
-                       ndst -= 4 - l%4
-               }
-               nsrc += 1 + el + 1
-       }
-       return ndst, nil
-}
-
-func MaxDecodedLen(n int) int { return n / 5 * 4 }
-
-// NewEncoder returns a new Git base85 stream encoder.  Data written to
-// the returned writer will be encoded and then written to w.
-// The Git encoding operates on 52-byte blocks; when finished
-// writing, the caller must Close the returned encoder to flush any
-// partially written blocks.
-func NewEncoder(w io.Writer) io.WriteCloser { return &encoder{w: w} }
-
-type encoder struct {
-       w    io.Writer
-       err  error
-       buf  [52]byte
-       nbuf int
-       out  [1024]byte
-       nout int
-}
-
-func (e *encoder) Write(p []byte) (n int, err error) {
-       if e.err != nil {
-               return 0, e.err
-       }
-
-       // Leading fringe.
-       if e.nbuf > 0 {
-               var i int
-               for i = 0; i < len(p) && e.nbuf < 52; i++ {
-                       e.buf[e.nbuf] = p[i]
-                       e.nbuf++
-               }
-               n += i
-               p = p[i:]
-               if e.nbuf < 52 {
-                       return
-               }
-               nout := Encode(e.out[0:], e.buf[0:])
-               if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
-                       return n, e.err
-               }
-               e.nbuf = 0
-       }
-
-       // Large interior chunks.
-       for len(p) >= 52 {
-               nn := len(e.out) / (1 + 52/4*5 + 1) * 52
-               if nn > len(p) {
-                       nn = len(p) / 52 * 52
-               }
-               if nn > 0 {
-                       nout := Encode(e.out[0:], p[0:nn])
-                       if _, e.err = e.w.Write(e.out[0:nout]); e.err != nil {
-                               return n, e.err
-                       }
-               }
-               n += nn
-               p = p[nn:]
-       }
-
-       // Trailing fringe.
-       for i := 0; i < len(p); i++ {
-               e.buf[i] = p[i]
-       }
-       e.nbuf = len(p)
-       n += len(p)
-       return
-}
-
-func (e *encoder) Close() error {
-       // If there's anything left in the buffer, flush it out
-       if e.err == nil && e.nbuf > 0 {
-               nout := Encode(e.out[0:], e.buf[0:e.nbuf])
-               e.nbuf = 0
-               _, e.err = e.w.Write(e.out[0:nout])
-       }
-       return e.err
-}
-
-// NewDecoder returns a new Git base85 stream decoder.
-func NewDecoder(r io.Reader) io.Reader { return &decoder{r: r} }
-
-type decoder struct {
-       r       io.Reader
-       err     error
-       readErr error
-       buf     [1024]byte
-       nbuf    int
-       out     []byte
-       outbuf  [1024]byte
-       off     int64
-}
-
-func (d *decoder) Read(p []byte) (n int, err error) {
-       if len(p) == 0 {
-               return 0, nil
-       }
-
-       for {
-               // Copy leftover output from last decode.
-               if len(d.out) > 0 {
-                       n = copy(p, d.out)
-                       d.out = d.out[n:]
-                       return
-               }
-
-               // Out of decoded output.  Check errors.
-               if d.err != nil {
-                       return 0, d.err
-               }
-               if d.readErr != nil {
-                       d.err = d.readErr
-                       return 0, d.err
-               }
-
-               // Read and decode more input.
-               var nn int
-               nn, d.readErr = d.r.Read(d.buf[d.nbuf:])
-               d.nbuf += nn
-
-               // Send complete lines to Decode.
-               nl := bytes.LastIndex(d.buf[0:d.nbuf], newline)
-               if nl < 0 {
-                       continue
-               }
-               nn, d.err = Decode(d.outbuf[0:], d.buf[0:nl+1])
-               if e, ok := d.err.(CorruptInputError); ok {
-                       d.err = CorruptInputError(int64(e) + d.off)
-               }
-               d.out = d.outbuf[0:nn]
-               d.nbuf = copy(d.buf[0:], d.buf[nl+1:d.nbuf])
-               d.off += int64(nl + 1)
-       }
-       panic("unreachable")
-}
diff --git a/libgo/go/encoding/git85/git_test.go b/libgo/go/encoding/git85/git_test.go
deleted file mode 100644 (file)
index 81f5b0e..0000000
+++ /dev/null
@@ -1,194 +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 git85
-
-import (
-       "bytes"
-       "io"
-       "io/ioutil"
-       "testing"
-)
-
-type testpair struct {
-       decoded, encoded string
-}
-
-func testEqual(t *testing.T, msg string, args ...interface{}) bool {
-       if args[len(args)-2] != args[len(args)-1] {
-               t.Errorf(msg, args...)
-               return false
-       }
-       return true
-}
-
-func TestGitTable(t *testing.T) {
-       var saw [256]bool
-       for i, c := range encode {
-               if decode[c] != uint8(i+1) {
-                       t.Errorf("decode['%c'] = %d, want %d", c, decode[c], i+1)
-               }
-               saw[c] = true
-       }
-       for i, b := range saw {
-               if !b && decode[i] != 0 {
-                       t.Errorf("decode[%d] = %d, want 0", i, decode[i])
-               }
-       }
-}
-
-var gitPairs = []testpair{
-       // Wikipedia example, adapted.
-       {
-               "Man is distinguished, not only by his reason, but by this singular passion from " +
-                       "other animals, which is a lust of the mind, that by a perseverance of delight in " +
-                       "the continued and indefatigable generation of knowledge, exceeds the short " +
-                       "vehemence of any carnal pleasure.",
-
-               "zO<`^zX>%ZCX>)XGZfA9Ab7*B`EFf-gbRchTY<VDJc_3(Mb0BhMVRLV8EFfZabRc4R\n" +
-                       "zAarPHb0BkRZfA9DVR9gFVRLh7Z*CxFa&K)QZ**v7av))DX>DO_b1WctXlY|;AZc?T\n" +
-                       "zVIXXEb95kYW*~HEWgu;7Ze%PVbZB98AYyqSVIXj2a&u*NWpZI|V`U(3W*}r`Y-wj`\n" +
-                       "zbRcPNAarPDAY*TCbZKsNWn>^>Ze$>7Ze(R<VRUI{VPb4$AZKN6WpZJ3X>V>IZ)PBC\n" +
-                       "zZf|#NWn^b%EFfigV`XJzb0BnRWgv5CZ*p`Xc4cT~ZDnp_Wgu^6AYpEKAY);2ZeeU7\n" +
-                       "IaBO8^b9HiME&u=k\n",
-       },
-}
-
-var gitBigtest = gitPairs[len(gitPairs)-1]
-
-func TestEncode(t *testing.T) {
-       for _, p := range gitPairs {
-               buf := make([]byte, EncodedLen(len(p.decoded)))
-               n := Encode(buf, []byte(p.decoded))
-               if n != len(buf) {
-                       t.Errorf("EncodedLen does not agree with Encode")
-               }
-               buf = buf[0:n]
-               testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded)
-       }
-}
-
-func TestEncoder(t *testing.T) {
-       for _, p := range gitPairs {
-               bb := &bytes.Buffer{}
-               encoder := NewEncoder(bb)
-               encoder.Write([]byte(p.decoded))
-               encoder.Close()
-               testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
-       }
-}
-
-func TestEncoderBuffering(t *testing.T) {
-       input := []byte(gitBigtest.decoded)
-       for bs := 1; bs <= 12; bs++ {
-               bb := &bytes.Buffer{}
-               encoder := NewEncoder(bb)
-               for pos := 0; pos < len(input); pos += bs {
-                       end := pos + bs
-                       if end > len(input) {
-                               end = len(input)
-                       }
-                       n, err := encoder.Write(input[pos:end])
-                       testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
-                       testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
-               }
-               err := encoder.Close()
-               testEqual(t, "Close gave error %v, want %v", err, error(nil))
-               testEqual(t, "Encoding/%d of %q = %q, want %q", bs, gitBigtest.decoded, bb.String(), gitBigtest.encoded)
-       }
-}
-
-func TestDecode(t *testing.T) {
-       for _, p := range gitPairs {
-               dbuf := make([]byte, 4*len(p.encoded))
-               ndst, err := Decode(dbuf, []byte(p.encoded))
-               testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
-               testEqual(t, "Decode(%q) = ndst %v, want %v", p.encoded, ndst, len(p.decoded))
-               testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:ndst]), p.decoded)
-       }
-}
-
-func TestDecoder(t *testing.T) {
-       for _, p := range gitPairs {
-               decoder := NewDecoder(bytes.NewBufferString(p.encoded))
-               dbuf, err := ioutil.ReadAll(decoder)
-               if err != nil {
-                       t.Fatal("Read failed", err)
-               }
-               testEqual(t, "Read from %q = length %v, want %v", p.encoded, len(dbuf), len(p.decoded))
-               testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf), p.decoded)
-               if err != nil {
-                       testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
-               }
-       }
-}
-
-func TestDecoderBuffering(t *testing.T) {
-       for bs := 1; bs <= 12; bs++ {
-               decoder := NewDecoder(bytes.NewBufferString(gitBigtest.encoded))
-               buf := make([]byte, len(gitBigtest.decoded)+12)
-               var total int
-               for total = 0; total < len(gitBigtest.decoded); {
-                       n, err := decoder.Read(buf[total : total+bs])
-                       testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", gitBigtest.encoded, total, n, err, error(nil))
-                       total += n
-               }
-               testEqual(t, "Decoding/%d of %q = %q, want %q", bs, gitBigtest.encoded, string(buf[0:total]), gitBigtest.decoded)
-       }
-}
-
-func TestDecodeCorrupt(t *testing.T) {
-       type corrupt struct {
-               e string
-               p int
-       }
-       examples := []corrupt{
-               {"v", 0},
-               {"!z!!!!!!!!!", 0},
-       }
-
-       for _, e := range examples {
-               dbuf := make([]byte, 2*len(e.e))
-               _, err := Decode(dbuf, []byte(e.e))
-               switch err := err.(type) {
-               case CorruptInputError:
-                       testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p)
-               default:
-                       t.Error("Decoder failed to detect corruption in", e)
-               }
-       }
-}
-
-func TestGitBig(t *testing.T) {
-       n := 3*1000 + 1
-       raw := make([]byte, n)
-       const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
-       for i := 0; i < n; i++ {
-               raw[i] = alpha[i%len(alpha)]
-       }
-       encoded := new(bytes.Buffer)
-       w := NewEncoder(encoded)
-       nn, err := w.Write(raw)
-       if nn != n || err != nil {
-               t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
-       }
-       err = w.Close()
-       if err != nil {
-               t.Fatalf("Encoder.Close() = %v want nil", err)
-       }
-       decoded, err := ioutil.ReadAll(NewDecoder(encoded))
-       if err != nil {
-               t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
-       }
-
-       if !bytes.Equal(raw, decoded) {
-               var i int
-               for i = 0; i < len(decoded) && i < len(raw); i++ {
-                       if decoded[i] != raw[i] {
-                               break
-                       }
-               }
-               t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
-       }
-}
index 4a61d0fb2f8b676c0b17c09cb8e7adc2cdb8000e..6dc7fc9aca0604d523ee262ce55328fe6004fad0 100644 (file)
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// Delete the next line to include this file in the gob package.
+// +build ignore
+
 package gob
 
 // This file is not normally included in the gob package.  Used only for debugging the package itself.
index 5e684d3ee7eba49ab243fc4674b8f8aa9be8bb5f..fb28c8caf53561f24791fbef614e5d4a168d3947 100644 (file)
@@ -75,7 +75,9 @@ func (dec *Decoder) recvMessage() bool {
                dec.err = err
                return false
        }
-       if nbytes >= 1<<31 {
+       // Upper limit of 1GB, allowing room to grow a little without overflow.
+       // TODO: We might want more control over this limit.
+       if nbytes >= 1<<30 {
                dec.err = errBadCount
                return false
        }
index b8dfeeb5156d0e066794ef749c3a6df588b8006d..83644c0331b426437888e3579dba1e3a760fac57 100644 (file)
@@ -547,7 +547,6 @@ func (a isZeroBugArray) GobEncode() (b []byte, e error) {
 }
 
 func (a *isZeroBugArray) GobDecode(data []byte) error {
-       println("DECODE")
        if len(data) != len(a) {
                return io.EOF
        }
index d25ee30a72b0b82387313cdcb41ac779615ba61d..7a05a1bb10e711696920b4095dde5cc08ae5a7c2 100644 (file)
@@ -15,26 +15,13 @@ import (
 )
 
 const (
-       // A generic XML header suitable for use with the output of Marshal and
-       // MarshalIndent.  This is not automatically added to any output of this
-       // package, it is provided as a convenience.
+       // A generic XML header suitable for use with the output of Marshal.
+       // This is not automatically added to any output of this package,
+       // it is provided as a convenience.
        Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
 )
 
-// A Marshaler can produce well-formatted XML representing its internal state.
-// It is used by both Marshal and MarshalIndent.
-type Marshaler interface {
-       MarshalXML() ([]byte, error)
-}
-
-type printer struct {
-       *bufio.Writer
-}
-
-// Marshal writes an XML-formatted representation of v to w.
-//
-// If v implements Marshaler, then Marshal calls its MarshalXML method.
-// Otherwise, Marshal uses the following procedure to create the XML.
+// Marshal returns the XML encoding of v.
 //
 // Marshal handles an array or slice by marshalling each of the elements.
 // Marshal handles a pointer by marshalling the value it points at or, if the
@@ -53,6 +40,7 @@ type printer struct {
 // The XML element for a struct contains marshalled elements for each of the
 // exported fields of the struct, with these exceptions:
 //     - the XMLName field, described above, is omitted.
+//     - a field with tag "-" is omitted.
 //     - a field with tag "name,attr" becomes an attribute with
 //       the given name in the XML element.
 //     - a field with tag ",attr" becomes an attribute with the
@@ -77,7 +65,7 @@ type printer struct {
 //             Age       int      `xml:"person>age"`
 //     }
 //
-//     xml.Marshal(w, &Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
+//     xml.Marshal(&Result{Id: 13, FirstName: "John", LastName: "Doe", Age: 42})
 //
 // would be marshalled as:
 //
@@ -92,13 +80,38 @@ type printer struct {
 //     </result>
 //
 // Marshal will return an error if asked to marshal a channel, function, or map.
-func Marshal(w io.Writer, v interface{}) (err error) {
-       p := &printer{bufio.NewWriter(w)}
-       err = p.marshalValue(reflect.ValueOf(v), nil)
-       p.Flush()
+func Marshal(v interface{}) ([]byte, error) {
+       var b bytes.Buffer
+       if err := NewEncoder(&b).Encode(v); err != nil {
+               return nil, err
+       }
+       return b.Bytes(), nil
+}
+
+// An Encoder writes XML data to an output stream.
+type Encoder struct {
+       printer
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+       return &Encoder{printer{bufio.NewWriter(w)}}
+}
+
+// Encode writes the XML encoding of v to the stream.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+func (enc *Encoder) Encode(v interface{}) error {
+       err := enc.marshalValue(reflect.ValueOf(v), nil)
+       enc.Flush()
        return err
 }
 
+type printer struct {
+       *bufio.Writer
+}
+
 func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
        if !val.IsValid() {
                return nil
@@ -107,18 +120,6 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
        kind := val.Kind()
        typ := val.Type()
 
-       // Try Marshaler
-       if typ.NumMethod() > 0 {
-               if marshaler, ok := val.Interface().(Marshaler); ok {
-                       bytes, err := marshaler.MarshalXML()
-                       if err != nil {
-                               return err
-                       }
-                       p.Write(bytes)
-                       return nil
-               }
-       }
-
        // Drill into pointers/interfaces
        if kind == reflect.Ptr || kind == reflect.Interface {
                if val.IsNil() {
@@ -181,23 +182,43 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
                if finfo.flags&fAttr == 0 {
                        continue
                }
-               var str string
-               if fv := val.FieldByIndex(finfo.idx); fv.Kind() == reflect.String {
-                       str = fv.String()
-               } else {
-                       str = fmt.Sprint(fv.Interface())
+               fv := val.FieldByIndex(finfo.idx)
+               switch fv.Kind() {
+               case reflect.String, reflect.Array, reflect.Slice:
+                       // TODO: Should we really do this once ,omitempty is in?
+                       if fv.Len() == 0 {
+                               continue
+                       }
                }
-               if str != "" {
-                       p.WriteByte(' ')
-                       p.WriteString(finfo.name)
-                       p.WriteString(`="`)
-                       Escape(p, []byte(str))
-                       p.WriteByte('"')
+               p.WriteByte(' ')
+               p.WriteString(finfo.name)
+               p.WriteString(`="`)
+               if err := p.marshalSimple(fv.Type(), fv); err != nil {
+                       return err
                }
+               p.WriteByte('"')
        }
        p.WriteByte('>')
 
-       switch k := val.Kind(); k {
+       if val.Kind() == reflect.Struct {
+               err = p.marshalStruct(tinfo, val)
+       } else {
+               err = p.marshalSimple(typ, val)
+       }
+       if err != nil {
+               return err
+       }
+
+       p.WriteByte('<')
+       p.WriteByte('/')
+       p.WriteString(name)
+       p.WriteByte('>')
+
+       return nil
+}
+
+func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
+       switch val.Kind() {
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
                p.WriteString(strconv.FormatInt(val.Int(), 10))
        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
@@ -205,6 +226,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
        case reflect.Float32, reflect.Float64:
                p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, 64))
        case reflect.String:
+               // TODO: Add EscapeString.
                Escape(p, []byte(val.String()))
        case reflect.Bool:
                p.WriteString(strconv.FormatBool(val.Bool()))
@@ -217,21 +239,10 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
                Escape(p, bytes)
        case reflect.Slice:
                // will be []byte
-               bytes := val.Interface().([]byte)
-               Escape(p, bytes)
-       case reflect.Struct:
-               if err := p.marshalStruct(tinfo, val); err != nil {
-                       return err
-               }
+               Escape(p, val.Bytes())
        default:
                return &UnsupportedTypeError{typ}
        }
-
-       p.WriteByte('<')
-       p.WriteByte('/')
-       p.WriteString(name)
-       p.WriteByte('>')
-
        return nil
 }
 
@@ -358,7 +369,7 @@ func (s *parentStack) push(parents []string) {
        s.stack = append(s.stack, parents...)
 }
 
-// A MarshalXMLError is returned when Marshal or MarshalIndent encounter a type
+// A MarshalXMLError is returned when Marshal encounters a type
 // that cannot be converted into XML.
 type UnsupportedTypeError struct {
        Type reflect.Type
index f23b2cb7e080e2bc226d45ecbd789f1f65503c69..e0be33200864e9af9ffcc346963057f644fd0b6d 100644 (file)
@@ -5,7 +5,6 @@
 package xml
 
 import (
-       "bytes"
        "reflect"
        "strconv"
        "strings"
@@ -35,12 +34,6 @@ type Ship struct {
        secret    string
 }
 
-type RawXML string
-
-func (rx RawXML) MarshalXML() ([]byte, error) {
-       return []byte(rx), nil
-}
-
 type NamedType string
 
 type Port struct {
@@ -184,6 +177,22 @@ type RecurseB struct {
        B string
 }
 
+type PresenceTest struct {
+       Exists *struct{}
+}
+
+type IgnoreTest struct {
+       PublicSecret string `xml:"-"`
+}
+
+type MyBytes []byte
+
+type Data struct {
+       Bytes  []byte
+       Attr   []byte `xml:",attr"`
+       Custom MyBytes
+}
+
 type Plain struct {
        V interface{}
 }
@@ -225,6 +234,44 @@ var marshalTests = []struct {
        {Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
        {Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
 
+       // A pointer to struct{} may be used to test for an element's presence.
+       {
+               Value:     &PresenceTest{new(struct{})},
+               ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+       },
+       {
+               Value:     &PresenceTest{},
+               ExpectXML: `<PresenceTest></PresenceTest>`,
+       },
+
+       // A pointer to struct{} may be used to test for an element's presence.
+       {
+               Value:     &PresenceTest{new(struct{})},
+               ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
+       },
+       {
+               Value:     &PresenceTest{},
+               ExpectXML: `<PresenceTest></PresenceTest>`,
+       },
+
+       // A []byte field is only nil if the element was not found.
+       {
+               Value:         &Data{},
+               ExpectXML:     `<Data></Data>`,
+               UnmarshalOnly: true,
+       },
+       {
+               Value:         &Data{Bytes: []byte{}, Custom: MyBytes{}, Attr: []byte{}},
+               ExpectXML:     `<Data Attr=""><Bytes></Bytes><Custom></Custom></Data>`,
+               UnmarshalOnly: true,
+       },
+
+       // Check that []byte works, including named []byte types.
+       {
+               Value:     &Data{Bytes: []byte("ab"), Custom: MyBytes("cd"), Attr: []byte{'v'}},
+               ExpectXML: `<Data Attr="v"><Bytes>ab</Bytes><Custom>cd</Custom></Data>`,
+       },
+
        // Test innerxml
        {
                Value: &SecretAgent{
@@ -245,13 +292,6 @@ var marshalTests = []struct {
                UnmarshalOnly: true,
        },
 
-       // Test marshaller interface
-       {
-               Value:       RawXML("</>"),
-               ExpectXML:   `</>`,
-               MarshalOnly: true,
-       },
-
        // Test structs
        {Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
        {Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
@@ -542,6 +582,22 @@ var marshalTests = []struct {
                },
                ExpectXML: `<RecurseA><A>a1</A><B><A><A>a2</A></A><B>b1</B></B></RecurseA>`,
        },
+
+       // Test ignoring fields via "-" tag
+       {
+               ExpectXML: `<IgnoreTest></IgnoreTest>`,
+               Value:     &IgnoreTest{},
+       },
+       {
+               ExpectXML:   `<IgnoreTest></IgnoreTest>`,
+               Value:       &IgnoreTest{PublicSecret: "can't tell"},
+               MarshalOnly: true,
+       },
+       {
+               ExpectXML:     `<IgnoreTest><PublicSecret>ignore me</PublicSecret></IgnoreTest>`,
+               Value:         &IgnoreTest{},
+               UnmarshalOnly: true,
+       },
 }
 
 func TestMarshal(t *testing.T) {
@@ -549,13 +605,12 @@ func TestMarshal(t *testing.T) {
                if test.UnmarshalOnly {
                        continue
                }
-               buf := bytes.NewBuffer(nil)
-               err := Marshal(buf, test.Value)
+               data, err := Marshal(test.Value)
                if err != nil {
                        t.Errorf("#%d: Error: %s", idx, err)
                        continue
                }
-               if got, want := buf.String(), test.ExpectXML; got != want {
+               if got, want := string(data), test.ExpectXML; got != want {
                        if strings.Contains(want, "\n") {
                                t.Errorf("#%d: marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", idx, test.Value, got, want)
                        } else {
@@ -596,8 +651,7 @@ var marshalErrorTests = []struct {
 
 func TestMarshalErrors(t *testing.T) {
        for idx, test := range marshalErrorTests {
-               buf := bytes.NewBuffer(nil)
-               err := Marshal(buf, test.Value)
+               _, err := Marshal(test.Value)
                if err == nil || err.Error() != test.Err {
                        t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
                }
@@ -621,8 +675,7 @@ func TestUnmarshal(t *testing.T) {
 
                vt := reflect.TypeOf(test.Value)
                dest := reflect.New(vt.Elem()).Interface()
-               buffer := bytes.NewBufferString(test.ExpectXML)
-               err := Unmarshal(buffer, dest)
+               err := Unmarshal([]byte(test.ExpectXML), dest)
 
                switch fix := dest.(type) {
                case *Feed:
@@ -641,17 +694,14 @@ func TestUnmarshal(t *testing.T) {
 }
 
 func BenchmarkMarshal(b *testing.B) {
-       buf := bytes.NewBuffer(nil)
        for i := 0; i < b.N; i++ {
-               Marshal(buf, atomValue)
-               buf.Truncate(0)
+               Marshal(atomValue)
        }
 }
 
 func BenchmarkUnmarshal(b *testing.B) {
        xml := []byte(atomXml)
        for i := 0; i < b.N; i++ {
-               buffer := bytes.NewBuffer(xml)
-               Unmarshal(buffer, &Feed{})
+               Unmarshal(xml, &Feed{})
        }
 }
index 4419ed1e4773fc111b26a891cc10411a40cd008a..871fe059cfa1880d0cf1790368b77048deb1bbff 100644 (file)
@@ -7,7 +7,6 @@ package xml
 import (
        "bytes"
        "errors"
-       "io"
        "reflect"
        "strconv"
        "strings"
@@ -20,10 +19,10 @@ import (
 // See package json for a textual representation more suitable
 // to data structures.
 
-// Unmarshal parses an XML element from r and uses the
-// reflect library to fill in an arbitrary struct, slice, or string
-// pointed at by val.  Well-formed data that does not fit
-// into val is discarded.
+// Unmarshal parses the XML-encoded data and stores the result in
+// the value pointed to by v, which must be an arbitrary struct,
+// slice, or string. Well-formed data that does not fit into v is
+// discarded.
 //
 // For example, given these definitions:
 //
@@ -59,7 +58,7 @@ import (
 //             <address>123 Main Street</address>
 //     </result>
 //
-// via Unmarshal(r, &result) is equivalent to assigning
+// via Unmarshal(data, &result) is equivalent to assigning
 //
 //     r = Result{
 //             xml.Name{Local: "result"},
@@ -78,8 +77,9 @@ import (
 // field tag.
 //
 // Because Unmarshal uses the reflect package, it can only assign
-// to exported (upper case) fields.  Unmarshal uses a case-insensitive
-// comparison to match XML element names to struct field names.
+// to exported (upper case) fields.  Unmarshal uses a case-sensitive
+// comparison to match XML element names to tag values and struct
+// field names.
 //
 // Unmarshal maps an XML element to a struct using the following rules.
 // In the rules, the tag of a field refers to the value associated with the
@@ -132,9 +132,11 @@ import (
 //      of the above rules and the struct has a field with tag ",any",
 //      unmarshal maps the sub-element to that struct field.
 //
+//   * A struct field with tag "-" is never unmarshalled into.
+//
 // Unmarshal maps an XML element to a string or []byte by saving the
 // concatenation of that element's character data in the string or
-// []byte.
+// []byte. The saved []byte is never nil.
 //
 // Unmarshal maps an attribute value to a string or []byte by saving
 // the value in the string or slice.
@@ -156,18 +158,26 @@ import (
 // Unmarshal maps an XML element to a pointer by setting the pointer
 // to a freshly allocated value and then mapping the element to that value.
 //
-func Unmarshal(r io.Reader, val interface{}) error {
-       v := reflect.ValueOf(val)
-       if v.Kind() != reflect.Ptr {
+func Unmarshal(data []byte, v interface{}) error {
+       return NewDecoder(bytes.NewBuffer(data)).Decode(v)
+}
+
+// Decode works like xml.Unmarshal, except it reads the decoder
+// stream to find the start element.
+func (d *Decoder) Decode(v interface{}) error {
+       return d.DecodeElement(v, nil)
+}
+
+// DecodeElement works like xml.Unmarshal except that it takes
+// a pointer to the start XML element to decode into v.
+// It is useful when a client reads some raw XML tokens itself
+// but also wants to defer to Unmarshal for some elements.
+func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
+       val := reflect.ValueOf(v)
+       if val.Kind() != reflect.Ptr {
                return errors.New("non-pointer passed to Unmarshal")
        }
-       p := NewParser(r)
-       elem := v.Elem()
-       err := p.unmarshal(elem, nil)
-       if err != nil {
-               return err
-       }
-       return nil
+       return d.unmarshal(val.Elem(), start)
 }
 
 // An UnmarshalError represents an error in the unmarshalling process.
@@ -175,22 +185,8 @@ type UnmarshalError string
 
 func (e UnmarshalError) Error() string { return string(e) }
 
-// The Parser's Unmarshal method is like xml.Unmarshal
-// except that it can be passed a pointer to the initial start element,
-// useful when a client reads some raw XML tokens itself
-// but also defers to Unmarshal for some elements.
-// Passing a nil start element indicates that Unmarshal should
-// read the token stream to find the start element.
-func (p *Parser) Unmarshal(val interface{}, start *StartElement) error {
-       v := reflect.ValueOf(val)
-       if v.Kind() != reflect.Ptr {
-               return errors.New("non-pointer passed to Unmarshal")
-       }
-       return p.unmarshal(v.Elem(), start)
-}
-
 // Unmarshal a single XML element into val.
-func (p *Parser) unmarshal(val reflect.Value, start *StartElement) error {
+func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
        // Find start element if we need it.
        if start == nil {
                for {
@@ -309,14 +305,12 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) error {
                        case fAttr:
                                strv := sv.FieldByIndex(finfo.idx)
                                // Look for attribute.
-                               val := ""
                                for _, a := range start.Attr {
                                        if a.Name.Local == finfo.name {
-                                               val = a.Value
+                                               copyValue(strv, []byte(a.Value))
                                                break
                                        }
                                }
-                               copyValue(strv, []byte(val))
 
                        case fCharData:
                                if !saveData.IsValid() {
@@ -473,7 +467,11 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
        case reflect.String:
                t.SetString(string(src))
        case reflect.Slice:
-               t.Set(reflect.ValueOf(src))
+               if len(src) == 0 {
+                       // non-nil to flag presence
+                       src = []byte{}
+               }
+               t.SetBytes(src)
        }
        return nil
 }
@@ -481,9 +479,9 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
 // unmarshalPath walks down an XML structure looking for wanted
 // paths, and calls unmarshal on them.
 // The consumed result tells whether XML elements have been consumed
-// from the Parser until start's matching end element, or if it's
+// from the Decoder until start's matching end element, or if it's
 // still untouched because start is uninteresting for sv's fields.
-func (p *Parser) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
+func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
        recurse := false
 Loop:
        for i := range tinfo.fields {
@@ -547,7 +545,7 @@ Loop:
 // Read tokens until we find the end element.
 // Token is taking care of making sure the
 // end element matches the start element we saw.
-func (p *Parser) Skip() error {
+func (p *Decoder) Skip() error {
        for {
                tok, err := p.Token()
                if err != nil {
index ff61bd7e1c51eee836fc2c75db1aa79e6d65151a..833eafc9a586909637a626eb902e0894e1ce589b 100644 (file)
@@ -6,7 +6,6 @@ package xml
 
 import (
        "reflect"
-       "strings"
        "testing"
 )
 
@@ -14,7 +13,7 @@ import (
 
 func TestUnmarshalFeed(t *testing.T) {
        var f Feed
-       if err := Unmarshal(strings.NewReader(atomFeedString), &f); err != nil {
+       if err := Unmarshal([]byte(atomFeedString), &f); err != nil {
                t.Fatalf("Unmarshal: %s", err)
        }
        if !reflect.DeepEqual(f, atomFeed) {
@@ -281,7 +280,7 @@ var pathTests = []interface{}{
 func TestUnmarshalPaths(t *testing.T) {
        for _, pt := range pathTests {
                v := reflect.New(reflect.TypeOf(pt).Elem()).Interface()
-               if err := Unmarshal(strings.NewReader(pathTestString), v); err != nil {
+               if err := Unmarshal([]byte(pathTestString), v); err != nil {
                        t.Fatalf("Unmarshal: %s", err)
                }
                if !reflect.DeepEqual(v, pt) {
@@ -331,7 +330,7 @@ var badPathTests = []struct {
 
 func TestUnmarshalBadPaths(t *testing.T) {
        for _, tt := range badPathTests {
-               err := Unmarshal(strings.NewReader(pathTestString), tt.v)
+               err := Unmarshal([]byte(pathTestString), tt.v)
                if !reflect.DeepEqual(err, tt.e) {
                        t.Fatalf("Unmarshal with %#v didn't fail properly:\nhave %#v,\nwant %#v", tt.v, err, tt.e)
                }
@@ -350,7 +349,7 @@ type TestThree struct {
 
 func TestUnmarshalWithoutNameType(t *testing.T) {
        var x TestThree
-       if err := Unmarshal(strings.NewReader(withoutNameTypeData), &x); err != nil {
+       if err := Unmarshal([]byte(withoutNameTypeData), &x); err != nil {
                t.Fatalf("Unmarshal: %s", err)
        }
        if x.Attr != OK {
index 36b35ed2ee888920cf6ec75c68c7cc04144a21de..2bf2c6b3032e98d580e7fabc62c6b6dc3f9db16d 100644 (file)
@@ -37,7 +37,6 @@ const (
        fAny
 
        // TODO:
-       //fIgnore
        //fOmitEmpty
 
        fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
@@ -62,7 +61,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
                n := typ.NumField()
                for i := 0; i < n; i++ {
                        f := typ.Field(i)
-                       if f.PkgPath != "" {
+                       if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
                                continue // Private field
                        }
 
index d001c4089236aad6156c4193a3e920f51d6c8b96..5066f5c01067f9bc69d324bc997644b5fd893e64 100644 (file)
@@ -36,7 +36,7 @@ func (e *SyntaxError) Error() string {
 
 // A Name represents an XML name (Local) annotated
 // with a name space identifier (Space).
-// In tokens returned by Parser.Token, the Space identifier
+// In tokens returned by Decoder.Token, the Space identifier
 // is given as a canonical URL, not the short prefix used
 // in the document being parsed.
 type Name struct {
@@ -124,9 +124,9 @@ func CopyToken(t Token) Token {
        return t
 }
 
-// A Parser represents an XML parser reading a particular input stream.
+// A Decoder represents an XML parser reading a particular input stream.
 // The parser assumes that its input is encoded in UTF-8.
-type Parser struct {
+type Decoder struct {
        // Strict defaults to true, enforcing the requirements
        // of the XML specification.
        // If set to false, the parser allows input containing common
@@ -139,9 +139,9 @@ type Parser struct {
        //
        // Setting:
        //
-       //      p.Strict = false;
-       //      p.AutoClose = HTMLAutoClose;
-       //      p.Entity = HTMLEntity
+       //      d.Strict = false;
+       //      d.AutoClose = HTMLAutoClose;
+       //      d.Entity = HTMLEntity
        //
        // creates a parser that can handle typical HTML.
        Strict bool
@@ -184,16 +184,16 @@ type Parser struct {
        tmp       [32]byte
 }
 
-// NewParser creates a new XML parser reading from r.
-func NewParser(r io.Reader) *Parser {
-       p := &Parser{
+// NewDecoder creates a new XML parser reading from r.
+func NewDecoder(r io.Reader) *Decoder {
+       d := &Decoder{
                ns:       make(map[string]string),
                nextByte: -1,
                line:     1,
                Strict:   true,
        }
-       p.switchToReader(r)
-       return p
+       d.switchToReader(r)
+       return d
 }
 
 // Token returns the next XML token in the input stream.
@@ -218,17 +218,17 @@ func NewParser(r io.Reader) *Parser {
 // set to the URL identifying its name space when known.
 // If Token encounters an unrecognized name space prefix,
 // it uses the prefix as the Space rather than report an error.
-func (p *Parser) Token() (t Token, err error) {
-       if p.nextToken != nil {
-               t = p.nextToken
-               p.nextToken = nil
-       } else if t, err = p.RawToken(); err != nil {
+func (d *Decoder) Token() (t Token, err error) {
+       if d.nextToken != nil {
+               t = d.nextToken
+               d.nextToken = nil
+       } else if t, err = d.RawToken(); err != nil {
                return
        }
 
-       if !p.Strict {
-               if t1, ok := p.autoClose(t); ok {
-                       p.nextToken = t
+       if !d.Strict {
+               if t1, ok := d.autoClose(t); ok {
+                       d.nextToken = t
                        t = t1
                }
        }
@@ -240,29 +240,29 @@ func (p *Parser) Token() (t Token, err error) {
                // the translations first.
                for _, a := range t1.Attr {
                        if a.Name.Space == "xmlns" {
-                               v, ok := p.ns[a.Name.Local]
-                               p.pushNs(a.Name.Local, v, ok)
-                               p.ns[a.Name.Local] = a.Value
+                               v, ok := d.ns[a.Name.Local]
+                               d.pushNs(a.Name.Local, v, ok)
+                               d.ns[a.Name.Local] = a.Value
                        }
                        if a.Name.Space == "" && a.Name.Local == "xmlns" {
                                // Default space for untagged names
-                               v, ok := p.ns[""]
-                               p.pushNs("", v, ok)
-                               p.ns[""] = a.Value
+                               v, ok := d.ns[""]
+                               d.pushNs("", v, ok)
+                               d.ns[""] = a.Value
                        }
                }
 
-               p.translate(&t1.Name, true)
+               d.translate(&t1.Name, true)
                for i := range t1.Attr {
-                       p.translate(&t1.Attr[i].Name, false)
+                       d.translate(&t1.Attr[i].Name, false)
                }
-               p.pushElement(t1.Name)
+               d.pushElement(t1.Name)
                t = t1
 
        case EndElement:
-               p.translate(&t1.Name, true)
-               if !p.popElement(&t1) {
-                       return nil, p.err
+               d.translate(&t1.Name, true)
+               if !d.popElement(&t1) {
+                       return nil, d.err
                }
                t = t1
        }
@@ -272,7 +272,7 @@ func (p *Parser) Token() (t Token, err error) {
 // Apply name space translation to name n.
 // The default name space (for Space=="")
 // applies only to element names, not to attribute names.
-func (p *Parser) translate(n *Name, isElementName bool) {
+func (d *Decoder) translate(n *Name, isElementName bool) {
        switch {
        case n.Space == "xmlns":
                return
@@ -281,20 +281,20 @@ func (p *Parser) translate(n *Name, isElementName bool) {
        case n.Space == "" && n.Local == "xmlns":
                return
        }
-       if v, ok := p.ns[n.Space]; ok {
+       if v, ok := d.ns[n.Space]; ok {
                n.Space = v
        }
 }
 
-func (p *Parser) switchToReader(r io.Reader) {
+func (d *Decoder) switchToReader(r io.Reader) {
        // Get efficient byte at a time reader.
        // Assume that if reader has its own
        // ReadByte, it's efficient enough.
        // Otherwise, use bufio.
        if rb, ok := r.(io.ByteReader); ok {
-               p.r = rb
+               d.r = rb
        } else {
-               p.r = bufio.NewReader(r)
+               d.r = bufio.NewReader(r)
        }
 }
 
@@ -314,47 +314,47 @@ const (
        stkNs
 )
 
-func (p *Parser) push(kind int) *stack {
-       s := p.free
+func (d *Decoder) push(kind int) *stack {
+       s := d.free
        if s != nil {
-               p.free = s.next
+               d.free = s.next
        } else {
                s = new(stack)
        }
-       s.next = p.stk
+       s.next = d.stk
        s.kind = kind
-       p.stk = s
+       d.stk = s
        return s
 }
 
-func (p *Parser) pop() *stack {
-       s := p.stk
+func (d *Decoder) pop() *stack {
+       s := d.stk
        if s != nil {
-               p.stk = s.next
-               s.next = p.free
-               p.free = s
+               d.stk = s.next
+               s.next = d.free
+               d.free = s
        }
        return s
 }
 
 // Record that we are starting an element with the given name.
-func (p *Parser) pushElement(name Name) {
-       s := p.push(stkStart)
+func (d *Decoder) pushElement(name Name) {
+       s := d.push(stkStart)
        s.name = name
 }
 
 // Record that we are changing the value of ns[local].
 // The old value is url, ok.
-func (p *Parser) pushNs(local string, url string, ok bool) {
-       s := p.push(stkNs)
+func (d *Decoder) pushNs(local string, url string, ok bool) {
+       s := d.push(stkNs)
        s.name.Local = local
        s.name.Space = url
        s.ok = ok
 }
 
 // Creates a SyntaxError with the current line number.
-func (p *Parser) syntaxError(msg string) error {
-       return &SyntaxError{Msg: msg, Line: p.line}
+func (d *Decoder) syntaxError(msg string) error {
+       return &SyntaxError{Msg: msg, Line: d.line}
 }
 
 // Record that we are ending an element with the given name.
@@ -363,36 +363,36 @@ func (p *Parser) syntaxError(msg string) error {
 // After popping the element, apply any undo records from
 // the stack to restore the name translations that existed
 // before we saw this element.
-func (p *Parser) popElement(t *EndElement) bool {
-       s := p.pop()
+func (d *Decoder) popElement(t *EndElement) bool {
+       s := d.pop()
        name := t.Name
        switch {
        case s == nil || s.kind != stkStart:
-               p.err = p.syntaxError("unexpected end element </" + name.Local + ">")
+               d.err = d.syntaxError("unexpected end element </" + name.Local + ">")
                return false
        case s.name.Local != name.Local:
-               if !p.Strict {
-                       p.needClose = true
-                       p.toClose = t.Name
+               if !d.Strict {
+                       d.needClose = true
+                       d.toClose = t.Name
                        t.Name = s.name
                        return true
                }
-               p.err = p.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
+               d.err = d.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
                return false
        case s.name.Space != name.Space:
-               p.err = p.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
+               d.err = d.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
                        "closed by </" + name.Local + "> in space " + name.Space)
                return false
        }
 
        // Pop stack until a Start is on the top, undoing the
        // translations that were associated with the element we just closed.
-       for p.stk != nil && p.stk.kind != stkStart {
-               s := p.pop()
+       for d.stk != nil && d.stk.kind != stkStart {
+               s := d.pop()
                if s.ok {
-                       p.ns[s.name.Local] = s.name.Space
+                       d.ns[s.name.Local] = s.name.Space
                } else {
-                       delete(p.ns, s.name.Local)
+                       delete(d.ns, s.name.Local)
                }
        }
 
@@ -401,17 +401,17 @@ func (p *Parser) popElement(t *EndElement) bool {
 
 // If the top element on the stack is autoclosing and
 // t is not the end tag, invent the end tag.
-func (p *Parser) autoClose(t Token) (Token, bool) {
-       if p.stk == nil || p.stk.kind != stkStart {
+func (d *Decoder) autoClose(t Token) (Token, bool) {
+       if d.stk == nil || d.stk.kind != stkStart {
                return nil, false
        }
-       name := strings.ToLower(p.stk.name.Local)
-       for _, s := range p.AutoClose {
+       name := strings.ToLower(d.stk.name.Local)
+       for _, s := range d.AutoClose {
                if strings.ToLower(s) == name {
                        // This one should be auto closed if t doesn't close it.
                        et, ok := t.(EndElement)
                        if !ok || et.Name.Local != name {
-                               return EndElement{p.stk.name}, true
+                               return EndElement{d.stk.name}, true
                        }
                        break
                }
@@ -422,53 +422,53 @@ func (p *Parser) autoClose(t Token) (Token, bool) {
 // RawToken is like Token but does not verify that
 // start and end elements match and does not translate
 // name space prefixes to their corresponding URLs.
-func (p *Parser) RawToken() (Token, error) {
-       if p.err != nil {
-               return nil, p.err
+func (d *Decoder) RawToken() (Token, error) {
+       if d.err != nil {
+               return nil, d.err
        }
-       if p.needClose {
+       if d.needClose {
                // The last element we read was self-closing and
                // we returned just the StartElement half.
                // Return the EndElement half now.
-               p.needClose = false
-               return EndElement{p.toClose}, nil
+               d.needClose = false
+               return EndElement{d.toClose}, nil
        }
 
-       b, ok := p.getc()
+       b, ok := d.getc()
        if !ok {
-               return nil, p.err
+               return nil, d.err
        }
 
        if b != '<' {
                // Text section.
-               p.ungetc(b)
-               data := p.text(-1, false)
+               d.ungetc(b)
+               data := d.text(-1, false)
                if data == nil {
-                       return nil, p.err
+                       return nil, d.err
                }
                return CharData(data), nil
        }
 
-       if b, ok = p.mustgetc(); !ok {
-               return nil, p.err
+       if b, ok = d.mustgetc(); !ok {
+               return nil, d.err
        }
        switch b {
        case '/':
                // </: End element
                var name Name
-               if name, ok = p.nsname(); !ok {
-                       if p.err == nil {
-                               p.err = p.syntaxError("expected element name after </")
+               if name, ok = d.nsname(); !ok {
+                       if d.err == nil {
+                               d.err = d.syntaxError("expected element name after </")
                        }
-                       return nil, p.err
+                       return nil, d.err
                }
-               p.space()
-               if b, ok = p.mustgetc(); !ok {
-                       return nil, p.err
+               d.space()
+               if b, ok = d.mustgetc(); !ok {
+                       return nil, d.err
                }
                if b != '>' {
-                       p.err = p.syntaxError("invalid characters between </" + name.Local + " and >")
-                       return nil, p.err
+                       d.err = d.syntaxError("invalid characters between </" + name.Local + " and >")
+                       return nil, d.err
                }
                return EndElement{name}, nil
 
@@ -477,95 +477,95 @@ func (p *Parser) RawToken() (Token, error) {
                // TODO(rsc): Should parse the <?xml declaration to make sure
                // the version is 1.0 and the encoding is UTF-8.
                var target string
-               if target, ok = p.name(); !ok {
-                       if p.err == nil {
-                               p.err = p.syntaxError("expected target name after <?")
+               if target, ok = d.name(); !ok {
+                       if d.err == nil {
+                               d.err = d.syntaxError("expected target name after <?")
                        }
-                       return nil, p.err
+                       return nil, d.err
                }
-               p.space()
-               p.buf.Reset()
+               d.space()
+               d.buf.Reset()
                var b0 byte
                for {
-                       if b, ok = p.mustgetc(); !ok {
-                               return nil, p.err
+                       if b, ok = d.mustgetc(); !ok {
+                               return nil, d.err
                        }
-                       p.buf.WriteByte(b)
+                       d.buf.WriteByte(b)
                        if b0 == '?' && b == '>' {
                                break
                        }
                        b0 = b
                }
-               data := p.buf.Bytes()
+               data := d.buf.Bytes()
                data = data[0 : len(data)-2] // chop ?>
 
                if target == "xml" {
                        enc := procInstEncoding(string(data))
                        if enc != "" && enc != "utf-8" && enc != "UTF-8" {
-                               if p.CharsetReader == nil {
-                                       p.err = fmt.Errorf("xml: encoding %q declared but Parser.CharsetReader is nil", enc)
-                                       return nil, p.err
+                               if d.CharsetReader == nil {
+                                       d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc)
+                                       return nil, d.err
                                }
-                               newr, err := p.CharsetReader(enc, p.r.(io.Reader))
+                               newr, err := d.CharsetReader(enc, d.r.(io.Reader))
                                if err != nil {
-                                       p.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
-                                       return nil, p.err
+                                       d.err = fmt.Errorf("xml: opening charset %q: %v", enc, err)
+                                       return nil, d.err
                                }
                                if newr == nil {
                                        panic("CharsetReader returned a nil Reader for charset " + enc)
                                }
-                               p.switchToReader(newr)
+                               d.switchToReader(newr)
                        }
                }
                return ProcInst{target, data}, nil
 
        case '!':
                // <!: Maybe comment, maybe CDATA.
-               if b, ok = p.mustgetc(); !ok {
-                       return nil, p.err
+               if b, ok = d.mustgetc(); !ok {
+                       return nil, d.err
                }
                switch b {
                case '-': // <!-
                        // Probably <!-- for a comment.
-                       if b, ok = p.mustgetc(); !ok {
-                               return nil, p.err
+                       if b, ok = d.mustgetc(); !ok {
+                               return nil, d.err
                        }
                        if b != '-' {
-                               p.err = p.syntaxError("invalid sequence <!- not part of <!--")
-                               return nil, p.err
+                               d.err = d.syntaxError("invalid sequence <!- not part of <!--")
+                               return nil, d.err
                        }
                        // Look for terminator.
-                       p.buf.Reset()
+                       d.buf.Reset()
                        var b0, b1 byte
                        for {
-                               if b, ok = p.mustgetc(); !ok {
-                                       return nil, p.err
+                               if b, ok = d.mustgetc(); !ok {
+                                       return nil, d.err
                                }
-                               p.buf.WriteByte(b)
+                               d.buf.WriteByte(b)
                                if b0 == '-' && b1 == '-' && b == '>' {
                                        break
                                }
                                b0, b1 = b1, b
                        }
-                       data := p.buf.Bytes()
+                       data := d.buf.Bytes()
                        data = data[0 : len(data)-3] // chop -->
                        return Comment(data), nil
 
                case '[': // <![
                        // Probably <![CDATA[.
                        for i := 0; i < 6; i++ {
-                               if b, ok = p.mustgetc(); !ok {
-                                       return nil, p.err
+                               if b, ok = d.mustgetc(); !ok {
+                                       return nil, d.err
                                }
                                if b != "CDATA["[i] {
-                                       p.err = p.syntaxError("invalid <![ sequence")
-                                       return nil, p.err
+                                       d.err = d.syntaxError("invalid <![ sequence")
+                                       return nil, d.err
                                }
                        }
                        // Have <![CDATA[.  Read text until ]]>.
-                       data := p.text(-1, true)
+                       data := d.text(-1, true)
                        if data == nil {
-                               return nil, p.err
+                               return nil, d.err
                        }
                        return CharData(data), nil
                }
@@ -573,18 +573,18 @@ func (p *Parser) RawToken() (Token, error) {
                // Probably a directive: <!DOCTYPE ...>, <!ENTITY ...>, etc.
                // We don't care, but accumulate for caller. Quoted angle
                // brackets do not count for nesting.
-               p.buf.Reset()
-               p.buf.WriteByte(b)
+               d.buf.Reset()
+               d.buf.WriteByte(b)
                inquote := uint8(0)
                depth := 0
                for {
-                       if b, ok = p.mustgetc(); !ok {
-                               return nil, p.err
+                       if b, ok = d.mustgetc(); !ok {
+                               return nil, d.err
                        }
                        if inquote == 0 && b == '>' && depth == 0 {
                                break
                        }
-                       p.buf.WriteByte(b)
+                       d.buf.WriteByte(b)
                        switch {
                        case b == inquote:
                                inquote = 0
@@ -602,45 +602,45 @@ func (p *Parser) RawToken() (Token, error) {
                                depth++
                        }
                }
-               return Directive(p.buf.Bytes()), nil
+               return Directive(d.buf.Bytes()), nil
        }
 
        // Must be an open element like <a href="foo">
-       p.ungetc(b)
+       d.ungetc(b)
 
        var (
                name  Name
                empty bool
                attr  []Attr
        )
-       if name, ok = p.nsname(); !ok {
-               if p.err == nil {
-                       p.err = p.syntaxError("expected element name after <")
+       if name, ok = d.nsname(); !ok {
+               if d.err == nil {
+                       d.err = d.syntaxError("expected element name after <")
                }
-               return nil, p.err
+               return nil, d.err
        }
 
        attr = make([]Attr, 0, 4)
        for {
-               p.space()
-               if b, ok = p.mustgetc(); !ok {
-                       return nil, p.err
+               d.space()
+               if b, ok = d.mustgetc(); !ok {
+                       return nil, d.err
                }
                if b == '/' {
                        empty = true
-                       if b, ok = p.mustgetc(); !ok {
-                               return nil, p.err
+                       if b, ok = d.mustgetc(); !ok {
+                               return nil, d.err
                        }
                        if b != '>' {
-                               p.err = p.syntaxError("expected /> in element")
-                               return nil, p.err
+                               d.err = d.syntaxError("expected /> in element")
+                               return nil, d.err
                        }
                        break
                }
                if b == '>' {
                        break
                }
-               p.ungetc(b)
+               d.ungetc(b)
 
                n := len(attr)
                if n >= cap(attr) {
@@ -650,85 +650,85 @@ func (p *Parser) RawToken() (Token, error) {
                }
                attr = attr[0 : n+1]
                a := &attr[n]
-               if a.Name, ok = p.nsname(); !ok {
-                       if p.err == nil {
-                               p.err = p.syntaxError("expected attribute name in element")
+               if a.Name, ok = d.nsname(); !ok {
+                       if d.err == nil {
+                               d.err = d.syntaxError("expected attribute name in element")
                        }
-                       return nil, p.err
+                       return nil, d.err
                }
-               p.space()
-               if b, ok = p.mustgetc(); !ok {
-                       return nil, p.err
+               d.space()
+               if b, ok = d.mustgetc(); !ok {
+                       return nil, d.err
                }
                if b != '=' {
-                       if p.Strict {
-                               p.err = p.syntaxError("attribute name without = in element")
-                               return nil, p.err
+                       if d.Strict {
+                               d.err = d.syntaxError("attribute name without = in element")
+                               return nil, d.err
                        } else {
-                               p.ungetc(b)
+                               d.ungetc(b)
                                a.Value = a.Name.Local
                        }
                } else {
-                       p.space()
-                       data := p.attrval()
+                       d.space()
+                       data := d.attrval()
                        if data == nil {
-                               return nil, p.err
+                               return nil, d.err
                        }
                        a.Value = string(data)
                }
        }
        if empty {
-               p.needClose = true
-               p.toClose = name
+               d.needClose = true
+               d.toClose = name
        }
        return StartElement{name, attr}, nil
 }
 
-func (p *Parser) attrval() []byte {
-       b, ok := p.mustgetc()
+func (d *Decoder) attrval() []byte {
+       b, ok := d.mustgetc()
        if !ok {
                return nil
        }
        // Handle quoted attribute values
        if b == '"' || b == '\'' {
-               return p.text(int(b), false)
+               return d.text(int(b), false)
        }
        // Handle unquoted attribute values for strict parsers
-       if p.Strict {
-               p.err = p.syntaxError("unquoted or missing attribute value in element")
+       if d.Strict {
+               d.err = d.syntaxError("unquoted or missing attribute value in element")
                return nil
        }
        // Handle unquoted attribute values for unstrict parsers
-       p.ungetc(b)
-       p.buf.Reset()
+       d.ungetc(b)
+       d.buf.Reset()
        for {
-               b, ok = p.mustgetc()
+               b, ok = d.mustgetc()
                if !ok {
                        return nil
                }
                // http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
                if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' ||
                        '0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' {
-                       p.buf.WriteByte(b)
+                       d.buf.WriteByte(b)
                } else {
-                       p.ungetc(b)
+                       d.ungetc(b)
                        break
                }
        }
-       return p.buf.Bytes()
+       return d.buf.Bytes()
 }
 
 // Skip spaces if any
-func (p *Parser) space() {
+func (d *Decoder) space() {
        for {
-               b, ok := p.getc()
+               b, ok := d.getc()
                if !ok {
                        return
                }
                switch b {
                case ' ', '\r', '\n', '\t':
                default:
-                       p.ungetc(b)
+                       d.ungetc(b)
                        return
                }
        }
@@ -736,35 +736,35 @@ func (p *Parser) space() {
 
 // Read a single byte.
 // If there is no byte to read, return ok==false
-// and leave the error in p.err.
+// and leave the error in d.err.
 // Maintain line number.
-func (p *Parser) getc() (b byte, ok bool) {
-       if p.err != nil {
+func (d *Decoder) getc() (b byte, ok bool) {
+       if d.err != nil {
                return 0, false
        }
-       if p.nextByte >= 0 {
-               b = byte(p.nextByte)
-               p.nextByte = -1
+       if d.nextByte >= 0 {
+               b = byte(d.nextByte)
+               d.nextByte = -1
        } else {
-               b, p.err = p.r.ReadByte()
-               if p.err != nil {
+               b, d.err = d.r.ReadByte()
+               if d.err != nil {
                        return 0, false
                }
-               if p.saved != nil {
-                       p.saved.WriteByte(b)
+               if d.saved != nil {
+                       d.saved.WriteByte(b)
                }
        }
        if b == '\n' {
-               p.line++
+               d.line++
        }
        return b, true
 }
 
 // Return saved offset.
 // If we did ungetc (nextByte >= 0), have to back up one.
-func (p *Parser) savedOffset() int {
-       n := p.saved.Len()
-       if p.nextByte >= 0 {
+func (d *Decoder) savedOffset() int {
+       n := d.saved.Len()
+       if d.nextByte >= 0 {
                n--
        }
        return n
@@ -772,23 +772,23 @@ func (p *Parser) savedOffset() int {
 
 // Must read a single byte.
 // If there is no byte to read,
-// set p.err to SyntaxError("unexpected EOF")
+// set d.err to SyntaxError("unexpected EOF")
 // and return ok==false
-func (p *Parser) mustgetc() (b byte, ok bool) {
-       if b, ok = p.getc(); !ok {
-               if p.err == io.EOF {
-                       p.err = p.syntaxError("unexpected EOF")
+func (d *Decoder) mustgetc() (b byte, ok bool) {
+       if b, ok = d.getc(); !ok {
+               if d.err == io.EOF {
+                       d.err = d.syntaxError("unexpected EOF")
                }
        }
        return
 }
 
 // Unread a single byte.
-func (p *Parser) ungetc(b byte) {
+func (d *Decoder) ungetc(b byte) {
        if b == '\n' {
-               p.line--
+               d.line--
        }
-       p.nextByte = int(b)
+       d.nextByte = int(b)
 }
 
 var entity = map[string]int{
@@ -802,18 +802,18 @@ var entity = map[string]int{
 // Read plain text section (XML calls it character data).
 // If quote >= 0, we are in a quoted string and need to find the matching quote.
 // If cdata == true, we are in a <![CDATA[ section and need to find ]]>.
-// On failure return nil and leave the error in p.err.
-func (p *Parser) text(quote int, cdata bool) []byte {
+// On failure return nil and leave the error in d.err.
+func (d *Decoder) text(quote int, cdata bool) []byte {
        var b0, b1 byte
        var trunc int
-       p.buf.Reset()
+       d.buf.Reset()
 Input:
        for {
-               b, ok := p.getc()
+               b, ok := d.getc()
                if !ok {
                        if cdata {
-                               if p.err == io.EOF {
-                                       p.err = p.syntaxError("unexpected EOF in CDATA section")
+                               if d.err == io.EOF {
+                                       d.err = d.syntaxError("unexpected EOF in CDATA section")
                                }
                                return nil
                        }
@@ -827,17 +827,17 @@ Input:
                                trunc = 2
                                break Input
                        }
-                       p.err = p.syntaxError("unescaped ]]> not in CDATA section")
+                       d.err = d.syntaxError("unescaped ]]> not in CDATA section")
                        return nil
                }
 
                // Stop reading text if we see a <.
                if b == '<' && !cdata {
                        if quote >= 0 {
-                               p.err = p.syntaxError("unescaped < inside quoted string")
+                               d.err = d.syntaxError("unescaped < inside quoted string")
                                return nil
                        }
-                       p.ungetc('<')
+                       d.ungetc('<')
                        break Input
                }
                if quote >= 0 && b == byte(quote) {
@@ -850,16 +850,16 @@ Input:
                        // Parsers are required to recognize lt, gt, amp, apos, and quot
                        // even if they have not been declared.  That's all we allow.
                        var i int
-                       for i = 0; i < len(p.tmp); i++ {
+                       for i = 0; i < len(d.tmp); i++ {
                                var ok bool
-                               p.tmp[i], ok = p.getc()
+                               d.tmp[i], ok = d.getc()
                                if !ok {
-                                       if p.err == io.EOF {
-                                               p.err = p.syntaxError("unexpected EOF")
+                                       if d.err == io.EOF {
+                                               d.err = d.syntaxError("unexpected EOF")
                                        }
                                        return nil
                                }
-                               c := p.tmp[i]
+                               c := d.tmp[i]
                                if c == ';' {
                                        break
                                }
@@ -869,18 +869,18 @@ Input:
                                        c == '_' || c == '#' {
                                        continue
                                }
-                               p.ungetc(c)
+                               d.ungetc(c)
                                break
                        }
-                       s := string(p.tmp[0:i])
-                       if i >= len(p.tmp) {
-                               if !p.Strict {
+                       s := string(d.tmp[0:i])
+                       if i >= len(d.tmp) {
+                               if !d.Strict {
                                        b0, b1 = 0, 0
-                                       p.buf.WriteByte('&')
-                                       p.buf.Write(p.tmp[0:i])
+                                       d.buf.WriteByte('&')
+                                       d.buf.Write(d.tmp[0:i])
                                        continue Input
                                }
-                               p.err = p.syntaxError("character entity expression &" + s + "... too long")
+                               d.err = d.syntaxError("character entity expression &" + s + "... too long")
                                return nil
                        }
                        var haveText bool
@@ -901,28 +901,28 @@ Input:
                                if r, ok := entity[s]; ok {
                                        text = string(r)
                                        haveText = true
-                               } else if p.Entity != nil {
-                                       text, haveText = p.Entity[s]
+                               } else if d.Entity != nil {
+                                       text, haveText = d.Entity[s]
                                }
                        }
                        if !haveText {
-                               if !p.Strict {
+                               if !d.Strict {
                                        b0, b1 = 0, 0
-                                       p.buf.WriteByte('&')
-                                       p.buf.Write(p.tmp[0:i])
+                                       d.buf.WriteByte('&')
+                                       d.buf.Write(d.tmp[0:i])
                                        continue Input
                                }
-                               p.err = p.syntaxError("invalid character entity &" + s + ";")
+                               d.err = d.syntaxError("invalid character entity &" + s + ";")
                                return nil
                        }
-                       p.buf.Write([]byte(text))
+                       d.buf.Write([]byte(text))
                        b0, b1 = 0, 0
                        continue Input
                }
-               p.buf.WriteByte(b)
+               d.buf.WriteByte(b)
                b0, b1 = b1, b
        }
-       data := p.buf.Bytes()
+       data := d.buf.Bytes()
        data = data[0 : len(data)-trunc]
 
        // Inspect each rune for being a disallowed character.
@@ -930,12 +930,12 @@ Input:
        for len(buf) > 0 {
                r, size := utf8.DecodeRune(buf)
                if r == utf8.RuneError && size == 1 {
-                       p.err = p.syntaxError("invalid UTF-8")
+                       d.err = d.syntaxError("invalid UTF-8")
                        return nil
                }
                buf = buf[size:]
                if !isInCharacterRange(r) {
-                       p.err = p.syntaxError(fmt.Sprintf("illegal character code %U", r))
+                       d.err = d.syntaxError(fmt.Sprintf("illegal character code %U", r))
                        return nil
                }
        }
@@ -970,8 +970,8 @@ func isInCharacterRange(r rune) (inrange bool) {
 
 // Get name space name: name with a : stuck in the middle.
 // The part before the : is the name space identifier.
-func (p *Parser) nsname() (name Name, ok bool) {
-       s, ok := p.name()
+func (d *Decoder) nsname() (name Name, ok bool) {
+       s, ok := d.name()
        if !ok {
                return
        }
@@ -986,37 +986,37 @@ func (p *Parser) nsname() (name Name, ok bool) {
 }
 
 // Get name: /first(first|second)*/
-// Do not set p.err if the name is missing (unless unexpected EOF is received):
+// Do not set d.err if the name is missing (unless unexpected EOF is received):
 // let the caller provide better context.
-func (p *Parser) name() (s string, ok bool) {
+func (d *Decoder) name() (s string, ok bool) {
        var b byte
-       if b, ok = p.mustgetc(); !ok {
+       if b, ok = d.mustgetc(); !ok {
                return
        }
 
        // As a first approximation, we gather the bytes [A-Za-z_:.-\x80-\xFF]*
        if b < utf8.RuneSelf && !isNameByte(b) {
-               p.ungetc(b)
+               d.ungetc(b)
                return "", false
        }
-       p.buf.Reset()
-       p.buf.WriteByte(b)
+       d.buf.Reset()
+       d.buf.WriteByte(b)
        for {
-               if b, ok = p.mustgetc(); !ok {
+               if b, ok = d.mustgetc(); !ok {
                        return
                }
                if b < utf8.RuneSelf && !isNameByte(b) {
-                       p.ungetc(b)
+                       d.ungetc(b)
                        break
                }
-               p.buf.WriteByte(b)
+               d.buf.WriteByte(b)
        }
 
        // Then we check the characters.
-       s = p.buf.String()
+       s = d.buf.String()
        for i, c := range s {
                if !unicode.Is(first, c) && (i == 0 || !unicode.Is(second, c)) {
-                       p.err = p.syntaxError("invalid XML name: " + s)
+                       d.err = d.syntaxError("invalid XML name: " + s)
                        return "", false
                }
        }
index 524d4dda4f4f8aabfd9c749b711ee34fe4a5cfd5..1d0696ce087b3446a7df588103f284f6eb1ed8b5 100644 (file)
@@ -5,7 +5,6 @@
 package xml
 
 import (
-       "bytes"
        "io"
        "reflect"
        "strings"
@@ -155,8 +154,8 @@ var xmlInput = []string{
 }
 
 func TestRawToken(t *testing.T) {
-       p := NewParser(strings.NewReader(testInput))
-       testRawToken(t, p, rawTokens)
+       d := NewDecoder(strings.NewReader(testInput))
+       testRawToken(t, d, rawTokens)
 }
 
 type downCaser struct {
@@ -179,27 +178,27 @@ func (d *downCaser) Read(p []byte) (int, error) {
 
 func TestRawTokenAltEncoding(t *testing.T) {
        sawEncoding := ""
-       p := NewParser(strings.NewReader(testInputAltEncoding))
-       p.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
+       d := NewDecoder(strings.NewReader(testInputAltEncoding))
+       d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
                sawEncoding = charset
                if charset != "x-testing-uppercase" {
                        t.Fatalf("unexpected charset %q", charset)
                }
                return &downCaser{t, input.(io.ByteReader)}, nil
        }
-       testRawToken(t, p, rawTokensAltEncoding)
+       testRawToken(t, d, rawTokensAltEncoding)
 }
 
 func TestRawTokenAltEncodingNoConverter(t *testing.T) {
-       p := NewParser(strings.NewReader(testInputAltEncoding))
-       token, err := p.RawToken()
+       d := NewDecoder(strings.NewReader(testInputAltEncoding))
+       token, err := d.RawToken()
        if token == nil {
                t.Fatalf("expected a token on first RawToken call")
        }
        if err != nil {
                t.Fatal(err)
        }
-       token, err = p.RawToken()
+       token, err = d.RawToken()
        if token != nil {
                t.Errorf("expected a nil token; got %#v", token)
        }
@@ -213,9 +212,9 @@ func TestRawTokenAltEncodingNoConverter(t *testing.T) {
        }
 }
 
-func testRawToken(t *testing.T, p *Parser, rawTokens []Token) {
+func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) {
        for i, want := range rawTokens {
-               have, err := p.RawToken()
+               have, err := d.RawToken()
                if err != nil {
                        t.Fatalf("token %d: unexpected error: %s", i, err)
                }
@@ -258,10 +257,10 @@ var nestedDirectivesTokens = []Token{
 }
 
 func TestNestedDirectives(t *testing.T) {
-       p := NewParser(strings.NewReader(nestedDirectivesInput))
+       d := NewDecoder(strings.NewReader(nestedDirectivesInput))
 
        for i, want := range nestedDirectivesTokens {
-               have, err := p.Token()
+               have, err := d.Token()
                if err != nil {
                        t.Fatalf("token %d: unexpected error: %s", i, err)
                }
@@ -272,10 +271,10 @@ func TestNestedDirectives(t *testing.T) {
 }
 
 func TestToken(t *testing.T) {
-       p := NewParser(strings.NewReader(testInput))
+       d := NewDecoder(strings.NewReader(testInput))
 
        for i, want := range cookedTokens {
-               have, err := p.Token()
+               have, err := d.Token()
                if err != nil {
                        t.Fatalf("token %d: unexpected error: %s", i, err)
                }
@@ -287,9 +286,9 @@ func TestToken(t *testing.T) {
 
 func TestSyntax(t *testing.T) {
        for i := range xmlInput {
-               p := NewParser(strings.NewReader(xmlInput[i]))
+               d := NewDecoder(strings.NewReader(xmlInput[i]))
                var err error
-               for _, err = p.Token(); err == nil; _, err = p.Token() {
+               for _, err = d.Token(); err == nil; _, err = d.Token() {
                }
                if _, ok := err.(*SyntaxError); !ok {
                        t.Fatalf(`xmlInput "%s": expected SyntaxError not received`, xmlInput[i])
@@ -368,8 +367,7 @@ const testScalarsInput = `<allscalars>
 
 func TestAllScalars(t *testing.T) {
        var a allScalars
-       buf := bytes.NewBufferString(testScalarsInput)
-       err := Unmarshal(buf, &a)
+       err := Unmarshal([]byte(testScalarsInput), &a)
 
        if err != nil {
                t.Fatal(err)
@@ -386,8 +384,7 @@ type item struct {
 func TestIssue569(t *testing.T) {
        data := `<item><Field_a>abcd</Field_a></item>`
        var i item
-       buf := bytes.NewBufferString(data)
-       err := Unmarshal(buf, &i)
+       err := Unmarshal([]byte(data), &i)
 
        if err != nil || i.Field_a != "abcd" {
                t.Fatal("Expecting abcd")
@@ -396,9 +393,9 @@ func TestIssue569(t *testing.T) {
 
 func TestUnquotedAttrs(t *testing.T) {
        data := "<tag attr=azAZ09:-_\t>"
-       p := NewParser(strings.NewReader(data))
-       p.Strict = false
-       token, err := p.Token()
+       d := NewDecoder(strings.NewReader(data))
+       d.Strict = false
+       token, err := d.Token()
        if _, ok := err.(*SyntaxError); ok {
                t.Errorf("Unexpected error: %v", err)
        }
@@ -422,9 +419,9 @@ func TestValuelessAttrs(t *testing.T) {
                {"<input checked />", "input", "checked"},
        }
        for _, test := range tests {
-               p := NewParser(strings.NewReader(test[0]))
-               p.Strict = false
-               token, err := p.Token()
+               d := NewDecoder(strings.NewReader(test[0]))
+               d.Strict = false
+               token, err := d.Token()
                if _, ok := err.(*SyntaxError); ok {
                        t.Errorf("Unexpected error: %v", err)
                }
@@ -472,9 +469,9 @@ func TestCopyTokenStartElement(t *testing.T) {
 
 func TestSyntaxErrorLineNum(t *testing.T) {
        testInput := "<P>Foo<P>\n\n<P>Bar</>\n"
-       p := NewParser(strings.NewReader(testInput))
+       d := NewDecoder(strings.NewReader(testInput))
        var err error
-       for _, err = p.Token(); err == nil; _, err = p.Token() {
+       for _, err = d.Token(); err == nil; _, err = d.Token() {
        }
        synerr, ok := err.(*SyntaxError)
        if !ok {
@@ -487,41 +484,41 @@ func TestSyntaxErrorLineNum(t *testing.T) {
 
 func TestTrailingRawToken(t *testing.T) {
        input := `<FOO></FOO>  `
-       p := NewParser(strings.NewReader(input))
+       d := NewDecoder(strings.NewReader(input))
        var err error
-       for _, err = p.RawToken(); err == nil; _, err = p.RawToken() {
+       for _, err = d.RawToken(); err == nil; _, err = d.RawToken() {
        }
        if err != io.EOF {
-               t.Fatalf("p.RawToken() = _, %v, want _, io.EOF", err)
+               t.Fatalf("d.RawToken() = _, %v, want _, io.EOF", err)
        }
 }
 
 func TestTrailingToken(t *testing.T) {
        input := `<FOO></FOO>  `
-       p := NewParser(strings.NewReader(input))
+       d := NewDecoder(strings.NewReader(input))
        var err error
-       for _, err = p.Token(); err == nil; _, err = p.Token() {
+       for _, err = d.Token(); err == nil; _, err = d.Token() {
        }
        if err != io.EOF {
-               t.Fatalf("p.Token() = _, %v, want _, io.EOF", err)
+               t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
        }
 }
 
 func TestEntityInsideCDATA(t *testing.T) {
        input := `<test><![CDATA[ &val=foo ]]></test>`
-       p := NewParser(strings.NewReader(input))
+       d := NewDecoder(strings.NewReader(input))
        var err error
-       for _, err = p.Token(); err == nil; _, err = p.Token() {
+       for _, err = d.Token(); err == nil; _, err = d.Token() {
        }
        if err != io.EOF {
-               t.Fatalf("p.Token() = _, %v, want _, io.EOF", err)
+               t.Fatalf("d.Token() = _, %v, want _, io.EOF", err)
        }
 }
 
 // The last three tests (respectively one for characters in attribute
 // names and two for character entities) pass not because of code
 // changed for issue 1259, but instead pass with the given messages
-// from other parts of xml.Parser.  I provide these to note the
+// from other parts of xml.Decoder.  I provide these to note the
 // current behavior of situations where one might think that character
 // range checking would detect the error, but it does not in fact.
 
@@ -541,15 +538,15 @@ var characterTests = []struct {
 func TestDisallowedCharacters(t *testing.T) {
 
        for i, tt := range characterTests {
-               p := NewParser(strings.NewReader(tt.in))
+               d := NewDecoder(strings.NewReader(tt.in))
                var err error
 
                for err == nil {
-                       _, err = p.Token()
+                       _, err = d.Token()
                }
                synerr, ok := err.(*SyntaxError)
                if !ok {
-                       t.Fatalf("input %d p.Token() = _, %v, want _, *SyntaxError", i, err)
+                       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)
index 6d6f516c905eee3a637d6081e837bfb1fa2414ae..2cb5aa6ed6c83115e387aadefc91d7ee2458db5e 100644 (file)
@@ -11,6 +11,7 @@ import (
        "fmt"
        "go/scanner"
        "go/token"
+       "io"
        "io/ioutil"
        "os"
        "path/filepath"
@@ -76,34 +77,46 @@ func main() {
        flag.Parse()
 
        var (
-               filename string
-               src      []byte
-               err      error
+               name string
+               r    io.Reader
        )
        switch flag.NArg() {
        case 0:
-               filename = "<stdin>"
-               src, err = ioutil.ReadAll(os.Stdin)
+               name, r = "<stdin>", os.Stdin
        case 1:
-               filename = flag.Arg(0)
-               src, err = ioutil.ReadFile(filename)
+               name = flag.Arg(0)
        default:
                usage()
        }
-       if err != nil {
+
+       if err := verify(name, *start, r); err != nil {
                report(err)
        }
+}
 
-       if filepath.Ext(filename) == ".html" || bytes.Index(src, open) >= 0 {
-               src = extractEBNF(src)
+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
        }
 
-       grammar, err := ebnf.Parse(filename, bytes.NewBuffer(src))
+       src, err := ioutil.ReadAll(r)
        if err != nil {
-               report(err)
+               return err
        }
 
-       if err = ebnf.Verify(grammar, *start); err != nil {
-               report(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
new file mode 100644 (file)
index 0000000..875dbc1
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package 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/html/entity.go b/libgo/go/exp/html/entity.go
new file mode 100644 (file)
index 0000000..bd83075
--- /dev/null
@@ -0,0 +1,2253 @@
+// 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
new file mode 100644 (file)
index 0000000..b53f866
--- /dev/null
@@ -0,0 +1,29 @@
+// 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
new file mode 100644 (file)
index 0000000..42be865
--- /dev/null
@@ -0,0 +1,253 @@
+// 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 "&lt;" 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&lt;b" becomes "a<b".
+func unescape(b []byte) []byte {
+       for i, c := range b {
+               if c == '&' {
+                       dst, src := unescapeEntity(b, i, i, false)
+                       for src < len(b) {
+                               c := b[src]
+                               if c == '&' {
+                                       dst, src = unescapeEntity(b, dst, src, false)
+                               } else {
+                                       b[dst] = c
+                                       dst, src = dst+1, src+1
+                               }
+                       }
+                       return b[0:dst]
+               }
+       }
+       return b
+}
+
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
+func lower(b []byte) []byte {
+       for i, c := range b {
+               if 'A' <= c && c <= 'Z' {
+                       b[i] = c + 'a' - 'A'
+               }
+       }
+       return b
+}
+
+const escapedChars = `&'<>"`
+
+func escape(w writer, s string) error {
+       i := strings.IndexAny(s, escapedChars)
+       for i != -1 {
+               if _, err := w.WriteString(s[:i]); err != nil {
+                       return err
+               }
+               var esc string
+               switch s[i] {
+               case '&':
+                       esc = "&amp;"
+               case '\'':
+                       esc = "&apos;"
+               case '<':
+                       esc = "&lt;"
+               case '>':
+                       esc = "&gt;"
+               case '"':
+                       esc = "&quot;"
+               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 "&lt;". It
+// escapes only five such characters: amp, apos, lt, gt and quot.
+// 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
+       }
+       buf := bytes.NewBuffer(nil)
+       escape(buf, s)
+       return buf.String()
+}
+
+// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
+// larger range of entities than EscapeString escapes. For example, "&aacute;"
+// unescapes to "á", as does "&#225;" 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)))
+               }
+       }
+       return s
+}
index 55ff052dcbc3b0ec7934ce20097a71e597bebb30..9044a72fd476ffd31caad9e6372c29639f867ca7 100644 (file)
@@ -2804,12 +2804,12 @@ var nfcDecompSparseValues = [341]valueRange{
        {value: 0x0005, lo: 0x01},
        {value: 0x068d, lo: 0xa2, hi: 0xa6},
        // Block 0xc, offset 0xd
-       {value: 0x0005, lo: 0x03},
+       {value: 0x0000, lo: 0x03},
        {value: 0x06ba, lo: 0x80, hi: 0x80},
        {value: 0x06bf, lo: 0x82, hi: 0x82},
        {value: 0x06c4, lo: 0x93, hi: 0x93},
        // Block 0xd, offset 0xe
-       {value: 0x0007, lo: 0x03},
+       {value: 0x0000, lo: 0x03},
        {value: 0x06c9, lo: 0xa9, hi: 0xa9},
        {value: 0x06d0, lo: 0xb1, hi: 0xb1},
        {value: 0x06d7, lo: 0xb4, hi: 0xb4},
@@ -2822,7 +2822,7 @@ var nfcDecompSparseValues = [341]valueRange{
        {value: 0x0724, lo: 0x9c, hi: 0x9d},
        {value: 0x0732, lo: 0x9f, hi: 0x9f},
        // Block 0x10, offset 0x11
-       {value: 0x0007, lo: 0x02},
+       {value: 0x0000, lo: 0x02},
        {value: 0x0739, lo: 0xb3, hi: 0xb3},
        {value: 0x0740, lo: 0xb6, hi: 0xb6},
        // Block 0x11, offset 0x12
@@ -2868,7 +2868,7 @@ var nfcDecompSparseValues = [341]valueRange{
        {value: 0x0854, lo: 0xb5, hi: 0xb6},
        {value: 0x086c, lo: 0xb8, hi: 0xb8},
        // Block 0x1a, offset 0x1b
-       {value: 0x0007, lo: 0x07},
+       {value: 0x0000, lo: 0x07},
        {value: 0x087d, lo: 0x81, hi: 0x81},
        {value: 0x0884, lo: 0x93, hi: 0x93},
        {value: 0x088b, lo: 0x9d, hi: 0x9d},
@@ -2880,7 +2880,7 @@ var nfcDecompSparseValues = [341]valueRange{
        {value: 0x0000, lo: 0x01},
        {value: 0x08ae, lo: 0xa6, hi: 0xa6},
        // Block 0x1c, offset 0x1d
-       {value: 0x0007, lo: 0x08},
+       {value: 0x0000, lo: 0x08},
        {value: 0x08b9, lo: 0x86, hi: 0x86},
        {value: 0x08c0, lo: 0x88, hi: 0x88},
        {value: 0x08c7, lo: 0x8a, hi: 0x8a},
@@ -2924,7 +2924,7 @@ var nfcDecompSparseValues = [341]valueRange{
        {value: 0x0006, lo: 0x01},
        {value: 0x15b1, lo: 0x8d, hi: 0x8f},
        // Block 0x23, offset 0x24
-       {value: 0x0006, lo: 0x05},
+       {value: 0x0000, lo: 0x05},
        {value: 0x15c3, lo: 0x84, hi: 0x84},
        {value: 0x15c9, lo: 0x89, hi: 0x89},
        {value: 0x15cf, lo: 0x8c, hi: 0x8c},
@@ -2960,7 +2960,7 @@ var nfcDecompSparseValues = [341]valueRange{
        {value: 0x0000, lo: 0x01},
        {value: 0x1814, lo: 0x9c, hi: 0x9c},
        // Block 0x29, offset 0x2a
-       {value: 0x0007, lo: 0x0c},
+       {value: 0x0000, lo: 0x0c},
        {value: 0x1c39, lo: 0x94, hi: 0x94},
        {value: 0x1c4a, lo: 0x9e, hi: 0x9e},
        {value: 0x1c58, lo: 0xac, hi: 0xac},
@@ -3084,7 +3084,7 @@ var nfcDecompSparseValues = [341]valueRange{
        {value: 0x3191, lo: 0x83, hi: 0x84},
        {value: 0x319b, lo: 0x86, hi: 0x8e},
        // Block 0x33, offset 0x34
-       {value: 0x0009, lo: 0x03},
+       {value: 0x0000, lo: 0x03},
        {value: 0x3a73, lo: 0x9a, hi: 0x9a},
        {value: 0x3a7c, lo: 0x9c, hi: 0x9c},
        {value: 0x3a85, lo: 0xab, hi: 0xab},
@@ -3897,10 +3897,10 @@ var nfkcDecompValues = [4224]uint16{
 }
 
 // nfkcDecompSparseOffset: 93 entries, 186 bytes
-var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10e, 0x11a, 0x11f, 0x122, 0x124, 0x126, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13b, 0x140, 0x14f, 0x15d, 0x15f, 0x161, 0x169, 0x179, 0x17b, 0x186, 0x18d, 0x198, 0x1a4, 0x1b5, 0x1c6, 0x1cd, 0x1de, 0x1ec, 0x1fa, 0x209, 0x21a, 0x21f, 0x22c, 0x230, 0x234, 0x238, 0x23a, 0x249, 0x24b, 0x24f}
+var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10c, 0x118, 0x11d, 0x120, 0x122, 0x124, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13e, 0x14d, 0x15b, 0x15d, 0x15f, 0x167, 0x177, 0x179, 0x184, 0x18b, 0x196, 0x1a2, 0x1b3, 0x1c4, 0x1cb, 0x1dc, 0x1ea, 0x1f8, 0x207, 0x218, 0x21d, 0x22a, 0x22e, 0x232, 0x236, 0x238, 0x247, 0x249, 0x24d}
 
-// nfkcDecompSparseValues: 605 entries, 2420 bytes
-var nfkcDecompSparseValues = [605]valueRange{
+// nfkcDecompSparseValues: 603 entries, 2412 bytes
+var nfkcDecompSparseValues = [603]valueRange{
        // Block 0x0, offset 0x1
        {value: 0x0002, lo: 0x0b},
        {value: 0x0001, lo: 0xa0, hi: 0xa0},
@@ -4035,12 +4035,12 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x0005, lo: 0x01},
        {value: 0x06a6, lo: 0xb5, hi: 0xb8},
        // Block 0x11, offset 0x12
-       {value: 0x0005, lo: 0x03},
+       {value: 0x0000, lo: 0x03},
        {value: 0x06ba, lo: 0x80, hi: 0x80},
        {value: 0x06bf, lo: 0x82, hi: 0x82},
        {value: 0x06c4, lo: 0x93, hi: 0x93},
        // Block 0x12, offset 0x13
-       {value: 0x0007, lo: 0x03},
+       {value: 0x0000, lo: 0x03},
        {value: 0x06c9, lo: 0xa9, hi: 0xa9},
        {value: 0x06d0, lo: 0xb1, hi: 0xb1},
        {value: 0x06d7, lo: 0xb4, hi: 0xb4},
@@ -4053,7 +4053,7 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x0724, lo: 0x9c, hi: 0x9d},
        {value: 0x0732, lo: 0x9f, hi: 0x9f},
        // Block 0x15, offset 0x16
-       {value: 0x0007, lo: 0x02},
+       {value: 0x0000, lo: 0x02},
        {value: 0x0739, lo: 0xb3, hi: 0xb3},
        {value: 0x0740, lo: 0xb6, hi: 0xb6},
        // Block 0x16, offset 0x17
@@ -4111,7 +4111,7 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x0854, lo: 0xb5, hi: 0xb7},
        {value: 0x086c, lo: 0xb8, hi: 0xb9},
        // Block 0x23, offset 0x24
-       {value: 0x0007, lo: 0x07},
+       {value: 0x0000, lo: 0x07},
        {value: 0x087d, lo: 0x81, hi: 0x81},
        {value: 0x0884, lo: 0x93, hi: 0x93},
        {value: 0x088b, lo: 0x9d, hi: 0x9d},
@@ -4126,7 +4126,7 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x0000, lo: 0x01},
        {value: 0x08b5, lo: 0xbc, hi: 0xbc},
        // Block 0x26, offset 0x27
-       {value: 0x0007, lo: 0x08},
+       {value: 0x0000, lo: 0x08},
        {value: 0x08b9, lo: 0x86, hi: 0x86},
        {value: 0x08c0, lo: 0x88, hi: 0x88},
        {value: 0x08c7, lo: 0x8a, hi: 0x8a},
@@ -4209,16 +4209,14 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x0006, lo: 0x01},
        {value: 0x15b1, lo: 0x8d, hi: 0x8f},
        // Block 0x2f, offset 0x30
-       {value: 0x0006, lo: 0x09},
+       {value: 0x0007, lo: 0x07},
        {value: 0x15c3, lo: 0x84, hi: 0x84},
        {value: 0x15c9, lo: 0x89, hi: 0x89},
        {value: 0x15cf, lo: 0x8c, hi: 0x8c},
        {value: 0x15d5, lo: 0xa4, hi: 0xa4},
        {value: 0x15db, lo: 0xa6, hi: 0xa6},
-       {value: 0x15e1, lo: 0xac, hi: 0xac},
-       {value: 0x15e8, lo: 0xad, hi: 0xad},
-       {value: 0x15f2, lo: 0xaf, hi: 0xaf},
-       {value: 0x15f9, lo: 0xb0, hi: 0xb0},
+       {value: 0x15e1, lo: 0xac, hi: 0xad},
+       {value: 0x15f2, lo: 0xaf, hi: 0xb0},
        // Block 0x30, offset 0x31
        {value: 0x0006, lo: 0x0b},
        {value: 0x1603, lo: 0x81, hi: 0x81},
@@ -4249,9 +4247,9 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x0000, lo: 0x01},
        {value: 0x17fc, lo: 0x8c, hi: 0x8c},
        // Block 0x35, offset 0x36
-       {value: 0x0004, lo: 0x02},
-       {value: 0x1809, lo: 0xb4, hi: 0xb5},
-       {value: 0x1810, lo: 0xb6, hi: 0xb6},
+       {value: 0x0003, lo: 0x02},
+       {value: 0x1809, lo: 0xb4, hi: 0xb4},
+       {value: 0x180d, lo: 0xb5, hi: 0xb6},
        // Block 0x36, offset 0x37
        {value: 0x0000, lo: 0x01},
        {value: 0x1814, lo: 0x9c, hi: 0x9c},
@@ -4280,17 +4278,17 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x0004, lo: 0x01},
        {value: 0x1b26, lo: 0x80, hi: 0x95},
        // Block 0x3f, offset 0x40
-       {value: 0x0300, lo: 0x04},
+       {value: 0x0004, lo: 0x04},
        {value: 0x0001, lo: 0x80, hi: 0x80},
        {value: 0x1b7e, lo: 0xb6, hi: 0xb6},
-       {value: 0x1882, lo: 0xb8, hi: 0xb9},
-       {value: 0x1b86, lo: 0xba, hi: 0xba},
+       {value: 0x1882, lo: 0xb8, hi: 0xb8},
+       {value: 0x1b82, lo: 0xb9, hi: 0xba},
        // Block 0x40, offset 0x41
-       {value: 0x0007, lo: 0x0e},
+       {value: 0x0005, lo: 0x0e},
        {value: 0x1c39, lo: 0x94, hi: 0x94},
-       {value: 0x1c40, lo: 0x9b, hi: 0x9b},
-       {value: 0x1c45, lo: 0x9c, hi: 0x9c},
-       {value: 0x1c4a, lo: 0x9e, hi: 0x9f},
+       {value: 0x1c40, lo: 0x9b, hi: 0x9c},
+       {value: 0x1c4a, lo: 0x9e, hi: 0x9e},
+       {value: 0x1c51, lo: 0x9f, hi: 0x9f},
        {value: 0x1c58, lo: 0xac, hi: 0xac},
        {value: 0x1c5f, lo: 0xae, hi: 0xae},
        {value: 0x1c66, lo: 0xb0, hi: 0xb0},
@@ -4543,7 +4541,7 @@ var nfkcDecompSparseValues = [605]valueRange{
        {value: 0x3a53, lo: 0xa6, hi: 0xa6},
        {value: 0x3a57, lo: 0xa8, hi: 0xae},
        // Block 0x55, offset 0x56
-       {value: 0x0009, lo: 0x03},
+       {value: 0x0000, lo: 0x03},
        {value: 0x3a73, lo: 0x9a, hi: 0x9a},
        {value: 0x3a7c, lo: 0x9c, hi: 0x9c},
        {value: 0x3a85, lo: 0xab, hi: 0xab},
@@ -5760,10 +5758,10 @@ var charInfoValues = [1024]uint16{
 }
 
 // charInfoSparseOffset: 156 entries, 312 bytes
-var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd7, 0xda, 0xe3, 0xe5, 0xed, 0xf1, 0xf3, 0xf6, 0xf9, 0xff, 0x10f, 0x11b, 0x11d, 0x123, 0x125, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x134, 0x137, 0x139, 0x13c, 0x13f, 0x143, 0x152, 0x15a, 0x15c, 0x15f, 0x161, 0x16a, 0x16e, 0x172, 0x174, 0x183, 0x187, 0x18d, 0x195, 0x199, 0x1a2, 0x1ab, 0x1b6, 0x1bc, 0x1c0, 0x1ce, 0x1dd, 0x1e1, 0x1e8, 0x1ed, 0x1fc, 0x208, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21d, 0x220, 0x222, 0x224, 0x226, 0x228, 0x231, 0x233, 0x236, 0x239, 0x23c, 0x23e, 0x241, 0x243, 0x245, 0x247, 0x24a, 0x24c, 0x24e, 0x250, 0x252, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x262, 0x26c, 0x26f, 0x271, 0x27b, 0x280, 0x282, 0x284, 0x286, 0x288, 0x28b, 0x28e, 0x292, 0x29a, 0x29c, 0x29e, 0x2a5, 0x2a7, 0x2ae, 0x2b6, 0x2bd, 0x2c3, 0x2c5, 0x2c7, 0x2ca, 0x2d3, 0x2d6, 0x2dd, 0x2e2, 0x2e5, 0x2e8, 0x2ec, 0x2ee, 0x2f0, 0x2f3, 0x2f6}
+var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd6, 0xd9, 0xe2, 0xe4, 0xec, 0xf0, 0xf2, 0xf5, 0xf8, 0xfe, 0x10e, 0x11a, 0x11c, 0x122, 0x124, 0x126, 0x128, 0x12a, 0x12c, 0x12e, 0x130, 0x133, 0x136, 0x138, 0x13b, 0x13e, 0x142, 0x151, 0x159, 0x15b, 0x15e, 0x160, 0x169, 0x16d, 0x171, 0x173, 0x182, 0x186, 0x18c, 0x194, 0x198, 0x1a1, 0x1aa, 0x1b5, 0x1bb, 0x1bf, 0x1cd, 0x1dc, 0x1e0, 0x1e7, 0x1ec, 0x1fa, 0x206, 0x209, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21e, 0x220, 0x222, 0x224, 0x226, 0x22f, 0x231, 0x234, 0x237, 0x23a, 0x23c, 0x23f, 0x241, 0x243, 0x245, 0x248, 0x24a, 0x24c, 0x24e, 0x250, 0x256, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x26a, 0x26d, 0x26f, 0x279, 0x27e, 0x280, 0x282, 0x284, 0x286, 0x289, 0x28c, 0x290, 0x298, 0x29a, 0x29c, 0x2a3, 0x2a5, 0x2ab, 0x2b3, 0x2ba, 0x2c0, 0x2c2, 0x2c4, 0x2c7, 0x2d0, 0x2d3, 0x2da, 0x2df, 0x2e2, 0x2e5, 0x2e9, 0x2eb, 0x2ed, 0x2f0, 0x2f3}
 
-// charInfoSparseValues: 760 entries, 3040 bytes
-var charInfoSparseValues = [760]valueRange{
+// charInfoSparseValues: 757 entries, 3028 bytes
+var charInfoSparseValues = [757]valueRange{
        // Block 0x0, offset 0x1
        {value: 0x0000, lo: 0x07},
        {value: 0x3000, lo: 0xa0, hi: 0xa0},
@@ -5942,7 +5940,7 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x0000, lo: 0x01},
        {value: 0x00dc, lo: 0x99, hi: 0x9b},
        // Block 0x14, offset 0x15
-       {value: 0x7700, lo: 0x07},
+       {value: 0x0000, lo: 0x07},
        {value: 0x8800, lo: 0xa8, hi: 0xa8},
        {value: 0x1100, lo: 0xa9, hi: 0xa9},
        {value: 0x8800, lo: 0xb0, hi: 0xb0},
@@ -5958,7 +5956,7 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x00e6, lo: 0x93, hi: 0x94},
        {value: 0x3300, lo: 0x98, hi: 0x9f},
        // Block 0x16, offset 0x17
-       {value: 0x65f9, lo: 0x02},
+       {value: 0x0000, lo: 0x02},
        {value: 0x0007, lo: 0xbc, hi: 0xbc},
        {value: 0x6600, lo: 0xbe, hi: 0xbe},
        // Block 0x17, offset 0x18
@@ -5994,7 +5992,7 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x6600, lo: 0x96, hi: 0x97},
        {value: 0x3300, lo: 0x9c, hi: 0x9d},
        // Block 0x1d, offset 0x1e
-       {value: 0x5500, lo: 0x03},
+       {value: 0x0000, lo: 0x03},
        {value: 0x8800, lo: 0x92, hi: 0x92},
        {value: 0x1100, lo: 0x94, hi: 0x94},
        {value: 0x6600, lo: 0xbe, hi: 0xbe},
@@ -6005,14 +6003,13 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x0009, lo: 0x8d, hi: 0x8d},
        {value: 0x6600, lo: 0x97, hi: 0x97},
        // Block 0x1f, offset 0x20
-       {value: 0x004b, lo: 0x05},
+       {value: 0x6607, lo: 0x04},
        {value: 0x8800, lo: 0x86, hi: 0x86},
        {value: 0x1100, lo: 0x88, hi: 0x88},
        {value: 0x0009, lo: 0x8d, hi: 0x8d},
-       {value: 0x0054, lo: 0x95, hi: 0x95},
-       {value: 0x665b, lo: 0x96, hi: 0x96},
+       {value: 0x0054, lo: 0x95, hi: 0x96},
        // Block 0x20, offset 0x21
-       {value: 0x87f9, lo: 0x02},
+       {value: 0x0000, lo: 0x02},
        {value: 0x0007, lo: 0xbc, hi: 0xbc},
        {value: 0x8800, lo: 0xbf, hi: 0xbf},
        // Block 0x21, offset 0x22
@@ -6126,7 +6123,7 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x0009, lo: 0x94, hi: 0x94},
        {value: 0x0009, lo: 0xb4, hi: 0xb4},
        // Block 0x35, offset 0x36
-       {value: 0x00dd, lo: 0x02},
+       {value: 0x0000, lo: 0x02},
        {value: 0x0009, lo: 0x92, hi: 0x92},
        {value: 0x00e6, lo: 0x9d, hi: 0x9d},
        // Block 0x36, offset 0x37
@@ -6340,7 +6337,7 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x8800, lo: 0x92, hi: 0x92},
        {value: 0x8800, lo: 0x94, hi: 0x94},
        // Block 0x52, offset 0x53
-       {value: 0x7700, lo: 0x0e},
+       {value: 0x0000, lo: 0x0d},
        {value: 0x8800, lo: 0x83, hi: 0x83},
        {value: 0x1100, lo: 0x84, hi: 0x84},
        {value: 0x8800, lo: 0x88, hi: 0x88},
@@ -6348,12 +6345,11 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x8800, lo: 0x8b, hi: 0x8b},
        {value: 0x1100, lo: 0x8c, hi: 0x8c},
        {value: 0x8800, lo: 0xa3, hi: 0xa3},
-       {value: 0x1100, lo: 0xa4, hi: 0xa5},
+       {value: 0x1100, lo: 0xa4, hi: 0xa4},
+       {value: 0x8800, lo: 0xa5, hi: 0xa5},
        {value: 0x1100, lo: 0xa6, hi: 0xa6},
-       {value: 0x3000, lo: 0xac, hi: 0xac},
-       {value: 0x3000, lo: 0xad, hi: 0xad},
-       {value: 0x3000, lo: 0xaf, hi: 0xaf},
-       {value: 0x3000, lo: 0xb0, hi: 0xb0},
+       {value: 0x3000, lo: 0xac, hi: 0xad},
+       {value: 0x3000, lo: 0xaf, hi: 0xb0},
        {value: 0x8800, lo: 0xbc, hi: 0xbc},
        // Block 0x53, offset 0x54
        {value: 0x0000, lo: 0x0b},
@@ -6581,22 +6577,21 @@ var charInfoSparseValues = [760]valueRange{
        {value: 0x0000, lo: 0x01},
        {value: 0x00dc, lo: 0xbd, hi: 0xbd},
        // Block 0x89, offset 0x8a
-       {value: 0x0000, lo: 0x06},
+       {value: 0x00db, lo: 0x05},
        {value: 0x00dc, lo: 0x8d, hi: 0x8d},
        {value: 0x00e6, lo: 0x8f, hi: 0x8f},
        {value: 0x00e6, lo: 0xb8, hi: 0xb8},
-       {value: 0x0001, lo: 0xb9, hi: 0xb9},
-       {value: 0x00dc, lo: 0xba, hi: 0xba},
+       {value: 0x0001, lo: 0xb9, hi: 0xba},
        {value: 0x0009, lo: 0xbf, hi: 0xbf},
        // Block 0x8a, offset 0x8b
-       {value: 0x7700, lo: 0x07},
+       {value: 0x65fe, lo: 0x07},
        {value: 0x8800, lo: 0x99, hi: 0x99},
-       {value: 0x1100, lo: 0x9a, hi: 0x9b},
+       {value: 0x1100, lo: 0x9a, hi: 0x9a},
+       {value: 0x8800, lo: 0x9b, hi: 0x9b},
        {value: 0x1100, lo: 0x9c, hi: 0x9c},
        {value: 0x8800, lo: 0xa5, hi: 0xa5},
        {value: 0x1100, lo: 0xab, hi: 0xab},
-       {value: 0x0009, lo: 0xb9, hi: 0xb9},
-       {value: 0x6607, lo: 0xba, hi: 0xba},
+       {value: 0x0009, lo: 0xb9, hi: 0xba},
        // Block 0x8b, offset 0x8c
        {value: 0x0000, lo: 0x06},
        {value: 0x3300, lo: 0x9e, hi: 0xa4},
@@ -6768,4 +6763,4 @@ var charInfoLookup = [1152]uint8{
 
 var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:], charInfoSparseValues[:], charInfoSparseOffset[:], 16}
 
-// Total size of tables: 48KB (48756 bytes)
+// Total size of tables: 48KB (48736 bytes)
index 5edadac0a41672e1df5ccfba8825895184a0b1fe..4ad9e0e057c7cb3063bc70185d62e6e76dcb6a8f 100644 (file)
@@ -65,11 +65,13 @@ func (n trieNode) mostFrequentStride() int {
                                counts[stride]++
                        }
                        v = t.value
+               } else {
+                       v = 0
                }
        }
        var maxs, maxc int
        for stride, cnt := range counts {
-               if cnt > maxc {
+               if cnt > maxc || (cnt == maxc && stride < maxs) {
                        maxs, maxc = stride, cnt
                }
        }
diff --git a/libgo/go/exp/spdy/read.go b/libgo/go/exp/spdy/read.go
deleted file mode 100644 (file)
index 4830a1d..0000000
+++ /dev/null
@@ -1,312 +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 spdy
-
-import (
-       "compress/zlib"
-       "encoding/binary"
-       "io"
-       "net/http"
-       "strings"
-)
-
-func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error {
-       return f.readSynStreamFrame(h, frame)
-}
-
-func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error {
-       return f.readSynReplyFrame(h, frame)
-}
-
-func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error {
-       frame.CFHeader = h
-       if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-               return err
-       }
-       if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
-               return err
-       }
-       return nil
-}
-
-func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
-       frame.CFHeader = h
-       var numSettings uint32
-       if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
-               return err
-       }
-       frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
-       for i := uint32(0); i < numSettings; i++ {
-               if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
-                       return err
-               }
-               frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
-               frame.FlagIdValues[i].Id &= 0xffffff
-               if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-func (frame *NoopFrame) read(h ControlFrameHeader, f *Framer) error {
-       frame.CFHeader = h
-       return nil
-}
-
-func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error {
-       frame.CFHeader = h
-       if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
-               return err
-       }
-       return nil
-}
-
-func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error {
-       frame.CFHeader = h
-       if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
-               return err
-       }
-       return nil
-}
-
-func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error {
-       return f.readHeadersFrame(h, frame)
-}
-
-func newControlFrame(frameType ControlFrameType) (controlFrame, error) {
-       ctor, ok := cframeCtor[frameType]
-       if !ok {
-               return nil, &Error{Err: InvalidControlFrame}
-       }
-       return ctor(), nil
-}
-
-var cframeCtor = map[ControlFrameType]func() controlFrame{
-       TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
-       TypeSynReply:  func() controlFrame { return new(SynReplyFrame) },
-       TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
-       TypeSettings:  func() controlFrame { return new(SettingsFrame) },
-       TypeNoop:      func() controlFrame { return new(NoopFrame) },
-       TypePing:      func() controlFrame { return new(PingFrame) },
-       TypeGoAway:    func() controlFrame { return new(GoAwayFrame) },
-       TypeHeaders:   func() controlFrame { return new(HeadersFrame) },
-       // TODO(willchan): Add TypeWindowUpdate
-}
-
-func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error {
-       if f.headerDecompressor != nil {
-               f.headerReader.N = payloadSize
-               return nil
-       }
-       f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
-       decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(HeaderDictionary))
-       if err != nil {
-               return err
-       }
-       f.headerDecompressor = decompressor
-       return nil
-}
-
-// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
-func (f *Framer) ReadFrame() (Frame, error) {
-       var firstWord uint32
-       if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
-               return nil, err
-       }
-       if (firstWord & 0x80000000) != 0 {
-               frameType := ControlFrameType(firstWord & 0xffff)
-               version := uint16(0x7fff & (firstWord >> 16))
-               return f.parseControlFrame(version, frameType)
-       }
-       return f.parseDataFrame(firstWord & 0x7fffffff)
-}
-
-func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) {
-       var length uint32
-       if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
-               return nil, err
-       }
-       flags := ControlFlags((length & 0xff000000) >> 24)
-       length &= 0xffffff
-       header := ControlFrameHeader{version, frameType, flags, length}
-       cframe, err := newControlFrame(frameType)
-       if err != nil {
-               return nil, err
-       }
-       if err = cframe.read(header, f); err != nil {
-               return nil, err
-       }
-       return cframe, nil
-}
-
-func parseHeaderValueBlock(r io.Reader, streamId uint32) (http.Header, error) {
-       var numHeaders uint16
-       if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
-               return nil, err
-       }
-       var e error
-       h := make(http.Header, int(numHeaders))
-       for i := 0; i < int(numHeaders); i++ {
-               var length uint16
-               if err := binary.Read(r, binary.BigEndian, &length); err != nil {
-                       return nil, err
-               }
-               nameBytes := make([]byte, length)
-               if _, err := io.ReadFull(r, nameBytes); err != nil {
-                       return nil, err
-               }
-               name := string(nameBytes)
-               if name != strings.ToLower(name) {
-                       e = &Error{UnlowercasedHeaderName, streamId}
-                       name = strings.ToLower(name)
-               }
-               if h[name] != nil {
-                       e = &Error{DuplicateHeaders, streamId}
-               }
-               if err := binary.Read(r, binary.BigEndian, &length); err != nil {
-                       return nil, err
-               }
-               value := make([]byte, length)
-               if _, err := io.ReadFull(r, value); err != nil {
-                       return nil, err
-               }
-               valueList := strings.Split(string(value), "\x00")
-               for _, v := range valueList {
-                       h.Add(name, v)
-               }
-       }
-       if e != nil {
-               return h, e
-       }
-       return h, nil
-}
-
-func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error {
-       frame.CFHeader = h
-       var err error
-       if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-               return err
-       }
-       if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
-               return err
-       }
-       if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
-               return err
-       }
-       frame.Priority >>= 14
-
-       reader := f.r
-       if !f.headerCompressionDisabled {
-               f.uncorkHeaderDecompressor(int64(h.length - 10))
-               reader = f.headerDecompressor
-       }
-
-       frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
-       if !f.headerCompressionDisabled && ((err == io.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
-               err = &Error{WrongCompressedPayloadSize, 0}
-       }
-       if err != nil {
-               return err
-       }
-       // Remove this condition when we bump Version to 3.
-       if Version >= 3 {
-               for h := range frame.Headers {
-                       if invalidReqHeaders[h] {
-                               return &Error{InvalidHeaderPresent, frame.StreamId}
-                       }
-               }
-       }
-       return nil
-}
-
-func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error {
-       frame.CFHeader = h
-       var err error
-       if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-               return err
-       }
-       var unused uint16
-       if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
-               return err
-       }
-       reader := f.r
-       if !f.headerCompressionDisabled {
-               f.uncorkHeaderDecompressor(int64(h.length - 6))
-               reader = f.headerDecompressor
-       }
-       frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
-       if !f.headerCompressionDisabled && ((err == io.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
-               err = &Error{WrongCompressedPayloadSize, 0}
-       }
-       if err != nil {
-               return err
-       }
-       // Remove this condition when we bump Version to 3.
-       if Version >= 3 {
-               for h := range frame.Headers {
-                       if invalidRespHeaders[h] {
-                               return &Error{InvalidHeaderPresent, frame.StreamId}
-                       }
-               }
-       }
-       return nil
-}
-
-func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error {
-       frame.CFHeader = h
-       var err error
-       if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
-               return err
-       }
-       var unused uint16
-       if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
-               return err
-       }
-       reader := f.r
-       if !f.headerCompressionDisabled {
-               f.uncorkHeaderDecompressor(int64(h.length - 6))
-               reader = f.headerDecompressor
-       }
-       frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
-       if !f.headerCompressionDisabled && ((err == io.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
-               err = &Error{WrongCompressedPayloadSize, 0}
-       }
-       if err != nil {
-               return err
-       }
-
-       // Remove this condition when we bump Version to 3.
-       if Version >= 3 {
-               var invalidHeaders map[string]bool
-               if frame.StreamId%2 == 0 {
-                       invalidHeaders = invalidReqHeaders
-               } else {
-                       invalidHeaders = invalidRespHeaders
-               }
-               for h := range frame.Headers {
-                       if invalidHeaders[h] {
-                               return &Error{InvalidHeaderPresent, frame.StreamId}
-                       }
-               }
-       }
-       return nil
-}
-
-func (f *Framer) parseDataFrame(streamId uint32) (*DataFrame, error) {
-       var length uint32
-       if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
-               return nil, err
-       }
-       var frame DataFrame
-       frame.StreamId = streamId
-       frame.Flags = DataFlags(length >> 24)
-       length &= 0xffffff
-       frame.Data = make([]byte, length)
-       if _, err := io.ReadFull(f.r, frame.Data); err != nil {
-               return nil, err
-       }
-       return &frame, nil
-}
diff --git a/libgo/go/exp/spdy/spdy_test.go b/libgo/go/exp/spdy/spdy_test.go
deleted file mode 100644 (file)
index c1cad4b..0000000
+++ /dev/null
@@ -1,497 +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 spdy
-
-import (
-       "bytes"
-       "io"
-       "net/http"
-       "reflect"
-       "testing"
-)
-
-func TestHeaderParsing(t *testing.T) {
-       headers := http.Header{
-               "Url":     []string{"http://www.google.com/"},
-               "Method":  []string{"get"},
-               "Version": []string{"http/1.1"},
-       }
-       var headerValueBlockBuf bytes.Buffer
-       writeHeaderValueBlock(&headerValueBlockBuf, headers)
-
-       const bogusStreamId = 1
-       newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
-       if err != nil {
-               t.Fatal("parseHeaderValueBlock:", err)
-       }
-
-       if !reflect.DeepEqual(headers, newHeaders) {
-               t.Fatal("got: ", newHeaders, "\nwant: ", headers)
-       }
-}
-
-func TestCreateParseSynStreamFrame(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer := &Framer{
-               headerCompressionDisabled: true,
-               w:                         buffer,
-               headerBuf:                 new(bytes.Buffer),
-               r:                         buffer,
-       }
-       synStreamFrame := SynStreamFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeSynStream,
-               },
-               Headers: http.Header{
-                       "Url":     []string{"http://www.google.com/"},
-                       "Method":  []string{"get"},
-                       "Version": []string{"http/1.1"},
-               },
-       }
-       if err := framer.WriteFrame(&synStreamFrame); err != nil {
-               t.Fatal("WriteFrame without compression:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame without compression:", err)
-       }
-       parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-               t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-       }
-
-       // Test again with compression
-       buffer.Reset()
-       framer, err = NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       if err := framer.WriteFrame(&synStreamFrame); err != nil {
-               t.Fatal("WriteFrame with compression:", err)
-       }
-       frame, err = framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame with compression:", err)
-       }
-       parsedSynStreamFrame, ok = frame.(*SynStreamFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-               t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-       }
-}
-
-func TestCreateParseSynReplyFrame(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer := &Framer{
-               headerCompressionDisabled: true,
-               w:                         buffer,
-               headerBuf:                 new(bytes.Buffer),
-               r:                         buffer,
-       }
-       synReplyFrame := SynReplyFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeSynReply,
-               },
-               Headers: http.Header{
-                       "Url":     []string{"http://www.google.com/"},
-                       "Method":  []string{"get"},
-                       "Version": []string{"http/1.1"},
-               },
-       }
-       if err := framer.WriteFrame(&synReplyFrame); err != nil {
-               t.Fatal("WriteFrame without compression:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame without compression:", err)
-       }
-       parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
-               t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
-       }
-
-       // Test again with compression
-       buffer.Reset()
-       framer, err = NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       if err := framer.WriteFrame(&synReplyFrame); err != nil {
-               t.Fatal("WriteFrame with compression:", err)
-       }
-       frame, err = framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame with compression:", err)
-       }
-       parsedSynReplyFrame, ok = frame.(*SynReplyFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
-               t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
-       }
-}
-
-func TestCreateParseRstStream(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer, err := NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       rstStreamFrame := RstStreamFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeRstStream,
-               },
-               StreamId: 1,
-               Status:   InvalidStream,
-       }
-       if err := framer.WriteFrame(&rstStreamFrame); err != nil {
-               t.Fatal("WriteFrame:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame:", err)
-       }
-       parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
-               t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
-       }
-}
-
-func TestCreateParseSettings(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer, err := NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       settingsFrame := SettingsFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeSettings,
-               },
-               FlagIdValues: []SettingsFlagIdValue{
-                       {FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
-                       {FlagSettingsPersisted, SettingsUploadBandwidth, 1},
-               },
-       }
-       if err := framer.WriteFrame(&settingsFrame); err != nil {
-               t.Fatal("WriteFrame:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame:", err)
-       }
-       parsedSettingsFrame, ok := frame.(*SettingsFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
-               t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
-       }
-}
-
-func TestCreateParseNoop(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer, err := NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       noopFrame := NoopFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeNoop,
-               },
-       }
-       if err := framer.WriteFrame(&noopFrame); err != nil {
-               t.Fatal("WriteFrame:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame:", err)
-       }
-       parsedNoopFrame, ok := frame.(*NoopFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(noopFrame, *parsedNoopFrame) {
-               t.Fatal("got: ", *parsedNoopFrame, "\nwant: ", noopFrame)
-       }
-}
-
-func TestCreateParsePing(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer, err := NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       pingFrame := PingFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypePing,
-               },
-               Id: 31337,
-       }
-       if err := framer.WriteFrame(&pingFrame); err != nil {
-               t.Fatal("WriteFrame:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame:", err)
-       }
-       parsedPingFrame, ok := frame.(*PingFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
-               t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
-       }
-}
-
-func TestCreateParseGoAway(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer, err := NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       goAwayFrame := GoAwayFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeGoAway,
-               },
-               LastGoodStreamId: 31337,
-       }
-       if err := framer.WriteFrame(&goAwayFrame); err != nil {
-               t.Fatal("WriteFrame:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame:", err)
-       }
-       parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
-               t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
-       }
-}
-
-func TestCreateParseHeadersFrame(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer := &Framer{
-               headerCompressionDisabled: true,
-               w:                         buffer,
-               headerBuf:                 new(bytes.Buffer),
-               r:                         buffer,
-       }
-       headersFrame := HeadersFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeHeaders,
-               },
-       }
-       headersFrame.Headers = http.Header{
-               "Url":     []string{"http://www.google.com/"},
-               "Method":  []string{"get"},
-               "Version": []string{"http/1.1"},
-       }
-       if err := framer.WriteFrame(&headersFrame); err != nil {
-               t.Fatal("WriteFrame without compression:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame without compression:", err)
-       }
-       parsedHeadersFrame, ok := frame.(*HeadersFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-               t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-       }
-
-       // Test again with compression
-       buffer.Reset()
-       framer, err = NewFramer(buffer, buffer)
-       if err := framer.WriteFrame(&headersFrame); err != nil {
-               t.Fatal("WriteFrame with compression:", err)
-       }
-       frame, err = framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame with compression:", err)
-       }
-       parsedHeadersFrame, ok = frame.(*HeadersFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-               t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-       }
-}
-
-func TestCreateParseDataFrame(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer, err := NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       dataFrame := DataFrame{
-               StreamId: 1,
-               Data:     []byte{'h', 'e', 'l', 'l', 'o'},
-       }
-       if err := framer.WriteFrame(&dataFrame); err != nil {
-               t.Fatal("WriteFrame:", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame:", err)
-       }
-       parsedDataFrame, ok := frame.(*DataFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
-               t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
-       }
-}
-
-func TestCompressionContextAcrossFrames(t *testing.T) {
-       buffer := new(bytes.Buffer)
-       framer, err := NewFramer(buffer, buffer)
-       if err != nil {
-               t.Fatal("Failed to create new framer:", err)
-       }
-       headersFrame := HeadersFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeHeaders,
-               },
-               Headers: http.Header{
-                       "Url":     []string{"http://www.google.com/"},
-                       "Method":  []string{"get"},
-                       "Version": []string{"http/1.1"},
-               },
-       }
-       if err := framer.WriteFrame(&headersFrame); err != nil {
-               t.Fatal("WriteFrame (HEADERS):", err)
-       }
-       synStreamFrame := SynStreamFrame{ControlFrameHeader{Version, TypeSynStream, 0, 0}, 0, 0, 0, nil}
-       synStreamFrame.Headers = http.Header{
-               "Url":     []string{"http://www.google.com/"},
-               "Method":  []string{"get"},
-               "Version": []string{"http/1.1"},
-       }
-       if err := framer.WriteFrame(&synStreamFrame); err != nil {
-               t.Fatal("WriteFrame (SYN_STREAM):", err)
-       }
-       frame, err := framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
-       }
-       parsedHeadersFrame, ok := frame.(*HeadersFrame)
-       if !ok {
-               t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
-       }
-       if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-               t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-       }
-       frame, err = framer.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
-       }
-       parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
-       if !ok {
-               t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
-       }
-       if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-               t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-       }
-}
-
-func TestMultipleSPDYFrames(t *testing.T) {
-       // Initialize the framers.
-       pr1, pw1 := io.Pipe()
-       pr2, pw2 := io.Pipe()
-       writer, err := NewFramer(pw1, pr2)
-       if err != nil {
-               t.Fatal("Failed to create writer:", err)
-       }
-       reader, err := NewFramer(pw2, pr1)
-       if err != nil {
-               t.Fatal("Failed to create reader:", err)
-       }
-
-       // Set up the frames we're actually transferring.
-       headersFrame := HeadersFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeHeaders,
-               },
-               Headers: http.Header{
-                       "Url":     []string{"http://www.google.com/"},
-                       "Method":  []string{"get"},
-                       "Version": []string{"http/1.1"},
-               },
-       }
-       synStreamFrame := SynStreamFrame{
-               CFHeader: ControlFrameHeader{
-                       version:   Version,
-                       frameType: TypeSynStream,
-               },
-               Headers: http.Header{
-                       "Url":     []string{"http://www.google.com/"},
-                       "Method":  []string{"get"},
-                       "Version": []string{"http/1.1"},
-               },
-       }
-
-       // Start the goroutines to write the frames.
-       go func() {
-               if err := writer.WriteFrame(&headersFrame); err != nil {
-                       t.Fatal("WriteFrame (HEADERS): ", err)
-               }
-               if err := writer.WriteFrame(&synStreamFrame); err != nil {
-                       t.Fatal("WriteFrame (SYN_STREAM): ", err)
-               }
-       }()
-
-       // Read the frames and verify they look as expected.
-       frame, err := reader.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame (HEADERS): ", err)
-       }
-       parsedHeadersFrame, ok := frame.(*HeadersFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type:", frame)
-       }
-       if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
-               t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
-       }
-       frame, err = reader.ReadFrame()
-       if err != nil {
-               t.Fatal("ReadFrame (SYN_STREAM):", err)
-       }
-       parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
-       if !ok {
-               t.Fatal("Parsed incorrect frame type.")
-       }
-       if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
-               t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
-       }
-}
diff --git a/libgo/go/exp/spdy/types.go b/libgo/go/exp/spdy/types.go
deleted file mode 100644 (file)
index 2648c4f..0000000
+++ /dev/null
@@ -1,369 +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 spdy
-
-import (
-       "bytes"
-       "compress/zlib"
-       "io"
-       "net/http"
-)
-
-//  Data Frame Format
-//  +----------------------------------+
-//  |0|       Stream-ID (31bits)       |
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |
-//  +----------------------------------+
-//  |               Data               |
-//  +----------------------------------+
-//
-//  Control Frame Format
-//  +----------------------------------+
-//  |1| Version(15bits) | Type(16bits) |
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |
-//  +----------------------------------+
-//  |               Data               |
-//  +----------------------------------+
-//
-//  Control Frame: SYN_STREAM
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000001|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |  >= 12
-//  +----------------------------------+
-//  |X|       Stream-ID(31bits)        |
-//  +----------------------------------+
-//  |X|Associated-To-Stream-ID (31bits)|
-//  +----------------------------------+
-//  |Pri| unused      | Length (16bits)|
-//  +----------------------------------+
-//
-//  Control Frame: SYN_REPLY
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000010|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |  >= 8
-//  +----------------------------------+
-//  |X|       Stream-ID(31bits)        |
-//  +----------------------------------+
-//  | unused (16 bits)| Length (16bits)|
-//  +----------------------------------+
-//
-//  Control Frame: RST_STREAM
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000011|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |  >= 4
-//  +----------------------------------+
-//  |X|       Stream-ID(31bits)        |
-//  +----------------------------------+
-//  |        Status code (32 bits)     |
-//  +----------------------------------+
-//
-//  Control Frame: SETTINGS
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000100|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   |
-//  +----------------------------------+
-//  |        # of entries (32)         |
-//  +----------------------------------+
-//
-//  Control Frame: NOOP
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000101|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 0
-//  +----------------------------------+
-//
-//  Control Frame: PING
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000110|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 4
-//  +----------------------------------+
-//  |        Unique id (32 bits)       |
-//  +----------------------------------+
-//
-//  Control Frame: GOAWAY
-//  +----------------------------------+
-//  |1|000000000000001|0000000000000111|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 4
-//  +----------------------------------+
-//  |X|  Last-accepted-stream-id       |
-//  +----------------------------------+
-//
-//  Control Frame: HEADERS
-//  +----------------------------------+
-//  |1|000000000000001|0000000000001000|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | >= 8
-//  +----------------------------------+
-//  |X|      Stream-ID (31 bits)       |
-//  +----------------------------------+
-//  | unused (16 bits)| Length (16bits)|
-//  +----------------------------------+
-//
-//  Control Frame: WINDOW_UPDATE
-//  +----------------------------------+
-//  |1|000000000000001|0000000000001001|
-//  +----------------------------------+
-//  | flags (8)  |  Length (24 bits)   | = 8
-//  +----------------------------------+
-//  |X|      Stream-ID (31 bits)       |
-//  +----------------------------------+
-//  |   Delta-Window-Size (32 bits)    |
-//  +----------------------------------+
-
-// Version is the protocol version number that this package implements.
-const Version = 2
-
-// ControlFrameType stores the type field in a control frame header.
-type ControlFrameType uint16
-
-// Control frame type constants
-const (
-       TypeSynStream    ControlFrameType = 0x0001
-       TypeSynReply                      = 0x0002
-       TypeRstStream                     = 0x0003
-       TypeSettings                      = 0x0004
-       TypeNoop                          = 0x0005
-       TypePing                          = 0x0006
-       TypeGoAway                        = 0x0007
-       TypeHeaders                       = 0x0008
-       TypeWindowUpdate                  = 0x0009
-)
-
-// ControlFlags are the flags that can be set on a control frame.
-type ControlFlags uint8
-
-const (
-       ControlFlagFin ControlFlags = 0x01
-)
-
-// DataFlags are the flags that can be set on a data frame.
-type DataFlags uint8
-
-const (
-       DataFlagFin        DataFlags = 0x01
-       DataFlagCompressed           = 0x02
-)
-
-// MaxDataLength is the maximum number of bytes that can be stored in one frame.
-const MaxDataLength = 1<<24 - 1
-
-// Frame is a single SPDY frame in its unpacked in-memory representation. Use
-// Framer to read and write it.
-type Frame interface {
-       write(f *Framer) error
-}
-
-// ControlFrameHeader contains all the fields in a control frame header,
-// in its unpacked in-memory representation.
-type ControlFrameHeader struct {
-       // Note, high bit is the "Control" bit.
-       version   uint16
-       frameType ControlFrameType
-       Flags     ControlFlags
-       length    uint32
-}
-
-type controlFrame interface {
-       Frame
-       read(h ControlFrameHeader, f *Framer) error
-}
-
-// SynStreamFrame is the unpacked, in-memory representation of a SYN_STREAM
-// frame.
-type SynStreamFrame struct {
-       CFHeader             ControlFrameHeader
-       StreamId             uint32
-       AssociatedToStreamId uint32
-       // Note, only 2 highest bits currently used
-       // Rest of Priority is unused.
-       Priority uint16
-       Headers  http.Header
-}
-
-// SynReplyFrame is the unpacked, in-memory representation of a SYN_REPLY frame.
-type SynReplyFrame struct {
-       CFHeader ControlFrameHeader
-       StreamId uint32
-       Headers  http.Header
-}
-
-// StatusCode represents the status that led to a RST_STREAM
-type StatusCode uint32
-
-const (
-       ProtocolError      StatusCode = 1
-       InvalidStream                 = 2
-       RefusedStream                 = 3
-       UnsupportedVersion            = 4
-       Cancel                        = 5
-       InternalError                 = 6
-       FlowControlError              = 7
-)
-
-// RstStreamFrame is the unpacked, in-memory representation of a RST_STREAM
-// frame.
-type RstStreamFrame struct {
-       CFHeader ControlFrameHeader
-       StreamId uint32
-       Status   StatusCode
-}
-
-// SettingsFlag represents a flag in a SETTINGS frame.
-type SettingsFlag uint8
-
-const (
-       FlagSettingsPersistValue SettingsFlag = 0x1
-       FlagSettingsPersisted                 = 0x2
-)
-
-// SettingsFlag represents the id of an id/value pair in a SETTINGS frame.
-type SettingsId uint32
-
-const (
-       SettingsUploadBandwidth      SettingsId = 1
-       SettingsDownloadBandwidth               = 2
-       SettingsRoundTripTime                   = 3
-       SettingsMaxConcurrentStreams            = 4
-       SettingsCurrentCwnd                     = 5
-)
-
-// SettingsFlagIdValue is the unpacked, in-memory representation of the
-// combined flag/id/value for a setting in a SETTINGS frame.
-type SettingsFlagIdValue struct {
-       Flag  SettingsFlag
-       Id    SettingsId
-       Value uint32
-}
-
-// SettingsFrame is the unpacked, in-memory representation of a SPDY
-// SETTINGS frame.
-type SettingsFrame struct {
-       CFHeader     ControlFrameHeader
-       FlagIdValues []SettingsFlagIdValue
-}
-
-// NoopFrame is the unpacked, in-memory representation of a NOOP frame.
-type NoopFrame struct {
-       CFHeader ControlFrameHeader
-}
-
-// PingFrame is the unpacked, in-memory representation of a PING frame.
-type PingFrame struct {
-       CFHeader ControlFrameHeader
-       Id       uint32
-}
-
-// GoAwayFrame is the unpacked, in-memory representation of a GOAWAY frame.
-type GoAwayFrame struct {
-       CFHeader         ControlFrameHeader
-       LastGoodStreamId uint32
-}
-
-// HeadersFrame is the unpacked, in-memory representation of a HEADERS frame.
-type HeadersFrame struct {
-       CFHeader ControlFrameHeader
-       StreamId uint32
-       Headers  http.Header
-}
-
-// DataFrame is the unpacked, in-memory representation of a DATA frame.
-type DataFrame struct {
-       // Note, high bit is the "Control" bit. Should be 0 for data frames.
-       StreamId uint32
-       Flags    DataFlags
-       Data     []byte
-}
-
-// HeaderDictionary is the dictionary sent to the zlib compressor/decompressor.
-// Even though the specification states there is no null byte at the end, Chrome sends it.
-const HeaderDictionary = "optionsgetheadpostputdeletetrace" +
-       "acceptaccept-charsetaccept-encodingaccept-languageauthorizationexpectfromhost" +
-       "if-modified-sinceif-matchif-none-matchif-rangeif-unmodifiedsince" +
-       "max-forwardsproxy-authorizationrangerefererteuser-agent" +
-       "100101200201202203204205206300301302303304305306307400401402403404405406407408409410411412413414415416417500501502503504505" +
-       "accept-rangesageetaglocationproxy-authenticatepublicretry-after" +
-       "servervarywarningwww-authenticateallowcontent-basecontent-encodingcache-control" +
-       "connectiondatetrailertransfer-encodingupgradeviawarning" +
-       "content-languagecontent-lengthcontent-locationcontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookie" +
-       "MondayTuesdayWednesdayThursdayFridaySaturdaySunday" +
-       "JanFebMarAprMayJunJulAugSepOctNovDec" +
-       "chunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplication/xhtmltext/plainpublicmax-age" +
-       "charset=iso-8859-1utf-8gzipdeflateHTTP/1.1statusversionurl\x00"
-
-// A SPDY specific error.
-type ErrorCode string
-
-const (
-       UnlowercasedHeaderName     ErrorCode = "header was not lowercased"
-       DuplicateHeaders           ErrorCode = "multiple headers with same name"
-       WrongCompressedPayloadSize ErrorCode = "compressed payload size was incorrect"
-       UnknownFrameType           ErrorCode = "unknown frame type"
-       InvalidControlFrame        ErrorCode = "invalid control frame"
-       InvalidDataFrame           ErrorCode = "invalid data frame"
-       InvalidHeaderPresent       ErrorCode = "frame contained invalid header"
-)
-
-// Error contains both the type of error and additional values. StreamId is 0
-// if Error is not associated with a stream.
-type Error struct {
-       Err      ErrorCode
-       StreamId uint32
-}
-
-func (e *Error) Error() string {
-       return string(e.Err)
-}
-
-var invalidReqHeaders = map[string]bool{
-       "Connection":        true,
-       "Keep-Alive":        true,
-       "Proxy-Connection":  true,
-       "Transfer-Encoding": true,
-}
-
-var invalidRespHeaders = map[string]bool{
-       "Connection":        true,
-       "Keep-Alive":        true,
-       "Transfer-Encoding": true,
-}
-
-// Framer handles serializing/deserializing SPDY frames, including compressing/
-// decompressing payloads.
-type Framer struct {
-       headerCompressionDisabled bool
-       w                         io.Writer
-       headerBuf                 *bytes.Buffer
-       headerCompressor          *zlib.Writer
-       r                         io.Reader
-       headerReader              io.LimitedReader
-       headerDecompressor        io.ReadCloser
-}
-
-// NewFramer allocates a new Framer for a given SPDY connection, repesented by
-// a io.Writer and io.Reader. Note that Framer will read and write individual fields 
-// from/to the Reader and Writer, so the caller should pass in an appropriately 
-// buffered implementation to optimize performance.
-func NewFramer(w io.Writer, r io.Reader) (*Framer, error) {
-       compressBuf := new(bytes.Buffer)
-       compressor, err := zlib.NewWriterDict(compressBuf, zlib.BestCompression, []byte(HeaderDictionary))
-       if err != nil {
-               return nil, err
-       }
-       framer := &Framer{
-               w:                w,
-               headerBuf:        compressBuf,
-               headerCompressor: compressor,
-               r:                r,
-       }
-       return framer, nil
-}
diff --git a/libgo/go/exp/spdy/write.go b/libgo/go/exp/spdy/write.go
deleted file mode 100644 (file)
index 3dd2ca1..0000000
+++ /dev/null
@@ -1,285 +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 spdy
-
-import (
-       "encoding/binary"
-       "io"
-       "net/http"
-       "strings"
-)
-
-func (frame *SynStreamFrame) write(f *Framer) error {
-       return f.writeSynStreamFrame(frame)
-}
-
-func (frame *SynReplyFrame) write(f *Framer) error {
-       return f.writeSynReplyFrame(frame)
-}
-
-func (frame *RstStreamFrame) write(f *Framer) (err error) {
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypeRstStream
-       frame.CFHeader.length = 8
-
-       // Serialize frame to Writer
-       if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
-               return
-       }
-       return
-}
-
-func (frame *SettingsFrame) write(f *Framer) (err error) {
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypeSettings
-       frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
-
-       // Serialize frame to Writer
-       if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
-               return
-       }
-       for _, flagIdValue := range frame.FlagIdValues {
-               flagId := (uint32(flagIdValue.Flag) << 24) | uint32(flagIdValue.Id)
-               if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
-                       return
-               }
-               if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
-                       return
-               }
-       }
-       return
-}
-
-func (frame *NoopFrame) write(f *Framer) error {
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypeNoop
-
-       // Serialize frame to Writer
-       return writeControlFrameHeader(f.w, frame.CFHeader)
-}
-
-func (frame *PingFrame) write(f *Framer) (err error) {
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypePing
-       frame.CFHeader.length = 4
-
-       // Serialize frame to Writer
-       if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
-               return
-       }
-       return
-}
-
-func (frame *GoAwayFrame) write(f *Framer) (err error) {
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypeGoAway
-       frame.CFHeader.length = 4
-
-       // Serialize frame to Writer
-       if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
-               return
-       }
-       return nil
-}
-
-func (frame *HeadersFrame) write(f *Framer) error {
-       return f.writeHeadersFrame(frame)
-}
-
-func (frame *DataFrame) write(f *Framer) error {
-       return f.writeDataFrame(frame)
-}
-
-// WriteFrame writes a frame.
-func (f *Framer) WriteFrame(frame Frame) error {
-       return frame.write(f)
-}
-
-func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
-       if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
-               return err
-       }
-       if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
-               return err
-       }
-       flagsAndLength := (uint32(h.Flags) << 24) | h.length
-       if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
-               return err
-       }
-       return nil
-}
-
-func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
-       n = 0
-       if err = binary.Write(w, binary.BigEndian, uint16(len(h))); err != nil {
-               return
-       }
-       n += 2
-       for name, values := range h {
-               if err = binary.Write(w, binary.BigEndian, uint16(len(name))); err != nil {
-                       return
-               }
-               n += 2
-               name = strings.ToLower(name)
-               if _, err = io.WriteString(w, name); err != nil {
-                       return
-               }
-               n += len(name)
-               v := strings.Join(values, "\x00")
-               if err = binary.Write(w, binary.BigEndian, uint16(len(v))); err != nil {
-                       return
-               }
-               n += 2
-               if _, err = io.WriteString(w, v); err != nil {
-                       return
-               }
-               n += len(v)
-       }
-       return
-}
-
-func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
-       // Marshal the headers.
-       var writer io.Writer = f.headerBuf
-       if !f.headerCompressionDisabled {
-               writer = f.headerCompressor
-       }
-       if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
-               return
-       }
-       if !f.headerCompressionDisabled {
-               f.headerCompressor.Flush()
-       }
-
-       // Set ControlFrameHeader
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypeSynStream
-       frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
-
-       // Serialize frame to Writer
-       if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-               return err
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-               return err
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
-               return err
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<14); err != nil {
-               return err
-       }
-       if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
-               return err
-       }
-       f.headerBuf.Reset()
-       return nil
-}
-
-func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
-       // Marshal the headers.
-       var writer io.Writer = f.headerBuf
-       if !f.headerCompressionDisabled {
-               writer = f.headerCompressor
-       }
-       if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
-               return
-       }
-       if !f.headerCompressionDisabled {
-               f.headerCompressor.Flush()
-       }
-
-       // Set ControlFrameHeader
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypeSynReply
-       frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
-
-       // Serialize frame to Writer
-       if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
-               return
-       }
-       if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
-               return
-       }
-       f.headerBuf.Reset()
-       return
-}
-
-func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
-       // Marshal the headers.
-       var writer io.Writer = f.headerBuf
-       if !f.headerCompressionDisabled {
-               writer = f.headerCompressor
-       }
-       if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
-               return
-       }
-       if !f.headerCompressionDisabled {
-               f.headerCompressor.Flush()
-       }
-
-       // Set ControlFrameHeader
-       frame.CFHeader.version = Version
-       frame.CFHeader.frameType = TypeHeaders
-       frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 6)
-
-       // Serialize frame to Writer
-       if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-               return
-       }
-       if err = binary.Write(f.w, binary.BigEndian, uint16(0)); err != nil {
-               return
-       }
-       if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
-               return
-       }
-       f.headerBuf.Reset()
-       return
-}
-
-func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
-       // Validate DataFrame
-       if frame.StreamId&0x80000000 != 0 || len(frame.Data) >= 0x0f000000 {
-               return &Error{InvalidDataFrame, frame.StreamId}
-       }
-
-       // Serialize frame to Writer
-       if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
-               return
-       }
-       flagsAndLength := (uint32(frame.Flags) << 24) | uint32(len(frame.Data))
-       if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
-               return
-       }
-       if _, err = f.w.Write(frame.Data); err != nil {
-               return
-       }
-
-       return nil
-}
diff --git a/libgo/go/exp/ssh/channel.go b/libgo/go/exp/ssh/channel.go
deleted file mode 100644 (file)
index 9d75f37..0000000
+++ /dev/null
@@ -1,318 +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 ssh
-
-import (
-       "errors"
-       "io"
-       "sync"
-)
-
-// A Channel is an ordered, reliable, duplex stream that is multiplexed over an
-// SSH connection.
-type Channel interface {
-       // Accept accepts the channel creation request.
-       Accept() error
-       // Reject rejects the channel creation request. After calling this, no
-       // other methods on the Channel may be called. If they are then the
-       // peer is likely to signal a protocol error and drop the connection.
-       Reject(reason RejectionReason, message string) error
-
-       // Read may return a ChannelRequest as an error.
-       Read(data []byte) (int, error)
-       Write(data []byte) (int, error)
-       Close() error
-
-       // AckRequest either sends an ack or nack to the channel request.
-       AckRequest(ok bool) error
-
-       // ChannelType returns the type of the channel, as supplied by the
-       // client.
-       ChannelType() string
-       // ExtraData returns the arbitary payload for this channel, as supplied
-       // by the client. This data is specific to the channel type.
-       ExtraData() []byte
-}
-
-// ChannelRequest represents a request sent on a channel, outside of the normal
-// stream of bytes. It may result from calling Read on a Channel.
-type ChannelRequest struct {
-       Request   string
-       WantReply bool
-       Payload   []byte
-}
-
-func (c ChannelRequest) Error() string {
-       return "channel request received"
-}
-
-// RejectionReason is an enumeration used when rejecting channel creation
-// requests. See RFC 4254, section 5.1.
-type RejectionReason int
-
-const (
-       Prohibited RejectionReason = iota + 1
-       ConnectionFailed
-       UnknownChannelType
-       ResourceShortage
-)
-
-type channel struct {
-       // immutable once created
-       chanType  string
-       extraData []byte
-
-       theyClosed  bool
-       theySentEOF bool
-       weClosed    bool
-       dead        bool
-
-       serverConn            *ServerConn
-       myId, theirId         uint32
-       myWindow, theirWindow uint32
-       maxPacketSize         uint32
-       err                   error
-
-       pendingRequests []ChannelRequest
-       pendingData     []byte
-       head, length    int
-
-       // This lock is inferior to serverConn.lock
-       lock sync.Mutex
-       cond *sync.Cond
-}
-
-func (c *channel) Accept() error {
-       c.serverConn.lock.Lock()
-       defer c.serverConn.lock.Unlock()
-
-       if c.serverConn.err != nil {
-               return c.serverConn.err
-       }
-
-       confirm := channelOpenConfirmMsg{
-               PeersId:       c.theirId,
-               MyId:          c.myId,
-               MyWindow:      c.myWindow,
-               MaxPacketSize: c.maxPacketSize,
-       }
-       return c.serverConn.writePacket(marshal(msgChannelOpenConfirm, confirm))
-}
-
-func (c *channel) Reject(reason RejectionReason, message string) error {
-       c.serverConn.lock.Lock()
-       defer c.serverConn.lock.Unlock()
-
-       if c.serverConn.err != nil {
-               return c.serverConn.err
-       }
-
-       reject := channelOpenFailureMsg{
-               PeersId:  c.theirId,
-               Reason:   uint32(reason),
-               Message:  message,
-               Language: "en",
-       }
-       return c.serverConn.writePacket(marshal(msgChannelOpenFailure, reject))
-}
-
-func (c *channel) handlePacket(packet interface{}) {
-       c.lock.Lock()
-       defer c.lock.Unlock()
-
-       switch packet := packet.(type) {
-       case *channelRequestMsg:
-               req := ChannelRequest{
-                       Request:   packet.Request,
-                       WantReply: packet.WantReply,
-                       Payload:   packet.RequestSpecificData,
-               }
-
-               c.pendingRequests = append(c.pendingRequests, req)
-               c.cond.Signal()
-       case *channelCloseMsg:
-               c.theyClosed = true
-               c.cond.Signal()
-       case *channelEOFMsg:
-               c.theySentEOF = true
-               c.cond.Signal()
-       default:
-               panic("unknown packet type")
-       }
-}
-
-func (c *channel) handleData(data []byte) {
-       c.lock.Lock()
-       defer c.lock.Unlock()
-
-       // The other side should never send us more than our window.
-       if len(data)+c.length > len(c.pendingData) {
-               // TODO(agl): we should tear down the channel with a protocol
-               // error.
-               return
-       }
-
-       c.myWindow -= uint32(len(data))
-       for i := 0; i < 2; i++ {
-               tail := c.head + c.length
-               if tail > len(c.pendingData) {
-                       tail -= len(c.pendingData)
-               }
-               n := copy(c.pendingData[tail:], data)
-               data = data[n:]
-               c.length += n
-       }
-
-       c.cond.Signal()
-}
-
-func (c *channel) Read(data []byte) (n int, err error) {
-       c.lock.Lock()
-       defer c.lock.Unlock()
-
-       if c.err != nil {
-               return 0, c.err
-       }
-
-       if c.myWindow <= uint32(len(c.pendingData))/2 {
-               packet := marshal(msgChannelWindowAdjust, windowAdjustMsg{
-                       PeersId:         c.theirId,
-                       AdditionalBytes: uint32(len(c.pendingData)) - c.myWindow,
-               })
-               if err := c.serverConn.writePacket(packet); err != nil {
-                       return 0, err
-               }
-       }
-
-       for {
-               if c.theySentEOF || c.theyClosed || c.dead {
-                       return 0, io.EOF
-               }
-
-               if len(c.pendingRequests) > 0 {
-                       req := c.pendingRequests[0]
-                       if len(c.pendingRequests) == 1 {
-                               c.pendingRequests = nil
-                       } else {
-                               oldPendingRequests := c.pendingRequests
-                               c.pendingRequests = make([]ChannelRequest, len(oldPendingRequests)-1)
-                               copy(c.pendingRequests, oldPendingRequests[1:])
-                       }
-
-                       return 0, req
-               }
-
-               if c.length > 0 {
-                       tail := c.head + c.length
-                       if tail > len(c.pendingData) {
-                               tail -= len(c.pendingData)
-                       }
-                       n = copy(data, c.pendingData[c.head:tail])
-                       c.head += n
-                       c.length -= n
-                       if c.head == len(c.pendingData) {
-                               c.head = 0
-                       }
-                       return
-               }
-
-               c.cond.Wait()
-       }
-
-       panic("unreachable")
-}
-
-func (c *channel) Write(data []byte) (n int, err error) {
-       for len(data) > 0 {
-               c.lock.Lock()
-               if c.dead || c.weClosed {
-                       return 0, io.EOF
-               }
-
-               if c.theirWindow == 0 {
-                       c.cond.Wait()
-                       continue
-               }
-               c.lock.Unlock()
-
-               todo := data
-               if uint32(len(todo)) > c.theirWindow {
-                       todo = todo[:c.theirWindow]
-               }
-
-               packet := make([]byte, 1+4+4+len(todo))
-               packet[0] = msgChannelData
-               packet[1] = byte(c.theirId >> 24)
-               packet[2] = byte(c.theirId >> 16)
-               packet[3] = byte(c.theirId >> 8)
-               packet[4] = byte(c.theirId)
-               packet[5] = byte(len(todo) >> 24)
-               packet[6] = byte(len(todo) >> 16)
-               packet[7] = byte(len(todo) >> 8)
-               packet[8] = byte(len(todo))
-               copy(packet[9:], todo)
-
-               c.serverConn.lock.Lock()
-               if err = c.serverConn.writePacket(packet); err != nil {
-                       c.serverConn.lock.Unlock()
-                       return
-               }
-               c.serverConn.lock.Unlock()
-
-               n += len(todo)
-               data = data[len(todo):]
-       }
-
-       return
-}
-
-func (c *channel) Close() error {
-       c.serverConn.lock.Lock()
-       defer c.serverConn.lock.Unlock()
-
-       if c.serverConn.err != nil {
-               return c.serverConn.err
-       }
-
-       if c.weClosed {
-               return errors.New("ssh: channel already closed")
-       }
-       c.weClosed = true
-
-       closeMsg := channelCloseMsg{
-               PeersId: c.theirId,
-       }
-       return c.serverConn.writePacket(marshal(msgChannelClose, closeMsg))
-}
-
-func (c *channel) AckRequest(ok bool) error {
-       c.serverConn.lock.Lock()
-       defer c.serverConn.lock.Unlock()
-
-       if c.serverConn.err != nil {
-               return c.serverConn.err
-       }
-
-       if ok {
-               ack := channelRequestSuccessMsg{
-                       PeersId: c.theirId,
-               }
-               return c.serverConn.writePacket(marshal(msgChannelSuccess, ack))
-       } else {
-               ack := channelRequestFailureMsg{
-                       PeersId: c.theirId,
-               }
-               return c.serverConn.writePacket(marshal(msgChannelFailure, ack))
-       }
-       panic("unreachable")
-}
-
-func (c *channel) ChannelType() string {
-       return c.chanType
-}
-
-func (c *channel) ExtraData() []byte {
-       return c.extraData
-}
diff --git a/libgo/go/exp/ssh/cipher.go b/libgo/go/exp/ssh/cipher.go
deleted file mode 100644 (file)
index d91929a..0000000
+++ /dev/null
@@ -1,88 +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 ssh
-
-import (
-       "crypto/aes"
-       "crypto/cipher"
-       "crypto/rc4"
-)
-
-// streamDump is used to dump the initial keystream for stream ciphers. It is a
-// a write-only buffer, and not intended for reading so do not require a mutex.
-var streamDump [512]byte
-
-// noneCipher implements cipher.Stream and provides no encryption. It is used
-// by the transport before the first key-exchange.
-type noneCipher struct{}
-
-func (c noneCipher) XORKeyStream(dst, src []byte) {
-       copy(dst, src)
-}
-
-func newAESCTR(key, iv []byte) (cipher.Stream, error) {
-       c, err := aes.NewCipher(key)
-       if err != nil {
-               return nil, err
-       }
-       return cipher.NewCTR(c, iv), nil
-}
-
-func newRC4(key, iv []byte) (cipher.Stream, error) {
-       return rc4.NewCipher(key)
-}
-
-type cipherMode struct {
-       keySize  int
-       ivSize   int
-       skip     int
-       createFn func(key, iv []byte) (cipher.Stream, error)
-}
-
-func (c *cipherMode) createCipher(key, iv []byte) (cipher.Stream, error) {
-       if len(key) < c.keySize {
-               panic("ssh: key length too small for cipher")
-       }
-       if len(iv) < c.ivSize {
-               panic("ssh: iv too small for cipher")
-       }
-
-       stream, err := c.createFn(key[:c.keySize], iv[:c.ivSize])
-       if err != nil {
-               return nil, err
-       }
-
-       for remainingToDump := c.skip; remainingToDump > 0; {
-               dumpThisTime := remainingToDump
-               if dumpThisTime > len(streamDump) {
-                       dumpThisTime = len(streamDump)
-               }
-               stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
-               remainingToDump -= dumpThisTime
-       }
-
-       return stream, nil
-}
-
-// Specifies a default set of ciphers and a preference order. This is based on
-// OpenSSH's default client preference order, minus algorithms that are not
-// implemented.
-var DefaultCipherOrder = []string{
-       "aes128-ctr", "aes192-ctr", "aes256-ctr",
-       "arcfour256", "arcfour128",
-}
-
-var cipherModes = map[string]*cipherMode{
-       // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
-       // are defined in the order specified in the RFC.
-       "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
-       "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
-       "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
-
-       // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
-       // They are defined in the order specified in the RFC.
-       "arcfour128": {16, 0, 1536, newRC4},
-       "arcfour256": {32, 0, 1536, newRC4},
-}
diff --git a/libgo/go/exp/ssh/cipher_test.go b/libgo/go/exp/ssh/cipher_test.go
deleted file mode 100644 (file)
index ea27bd8..0000000
+++ /dev/null
@@ -1,62 +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 ssh
-
-import (
-       "bytes"
-       "testing"
-)
-
-// TestCipherReversal tests that each cipher factory produces ciphers that can
-// encrypt and decrypt some data successfully.
-func TestCipherReversal(t *testing.T) {
-       testData := []byte("abcdefghijklmnopqrstuvwxyz012345")
-       testKey := []byte("AbCdEfGhIjKlMnOpQrStUvWxYz012345")
-       testIv := []byte("sdflkjhsadflkjhasdflkjhsadfklhsa")
-
-       cryptBuffer := make([]byte, 32)
-
-       for name, cipherMode := range cipherModes {
-               encrypter, err := cipherMode.createCipher(testKey, testIv)
-               if err != nil {
-                       t.Errorf("failed to create encrypter for %q: %s", name, err)
-                       continue
-               }
-               decrypter, err := cipherMode.createCipher(testKey, testIv)
-               if err != nil {
-                       t.Errorf("failed to create decrypter for %q: %s", name, err)
-                       continue
-               }
-
-               copy(cryptBuffer, testData)
-
-               encrypter.XORKeyStream(cryptBuffer, cryptBuffer)
-               if name == "none" {
-                       if !bytes.Equal(cryptBuffer, testData) {
-                               t.Errorf("encryption made change with 'none' cipher")
-                               continue
-                       }
-               } else {
-                       if bytes.Equal(cryptBuffer, testData) {
-                               t.Errorf("encryption made no change with %q", name)
-                               continue
-                       }
-               }
-
-               decrypter.XORKeyStream(cryptBuffer, cryptBuffer)
-               if !bytes.Equal(cryptBuffer, testData) {
-                       t.Errorf("decrypted bytes not equal to input with %q", name)
-                       continue
-               }
-       }
-}
-
-func TestDefaultCiphersExist(t *testing.T) {
-       for _, cipherAlgo := range DefaultCipherOrder {
-               if _, ok := cipherModes[cipherAlgo]; !ok {
-                       t.Errorf("default cipher %q is unknown", cipherAlgo)
-               }
-       }
-}
diff --git a/libgo/go/exp/ssh/client.go b/libgo/go/exp/ssh/client.go
deleted file mode 100644 (file)
index eb6c035..0000000
+++ /dev/null
@@ -1,505 +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 ssh
-
-import (
-       "crypto"
-       "crypto/rand"
-       "errors"
-       "fmt"
-       "io"
-       "math/big"
-       "net"
-       "sync"
-)
-
-// clientVersion is the fixed identification string that the client will use.
-var clientVersion = []byte("SSH-2.0-Go\r\n")
-
-// ClientConn represents the client side of an SSH connection.
-type ClientConn struct {
-       *transport
-       config *ClientConfig
-       chanlist
-}
-
-// Client returns a new SSH client connection using c as the underlying transport.
-func Client(c net.Conn, config *ClientConfig) (*ClientConn, error) {
-       conn := &ClientConn{
-               transport: newTransport(c, config.rand()),
-               config:    config,
-       }
-       if err := conn.handshake(); err != nil {
-               conn.Close()
-               return nil, err
-       }
-       go conn.mainLoop()
-       return conn, nil
-}
-
-// handshake performs the client side key exchange. See RFC 4253 Section 7.
-func (c *ClientConn) handshake() error {
-       var magics handshakeMagics
-
-       if _, err := c.Write(clientVersion); err != nil {
-               return err
-       }
-       if err := c.Flush(); err != nil {
-               return err
-       }
-       magics.clientVersion = clientVersion[:len(clientVersion)-2]
-
-       // read remote server version
-       version, err := readVersion(c)
-       if err != nil {
-               return err
-       }
-       magics.serverVersion = version
-       clientKexInit := kexInitMsg{
-               KexAlgos:                supportedKexAlgos,
-               ServerHostKeyAlgos:      supportedHostKeyAlgos,
-               CiphersClientServer:     c.config.Crypto.ciphers(),
-               CiphersServerClient:     c.config.Crypto.ciphers(),
-               MACsClientServer:        supportedMACs,
-               MACsServerClient:        supportedMACs,
-               CompressionClientServer: supportedCompressions,
-               CompressionServerClient: supportedCompressions,
-       }
-       kexInitPacket := marshal(msgKexInit, clientKexInit)
-       magics.clientKexInit = kexInitPacket
-
-       if err := c.writePacket(kexInitPacket); err != nil {
-               return err
-       }
-       packet, err := c.readPacket()
-       if err != nil {
-               return err
-       }
-
-       magics.serverKexInit = packet
-
-       var serverKexInit kexInitMsg
-       if err = unmarshal(&serverKexInit, packet, msgKexInit); err != nil {
-               return err
-       }
-
-       kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(c.transport, &clientKexInit, &serverKexInit)
-       if !ok {
-               return errors.New("ssh: no common algorithms")
-       }
-
-       if serverKexInit.FirstKexFollows && kexAlgo != serverKexInit.KexAlgos[0] {
-               // The server sent a Kex message for the wrong algorithm,
-               // which we have to ignore.
-               if _, err := c.readPacket(); err != nil {
-                       return err
-               }
-       }
-
-       var H, K []byte
-       var hashFunc crypto.Hash
-       switch kexAlgo {
-       case kexAlgoDH14SHA1:
-               hashFunc = crypto.SHA1
-               dhGroup14Once.Do(initDHGroup14)
-               H, K, err = c.kexDH(dhGroup14, hashFunc, &magics, hostKeyAlgo)
-       default:
-               err = fmt.Errorf("ssh: unexpected key exchange algorithm %v", kexAlgo)
-       }
-       if err != nil {
-               return err
-       }
-
-       if err = c.writePacket([]byte{msgNewKeys}); err != nil {
-               return err
-       }
-       if err = c.transport.writer.setupKeys(clientKeys, K, H, H, hashFunc); err != nil {
-               return err
-       }
-       if packet, err = c.readPacket(); err != nil {
-               return err
-       }
-       if packet[0] != msgNewKeys {
-               return UnexpectedMessageError{msgNewKeys, packet[0]}
-       }
-       if err := c.transport.reader.setupKeys(serverKeys, K, H, H, hashFunc); err != nil {
-               return err
-       }
-       return c.authenticate(H)
-}
-
-// kexDH performs Diffie-Hellman key agreement on a ClientConn. The
-// returned values are given the same names as in RFC 4253, section 8.
-func (c *ClientConn) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handshakeMagics, hostKeyAlgo string) ([]byte, []byte, error) {
-       x, err := rand.Int(c.config.rand(), group.p)
-       if err != nil {
-               return nil, nil, err
-       }
-       X := new(big.Int).Exp(group.g, x, group.p)
-       kexDHInit := kexDHInitMsg{
-               X: X,
-       }
-       if err := c.writePacket(marshal(msgKexDHInit, kexDHInit)); err != nil {
-               return nil, nil, err
-       }
-
-       packet, err := c.readPacket()
-       if err != nil {
-               return nil, nil, err
-       }
-
-       var kexDHReply = new(kexDHReplyMsg)
-       if err = unmarshal(kexDHReply, packet, msgKexDHReply); err != nil {
-               return nil, nil, err
-       }
-
-       if kexDHReply.Y.Sign() == 0 || kexDHReply.Y.Cmp(group.p) >= 0 {
-               return nil, nil, errors.New("server DH parameter out of bounds")
-       }
-
-       kInt := new(big.Int).Exp(kexDHReply.Y, x, group.p)
-       h := hashFunc.New()
-       writeString(h, magics.clientVersion)
-       writeString(h, magics.serverVersion)
-       writeString(h, magics.clientKexInit)
-       writeString(h, magics.serverKexInit)
-       writeString(h, kexDHReply.HostKey)
-       writeInt(h, X)
-       writeInt(h, kexDHReply.Y)
-       K := make([]byte, intLength(kInt))
-       marshalInt(K, kInt)
-       h.Write(K)
-
-       H := h.Sum(nil)
-
-       return H, K, nil
-}
-
-// mainLoop reads incoming messages and routes channel messages
-// to their respective ClientChans.
-func (c *ClientConn) mainLoop() {
-       // TODO(dfc) signal the underlying close to all channels
-       defer c.Close()
-       for {
-               packet, err := c.readPacket()
-               if err != nil {
-                       break
-               }
-               // TODO(dfc) A note on blocking channel use.
-               // The msg, win, data and dataExt channels of a clientChan can
-               // cause this loop to block indefinately if the consumer does
-               // not service them.
-               switch packet[0] {
-               case msgChannelData:
-                       if len(packet) < 9 {
-                               // malformed data packet
-                               break
-                       }
-                       peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
-                       if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 {
-                               packet = packet[9:]
-                               c.getChan(peersId).stdout.handleData(packet[:length])
-                       }
-               case msgChannelExtendedData:
-                       if len(packet) < 13 {
-                               // malformed data packet
-                               break
-                       }
-                       peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
-                       datatype := uint32(packet[5])<<24 | uint32(packet[6])<<16 | uint32(packet[7])<<8 | uint32(packet[8])
-                       if length := int(packet[9])<<24 | int(packet[10])<<16 | int(packet[11])<<8 | int(packet[12]); length > 0 {
-                               packet = packet[13:]
-                               // RFC 4254 5.2 defines data_type_code 1 to be data destined
-                               // for stderr on interactive sessions. Other data types are
-                               // silently discarded.
-                               if datatype == 1 {
-                                       c.getChan(peersId).stderr.handleData(packet[:length])
-                               }
-                       }
-               default:
-                       switch msg := decode(packet).(type) {
-                       case *channelOpenMsg:
-                               c.getChan(msg.PeersId).msg <- msg
-                       case *channelOpenConfirmMsg:
-                               c.getChan(msg.PeersId).msg <- msg
-                       case *channelOpenFailureMsg:
-                               c.getChan(msg.PeersId).msg <- msg
-                       case *channelCloseMsg:
-                               ch := c.getChan(msg.PeersId)
-                               ch.theyClosed = true
-                               close(ch.stdin.win)
-                               ch.stdout.eof()
-                               ch.stderr.eof()
-                               close(ch.msg)
-                               if !ch.weClosed {
-                                       ch.weClosed = true
-                                       ch.sendClose()
-                               }
-                               c.chanlist.remove(msg.PeersId)
-                       case *channelEOFMsg:
-                               ch := c.getChan(msg.PeersId)
-                               ch.stdout.eof()
-                               // RFC 4254 is mute on how EOF affects dataExt messages but
-                               // it is logical to signal EOF at the same time.
-                               ch.stderr.eof()
-                       case *channelRequestSuccessMsg:
-                               c.getChan(msg.PeersId).msg <- msg
-                       case *channelRequestFailureMsg:
-                               c.getChan(msg.PeersId).msg <- msg
-                       case *channelRequestMsg:
-                               c.getChan(msg.PeersId).msg <- msg
-                       case *windowAdjustMsg:
-                               c.getChan(msg.PeersId).stdin.win <- int(msg.AdditionalBytes)
-                       case *disconnectMsg:
-                               break
-                       default:
-                               fmt.Printf("mainLoop: unhandled message %T: %v\n", msg, msg)
-                       }
-               }
-       }
-}
-
-// Dial connects to the given network address using net.Dial and
-// then initiates a SSH handshake, returning the resulting client connection.
-func Dial(network, addr string, config *ClientConfig) (*ClientConn, error) {
-       conn, err := net.Dial(network, addr)
-       if err != nil {
-               return nil, err
-       }
-       return Client(conn, config)
-}
-
-// A ClientConfig structure is used to configure a ClientConn. After one has
-// been passed to an SSH function it must not be modified.
-type ClientConfig struct {
-       // Rand provides the source of entropy for key exchange. If Rand is
-       // nil, the cryptographic random reader in package crypto/rand will
-       // be used.
-       Rand io.Reader
-
-       // The username to authenticate.
-       User string
-
-       // A slice of ClientAuth methods. Only the first instance
-       // of a particular RFC 4252 method will be used during authentication.
-       Auth []ClientAuth
-
-       // Cryptographic-related configuration.
-       Crypto CryptoConfig
-}
-
-func (c *ClientConfig) rand() io.Reader {
-       if c.Rand == nil {
-               return rand.Reader
-       }
-       return c.Rand
-}
-
-// A clientChan represents a single RFC 4254 channel that is multiplexed
-// over a single SSH connection.
-type clientChan struct {
-       packetWriter
-       id, peersId uint32
-       stdin       *chanWriter      // receives window adjustments
-       stdout      *chanReader      // receives the payload of channelData messages
-       stderr      *chanReader      // receives the payload of channelExtendedData messages
-       msg         chan interface{} // incoming messages
-       theyClosed  bool             // indicates the close msg has been received from the remote side
-       weClosed    bool             // incidates the close msg has been sent from our side
-}
-
-// newClientChan returns a partially constructed *clientChan
-// using the local id provided. To be usable clientChan.peersId
-// needs to be assigned once known.
-func newClientChan(t *transport, id uint32) *clientChan {
-       c := &clientChan{
-               packetWriter: t,
-               id:           id,
-               msg:          make(chan interface{}, 16),
-       }
-       c.stdin = &chanWriter{
-               win:        make(chan int, 16),
-               clientChan: c,
-       }
-       c.stdout = &chanReader{
-               data:       make(chan []byte, 16),
-               clientChan: c,
-       }
-       c.stderr = &chanReader{
-               data:       make(chan []byte, 16),
-               clientChan: c,
-       }
-       return c
-}
-
-// waitForChannelOpenResponse, if successful, fills out
-// the peerId and records any initial window advertisement.
-func (c *clientChan) waitForChannelOpenResponse() error {
-       switch msg := (<-c.msg).(type) {
-       case *channelOpenConfirmMsg:
-               // fixup peersId field
-               c.peersId = msg.MyId
-               c.stdin.win <- int(msg.MyWindow)
-               return nil
-       case *channelOpenFailureMsg:
-               return errors.New(safeString(msg.Message))
-       }
-       return errors.New("unexpected packet")
-}
-
-// sendEOF sends EOF to the server. RFC 4254 Section 5.3
-func (c *clientChan) sendEOF() error {
-       return c.writePacket(marshal(msgChannelEOF, channelEOFMsg{
-               PeersId: c.peersId,
-       }))
-}
-
-// sendClose signals the intent to close the channel.
-func (c *clientChan) sendClose() error {
-       return c.writePacket(marshal(msgChannelClose, channelCloseMsg{
-               PeersId: c.peersId,
-       }))
-}
-
-// Close closes the channel. This does not close the underlying connection.
-func (c *clientChan) Close() error {
-       if !c.weClosed {
-               c.weClosed = true
-               return c.sendClose()
-       }
-       return nil
-}
-
-// Thread safe channel list.
-type chanlist struct {
-       // protects concurrent access to chans
-       sync.Mutex
-       // chans are indexed by the local id of the channel, clientChan.id.
-       // The PeersId value of messages received by ClientConn.mainLoop is
-       // used to locate the right local clientChan in this slice.
-       chans []*clientChan
-}
-
-// Allocate a new ClientChan with the next avail local id.
-func (c *chanlist) newChan(t *transport) *clientChan {
-       c.Lock()
-       defer c.Unlock()
-       for i := range c.chans {
-               if c.chans[i] == nil {
-                       ch := newClientChan(t, uint32(i))
-                       c.chans[i] = ch
-                       return ch
-               }
-       }
-       i := len(c.chans)
-       ch := newClientChan(t, uint32(i))
-       c.chans = append(c.chans, ch)
-       return ch
-}
-
-func (c *chanlist) getChan(id uint32) *clientChan {
-       c.Lock()
-       defer c.Unlock()
-       return c.chans[int(id)]
-}
-
-func (c *chanlist) remove(id uint32) {
-       c.Lock()
-       defer c.Unlock()
-       c.chans[int(id)] = nil
-}
-
-// A chanWriter represents the stdin of a remote process.
-type chanWriter struct {
-       win        chan int    // receives window adjustments
-       rwin       int         // current rwin size
-       clientChan *clientChan // the channel backing this writer
-}
-
-// Write writes data to the remote process's standard input.
-func (w *chanWriter) Write(data []byte) (written int, err error) {
-       for len(data) > 0 {
-               for w.rwin < 1 {
-                       win, ok := <-w.win
-                       if !ok {
-                               return 0, io.EOF
-                       }
-                       w.rwin += win
-               }
-               n := min(len(data), w.rwin)
-               peersId := w.clientChan.peersId
-               packet := []byte{
-                       msgChannelData,
-                       byte(peersId >> 24), byte(peersId >> 16), byte(peersId >> 8), byte(peersId),
-                       byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
-               }
-               if err = w.clientChan.writePacket(append(packet, data[:n]...)); err != nil {
-                       break
-               }
-               data = data[n:]
-               w.rwin -= n
-               written += n
-       }
-       return
-}
-
-func min(a, b int) int {
-       if a < b {
-               return a
-       }
-       return b
-}
-
-func (w *chanWriter) Close() error {
-       return w.clientChan.sendEOF()
-}
-
-// A chanReader represents stdout or stderr of a remote process.
-type chanReader struct {
-       // TODO(dfc) a fixed size channel may not be the right data structure.
-       // If writes to this channel block, they will block mainLoop, making
-       // it unable to receive new messages from the remote side.
-       data       chan []byte // receives data from remote
-       dataClosed bool        // protects data from being closed twice
-       clientChan *clientChan // the channel backing this reader
-       buf        []byte
-}
-
-// eof signals to the consumer that there is no more data to be received.
-func (r *chanReader) eof() {
-       if !r.dataClosed {
-               r.dataClosed = true
-               close(r.data)
-       }
-}
-
-// handleData sends buf to the reader's consumer. If r.data is closed
-// the data will be silently discarded
-func (r *chanReader) handleData(buf []byte) {
-       if !r.dataClosed {
-               r.data <- buf
-       }
-}
-
-// Read reads data from the remote process's stdout or stderr.
-func (r *chanReader) Read(data []byte) (int, error) {
-       var ok bool
-       for {
-               if len(r.buf) > 0 {
-                       n := copy(data, r.buf)
-                       r.buf = r.buf[n:]
-                       msg := windowAdjustMsg{
-                               PeersId:         r.clientChan.peersId,
-                               AdditionalBytes: uint32(n),
-                       }
-                       return n, r.clientChan.writePacket(marshal(msgChannelWindowAdjust, msg))
-               }
-               r.buf, ok = <-r.data
-               if !ok {
-                       return 0, io.EOF
-               }
-       }
-       panic("unreachable")
-}
diff --git a/libgo/go/exp/ssh/client_auth.go b/libgo/go/exp/ssh/client_auth.go
deleted file mode 100644 (file)
index 3a7e9fb..0000000
+++ /dev/null
@@ -1,316 +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 ssh
-
-import (
-       "errors"
-       "io"
-)
-
-// authenticate authenticates with the remote server. See RFC 4252.
-func (c *ClientConn) authenticate(session []byte) error {
-       // initiate user auth session
-       if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
-               return err
-       }
-       packet, err := c.readPacket()
-       if err != nil {
-               return err
-       }
-       var serviceAccept serviceAcceptMsg
-       if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
-               return err
-       }
-       // during the authentication phase the client first attempts the "none" method
-       // then any untried methods suggested by the server.
-       tried, remain := make(map[string]bool), make(map[string]bool)
-       for auth := ClientAuth(new(noneAuth)); auth != nil; {
-               ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
-               if err != nil {
-                       return err
-               }
-               if ok {
-                       // success
-                       return nil
-               }
-               tried[auth.method()] = true
-               delete(remain, auth.method())
-               for _, meth := range methods {
-                       if tried[meth] {
-                               // if we've tried meth already, skip it.
-                               continue
-                       }
-                       remain[meth] = true
-               }
-               auth = nil
-               for _, a := range c.config.Auth {
-                       if remain[a.method()] {
-                               auth = a
-                               break
-                       }
-               }
-       }
-       return errors.New("ssh: unable to authenticate, no supported methods remain")
-}
-
-// A ClientAuth represents an instance of an RFC 4252 authentication method.
-type ClientAuth interface {
-       // auth authenticates user over transport t.
-       // Returns true if authentication is successful.
-       // If authentication is not successful, a []string of alternative
-       // method names is returned.
-       auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)
-
-       // method returns the RFC 4252 method name.
-       method() string
-}
-
-// "none" authentication, RFC 4252 section 5.2.
-type noneAuth int
-
-func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
-       if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
-               User:    user,
-               Service: serviceSSH,
-               Method:  "none",
-       })); err != nil {
-               return false, nil, err
-       }
-
-       return handleAuthResponse(t)
-}
-
-func (n *noneAuth) method() string {
-       return "none"
-}
-
-// "password" authentication, RFC 4252 Section 8.
-type passwordAuth struct {
-       ClientPassword
-}
-
-func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
-       type passwordAuthMsg struct {
-               User     string
-               Service  string
-               Method   string
-               Reply    bool
-               Password string
-       }
-
-       pw, err := p.Password(user)
-       if err != nil {
-               return false, nil, err
-       }
-
-       if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
-               User:     user,
-               Service:  serviceSSH,
-               Method:   "password",
-               Reply:    false,
-               Password: pw,
-       })); err != nil {
-               return false, nil, err
-       }
-
-       return handleAuthResponse(t)
-}
-
-func (p *passwordAuth) method() string {
-       return "password"
-}
-
-// A ClientPassword implements access to a client's passwords.
-type ClientPassword interface {
-       // Password returns the password to use for user.
-       Password(user string) (password string, err error)
-}
-
-// ClientAuthPassword returns a ClientAuth using password authentication.
-func ClientAuthPassword(impl ClientPassword) ClientAuth {
-       return &passwordAuth{impl}
-}
-
-// ClientKeyring implements access to a client key ring.
-type ClientKeyring interface {
-       // Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if
-       // no key exists at i.
-       Key(i int) (key interface{}, err error)
-
-       // Sign returns a signature of the given data using the i'th key
-       // and the supplied random source.
-       Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
-}
-
-// "publickey" authentication, RFC 4252 Section 7.
-type publickeyAuth struct {
-       ClientKeyring
-}
-
-type publickeyAuthMsg struct {
-       User    string
-       Service string
-       Method  string
-       // HasSig indicates to the reciver packet that the auth request is signed and
-       // should be used for authentication of the request.
-       HasSig   bool
-       Algoname string
-       Pubkey   string
-       // Sig is defined as []byte so marshal will exclude it during validateKey
-       Sig []byte `ssh:"rest"`
-}
-
-func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
-
-       // Authentication is performed in two stages. The first stage sends an
-       // enquiry to test if each key is acceptable to the remote. The second
-       // stage attempts to authenticate with the valid keys obtained in the
-       // first stage.
-
-       var index int
-       // a map of public keys to their index in the keyring
-       validKeys := make(map[int]interface{})
-       for {
-               key, err := p.Key(index)
-               if err != nil {
-                       return false, nil, err
-               }
-               if key == nil {
-                       // no more keys in the keyring
-                       break
-               }
-
-               if ok, err := p.validateKey(key, user, t); ok {
-                       validKeys[index] = key
-               } else {
-                       if err != nil {
-                               return false, nil, err
-                       }
-               }
-               index++
-       }
-
-       // methods that may continue if this auth is not successful.
-       var methods []string
-       for i, key := range validKeys {
-               pubkey := serializePublickey(key)
-               algoname := algoName(key)
-               sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
-                       User:    user,
-                       Service: serviceSSH,
-                       Method:  p.method(),
-               }, []byte(algoname), pubkey))
-               if err != nil {
-                       return false, nil, err
-               }
-               // manually wrap the serialized signature in a string
-               s := serializeSignature(algoname, sign)
-               sig := make([]byte, stringLength(s))
-               marshalString(sig, s)
-               msg := publickeyAuthMsg{
-                       User:     user,
-                       Service:  serviceSSH,
-                       Method:   p.method(),
-                       HasSig:   true,
-                       Algoname: algoname,
-                       Pubkey:   string(pubkey),
-                       Sig:      sig,
-               }
-               p := marshal(msgUserAuthRequest, msg)
-               if err := t.writePacket(p); err != nil {
-                       return false, nil, err
-               }
-               success, methods, err := handleAuthResponse(t)
-               if err != nil {
-                       return false, nil, err
-               }
-               if success {
-                       return success, methods, err
-               }
-       }
-       return false, methods, nil
-}
-
-// validateKey validates the key provided it is acceptable to the server.
-func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) {
-       pubkey := serializePublickey(key)
-       algoname := algoName(key)
-       msg := publickeyAuthMsg{
-               User:     user,
-               Service:  serviceSSH,
-               Method:   p.method(),
-               HasSig:   false,
-               Algoname: algoname,
-               Pubkey:   string(pubkey),
-       }
-       if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
-               return false, err
-       }
-
-       return p.confirmKeyAck(key, t)
-}
-
-func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) {
-       pubkey := serializePublickey(key)
-       algoname := algoName(key)
-
-       for {
-               packet, err := t.readPacket()
-               if err != nil {
-                       return false, err
-               }
-               switch packet[0] {
-               case msgUserAuthBanner:
-                       // TODO(gpaul): add callback to present the banner to the user
-               case msgUserAuthPubKeyOk:
-                       msg := decode(packet).(*userAuthPubKeyOkMsg)
-                       if msg.Algo != algoname || msg.PubKey != string(pubkey) {
-                               return false, nil
-                       }
-                       return true, nil
-               case msgUserAuthFailure:
-                       return false, nil
-               default:
-                       return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
-               }
-       }
-       panic("unreachable")
-}
-
-func (p *publickeyAuth) method() string {
-       return "publickey"
-}
-
-// ClientAuthKeyring returns a ClientAuth using public key authentication.
-func ClientAuthKeyring(impl ClientKeyring) ClientAuth {
-       return &publickeyAuth{impl}
-}
-
-// handleAuthResponse returns whether the preceding authentication request succeeded
-// along with a list of remaining authentication methods to try next and
-// an error if an unexpected response was received.
-func handleAuthResponse(t *transport) (bool, []string, error) {
-       for {
-               packet, err := t.readPacket()
-               if err != nil {
-                       return false, nil, err
-               }
-
-               switch packet[0] {
-               case msgUserAuthBanner:
-                       // TODO: add callback to present the banner to the user
-               case msgUserAuthFailure:
-                       msg := decode(packet).(*userAuthFailureMsg)
-                       return false, msg.Methods, nil
-               case msgUserAuthSuccess:
-                       return true, nil, nil
-               case msgDisconnect:
-                       return false, nil, io.EOF
-               default:
-                       return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
-               }
-       }
-       panic("unreachable")
-}
diff --git a/libgo/go/exp/ssh/client_auth_test.go b/libgo/go/exp/ssh/client_auth_test.go
deleted file mode 100644 (file)
index c41a93b..0000000
+++ /dev/null
@@ -1,257 +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 ssh
-
-import (
-       "bytes"
-       "crypto"
-       "crypto/dsa"
-       "crypto/rsa"
-       _ "crypto/sha1"
-       "crypto/x509"
-       "encoding/pem"
-       "errors"
-       "io"
-       "io/ioutil"
-       "math/big"
-       "testing"
-)
-
-// private key for mock server
-const testServerPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU
-70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx
-9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF
-tupdMODN064vd3gyMKTwrlQ8tZM6aYuyOPsutLlUY7M5x5FwMDYvnPDSeyT/Iw0z
-s3B+NCyqeeMd2T7YzQFnRATj0M7rM5LoSs7DVqVriOEABssFyLj31PboaoLhOKgc
-qoM9khkNzr7FHVvi+DhYM2jD0DwvqZLN6NmnLwIDAQABAoIBAQCGVj+kuSFOV1lT
-+IclQYA6bM6uY5mroqcSBNegVxCNhWU03BxlW//BE9tA/+kq53vWylMeN9mpGZea
-riEMIh25KFGWXqXlOOioH8bkMsqA8S7sBmc7jljyv+0toQ9vCCtJ+sueNPhxQQxH
-D2YvUjfzBQ04I9+wn30BByDJ1QA/FoPsunxIOUCcRBE/7jxuLYcpR+JvEF68yYIh
-atXRld4W4in7T65YDR8jK1Uj9XAcNeDYNpT/M6oFLx1aPIlkG86aCWRO19S1jLPT
-b1ZAKHHxPMCVkSYW0RqvIgLXQOR62D0Zne6/2wtzJkk5UCjkSQ2z7ZzJpMkWgDgN
-ifCULFPBAoGBAPoMZ5q1w+zB+knXUD33n1J+niN6TZHJulpf2w5zsW+m2K6Zn62M
-MXndXlVAHtk6p02q9kxHdgov34Uo8VpuNjbS1+abGFTI8NZgFo+bsDxJdItemwC4
-KJ7L1iz39hRN/ZylMRLz5uTYRGddCkeIHhiG2h7zohH/MaYzUacXEEy3AoGBANz8
-e/msleB+iXC0cXKwds26N4hyMdAFE5qAqJXvV3S2W8JZnmU+sS7vPAWMYPlERPk1
-D8Q2eXqdPIkAWBhrx4RxD7rNc5qFNcQWEhCIxC9fccluH1y5g2M+4jpMX2CT8Uv+
-3z+NoJ5uDTXZTnLCfoZzgZ4nCZVZ+6iU5U1+YXFJAoGBANLPpIV920n/nJmmquMj
-orI1R/QXR9Cy56cMC65agezlGOfTYxk5Cfl5Ve+/2IJCfgzwJyjWUsFx7RviEeGw
-64o7JoUom1HX+5xxdHPsyZ96OoTJ5RqtKKoApnhRMamau0fWydH1yeOEJd+TRHhc
-XStGfhz8QNa1dVFvENczja1vAoGABGWhsd4VPVpHMc7lUvrf4kgKQtTC2PjA4xoc
-QJ96hf/642sVE76jl+N6tkGMzGjnVm4P2j+bOy1VvwQavKGoXqJBRd5Apppv727g
-/SM7hBXKFc/zH80xKBBgP/i1DR7kdjakCoeu4ngeGywvu2jTS6mQsqzkK+yWbUxJ
-I7mYBsECgYB/KNXlTEpXtz/kwWCHFSYA8U74l7zZbVD8ul0e56JDK+lLcJ0tJffk
-gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl
-NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw==
------END RSA PRIVATE KEY-----`
-
-const testClientPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
-MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld
-r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
-tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
-nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
-2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
-y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
-rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
------END RSA PRIVATE KEY-----`
-
-// keychain implements the ClientPublickey interface
-type keychain struct {
-       keys []interface{}
-}
-
-func (k *keychain) Key(i int) (interface{}, error) {
-       if i < 0 || i >= len(k.keys) {
-               return nil, nil
-       }
-       switch key := k.keys[i].(type) {
-       case *rsa.PrivateKey:
-               return key.PublicKey, nil
-       case *dsa.PrivateKey:
-               return key.PublicKey, nil
-       }
-       panic("unknown key type")
-}
-
-func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
-       hashFunc := crypto.SHA1
-       h := hashFunc.New()
-       h.Write(data)
-       digest := h.Sum(nil)
-       switch key := k.keys[i].(type) {
-       case *rsa.PrivateKey:
-               return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
-       }
-       return nil, errors.New("unknown key type")
-}
-
-func (k *keychain) loadPEM(file string) error {
-       buf, err := ioutil.ReadFile(file)
-       if err != nil {
-               return err
-       }
-       block, _ := pem.Decode(buf)
-       if block == nil {
-               return errors.New("ssh: no key found")
-       }
-       r, err := x509.ParsePKCS1PrivateKey(block.Bytes)
-       if err != nil {
-               return err
-       }
-       k.keys = append(k.keys, r)
-       return nil
-}
-
-// password implements the ClientPassword interface
-type password string
-
-func (p password) Password(user string) (string, error) {
-       return string(p), nil
-}
-
-// reused internally by tests
-var (
-       rsakey         *rsa.PrivateKey
-       dsakey         *dsa.PrivateKey
-       clientKeychain = new(keychain)
-       clientPassword = password("tiger")
-       serverConfig   = &ServerConfig{
-               PasswordCallback: func(user, pass string) bool {
-                       return user == "testuser" && pass == string(clientPassword)
-               },
-               PublicKeyCallback: func(user, algo string, pubkey []byte) bool {
-                       key := clientKeychain.keys[0].(*rsa.PrivateKey).PublicKey
-                       expected := []byte(serializePublickey(key))
-                       algoname := algoName(key)
-                       return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
-               },
-       }
-)
-
-func init() {
-       if err := serverConfig.SetRSAPrivateKey([]byte(testServerPrivateKey)); err != nil {
-               panic("unable to set private key: " + err.Error())
-       }
-
-       block, _ := pem.Decode([]byte(testClientPrivateKey))
-       rsakey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
-
-       clientKeychain.keys = append(clientKeychain.keys, rsakey)
-       dsakey = new(dsa.PrivateKey)
-       // taken from crypto/dsa/dsa_test.go
-       dsakey.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
-       dsakey.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
-       dsakey.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
-       dsakey.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
-       dsakey.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
-}
-
-// newMockAuthServer creates a new Server bound to 
-// the loopback interface. The server exits after 
-// processing one handshake.
-func newMockAuthServer(t *testing.T) string {
-       l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
-       if err != nil {
-               t.Fatalf("unable to newMockAuthServer: %s", err)
-       }
-       go func() {
-               defer l.Close()
-               c, err := l.Accept()
-               defer c.Close()
-               if err != nil {
-                       t.Errorf("Unable to accept incoming connection: %v", err)
-                       return
-               }
-               if err := c.Handshake(); err != nil {
-                       // not Errorf because this is expected to
-                       // fail for some tests.
-                       t.Logf("Handshaking error: %v", err)
-                       return
-               }
-       }()
-       return l.Addr().String()
-}
-
-func TestClientAuthPublickey(t *testing.T) {
-       config := &ClientConfig{
-               User: "testuser",
-               Auth: []ClientAuth{
-                       ClientAuthKeyring(clientKeychain),
-               },
-       }
-       c, err := Dial("tcp", newMockAuthServer(t), config)
-       if err != nil {
-               t.Fatalf("unable to dial remote side: %s", err)
-       }
-       c.Close()
-}
-
-func TestClientAuthPassword(t *testing.T) {
-       config := &ClientConfig{
-               User: "testuser",
-               Auth: []ClientAuth{
-                       ClientAuthPassword(clientPassword),
-               },
-       }
-
-       c, err := Dial("tcp", newMockAuthServer(t), config)
-       if err != nil {
-               t.Fatalf("unable to dial remote side: %s", err)
-       }
-       c.Close()
-}
-
-func TestClientAuthWrongPassword(t *testing.T) {
-       wrongPw := password("wrong")
-       config := &ClientConfig{
-               User: "testuser",
-               Auth: []ClientAuth{
-                       ClientAuthPassword(wrongPw),
-                       ClientAuthKeyring(clientKeychain),
-               },
-       }
-
-       c, err := Dial("tcp", newMockAuthServer(t), config)
-       if err != nil {
-               t.Fatalf("unable to dial remote side: %s", err)
-       }
-       c.Close()
-}
-
-// the mock server will only authenticate ssh-rsa keys
-func TestClientAuthInvalidPublickey(t *testing.T) {
-       kc := new(keychain)
-       kc.keys = append(kc.keys, dsakey)
-       config := &ClientConfig{
-               User: "testuser",
-               Auth: []ClientAuth{
-                       ClientAuthKeyring(kc),
-               },
-       }
-
-       c, err := Dial("tcp", newMockAuthServer(t), config)
-       if err == nil {
-               c.Close()
-               t.Fatalf("dsa private key should not have authenticated with rsa public key")
-       }
-}
-
-// the client should authenticate with the second key
-func TestClientAuthRSAandDSA(t *testing.T) {
-       kc := new(keychain)
-       kc.keys = append(kc.keys, dsakey, rsakey)
-       config := &ClientConfig{
-               User: "testuser",
-               Auth: []ClientAuth{
-                       ClientAuthKeyring(kc),
-               },
-       }
-       c, err := Dial("tcp", newMockAuthServer(t), config)
-       if err != nil {
-               t.Fatalf("client could not authenticate with rsa key: %v", err)
-       }
-       c.Close()
-}
diff --git a/libgo/go/exp/ssh/client_func_test.go b/libgo/go/exp/ssh/client_func_test.go
deleted file mode 100644 (file)
index b4bdba9..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ssh
-
-// ClientConn functional tests.
-// These tests require a running ssh server listening on port 22
-// on the local host. Functional tests will be skipped unless
-// -ssh.user and -ssh.pass must be passed to gotest.
-
-import (
-       "flag"
-       "testing"
-)
-
-var (
-       sshuser    = flag.String("ssh.user", "", "ssh username")
-       sshpass    = flag.String("ssh.pass", "", "ssh password")
-       sshprivkey = flag.String("ssh.privkey", "", "ssh privkey file")
-)
-
-func TestFuncPasswordAuth(t *testing.T) {
-       if *sshuser == "" {
-               t.Log("ssh.user not defined, skipping test")
-               return
-       }
-       config := &ClientConfig{
-               User: *sshuser,
-               Auth: []ClientAuth{
-                       ClientAuthPassword(password(*sshpass)),
-               },
-       }
-       conn, err := Dial("tcp", "localhost:22", config)
-       if err != nil {
-               t.Fatalf("Unable to connect: %s", err)
-       }
-       defer conn.Close()
-}
-
-func TestFuncPublickeyAuth(t *testing.T) {
-       if *sshuser == "" {
-               t.Log("ssh.user not defined, skipping test")
-               return
-       }
-       kc := new(keychain)
-       if err := kc.loadPEM(*sshprivkey); err != nil {
-               t.Fatalf("unable to load private key: %s", err)
-       }
-       config := &ClientConfig{
-               User: *sshuser,
-               Auth: []ClientAuth{
-                       ClientAuthKeyring(kc),
-               },
-       }
-       conn, err := Dial("tcp", "localhost:22", config)
-       if err != nil {
-               t.Fatalf("unable to connect: %s", err)
-       }
-       defer conn.Close()
-}
diff --git a/libgo/go/exp/ssh/common.go b/libgo/go/exp/ssh/common.go
deleted file mode 100644 (file)
index 6844fb8..0000000
+++ /dev/null
@@ -1,239 +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 ssh
-
-import (
-       "crypto/dsa"
-       "crypto/rsa"
-       "math/big"
-       "strconv"
-       "sync"
-)
-
-// These are string constants in the SSH protocol.
-const (
-       kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
-       hostAlgoRSA     = "ssh-rsa"
-       macSHA196       = "hmac-sha1-96"
-       compressionNone = "none"
-       serviceUserAuth = "ssh-userauth"
-       serviceSSH      = "ssh-connection"
-)
-
-var supportedKexAlgos = []string{kexAlgoDH14SHA1}
-var supportedHostKeyAlgos = []string{hostAlgoRSA}
-var supportedMACs = []string{macSHA196}
-var supportedCompressions = []string{compressionNone}
-
-// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
-type dhGroup struct {
-       g, p *big.Int
-}
-
-// dhGroup14 is the group called diffie-hellman-group14-sha1 in RFC 4253 and
-// Oakley Group 14 in RFC 3526.
-var dhGroup14 *dhGroup
-
-var dhGroup14Once sync.Once
-
-func initDHGroup14() {
-       p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
-
-       dhGroup14 = &dhGroup{
-               g: new(big.Int).SetInt64(2),
-               p: p,
-       }
-}
-
-// UnexpectedMessageError results when the SSH message that we received didn't
-// match what we wanted.
-type UnexpectedMessageError struct {
-       expected, got uint8
-}
-
-func (u UnexpectedMessageError) Error() string {
-       return "ssh: unexpected message type " + strconv.Itoa(int(u.got)) + " (expected " + strconv.Itoa(int(u.expected)) + ")"
-}
-
-// ParseError results from a malformed SSH message.
-type ParseError struct {
-       msgType uint8
-}
-
-func (p ParseError) Error() string {
-       return "ssh: parse error in message type " + strconv.Itoa(int(p.msgType))
-}
-
-type handshakeMagics struct {
-       clientVersion, serverVersion []byte
-       clientKexInit, serverKexInit []byte
-}
-
-func findCommonAlgorithm(clientAlgos []string, serverAlgos []string) (commonAlgo string, ok bool) {
-       for _, clientAlgo := range clientAlgos {
-               for _, serverAlgo := range serverAlgos {
-                       if clientAlgo == serverAlgo {
-                               return clientAlgo, true
-                       }
-               }
-       }
-
-       return
-}
-
-func findAgreedAlgorithms(transport *transport, clientKexInit, serverKexInit *kexInitMsg) (kexAlgo, hostKeyAlgo string, ok bool) {
-       kexAlgo, ok = findCommonAlgorithm(clientKexInit.KexAlgos, serverKexInit.KexAlgos)
-       if !ok {
-               return
-       }
-
-       hostKeyAlgo, ok = findCommonAlgorithm(clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
-       if !ok {
-               return
-       }
-
-       transport.writer.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
-       if !ok {
-               return
-       }
-
-       transport.reader.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
-       if !ok {
-               return
-       }
-
-       transport.writer.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
-       if !ok {
-               return
-       }
-
-       transport.reader.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
-       if !ok {
-               return
-       }
-
-       transport.writer.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
-       if !ok {
-               return
-       }
-
-       transport.reader.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
-       if !ok {
-               return
-       }
-
-       ok = true
-       return
-}
-
-// Cryptographic configuration common to both ServerConfig and ClientConfig.
-type CryptoConfig struct {
-       // The allowed cipher algorithms. If unspecified then DefaultCipherOrder is
-       // used.
-       Ciphers []string
-}
-
-func (c *CryptoConfig) ciphers() []string {
-       if c.Ciphers == nil {
-               return DefaultCipherOrder
-       }
-       return c.Ciphers
-}
-
-// serialize a signed slice according to RFC 4254 6.6.
-func serializeSignature(algoname string, sig []byte) []byte {
-       length := stringLength([]byte(algoname))
-       length += stringLength(sig)
-
-       ret := make([]byte, length)
-       r := marshalString(ret, []byte(algoname))
-       r = marshalString(r, sig)
-
-       return ret
-}
-
-// serialize an rsa.PublicKey or dsa.PublicKey according to RFC 4253 6.6.
-func serializePublickey(key interface{}) []byte {
-       algoname := algoName(key)
-       switch key := key.(type) {
-       case rsa.PublicKey:
-               e := new(big.Int).SetInt64(int64(key.E))
-               length := stringLength([]byte(algoname))
-               length += intLength(e)
-               length += intLength(key.N)
-               ret := make([]byte, length)
-               r := marshalString(ret, []byte(algoname))
-               r = marshalInt(r, e)
-               marshalInt(r, key.N)
-               return ret
-       case dsa.PublicKey:
-               length := stringLength([]byte(algoname))
-               length += intLength(key.P)
-               length += intLength(key.Q)
-               length += intLength(key.G)
-               length += intLength(key.Y)
-               ret := make([]byte, length)
-               r := marshalString(ret, []byte(algoname))
-               r = marshalInt(r, key.P)
-               r = marshalInt(r, key.Q)
-               r = marshalInt(r, key.G)
-               marshalInt(r, key.Y)
-               return ret
-       }
-       panic("unexpected key type")
-}
-
-func algoName(key interface{}) string {
-       switch key.(type) {
-       case rsa.PublicKey:
-               return "ssh-rsa"
-       case dsa.PublicKey:
-               return "ssh-dss"
-       }
-       panic("unexpected key type")
-}
-
-// buildDataSignedForAuth returns the data that is signed in order to prove
-// posession of a private key. See RFC 4252, section 7.
-func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
-       user := []byte(req.User)
-       service := []byte(req.Service)
-       method := []byte(req.Method)
-
-       length := stringLength(sessionId)
-       length += 1
-       length += stringLength(user)
-       length += stringLength(service)
-       length += stringLength(method)
-       length += 1
-       length += stringLength(algo)
-       length += stringLength(pubKey)
-
-       ret := make([]byte, length)
-       r := marshalString(ret, sessionId)
-       r[0] = msgUserAuthRequest
-       r = r[1:]
-       r = marshalString(r, user)
-       r = marshalString(r, service)
-       r = marshalString(r, method)
-       r[0] = 1
-       r = r[1:]
-       r = marshalString(r, algo)
-       r = marshalString(r, pubKey)
-       return ret
-}
-
-// safeString sanitises s according to RFC 4251, section 9.2. 
-// All control characters except tab, carriage return and newline are
-// replaced by 0x20.
-func safeString(s string) string {
-       out := []byte(s)
-       for i, c := range out {
-               if c < 0x20 && c != 0xd && c != 0xa && c != 0x9 {
-                       out[i] = 0x20
-               }
-       }
-       return string(out)
-}
diff --git a/libgo/go/exp/ssh/common_test.go b/libgo/go/exp/ssh/common_test.go
deleted file mode 100644 (file)
index 058fb04..0000000
+++ /dev/null
@@ -1,26 +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 ssh
-
-import (
-       "testing"
-)
-
-func TestSafeString(t *testing.T) {
-       strings := map[string]string{
-               "\x20\x0d\x0a":  "\x20\x0d\x0a",
-               "flibble":       "flibble",
-               "new\x20line":   "new\x20line",
-               "123456\x07789": "123456 789",
-               "\t\t\x10\r\n":  "\t\t \r\n",
-       }
-
-       for s, expected := range strings {
-               actual := safeString(s)
-               if expected != actual {
-                       t.Errorf("expected: %v, actual: %v", []byte(expected), []byte(actual))
-               }
-       }
-}
diff --git a/libgo/go/exp/ssh/doc.go b/libgo/go/exp/ssh/doc.go
deleted file mode 100644 (file)
index e7deb5e..0000000
+++ /dev/null
@@ -1,127 +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 ssh implements an SSH client and server.
-
-SSH is a transport security protocol, an authentication protocol and a
-family of application protocols. The most typical application level
-protocol is a remote shell and this is specifically implemented.  However,
-the multiplexed nature of SSH is exposed to users that wish to support
-others.
-
-An SSH server is represented by a ServerConfig, which holds certificate
-details and handles authentication of ServerConns.
-
-       config := new(ssh.ServerConfig)
-       config.PubKeyCallback = pubKeyAuth
-       config.PasswordCallback = passwordAuth
-
-       pemBytes, err := ioutil.ReadFile("id_rsa")
-       if err != nil {
-               panic("Failed to load private key")
-       }
-       err = config.SetRSAPrivateKey(pemBytes)
-       if err != nil {
-               panic("Failed to parse private key")
-       }
-
-Once a ServerConfig has been configured, connections can be accepted.
-
-       listener := Listen("tcp", "0.0.0.0:2022", config)
-       sConn, err := listener.Accept()
-       if err != nil {
-               panic("failed to accept incoming connection")
-       }
-       if err := sConn.Handshake(conn); err != nil {
-               panic("failed to handshake")
-       }
-
-An SSH connection multiplexes several channels, which must be accepted themselves:
-
-       for {
-               channel, err := sConn.Accept()
-               if err != nil {
-                       panic("error from Accept")
-               }
-
-               ...
-       }
-
-Accept reads from the connection, demultiplexes packets to their corresponding
-channels and returns when a new channel request is seen. Some goroutine must
-always be calling Accept; otherwise no messages will be forwarded to the
-channels.
-
-Channels have a type, depending on the application level protocol intended. In
-the case of a shell, the type is "session" and ServerShell may be used to
-present a simple terminal interface.
-
-       if channel.ChannelType() != "session" {
-               channel.Reject(UnknownChannelType, "unknown channel type")
-               return
-       }
-       channel.Accept()
-
-       term := terminal.NewTerminal(channel, "> ")
-       serverTerm := &ssh.ServerTerminal{
-               Term: term,
-               Channel: channel,
-       }
-       go func() {
-               defer channel.Close()
-               for {
-                       line, err := serverTerm.ReadLine()
-                       if err != nil {
-                               break
-                       }
-                       println(line)
-               }
-               return
-       }()
-
-To authenticate with the remote server you must pass at least one implementation of 
-ClientAuth via the Auth field in ClientConfig.
-
-       // password implements the ClientPassword interface
-       type password string
-
-       func (p password) Password(user string) (string, error) {
-               return string(p), nil
-       }
-
-       config := &ssh.ClientConfig {
-               User: "username",
-               Auth: []ClientAuth {
-                       // ClientAuthPassword wraps a ClientPassword implementation
-                       // in a type that implements ClientAuth.
-                       ClientAuthPassword(password("yourpassword")),
-               }
-       }
-
-An SSH client is represented with a ClientConn. Currently only the "password"
-authentication method is supported.
-
-       config := &ClientConfig{
-               User: "username",
-               Auth: []ClientAuth{ ... },
-       }
-       client, err := Dial("yourserver.com:22", config)
-
-Each ClientConn can support multiple interactive sessions, represented by a Session.
-
-       session, err := client.NewSession()
-
-Once a Session is created, you can execute a single command on the remote side
-using the Exec method.
-
-       b := bytes.NewBuffer()
-       session.Stdin = b
-       if err := session.Run("/usr/bin/whoami"); err != nil {
-               panic("Failed to exec: " + err.String())
-       }
-       fmt.Println(bytes.String())
-       session.Close()
-*/
-package ssh
diff --git a/libgo/go/exp/ssh/messages.go b/libgo/go/exp/ssh/messages.go
deleted file mode 100644 (file)
index 34ad131..0000000
+++ /dev/null
@@ -1,640 +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 ssh
-
-import (
-       "bytes"
-       "io"
-       "math/big"
-       "reflect"
-)
-
-// These are SSH message type numbers. They are scattered around several
-// documents but many were taken from
-// http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
-const (
-       msgDisconnect     = 1
-       msgIgnore         = 2
-       msgUnimplemented  = 3
-       msgDebug          = 4
-       msgServiceRequest = 5
-       msgServiceAccept  = 6
-
-       msgKexInit = 20
-       msgNewKeys = 21
-
-       msgKexDHInit  = 30
-       msgKexDHReply = 31
-
-       msgUserAuthRequest  = 50
-       msgUserAuthFailure  = 51
-       msgUserAuthSuccess  = 52
-       msgUserAuthBanner   = 53
-       msgUserAuthPubKeyOk = 60
-
-       msgGlobalRequest  = 80
-       msgRequestSuccess = 81
-       msgRequestFailure = 82
-
-       msgChannelOpen         = 90
-       msgChannelOpenConfirm  = 91
-       msgChannelOpenFailure  = 92
-       msgChannelWindowAdjust = 93
-       msgChannelData         = 94
-       msgChannelExtendedData = 95
-       msgChannelEOF          = 96
-       msgChannelClose        = 97
-       msgChannelRequest      = 98
-       msgChannelSuccess      = 99
-       msgChannelFailure      = 100
-)
-
-// SSH messages:
-//
-// These structures mirror the wire format of the corresponding SSH messages.
-// They are marshaled using reflection with the marshal and unmarshal functions
-// in this file. The only wrinkle is that a final member of type []byte with a
-// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
-
-// See RFC 4253, section 11.1.
-type disconnectMsg struct {
-       Reason   uint32
-       Message  string
-       Language string
-}
-
-// See RFC 4253, section 7.1.
-type kexInitMsg struct {
-       Cookie                  [16]byte
-       KexAlgos                []string
-       ServerHostKeyAlgos      []string
-       CiphersClientServer     []string
-       CiphersServerClient     []string
-       MACsClientServer        []string
-       MACsServerClient        []string
-       CompressionClientServer []string
-       CompressionServerClient []string
-       LanguagesClientServer   []string
-       LanguagesServerClient   []string
-       FirstKexFollows         bool
-       Reserved                uint32
-}
-
-// See RFC 4253, section 8.
-type kexDHInitMsg struct {
-       X *big.Int
-}
-
-type kexDHReplyMsg struct {
-       HostKey   []byte
-       Y         *big.Int
-       Signature []byte
-}
-
-// See RFC 4253, section 10.
-type serviceRequestMsg struct {
-       Service string
-}
-
-// See RFC 4253, section 10.
-type serviceAcceptMsg struct {
-       Service string
-}
-
-// See RFC 4252, section 5.
-type userAuthRequestMsg struct {
-       User    string
-       Service string
-       Method  string
-       Payload []byte `ssh:"rest"`
-}
-
-// See RFC 4252, section 5.1
-type userAuthFailureMsg struct {
-       Methods        []string
-       PartialSuccess bool
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenMsg struct {
-       ChanType         string
-       PeersId          uint32
-       PeersWindow      uint32
-       MaxPacketSize    uint32
-       TypeSpecificData []byte `ssh:"rest"`
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenConfirmMsg struct {
-       PeersId          uint32
-       MyId             uint32
-       MyWindow         uint32
-       MaxPacketSize    uint32
-       TypeSpecificData []byte `ssh:"rest"`
-}
-
-// See RFC 4254, section 5.1.
-type channelOpenFailureMsg struct {
-       PeersId  uint32
-       Reason   uint32
-       Message  string
-       Language string
-}
-
-type channelRequestMsg struct {
-       PeersId             uint32
-       Request             string
-       WantReply           bool
-       RequestSpecificData []byte `ssh:"rest"`
-}
-
-// See RFC 4254, section 5.4.
-type channelRequestSuccessMsg struct {
-       PeersId uint32
-}
-
-// See RFC 4254, section 5.4.
-type channelRequestFailureMsg struct {
-       PeersId uint32
-}
-
-// See RFC 4254, section 5.3
-type channelCloseMsg struct {
-       PeersId uint32
-}
-
-// See RFC 4254, section 5.3
-type channelEOFMsg struct {
-       PeersId uint32
-}
-
-// See RFC 4254, section 4
-type globalRequestMsg struct {
-       Type      string
-       WantReply bool
-}
-
-// See RFC 4254, section 5.2
-type windowAdjustMsg struct {
-       PeersId         uint32
-       AdditionalBytes uint32
-}
-
-// See RFC 4252, section 7
-type userAuthPubKeyOkMsg struct {
-       Algo   string
-       PubKey string
-}
-
-// unmarshal parses the SSH wire data in packet into out using reflection.
-// expectedType is the expected SSH message type. It either returns nil on
-// success, or a ParseError or UnexpectedMessageError on error.
-func unmarshal(out interface{}, packet []byte, expectedType uint8) error {
-       if len(packet) == 0 {
-               return ParseError{expectedType}
-       }
-       if packet[0] != expectedType {
-               return UnexpectedMessageError{expectedType, packet[0]}
-       }
-       packet = packet[1:]
-
-       v := reflect.ValueOf(out).Elem()
-       structType := v.Type()
-       var ok bool
-       for i := 0; i < v.NumField(); i++ {
-               field := v.Field(i)
-               t := field.Type()
-               switch t.Kind() {
-               case reflect.Bool:
-                       if len(packet) < 1 {
-                               return ParseError{expectedType}
-                       }
-                       field.SetBool(packet[0] != 0)
-                       packet = packet[1:]
-               case reflect.Array:
-                       if t.Elem().Kind() != reflect.Uint8 {
-                               panic("array of non-uint8")
-                       }
-                       if len(packet) < t.Len() {
-                               return ParseError{expectedType}
-                       }
-                       for j := 0; j < t.Len(); j++ {
-                               field.Index(j).Set(reflect.ValueOf(packet[j]))
-                       }
-                       packet = packet[t.Len():]
-               case reflect.Uint32:
-                       var u32 uint32
-                       if u32, packet, ok = parseUint32(packet); !ok {
-                               return ParseError{expectedType}
-                       }
-                       field.SetUint(uint64(u32))
-               case reflect.String:
-                       var s []byte
-                       if s, packet, ok = parseString(packet); !ok {
-                               return ParseError{expectedType}
-                       }
-                       field.SetString(string(s))
-               case reflect.Slice:
-                       switch t.Elem().Kind() {
-                       case reflect.Uint8:
-                               if structType.Field(i).Tag.Get("ssh") == "rest" {
-                                       field.Set(reflect.ValueOf(packet))
-                                       packet = nil
-                               } else {
-                                       var s []byte
-                                       if s, packet, ok = parseString(packet); !ok {
-                                               return ParseError{expectedType}
-                                       }
-                                       field.Set(reflect.ValueOf(s))
-                               }
-                       case reflect.String:
-                               var nl []string
-                               if nl, packet, ok = parseNameList(packet); !ok {
-                                       return ParseError{expectedType}
-                               }
-                               field.Set(reflect.ValueOf(nl))
-                       default:
-                               panic("slice of unknown type")
-                       }
-               case reflect.Ptr:
-                       if t == bigIntType {
-                               var n *big.Int
-                               if n, packet, ok = parseInt(packet); !ok {
-                                       return ParseError{expectedType}
-                               }
-                               field.Set(reflect.ValueOf(n))
-                       } else {
-                               panic("pointer to unknown type")
-                       }
-               default:
-                       panic("unknown type")
-               }
-       }
-
-       if len(packet) != 0 {
-               return ParseError{expectedType}
-       }
-
-       return nil
-}
-
-// marshal serializes the message in msg, using the given message type.
-func marshal(msgType uint8, msg interface{}) []byte {
-       var out []byte
-       out = append(out, msgType)
-
-       v := reflect.ValueOf(msg)
-       structType := v.Type()
-       for i := 0; i < v.NumField(); i++ {
-               field := v.Field(i)
-               t := field.Type()
-               switch t.Kind() {
-               case reflect.Bool:
-                       var v uint8
-                       if field.Bool() {
-                               v = 1
-                       }
-                       out = append(out, v)
-               case reflect.Array:
-                       if t.Elem().Kind() != reflect.Uint8 {
-                               panic("array of non-uint8")
-                       }
-                       for j := 0; j < t.Len(); j++ {
-                               out = append(out, byte(field.Index(j).Uint()))
-                       }
-               case reflect.Uint32:
-                       u32 := uint32(field.Uint())
-                       out = append(out, byte(u32>>24))
-                       out = append(out, byte(u32>>16))
-                       out = append(out, byte(u32>>8))
-                       out = append(out, byte(u32))
-               case reflect.String:
-                       s := field.String()
-                       out = append(out, byte(len(s)>>24))
-                       out = append(out, byte(len(s)>>16))
-                       out = append(out, byte(len(s)>>8))
-                       out = append(out, byte(len(s)))
-                       out = append(out, s...)
-               case reflect.Slice:
-                       switch t.Elem().Kind() {
-                       case reflect.Uint8:
-                               length := field.Len()
-                               if structType.Field(i).Tag.Get("ssh") != "rest" {
-                                       out = append(out, byte(length>>24))
-                                       out = append(out, byte(length>>16))
-                                       out = append(out, byte(length>>8))
-                                       out = append(out, byte(length))
-                               }
-                               for j := 0; j < length; j++ {
-                                       out = append(out, byte(field.Index(j).Uint()))
-                               }
-                       case reflect.String:
-                               var length int
-                               for j := 0; j < field.Len(); j++ {
-                                       if j != 0 {
-                                               length++ /* comma */
-                                       }
-                                       length += len(field.Index(j).String())
-                               }
-
-                               out = append(out, byte(length>>24))
-                               out = append(out, byte(length>>16))
-                               out = append(out, byte(length>>8))
-                               out = append(out, byte(length))
-                               for j := 0; j < field.Len(); j++ {
-                                       if j != 0 {
-                                               out = append(out, ',')
-                                       }
-                                       out = append(out, field.Index(j).String()...)
-                               }
-                       default:
-                               panic("slice of unknown type")
-                       }
-               case reflect.Ptr:
-                       if t == bigIntType {
-                               var n *big.Int
-                               nValue := reflect.ValueOf(&n)
-                               nValue.Elem().Set(field)
-                               needed := intLength(n)
-                               oldLength := len(out)
-
-                               if cap(out)-len(out) < needed {
-                                       newOut := make([]byte, len(out), 2*(len(out)+needed))
-                                       copy(newOut, out)
-                                       out = newOut
-                               }
-                               out = out[:oldLength+needed]
-                               marshalInt(out[oldLength:], n)
-                       } else {
-                               panic("pointer to unknown type")
-                       }
-               }
-       }
-
-       return out
-}
-
-var bigOne = big.NewInt(1)
-
-func parseString(in []byte) (out, rest []byte, ok bool) {
-       if len(in) < 4 {
-               return
-       }
-       length := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
-       if uint32(len(in)) < 4+length {
-               return
-       }
-       out = in[4 : 4+length]
-       rest = in[4+length:]
-       ok = true
-       return
-}
-
-var (
-       comma         = []byte{','}
-       emptyNameList = []string{}
-)
-
-func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
-       contents, rest, ok := parseString(in)
-       if !ok {
-               return
-       }
-       if len(contents) == 0 {
-               out = emptyNameList
-               return
-       }
-       parts := bytes.Split(contents, comma)
-       out = make([]string, len(parts))
-       for i, part := range parts {
-               out[i] = string(part)
-       }
-       return
-}
-
-func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
-       contents, rest, ok := parseString(in)
-       if !ok {
-               return
-       }
-       out = new(big.Int)
-
-       if len(contents) > 0 && contents[0]&0x80 == 0x80 {
-               // This is a negative number
-               notBytes := make([]byte, len(contents))
-               for i := range notBytes {
-                       notBytes[i] = ^contents[i]
-               }
-               out.SetBytes(notBytes)
-               out.Add(out, bigOne)
-               out.Neg(out)
-       } else {
-               // Positive number
-               out.SetBytes(contents)
-       }
-       ok = true
-       return
-}
-
-func parseUint32(in []byte) (out uint32, rest []byte, ok bool) {
-       if len(in) < 4 {
-               return
-       }
-       out = uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
-       rest = in[4:]
-       ok = true
-       return
-}
-
-func nameListLength(namelist []string) int {
-       length := 4 /* uint32 length prefix */
-       for i, name := range namelist {
-               if i != 0 {
-                       length++ /* comma */
-               }
-               length += len(name)
-       }
-       return length
-}
-
-func intLength(n *big.Int) int {
-       length := 4 /* length bytes */
-       if n.Sign() < 0 {
-               nMinus1 := new(big.Int).Neg(n)
-               nMinus1.Sub(nMinus1, bigOne)
-               bitLen := nMinus1.BitLen()
-               if bitLen%8 == 0 {
-                       // The number will need 0xff padding
-                       length++
-               }
-               length += (bitLen + 7) / 8
-       } else if n.Sign() == 0 {
-               // A zero is the zero length string
-       } else {
-               bitLen := n.BitLen()
-               if bitLen%8 == 0 {
-                       // The number will need 0x00 padding
-                       length++
-               }
-               length += (bitLen + 7) / 8
-       }
-
-       return length
-}
-
-func marshalUint32(to []byte, n uint32) []byte {
-       to[0] = byte(n >> 24)
-       to[1] = byte(n >> 16)
-       to[2] = byte(n >> 8)
-       to[3] = byte(n)
-       return to[4:]
-}
-
-func marshalUint64(to []byte, n uint64) []byte {
-       to[0] = byte(n >> 56)
-       to[1] = byte(n >> 48)
-       to[2] = byte(n >> 40)
-       to[3] = byte(n >> 32)
-       to[4] = byte(n >> 24)
-       to[5] = byte(n >> 16)
-       to[6] = byte(n >> 8)
-       to[7] = byte(n)
-       return to[8:]
-}
-
-func marshalInt(to []byte, n *big.Int) []byte {
-       lengthBytes := to
-       to = to[4:]
-       length := 0
-
-       if n.Sign() < 0 {
-               // A negative number has to be converted to two's-complement
-               // form. So we'll subtract 1 and invert. If the
-               // most-significant-bit isn't set then we'll need to pad the
-               // beginning with 0xff in order to keep the number negative.
-               nMinus1 := new(big.Int).Neg(n)
-               nMinus1.Sub(nMinus1, bigOne)
-               bytes := nMinus1.Bytes()
-               for i := range bytes {
-                       bytes[i] ^= 0xff
-               }
-               if len(bytes) == 0 || bytes[0]&0x80 == 0 {
-                       to[0] = 0xff
-                       to = to[1:]
-                       length++
-               }
-               nBytes := copy(to, bytes)
-               to = to[nBytes:]
-               length += nBytes
-       } else if n.Sign() == 0 {
-               // A zero is the zero length string
-       } else {
-               bytes := n.Bytes()
-               if len(bytes) > 0 && bytes[0]&0x80 != 0 {
-                       // We'll have to pad this with a 0x00 in order to
-                       // stop it looking like a negative number.
-                       to[0] = 0
-                       to = to[1:]
-                       length++
-               }
-               nBytes := copy(to, bytes)
-               to = to[nBytes:]
-               length += nBytes
-       }
-
-       lengthBytes[0] = byte(length >> 24)
-       lengthBytes[1] = byte(length >> 16)
-       lengthBytes[2] = byte(length >> 8)
-       lengthBytes[3] = byte(length)
-       return to
-}
-
-func writeInt(w io.Writer, n *big.Int) {
-       length := intLength(n)
-       buf := make([]byte, length)
-       marshalInt(buf, n)
-       w.Write(buf)
-}
-
-func writeString(w io.Writer, s []byte) {
-       var lengthBytes [4]byte
-       lengthBytes[0] = byte(len(s) >> 24)
-       lengthBytes[1] = byte(len(s) >> 16)
-       lengthBytes[2] = byte(len(s) >> 8)
-       lengthBytes[3] = byte(len(s))
-       w.Write(lengthBytes[:])
-       w.Write(s)
-}
-
-func stringLength(s []byte) int {
-       return 4 + len(s)
-}
-
-func marshalString(to []byte, s []byte) []byte {
-       to[0] = byte(len(s) >> 24)
-       to[1] = byte(len(s) >> 16)
-       to[2] = byte(len(s) >> 8)
-       to[3] = byte(len(s))
-       to = to[4:]
-       copy(to, s)
-       return to[len(s):]
-}
-
-var bigIntType = reflect.TypeOf((*big.Int)(nil))
-
-// Decode a packet into it's corresponding message.
-func decode(packet []byte) interface{} {
-       var msg interface{}
-       switch packet[0] {
-       case msgDisconnect:
-               msg = new(disconnectMsg)
-       case msgServiceRequest:
-               msg = new(serviceRequestMsg)
-       case msgServiceAccept:
-               msg = new(serviceAcceptMsg)
-       case msgKexInit:
-               msg = new(kexInitMsg)
-       case msgKexDHInit:
-               msg = new(kexDHInitMsg)
-       case msgKexDHReply:
-               msg = new(kexDHReplyMsg)
-       case msgUserAuthRequest:
-               msg = new(userAuthRequestMsg)
-       case msgUserAuthFailure:
-               msg = new(userAuthFailureMsg)
-       case msgUserAuthPubKeyOk:
-               msg = new(userAuthPubKeyOkMsg)
-       case msgGlobalRequest:
-               msg = new(globalRequestMsg)
-       case msgRequestSuccess:
-               msg = new(channelRequestSuccessMsg)
-       case msgRequestFailure:
-               msg = new(channelRequestFailureMsg)
-       case msgChannelOpen:
-               msg = new(channelOpenMsg)
-       case msgChannelOpenConfirm:
-               msg = new(channelOpenConfirmMsg)
-       case msgChannelOpenFailure:
-               msg = new(channelOpenFailureMsg)
-       case msgChannelWindowAdjust:
-               msg = new(windowAdjustMsg)
-       case msgChannelEOF:
-               msg = new(channelEOFMsg)
-       case msgChannelClose:
-               msg = new(channelCloseMsg)
-       case msgChannelRequest:
-               msg = new(channelRequestMsg)
-       case msgChannelSuccess:
-               msg = new(channelRequestSuccessMsg)
-       case msgChannelFailure:
-               msg = new(channelRequestFailureMsg)
-       default:
-               return UnexpectedMessageError{0, packet[0]}
-       }
-       if err := unmarshal(msg, packet, packet[0]); err != nil {
-               return err
-       }
-       return msg
-}
diff --git a/libgo/go/exp/ssh/messages_test.go b/libgo/go/exp/ssh/messages_test.go
deleted file mode 100644 (file)
index fe4c397..0000000
+++ /dev/null
@@ -1,125 +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 ssh
-
-import (
-       "math/big"
-       "math/rand"
-       "reflect"
-       "testing"
-       "testing/quick"
-)
-
-var intLengthTests = []struct {
-       val, length int
-}{
-       {0, 4 + 0},
-       {1, 4 + 1},
-       {127, 4 + 1},
-       {128, 4 + 2},
-       {-1, 4 + 1},
-}
-
-func TestIntLength(t *testing.T) {
-       for _, test := range intLengthTests {
-               v := new(big.Int).SetInt64(int64(test.val))
-               length := intLength(v)
-               if length != test.length {
-                       t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
-               }
-       }
-}
-
-var messageTypes = []interface{}{
-       &kexInitMsg{},
-       &kexDHInitMsg{},
-       &serviceRequestMsg{},
-       &serviceAcceptMsg{},
-       &userAuthRequestMsg{},
-       &channelOpenMsg{},
-       &channelOpenConfirmMsg{},
-       &channelRequestMsg{},
-       &channelRequestSuccessMsg{},
-}
-
-func TestMarshalUnmarshal(t *testing.T) {
-       rand := rand.New(rand.NewSource(0))
-       for i, iface := range messageTypes {
-               ty := reflect.ValueOf(iface).Type()
-
-               n := 100
-               if testing.Short() {
-                       n = 5
-               }
-               for j := 0; j < n; j++ {
-                       v, ok := quick.Value(ty, rand)
-                       if !ok {
-                               t.Errorf("#%d: failed to create value", i)
-                               break
-                       }
-
-                       m1 := v.Elem().Interface()
-                       m2 := iface
-
-                       marshaled := marshal(msgIgnore, m1)
-                       if err := unmarshal(m2, marshaled, msgIgnore); err != nil {
-                               t.Errorf("#%d failed to unmarshal %#v: %s", i, m1, err)
-                               break
-                       }
-
-                       if !reflect.DeepEqual(v.Interface(), m2) {
-                               t.Errorf("#%d\ngot: %#v\nwant:%#v\n%x", i, m2, m1, marshaled)
-                               break
-                       }
-               }
-       }
-}
-
-func randomBytes(out []byte, rand *rand.Rand) {
-       for i := 0; i < len(out); i++ {
-               out[i] = byte(rand.Int31())
-       }
-}
-
-func randomNameList(rand *rand.Rand) []string {
-       ret := make([]string, rand.Int31()&15)
-       for i := range ret {
-               s := make([]byte, 1+(rand.Int31()&15))
-               for j := range s {
-                       s[j] = 'a' + uint8(rand.Int31()&15)
-               }
-               ret[i] = string(s)
-       }
-       return ret
-}
-
-func randomInt(rand *rand.Rand) *big.Int {
-       return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
-}
-
-func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
-       ki := &kexInitMsg{}
-       randomBytes(ki.Cookie[:], rand)
-       ki.KexAlgos = randomNameList(rand)
-       ki.ServerHostKeyAlgos = randomNameList(rand)
-       ki.CiphersClientServer = randomNameList(rand)
-       ki.CiphersServerClient = randomNameList(rand)
-       ki.MACsClientServer = randomNameList(rand)
-       ki.MACsServerClient = randomNameList(rand)
-       ki.CompressionClientServer = randomNameList(rand)
-       ki.CompressionServerClient = randomNameList(rand)
-       ki.LanguagesClientServer = randomNameList(rand)
-       ki.LanguagesServerClient = randomNameList(rand)
-       if rand.Int31()&1 == 1 {
-               ki.FirstKexFollows = true
-       }
-       return reflect.ValueOf(ki)
-}
-
-func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
-       dhi := &kexDHInitMsg{}
-       dhi.X = randomInt(rand)
-       return reflect.ValueOf(dhi)
-}
diff --git a/libgo/go/exp/ssh/server.go b/libgo/go/exp/ssh/server.go
deleted file mode 100644 (file)
index 31011c6..0000000
+++ /dev/null
@@ -1,676 +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 ssh
-
-import (
-       "bytes"
-       "crypto"
-       "crypto/rand"
-       "crypto/rsa"
-       "crypto/x509"
-       "encoding/pem"
-       "errors"
-       "io"
-       "math/big"
-       "net"
-       "sync"
-)
-
-type ServerConfig struct {
-       rsa           *rsa.PrivateKey
-       rsaSerialized []byte
-
-       // Rand provides the source of entropy for key exchange. If Rand is 
-       // nil, the cryptographic random reader in package crypto/rand will 
-       // be used.
-       Rand io.Reader
-
-       // NoClientAuth is true if clients are allowed to connect without
-       // authenticating.
-       NoClientAuth bool
-
-       // PasswordCallback, if non-nil, is called when a user attempts to
-       // authenticate using a password. It may be called concurrently from
-       // several goroutines.
-       PasswordCallback func(user, password string) bool
-
-       // PublicKeyCallback, if non-nil, is called when a client attempts public
-       // key authentication. It must return true iff the given public key is
-       // valid for the given user.
-       PublicKeyCallback func(user, algo string, pubkey []byte) bool
-
-       // Cryptographic-related configuration.
-       Crypto CryptoConfig
-}
-
-func (c *ServerConfig) rand() io.Reader {
-       if c.Rand == nil {
-               return rand.Reader
-       }
-       return c.Rand
-}
-
-// SetRSAPrivateKey sets the private key for a Server. A Server must have a
-// private key configured in order to accept connections. The private key must
-// be in the form of a PEM encoded, PKCS#1, RSA private key. The file "id_rsa"
-// typically contains such a key.
-func (s *ServerConfig) SetRSAPrivateKey(pemBytes []byte) error {
-       block, _ := pem.Decode(pemBytes)
-       if block == nil {
-               return errors.New("ssh: no key found")
-       }
-       var err error
-       s.rsa, err = x509.ParsePKCS1PrivateKey(block.Bytes)
-       if err != nil {
-               return err
-       }
-
-       s.rsaSerialized = marshalRSA(s.rsa)
-       return nil
-}
-
-// marshalRSA serializes an RSA private key according to RFC 4256, section 6.6.
-func marshalRSA(priv *rsa.PrivateKey) []byte {
-       e := new(big.Int).SetInt64(int64(priv.E))
-       length := stringLength([]byte(hostAlgoRSA))
-       length += intLength(e)
-       length += intLength(priv.N)
-
-       ret := make([]byte, length)
-       r := marshalString(ret, []byte(hostAlgoRSA))
-       r = marshalInt(r, e)
-       r = marshalInt(r, priv.N)
-
-       return ret
-}
-
-// parseRSA parses an RSA key according to RFC 4256, section 6.6.
-func parseRSA(in []byte) (pubKey *rsa.PublicKey, ok bool) {
-       algo, in, ok := parseString(in)
-       if !ok || string(algo) != hostAlgoRSA {
-               return nil, false
-       }
-       bigE, in, ok := parseInt(in)
-       if !ok || bigE.BitLen() > 24 {
-               return nil, false
-       }
-       e := bigE.Int64()
-       if e < 3 || e&1 == 0 {
-               return nil, false
-       }
-       N, in, ok := parseInt(in)
-       if !ok || len(in) > 0 {
-               return nil, false
-       }
-       return &rsa.PublicKey{
-               N: N,
-               E: int(e),
-       }, true
-}
-
-func parseRSASig(in []byte) (sig []byte, ok bool) {
-       algo, in, ok := parseString(in)
-       if !ok || string(algo) != hostAlgoRSA {
-               return nil, false
-       }
-       sig, in, ok = parseString(in)
-       if len(in) > 0 {
-               ok = false
-       }
-       return
-}
-
-// cachedPubKey contains the results of querying whether a public key is
-// acceptable for a user. The cache only applies to a single ServerConn.
-type cachedPubKey struct {
-       user, algo string
-       pubKey     []byte
-       result     bool
-}
-
-const maxCachedPubKeys = 16
-
-// A ServerConn represents an incomming connection.
-type ServerConn struct {
-       *transport
-       config *ServerConfig
-
-       channels   map[uint32]*channel
-       nextChanId uint32
-
-       // lock protects err and also allows Channels to serialise their writes
-       // to out.
-       lock sync.RWMutex
-       err  error
-
-       // cachedPubKeys contains the cache results of tests for public keys.
-       // Since SSH clients will query whether a public key is acceptable
-       // before attempting to authenticate with it, we end up with duplicate
-       // queries for public key validity.
-       cachedPubKeys []cachedPubKey
-}
-
-// Server returns a new SSH server connection
-// using c as the underlying transport.
-func Server(c net.Conn, config *ServerConfig) *ServerConn {
-       conn := &ServerConn{
-               transport: newTransport(c, config.rand()),
-               channels:  make(map[uint32]*channel),
-               config:    config,
-       }
-       return conn
-}
-
-// kexDH performs Diffie-Hellman key agreement on a ServerConnection. The
-// returned values are given the same names as in RFC 4253, section 8.
-func (s *ServerConn) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handshakeMagics, hostKeyAlgo string) (H, K []byte, err error) {
-       packet, err := s.readPacket()
-       if err != nil {
-               return
-       }
-       var kexDHInit kexDHInitMsg
-       if err = unmarshal(&kexDHInit, packet, msgKexDHInit); err != nil {
-               return
-       }
-
-       if kexDHInit.X.Sign() == 0 || kexDHInit.X.Cmp(group.p) >= 0 {
-               return nil, nil, errors.New("client DH parameter out of bounds")
-       }
-
-       y, err := rand.Int(s.config.rand(), group.p)
-       if err != nil {
-               return
-       }
-
-       Y := new(big.Int).Exp(group.g, y, group.p)
-       kInt := new(big.Int).Exp(kexDHInit.X, y, group.p)
-
-       var serializedHostKey []byte
-       switch hostKeyAlgo {
-       case hostAlgoRSA:
-               serializedHostKey = s.config.rsaSerialized
-       default:
-               return nil, nil, errors.New("internal error")
-       }
-
-       h := hashFunc.New()
-       writeString(h, magics.clientVersion)
-       writeString(h, magics.serverVersion)
-       writeString(h, magics.clientKexInit)
-       writeString(h, magics.serverKexInit)
-       writeString(h, serializedHostKey)
-       writeInt(h, kexDHInit.X)
-       writeInt(h, Y)
-       K = make([]byte, intLength(kInt))
-       marshalInt(K, kInt)
-       h.Write(K)
-
-       H = h.Sum(nil)
-
-       h.Reset()
-       h.Write(H)
-       hh := h.Sum(nil)
-
-       var sig []byte
-       switch hostKeyAlgo {
-       case hostAlgoRSA:
-               sig, err = rsa.SignPKCS1v15(s.config.rand(), s.config.rsa, hashFunc, hh)
-               if err != nil {
-                       return
-               }
-       default:
-               return nil, nil, errors.New("internal error")
-       }
-
-       serializedSig := serializeSignature(hostAlgoRSA, sig)
-
-       kexDHReply := kexDHReplyMsg{
-               HostKey:   serializedHostKey,
-               Y:         Y,
-               Signature: serializedSig,
-       }
-       packet = marshal(msgKexDHReply, kexDHReply)
-
-       err = s.writePacket(packet)
-       return
-}
-
-// serverVersion is the fixed identification string that Server will use.
-var serverVersion = []byte("SSH-2.0-Go\r\n")
-
-// Handshake performs an SSH transport and client authentication on the given ServerConn.
-func (s *ServerConn) Handshake() error {
-       var magics handshakeMagics
-       if _, err := s.Write(serverVersion); err != nil {
-               return err
-       }
-       if err := s.Flush(); err != nil {
-               return err
-       }
-       magics.serverVersion = serverVersion[:len(serverVersion)-2]
-
-       version, err := readVersion(s)
-       if err != nil {
-               return err
-       }
-       magics.clientVersion = version
-
-       serverKexInit := kexInitMsg{
-               KexAlgos:                supportedKexAlgos,
-               ServerHostKeyAlgos:      supportedHostKeyAlgos,
-               CiphersClientServer:     s.config.Crypto.ciphers(),
-               CiphersServerClient:     s.config.Crypto.ciphers(),
-               MACsClientServer:        supportedMACs,
-               MACsServerClient:        supportedMACs,
-               CompressionClientServer: supportedCompressions,
-               CompressionServerClient: supportedCompressions,
-       }
-       kexInitPacket := marshal(msgKexInit, serverKexInit)
-       magics.serverKexInit = kexInitPacket
-
-       if err := s.writePacket(kexInitPacket); err != nil {
-               return err
-       }
-
-       packet, err := s.readPacket()
-       if err != nil {
-               return err
-       }
-
-       magics.clientKexInit = packet
-
-       var clientKexInit kexInitMsg
-       if err = unmarshal(&clientKexInit, packet, msgKexInit); err != nil {
-               return err
-       }
-
-       kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, &clientKexInit, &serverKexInit)
-       if !ok {
-               return errors.New("ssh: no common algorithms")
-       }
-
-       if clientKexInit.FirstKexFollows && kexAlgo != clientKexInit.KexAlgos[0] {
-               // The client sent a Kex message for the wrong algorithm,
-               // which we have to ignore.
-               if _, err := s.readPacket(); err != nil {
-                       return err
-               }
-       }
-
-       var H, K []byte
-       var hashFunc crypto.Hash
-       switch kexAlgo {
-       case kexAlgoDH14SHA1:
-               hashFunc = crypto.SHA1
-               dhGroup14Once.Do(initDHGroup14)
-               H, K, err = s.kexDH(dhGroup14, hashFunc, &magics, hostKeyAlgo)
-       default:
-               err = errors.New("ssh: unexpected key exchange algorithm " + kexAlgo)
-       }
-       if err != nil {
-               return err
-       }
-
-       if err = s.writePacket([]byte{msgNewKeys}); err != nil {
-               return err
-       }
-       if err = s.transport.writer.setupKeys(serverKeys, K, H, H, hashFunc); err != nil {
-               return err
-       }
-       if packet, err = s.readPacket(); err != nil {
-               return err
-       }
-
-       if packet[0] != msgNewKeys {
-               return UnexpectedMessageError{msgNewKeys, packet[0]}
-       }
-       if err = s.transport.reader.setupKeys(clientKeys, K, H, H, hashFunc); err != nil {
-               return err
-       }
-       if packet, err = s.readPacket(); err != nil {
-               return err
-       }
-
-       var serviceRequest serviceRequestMsg
-       if err = unmarshal(&serviceRequest, packet, msgServiceRequest); err != nil {
-               return err
-       }
-       if serviceRequest.Service != serviceUserAuth {
-               return errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
-       }
-       serviceAccept := serviceAcceptMsg{
-               Service: serviceUserAuth,
-       }
-       if err = s.writePacket(marshal(msgServiceAccept, serviceAccept)); err != nil {
-               return err
-       }
-
-       if err = s.authenticate(H); err != nil {
-               return err
-       }
-       return nil
-}
-
-func isAcceptableAlgo(algo string) bool {
-       return algo == hostAlgoRSA
-}
-
-// testPubKey returns true if the given public key is acceptable for the user.
-func (s *ServerConn) testPubKey(user, algo string, pubKey []byte) bool {
-       if s.config.PublicKeyCallback == nil || !isAcceptableAlgo(algo) {
-               return false
-       }
-
-       for _, c := range s.cachedPubKeys {
-               if c.user == user && c.algo == algo && bytes.Equal(c.pubKey, pubKey) {
-                       return c.result
-               }
-       }
-
-       result := s.config.PublicKeyCallback(user, algo, pubKey)
-       if len(s.cachedPubKeys) < maxCachedPubKeys {
-               c := cachedPubKey{
-                       user:   user,
-                       algo:   algo,
-                       pubKey: make([]byte, len(pubKey)),
-                       result: result,
-               }
-               copy(c.pubKey, pubKey)
-               s.cachedPubKeys = append(s.cachedPubKeys, c)
-       }
-
-       return result
-}
-
-func (s *ServerConn) authenticate(H []byte) error {
-       var userAuthReq userAuthRequestMsg
-       var err error
-       var packet []byte
-
-userAuthLoop:
-       for {
-               if packet, err = s.readPacket(); err != nil {
-                       return err
-               }
-               if err = unmarshal(&userAuthReq, packet, msgUserAuthRequest); err != nil {
-                       return err
-               }
-
-               if userAuthReq.Service != serviceSSH {
-                       return errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
-               }
-
-               switch userAuthReq.Method {
-               case "none":
-                       if s.config.NoClientAuth {
-                               break userAuthLoop
-                       }
-               case "password":
-                       if s.config.PasswordCallback == nil {
-                               break
-                       }
-                       payload := userAuthReq.Payload
-                       if len(payload) < 1 || payload[0] != 0 {
-                               return ParseError{msgUserAuthRequest}
-                       }
-                       payload = payload[1:]
-                       password, payload, ok := parseString(payload)
-                       if !ok || len(payload) > 0 {
-                               return ParseError{msgUserAuthRequest}
-                       }
-
-                       if s.config.PasswordCallback(userAuthReq.User, string(password)) {
-                               break userAuthLoop
-                       }
-               case "publickey":
-                       if s.config.PublicKeyCallback == nil {
-                               break
-                       }
-                       payload := userAuthReq.Payload
-                       if len(payload) < 1 {
-                               return ParseError{msgUserAuthRequest}
-                       }
-                       isQuery := payload[0] == 0
-                       payload = payload[1:]
-                       algoBytes, payload, ok := parseString(payload)
-                       if !ok {
-                               return ParseError{msgUserAuthRequest}
-                       }
-                       algo := string(algoBytes)
-
-                       pubKey, payload, ok := parseString(payload)
-                       if !ok {
-                               return ParseError{msgUserAuthRequest}
-                       }
-                       if isQuery {
-                               // The client can query if the given public key
-                               // would be ok.
-                               if len(payload) > 0 {
-                                       return ParseError{msgUserAuthRequest}
-                               }
-                               if s.testPubKey(userAuthReq.User, algo, pubKey) {
-                                       okMsg := userAuthPubKeyOkMsg{
-                                               Algo:   algo,
-                                               PubKey: string(pubKey),
-                                       }
-                                       if err = s.writePacket(marshal(msgUserAuthPubKeyOk, okMsg)); err != nil {
-                                               return err
-                                       }
-                                       continue userAuthLoop
-                               }
-                       } else {
-                               sig, payload, ok := parseString(payload)
-                               if !ok || len(payload) > 0 {
-                                       return ParseError{msgUserAuthRequest}
-                               }
-                               if !isAcceptableAlgo(algo) {
-                                       break
-                               }
-                               rsaSig, ok := parseRSASig(sig)
-                               if !ok {
-                                       return ParseError{msgUserAuthRequest}
-                               }
-                               signedData := buildDataSignedForAuth(H, userAuthReq, algoBytes, pubKey)
-                               switch algo {
-                               case hostAlgoRSA:
-                                       hashFunc := crypto.SHA1
-                                       h := hashFunc.New()
-                                       h.Write(signedData)
-                                       digest := h.Sum(nil)
-                                       rsaKey, ok := parseRSA(pubKey)
-                                       if !ok {
-                                               return ParseError{msgUserAuthRequest}
-                                       }
-                                       if rsa.VerifyPKCS1v15(rsaKey, hashFunc, digest, rsaSig) != nil {
-                                               return ParseError{msgUserAuthRequest}
-                                       }
-                               default:
-                                       return errors.New("ssh: isAcceptableAlgo incorrect")
-                               }
-                               if s.testPubKey(userAuthReq.User, algo, pubKey) {
-                                       break userAuthLoop
-                               }
-                       }
-               }
-
-               var failureMsg userAuthFailureMsg
-               if s.config.PasswordCallback != nil {
-                       failureMsg.Methods = append(failureMsg.Methods, "password")
-               }
-               if s.config.PublicKeyCallback != nil {
-                       failureMsg.Methods = append(failureMsg.Methods, "publickey")
-               }
-
-               if len(failureMsg.Methods) == 0 {
-                       return errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
-               }
-
-               if err = s.writePacket(marshal(msgUserAuthFailure, failureMsg)); err != nil {
-                       return err
-               }
-       }
-
-       packet = []byte{msgUserAuthSuccess}
-       if err = s.writePacket(packet); err != nil {
-               return err
-       }
-
-       return nil
-}
-
-const defaultWindowSize = 32768
-
-// Accept reads and processes messages on a ServerConn. It must be called
-// in order to demultiplex messages to any resulting Channels.
-func (s *ServerConn) Accept() (Channel, error) {
-       if s.err != nil {
-               return nil, s.err
-       }
-
-       for {
-               packet, err := s.readPacket()
-               if err != nil {
-
-                       s.lock.Lock()
-                       s.err = err
-                       s.lock.Unlock()
-
-                       for _, c := range s.channels {
-                               c.dead = true
-                               c.handleData(nil)
-                       }
-
-                       return nil, err
-               }
-
-               switch packet[0] {
-               case msgChannelData:
-                       if len(packet) < 9 {
-                               // malformed data packet
-                               return nil, ParseError{msgChannelData}
-                       }
-                       peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
-                       s.lock.Lock()
-                       c, ok := s.channels[peersId]
-                       if !ok {
-                               s.lock.Unlock()
-                               continue
-                       }
-                       if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 {
-                               packet = packet[9:]
-                               c.handleData(packet[:length])
-                       }
-                       s.lock.Unlock()
-               default:
-                       switch msg := decode(packet).(type) {
-                       case *channelOpenMsg:
-                               c := new(channel)
-                               c.chanType = msg.ChanType
-                               c.theirId = msg.PeersId
-                               c.theirWindow = msg.PeersWindow
-                               c.maxPacketSize = msg.MaxPacketSize
-                               c.extraData = msg.TypeSpecificData
-                               c.myWindow = defaultWindowSize
-                               c.serverConn = s
-                               c.cond = sync.NewCond(&c.lock)
-                               c.pendingData = make([]byte, c.myWindow)
-
-                               s.lock.Lock()
-                               c.myId = s.nextChanId
-                               s.nextChanId++
-                               s.channels[c.myId] = c
-                               s.lock.Unlock()
-                               return c, nil
-
-                       case *channelRequestMsg:
-                               s.lock.Lock()
-                               c, ok := s.channels[msg.PeersId]
-                               if !ok {
-                                       s.lock.Unlock()
-                                       continue
-                               }
-                               c.handlePacket(msg)
-                               s.lock.Unlock()
-
-                       case *channelEOFMsg:
-                               s.lock.Lock()
-                               c, ok := s.channels[msg.PeersId]
-                               if !ok {
-                                       s.lock.Unlock()
-                                       continue
-                               }
-                               c.handlePacket(msg)
-                               s.lock.Unlock()
-
-                       case *channelCloseMsg:
-                               s.lock.Lock()
-                               c, ok := s.channels[msg.PeersId]
-                               if !ok {
-                                       s.lock.Unlock()
-                                       continue
-                               }
-                               c.handlePacket(msg)
-                               s.lock.Unlock()
-
-                       case *globalRequestMsg:
-                               if msg.WantReply {
-                                       if err := s.writePacket([]byte{msgRequestFailure}); err != nil {
-                                               return nil, err
-                                       }
-                               }
-
-                       case UnexpectedMessageError:
-                               return nil, msg
-                       case *disconnectMsg:
-                               return nil, io.EOF
-                       default:
-                               // Unknown message. Ignore.
-                       }
-               }
-       }
-
-       panic("unreachable")
-}
-
-// A Listener implements a network listener (net.Listener) for SSH connections.
-type Listener struct {
-       listener net.Listener
-       config   *ServerConfig
-}
-
-// Accept waits for and returns the next incoming SSH connection.
-// The receiver should call Handshake() in another goroutine 
-// to avoid blocking the accepter.
-func (l *Listener) Accept() (*ServerConn, error) {
-       c, err := l.listener.Accept()
-       if err != nil {
-               return nil, err
-       }
-       conn := Server(c, l.config)
-       return conn, nil
-}
-
-// Addr returns the listener's network address.
-func (l *Listener) Addr() net.Addr {
-       return l.listener.Addr()
-}
-
-// Close closes the listener.
-func (l *Listener) Close() error {
-       return l.listener.Close()
-}
-
-// Listen creates an SSH listener accepting connections on
-// the given network address using net.Listen.
-func Listen(network, addr string, config *ServerConfig) (*Listener, error) {
-       l, err := net.Listen(network, addr)
-       if err != nil {
-               return nil, err
-       }
-       return &Listener{
-               l,
-               config,
-       }, nil
-}
diff --git a/libgo/go/exp/ssh/server_terminal.go b/libgo/go/exp/ssh/server_terminal.go
deleted file mode 100644 (file)
index 708a915..0000000
+++ /dev/null
@@ -1,81 +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 ssh
-
-// A Terminal is capable of parsing and generating virtual terminal
-// data from an SSH client.
-type Terminal interface {
-       ReadLine() (line string, err error)
-       SetSize(x, y int)
-       Write([]byte) (int, error)
-}
-
-// ServerTerminal contains the state for running a terminal that is capable of
-// reading lines of input.
-type ServerTerminal struct {
-       Term    Terminal
-       Channel Channel
-}
-
-// parsePtyRequest parses the payload of the pty-req message and extracts the
-// dimensions of the terminal. See RFC 4254, section 6.2.
-func parsePtyRequest(s []byte) (width, height int, ok bool) {
-       _, s, ok = parseString(s)
-       if !ok {
-               return
-       }
-       width32, s, ok := parseUint32(s)
-       if !ok {
-               return
-       }
-       height32, _, ok := parseUint32(s)
-       width = int(width32)
-       height = int(height32)
-       if width < 1 {
-               ok = false
-       }
-       if height < 1 {
-               ok = false
-       }
-       return
-}
-
-func (ss *ServerTerminal) Write(buf []byte) (n int, err error) {
-       return ss.Term.Write(buf)
-}
-
-// ReadLine returns a line of input from the terminal.
-func (ss *ServerTerminal) ReadLine() (line string, err error) {
-       for {
-               if line, err = ss.Term.ReadLine(); err == nil {
-                       return
-               }
-
-               req, ok := err.(ChannelRequest)
-               if !ok {
-                       return
-               }
-
-               ok = false
-               switch req.Request {
-               case "pty-req":
-                       var width, height int
-                       width, height, ok = parsePtyRequest(req.Payload)
-                       ss.Term.SetSize(width, height)
-               case "shell":
-                       ok = true
-                       if len(req.Payload) > 0 {
-                               // We don't accept any commands, only the default shell.
-                               ok = false
-                       }
-               case "env":
-                       ok = true
-               }
-               if req.WantReply {
-                       ss.Channel.AckRequest(ok)
-               }
-       }
-       panic("unreachable")
-}
diff --git a/libgo/go/exp/ssh/session.go b/libgo/go/exp/ssh/session.go
deleted file mode 100644 (file)
index ea4addb..0000000
+++ /dev/null
@@ -1,494 +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 ssh
-
-// Session implements an interactive session described in
-// "RFC 4254, section 6".
-
-import (
-       "bytes"
-       "errors"
-       "fmt"
-       "io"
-       "io/ioutil"
-)
-
-type Signal string
-
-// POSIX signals as listed in RFC 4254 Section 6.10.
-const (
-       SIGABRT Signal = "ABRT"
-       SIGALRM Signal = "ALRM"
-       SIGFPE  Signal = "FPE"
-       SIGHUP  Signal = "HUP"
-       SIGILL  Signal = "ILL"
-       SIGINT  Signal = "INT"
-       SIGKILL Signal = "KILL"
-       SIGPIPE Signal = "PIPE"
-       SIGQUIT Signal = "QUIT"
-       SIGSEGV Signal = "SEGV"
-       SIGTERM Signal = "TERM"
-       SIGUSR1 Signal = "USR1"
-       SIGUSR2 Signal = "USR2"
-)
-
-var signals = map[Signal]int{
-       SIGABRT: 6,
-       SIGALRM: 14,
-       SIGFPE:  8,
-       SIGHUP:  1,
-       SIGILL:  4,
-       SIGINT:  2,
-       SIGKILL: 9,
-       SIGPIPE: 13,
-       SIGQUIT: 3,
-       SIGSEGV: 11,
-       SIGTERM: 15,
-}
-
-// A Session represents a connection to a remote command or shell.
-type Session struct {
-       // Stdin specifies the remote process's standard input.
-       // If Stdin is nil, the remote process reads from an empty
-       // bytes.Buffer.
-       Stdin io.Reader
-
-       // Stdout and Stderr specify the remote process's standard
-       // output and error.
-       //
-       // If either is nil, Run connects the corresponding file
-       // descriptor to an instance of ioutil.Discard. There is a
-       // fixed amount of buffering that is shared for the two streams.
-       // If either blocks it may eventually cause the remote
-       // command to block.
-       Stdout io.Writer
-       Stderr io.Writer
-
-       *clientChan // the channel backing this session
-
-       started   bool // true once Start, Run or Shell is invoked.
-       copyFuncs []func() error
-       errors    chan error // one send per copyFunc
-
-       // true if pipe method is active
-       stdinpipe, stdoutpipe, stderrpipe bool
-}
-
-// RFC 4254 Section 6.4.
-type setenvRequest struct {
-       PeersId   uint32
-       Request   string
-       WantReply bool
-       Name      string
-       Value     string
-}
-
-// Setenv sets an environment variable that will be applied to any
-// command executed by Shell or Run.
-func (s *Session) Setenv(name, value string) error {
-       req := setenvRequest{
-               PeersId:   s.peersId,
-               Request:   "env",
-               WantReply: true,
-               Name:      name,
-               Value:     value,
-       }
-       if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
-               return err
-       }
-       return s.waitForResponse()
-}
-
-// An empty mode list, see RFC 4254 Section 8.
-var emptyModelist = "\x00"
-
-// RFC 4254 Section 6.2.
-type ptyRequestMsg struct {
-       PeersId   uint32
-       Request   string
-       WantReply bool
-       Term      string
-       Columns   uint32
-       Rows      uint32
-       Width     uint32
-       Height    uint32
-       Modelist  string
-}
-
-// RequestPty requests the association of a pty with the session on the remote host.
-func (s *Session) RequestPty(term string, h, w int) error {
-       req := ptyRequestMsg{
-               PeersId:   s.peersId,
-               Request:   "pty-req",
-               WantReply: true,
-               Term:      term,
-               Columns:   uint32(w),
-               Rows:      uint32(h),
-               Width:     uint32(w * 8),
-               Height:    uint32(h * 8),
-               Modelist:  emptyModelist,
-       }
-       if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
-               return err
-       }
-       return s.waitForResponse()
-}
-
-// RFC 4254 Section 6.9.
-type signalMsg struct {
-       PeersId   uint32
-       Request   string
-       WantReply bool
-       Signal    string
-}
-
-// Signal sends the given signal to the remote process.
-// sig is one of the SIG* constants.
-func (s *Session) Signal(sig Signal) error {
-       req := signalMsg{
-               PeersId:   s.peersId,
-               Request:   "signal",
-               WantReply: false,
-               Signal:    string(sig),
-       }
-       return s.writePacket(marshal(msgChannelRequest, req))
-}
-
-// RFC 4254 Section 6.5.
-type execMsg struct {
-       PeersId   uint32
-       Request   string
-       WantReply bool
-       Command   string
-}
-
-// Start runs cmd on the remote host. Typically, the remote
-// server passes cmd to the shell for interpretation.
-// A Session only accepts one call to Run, Start or Shell.
-func (s *Session) Start(cmd string) error {
-       if s.started {
-               return errors.New("ssh: session already started")
-       }
-       req := execMsg{
-               PeersId:   s.peersId,
-               Request:   "exec",
-               WantReply: true,
-               Command:   cmd,
-       }
-       if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
-               return err
-       }
-       if err := s.waitForResponse(); err != nil {
-               return fmt.Errorf("ssh: could not execute command %s: %v", cmd, err)
-       }
-       return s.start()
-}
-
-// Run runs cmd on the remote host. Typically, the remote
-// server passes cmd to the shell for interpretation.
-// A Session only accepts one call to Run, Start or Shell.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command fails to run or doesn't complete successfully, the
-// error is of type *ExitError. Other error types may be
-// returned for I/O problems.
-func (s *Session) Run(cmd string) error {
-       err := s.Start(cmd)
-       if err != nil {
-               return err
-       }
-       return s.Wait()
-}
-
-// Shell starts a login shell on the remote host. A Session only
-// accepts one call to Run, Start or Shell.
-func (s *Session) Shell() error {
-       if s.started {
-               return errors.New("ssh: session already started")
-       }
-       req := channelRequestMsg{
-               PeersId:   s.peersId,
-               Request:   "shell",
-               WantReply: true,
-       }
-       if err := s.writePacket(marshal(msgChannelRequest, req)); err != nil {
-               return err
-       }
-       if err := s.waitForResponse(); err != nil {
-               return fmt.Errorf("ssh: cound not execute shell: %v", err)
-       }
-       return s.start()
-}
-
-func (s *Session) waitForResponse() error {
-       msg := <-s.msg
-       switch msg.(type) {
-       case *channelRequestSuccessMsg:
-               return nil
-       case *channelRequestFailureMsg:
-               return errors.New("request failed")
-       }
-       return fmt.Errorf("unknown packet %T received: %v", msg, msg)
-}
-
-func (s *Session) start() error {
-       s.started = true
-
-       type F func(*Session)
-       for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} {
-               setupFd(s)
-       }
-
-       s.errors = make(chan error, len(s.copyFuncs))
-       for _, fn := range s.copyFuncs {
-               go func(fn func() error) {
-                       s.errors <- fn()
-               }(fn)
-       }
-       return nil
-}
-
-// Wait waits for the remote command to exit.
-//
-// The returned error is nil if the command runs, has no problems
-// copying stdin, stdout, and stderr, and exits with a zero exit
-// status.
-//
-// If the command fails to run or doesn't complete successfully, the
-// error is of type *ExitError. Other error types may be
-// returned for I/O problems.
-func (s *Session) Wait() error {
-       if !s.started {
-               return errors.New("ssh: session not started")
-       }
-       waitErr := s.wait()
-
-       var copyError error
-       for _ = range s.copyFuncs {
-               if err := <-s.errors; err != nil && copyError == nil {
-                       copyError = err
-               }
-       }
-       if waitErr != nil {
-               return waitErr
-       }
-       return copyError
-}
-
-func (s *Session) wait() error {
-       wm := Waitmsg{status: -1}
-
-       // Wait for msg channel to be closed before returning.
-       for msg := range s.msg {
-               switch msg := msg.(type) {
-               case *channelRequestMsg:
-                       switch msg.Request {
-                       case "exit-status":
-                               d := msg.RequestSpecificData
-                               wm.status = int(d[0])<<24 | int(d[1])<<16 | int(d[2])<<8 | int(d[3])
-                       case "exit-signal":
-                               signal, rest, ok := parseString(msg.RequestSpecificData)
-                               if !ok {
-                                       return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
-                               }
-                               wm.signal = safeString(string(signal))
-
-                               // skip coreDumped bool
-                               if len(rest) == 0 {
-                                       return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
-                               }
-                               rest = rest[1:]
-
-                               errmsg, rest, ok := parseString(rest)
-                               if !ok {
-                                       return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
-                               }
-                               wm.msg = safeString(string(errmsg))
-
-                               lang, _, ok := parseString(rest)
-                               if !ok {
-                                       return fmt.Errorf("wait: could not parse request data: %v", msg.RequestSpecificData)
-                               }
-                               wm.lang = safeString(string(lang))
-                       default:
-                               return fmt.Errorf("wait: unexpected channel request: %v", msg)
-                       }
-               default:
-                       return fmt.Errorf("wait: unexpected packet %T received: %v", msg, msg)
-               }
-       }
-       if wm.status == 0 {
-               return nil
-       }
-       if wm.status == -1 {
-               // exit-status was never sent from server
-               if wm.signal == "" {
-                       return errors.New("wait: remote command exited without exit status or exit signal")
-               }
-               wm.status = 128
-               if _, ok := signals[Signal(wm.signal)]; ok {
-                       wm.status += signals[Signal(wm.signal)]
-               }
-       }
-       return &ExitError{wm}
-}
-
-func (s *Session) stdin() {
-       if s.stdinpipe {
-               return
-       }
-       if s.Stdin == nil {
-               s.Stdin = new(bytes.Buffer)
-       }
-       s.copyFuncs = append(s.copyFuncs, func() error {
-               _, err := io.Copy(s.clientChan.stdin, s.Stdin)
-               if err1 := s.clientChan.stdin.Close(); err == nil {
-                       err = err1
-               }
-               return err
-       })
-}
-
-func (s *Session) stdout() {
-       if s.stdoutpipe {
-               return
-       }
-       if s.Stdout == nil {
-               s.Stdout = ioutil.Discard
-       }
-       s.copyFuncs = append(s.copyFuncs, func() error {
-               _, err := io.Copy(s.Stdout, s.clientChan.stdout)
-               return err
-       })
-}
-
-func (s *Session) stderr() {
-       if s.stderrpipe {
-               return
-       }
-       if s.Stderr == nil {
-               s.Stderr = ioutil.Discard
-       }
-       s.copyFuncs = append(s.copyFuncs, func() error {
-               _, err := io.Copy(s.Stderr, s.clientChan.stderr)
-               return err
-       })
-}
-
-// StdinPipe returns a pipe that will be connected to the
-// remote command's standard input when the command starts.
-func (s *Session) StdinPipe() (io.WriteCloser, error) {
-       if s.Stdin != nil {
-               return nil, errors.New("ssh: Stdin already set")
-       }
-       if s.started {
-               return nil, errors.New("ssh: StdinPipe after process started")
-       }
-       s.stdinpipe = true
-       return s.clientChan.stdin, nil
-}
-
-// StdoutPipe returns a pipe that will be connected to the
-// remote command's standard output when the command starts.
-// There is a fixed amount of buffering that is shared between
-// stdout and stderr streams. If the StdoutPipe reader is
-// not serviced fast enought it may eventually cause the
-// remote command to block.
-func (s *Session) StdoutPipe() (io.Reader, error) {
-       if s.Stdout != nil {
-               return nil, errors.New("ssh: Stdout already set")
-       }
-       if s.started {
-               return nil, errors.New("ssh: StdoutPipe after process started")
-       }
-       s.stdoutpipe = true
-       return s.clientChan.stdout, nil
-}
-
-// StderrPipe returns a pipe that will be connected to the
-// remote command's standard error when the command starts.
-// There is a fixed amount of buffering that is shared between
-// stdout and stderr streams. If the StderrPipe reader is
-// not serviced fast enought it may eventually cause the
-// remote command to block.
-func (s *Session) StderrPipe() (io.Reader, error) {
-       if s.Stderr != nil {
-               return nil, errors.New("ssh: Stderr already set")
-       }
-       if s.started {
-               return nil, errors.New("ssh: StderrPipe after process started")
-       }
-       s.stderrpipe = true
-       return s.clientChan.stderr, nil
-}
-
-// TODO(dfc) add Output and CombinedOutput helpers
-
-// NewSession returns a new interactive session on the remote host.
-func (c *ClientConn) NewSession() (*Session, error) {
-       ch := c.newChan(c.transport)
-       if err := c.writePacket(marshal(msgChannelOpen, channelOpenMsg{
-               ChanType:      "session",
-               PeersId:       ch.id,
-               PeersWindow:   1 << 14,
-               MaxPacketSize: 1 << 15, // RFC 4253 6.1
-       })); err != nil {
-               c.chanlist.remove(ch.id)
-               return nil, err
-       }
-       if err := ch.waitForChannelOpenResponse(); err != nil {
-               c.chanlist.remove(ch.id)
-               return nil, fmt.Errorf("ssh: unable to open session: %v", err)
-       }
-       return &Session{
-               clientChan: ch,
-       }, nil
-}
-
-// An ExitError reports unsuccessful completion of a remote command.
-type ExitError struct {
-       Waitmsg
-}
-
-func (e *ExitError) Error() string {
-       return e.Waitmsg.String()
-}
-
-// Waitmsg stores the information about an exited remote command
-// as reported by Wait.
-type Waitmsg struct {
-       status int
-       signal string
-       msg    string
-       lang   string
-}
-
-// ExitStatus returns the exit status of the remote command.
-func (w Waitmsg) ExitStatus() int {
-       return w.status
-}
-
-// Signal returns the exit signal of the remote command if
-// it was terminated violently.
-func (w Waitmsg) Signal() string {
-       return w.signal
-}
-
-// Msg returns the exit message given by the remote command
-func (w Waitmsg) Msg() string {
-       return w.msg
-}
-
-// Lang returns the language tag. See RFC 3066
-func (w Waitmsg) Lang() string {
-       return w.lang
-}
-
-func (w Waitmsg) String() string {
-       return fmt.Sprintf("Process exited with: %v. Reason was: %v (%v)", w.status, w.msg, w.signal)
-}
diff --git a/libgo/go/exp/ssh/session_test.go b/libgo/go/exp/ssh/session_test.go
deleted file mode 100644 (file)
index 4a3d22b..0000000
+++ /dev/null
@@ -1,374 +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 ssh
-
-// Session tests.
-
-import (
-       "bytes"
-       "exp/terminal"
-       "io"
-       "testing"
-)
-
-type serverType func(*channel)
-
-// dial constructs a new test server and returns a *ClientConn.
-func dial(handler serverType, t *testing.T) *ClientConn {
-       pw := password("tiger")
-       serverConfig.PasswordCallback = func(user, pass string) bool {
-               return user == "testuser" && pass == string(pw)
-       }
-       serverConfig.PublicKeyCallback = nil
-
-       l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
-       if err != nil {
-               t.Fatalf("unable to listen: %s", err)
-       }
-       go func() {
-               defer l.Close()
-               conn, err := l.Accept()
-               if err != nil {
-                       t.Errorf("Unable to accept: %v", err)
-                       return
-               }
-               defer conn.Close()
-               if err := conn.Handshake(); err != nil {
-                       t.Errorf("Unable to handshake: %v", err)
-                       return
-               }
-               for {
-                       ch, err := conn.Accept()
-                       if err == io.EOF {
-                               return
-                       }
-                       if err != nil {
-                               t.Errorf("Unable to accept incoming channel request: %v", err)
-                               return
-                       }
-                       if ch.ChannelType() != "session" {
-                               ch.Reject(UnknownChannelType, "unknown channel type")
-                               continue
-                       }
-                       ch.Accept()
-                       go handler(ch.(*channel))
-               }
-               t.Log("done")
-       }()
-
-       config := &ClientConfig{
-               User: "testuser",
-               Auth: []ClientAuth{
-                       ClientAuthPassword(pw),
-               },
-       }
-
-       c, err := Dial("tcp", l.Addr().String(), config)
-       if err != nil {
-               t.Fatalf("unable to dial remote side: %s", err)
-       }
-       return c
-}
-
-// Test a simple string is returned to session.Stdout.
-func TestSessionShell(t *testing.T) {
-       conn := dial(shellHandler, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-       stdout := new(bytes.Buffer)
-       session.Stdout = stdout
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       if err := session.Wait(); err != nil {
-               t.Fatalf("Remote command did not exit cleanly: %s", err)
-       }
-       actual := stdout.String()
-       if actual != "golang" {
-               t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
-       }
-}
-
-// TODO(dfc) add support for Std{in,err}Pipe when the Server supports it.
-
-// Test a simple string is returned via StdoutPipe.
-func TestSessionStdoutPipe(t *testing.T) {
-       conn := dial(shellHandler, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-       stdout, err := session.StdoutPipe()
-       if err != nil {
-               t.Fatalf("Unable to request StdoutPipe(): %v", err)
-       }
-       var buf bytes.Buffer
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       done := make(chan bool, 1)
-       go func() {
-               if _, err := io.Copy(&buf, stdout); err != nil {
-                       t.Errorf("Copy of stdout failed: %v", err)
-               }
-               done <- true
-       }()
-       if err := session.Wait(); err != nil {
-               t.Fatalf("Remote command did not exit cleanly: %s", err)
-       }
-       <-done
-       actual := buf.String()
-       if actual != "golang" {
-               t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
-       }
-}
-
-// Test non-0 exit status is returned correctly.
-func TestExitStatusNonZero(t *testing.T) {
-       conn := dial(exitStatusNonZeroHandler, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       err = session.Wait()
-       if err == nil {
-               t.Fatalf("expected command to fail but it didn't")
-       }
-       e, ok := err.(*ExitError)
-       if !ok {
-               t.Fatalf("expected *ExitError but got %T", err)
-       }
-       if e.ExitStatus() != 15 {
-               t.Fatalf("expected command to exit with 15 but got %s", e.ExitStatus())
-       }
-}
-
-// Test 0 exit status is returned correctly.
-func TestExitStatusZero(t *testing.T) {
-       conn := dial(exitStatusZeroHandler, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       err = session.Wait()
-       if err != nil {
-               t.Fatalf("expected nil but got %s", err)
-       }
-}
-
-// Test exit signal and status are both returned correctly.
-func TestExitSignalAndStatus(t *testing.T) {
-       conn := dial(exitSignalAndStatusHandler, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       err = session.Wait()
-       if err == nil {
-               t.Fatalf("expected command to fail but it didn't")
-       }
-       e, ok := err.(*ExitError)
-       if !ok {
-               t.Fatalf("expected *ExitError but got %T", err)
-       }
-       if e.Signal() != "TERM" || e.ExitStatus() != 15 {
-               t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
-       }
-}
-
-// Test exit signal and status are both returned correctly.
-func TestKnownExitSignalOnly(t *testing.T) {
-       conn := dial(exitSignalHandler, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       err = session.Wait()
-       if err == nil {
-               t.Fatalf("expected command to fail but it didn't")
-       }
-       e, ok := err.(*ExitError)
-       if !ok {
-               t.Fatalf("expected *ExitError but got %T", err)
-       }
-       if e.Signal() != "TERM" || e.ExitStatus() != 143 {
-               t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
-       }
-}
-
-// Test exit signal and status are both returned correctly.
-func TestUnknownExitSignal(t *testing.T) {
-       conn := dial(exitSignalUnknownHandler, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       err = session.Wait()
-       if err == nil {
-               t.Fatalf("expected command to fail but it didn't")
-       }
-       e, ok := err.(*ExitError)
-       if !ok {
-               t.Fatalf("expected *ExitError but got %T", err)
-       }
-       if e.Signal() != "SYS" || e.ExitStatus() != 128 {
-               t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
-       }
-}
-
-// Test WaitMsg is not returned if the channel closes abruptly.
-func TestExitWithoutStatusOrSignal(t *testing.T) {
-       conn := dial(exitWithoutSignalOrStatus, t)
-       defer conn.Close()
-       session, err := conn.NewSession()
-       if err != nil {
-               t.Fatalf("Unable to request new session: %s", err)
-       }
-       defer session.Close()
-       if err := session.Shell(); err != nil {
-               t.Fatalf("Unable to execute command: %s", err)
-       }
-       err = session.Wait()
-       if err == nil {
-               t.Fatalf("expected command to fail but it didn't")
-       }
-       _, ok := err.(*ExitError)
-       if ok {
-               // you can't actually test for errors.errorString
-               // because it's not exported.
-               t.Fatalf("expected *errorString but got %T", err)
-       }
-}
-
-type exitStatusMsg struct {
-       PeersId   uint32
-       Request   string
-       WantReply bool
-       Status    uint32
-}
-
-type exitSignalMsg struct {
-       PeersId    uint32
-       Request    string
-       WantReply  bool
-       Signal     string
-       CoreDumped bool
-       Errmsg     string
-       Lang       string
-}
-
-func newServerShell(ch *channel, prompt string) *ServerTerminal {
-       term := terminal.NewTerminal(ch, prompt)
-       return &ServerTerminal{
-               Term:    term,
-               Channel: ch,
-       }
-}
-
-func exitStatusZeroHandler(ch *channel) {
-       defer ch.Close()
-       // this string is returned to stdout
-       shell := newServerShell(ch, "> ")
-       shell.ReadLine()
-       sendStatus(0, ch)
-}
-
-func exitStatusNonZeroHandler(ch *channel) {
-       defer ch.Close()
-       shell := newServerShell(ch, "> ")
-       shell.ReadLine()
-       sendStatus(15, ch)
-}
-
-func exitSignalAndStatusHandler(ch *channel) {
-       defer ch.Close()
-       shell := newServerShell(ch, "> ")
-       shell.ReadLine()
-       sendStatus(15, ch)
-       sendSignal("TERM", ch)
-}
-
-func exitSignalHandler(ch *channel) {
-       defer ch.Close()
-       shell := newServerShell(ch, "> ")
-       shell.ReadLine()
-       sendSignal("TERM", ch)
-}
-
-func exitSignalUnknownHandler(ch *channel) {
-       defer ch.Close()
-       shell := newServerShell(ch, "> ")
-       shell.ReadLine()
-       sendSignal("SYS", ch)
-}
-
-func exitWithoutSignalOrStatus(ch *channel) {
-       defer ch.Close()
-       shell := newServerShell(ch, "> ")
-       shell.ReadLine()
-}
-
-func shellHandler(ch *channel) {
-       defer ch.Close()
-       // this string is returned to stdout
-       shell := newServerShell(ch, "golang")
-       shell.ReadLine()
-       sendStatus(0, ch)
-}
-
-func sendStatus(status uint32, ch *channel) {
-       msg := exitStatusMsg{
-               PeersId:   ch.theirId,
-               Request:   "exit-status",
-               WantReply: false,
-               Status:    status,
-       }
-       ch.serverConn.writePacket(marshal(msgChannelRequest, msg))
-}
-
-func sendSignal(signal string, ch *channel) {
-       sig := exitSignalMsg{
-               PeersId:    ch.theirId,
-               Request:    "exit-signal",
-               WantReply:  false,
-               Signal:     signal,
-               CoreDumped: false,
-               Errmsg:     "Process terminated",
-               Lang:       "en-GB-oed",
-       }
-       ch.serverConn.writePacket(marshal(msgChannelRequest, sig))
-}
diff --git a/libgo/go/exp/ssh/tcpip.go b/libgo/go/exp/ssh/tcpip.go
deleted file mode 100644 (file)
index e0c47bc..0000000
+++ /dev/null
@@ -1,132 +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 ssh
-
-import (
-       "errors"
-       "fmt"
-       "io"
-       "net"
-       "time"
-)
-
-// Dial initiates a connection to the addr from the remote host.
-// addr is resolved using net.ResolveTCPAddr before connection. 
-// This could allow an observer to observe the DNS name of the 
-// remote host. Consider using ssh.DialTCP to avoid this.
-func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
-       raddr, err := net.ResolveTCPAddr(n, addr)
-       if err != nil {
-               return nil, err
-       }
-       return c.DialTCP(n, nil, raddr)
-}
-
-// DialTCP connects to the remote address raddr on the network net,
-// which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is used
-// as the local address for the connection.
-func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
-       if laddr == nil {
-               laddr = &net.TCPAddr{
-                       IP:   net.IPv4zero,
-                       Port: 0,
-               }
-       }
-       ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
-       if err != nil {
-               return nil, err
-       }
-       return &tcpchanconn{
-               tcpchan: ch,
-               laddr:   laddr,
-               raddr:   raddr,
-       }, nil
-}
-
-// RFC 4254 7.2
-type channelOpenDirectMsg struct {
-       ChanType      string
-       PeersId       uint32
-       PeersWindow   uint32
-       MaxPacketSize uint32
-       raddr         string
-       rport         uint32
-       laddr         string
-       lport         uint32
-}
-
-// dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
-// strings and are expected to be resolveable at the remote end.
-func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) {
-       ch := c.newChan(c.transport)
-       if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
-               ChanType:      "direct-tcpip",
-               PeersId:       ch.id,
-               PeersWindow:   1 << 14,
-               MaxPacketSize: 1 << 15, // RFC 4253 6.1
-               raddr:         raddr,
-               rport:         uint32(rport),
-               laddr:         laddr,
-               lport:         uint32(lport),
-       })); err != nil {
-               c.chanlist.remove(ch.id)
-               return nil, err
-       }
-       if err := ch.waitForChannelOpenResponse(); err != nil {
-               c.chanlist.remove(ch.id)
-               return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
-       }
-       return &tcpchan{
-               clientChan: ch,
-               Reader:     ch.stdout,
-               Writer:     ch.stdin,
-       }, nil
-}
-
-type tcpchan struct {
-       *clientChan // the backing channel
-       io.Reader
-       io.Writer
-}
-
-// tcpchanconn fulfills the net.Conn interface without 
-// the tcpchan having to hold laddr or raddr directly.
-type tcpchanconn struct {
-       *tcpchan
-       laddr, raddr net.Addr
-}
-
-// LocalAddr returns the local network address.
-func (t *tcpchanconn) LocalAddr() net.Addr {
-       return t.laddr
-}
-
-// RemoteAddr returns the remote network address.
-func (t *tcpchanconn) RemoteAddr() net.Addr {
-       return t.raddr
-}
-
-// SetDeadline sets the read and write deadlines associated
-// with the connection.
-func (t *tcpchanconn) SetDeadline(deadline time.Time) error {
-       if err := t.SetReadDeadline(deadline); err != nil {
-               return err
-       }
-       return t.SetWriteDeadline(deadline)
-}
-
-// SetReadDeadline sets the read deadline.
-// A zero value for t means Read will not time out.
-// After the deadline, the error from Read will implement net.Error
-// with Timeout() == true.
-func (t *tcpchanconn) SetReadDeadline(deadline time.Time) error {
-       return errors.New("ssh: tcpchan: deadline not supported")
-}
-
-// SetWriteDeadline exists to satisfy the net.Conn interface
-// but is not implemented by this type.  It always returns an error.
-func (t *tcpchanconn) SetWriteDeadline(deadline time.Time) error {
-       return errors.New("ssh: tcpchan: deadline not supported")
-}
diff --git a/libgo/go/exp/ssh/tcpip_func_test.go b/libgo/go/exp/ssh/tcpip_func_test.go
deleted file mode 100644 (file)
index 2612972..0000000
+++ /dev/null
@@ -1,59 +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 ssh
-
-// direct-tcpip functional tests
-
-import (
-       "net"
-       "net/http"
-       "testing"
-)
-
-func TestTCPIPHTTP(t *testing.T) {
-       if *sshuser == "" {
-               t.Log("ssh.user not defined, skipping test")
-               return
-       }
-       // google.com will generate at least one redirect, possibly three
-       // depending on your location.
-       doTest(t, "http://google.com")
-}
-
-func TestTCPIPHTTPS(t *testing.T) {
-       if *sshuser == "" {
-               t.Log("ssh.user not defined, skipping test")
-               return
-       }
-       doTest(t, "https://encrypted.google.com/")
-}
-
-func doTest(t *testing.T, url string) {
-       config := &ClientConfig{
-               User: *sshuser,
-               Auth: []ClientAuth{
-                       ClientAuthPassword(password(*sshpass)),
-               },
-       }
-       conn, err := Dial("tcp", "localhost:22", config)
-       if err != nil {
-               t.Fatalf("Unable to connect: %s", err)
-       }
-       defer conn.Close()
-       tr := &http.Transport{
-               Dial: func(n, addr string) (net.Conn, error) {
-                       return conn.Dial(n, addr)
-               },
-       }
-       client := &http.Client{
-               Transport: tr,
-       }
-       resp, err := client.Get(url)
-       if err != nil {
-               t.Fatalf("unable to proxy: %s", err)
-       }
-       // got a body without error
-       t.Log(resp)
-}
diff --git a/libgo/go/exp/ssh/transport.go b/libgo/go/exp/ssh/transport.go
deleted file mode 100644 (file)
index e21bc4b..0000000
+++ /dev/null
@@ -1,369 +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 ssh
-
-import (
-       "bufio"
-       "crypto"
-       "crypto/cipher"
-       "crypto/hmac"
-       "crypto/sha1"
-       "crypto/subtle"
-       "errors"
-       "hash"
-       "io"
-       "net"
-       "sync"
-)
-
-const (
-       packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
-       minPacketSize      = 16
-       maxPacketSize      = 36000
-       minPaddingSize     = 4 // TODO(huin) should this be configurable?
-)
-
-// filteredConn reduces the set of methods exposed when embeddeding
-// a net.Conn inside ssh.transport.
-// TODO(dfc) suggestions for a better name will be warmly received.
-type filteredConn interface {
-       // Close closes the connection.
-       Close() error
-
-       // LocalAddr returns the local network address.
-       LocalAddr() net.Addr
-
-       // RemoteAddr returns the remote network address.
-       RemoteAddr() net.Addr
-}
-
-// Types implementing packetWriter provide the ability to send packets to
-// an SSH peer.
-type packetWriter interface {
-       // Encrypt and send a packet of data to the remote peer.
-       writePacket(packet []byte) error
-}
-
-// transport represents the SSH connection to the remote peer.
-type transport struct {
-       reader
-       writer
-
-       filteredConn
-}
-
-// reader represents the incoming connection state.
-type reader struct {
-       io.Reader
-       common
-}
-
-// writer represnts the outgoing connection state.
-type writer struct {
-       *sync.Mutex // protects writer.Writer from concurrent writes
-       *bufio.Writer
-       rand io.Reader
-       common
-}
-
-// common represents the cipher state needed to process messages in a single
-// direction.
-type common struct {
-       seqNum uint32
-       mac    hash.Hash
-       cipher cipher.Stream
-
-       cipherAlgo      string
-       macAlgo         string
-       compressionAlgo string
-}
-
-// Read and decrypt a single packet from the remote peer.
-func (r *reader) readOnePacket() ([]byte, error) {
-       var lengthBytes = make([]byte, 5)
-       var macSize uint32
-       if _, err := io.ReadFull(r, lengthBytes); err != nil {
-               return nil, err
-       }
-
-       r.cipher.XORKeyStream(lengthBytes, lengthBytes)
-
-       if r.mac != nil {
-               r.mac.Reset()
-               seqNumBytes := []byte{
-                       byte(r.seqNum >> 24),
-                       byte(r.seqNum >> 16),
-                       byte(r.seqNum >> 8),
-                       byte(r.seqNum),
-               }
-               r.mac.Write(seqNumBytes)
-               r.mac.Write(lengthBytes)
-               macSize = uint32(r.mac.Size())
-       }
-
-       length := uint32(lengthBytes[0])<<24 | uint32(lengthBytes[1])<<16 | uint32(lengthBytes[2])<<8 | uint32(lengthBytes[3])
-       paddingLength := uint32(lengthBytes[4])
-
-       if length <= paddingLength+1 {
-               return nil, errors.New("invalid packet length")
-       }
-       if length > maxPacketSize {
-               return nil, errors.New("packet too large")
-       }
-
-       packet := make([]byte, length-1+macSize)
-       if _, err := io.ReadFull(r, packet); err != nil {
-               return nil, err
-       }
-       mac := packet[length-1:]
-       r.cipher.XORKeyStream(packet, packet[:length-1])
-
-       if r.mac != nil {
-               r.mac.Write(packet[:length-1])
-               if subtle.ConstantTimeCompare(r.mac.Sum(nil), mac) != 1 {
-                       return nil, errors.New("ssh: MAC failure")
-               }
-       }
-
-       r.seqNum++
-       return packet[:length-paddingLength-1], nil
-}
-
-// Read and decrypt next packet discarding debug and noop messages.
-func (t *transport) readPacket() ([]byte, error) {
-       for {
-               packet, err := t.readOnePacket()
-               if err != nil {
-                       return nil, err
-               }
-               if packet[0] != msgIgnore && packet[0] != msgDebug {
-                       return packet, nil
-               }
-       }
-       panic("unreachable")
-}
-
-// Encrypt and send a packet of data to the remote peer.
-func (w *writer) writePacket(packet []byte) error {
-       w.Mutex.Lock()
-       defer w.Mutex.Unlock()
-
-       paddingLength := packetSizeMultiple - (5+len(packet))%packetSizeMultiple
-       if paddingLength < 4 {
-               paddingLength += packetSizeMultiple
-       }
-
-       length := len(packet) + 1 + paddingLength
-       lengthBytes := []byte{
-               byte(length >> 24),
-               byte(length >> 16),
-               byte(length >> 8),
-               byte(length),
-               byte(paddingLength),
-       }
-       padding := make([]byte, paddingLength)
-       _, err := io.ReadFull(w.rand, padding)
-       if err != nil {
-               return err
-       }
-
-       if w.mac != nil {
-               w.mac.Reset()
-               seqNumBytes := []byte{
-                       byte(w.seqNum >> 24),
-                       byte(w.seqNum >> 16),
-                       byte(w.seqNum >> 8),
-                       byte(w.seqNum),
-               }
-               w.mac.Write(seqNumBytes)
-               w.mac.Write(lengthBytes)
-               w.mac.Write(packet)
-               w.mac.Write(padding)
-       }
-
-       // TODO(dfc) lengthBytes, packet and padding should be
-       // subslices of a single buffer
-       w.cipher.XORKeyStream(lengthBytes, lengthBytes)
-       w.cipher.XORKeyStream(packet, packet)
-       w.cipher.XORKeyStream(padding, padding)
-
-       if _, err := w.Write(lengthBytes); err != nil {
-               return err
-       }
-       if _, err := w.Write(packet); err != nil {
-               return err
-       }
-       if _, err := w.Write(padding); err != nil {
-               return err
-       }
-
-       if w.mac != nil {
-               if _, err := w.Write(w.mac.Sum(nil)); err != nil {
-                       return err
-               }
-       }
-
-       if err := w.Flush(); err != nil {
-               return err
-       }
-       w.seqNum++
-       return err
-}
-
-// Send a message to the remote peer
-func (t *transport) sendMessage(typ uint8, msg interface{}) error {
-       packet := marshal(typ, msg)
-       return t.writePacket(packet)
-}
-
-func newTransport(conn net.Conn, rand io.Reader) *transport {
-       return &transport{
-               reader: reader{
-                       Reader: bufio.NewReader(conn),
-                       common: common{
-                               cipher: noneCipher{},
-                       },
-               },
-               writer: writer{
-                       Writer: bufio.NewWriter(conn),
-                       rand:   rand,
-                       Mutex:  new(sync.Mutex),
-                       common: common{
-                               cipher: noneCipher{},
-                       },
-               },
-               filteredConn: conn,
-       }
-}
-
-type direction struct {
-       ivTag     []byte
-       keyTag    []byte
-       macKeyTag []byte
-}
-
-// TODO(dfc) can this be made a constant ?
-var (
-       serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
-       clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
-)
-
-// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
-// described in RFC 4253, section 6.4. direction should either be serverKeys
-// (to setup server->client keys) or clientKeys (for client->server keys).
-func (c *common) setupKeys(d direction, K, H, sessionId []byte, hashFunc crypto.Hash) error {
-       cipherMode := cipherModes[c.cipherAlgo]
-
-       macKeySize := 20
-
-       iv := make([]byte, cipherMode.ivSize)
-       key := make([]byte, cipherMode.keySize)
-       macKey := make([]byte, macKeySize)
-
-       h := hashFunc.New()
-       generateKeyMaterial(iv, d.ivTag, K, H, sessionId, h)
-       generateKeyMaterial(key, d.keyTag, K, H, sessionId, h)
-       generateKeyMaterial(macKey, d.macKeyTag, K, H, sessionId, h)
-
-       c.mac = truncatingMAC{12, hmac.New(sha1.New, macKey)}
-
-       cipher, err := cipherMode.createCipher(key, iv)
-       if err != nil {
-               return err
-       }
-
-       c.cipher = cipher
-
-       return nil
-}
-
-// generateKeyMaterial fills out with key material generated from tag, K, H
-// and sessionId, as specified in RFC 4253, section 7.2.
-func generateKeyMaterial(out, tag []byte, K, H, sessionId []byte, h hash.Hash) {
-       var digestsSoFar []byte
-
-       for len(out) > 0 {
-               h.Reset()
-               h.Write(K)
-               h.Write(H)
-
-               if len(digestsSoFar) == 0 {
-                       h.Write(tag)
-                       h.Write(sessionId)
-               } else {
-                       h.Write(digestsSoFar)
-               }
-
-               digest := h.Sum(nil)
-               n := copy(out, digest)
-               out = out[n:]
-               if len(out) > 0 {
-                       digestsSoFar = append(digestsSoFar, digest...)
-               }
-       }
-}
-
-// truncatingMAC wraps around a hash.Hash and truncates the output digest to
-// a given size.
-type truncatingMAC struct {
-       length int
-       hmac   hash.Hash
-}
-
-func (t truncatingMAC) Write(data []byte) (int, error) {
-       return t.hmac.Write(data)
-}
-
-func (t truncatingMAC) Sum(in []byte) []byte {
-       out := t.hmac.Sum(in)
-       return out[:len(in)+t.length]
-}
-
-func (t truncatingMAC) Reset() {
-       t.hmac.Reset()
-}
-
-func (t truncatingMAC) Size() int {
-       return t.length
-}
-
-func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
-
-// maxVersionStringBytes is the maximum number of bytes that we'll accept as a
-// version string. In the event that the client is talking a different protocol
-// we need to set a limit otherwise we will keep using more and more memory
-// while searching for the end of the version handshake.
-const maxVersionStringBytes = 1024
-
-// Read version string as specified by RFC 4253, section 4.2.
-func readVersion(r io.Reader) ([]byte, error) {
-       versionString := make([]byte, 0, 64)
-       var ok bool
-       var buf [1]byte
-forEachByte:
-       for len(versionString) < maxVersionStringBytes {
-               _, err := io.ReadFull(r, buf[:])
-               if err != nil {
-                       return nil, err
-               }
-               // The RFC says that the version should be terminated with \r\n
-               // but several SSH servers actually only send a \n.
-               if buf[0] == '\n' {
-                       ok = true
-                       break forEachByte
-               }
-               versionString = append(versionString, buf[0])
-       }
-
-       if !ok {
-               return nil, errors.New("ssh: failed to read version string")
-       }
-
-       // There might be a '\r' on the end which we should remove.
-       if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' {
-               versionString = versionString[:len(versionString)-1]
-       }
-       return versionString, nil
-}
diff --git a/libgo/go/exp/ssh/transport_test.go b/libgo/go/exp/ssh/transport_test.go
deleted file mode 100644 (file)
index ab9177f..0000000
+++ /dev/null
@@ -1,51 +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 ssh
-
-import (
-       "bufio"
-       "bytes"
-       "testing"
-)
-
-func TestReadVersion(t *testing.T) {
-       buf := serverVersion
-       result, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf)))
-       if err != nil {
-               t.Errorf("readVersion didn't read version correctly: %s", err)
-       }
-       if !bytes.Equal(buf[:len(buf)-2], result) {
-               t.Error("version read did not match expected")
-       }
-}
-
-func TestReadVersionWithJustLF(t *testing.T) {
-       var buf []byte
-       buf = append(buf, serverVersion...)
-       buf = buf[:len(buf)-1]
-       buf[len(buf)-1] = '\n'
-       result, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf)))
-       if err != nil {
-               t.Error("readVersion failed to handle just a \n")
-       }
-       if !bytes.Equal(buf[:len(buf)-1], result) {
-               t.Errorf("version read did not match expected: got %x, want %x", result, buf[:len(buf)-1])
-       }
-}
-
-func TestReadVersionTooLong(t *testing.T) {
-       buf := make([]byte, maxVersionStringBytes+1)
-       if _, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); err == nil {
-               t.Errorf("readVersion consumed %d bytes without error", len(buf))
-       }
-}
-
-func TestReadVersionWithoutCRLF(t *testing.T) {
-       buf := serverVersion
-       buf = buf[:len(buf)-1]
-       if _, err := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); err == nil {
-               t.Error("readVersion did not notice \\n was missing")
-       }
-}
index 894fecdaa7e8dd4ffea9dee9e90666ee87ea3d8d..2d4f69aaea6ca0c1776e509006a665ea8d89f51b 100644 (file)
@@ -67,12 +67,7 @@ func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
        // Record positions for specs.
        pos := make([]posSpan, len(specs))
        for i, s := range specs {
-               // Cannot use s.End(), because it looks at len(s.Path.Value),
-               // and that string might have gotten longer or shorter.
-               // Instead, use s.Pos()+1, which is guaranteed to be > s.Pos()
-               // and still before the original end of the string, since any
-               // string literal must be at least 2 characters ("" or ``).
-               pos[i] = posSpan{s.Pos(), s.Pos() + 1}
+               pos[i] = posSpan{s.Pos(), s.End()}
        }
 
        // Identify comments in this range.
index 9515a7e645224f41d032ad227e0ff4e4cf89ad1f..68e8d34200530753b76c4880a447cd7e9e66dcd8 100644 (file)
@@ -5,245 +5,7 @@
 // Package build provides tools for building Go packages.
 package build
 
-import (
-       "bytes"
-       "errors"
-       "fmt"
-       "os"
-       "os/exec"
-       "path/filepath"
-       "regexp"
-       "runtime"
-       "strings"
-       "time"
-)
-
-// Build produces a build Script for the given package.
-func Build(tree *Tree, pkg string, info *DirInfo) (*Script, error) {
-       s := &Script{}
-       b := &build{
-               script: s,
-               path:   filepath.Join(tree.SrcDir(), pkg),
-       }
-       b.obj = b.abs("_obj") + string(filepath.Separator)
-
-       b.goarch = runtime.GOARCH
-       if g := os.Getenv("GOARCH"); g != "" {
-               b.goarch = g
-       }
-       var err error
-       b.arch, err = ArchChar(b.goarch)
-       if err != nil {
-               return nil, err
-       }
-
-       // add import object files to list of Inputs
-       for _, pkg := range info.Imports {
-               t, p, err := FindTree(pkg)
-               if err != nil && err != ErrNotFound {
-                       // FindTree should always be able to suggest an import
-                       // path and tree. The path must be malformed
-                       // (for example, an absolute or relative path).
-                       return nil, errors.New("build: invalid import: " + pkg)
-               }
-               s.addInput(filepath.Join(t.PkgDir(), p+".a"))
-       }
-
-       // .go files to be built with gc
-       gofiles := b.abss(info.GoFiles...)
-       s.addInput(gofiles...)
-
-       var ofiles []string // object files to be linked or packed
-
-       // make build directory
-       b.mkdir(b.obj)
-       s.addIntermediate(b.obj)
-
-       // cgo
-       if len(info.CgoFiles) > 0 {
-               cgoFiles := b.abss(info.CgoFiles...)
-               s.addInput(cgoFiles...)
-               cgoCFiles := b.abss(info.CFiles...)
-               s.addInput(cgoCFiles...)
-               outGo, outObj := b.cgo(cgoFiles, cgoCFiles)
-               gofiles = append(gofiles, outGo...)
-               ofiles = append(ofiles, outObj...)
-               s.addIntermediate(outGo...)
-               s.addIntermediate(outObj...)
-       }
-
-       // compile
-       if len(gofiles) > 0 {
-               ofile := b.obj + "_go_." + b.arch
-               b.gc(ofile, gofiles...)
-               ofiles = append(ofiles, ofile)
-               s.addIntermediate(ofile)
-       }
-
-       // assemble
-       for _, sfile := range info.SFiles {
-               ofile := b.obj + sfile[:len(sfile)-1] + b.arch
-               sfile = b.abs(sfile)
-               s.addInput(sfile)
-               b.asm(ofile, sfile)
-               ofiles = append(ofiles, ofile)
-               s.addIntermediate(ofile)
-       }
-
-       if len(ofiles) == 0 {
-               return nil, errors.New("make: no object files to build")
-       }
-
-       // choose target file
-       var targ string
-       if info.IsCommand() {
-               // use the last part of the import path as binary name
-               _, bin := filepath.Split(pkg)
-               if runtime.GOOS == "windows" {
-                       bin += ".exe"
-               }
-               targ = filepath.Join(tree.BinDir(), bin)
-       } else {
-               targ = filepath.Join(tree.PkgDir(), pkg+".a")
-       }
-
-       // make target directory
-       targDir, _ := filepath.Split(targ)
-       b.mkdir(targDir)
-
-       // link binary or pack object
-       if info.IsCommand() {
-               b.ld(targ, ofiles...)
-       } else {
-               b.gopack(targ, ofiles...)
-       }
-       s.Output = append(s.Output, targ)
-
-       return b.script, nil
-}
-
-// A Script describes the build process for a Go package.
-// The Input, Intermediate, and Output fields are lists of absolute paths.
-type Script struct {
-       Cmd          []*Cmd
-       Input        []string
-       Intermediate []string
-       Output       []string
-}
-
-func (s *Script) addInput(file ...string) {
-       s.Input = append(s.Input, file...)
-}
-
-func (s *Script) addIntermediate(file ...string) {
-       s.Intermediate = append(s.Intermediate, file...)
-}
-
-// Run runs the Script's Cmds in order.
-func (s *Script) Run() error {
-       for _, c := range s.Cmd {
-               if err := c.Run(); err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-// Stale returns true if the build's inputs are newer than its outputs.
-func (s *Script) Stale() bool {
-       var latest time.Time
-       // get latest mtime of outputs
-       for _, file := range s.Output {
-               fi, err := os.Stat(file)
-               if err != nil {
-                       // any error reading output files means stale
-                       return true
-               }
-               if mtime := fi.ModTime(); mtime.After(latest) {
-                       latest = mtime
-               }
-       }
-       for _, file := range s.Input {
-               fi, err := os.Stat(file)
-               if err != nil || fi.ModTime().After(latest) {
-                       // any error reading input files means stale
-                       // (attempt to rebuild to figure out why)
-                       return true
-               }
-       }
-       return false
-}
-
-// Clean removes the Script's Intermediate files.
-// It tries to remove every file and returns the first error it encounters.
-func (s *Script) Clean() (err error) {
-       // Reverse order so that directories get removed after the files they contain.
-       for i := len(s.Intermediate) - 1; i >= 0; i-- {
-               if e := os.Remove(s.Intermediate[i]); err == nil {
-                       err = e
-               }
-       }
-       return
-}
-
-// Nuke removes the Script's Intermediate and Output files.
-// It tries to remove every file and returns the first error it encounters.
-func (s *Script) Nuke() (err error) {
-       // Reverse order so that directories get removed after the files they contain.
-       for i := len(s.Output) - 1; i >= 0; i-- {
-               if e := os.Remove(s.Output[i]); err == nil {
-                       err = e
-               }
-       }
-       if e := s.Clean(); err == nil {
-               err = e
-       }
-       return
-}
-
-// A Cmd describes an individual build command.
-type Cmd struct {
-       Args   []string // command-line
-       Stdout string   // write standard output to this file, "" is passthrough
-       Dir    string   // working directory
-       Env    []string // environment
-       Input  []string // file paths (dependencies)
-       Output []string // file paths
-}
-
-func (c *Cmd) String() string {
-       return strings.Join(c.Args, " ")
-}
-
-// Run executes the Cmd.
-func (c *Cmd) Run() error {
-       if c.Args[0] == "mkdir" {
-               for _, p := range c.Output {
-                       if err := os.MkdirAll(p, 0777); err != nil {
-                               return fmt.Errorf("command %q: %v", c, err)
-                       }
-               }
-               return nil
-       }
-       out := new(bytes.Buffer)
-       cmd := exec.Command(c.Args[0], c.Args[1:]...)
-       cmd.Dir = c.Dir
-       cmd.Env = c.Env
-       cmd.Stdout = out
-       cmd.Stderr = out
-       if c.Stdout != "" {
-               f, err := os.Create(c.Stdout)
-               if err != nil {
-                       return err
-               }
-               defer f.Close()
-               cmd.Stdout = f
-       }
-       if err := cmd.Run(); err != nil {
-               return fmt.Errorf("command %q: %v\n%v", c, err, out)
-       }
-       return nil
-}
+import "errors"
 
 // ArchChar returns the architecture character for the given goarch.
 // For example, ArchChar("amd64") returns "6".
@@ -258,188 +20,3 @@ func ArchChar(goarch string) (string, error) {
        }
        return "", errors.New("unsupported GOARCH " + goarch)
 }
-
-type build struct {
-       script *Script
-       path   string
-       obj    string
-       goarch string
-       arch   string
-}
-
-func (b *build) abs(file string) string {
-       if filepath.IsAbs(file) {
-               return file
-       }
-       return filepath.Join(b.path, file)
-}
-
-func (b *build) abss(file ...string) []string {
-       s := make([]string, len(file))
-       for i, f := range file {
-               s[i] = b.abs(f)
-       }
-       return s
-}
-
-func (b *build) add(c Cmd) {
-       b.script.Cmd = append(b.script.Cmd, &c)
-}
-
-func (b *build) mkdir(name string) {
-       b.add(Cmd{
-               Args:   []string{"mkdir", "-p", name},
-               Output: []string{name},
-       })
-}
-
-func (b *build) gc(ofile string, gofiles ...string) {
-       gc := b.arch + "g"
-       args := append([]string{gc, "-o", ofile}, gcImportArgs...)
-       args = append(args, gofiles...)
-       b.add(Cmd{
-               Args:   args,
-               Input:  gofiles,
-               Output: []string{ofile},
-       })
-}
-
-func (b *build) asm(ofile string, sfile string) {
-       asm := b.arch + "a"
-       b.add(Cmd{
-               Args:   []string{asm, "-o", ofile, sfile},
-               Input:  []string{sfile},
-               Output: []string{ofile},
-       })
-}
-
-func (b *build) ld(targ string, ofiles ...string) {
-       ld := b.arch + "l"
-       args := append([]string{ld, "-o", targ}, ldImportArgs...)
-       args = append(args, ofiles...)
-       b.add(Cmd{
-               Args:   args,
-               Input:  ofiles,
-               Output: []string{targ},
-       })
-}
-
-func (b *build) gopack(targ string, ofiles ...string) {
-       b.add(Cmd{
-               Args:   append([]string{"gopack", "grc", targ}, ofiles...),
-               Input:  ofiles,
-               Output: []string{targ},
-       })
-}
-
-func (b *build) cc(ofile string, cfiles ...string) {
-       cc := b.arch + "c"
-       dir := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
-       inc := filepath.Join(runtime.GOROOT(), "pkg", dir)
-       args := []string{cc, "-FVw", "-I", inc, "-o", ofile}
-       b.add(Cmd{
-               Args:   append(args, cfiles...),
-               Input:  cfiles,
-               Output: []string{ofile},
-       })
-}
-
-func (b *build) gccCompile(ofile, cfile string) {
-       b.add(Cmd{
-               Args:   b.gccArgs("-o", ofile, "-c", cfile),
-               Input:  []string{cfile},
-               Output: []string{ofile},
-       })
-}
-
-func (b *build) gccLink(ofile string, ofiles ...string) {
-       b.add(Cmd{
-               Args:   append(b.gccArgs("-o", ofile), ofiles...),
-               Input:  ofiles,
-               Output: []string{ofile},
-       })
-}
-
-func (b *build) gccArgs(args ...string) []string {
-       // TODO(adg): HOST_CC
-       a := []string{"gcc", "-I", b.path, "-g", "-fPIC", "-O2"}
-       switch b.arch {
-       case "8":
-               a = append(a, "-m32")
-       case "6":
-               a = append(a, "-m64")
-       }
-       return append(a, args...)
-}
-
-var cgoRe = regexp.MustCompile(`[/\\:]`)
-
-func (b *build) cgo(cgofiles, cgocfiles []string) (outGo, outObj []string) {
-       // cgo
-       // TODO(adg): CGOPKGPATH
-       // TODO(adg): CGO_FLAGS
-       gofiles := []string{b.obj + "_cgo_gotypes.go"}
-       cfiles := []string{b.obj + "_cgo_main.c", b.obj + "_cgo_export.c"}
-       for _, fn := range cgofiles {
-               f := b.obj + cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
-               gofiles = append(gofiles, f+"cgo1.go")
-               cfiles = append(cfiles, f+"cgo2.c")
-       }
-       defunC := b.obj + "_cgo_defun.c"
-       output := append([]string{defunC}, cfiles...)
-       output = append(output, gofiles...)
-       b.add(Cmd{
-               Args:   append([]string{"cgo", "--"}, cgofiles...),
-               Dir:    b.path,
-               Env:    append(os.Environ(), "GOARCH="+b.goarch),
-               Input:  cgofiles,
-               Output: output,
-       })
-       outGo = append(outGo, gofiles...)
-       b.script.addIntermediate(defunC, b.obj+"_cgo_export.h", b.obj+"_cgo_flags")
-       b.script.addIntermediate(cfiles...)
-
-       // cc _cgo_defun.c
-       defunObj := b.obj + "_cgo_defun." + b.arch
-       b.cc(defunObj, defunC)
-       outObj = append(outObj, defunObj)
-
-       // gcc
-       linkobj := make([]string, 0, len(cfiles))
-       for _, cfile := range cfiles {
-               ofile := cfile[:len(cfile)-1] + "o"
-               b.gccCompile(ofile, cfile)
-               linkobj = append(linkobj, ofile)
-               if !strings.HasSuffix(ofile, "_cgo_main.o") {
-                       outObj = append(outObj, ofile)
-               } else {
-                       b.script.addIntermediate(ofile)
-               }
-       }
-       for _, cfile := range cgocfiles {
-               ofile := b.obj + cgoRe.ReplaceAllString(cfile[:len(cfile)-1], "_") + "o"
-               b.gccCompile(ofile, cfile)
-               linkobj = append(linkobj, ofile)
-               outObj = append(outObj, ofile)
-       }
-       dynObj := b.obj + "_cgo_.o"
-       b.gccLink(dynObj, linkobj...)
-       b.script.addIntermediate(dynObj)
-
-       // cgo -dynimport
-       importC := b.obj + "_cgo_import.c"
-       b.add(Cmd{
-               Args:   []string{"cgo", "-dynimport", dynObj},
-               Stdout: importC,
-               Input:  []string{dynObj},
-               Output: []string{importC},
-       })
-       b.script.addIntermediate(importC)
-
-       // cc _cgo_import.ARCH
-       importObj := b.obj + "_cgo_import." + b.arch
-       b.cc(importObj, importC)
-       outObj = append(outObj, importObj)
-
-       return
-}
index fd4030632a9d8dc77cc9e898fdc6d3ef1f756501..381e2b2d96a2ab433ab30244e660606613911075 100644 (file)
@@ -5,7 +5,6 @@
 package build
 
 import (
-       "os/exec"
        "path/filepath"
        "reflect"
        "runtime"
@@ -63,8 +62,6 @@ func ifCgo(x []string) []string {
        return nil
 }
 
-const cmdtestOutput = "3"
-
 func TestBuild(t *testing.T) {
        for _, tt := range buildPkgs {
                tree := Path[0] // Goroot
@@ -78,39 +75,32 @@ func TestBuild(t *testing.T) {
                        t.Errorf("ScanDir(%#q) = %#v, want %#v\n", tt.dir, info, tt.info)
                        continue
                }
+       }
+}
 
-               if tt.dir == "go/build/cgotest" && len(info.CgoFiles) == 0 {
-                       continue
-               }
-
-               s, err := Build(tree, tt.dir, info)
-               if err != nil {
-                       t.Errorf("Build(%#q): %v", tt.dir, err)
-                       continue
+func TestMatch(t *testing.T) {
+       ctxt := DefaultContext
+       what := "default"
+       match := func(tag string) {
+               if !ctxt.match(tag) {
+                       t.Errorf("%s context should match %s, does not", what, tag)
                }
-
-               if err := s.Run(); err != nil {
-                       t.Errorf("Run(%#q): %v", tt.dir, err)
-                       continue
+       }
+       nomatch := func(tag string) {
+               if ctxt.match(tag) {
+                       t.Errorf("%s context should NOT match %s, does", what, tag)
                }
+       }
 
-               if tt.dir == "go/build/cmdtest" {
-                       bin := s.Output[0]
-                       b, err := exec.Command(bin).CombinedOutput()
-                       if err != nil {
-                               t.Errorf("exec %s: %v", bin, err)
-                               continue
-                       }
-                       if string(b) != cmdtestOutput {
-                               t.Errorf("cmdtest output: %s want: %s", b, cmdtestOutput)
-                       }
-               }
+       match(runtime.GOOS + "," + runtime.GOARCH)
+       match(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
+       nomatch(runtime.GOOS + "," + runtime.GOARCH + ",foo")
 
-               // Deferred because cmdtest depends on pkgtest.
-               defer func(s *Script) {
-                       if err := s.Nuke(); err != nil {
-                               t.Errorf("nuking: %v", err)
-                       }
-               }(s)
-       }
+       what = "modified"
+       ctxt.BuildTags = []string{"foo"}
+       match(runtime.GOOS + "," + runtime.GOARCH)
+       match(runtime.GOOS + "," + runtime.GOARCH + ",foo")
+       nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
+       match(runtime.GOOS + "," + runtime.GOARCH + ",!bar")
+       nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar")
 }
index 5ce75fda7e08d38e5f9afdd2359484bef8cfea7d..d49846f7d4dea114305d2a2da713509e85dcf6cd 100644 (file)
@@ -25,9 +25,10 @@ import (
 
 // A Context specifies the supporting context for a build.
 type Context struct {
-       GOARCH     string // target architecture
-       GOOS       string // target operating system
-       CgoEnabled bool   // whether cgo can be used
+       GOARCH     string   // target architecture
+       GOOS       string   // target operating system
+       CgoEnabled bool     // whether cgo can be used
+       BuildTags  []string // additional tags to recognize in +build lines
 
        // By default, ScanDir uses the operating system's
        // file system calls to read directories and files.
@@ -74,7 +75,7 @@ func (ctxt *Context) readFile(dir, file string) (string, []byte, error) {
 // The DefaultContext is the default Context for builds.
 // It uses the GOARCH and GOOS environment variables
 // if set, or else the compiled code's GOARCH and GOOS.
-var DefaultContext = defaultContext()
+var DefaultContext Context = defaultContext()
 
 var cgoEnabled = map[string]bool{
        "darwin/386":    true,
@@ -121,7 +122,7 @@ type DirInfo struct {
        Imports        []string          // All packages imported by GoFiles
 
        // Source files
-       GoFiles  []string // .go files in dir (excluding CgoFiles)
+       GoFiles  []string // .go files in dir (excluding CgoFiles, TestGoFiles, XTestGoFiles)
        HFiles   []string // .h files in dir
        CFiles   []string // .c files in dir
        SFiles   []string // .s (and, when using cgo, .S files in dir)
@@ -148,13 +149,71 @@ func ScanDir(dir string) (info *DirInfo, err error) {
        return DefaultContext.ScanDir(dir)
 }
 
-// ScanDir returns a structure with details about the Go content found
-// in the given directory. The file lists exclude:
+// TODO(rsc): Move this comment to a more appropriate place.
+
+// ScanDir returns a structure with details about the Go package
+// found in the given directory.
+//
+// Most .go, .c, .h, and .s files in the directory are considered part
+// of the package.  The exceptions are:
 //
-//     - files in package main (unless no other package is found)
-//     - files in package documentation
-//     - files ending in _test.go
+//     - .go files in package main (unless no other package is found)
+//     - .go files in package documentation
 //     - files starting with _ or .
+//     - files with build constraints not satisfied by the context
+//
+// Build Constraints
+//
+// A build constraint is a line comment beginning with the directive +build
+// that lists the conditions under which a file should be included in the package.
+// Constraints may appear in any kind of source file (not just Go), but
+// they must be appear near the top of the file, preceded
+// only by blank lines and other line comments.
+//
+// A build constraint is evaluated as the OR of space-separated options;
+// each option evaluates as the AND of its comma-separated terms;
+// and each term is an alphanumeric word or, preceded by !, its negation.
+// That is, the build constraint:
+//
+//     // +build linux,386 darwin,!cgo
+//
+// corresponds to the boolean formula:
+//
+//     (linux AND 386) OR (darwin AND (NOT cgo))
+//
+// During a particular build, the following words are satisfied:
+//
+//     - the target operating system, as spelled by runtime.GOOS
+//     - the target architecture, as spelled by runtime.GOARCH
+//     - "cgo", if ctxt.CgoEnabled is true
+//     - any additional words listed in ctxt.BuildTags
+//
+// If a file's name, after stripping the extension and a possible _test suffix,
+// matches *_GOOS, *_GOARCH, or *_GOOS_GOARCH for any known operating
+// system and architecture values, then the file is considered to have an implicit
+// build constraint requiring those terms.
+//
+// Examples
+//
+// To keep a file from being considered for the build:
+//
+//     // +build ignore
+//
+// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
+//
+// To build a file only when using cgo, and only on Linux and OS X:
+//
+//     // +build linux,cgo darwin,cgo
+// 
+// Such a file is usually paired with another file implementing the
+// default functionality for other systems, which in this case would
+// carry the constraint:
+//
+//     // +build !linux !darwin !cgo
+//
+// Naming a file dns_windows.go will cause it to be included only when
+// building the package for Windows; similarly, math_386.s will be included
+// only when building the package for 32-bit x86.
 //
 func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err error) {
        dirs, err := ctxt.readDir(dir)
@@ -389,7 +448,7 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
                                if f[0] == "+build" {
                                        ok := false
                                        for _, tok := range f[1:] {
-                                               if ctxt.matchOSArch(tok) {
+                                               if ctxt.match(tok) {
                                                        ok = true
                                                        break
                                                }
@@ -441,7 +500,7 @@ func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup)
                if len(cond) > 0 {
                        ok := false
                        for _, c := range cond {
-                               if ctxt.matchOSArch(c) {
+                               if ctxt.match(c) {
                                        ok = true
                                        break
                                }
@@ -550,26 +609,55 @@ func splitQuoted(s string) (r []string, err error) {
        return args, err
 }
 
-// matchOSArch returns true if the name is one of:
+// match returns true if the name is one of:
 //
 //     $GOOS
 //     $GOARCH
 //     cgo (if cgo is enabled)
-//     nocgo (if cgo is disabled)
+//     !cgo (if cgo is disabled)
+//     tag (if tag is listed in ctxt.BuildTags)
+//     !tag (if tag is not listed in ctxt.BuildTags)
 //     a slash-separated list of any of these
 //
-func (ctxt *Context) matchOSArch(name string) bool {
-       if ctxt.CgoEnabled && name == "cgo" {
-               return true
+func (ctxt *Context) match(name string) bool {
+       if name == "" {
+               return false
+       }
+       if i := strings.Index(name, ","); i >= 0 {
+               // comma-separated list
+               return ctxt.match(name[:i]) && ctxt.match(name[i+1:])
+       }
+       if strings.HasPrefix(name, "!!") { // bad syntax, reject always
+               return false
+       }
+       if strings.HasPrefix(name, "!") { // negation
+               return !ctxt.match(name[1:])
+       }
+
+       // Tags must be letters, digits, underscores.
+       // Unlike in Go identifiers, all digits is fine (e.g., "386").
+       for _, c := range name {
+               if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
+                       return false
+               }
        }
-       if !ctxt.CgoEnabled && name == "nocgo" {
+
+       // special tags
+       if ctxt.CgoEnabled && name == "cgo" {
                return true
        }
        if name == ctxt.GOOS || name == ctxt.GOARCH {
                return true
        }
-       i := strings.Index(name, "/")
-       return i >= 0 && ctxt.matchOSArch(name[:i]) && ctxt.matchOSArch(name[i+1:])
+
+       // other tags
+       for _, tag := range ctxt.BuildTags {
+               if tag == name {
+                       return true
+               }
+       }
+
+       return false
 }
 
 // goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
index b86f8288ea6d9527a6b59688d8d12e06821f4dd5..7e931faff1926a43f36044f9ff8cde7aee6cc919 100644 (file)
@@ -7,7 +7,6 @@ package build
 import (
        "errors"
        "fmt"
-       "log"
        "os"
        "path/filepath"
        "runtime"
@@ -81,7 +80,6 @@ func (t *Tree) HasPkg(pkg string) bool {
                return false
        }
        return !fi.IsDir()
-       // TODO(adg): check object version is consistent
 }
 
 var (
@@ -150,38 +148,20 @@ var (
 func init() {
        root := runtime.GOROOT()
        t, err := newTree(root)
-       if err != nil {
-               log.Printf("invalid GOROOT %q: %v", root, err)
-       } else {
+       if err == nil {
                t.Goroot = true
                Path = []*Tree{t}
        }
 
-Loop:
        for _, p := range filepath.SplitList(os.Getenv("GOPATH")) {
                if p == "" {
                        continue
                }
                t, err := newTree(p)
                if err != nil {
-                       log.Printf("invalid GOPATH %q: %v", p, err)
                        continue
                }
 
-               // Check for dupes.
-               // TODO(alexbrainman): make this correct under windows (case insensitive).
-               for _, t2 := range Path {
-                       if t2.Path != t.Path {
-                               continue
-                       }
-                       if t2.Goroot {
-                               log.Printf("GOPATH is the same as GOROOT: %q", t.Path)
-                       } else {
-                               log.Printf("duplicate GOPATH entry: %q", t.Path)
-                       }
-                       continue Loop
-               }
-
                Path = append(Path, t)
                gcImportArgs = append(gcImportArgs, "-I", t.PkgDir())
                ldImportArgs = append(ldImportArgs, "-L", t.PkgDir())
index 0259a6fec9c5929c9eb07e4702175e76ba8867e2..d4aae8ff05c27a9bbc3410aaa4649bd35235f6e3 100644 (file)
@@ -7,7 +7,7 @@ package doc
 
 import (
        "go/ast"
-       "sort"
+       "go/token"
 )
 
 // Package is the documentation for an entire package.
@@ -17,11 +17,13 @@ type Package struct {
        ImportPath string
        Imports    []string
        Filenames  []string
-       Consts     []*Value
-       Types      []*Type
-       Vars       []*Value
-       Funcs      []*Func
        Bugs       []string
+
+       // declarations
+       Consts []*Value
+       Types  []*Type
+       Vars   []*Value
+       Funcs  []*Func
 }
 
 // Value is the documentation for a (possibly grouped) var or const declaration.
@@ -33,36 +35,30 @@ type Value struct {
        order int
 }
 
-type Method struct {
-       *Func
-       // TODO(gri) The following fields are not set at the moment. 
-       Origin *Type // original receiver base type
-       Level  int   // embedding level; 0 means Func is not embedded
-}
-
-// Type is the documentation for type declaration.
+// Type is the documentation for a type declaration.
 type Type struct {
-       Doc     string
-       Name    string
-       Type    *ast.TypeSpec
-       Decl    *ast.GenDecl
-       Consts  []*Value  // sorted list of constants of (mostly) this type
-       Vars    []*Value  // sorted list of variables of (mostly) this type
-       Funcs   []*Func   // sorted list of functions returning this type
-       Methods []*Method // sorted list of methods (including embedded ones) of this type
+       Doc  string
+       Name string
+       Decl *ast.GenDecl
 
-       methods  []*Func   // top-level methods only
-       embedded methodSet // embedded methods only
-       order    int
+       // associated declarations
+       Consts  []*Value // sorted list of constants of (mostly) this type
+       Vars    []*Value // sorted list of variables of (mostly) this type
+       Funcs   []*Func  // sorted list of functions returning this type
+       Methods []*Func  // sorted list of methods (including embedded ones) of this type
 }
 
 // Func is the documentation for a func declaration.
 type Func struct {
        Doc  string
        Name string
-       // TODO(gri) remove Recv once we switch to new implementation
-       Recv ast.Expr // TODO(rsc): Would like string here
        Decl *ast.FuncDecl
+
+       // methods
+       // (for functions, these fields have the respective zero value)
+       Recv  string // actual   receiver "T" or "*T"
+       Orig  string // original receiver "T" or "*T"
+       Level int    // embedding level; 0 means not embedded
 }
 
 // Mode values control the operation of New.
@@ -74,27 +70,24 @@ const (
        AllDecls Mode = 1 << iota
 )
 
-// New computes the package documentation for the given package.
-func New(pkg *ast.Package, importpath string, mode Mode) *Package {
-       var r docReader
-       r.init(pkg.Name, mode)
-       filenames := make([]string, len(pkg.Files))
-       // sort package files before reading them so that the
-       // result is the same on different machines (32/64bit)
-       i := 0
-       for filename := range pkg.Files {
-               filenames[i] = filename
-               i++
-       }
-       sort.Strings(filenames)
-
-       // process files in sorted order
-       for _, filename := range filenames {
-               f := pkg.Files[filename]
-               if mode&AllDecls == 0 {
-                       r.fileExports(f)
-               }
-               r.addFile(f)
+// New computes the package documentation for the given package AST.
+// New takes ownership of the AST pkg and may edit or overwrite it.
+//
+func New(pkg *ast.Package, importPath string, mode Mode) *Package {
+       var r reader
+       r.readPackage(pkg, mode)
+       r.computeMethodSets()
+       r.cleanupTypes()
+       return &Package{
+               Doc:        r.doc,
+               Name:       pkg.Name,
+               ImportPath: importPath,
+               Imports:    sortedKeys(r.imports),
+               Filenames:  r.filenames,
+               Bugs:       r.bugs,
+               Consts:     sortedValues(r.values, token.CONST),
+               Types:      sortedTypes(r.types),
+               Vars:       sortedValues(r.values, token.VAR),
+               Funcs:      sortedFuncs(r.funcs),
        }
-       return r.newDoc(importpath, filenames)
 }
index 0a4830148afef44c71d5f0ce91a25f41367a2397..d9ffe47b61406ffefc1559238c641e7aab6b4278 100644 (file)
@@ -7,6 +7,7 @@ package doc
 import (
        "bytes"
        "flag"
+       "fmt"
        "go/parser"
        "go/printer"
        "go/token"
@@ -64,7 +65,7 @@ type bundle struct {
        FSet *token.FileSet
 }
 
-func Test(t *testing.T) {
+func test(t *testing.T, mode Mode) {
        // get all packages
        fset := token.NewFileSet()
        pkgs, err := parser.ParseDir(fset, dataDir, isGoFile, parser.ParseComments)
@@ -75,7 +76,7 @@ func Test(t *testing.T) {
        // test all packages
        for _, pkg := range pkgs {
                importpath := dataDir + "/" + pkg.Name
-               doc := New(pkg, importpath, 0)
+               doc := New(pkg, importpath, mode)
 
                // golden files always use / in filenames - canonicalize them
                for i, filename := range doc.Filenames {
@@ -91,7 +92,7 @@ func Test(t *testing.T) {
                got := buf.Bytes()
 
                // update golden file if necessary
-               golden := filepath.Join(dataDir, pkg.Name+".out")
+               golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
                if *update {
                        err := ioutil.WriteFile(golden, got, 0644)
                        if err != nil {
@@ -113,3 +114,8 @@ func Test(t *testing.T) {
                }
        }
 }
+
+func Test(t *testing.T) {
+       test(t, 0)
+       test(t, AllDecls)
+}
index a35b3e2391497aed5ccfba50b17a496acb512270..e6f58ccb3507c9afe6cb5498abb9e5a6f971bbb8 100644 (file)
@@ -8,6 +8,9 @@ package doc
 
 import "go/ast"
 
+// filterIdentList removes unexported names from list in place
+// and returns the resulting list.
+//
 func filterIdentList(list []*ast.Ident) []*ast.Ident {
        j := 0
        for _, x := range list {
@@ -19,54 +22,46 @@ func filterIdentList(list []*ast.Ident) []*ast.Ident {
        return list[0:j]
 }
 
-func baseName(x ast.Expr) *ast.Ident {
-       switch t := x.(type) {
-       case *ast.Ident:
-               return t
-       case *ast.SelectorExpr:
-               if _, ok := t.X.(*ast.Ident); ok {
-                       return t.Sel
-               }
-       case *ast.StarExpr:
-               return baseName(t.X)
-       }
-       return nil
-}
-
-func (doc *docReader) filterFieldList(tinfo *typeInfo, fields *ast.FieldList) (removedFields bool) {
+// filterFieldList removes unexported fields (field names) from the field list
+// in place and returns true if fields were removed. Removed fields that are
+// anonymous (embedded) fields are added as embedded types to base. filterType
+// is called with the types of all remaining fields.
+//
+func (r *reader) filterFieldList(base *baseType, fields *ast.FieldList) (removedFields bool) {
        if fields == nil {
-               return false
+               return
        }
        list := fields.List
        j := 0
-       for _, f := range list {
+       for _, field := range list {
                keepField := false
-               if len(f.Names) == 0 {
+               if n := len(field.Names); n == 0 {
                        // anonymous field
-                       name := baseName(f.Type)
-                       if name != nil && name.IsExported() {
-                               // we keep the field - in this case doc.addDecl
+                       name, imp := baseTypeName(field.Type)
+                       if ast.IsExported(name) {
+                               // we keep the field - in this case r.readDecl
                                // will take care of adding the embedded type
                                keepField = true
-                       } else if tinfo != nil {
+                       } else if base != nil && !imp {
                                // we don't keep the field - add it as an embedded
                                // type so we won't loose its methods, if any
-                               if embedded := doc.lookupTypeInfo(name.Name); embedded != nil {
-                                       _, ptr := f.Type.(*ast.StarExpr)
-                                       tinfo.addEmbeddedType(embedded, ptr)
+                               if embedded := r.lookupType(name); embedded != nil {
+                                       _, ptr := field.Type.(*ast.StarExpr)
+                                       base.addEmbeddedType(embedded, ptr)
                                }
                        }
                } else {
-                       n := len(f.Names)
-                       f.Names = filterIdentList(f.Names)
-                       if len(f.Names) < n {
+                       field.Names = filterIdentList(field.Names)
+                       if len(field.Names) < n {
                                removedFields = true
                        }
-                       keepField = len(f.Names) > 0
+                       if len(field.Names) > 0 {
+                               keepField = true
+                       }
                }
                if keepField {
-                       doc.filterType(nil, f.Type)
-                       list[j] = f
+                       r.filterType(nil, field.Type)
+                       list[j] = field
                        j++
                }
        }
@@ -77,52 +72,48 @@ func (doc *docReader) filterFieldList(tinfo *typeInfo, fields *ast.FieldList) (r
        return
 }
 
-func (doc *docReader) filterParamList(fields *ast.FieldList) bool {
-       if fields == nil {
-               return false
-       }
-       var b bool
-       for _, f := range fields.List {
-               if doc.filterType(nil, f.Type) {
-                       b = true
+// filterParamList applies filterType to each parameter type in fields.
+//
+func (r *reader) filterParamList(fields *ast.FieldList) {
+       if fields != nil {
+               for _, f := range fields.List {
+                       r.filterType(nil, f.Type)
                }
        }
-       return b
 }
 
-func (doc *docReader) filterType(tinfo *typeInfo, typ ast.Expr) bool {
+// filterType strips any unexported struct fields or method types from typ
+// in place. If fields (or methods) have been removed, the corresponding
+// struct or interface type has the Incomplete field set to true. 
+//
+func (r *reader) filterType(base *baseType, typ ast.Expr) {
        switch t := typ.(type) {
        case *ast.Ident:
-               return ast.IsExported(t.Name)
+               // nothing to do
        case *ast.ParenExpr:
-               return doc.filterType(nil, t.X)
+               r.filterType(nil, t.X)
        case *ast.ArrayType:
-               return doc.filterType(nil, t.Elt)
+               r.filterType(nil, t.Elt)
        case *ast.StructType:
-               if doc.filterFieldList(tinfo, t.Fields) {
+               if r.filterFieldList(base, t.Fields) {
                        t.Incomplete = true
                }
-               return len(t.Fields.List) > 0
        case *ast.FuncType:
-               b1 := doc.filterParamList(t.Params)
-               b2 := doc.filterParamList(t.Results)
-               return b1 || b2
+               r.filterParamList(t.Params)
+               r.filterParamList(t.Results)
        case *ast.InterfaceType:
-               if doc.filterFieldList(tinfo, t.Methods) {
+               if r.filterFieldList(base, t.Methods) {
                        t.Incomplete = true
                }
-               return len(t.Methods.List) > 0
        case *ast.MapType:
-               b1 := doc.filterType(nil, t.Key)
-               b2 := doc.filterType(nil, t.Value)
-               return b1 || b2
+               r.filterType(nil, t.Key)
+               r.filterType(nil, t.Value)
        case *ast.ChanType:
-               return doc.filterType(nil, t.Value)
+               r.filterType(nil, t.Value)
        }
-       return false
 }
 
-func (doc *docReader) filterSpec(spec ast.Spec) bool {
+func (r *reader) filterSpec(spec ast.Spec) bool {
        switch s := spec.(type) {
        case *ast.ImportSpec:
                // always keep imports so we can collect them
@@ -130,22 +121,22 @@ func (doc *docReader) filterSpec(spec ast.Spec) bool {
        case *ast.ValueSpec:
                s.Names = filterIdentList(s.Names)
                if len(s.Names) > 0 {
-                       doc.filterType(nil, s.Type)
+                       r.filterType(nil, s.Type)
                        return true
                }
        case *ast.TypeSpec:
                if ast.IsExported(s.Name.Name) {
-                       doc.filterType(doc.lookupTypeInfo(s.Name.Name), s.Type)
+                       r.filterType(r.lookupType(s.Name.Name), s.Type)
                        return true
                }
        }
        return false
 }
 
-func (doc *docReader) filterSpecList(list []ast.Spec) []ast.Spec {
+func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec {
        j := 0
        for _, s := range list {
-               if doc.filterSpec(s) {
+               if r.filterSpec(s) {
                        list[j] = s
                        j++
                }
@@ -153,10 +144,10 @@ func (doc *docReader) filterSpecList(list []ast.Spec) []ast.Spec {
        return list[0:j]
 }
 
-func (doc *docReader) filterDecl(decl ast.Decl) bool {
+func (r *reader) filterDecl(decl ast.Decl) bool {
        switch d := decl.(type) {
        case *ast.GenDecl:
-               d.Specs = doc.filterSpecList(d.Specs)
+               d.Specs = r.filterSpecList(d.Specs)
                return len(d.Specs) > 0
        case *ast.FuncDecl:
                return ast.IsExported(d.Name.Name)
@@ -164,18 +155,15 @@ func (doc *docReader) filterDecl(decl ast.Decl) bool {
        return false
 }
 
-// fileExports trims the AST for a Go file in place such that
-// only exported nodes remain. fileExports returns true if
-// there are exported declarations; otherwise it returns false.
+// fileExports removes unexported declarations from src in place.
 //
-func (doc *docReader) fileExports(src *ast.File) bool {
+func (r *reader) fileExports(src *ast.File) {
        j := 0
        for _, d := range src.Decls {
-               if doc.filterDecl(d) {
+               if r.filterDecl(d) {
                        src.Decls[j] = d
                        j++
                }
        }
        src.Decls = src.Decls[0:j]
-       return j > 0
 }
index fe2d39b8802d06fb73ae4f0fb73170c4668f8b0b..02b66ccefafcd5076e3b66cac7f6a353d105e916 100644 (file)
@@ -71,17 +71,6 @@ func filterFuncs(a []*Func, f Filter) []*Func {
        return a[0:w]
 }
 
-func filterMethods(a []*Method, f Filter) []*Method {
-       w := 0
-       for _, md := range a {
-               if f(md.Name) {
-                       a[w] = md
-                       w++
-               }
-       }
-       return a[0:w]
-}
-
 func filterTypes(a []*Type, f Filter) []*Type {
        w := 0
        for _, td := range a {
@@ -93,7 +82,7 @@ func filterTypes(a []*Type, f Filter) []*Type {
                        td.Consts = filterValues(td.Consts, f)
                        td.Vars = filterValues(td.Vars, f)
                        td.Funcs = filterFuncs(td.Funcs, f)
-                       td.Methods = filterMethods(td.Methods, f)
+                       td.Methods = filterFuncs(td.Methods, f)
                        n += len(td.Consts) + len(td.Vars) + len(td.Funcs) + len(td.Methods)
                }
                if n > 0 {
index 1a2fad559a63cf29e276a85d5e2eb4d6ed38d1a6..9c6f0816b60f81e864accc1ea477e559d63a9ffd 100644 (file)
@@ -13,112 +13,208 @@ import (
 )
 
 // ----------------------------------------------------------------------------
-// Collection of documentation info
+// function/method sets
+//
+// Internally, we treat functions like methods and collect them in method sets.
+
+// methodSet describes a set of methods. Entries where Decl == nil are conflict
+// entries (more then one method with the same name at the same embedding level).
+//
+type methodSet map[string]*Func
+
+// recvString returns a string representation of recv of the
+// form "T", "*T", or "BADRECV" (if not a proper receiver type).
+//
+func recvString(recv ast.Expr) string {
+       switch t := recv.(type) {
+       case *ast.Ident:
+               return t.Name
+       case *ast.StarExpr:
+               return "*" + recvString(t.X)
+       }
+       return "BADRECV"
+}
+
+// set creates the corresponding Func for f and adds it to mset.
+// If there are multiple f's with the same name, set keeps the first
+// one with documentation; conflicts are ignored.
+//
+func (mset methodSet) set(f *ast.FuncDecl) {
+       name := f.Name.Name
+       if g := mset[name]; g != nil && g.Doc != "" {
+               // A function with the same name has already been registered;
+               // since it has documentation, assume f is simply another
+               // implementation and ignore it. This does not happen if the
+               // caller is using go/build.ScanDir to determine the list of
+               // files implementing a package. 
+               return
+       }
+       // function doesn't exist or has no documentation; use f
+       recv := ""
+       if f.Recv != nil {
+               var typ ast.Expr
+               // be careful in case of incorrect ASTs
+               if list := f.Recv.List; len(list) == 1 {
+                       typ = list[0].Type
+               }
+               recv = recvString(typ)
+       }
+       mset[name] = &Func{
+               Doc:  f.Doc.Text(),
+               Name: name,
+               Decl: f,
+               Recv: recv,
+               Orig: recv,
+       }
+       f.Doc = nil // doc consumed - remove from AST
+}
+
+// add adds method m to the method set; m is ignored if the method set
+// already contains a method with the same name at the same or a higher
+// level then m.
+//
+func (mset methodSet) add(m *Func) {
+       old := mset[m.Name]
+       if old == nil || m.Level < old.Level {
+               mset[m.Name] = m
+               return
+       }
+       if old != nil && m.Level == old.Level {
+               // conflict - mark it using a method with nil Decl
+               mset[m.Name] = &Func{
+                       Name:  m.Name,
+                       Level: m.Level,
+               }
+       }
+}
+
+// ----------------------------------------------------------------------------
+// Base types
+
+// baseTypeName returns the name of the base type of x (or "")
+// and whether the type is imported or not.
+//
+func baseTypeName(x ast.Expr) (name string, imported bool) {
+       switch t := x.(type) {
+       case *ast.Ident:
+               return t.Name, false
+       case *ast.SelectorExpr:
+               if _, ok := t.X.(*ast.Ident); ok {
+                       // only possible for qualified type names;
+                       // assume type is imported
+                       return t.Sel.Name, true
+               }
+       case *ast.StarExpr:
+               return baseTypeName(t.X)
+       }
+       return
+}
 
 // embeddedType describes the type of an anonymous field.
 //
 type embeddedType struct {
-       typ *typeInfo // the corresponding base type
+       typ *baseType // the corresponding base type
        ptr bool      // if set, the anonymous field type is a pointer
 }
 
-type typeInfo struct {
-       name     string // base type name
-       isStruct bool
-       // len(decl.Specs) == 1, and the element type is *ast.TypeSpec
-       // if the type declaration hasn't been seen yet, decl is nil
-       decl     *ast.GenDecl
-       embedded []embeddedType
-       forward  *Type // forward link to processed type documentation
-
-       // declarations associated with the type
-       values    []*ast.GenDecl // consts and vars
-       factories map[string]*ast.FuncDecl
-       methods   map[string]*ast.FuncDecl
-}
+type baseType struct {
+       doc  string       // doc comment for type
+       name string       // local type name (excluding package qualifier)
+       decl *ast.GenDecl // nil if declaration hasn't been seen yet
 
-func (info *typeInfo) exported() bool {
-       return ast.IsExported(info.name)
+       // associated declarations
+       values  []*Value // consts and vars
+       funcs   methodSet
+       methods methodSet
+
+       isEmbedded bool           // true if this type is embedded
+       isStruct   bool           // true if this type is a struct
+       embedded   []embeddedType // list of embedded types
 }
 
-func (info *typeInfo) addEmbeddedType(embedded *typeInfo, isPtr bool) {
-       info.embedded = append(info.embedded, embeddedType{embedded, isPtr})
+func (typ *baseType) addEmbeddedType(e *baseType, isPtr bool) {
+       e.isEmbedded = true
+       typ.embedded = append(typ.embedded, embeddedType{e, isPtr})
 }
 
-// docReader accumulates documentation for a single package.
+// ----------------------------------------------------------------------------
+// AST reader
+
+// reader accumulates documentation for a single package.
 // It modifies the AST: Comments (declaration documentation)
-// that have been collected by the DocReader are set to nil
+// that have been collected by the reader are set to nil
 // in the respective AST nodes so that they are not printed
 // twice (once when printing the documentation and once when
 // printing the corresponding AST node).
 //
-type docReader struct {
-       doc      *ast.CommentGroup // package documentation, if any
-       pkgName  string
-       mode     Mode
-       imports  map[string]int
-       values   []*ast.GenDecl // consts and vars
-       types    map[string]*typeInfo
-       embedded map[string]*typeInfo // embedded types, possibly not exported
-       funcs    map[string]*ast.FuncDecl
-       bugs     []*ast.CommentGroup
+type reader struct {
+       mode Mode
+
+       // package properties
+       doc       string // package documentation, if any
+       filenames []string
+       bugs      []string
+
+       // declarations
+       imports map[string]int
+       values  []*Value // consts and vars
+       types   map[string]*baseType
+       funcs   methodSet
 }
 
-func (doc *docReader) init(pkgName string, mode Mode) {
-       doc.pkgName = pkgName
-       doc.mode = mode
-       doc.imports = make(map[string]int)
-       doc.types = make(map[string]*typeInfo)
-       doc.embedded = make(map[string]*typeInfo)
-       doc.funcs = make(map[string]*ast.FuncDecl)
-}
-
-func (doc *docReader) addDoc(comments *ast.CommentGroup) {
-       if doc.doc == nil {
-               // common case: just one package comment
-               doc.doc = comments
-               return
-       }
-       // More than one package comment: Usually there will be only
-       // one file with a package comment, but it's better to collect
-       // all comments than drop them on the floor.
-       blankComment := &ast.Comment{token.NoPos, "//"}
-       list := append(doc.doc.List, blankComment)
-       doc.doc.List = append(list, comments.List...)
+// isVisible reports whether name is visible in the documentation.
+//
+func (r *reader) isVisible(name string) bool {
+       return r.mode&AllDecls != 0 || ast.IsExported(name)
 }
 
-func (doc *docReader) lookupTypeInfo(name string) *typeInfo {
+// lookupType returns the base type with the given name.
+// If the base type has not been encountered yet, a new
+// type with the given name but no associated declaration
+// is added to the type map.
+//
+func (r *reader) lookupType(name string) *baseType {
        if name == "" || name == "_" {
                return nil // no type docs for anonymous types
        }
-       if info, found := doc.types[name]; found {
-               return info
+       if typ, found := r.types[name]; found {
+               return typ
        }
-       // type wasn't found - add one without declaration
-       info := &typeInfo{
-               name:      name,
-               factories: make(map[string]*ast.FuncDecl),
-               methods:   make(map[string]*ast.FuncDecl),
+       // type not found - add one without declaration
+       typ := &baseType{
+               name:    name,
+               funcs:   make(methodSet),
+               methods: make(methodSet),
        }
-       doc.types[name] = info
-       return info
+       r.types[name] = typ
+       return typ
 }
 
-func baseTypeName(typ ast.Expr, allTypes bool) string {
-       switch t := typ.(type) {
-       case *ast.Ident:
-               // if the type is not exported, the effect to
-               // a client is as if there were no type name
-               if t.IsExported() || allTypes {
-                       return t.Name
+func (r *reader) readDoc(comment *ast.CommentGroup) {
+       // By convention there should be only one package comment
+       // but collect all of them if there are more then one.
+       text := comment.Text()
+       if r.doc == "" {
+               r.doc = text
+               return
+       }
+       r.doc += "\n" + text
+}
+
+func specNames(specs []ast.Spec) []string {
+       names := make([]string, 0, len(specs)) // reasonable estimate
+       for _, s := range specs {
+               // s guaranteed to be an *ast.ValueSpec by readValue
+               for _, ident := range s.(*ast.ValueSpec).Names {
+                       names = append(names, ident.Name)
                }
-       case *ast.StarExpr:
-               return baseTypeName(t.X, allTypes)
        }
-       return ""
+       return names
 }
 
-func (doc *docReader) addValue(decl *ast.GenDecl) {
+// readValue processes a const or var declaration.
+//
+func (r *reader) readValue(decl *ast.GenDecl) {
        // determine if decl should be associated with a type
        // Heuristic: For each typed entry, determine the type name, if any.
        //            If there is exactly one type name that is sufficiently
@@ -126,91 +222,156 @@ func (doc *docReader) addValue(decl *ast.GenDecl) {
        domName := ""
        domFreq := 0
        prev := ""
-       for _, s := range decl.Specs {
-               if v, ok := s.(*ast.ValueSpec); ok {
-                       name := ""
-                       switch {
-                       case v.Type != nil:
-                               // a type is present; determine its name
-                               name = baseTypeName(v.Type, false)
-                       case decl.Tok == token.CONST:
-                               // no type is present but we have a constant declaration;
-                               // use the previous type name (w/o more type information
-                               // we cannot handle the case of unnamed variables with
-                               // initializer expressions except for some trivial cases)
-                               name = prev
+       n := 0
+       for _, spec := range decl.Specs {
+               s, ok := spec.(*ast.ValueSpec)
+               if !ok {
+                       continue // should not happen, but be conservative
+               }
+               name := ""
+               switch {
+               case s.Type != nil:
+                       // a type is present; determine its name
+                       if n, imp := baseTypeName(s.Type); !imp && r.isVisible(n) {
+                               name = n
                        }
-                       if name != "" {
-                               // entry has a named type
-                               if domName != "" && domName != name {
-                                       // more than one type name - do not associate
-                                       // with any type
-                                       domName = ""
-                                       break
-                               }
-                               domName = name
-                               domFreq++
+               case decl.Tok == token.CONST:
+                       // no type is present but we have a constant declaration;
+                       // use the previous type name (w/o more type information
+                       // we cannot handle the case of unnamed variables with
+                       // initializer expressions except for some trivial cases)
+                       name = prev
+               }
+               if name != "" {
+                       // entry has a named type
+                       if domName != "" && domName != name {
+                               // more than one type name - do not associate
+                               // with any type
+                               domName = ""
+                               break
                        }
-                       prev = name
+                       domName = name
+                       domFreq++
                }
+               prev = name
+               n++
+       }
+
+       // nothing to do w/o a legal declaration
+       if n == 0 {
+               return
        }
 
-       // determine values list
+       // determine values list with which to associate the Value for this decl
+       values := &r.values
        const threshold = 0.75
-       values := &doc.values
        if domName != "" && domFreq >= int(float64(len(decl.Specs))*threshold) {
                // typed entries are sufficiently frequent
-               typ := doc.lookupTypeInfo(domName)
+               typ := r.lookupType(domName)
                if typ != nil {
                        values = &typ.values // associate with that type
                }
        }
 
-       *values = append(*values, decl)
+       *values = append(*values, &Value{
+               Doc:   decl.Doc.Text(),
+               Names: specNames(decl.Specs),
+               Decl:  decl,
+               order: len(*values),
+       })
+       decl.Doc = nil // doc consumed - remove from AST
 }
 
-// Helper function to set the table entry for function f. Makes sure that
-// at least one f with associated documentation is stored in table, if there
-// are multiple f's with the same name.
-func setFunc(table map[string]*ast.FuncDecl, f *ast.FuncDecl) {
-       name := f.Name.Name
-       if g, exists := table[name]; exists && g.Doc != nil {
-               // a function with the same name has already been registered;
-               // since it has documentation, assume f is simply another
-               // implementation and ignore it
-               // TODO(gri) consider collecting all functions, or at least
-               //           all comments
-               return
+// fields returns a struct's fields or an interface's methods.
+//
+func fields(typ ast.Expr) (list []*ast.Field, isStruct bool) {
+       var fields *ast.FieldList
+       switch t := typ.(type) {
+       case *ast.StructType:
+               fields = t.Fields
+               isStruct = true
+       case *ast.InterfaceType:
+               fields = t.Methods
+       }
+       if fields != nil {
+               list = fields.List
+       }
+       return
+}
+
+// readType processes a type declaration.
+//
+func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) {
+       typ := r.lookupType(spec.Name.Name)
+       if typ == nil {
+               return // no name or blank name - ignore the type
+       }
+
+       // A type should be added at most once, so info.decl
+       // should be nil - if it is not, simply overwrite it.
+       typ.decl = decl
+
+       // compute documentation
+       doc := spec.Doc
+       spec.Doc = nil // doc consumed - remove from AST
+       if doc == nil {
+               // no doc associated with the spec, use the declaration doc, if any
+               doc = decl.Doc
+       }
+       decl.Doc = nil // doc consumed - remove from AST
+       typ.doc = doc.Text()
+
+       // look for anonymous fields that might contribute methods
+       var list []*ast.Field
+       list, typ.isStruct = fields(spec.Type)
+       for _, field := range list {
+               if len(field.Names) == 0 {
+                       // anonymous field - add corresponding field type to typ
+                       n, imp := baseTypeName(field.Type)
+                       if imp {
+                               // imported type - we don't handle this case
+                               // at the moment
+                               return
+                       }
+                       if embedded := r.lookupType(n); embedded != nil {
+                               _, ptr := field.Type.(*ast.StarExpr)
+                               typ.addEmbeddedType(embedded, ptr)
+                       }
+               }
        }
-       // function doesn't exist or has no documentation; use f
-       table[name] = f
 }
 
-func (doc *docReader) addFunc(fun *ast.FuncDecl) {
+// readFunc processes a func or method declaration.
+//
+func (r *reader) readFunc(fun *ast.FuncDecl) {
        // strip function body
        fun.Body = nil
 
        // determine if it should be associated with a type
        if fun.Recv != nil {
                // method
-               recvTypeName := baseTypeName(fun.Recv.List[0].Type, true /* exported or not */ )
-               var typ *typeInfo
-               if ast.IsExported(recvTypeName) {
-                       // exported recv type: if not found, add it to doc.types
-                       typ = doc.lookupTypeInfo(recvTypeName)
+               recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type)
+               if imp {
+                       // should not happen (incorrect AST);
+                       // don't show this method
+                       return
+               }
+               var typ *baseType
+               if r.isVisible(recvTypeName) {
+                       // visible recv type: if not found, add it to r.types
+                       typ = r.lookupType(recvTypeName)
                } else {
-                       // unexported recv type: if not found, do not add it
-                       // (unexported embedded types are added before this
+                       // invisible recv type: if not found, do not add it
+                       // (invisible embedded types are added before this
                        // phase, so if the type doesn't exist yet, we don't
                        // care about this method)
-                       typ = doc.types[recvTypeName]
+                       typ = r.types[recvTypeName]
                }
                if typ != nil {
-                       // exported receiver type
                        // associate method with the type
                        // (if the type is not exported, it may be embedded
                        // somewhere so we need to collect the method anyway)
-                       setFunc(typ.methods, fun)
+                       typ.methods.set(fun)
                }
                // otherwise don't show the method
                // TODO(gri): There may be exported methods of non-exported types
@@ -228,113 +389,70 @@ func (doc *docReader) addFunc(fun *ast.FuncDecl) {
                        // exactly one (named or anonymous) result associated
                        // with the first type in result signature (there may
                        // be more than one result)
-                       tname := baseTypeName(res.Type, false)
-                       typ := doc.lookupTypeInfo(tname)
-                       if typ != nil {
-                               // named and exported result type
-                               setFunc(typ.factories, fun)
-                               return
+                       if n, imp := baseTypeName(res.Type); !imp && r.isVisible(n) {
+                               if typ := r.lookupType(n); typ != nil {
+                                       // associate Func with typ
+                                       typ.funcs.set(fun)
+                                       return
+                               }
                        }
                }
        }
 
-       // ordinary function
-       setFunc(doc.funcs, fun)
+       // just an ordinary function
+       r.funcs.set(fun)
 }
 
-func (doc *docReader) addDecl(decl ast.Decl) {
-       switch d := decl.(type) {
-       case *ast.GenDecl:
-               if len(d.Specs) > 0 {
+var (
+       bug_markers = regexp.MustCompile("^/[/*][ \t]*BUG\\(.*\\):[ \t]*") // BUG(uid):
+       bug_content = regexp.MustCompile("[^ \n\r\t]+")                    // at least one non-whitespace char
+)
+
+// readFile adds the AST for a source file to the reader.
+//
+func (r *reader) readFile(src *ast.File) {
+       // add package documentation
+       if src.Doc != nil {
+               r.readDoc(src.Doc)
+               src.Doc = nil // doc consumed - remove from AST
+       }
+
+       // add all declarations
+       for _, decl := range src.Decls {
+               switch d := decl.(type) {
+               case *ast.GenDecl:
                        switch d.Tok {
                        case token.IMPORT:
                                // imports are handled individually
                                for _, spec := range d.Specs {
-                                       if import_, err := strconv.Unquote(spec.(*ast.ImportSpec).Path.Value); err == nil {
-                                               doc.imports[import_] = 1
+                                       if s, ok := spec.(*ast.ImportSpec); ok {
+                                               if import_, err := strconv.Unquote(s.Path.Value); err == nil {
+                                                       r.imports[import_] = 1
+                                               }
                                        }
                                }
                        case token.CONST, token.VAR:
                                // constants and variables are always handled as a group
-                               doc.addValue(d)
+                               r.readValue(d)
                        case token.TYPE:
                                // types are handled individually
                                for _, spec := range d.Specs {
-                                       tspec := spec.(*ast.TypeSpec)
-                                       // add the type to the documentation
-                                       info := doc.lookupTypeInfo(tspec.Name.Name)
-                                       if info == nil {
-                                               continue // no name - ignore the type
-                                       }
-                                       // Make a (fake) GenDecl node for this TypeSpec
-                                       // (we need to do this here - as opposed to just
-                                       // for printing - so we don't lose the GenDecl
-                                       // documentation). Since a new GenDecl node is
-                                       // created, there's no need to nil out d.Doc.
-                                       //
-                                       // TODO(gri): Consider just collecting the TypeSpec
-                                       // node (and copy in the GenDecl.doc if there is no
-                                       // doc in the TypeSpec - this is currently done in
-                                       // makeTypes below). Simpler data structures, but
-                                       // would lose GenDecl documentation if the TypeSpec
-                                       // has documentation as well.
-                                       fake := &ast.GenDecl{d.Doc, d.Pos(), token.TYPE, token.NoPos,
-                                               []ast.Spec{tspec}, token.NoPos}
-                                       // A type should be added at most once, so info.decl
-                                       // should be nil - if it isn't, simply overwrite it.
-                                       info.decl = fake
-                                       // Look for anonymous fields that might contribute methods.
-                                       var fields *ast.FieldList
-                                       switch typ := spec.(*ast.TypeSpec).Type.(type) {
-                                       case *ast.StructType:
-                                               fields = typ.Fields
-                                               info.isStruct = true
-                                       case *ast.InterfaceType:
-                                               fields = typ.Methods
-                                       }
-                                       if fields != nil {
-                                               for _, field := range fields.List {
-                                                       if len(field.Names) == 0 {
-                                                               // anonymous field - add corresponding type
-                                                               // to the info and collect it in doc
-                                                               name := baseTypeName(field.Type, true)
-                                                               if embedded := doc.lookupTypeInfo(name); embedded != nil {
-                                                                       _, ptr := field.Type.(*ast.StarExpr)
-                                                                       info.addEmbeddedType(embedded, ptr)
-                                                               }
-                                                       }
+                                       if s, ok := spec.(*ast.TypeSpec); ok {
+                                               // use an individual (possibly fake) declaration
+                                               // for each type; this also ensures that each type
+                                               // gets to (re-)use the declaration documentation
+                                               // if there's none associated with the spec itself
+                                               fake := &ast.GenDecl{
+                                                       d.Doc, d.Pos(), token.TYPE, token.NoPos,
+                                                       []ast.Spec{s}, token.NoPos,
                                                }
+                                               r.readType(fake, s)
                                        }
                                }
                        }
+               case *ast.FuncDecl:
+                       r.readFunc(d)
                }
-       case *ast.FuncDecl:
-               doc.addFunc(d)
-       }
-}
-
-func copyCommentList(list []*ast.Comment) []*ast.Comment {
-       return append([]*ast.Comment(nil), list...)
-}
-
-var (
-       bug_markers = regexp.MustCompile("^/[/*][ \t]*BUG\\(.*\\):[ \t]*") // BUG(uid):
-       bug_content = regexp.MustCompile("[^ \n\r\t]+")                    // at least one non-whitespace char
-)
-
-// addFile adds the AST for a source file to the docReader.
-// Adding the same AST multiple times is a no-op.
-//
-func (doc *docReader) addFile(src *ast.File) {
-       // add package documentation
-       if src.Doc != nil {
-               doc.addDoc(src.Doc)
-               src.Doc = nil // doc consumed - remove from ast.File node
-       }
-
-       // add all declarations
-       for _, decl := range src.Decls {
-               doc.addDecl(decl)
        }
 
        // collect BUG(...) comments
@@ -344,348 +462,273 @@ func (doc *docReader) addFile(src *ast.File) {
                        // found a BUG comment; maybe empty
                        if btxt := text[m[1]:]; bug_content.MatchString(btxt) {
                                // non-empty BUG comment; collect comment without BUG prefix
-                               list := copyCommentList(c.List)
+                               list := append([]*ast.Comment(nil), c.List...) // make a copy
                                list[0].Text = text[m[1]:]
-                               doc.bugs = append(doc.bugs, &ast.CommentGroup{list})
+                               r.bugs = append(r.bugs, (&ast.CommentGroup{list}).Text())
                        }
                }
        }
-       src.Comments = nil // consumed unassociated comments - remove from ast.File node
+       src.Comments = nil // consumed unassociated comments - remove from AST
 }
 
-// ----------------------------------------------------------------------------
-// Conversion to external representation
+func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
+       // initialize reader
+       r.filenames = make([]string, len(pkg.Files))
+       r.imports = make(map[string]int)
+       r.mode = mode
+       r.types = make(map[string]*baseType)
+       r.funcs = make(methodSet)
 
-func (doc *docReader) makeImports() []string {
-       list := make([]string, len(doc.imports))
+       // sort package files before reading them so that the
+       // result result does not depend on map iteration order
        i := 0
-       for import_ := range doc.imports {
-               list[i] = import_
+       for filename := range pkg.Files {
+               r.filenames[i] = filename
                i++
        }
-       sort.Strings(list)
-       return list
-}
+       sort.Strings(r.filenames)
 
-type sortValue []*Value
+       // process files in sorted order
+       for _, filename := range r.filenames {
+               f := pkg.Files[filename]
+               if mode&AllDecls == 0 {
+                       r.fileExports(f)
+               }
+               r.readFile(f)
+       }
+}
 
-func (p sortValue) Len() int      { return len(p) }
-func (p sortValue) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+// ----------------------------------------------------------------------------
+// Types
+
+var predeclaredTypes = map[string]bool{
+       "bool":       true,
+       "byte":       true,
+       "complex64":  true,
+       "complex128": true,
+       "float32":    true,
+       "float64":    true,
+       "int":        true,
+       "int8":       true,
+       "int16":      true,
+       "int32":      true,
+       "int64":      true,
+       "string":     true,
+       "uint":       true,
+       "uint8":      true,
+       "uint16":     true,
+       "uint32":     true,
+       "uint64":     true,
+       "uintptr":    true,
+}
 
-func declName(d *ast.GenDecl) string {
-       if len(d.Specs) != 1 {
-               return ""
+func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
+       if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
+               return f // shouldn't happen, but be safe
        }
 
-       switch v := d.Specs[0].(type) {
-       case *ast.ValueSpec:
-               return v.Names[0].Name
-       case *ast.TypeSpec:
-               return v.Name.Name
+       // copy existing receiver field and set new type
+       newField := *f.Decl.Recv.List[0]
+       _, origRecvIsPtr := newField.Type.(*ast.StarExpr)
+       var typ ast.Expr = ast.NewIdent(recvTypeName)
+       if !embeddedIsPtr && origRecvIsPtr {
+               typ = &ast.StarExpr{token.NoPos, typ}
        }
+       newField.Type = typ
 
-       return ""
-}
+       // copy existing receiver field list and set new receiver field
+       newFieldList := *f.Decl.Recv
+       newFieldList.List = []*ast.Field{&newField}
 
-func (p sortValue) Less(i, j int) bool {
-       // sort by name
-       // pull blocks (name = "") up to top
-       // in original order
-       if ni, nj := declName(p[i].Decl), declName(p[j].Decl); ni != nj {
-               return ni < nj
-       }
-       return p[i].order < p[j].order
+       // copy existing function declaration and set new receiver field list
+       newFuncDecl := *f.Decl
+       newFuncDecl.Recv = &newFieldList
+
+       // copy existing function documentation and set new declaration
+       newF := *f
+       newF.Decl = &newFuncDecl
+       newF.Recv = recvString(typ)
+       // the Orig field never changes
+       newF.Level = level
+
+       return &newF
 }
 
-func specNames(specs []ast.Spec) []string {
-       names := make([]string, len(specs)) // reasonable estimate
-       for _, s := range specs {
-               // should always be an *ast.ValueSpec, but be careful
-               if s, ok := s.(*ast.ValueSpec); ok {
-                       for _, ident := range s.Names {
-                               names = append(names, ident.Name)
+// collectEmbeddedMethods collects the embedded methods from
+// all processed embedded types found in info in mset.
+//
+func collectEmbeddedMethods(mset methodSet, typ *baseType, recvTypeName string, embeddedIsPtr bool, level int) {
+       for _, e := range typ.embedded {
+               // Once an embedded type is embedded as a pointer type
+               // all embedded types in those types are treated like
+               // pointer types for the purpose of the receiver type
+               // computation; i.e., embeddedIsPtr is sticky for this
+               // embedding hierarchy.
+               thisEmbeddedIsPtr := embeddedIsPtr || e.ptr
+               for _, m := range e.typ.methods {
+                       // only top-level methods are embedded
+                       if m.Level == 0 {
+                               mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level))
                        }
                }
+               collectEmbeddedMethods(mset, e.typ, recvTypeName, thisEmbeddedIsPtr, level+1)
        }
-       return names
 }
 
-func makeValues(list []*ast.GenDecl, tok token.Token) []*Value {
-       d := make([]*Value, len(list)) // big enough in any case
-       n := 0
-       for i, decl := range list {
-               if decl.Tok == tok {
-                       d[n] = &Value{decl.Doc.Text(), specNames(decl.Specs), decl, i}
-                       n++
-                       decl.Doc = nil // doc consumed - removed from AST
+// computeMethodSets determines the actual method sets for each type encountered.
+//
+func (r *reader) computeMethodSets() {
+       for _, t := range r.types {
+               // collect embedded methods for t
+               if t.isStruct {
+                       // struct
+                       collectEmbeddedMethods(t.methods, t, t.name, false, 1)
+               } else {
+                       // interface
+                       // TODO(gri) fix this
                }
        }
-       d = d[0:n]
-       sort.Sort(sortValue(d))
-       return d
 }
 
-type sortFunc []*Func
-
-func (p sortFunc) Len() int           { return len(p) }
-func (p sortFunc) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
-func (p sortFunc) Less(i, j int) bool { return p[i].Name < p[j].Name }
-
-func makeFuncs(m map[string]*ast.FuncDecl) []*Func {
-       d := make([]*Func, len(m))
-       i := 0
-       for _, f := range m {
-               doc := new(Func)
-               doc.Doc = f.Doc.Text()
-               f.Doc = nil // doc consumed - remove from ast.FuncDecl node
-               if f.Recv != nil {
-                       doc.Recv = f.Recv.List[0].Type
+// cleanupTypes removes the association of functions and methods with
+// types that have no declaration. Instead, these functions and methods
+// are shown at the package level. It also removes types with missing
+// declarations or which are not visible.
+// 
+func (r *reader) cleanupTypes() {
+       for _, t := range r.types {
+               visible := r.isVisible(t.name)
+               if t.decl == nil && (predeclaredTypes[t.name] || t.isEmbedded && visible) {
+                       // t.name is a predeclared type (and was not redeclared in this package),
+                       // or it was embedded somewhere but its declaration is missing (because
+                       // the AST is incomplete): move any associated values, funcs, and methods
+                       // back to the top-level so that they are not lost.
+                       // 1) move values
+                       r.values = append(r.values, t.values...)
+                       // 2) move factory functions
+                       for name, f := range t.funcs {
+                               r.funcs[name] = f
+                       }
+                       // 3) move methods
+                       for name, m := range t.methods {
+                               // don't overwrite functions with the same name - drop them
+                               if _, found := r.funcs[name]; !found {
+                                       r.funcs[name] = m
+                               }
+                       }
+               }
+               // remove types w/o declaration or which are not visible
+               if t.decl == nil || !visible {
+                       delete(r.types, t.name)
                }
-               doc.Name = f.Name.Name
-               doc.Decl = f
-               d[i] = doc
-               i++
        }
-       sort.Sort(sortFunc(d))
-       return d
 }
 
-type methodSet map[string]*Func
+// ----------------------------------------------------------------------------
+// Sorting
 
-func (mset methodSet) add(m *Func) {
-       if mset[m.Name] == nil {
-               mset[m.Name] = m
-       }
+type data struct {
+       n    int
+       swap func(i, j int)
+       less func(i, j int) bool
 }
 
-type sortMethod []*Method
+func (d *data) Len() int           { return d.n }
+func (d *data) Swap(i, j int)      { d.swap(i, j) }
+func (d *data) Less(i, j int) bool { return d.less(i, j) }
 
-func (p sortMethod) Len() int           { return len(p) }
-func (p sortMethod) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
-func (p sortMethod) Less(i, j int) bool { return p[i].Func.Name < p[j].Func.Name }
+// sortBy is a helper function for sorting
+func sortBy(less func(i, j int) bool, swap func(i, j int), n int) {
+       sort.Sort(&data{n, swap, less})
+}
 
-func (mset methodSet) sortedList() []*Method {
-       list := make([]*Method, len(mset))
+func sortedKeys(m map[string]int) []string {
+       list := make([]string, len(m))
        i := 0
-       for _, m := range mset {
-               list[i] = &Method{Func: m}
+       for key := range m {
+               list[i] = key
                i++
        }
-       sort.Sort(sortMethod(list))
+       sort.Strings(list)
        return list
 }
 
-type sortType []*Type
-
-func (p sortType) Len() int      { return len(p) }
-func (p sortType) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-func (p sortType) Less(i, j int) bool {
-       // sort by name
-       // pull blocks (name = "") up to top
-       // in original order
-       if ni, nj := p[i].Type.Name.Name, p[j].Type.Name.Name; ni != nj {
-               return ni < nj
+// sortingName returns the name to use when sorting d into place.
+//
+func sortingName(d *ast.GenDecl) string {
+       if len(d.Specs) == 1 {
+               if s, ok := d.Specs[0].(*ast.ValueSpec); ok {
+                       return s.Names[0].Name
+               }
        }
-       return p[i].order < p[j].order
+       return ""
 }
 
-// NOTE(rsc): This would appear not to be correct for type ( )
-// blocks, but the doc extractor above has split them into
-// individual declarations.
-func (doc *docReader) makeTypes(m map[string]*typeInfo) []*Type {
-       // TODO(gri) Consider computing the embedded method information
-       //           before calling makeTypes. Then this function can
-       //           be single-phased again. Also, it might simplify some
-       //           of the logic.
-       //
-       // phase 1: associate collected declarations with Types
-       list := make([]*Type, len(m))
+func sortedValues(m []*Value, tok token.Token) []*Value {
+       list := make([]*Value, len(m)) // big enough in any case
        i := 0
-       for _, old := range m {
-               // old typeInfos may not have a declaration associated with them
-               // if they are not exported but embedded, or because the package
-               // is incomplete.
-               if decl := old.decl; decl != nil || !old.exported() {
-                       // process the type even if not exported so that we have
-                       // its methods in case they are embedded somewhere
-                       t := new(Type)
-                       if decl != nil {
-                               typespec := decl.Specs[0].(*ast.TypeSpec)
-                               doc := typespec.Doc
-                               typespec.Doc = nil // doc consumed - remove from ast.TypeSpec node
-                               if doc == nil {
-                                       // no doc associated with the spec, use the declaration doc, if any
-                                       doc = decl.Doc
-                               }
-                               decl.Doc = nil // doc consumed - remove from ast.Decl node
-                               t.Doc = doc.Text()
-                               t.Type = typespec
-                       }
-                       t.Consts = makeValues(old.values, token.CONST)
-                       t.Vars = makeValues(old.values, token.VAR)
-                       t.Funcs = makeFuncs(old.factories)
-                       t.methods = makeFuncs(old.methods)
-                       // The list of embedded types' methods is computed from the list
-                       // of embedded types, some of which may not have been processed
-                       // yet (i.e., their forward link is nil) - do this in a 2nd phase.
-                       // The final list of methods can only be computed after that -
-                       // do this in a 3rd phase.
-                       t.Decl = old.decl
-                       t.order = i
-                       old.forward = t // old has been processed
-                       // only add the type to the final type list if it
-                       // is exported or if we want to see all types
-                       if old.exported() || doc.mode&AllDecls != 0 {
-                               list[i] = t
-                               i++
-                       }
-               } else {
-                       // no corresponding type declaration found - move any associated
-                       // values, factory functions, and methods back to the top-level
-                       // so that they are not lost (this should only happen if a package
-                       // file containing the explicit type declaration is missing or if
-                       // an unqualified type name was used after a "." import)
-                       // 1) move values
-                       doc.values = append(doc.values, old.values...)
-                       // 2) move factory functions
-                       for name, f := range old.factories {
-                               doc.funcs[name] = f
-                       }
-                       // 3) move methods
-                       for name, f := range old.methods {
-                               // don't overwrite functions with the same name
-                               if _, found := doc.funcs[name]; !found {
-                                       doc.funcs[name] = f
-                               }
-                       }
-               }
-       }
-       list = list[0:i] // some types may have been ignored
-
-       // phase 2: collect embedded methods for each processed typeInfo
-       for _, old := range m {
-               if t := old.forward; t != nil {
-                       // old has been processed into t; collect embedded
-                       // methods for t from the list of processed embedded
-                       // types in old (and thus for which the methods are known)
-                       if old.isStruct {
-                               // struct
-                               t.embedded = make(methodSet)
-                               collectEmbeddedMethods(t.embedded, old, old.name, false)
-                       } else {
-                               // interface
-                               // TODO(gri) fix this
-                       }
+       for _, val := range m {
+               if val.Decl.Tok == tok {
+                       list[i] = val
+                       i++
                }
        }
+       list = list[0:i]
 
-       // phase 3: compute final method set for each Type
-       for _, d := range list {
-               if len(d.embedded) > 0 {
-                       // there are embedded methods - exclude
-                       // the ones with names conflicting with
-                       // non-embedded methods
-                       mset := make(methodSet)
-                       // top-level methods have priority
-                       for _, m := range d.methods {
-                               mset.add(m)
+       sortBy(
+               func(i, j int) bool {
+                       if ni, nj := sortingName(list[i].Decl), sortingName(list[j].Decl); ni != nj {
+                               return ni < nj
                        }
-                       // add non-conflicting embedded methods
-                       for _, m := range d.embedded {
-                               mset.add(m)
-                       }
-                       d.Methods = mset.sortedList()
-               } else {
-                       // no embedded methods - convert into a Method list
-                       d.Methods = make([]*Method, len(d.methods))
-                       for i, m := range d.methods {
-                               d.Methods[i] = &Method{Func: m}
-                       }
-               }
-       }
+                       return list[i].order < list[j].order
+               },
+               func(i, j int) { list[i], list[j] = list[j], list[i] },
+               len(list),
+       )
 
-       sort.Sort(sortType(list))
        return list
 }
 
-// collectEmbeddedMethods collects the embedded methods from all
-// processed embedded types found in info in mset. It considers
-// embedded types at the most shallow level first so that more
-// deeply nested embedded methods with conflicting names are
-// excluded.
-//
-func collectEmbeddedMethods(mset methodSet, info *typeInfo, recvTypeName string, embeddedIsPtr bool) {
-       for _, e := range info.embedded {
-               if e.typ.forward != nil { // == e was processed
-                       // Once an embedded type was embedded as a pointer type
-                       // all embedded types in those types are treated like
-                       // pointer types for the purpose of the receiver type
-                       // computation; i.e., embeddedIsPtr is sticky for this
-                       // embedding hierarchy.
-                       thisEmbeddedIsPtr := embeddedIsPtr || e.ptr
-                       for _, m := range e.typ.forward.methods {
-                               mset.add(customizeRecv(m, thisEmbeddedIsPtr, recvTypeName))
-                       }
-                       collectEmbeddedMethods(mset, e.typ, recvTypeName, thisEmbeddedIsPtr)
+func sortedTypes(m map[string]*baseType) []*Type {
+       list := make([]*Type, len(m))
+       i := 0
+       for _, t := range m {
+               list[i] = &Type{
+                       Doc:     t.doc,
+                       Name:    t.name,
+                       Decl:    t.decl,
+                       Consts:  sortedValues(t.values, token.CONST),
+                       Vars:    sortedValues(t.values, token.VAR),
+                       Funcs:   sortedFuncs(t.funcs),
+                       Methods: sortedFuncs(t.methods),
                }
+               i++
        }
-}
-
-func customizeRecv(m *Func, embeddedIsPtr bool, recvTypeName string) *Func {
-       if m == nil || m.Decl == nil || m.Decl.Recv == nil || len(m.Decl.Recv.List) != 1 {
-               return m // shouldn't happen, but be safe
-       }
-
-       // copy existing receiver field and set new type
-       newField := *m.Decl.Recv.List[0]
-       _, origRecvIsPtr := newField.Type.(*ast.StarExpr)
-       var typ ast.Expr = ast.NewIdent(recvTypeName)
-       if !embeddedIsPtr && origRecvIsPtr {
-               typ = &ast.StarExpr{token.NoPos, typ}
-       }
-       newField.Type = typ
 
-       // copy existing receiver field list and set new receiver field
-       newFieldList := *m.Decl.Recv
-       newFieldList.List = []*ast.Field{&newField}
-
-       // copy existing function declaration and set new receiver field list
-       newFuncDecl := *m.Decl
-       newFuncDecl.Recv = &newFieldList
-
-       // copy existing function documentation and set new declaration
-       newM := *m
-       newM.Decl = &newFuncDecl
-       newM.Recv = typ
+       sortBy(
+               func(i, j int) bool { return list[i].Name < list[j].Name },
+               func(i, j int) { list[i], list[j] = list[j], list[i] },
+               len(list),
+       )
 
-       return &newM
+       return list
 }
 
-func makeBugs(list []*ast.CommentGroup) []string {
-       d := make([]string, len(list))
-       for i, g := range list {
-               d[i] = g.Text()
+func sortedFuncs(m methodSet) []*Func {
+       list := make([]*Func, len(m))
+       i := 0
+       for _, m := range m {
+               // exclude conflict entries
+               if m.Decl != nil {
+                       list[i] = m
+                       i++
+               }
        }
-       return d
-}
-
-// newDoc returns the accumulated documentation for the package.
-//
-func (doc *docReader) newDoc(importpath string, filenames []string) *Package {
-       p := new(Package)
-       p.Name = doc.pkgName
-       p.ImportPath = importpath
-       sort.Strings(filenames)
-       p.Filenames = filenames
-       p.Doc = doc.doc.Text()
-       // makeTypes may extend the list of doc.values and
-       // doc.funcs and thus must be called before any other
-       // function consuming those lists
-       p.Types = doc.makeTypes(doc.types)
-       p.Imports = doc.makeImports()
-       p.Consts = makeValues(doc.values, token.CONST)
-       p.Vars = makeValues(doc.values, token.VAR)
-       p.Funcs = makeFuncs(doc.funcs)
-       p.Bugs = makeBugs(doc.bugs)
-       return p
+       list = list[0:i]
+       sortBy(
+               func(i, j int) bool { return list[i].Name < list[j].Name },
+               func(i, j int) { list[i], list[j] = list[j], list[i] },
+               len(list),
+       )
+       return list
 }
diff --git a/libgo/go/go/doc/testdata/a.1.golden b/libgo/go/go/doc/testdata/a.1.golden
new file mode 100644 (file)
index 0000000..24db02d
--- /dev/null
@@ -0,0 +1,13 @@
+// comment 0  comment 1 
+PACKAGE a
+
+IMPORTPATH
+       testdata/a
+
+FILENAMES
+       testdata/a0.go
+       testdata/a1.go
+
+BUGS
+       // bug0 
+       // bug1 
similarity index 59%
rename from libgo/go/go/doc/testdata/b.out
rename to libgo/go/go/doc/testdata/b.0.golden
index c5ad0d0fc83e71565cef62f0c0489734486c363b..7c33300616d2b87549e6c86a431c3d61a035a8ba 100644 (file)
@@ -24,6 +24,12 @@ FUNCTIONS
        // 
        func F(x int) int
 
+       // Always under the package functions list. 
+       func NotAFactory() int
+
+       // Associated with uint type if AllDecls is set. 
+       func UintFactory() uint
+
 
 TYPES
        // 
@@ -32,3 +38,6 @@ TYPES
        // 
        var V T // v
 
+       // 
+       func (x *T) M()
+
diff --git a/libgo/go/go/doc/testdata/b.1.golden b/libgo/go/go/doc/testdata/b.1.golden
new file mode 100644 (file)
index 0000000..f303805
--- /dev/null
@@ -0,0 +1,49 @@
+// 
+PACKAGE b
+
+IMPORTPATH
+       testdata/b
+
+IMPORTS
+       a
+
+FILENAMES
+       testdata/b.go
+
+CONSTANTS
+       // 
+       const Pi = 3.14 // Pi
+
+
+VARIABLES
+       // 
+       var MaxInt int  // MaxInt
+
+
+FUNCTIONS
+       // 
+       func F(x int) int
+
+       // Always under the package functions list. 
+       func NotAFactory() int
+
+
+TYPES
+       // 
+       type T struct{} // T
+
+       // 
+       var V T // v
+
+       // 
+       func (x *T) M()
+
+       // Should only appear if AllDecls is set. 
+       type uint struct{}
+
+       // Associated with uint type if AllDecls is set. 
+       func UintFactory() uint
+
+       // Associated with uint type if AllDecls is set. 
+       func uintFactory() uint
+
index cdc77ef784c6ee68fb747a7938c2ab42df0705f5..28660f9be7c73ac095f6c532819b984e41ebe0f5 100644 (file)
@@ -6,8 +6,25 @@ package b
 
 import "a"
 
+// Basic declarations
+
 const Pi = 3.14   // Pi
 var MaxInt int    // MaxInt
 type T struct{}   // T
 var V T           // v
 func F(x int) int {} // F
+func (x *T) M()   {} // M
+
+// Corner cases: association with (presumed) predeclared types
+
+// Always under the package functions list.
+func NotAFactory() int {}
+
+// Associated with uint type if AllDecls is set.
+func UintFactory() uint {}
+
+// Associated with uint type if AllDecls is set.
+func uintFactory() uint {}
+
+// Should only appear if AllDecls is set.
+type uint struct{} // overrides a predeclared type uint
diff --git a/libgo/go/go/doc/testdata/c.0.golden b/libgo/go/go/doc/testdata/c.0.golden
new file mode 100644 (file)
index 0000000..e21959b
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+PACKAGE c
+
+IMPORTPATH
+       testdata/c
+
+IMPORTS
+       a
+
+FILENAMES
+       testdata/c.go
+
+TYPES
+       // A (should see this) 
+       type A struct{}
+
+       // B (should see this) 
+       type B struct{}
+
+       // C (should see this) 
+       type C struct{}
+
+       // D (should see this) 
+       type D struct{}
+
+       // E1 (should see this) 
+       type E1 struct{}
+
+       // E (should see this for E2 and E3) 
+       type E2 struct{}
+
+       // E (should see this for E2 and E3) 
+       type E3 struct{}
+
+       // E4 (should see this) 
+       type E4 struct{}
+
+       // 
+       type T1 struct{}
+
+       // 
+       func (t1 *T1) M()
+
+       // T2 must not show methods of local T1 
+       type T2 struct {
+               a.T1    // not the same as locally declared T1
+       }
+
diff --git a/libgo/go/go/doc/testdata/c.1.golden b/libgo/go/go/doc/testdata/c.1.golden
new file mode 100644 (file)
index 0000000..e21959b
--- /dev/null
@@ -0,0 +1,48 @@
+// 
+PACKAGE c
+
+IMPORTPATH
+       testdata/c
+
+IMPORTS
+       a
+
+FILENAMES
+       testdata/c.go
+
+TYPES
+       // A (should see this) 
+       type A struct{}
+
+       // B (should see this) 
+       type B struct{}
+
+       // C (should see this) 
+       type C struct{}
+
+       // D (should see this) 
+       type D struct{}
+
+       // E1 (should see this) 
+       type E1 struct{}
+
+       // E (should see this for E2 and E3) 
+       type E2 struct{}
+
+       // E (should see this for E2 and E3) 
+       type E3 struct{}
+
+       // E4 (should see this) 
+       type E4 struct{}
+
+       // 
+       type T1 struct{}
+
+       // 
+       func (t1 *T1) M()
+
+       // T2 must not show methods of local T1 
+       type T2 struct {
+               a.T1    // not the same as locally declared T1
+       }
+
diff --git a/libgo/go/go/doc/testdata/c.go b/libgo/go/go/doc/testdata/c.go
new file mode 100644 (file)
index 0000000..e0f3919
--- /dev/null
@@ -0,0 +1,62 @@
+// 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 c
+
+import "a"
+
+// ----------------------------------------------------------------------------
+// Test that empty declarations don't cause problems
+
+const ()
+
+type ()
+
+var ()
+
+// ----------------------------------------------------------------------------
+// Test that types with documentation on both, the Decl and the Spec node
+// are handled correctly.
+
+// A (should see this)
+type A struct{}
+
+// B (should see this)
+type (
+       B struct{}
+)
+
+type (
+       // C (should see this)
+       C struct{}
+)
+
+// D (should not see this)
+type (
+       // D (should see this)
+       D struct{}
+)
+
+// E (should see this for E2 and E3)
+type (
+       // E1 (should see this)
+       E1 struct{}
+       E2 struct{}
+       E3 struct{}
+       // E4 (should see this)
+       E4 struct{}
+)
+
+// ----------------------------------------------------------------------------
+// Test that local and imported types are different when
+// handling anonymous fields.
+
+type T1 struct{}
+
+func (t1 *T1) M() {}
+
+// T2 must not show methods of local T1
+type T2 struct {
+       a.T1 // not the same as locally declared T1
+}
diff --git a/libgo/go/go/doc/testdata/d.0.golden b/libgo/go/go/doc/testdata/d.0.golden
new file mode 100644 (file)
index 0000000..c005199
--- /dev/null
@@ -0,0 +1,104 @@
+// 
+PACKAGE d
+
+IMPORTPATH
+       testdata/d
+
+FILENAMES
+       testdata/d1.go
+       testdata/d2.go
+
+CONSTANTS
+       // CBx constants should appear before CAx constants. 
+       const (
+               CB2     = iota  // before CB1
+               CB1             // before CB0
+               CB0             // at end
+       )
+
+       // CAx constants should appear after CBx constants. 
+       const (
+               CA2     = iota  // before CA1
+               CA1             // before CA0
+               CA0             // at end
+       )
+
+       // C0 should be first. 
+       const C0 = 0
+
+       // C1 should be second. 
+       const C1 = 1
+
+       // C2 should be third. 
+       const C2 = 2
+
+       // 
+       const (
+               // Single const declarations inside ()'s are considered ungrouped
+               // and show up in sorted order.
+               Cungrouped = 0
+       )
+
+
+VARIABLES
+       // VBx variables should appear before VAx variables. 
+       var (
+               VB2     int     // before VB1
+               VB1     int     // before VB0
+               VB0     int     // at end
+       )
+
+       // VAx variables should appear after VBx variables. 
+       var (
+               VA2     int     // before VA1
+               VA1     int     // before VA0
+               VA0     int     // at end
+       )
+
+       // V0 should be first. 
+       var V0 uintptr
+
+       // V1 should be second. 
+       var V1 uint
+
+       // V2 should be third. 
+       var V2 int
+
+       // 
+       var (
+               // Single var declarations inside ()'s are considered ungrouped
+               // and show up in sorted order.
+               Vungrouped = 0
+       )
+
+
+FUNCTIONS
+       // F0 should be first. 
+       func F0()
+
+       // F1 should be second. 
+       func F1()
+
+       // F2 should be third. 
+       func F2()
+
+
+TYPES
+       // T0 should be first. 
+       type T0 struct{}
+
+       // T1 should be second. 
+       type T1 struct{}
+
+       // T2 should be third. 
+       type T2 struct{}
+
+       // TG0 should be first. 
+       type TG0 struct{}
+
+       // TG1 should be second. 
+       type TG1 struct{}
+
+       // TG2 should be third. 
+       type TG2 struct{}
+
diff --git a/libgo/go/go/doc/testdata/d.1.golden b/libgo/go/go/doc/testdata/d.1.golden
new file mode 100644 (file)
index 0000000..c005199
--- /dev/null
@@ -0,0 +1,104 @@
+// 
+PACKAGE d
+
+IMPORTPATH
+       testdata/d
+
+FILENAMES
+       testdata/d1.go
+       testdata/d2.go
+
+CONSTANTS
+       // CBx constants should appear before CAx constants. 
+       const (
+               CB2     = iota  // before CB1
+               CB1             // before CB0
+               CB0             // at end
+       )
+
+       // CAx constants should appear after CBx constants. 
+       const (
+               CA2     = iota  // before CA1
+               CA1             // before CA0
+               CA0             // at end
+       )
+
+       // C0 should be first. 
+       const C0 = 0
+
+       // C1 should be second. 
+       const C1 = 1
+
+       // C2 should be third. 
+       const C2 = 2
+
+       // 
+       const (
+               // Single const declarations inside ()'s are considered ungrouped
+               // and show up in sorted order.
+               Cungrouped = 0
+       )
+
+
+VARIABLES
+       // VBx variables should appear before VAx variables. 
+       var (
+               VB2     int     // before VB1
+               VB1     int     // before VB0
+               VB0     int     // at end
+       )
+
+       // VAx variables should appear after VBx variables. 
+       var (
+               VA2     int     // before VA1
+               VA1     int     // before VA0
+               VA0     int     // at end
+       )
+
+       // V0 should be first. 
+       var V0 uintptr
+
+       // V1 should be second. 
+       var V1 uint
+
+       // V2 should be third. 
+       var V2 int
+
+       // 
+       var (
+               // Single var declarations inside ()'s are considered ungrouped
+               // and show up in sorted order.
+               Vungrouped = 0
+       )
+
+
+FUNCTIONS
+       // F0 should be first. 
+       func F0()
+
+       // F1 should be second. 
+       func F1()
+
+       // F2 should be third. 
+       func F2()
+
+
+TYPES
+       // T0 should be first. 
+       type T0 struct{}
+
+       // T1 should be second. 
+       type T1 struct{}
+
+       // T2 should be third. 
+       type T2 struct{}
+
+       // TG0 should be first. 
+       type TG0 struct{}
+
+       // TG1 should be second. 
+       type TG1 struct{}
+
+       // TG2 should be third. 
+       type TG2 struct{}
+
diff --git a/libgo/go/go/doc/testdata/d1.go b/libgo/go/go/doc/testdata/d1.go
new file mode 100644 (file)
index 0000000..ebd6941
--- /dev/null
@@ -0,0 +1,57 @@
+// 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.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C2 should be third.
+const C2 = 2
+
+// V2 should be third.
+var V2 int
+
+// CBx constants should appear before CAx constants.
+const (
+       CB2 = iota // before CB1
+       CB1        // before CB0
+       CB0        // at end
+)
+
+// VBx variables should appear before VAx variables.
+var (
+       VB2 int // before VB1
+       VB1 int // before VB0
+       VB0 int // at end
+)
+
+const (
+       // Single const declarations inside ()'s are considered ungrouped
+       // and show up in sorted order.
+       Cungrouped = 0
+)
+
+var (
+       // Single var declarations inside ()'s are considered ungrouped
+       // and show up in sorted order.
+       Vungrouped = 0
+)
+
+// T2 should be third.
+type T2 struct{}
+
+// Grouped types are sorted nevertheless.
+type (
+       // TG2 should be third.
+       TG2 struct{}
+
+       // TG1 should be second.
+       TG1 struct{}
+
+       // TG0 should be first.
+       TG0 struct{}
+)
+
+// F2 should be third.
+func F2() {}
diff --git a/libgo/go/go/doc/testdata/d2.go b/libgo/go/go/doc/testdata/d2.go
new file mode 100644 (file)
index 0000000..2f56f4f
--- /dev/null
@@ -0,0 +1,45 @@
+// 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.
+
+// Test cases for sort order of declarations.
+
+package d
+
+// C1 should be second.
+const C1 = 1
+
+// C0 should be first.
+const C0 = 0
+
+// V1 should be second.
+var V1 uint
+
+// V0 should be first.
+var V0 uintptr
+
+// CAx constants should appear after CBx constants.
+const (
+       CA2 = iota // before CA1
+       CA1        // before CA0
+       CA0        // at end
+)
+
+// VAx variables should appear after VBx variables.
+var (
+       VA2 int // before VA1
+       VA1 int // before VA0
+       VA0 int // at end
+)
+
+// T1 should be second.
+type T1 struct{}
+
+// T0 should be first.
+type T0 struct{}
+
+// F1 should be second.
+func F1() {}
+
+// F0 should be first.
+func F0() {}
diff --git a/libgo/go/go/doc/testdata/e.0.golden b/libgo/go/go/doc/testdata/e.0.golden
new file mode 100644 (file)
index 0000000..3b128f7
--- /dev/null
@@ -0,0 +1,31 @@
+// 
+PACKAGE e
+
+IMPORTPATH
+       testdata/e
+
+FILENAMES
+       testdata/e.go
+
+TYPES
+       // T1 has no (top-level) M method due to conflict. 
+       type T1 struct {
+               // contains filtered or unexported fields
+       }
+
+       // T2 has only M as top-level method. 
+       type T2 struct {
+               // contains filtered or unexported fields
+       }
+
+       // T2.M should appear as method of T2. 
+       func (T2) M()
+
+       // T3 has only M as top-level method. 
+       type T3 struct {
+               // contains filtered or unexported fields
+       }
+
+       // T3.M should appear as method of T3. 
+       func (T3) M()
+
diff --git a/libgo/go/go/doc/testdata/e.1.golden b/libgo/go/go/doc/testdata/e.1.golden
new file mode 100644 (file)
index 0000000..d05602d
--- /dev/null
@@ -0,0 +1,61 @@
+// 
+PACKAGE e
+
+IMPORTPATH
+       testdata/e
+
+FILENAMES
+       testdata/e.go
+
+TYPES
+       // T1 has no (top-level) M method due to conflict. 
+       type T1 struct {
+               t1
+               t2
+       }
+
+       // T2 has only M as top-level method. 
+       type T2 struct {
+               t1
+       }
+
+       // T2.M should appear as method of T2. 
+       func (T2) M()
+
+       // T3 has only M as top-level method. 
+       type T3 struct {
+               t1e
+               t2e
+       }
+
+       // T3.M should appear as method of T3. 
+       func (T3) M()
+
+       // 
+       type t1 struct{}
+
+       // t1.M should not appear as method in a Tx type. 
+       func (t1) M()
+
+       // 
+       type t1e struct {
+               t1
+       }
+
+       // t1.M should not appear as method in a Tx type. 
+       func (t1e) M()
+
+       // 
+       type t2 struct{}
+
+       // t2.M should not appear as method in a Tx type. 
+       func (t2) M()
+
+       // 
+       type t2e struct {
+               t2
+       }
+
+       // t2.M should not appear as method in a Tx type. 
+       func (t2e) M()
+
diff --git a/libgo/go/go/doc/testdata/e.go b/libgo/go/go/doc/testdata/e.go
new file mode 100644 (file)
index 0000000..8ea6a83
--- /dev/null
@@ -0,0 +1,58 @@
+// 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.
+
+// Embedding tests.
+// TODO(gri): This should be comprehensive.
+
+package e
+
+// ----------------------------------------------------------------------------
+// Conflicting methods M must not show up.
+
+type t1 struct{}
+
+// t1.M should not appear as method in a Tx type.
+func (t1) M() {}
+
+type t2 struct{}
+
+// t2.M should not appear as method in a Tx type.
+func (t2) M() {}
+
+// T1 has no (top-level) M method due to conflict.
+type T1 struct {
+       t1
+       t2
+}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level method M.
+
+// T2 has only M as top-level method.
+type T2 struct {
+       t1
+}
+
+// T2.M should appear as method of T2.
+func (T2) M() {}
+
+// ----------------------------------------------------------------------------
+// Higher-level method M wins over lower-level conflicting methods M.
+
+type t1e struct {
+       t1
+}
+
+type t2e struct {
+       t2
+}
+
+// T3 has only M as top-level method.
+type T3 struct {
+       t1e
+       t2e
+}
+
+// T3.M should appear as method of T3.
+func (T3) M() {}
diff --git a/libgo/go/go/doc/testdata/testing.1.golden b/libgo/go/go/doc/testdata/testing.1.golden
new file mode 100644 (file)
index 0000000..1f92f8f
--- /dev/null
@@ -0,0 +1,298 @@
+// Package testing provides support for automated testing of Go ...
+PACKAGE testing
+
+IMPORTPATH
+       testdata/testing
+
+IMPORTS
+       bytes
+       flag
+       fmt
+       io
+       os
+       runtime
+       runtime/pprof
+       strconv
+       strings
+       time
+
+FILENAMES
+       testdata/benchmark.go
+       testdata/example.go
+       testdata/testing.go
+
+VARIABLES
+       // 
+       var (
+               // The short flag requests that tests run more quickly, but its functionality
+               // is provided by test writers themselves.  The testing package is just its
+               // home.  The all.bash installation script sets it to make installation more
+               // efficient, but by default the flag is off so a plain "gotest" will do a
+               // full test of the package.
+               short   = flag.Bool("test.short", false, "run smaller test suite to save time")
+       
+               // Report as tests are run; default is silent for success.
+               chatty          = flag.Bool("test.v", false, "verbose: print additional output")
+               match           = flag.String("test.run", "", "regular expression to select tests to run")
+               memProfile      = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+               memProfileRate  = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+               cpuProfile      = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
+               timeout         = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
+               cpuListStr      = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+               parallel        = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+       
+               cpuList []int
+       )
+
+       // 
+       var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
+
+       // 
+       var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+
+       // 
+       var timer *time.Timer
+
+
+FUNCTIONS
+       // An internal function but exported because it is cross-package; ...
+       func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)
+
+       // An internal function but exported because it is cross-package; ...
+       func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)
+
+       // 
+       func RunExamples(examples []InternalExample) (ok bool)
+
+       // 
+       func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
+
+       // Short reports whether the -test.short flag is set. 
+       func Short() bool
+
+       // after runs after all testing. 
+       func after()
+
+       // alarm is called if the timeout expires. 
+       func alarm()
+
+       // before runs before all testing. 
+       func before()
+
+       // decorate inserts the final newline if needed and indentation ...
+       func decorate(s string, addFileLine bool) string
+
+       // 
+       func max(x, y int) int
+
+       // 
+       func min(x, y int) int
+
+       // 
+       func parseCpuList()
+
+       // roundDown10 rounds a number down to the nearest power of 10. 
+       func roundDown10(n int) int
+
+       // roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. 
+       func roundUp(n int) int
+
+       // startAlarm starts an alarm if requested. 
+       func startAlarm()
+
+       // stopAlarm turns off the alarm. 
+       func stopAlarm()
+
+       // 
+       func tRunner(t *T, test *InternalTest)
+
+
+TYPES
+       // B is a type passed to Benchmark functions to manage benchmark ...
+       type B struct {
+               common
+               N               int
+               benchmark       InternalBenchmark
+               bytes           int64
+               timerOn         bool
+               result          BenchmarkResult
+       }
+
+       // Error is equivalent to Log() followed by Fail(). 
+       func (c *B) Error(args ...interface{})
+
+       // Errorf is equivalent to Logf() followed by Fail(). 
+       func (c *B) Errorf(format string, args ...interface{})
+
+       // Fail marks the function as having failed but continues ...
+       func (c *B) Fail()
+
+       // FailNow marks the function as having failed and stops its ...
+       func (c *B) FailNow()
+
+       // Failed returns whether the function has failed. 
+       func (c *B) Failed() bool
+
+       // Fatal is equivalent to Log() followed by FailNow(). 
+       func (c *B) Fatal(args ...interface{})
+
+       // Fatalf is equivalent to Logf() followed by FailNow(). 
+       func (c *B) Fatalf(format string, args ...interface{})
+
+       // Log formats its arguments using default formatting, analogous ...
+       func (c *B) Log(args ...interface{})
+
+       // Logf formats its arguments according to the format, analogous ...
+       func (c *B) Logf(format string, args ...interface{})
+
+       // ResetTimer sets the elapsed benchmark time to zero. It does not ...
+       func (b *B) ResetTimer()
+
+       // SetBytes records the number of bytes processed in a single ...
+       func (b *B) SetBytes(n int64)
+
+       // StartTimer starts timing a test.  This function is called ...
+       func (b *B) StartTimer()
+
+       // StopTimer stops timing a test.  This can be used to pause the ...
+       func (b *B) StopTimer()
+
+       // launch launches the benchmark function.  It gradually increases ...
+       func (b *B) launch()
+
+       // log generates the output. It's always at the same stack depth. 
+       func (c *B) log(s string)
+
+       // 
+       func (b *B) nsPerOp() int64
+
+       // run times the benchmark function in a separate goroutine. 
+       func (b *B) run() BenchmarkResult
+
+       // runN runs a single benchmark for the specified number of ...
+       func (b *B) runN(n int)
+
+       // trimOutput shortens the output from a benchmark, which can be ...
+       func (b *B) trimOutput()
+
+       // The results of a benchmark run. 
+       type BenchmarkResult struct {
+               N       int             // The number of iterations.
+               T       time.Duration   // The total time taken.
+               Bytes   int64           // Bytes processed in one iteration.
+       }
+
+       // Benchmark benchmarks a single function. Useful for creating ...
+       func Benchmark(f func(b *B)) BenchmarkResult
+
+       // 
+       func (r BenchmarkResult) NsPerOp() int64
+
+       // 
+       func (r BenchmarkResult) String() string
+
+       // 
+       func (r BenchmarkResult) mbPerSec() float64
+
+       // An internal type but exported because it is cross-package; part ...
+       type InternalBenchmark struct {
+               Name    string
+               F       func(b *B)
+       }
+
+       // 
+       type InternalExample struct {
+               Name    string
+               F       func()
+               Output  string
+       }
+
+       // An internal type but exported because it is cross-package; part ...
+       type InternalTest struct {
+               Name    string
+               F       func(*T)
+       }
+
+       // T is a type passed to Test functions to manage test state and ...
+       type T struct {
+               common
+               name            string          // Name of test.
+               startParallel   chan bool       // Parallel tests will wait on this.
+       }
+
+       // Error is equivalent to Log() followed by Fail(). 
+       func (c *T) Error(args ...interface{})
+
+       // Errorf is equivalent to Logf() followed by Fail(). 
+       func (c *T) Errorf(format string, args ...interface{})
+
+       // Fail marks the function as having failed but continues ...
+       func (c *T) Fail()
+
+       // FailNow marks the function as having failed and stops its ...
+       func (c *T) FailNow()
+
+       // Failed returns whether the function has failed. 
+       func (c *T) Failed() bool
+
+       // Fatal is equivalent to Log() followed by FailNow(). 
+       func (c *T) Fatal(args ...interface{})
+
+       // Fatalf is equivalent to Logf() followed by FailNow(). 
+       func (c *T) Fatalf(format string, args ...interface{})
+
+       // Log formats its arguments using default formatting, analogous ...
+       func (c *T) Log(args ...interface{})
+
+       // Logf formats its arguments according to the format, analogous ...
+       func (c *T) Logf(format string, args ...interface{})
+
+       // Parallel signals that this test is to be run in parallel with ...
+       func (t *T) Parallel()
+
+       // log generates the output. It's always at the same stack depth. 
+       func (c *T) log(s string)
+
+       // 
+       func (t *T) report()
+
+       // common holds the elements common between T and B and captures ...
+       type common struct {
+               output          []byte          // Output generated by test or benchmark.
+               failed          bool            // Test or benchmark has failed.
+               start           time.Time       // Time test or benchmark started
+               duration        time.Duration
+               self            interface{}             // To be sent on signal channel when done.
+               signal          chan interface{}        // Output for serial tests.
+       }
+
+       // Error is equivalent to Log() followed by Fail(). 
+       func (c *common) Error(args ...interface{})
+
+       // Errorf is equivalent to Logf() followed by Fail(). 
+       func (c *common) Errorf(format string, args ...interface{})
+
+       // Fail marks the function as having failed but continues ...
+       func (c *common) Fail()
+
+       // FailNow marks the function as having failed and stops its ...
+       func (c *common) FailNow()
+
+       // Failed returns whether the function has failed. 
+       func (c *common) Failed() bool
+
+       // Fatal is equivalent to Log() followed by FailNow(). 
+       func (c *common) Fatal(args ...interface{})
+
+       // Fatalf is equivalent to Logf() followed by FailNow(). 
+       func (c *common) Fatalf(format string, args ...interface{})
+
+       // Log formats its arguments using default formatting, analogous ...
+       func (c *common) Log(args ...interface{})
+
+       // Logf formats its arguments according to the format, analogous ...
+       func (c *common) Logf(format string, args ...interface{})
+
+       // log generates the output. It's always at the same stack depth. 
+       func (c *common) log(s string)
+
index 4b72f38518eeb8636c9995f3497a20e9d8dda3a7..f1b4ce34d1a04fc33a4c37f735d7b023497c3c06 100644 (file)
@@ -45,12 +45,14 @@ func readSource(filename string, src interface{}) ([]byte, error) {
        return ioutil.ReadFile(filename)
 }
 
-// The mode parameter to the Parse* functions is a set of flags (or 0).
+// A Mode value is a set of flags (or 0).
 // They control the amount of source code parsed and other optional
 // parser functionality.
 //
+type Mode uint
+
 const (
-       PackageClauseOnly uint = 1 << iota // parsing stops after package clause
+       PackageClauseOnly Mode = 1 << iota // parsing stops after package clause
        ImportsOnly                        // parsing stops after import declarations
        ParseComments                      // parse comments and add them to AST
        Trace                              // print a trace of parsed productions
@@ -77,7 +79,7 @@ const (
 // representing the fragments of erroneous source code). Multiple errors
 // are returned via a scanner.ErrorList which is sorted by file position.
 //
-func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint) (*ast.File, error) {
+func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (*ast.File, error) {
        text, err := readSource(filename, src)
        if err != nil {
                return nil, err
@@ -97,7 +99,7 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint)
 // returned. If a parse error occurred, a non-nil but incomplete map and the
 // first error encountered are returned.
 //
-func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode uint) (pkgs map[string]*ast.Package, first error) {
+func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) {
        fd, err := os.Open(path)
        if err != nil {
                return nil, err
@@ -117,7 +119,10 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
                                name := src.Name.Name
                                pkg, found := pkgs[name]
                                if !found {
-                                       pkg = &ast.Package{name, nil, nil, make(map[string]*ast.File)}
+                                       pkg = &ast.Package{
+                                               Name:  name,
+                                               Files: make(map[string]*ast.File),
+                                       }
                                        pkgs[name] = pkg
                                }
                                pkg.Files[filename] = src
index d90f5775df45eff5c6b51c10bffdb62a8e583f5d..6bee8de9f65e04fc3a95ca9be548d3f6a4cd0502 100644 (file)
@@ -23,7 +23,7 @@ type parser struct {
        scanner scanner.Scanner
 
        // Tracing/debugging
-       mode   uint // parsing mode
+       mode   Mode // parsing mode
        trace  bool // == (mode & Trace != 0)
        indent uint // indentation used for tracing output
 
@@ -52,9 +52,9 @@ type parser struct {
        targetStack [][]*ast.Ident // stack of unresolved labels
 }
 
-func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode uint) {
+func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) {
        p.file = fset.AddFile(filename, fset.Base(), len(src))
-       var m uint
+       var m scanner.Mode
        if mode&ParseComments != 0 {
                m = scanner.ScanComments
        }
index 6817cc42addef4323dd9dd22dd9083b52ef35eac..5f3b4d4a740b8dcc58649c710ba2bc0dda625ecf 100644 (file)
@@ -72,7 +72,7 @@ func (p *printer) setComment(g *ast.CommentGroup) {
                // for some reason there are pending comments; this
                // should never happen - handle gracefully and flush
                // all comments up to g, ignore anything after that
-               p.flush(p.fset.Position(g.List[0].Pos()), token.ILLEGAL)
+               p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL)
        }
        p.comments[0] = g
        p.cindex = 0
@@ -122,10 +122,10 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
                p.print(blank)
        }
 
-       prev := p.fset.Position(prev0)
-       next := p.fset.Position(next0)
-       line := p.fset.Position(list[0].Pos()).Line
-       endLine := p.fset.Position(list[len(list)-1].End()).Line
+       prev := p.posFor(prev0)
+       next := p.posFor(next0)
+       line := p.lineFor(list[0].Pos())
+       endLine := p.lineFor(list[len(list)-1].End())
 
        if prev.IsValid() && prev.Line == line && line == endLine {
                // all list entries on a single line
@@ -169,7 +169,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
        // print all list elements
        for i, x := range list {
                prevLine := line
-               line = p.fset.Position(x.Pos()).Line
+               line = p.lineFor(x.Pos())
 
                // determine if the next linebreak, if any, needs to use formfeed:
                // in general, use the entire node size to make the decision; for
@@ -272,23 +272,32 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
        p.print(fields.Opening, token.LPAREN)
        if len(fields.List) > 0 {
+               prevLine := p.lineFor(fields.Opening)
                ws := indent
-               var prevLine, line int
                for i, par := range fields.List {
+                       // determine par begin and end line (may be different
+                       // if there are multiple parameter names for this par
+                       // or the type is on a separate line)
+                       var parLineBeg int
+                       var parLineEnd = p.lineFor(par.Type.Pos())
+                       if len(par.Names) > 0 {
+                               parLineBeg = p.lineFor(par.Names[0].Pos())
+                       } else {
+                               parLineBeg = parLineEnd
+                       }
+                       // separating "," if needed
                        if i > 0 {
                                p.print(token.COMMA)
-                               if len(par.Names) > 0 {
-                                       line = p.fset.Position(par.Names[0].Pos()).Line
-                               } else {
-                                       line = p.fset.Position(par.Type.Pos()).Line
-                               }
-                               if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ws, true) {
-                                       ws = ignore
-                                       *multiLine = true
-                               } else {
-                                       p.print(blank)
-                               }
                        }
+                       // separator if needed (linebreak or blank)
+                       if 0 < prevLine && prevLine < parLineBeg && p.linebreak(parLineBeg, 0, ws, true) {
+                               // break line if the opening "(" or previous parameter ended on a different line
+                               ws = ignore
+                               *multiLine = true
+                       } else if i > 0 {
+                               p.print(blank)
+                       }
+                       // parameter names
                        if len(par.Names) > 0 {
                                // Very subtle: If we indented before (ws == ignore), identList
                                // won't indent again. If we didn't (ws == indent), identList will
@@ -299,11 +308,18 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
                                p.identList(par.Names, ws == indent, multiLine)
                                p.print(blank)
                        }
+                       // parameter type
                        p.expr(par.Type, multiLine)
-                       prevLine = p.fset.Position(par.Type.Pos()).Line
+                       prevLine = parLineEnd
                }
+               // if the closing ")" is on a separate line from the last parameter,
+               // print an additional "," and line break
+               if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
+                       p.print(",")
+                       p.linebreak(closing, 0, ignore, true)
+               }
+               // unindent if we indented
                if ws == ignore {
-                       // unindent if we indented
                        p.print(unindent)
                }
        }
@@ -364,8 +380,8 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
        lbrace := fields.Opening
        list := fields.List
        rbrace := fields.Closing
-       hasComments := isIncomplete || p.commentBefore(p.fset.Position(rbrace))
-       srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.fset.Position(lbrace).Line == p.fset.Position(rbrace).Line
+       hasComments := isIncomplete || p.commentBefore(p.posFor(rbrace))
+       srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.lineFor(lbrace) == p.lineFor(rbrace)
 
        if !hasComments && srcIsOneLine {
                // possibly a one-line struct/interface
@@ -408,7 +424,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
                var ml bool
                for i, f := range list {
                        if i > 0 {
-                               p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
+                               p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml)
                        }
                        ml = false
                        extraTabs := 0
@@ -443,7 +459,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
                        if len(list) > 0 {
                                p.print(formfeed)
                        }
-                       p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+                       p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
                        p.setLineComment("// contains filtered or unexported fields")
                }
 
@@ -452,7 +468,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
                var ml bool
                for i, f := range list {
                        if i > 0 {
-                               p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml)
+                               p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml)
                        }
                        ml = false
                        p.setComment(f.Doc)
@@ -470,7 +486,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
                        if len(list) > 0 {
                                p.print(formfeed)
                        }
-                       p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment
+                       p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
                        p.setLineComment("// contains filtered or unexported methods")
                }
 
@@ -626,7 +642,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
                p.print(blank)
        }
        xline := p.pos.Line // before the operator (it may be on the next line!)
-       yline := p.fset.Position(x.Y.Pos()).Line
+       yline := p.lineFor(x.Y.Pos())
        p.print(x.OpPos, x.Op)
        if xline != yline && xline > 0 && yline > 0 {
                // at least one line break, but respect an extra empty line
@@ -919,7 +935,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
        for i, s := range list {
                // _indent == 0 only for lists of switch/select case clauses;
                // in those cases each clause is a new section
-               p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, i == 0 || _indent == 0 || multiLine)
+               p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine)
                multiLine = false
                p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine)
        }
@@ -932,7 +948,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
 func (p *printer) block(s *ast.BlockStmt, indent int) {
        p.print(s.Pos(), token.LBRACE)
        p.stmtList(s.List, indent, true)
-       p.linebreak(p.fset.Position(s.Rbrace).Line, 1, ignore, true)
+       p.linebreak(p.lineFor(s.Rbrace), 1, ignore, true)
        p.print(s.Rbrace, token.RBRACE)
 }
 
@@ -1033,7 +1049,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
                                break
                        }
                } else {
-                       p.linebreak(p.fset.Position(s.Stmt.Pos()).Line, 1, ignore, true)
+                       p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true)
                }
                p.stmt(s.Stmt, nextIsRBrace, multiLine)
 
@@ -1145,7 +1161,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
        case *ast.SelectStmt:
                p.print(token.SELECT, blank)
                body := s.Body
-               if len(body.List) == 0 && !p.commentBefore(p.fset.Position(body.Rbrace)) {
+               if len(body.List) == 0 && !p.commentBefore(p.posFor(body.Rbrace)) {
                        // print empty select statement w/o comments on one line
                        p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE)
                } else {
@@ -1337,7 +1353,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
                                var ml bool
                                for i, s := range d.Specs {
                                        if i > 0 {
-                                               p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml)
+                                               p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml)
                                        }
                                        ml = false
                                        p.valueSpec(s.(*ast.ValueSpec), keepType[i], false, &ml)
@@ -1346,7 +1362,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
                                var ml bool
                                for i, s := range d.Specs {
                                        if i > 0 {
-                                               p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml)
+                                               p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml)
                                        }
                                        ml = false
                                        p.spec(s, n, false, &ml)
@@ -1403,11 +1419,11 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
 func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
        pos1 := b.Pos()
        pos2 := b.Rbrace
-       if pos1.IsValid() && pos2.IsValid() && p.fset.Position(pos1).Line != p.fset.Position(pos2).Line {
+       if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) {
                // opening and closing brace are on different lines - don't make it a one-liner
                return false
        }
-       if len(b.List) > 5 || p.commentBefore(p.fset.Position(pos2)) {
+       if len(b.List) > 5 || p.commentBefore(p.posFor(pos2)) {
                // too many statements or there is a comment inside - don't make it a one-liner
                return false
        }
@@ -1458,7 +1474,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
 // are on the same line; if they are on different lines (or unknown)
 // the result is infinity.
 func (p *printer) distance(from0 token.Pos, to token.Position) int {
-       from := p.fset.Position(from0)
+       from := p.posFor(from0)
        if from.IsValid() && to.IsValid() && from.Line == to.Line {
                return to.Column - from.Column
        }
@@ -1527,7 +1543,7 @@ func (p *printer) file(src *ast.File) {
                        if prev != tok || getDoc(d) != nil {
                                min = 2
                        }
-                       p.linebreak(p.fset.Position(d.Pos()).Line, min, ignore, false)
+                       p.linebreak(p.lineFor(d.Pos()), min, ignore, false)
                        p.decl(d, ignoreMultiLine)
                }
        }
index c720f2e665c479b263edd5c399a2573ac6b2e523..52dfff6f4b369863f55f3197971ea4d4a2f929c9 100644 (file)
@@ -75,6 +75,10 @@ type printer struct {
 
        // Cache of already computed node sizes.
        nodeSizes map[ast.Node]int
+
+       // Cache of most recently computed line position.
+       cachedPos  token.Pos
+       cachedLine int // line corresponding to cachedPos
 }
 
 func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]int) {
@@ -82,6 +86,7 @@ func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]
        p.fset = fset
        p.wsbuf = make([]whiteSpace, 0, 16) // whitespace sequences are short
        p.nodeSizes = nodeSizes
+       p.cachedPos = -1
 }
 
 func (p *printer) internalError(msg ...interface{}) {
@@ -92,6 +97,19 @@ func (p *printer) internalError(msg ...interface{}) {
        }
 }
 
+func (p *printer) posFor(pos token.Pos) token.Position {
+       // not used frequently enough to cache entire token.Position
+       return p.fset.Position(pos)
+}
+
+func (p *printer) lineFor(pos token.Pos) int {
+       if pos != p.cachedPos {
+               p.cachedPos = pos
+               p.cachedLine = p.fset.Position(pos).Line
+       }
+       return p.cachedLine
+}
+
 // writeByte writes ch to p.output and updates p.pos.
 func (p *printer) writeByte(ch byte) {
        p.output.WriteByte(ch)
@@ -529,7 +547,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
 
        // shortcut common case of //-style comments
        if text[1] == '/' {
-               p.writeItem(p.fset.Position(comment.Pos()), text, true)
+               p.writeItem(p.posFor(comment.Pos()), text, true)
                return
        }
 
@@ -540,7 +558,7 @@ func (p *printer) writeComment(comment *ast.Comment) {
 
        // write comment lines, separated by formfeed,
        // without a line break after the last line
-       pos := p.fset.Position(comment.Pos())
+       pos := p.posFor(comment.Pos())
        for i, line := range lines {
                if i > 0 {
                        p.writeByte('\f')
@@ -602,14 +620,14 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (wro
        var last *ast.Comment
        for ; p.commentBefore(next); p.cindex++ {
                for _, c := range p.comments[p.cindex].List {
-                       p.writeCommentPrefix(p.fset.Position(c.Pos()), next, last, c, tok.IsKeyword())
+                       p.writeCommentPrefix(p.posFor(c.Pos()), next, last, c, tok.IsKeyword())
                        p.writeComment(c)
                        last = c
                }
        }
 
        if last != nil {
-               if last.Text[1] == '*' && p.fset.Position(last.Pos()).Line == next.Line {
+               if last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line {
                        // the last comment is a /*-style comment and the next item
                        // follows on the same line: separate with an extra blank
                        p.writeByte(' ')
@@ -770,7 +788,7 @@ func (p *printer) print(args ...interface{}) {
                        tok = x
                case token.Pos:
                        if x.IsValid() {
-                               next = p.fset.Position(x) // accurate position of next item
+                               next = p.posFor(x) // accurate position of next item
                        }
                        tok = p.lastTok
                case string:
@@ -813,7 +831,7 @@ func (p *printer) print(args ...interface{}) {
 // before the next position in the source code.
 //
 func (p *printer) commentBefore(next token.Position) bool {
-       return p.cindex < len(p.comments) && p.fset.Position(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset
+       return p.cindex < len(p.comments) && p.posFor(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset
 }
 
 // Flush prints any pending comments and whitespace occurring textually
index 239ba890304599a0305f5567c666f3c518461fde..928b8ce0a9f826b1f9bf92b72493cbd82c7c19c0 100644 (file)
@@ -773,30 +773,39 @@ func ManageStatus(in <-chan *Status, req <-chan Request,
        TargetHistorySize int) {
 }
 
-func MultiLineSignature0(a, b, c int) {
+func MultiLineSignature0(
+       a, b, c int,
+) {
 }
 
-func MultiLineSignature1(a, b, c int,
-       u, v, w float) {
+func MultiLineSignature1(
+       a, b, c int,
+       u, v, w float,
+) {
 }
 
-func MultiLineSignature2(a, b,
-       c int) {
+func MultiLineSignature2(
+       a, b,
+       c int,
+) {
 }
 
-func MultiLineSignature3(a, b,
+func MultiLineSignature3(
+       a, b,
        c int, u, v,
        w float,
        x ...int) {
 }
 
-func MultiLineSignature4(a, b, c int,
+func MultiLineSignature4(
+       a, b, c int,
        u, v,
        w float,
        x ...int) {
 }
 
-func MultiLineSignature5(a, b, c int,
+func MultiLineSignature5(
+       a, b, c int,
        u, v, w float,
        p, q,
        r string,
@@ -805,25 +814,34 @@ func MultiLineSignature5(a, b, c int,
 
 // make sure it also works for methods in interfaces
 type _ interface {
-       MultiLineSignature0(a, b, c int)
+       MultiLineSignature0(
+               a, b, c int,
+       )
 
-       MultiLineSignature1(a, b, c int,
-               u, v, w float)
+       MultiLineSignature1(
+               a, b, c int,
+               u, v, w float,
+       )
 
-       MultiLineSignature2(a, b,
-               c int)
+       MultiLineSignature2(
+               a, b,
+               c int,
+       )
 
-       MultiLineSignature3(a, b,
+       MultiLineSignature3(
+               a, b,
                c int, u, v,
                w float,
                x ...int)
 
-       MultiLineSignature4(a, b, c int,
+       MultiLineSignature4(
+               a, b, c int,
                u, v,
                w float,
                x ...int)
 
-       MultiLineSignature5(a, b, c int,
+       MultiLineSignature5(
+               a, b, c int,
                u, v, w float,
                p, q,
                r string,
index be780da677a156138d906c2ab2e3f42d48cff774..006cf1718483d97da5a9d38d2d5db867a11407ed 100644 (file)
@@ -220,4 +220,56 @@ testLoop:
        }
 }
 
+// Respect line breaks in function calls.
+func _() {
+       f(x)
+       f(x,
+               x)
+       f(x,
+               x,
+       )
+       f(
+               x,
+               x)
+       f(
+               x,
+               x,
+       )
+}
+
+// Respect line breaks in function declarations.
+func _(x T)    {}
+func _(x T,
+       y T) {
+}
+func _(x T,
+       y T,
+) {
+}
+func _(
+       x T,
+       y T) {
+}
+func _(
+       x T,
+       y T,
+) {
+}
+
+// Example from issue 2597.
+func ManageStatus0(
+       in <-chan *Status,
+       req <-chan Request,
+       stat chan<- *TargetInfo,
+       TargetHistorySize int) {
+}
+
+func ManageStatus1(
+       in <-chan *Status,
+       req <-chan Request,
+       stat chan<- *TargetInfo,
+       TargetHistorySize int,
+) {
+}
+
 // There should be exactly one linebreak after this comment.
index 457b491e6d210af74808bc64e80220fa0a92d2be..e782bb04443702ecc1d94d2fe8bcab776478d723 100644 (file)
@@ -220,4 +220,52 @@ testLoop:
        }
 }
 
+// Respect line breaks in function calls.
+func _() {
+       f(x)
+       f(x,
+         x)
+       f(x,
+         x,
+       )
+       f(
+         x,
+         x)
+       f(
+         x,
+         x,
+       )
+}
+
+// Respect line breaks in function declarations.
+func _(x T) {}
+func _(x T,
+       y T) {}
+func _(x T,
+       y T,
+) {}
+func _(
+       x T,
+       y T) {}
+func _(
+       x T,
+       y T,
+) {}
+
+// Example from issue 2597.
+func ManageStatus0(
+       in <-chan *Status,
+       req <-chan Request,
+       stat chan<- *TargetInfo,
+       TargetHistorySize int) {
+}
+    
+func ManageStatus1(
+       in <-chan *Status,
+       req <-chan Request,
+       stat chan<- *TargetInfo,
+       TargetHistorySize int,
+) {
+}
+    
 // There should be exactly one linebreak after this comment.
index 05665b25487e58d5385a522b50f54d43848749ed..7c72c0a46b922372165aa1b1f47185962d95ac14 100644 (file)
@@ -40,7 +40,7 @@ type Scanner struct {
        dir  string       // directory portion of file.Name()
        src  []byte       // source
        err  ErrorHandler // error reporting; or nil
-       mode uint         // scanning mode
+       mode Mode         // scanning mode
 
        // scanning state
        ch         rune // current character
@@ -86,12 +86,14 @@ func (S *Scanner) next() {
        }
 }
 
-// The mode parameter to the Init function is a set of flags (or 0).
+// A mode value is set of flags (or 0).
 // They control scanner behavior.
 //
+type Mode uint
+
 const (
-       ScanComments    = 1 << iota // return comments as COMMENT tokens
-       dontInsertSemis             // do not automatically insert semicolons - for testing only
+       ScanComments    Mode = 1 << iota // return comments as COMMENT tokens
+       dontInsertSemis                  // do not automatically insert semicolons - for testing only
 )
 
 // Init prepares the scanner S to tokenize the text src by setting the
@@ -109,7 +111,7 @@ const (
 // Note that Init may call err if there is an error in the first character
 // of the file.
 //
-func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode uint) {
+func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) {
        // Explicitly initialize all fields since a scanner may be reused.
        if file.Size() != len(src) {
                panic("file size does not match src len")
index 2e4dd4fff638860b79aaf2a1e8a86930a014060f..af45bc5b1c8af8788a4275c07a97def3fd573867 100644 (file)
@@ -281,7 +281,7 @@ func TestScan(t *testing.T) {
        }
 }
 
-func checkSemi(t *testing.T, line string, mode uint) {
+func checkSemi(t *testing.T, line string, mode Mode) {
        var S Scanner
        file := fset.AddFile("TestSemis", fset.Base(), len(line))
        S.Init(file, []byte(line), nil, mode)
index 42be865ef080ad0b7c2a843da63dac852f40f25c..c0b5262af83a712ba572982a3daaa8ab6607dd87 100644 (file)
@@ -10,6 +10,10 @@ import (
        "unicode/utf8"
 )
 
+type writer interface {
+       WriteString(string) (int, error)
+}
+
 // 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
index 65f4b3ac2e57725f2b08c89472823df1f4a8792d..cbe1a5839df3256c109099b9ece9621d84b2901d 100644 (file)
@@ -14,9 +14,22 @@ import (
 
 // readAll reads from r until an error or EOF and returns the data it read
 // from the internal buffer allocated with a specified capacity.
-func readAll(r io.Reader, capacity int64) ([]byte, error) {
+func readAll(r io.Reader, capacity int64) (b []byte, err error) {
        buf := bytes.NewBuffer(make([]byte, 0, capacity))
-       _, err := buf.ReadFrom(r)
+       // If the buffer overflows, we will get bytes.ErrTooLarge.
+       // Return that as an error. Any other panic remains.
+       defer func() {
+               e := recover()
+               if e == nil {
+                       return
+               }
+               if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
+                       err = panicErr
+               } else {
+                       panic(e)
+               }
+       }()
+       _, err = buf.ReadFrom(r)
        return buf.Bytes(), err
 }
 
index 242bd1e8cc42d66c6cd28e2bee93bbb16f728375..41de17ba416f50bae06bf0f30a70e538ef3e01d8 100644 (file)
@@ -54,6 +54,7 @@ func subWW_g(x, y, c Word) (z1, z0 Word) {
 
 // z1<<_W + z0 = x*y
 func mulWW(x, y Word) (z1, z0 Word) { return mulWW_g(x, y) }
+
 // Adapted from Warren, Hacker's Delight, p. 132.
 func mulWW_g(x, y Word) (z1, z0 Word) {
        x0 := x & _M2
@@ -80,11 +81,24 @@ func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
 }
 
 // Length of x in bits.
-func bitLen(x Word) (n int) {
-       for ; x >= 0x100; x >>= 8 {
+func bitLen(x Word) (n int) { return bitLen_g(x) }
+func bitLen_g(x Word) (n int) {
+       for ; x >= 0x8000; x >>= 16 {
+               n += 16
+       }
+       if x >= 0x80 {
+               x >>= 8
                n += 8
        }
-       for ; x > 0; x >>= 1 {
+       if x >= 0x8 {
+               x >>= 4
+               n += 4
+       }
+       if x >= 0x2 {
+               x >>= 2
+               n += 2
+       }
+       if x >= 0x1 {
                n++
        }
        return
@@ -104,6 +118,7 @@ func leadingZeros(x Word) uint {
 
 // q = (u1<<_W + u0 - r)/y
 func divWW(x1, x0, y Word) (q, r Word) { return divWW_g(x1, x0, y) }
+
 // Adapted from Warren, Hacker's Delight, p. 152.
 func divWW_g(u1, u0, v Word) (q, r Word) {
        if u1 >= v {
index 95fcd8b94bed8208cd7bac115e3d970eeb951ae7..068cc8d93888f82385d614b4e5e023b865707b28 100644 (file)
@@ -16,3 +16,4 @@ func shrVU(z, x []Word, s uint) (c Word)
 func mulAddVWW(z, x []Word, y, r Word) (c Word)
 func addMulVVW(z, x []Word, y Word) (c Word)
 func divWVW(z []Word, xn Word, x []Word, y Word) (r Word)
+func bitLen(x Word) (n int)
index b6c56c39ef4756a65ec1dbee6f76aec203c3e498..c7e3d284c2de624679f0104b6f1e1963d0790a46 100644 (file)
@@ -333,3 +333,40 @@ func TestMulAddWWW(t *testing.T) {
                }
        }
 }
+
+func testWordBitLen(t *testing.T, fname string, f func(Word) int) {
+       for i := 0; i <= _W; i++ {
+               x := Word(1) << uint(i-1) // i == 0 => x == 0
+               n := f(x)
+               if n != i {
+                       t.Errorf("got %d; want %d for %s(%#x)", n, i, fname, x)
+               }
+       }
+}
+
+func TestWordBitLen(t *testing.T) {
+       testWordBitLen(t, "bitLen", bitLen)
+       testWordBitLen(t, "bitLen_g", bitLen_g)
+}
+
+// runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
+func benchmarkBitLenN(b *testing.B, nbits uint) {
+       testword := Word((uint64(1) << nbits) - 1)
+       for i := 0; i < b.N; i++ {
+               bitLen(testword)
+       }
+}
+
+// Individual bitLen tests.  Numbers chosen to examine both sides
+// of powers-of-two boundaries.
+func BenchmarkBitLen0(b *testing.B)  { benchmarkBitLenN(b, 0) }
+func BenchmarkBitLen1(b *testing.B)  { benchmarkBitLenN(b, 1) }
+func BenchmarkBitLen2(b *testing.B)  { benchmarkBitLenN(b, 2) }
+func BenchmarkBitLen3(b *testing.B)  { benchmarkBitLenN(b, 3) }
+func BenchmarkBitLen4(b *testing.B)  { benchmarkBitLenN(b, 4) }
+func BenchmarkBitLen5(b *testing.B)  { benchmarkBitLenN(b, 5) }
+func BenchmarkBitLen8(b *testing.B)  { benchmarkBitLenN(b, 8) }
+func BenchmarkBitLen9(b *testing.B)  { benchmarkBitLenN(b, 9) }
+func BenchmarkBitLen16(b *testing.B) { benchmarkBitLenN(b, 16) }
+func BenchmarkBitLen17(b *testing.B) { benchmarkBitLenN(b, 17) }
+func BenchmarkBitLen31(b *testing.B) { benchmarkBitLenN(b, 31) }
index 66aff837d0a412fc2529b874152600fd46e6b5d2..52e57d7400e075ef3f6ee968bed1616ee93ed792 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nocgo
+// +build !cgo
 
 // Stub cgo routines for systems that do not use cgo to do network lookups.
 
index 00acb8477d22dee3b555402b1aa7f50a4f675735..5d596bcb6b4b93bee0f337f5784233bade38cbec 100644 (file)
@@ -8,24 +8,59 @@ import (
        "time"
 )
 
-func resolveNetAddr(op, net, addr string) (a Addr, err error) {
-       if addr == "" {
-               return nil, &OpError{op, net, nil, errMissingAddress}
+func parseDialNetwork(net string) (afnet string, proto int, err error) {
+       i := last(net, ':')
+       if i < 0 { // no colon
+               switch net {
+               case "tcp", "tcp4", "tcp6":
+               case "udp", "udp4", "udp6":
+               case "unix", "unixgram", "unixpacket":
+               default:
+                       return "", 0, UnknownNetworkError(net)
+               }
+               return net, 0, nil
        }
-       switch net {
-       case "tcp", "tcp4", "tcp6":
-               a, err = ResolveTCPAddr(net, addr)
-       case "udp", "udp4", "udp6":
-               a, err = ResolveUDPAddr(net, addr)
-       case "unix", "unixgram", "unixpacket":
-               a, err = ResolveUnixAddr(net, addr)
+       afnet = net[:i]
+       switch afnet {
        case "ip", "ip4", "ip6":
-               a, err = ResolveIPAddr(net, addr)
-       default:
-               err = UnknownNetworkError(net)
+               protostr := net[i+1:]
+               proto, i, ok := dtoi(protostr, 0)
+               if !ok || i != len(protostr) {
+                       proto, err = lookupProtocol(protostr)
+                       if err != nil {
+                               return "", 0, err
+                       }
+               }
+               return afnet, proto, nil
        }
+       return "", 0, UnknownNetworkError(net)
+}
+
+func resolveNetAddr(op, net, addr string) (afnet string, a Addr, err error) {
+       afnet, _, err = parseDialNetwork(net)
        if err != nil {
-               return nil, &OpError{op, net + " " + addr, nil, err}
+               return "", nil, &OpError{op, net, nil, err}
+       }
+       if op == "dial" && addr == "" {
+               return "", nil, &OpError{op, net, nil, errMissingAddress}
+       }
+       switch afnet {
+       case "tcp", "tcp4", "tcp6":
+               if addr != "" {
+                       a, err = ResolveTCPAddr(afnet, addr)
+               }
+       case "udp", "udp4", "udp6":
+               if addr != "" {
+                       a, err = ResolveUDPAddr(afnet, addr)
+               }
+       case "ip", "ip4", "ip6":
+               if addr != "" {
+                       a, err = ResolveIPAddr(afnet, addr)
+               }
+       case "unix", "unixgram", "unixpacket":
+               if addr != "" {
+                       a, err = ResolveUnixAddr(afnet, addr)
+               }
        }
        return
 }
@@ -34,20 +69,27 @@ func resolveNetAddr(op, net, addr string) (a Addr, err error) {
 //
 // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
 // "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
-// (IPv4-only), "ip6" (IPv6-only), "unix" and "unixgram".
+// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and "unixpacket".
 //
-// For IP networks, addresses have the form host:port.  If host is
-// a literal IPv6 address, it must be enclosed in square brackets.
-// The functions JoinHostPort and SplitHostPort manipulate 
-// addresses in this form.
+// For TCP and UDP networks, addresses have the form host:port.
+// If host is a literal IPv6 address, it must be enclosed
+// in square brackets.  The functions JoinHostPort and SplitHostPort
+// manipulate addresses in this form.
 //
 // Examples:
 //     Dial("tcp", "12.34.56.78:80")
 //     Dial("tcp", "google.com:80")
 //     Dial("tcp", "[de:ad:be:ef::ca:fe]:80")
 //
+// For IP networks, addr must be "ip", "ip4" or "ip6" followed
+// by a colon and a protocol number or name.
+//
+// Examples:
+//     Dial("ip4:1", "127.0.0.1")
+//     Dial("ip6:ospf", "::1")
+//
 func Dial(net, addr string) (Conn, error) {
-       addri, err := resolveNetAddr("dial", net, addr)
+       _, addri, err := resolveNetAddr("dial", net, addr)
        if err != nil {
                return nil, err
        }
@@ -60,10 +102,10 @@ func dialAddr(net, addr string, addri Addr) (c Conn, err error) {
                c, err = DialTCP(net, nil, ra)
        case *UDPAddr:
                c, err = DialUDP(net, nil, ra)
-       case *UnixAddr:
-               c, err = DialUnix(net, nil, ra)
        case *IPAddr:
                c, err = DialIP(net, nil, ra)
+       case *UnixAddr:
+               c, err = DialUnix(net, nil, ra)
        default:
                err = &OpError{"dial", net + " " + addr, nil, UnknownNetworkError(net)}
        }
@@ -89,7 +131,7 @@ func DialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
        ch := make(chan pair, 1)
        resolvedAddr := make(chan Addr, 1)
        go func() {
-               addri, err := resolveNetAddr("dial", net, addr)
+               _, addri, err := resolveNetAddr("dial", net, addr)
                if err != nil {
                        ch <- pair{nil, err}
                        return
@@ -130,86 +172,57 @@ func (a stringAddr) Network() string { return a.net }
 func (a stringAddr) String() string  { return a.addr }
 
 // Listen announces on the local network address laddr.
-// The network string net must be a stream-oriented
-// network: "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
-func Listen(net, laddr string) (l Listener, err error) {
-       switch net {
+// The network string net must be a stream-oriented network:
+// "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
+func Listen(net, laddr string) (Listener, error) {
+       afnet, a, err := resolveNetAddr("listen", net, laddr)
+       if err != nil {
+               return nil, err
+       }
+       switch afnet {
        case "tcp", "tcp4", "tcp6":
                var la *TCPAddr
-               if laddr != "" {
-                       if la, err = ResolveTCPAddr(net, laddr); err != nil {
-                               return nil, err
-                       }
-               }
-               l, err := ListenTCP(net, la)
-               if err != nil {
-                       return nil, err
+               if a != nil {
+                       la = a.(*TCPAddr)
                }
-               return l, nil
+               return ListenTCP(afnet, la)
        case "unix", "unixpacket":
                var la *UnixAddr
-               if laddr != "" {
-                       if la, err = ResolveUnixAddr(net, laddr); err != nil {
-                               return nil, err
-                       }
-               }
-               l, err := ListenUnix(net, la)
-               if err != nil {
-                       return nil, err
+               if a != nil {
+                       la = a.(*UnixAddr)
                }
-               return l, nil
+               return ListenUnix(net, la)
        }
        return nil, UnknownNetworkError(net)
 }
 
 // ListenPacket announces on the local network address laddr.
 // The network string net must be a packet-oriented network:
-// "udp", "udp4", "udp6", or "unixgram".
-func ListenPacket(net, laddr string) (c PacketConn, err error) {
-       switch net {
+// "udp", "udp4", "udp6", "ip", "ip4", "ip6" or "unixgram".
+func ListenPacket(net, addr string) (PacketConn, error) {
+       afnet, a, err := resolveNetAddr("listen", net, addr)
+       if err != nil {
+               return nil, err
+       }
+       switch afnet {
        case "udp", "udp4", "udp6":
                var la *UDPAddr
-               if laddr != "" {
-                       if la, err = ResolveUDPAddr(net, laddr); err != nil {
-                               return nil, err
-                       }
+               if a != nil {
+                       la = a.(*UDPAddr)
                }
-               c, err := ListenUDP(net, la)
-               if err != nil {
-                       return nil, err
+               return ListenUDP(net, la)
+       case "ip", "ip4", "ip6":
+               var la *IPAddr
+               if a != nil {
+                       la = a.(*IPAddr)
                }
-               return c, nil
+               return ListenIP(net, la)
        case "unixgram":
                var la *UnixAddr
-               if laddr != "" {
-                       if la, err = ResolveUnixAddr(net, laddr); err != nil {
-                               return nil, err
-                       }
+               if a != nil {
+                       la = a.(*UnixAddr)
                }
-               c, err := DialUnix(net, la, nil)
-               if err != nil {
-                       return nil, err
-               }
-               return c, nil
+               return DialUnix(net, la, nil)
        }
-
-       var rawnet string
-       if rawnet, _, err = splitNetProto(net); err != nil {
-               switch rawnet {
-               case "ip", "ip4", "ip6":
-                       var la *IPAddr
-                       if laddr != "" {
-                               if la, err = ResolveIPAddr(rawnet, laddr); err != nil {
-                                       return nil, err
-                               }
-                       }
-                       c, err := ListenIP(net, la)
-                       if err != nil {
-                               return nil, err
-                       }
-                       return c, nil
-               }
-       }
-
        return nil, UnknownNetworkError(net)
 }
index 9ad1770dab7e5d26b0440177adbd2b9684422199..81750a3d73967b05f29889b9a507d16bc7dfc5a4 100644 (file)
@@ -19,7 +19,7 @@ var ipv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present")
 // fd is already connected to the destination, port 80.
 // Run an HTTP request to fetch the appropriate page.
 func fetchGoogle(t *testing.T, fd Conn, network, addr string) {
-       req := []byte("GET /intl/en/privacy/ HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
+       req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
        n, err := fd.Write(req)
 
        buf := make([]byte, 1000)
diff --git a/libgo/go/net/dict/dict.go b/libgo/go/net/dict/dict.go
deleted file mode 100644 (file)
index e7f5290..0000000
+++ /dev/null
@@ -1,210 +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 dict implements the Dictionary Server Protocol
-// as defined in RFC 2229.
-package dict
-
-import (
-       "net/textproto"
-       "strconv"
-       "strings"
-)
-
-// A Client represents a client connection to a dictionary server.
-type Client struct {
-       text *textproto.Conn
-}
-
-// Dial returns a new client connected to a dictionary server at
-// addr on the given network.
-func Dial(network, addr string) (*Client, error) {
-       text, err := textproto.Dial(network, addr)
-       if err != nil {
-               return nil, err
-       }
-       _, _, err = text.ReadCodeLine(220)
-       if err != nil {
-               text.Close()
-               return nil, err
-       }
-       return &Client{text: text}, nil
-}
-
-// Close closes the connection to the dictionary server.
-func (c *Client) Close() error {
-       return c.text.Close()
-}
-
-// A Dict represents a dictionary available on the server.
-type Dict struct {
-       Name string // short name of dictionary
-       Desc string // long description
-}
-
-// Dicts returns a list of the dictionaries available on the server.
-func (c *Client) Dicts() ([]Dict, error) {
-       id, err := c.text.Cmd("SHOW DB")
-       if err != nil {
-               return nil, err
-       }
-
-       c.text.StartResponse(id)
-       defer c.text.EndResponse(id)
-
-       _, _, err = c.text.ReadCodeLine(110)
-       if err != nil {
-               return nil, err
-       }
-       lines, err := c.text.ReadDotLines()
-       if err != nil {
-               return nil, err
-       }
-       _, _, err = c.text.ReadCodeLine(250)
-
-       dicts := make([]Dict, len(lines))
-       for i := range dicts {
-               d := &dicts[i]
-               a, _ := fields(lines[i])
-               if len(a) < 2 {
-                       return nil, textproto.ProtocolError("invalid dictionary: " + lines[i])
-               }
-               d.Name = a[0]
-               d.Desc = a[1]
-       }
-       return dicts, err
-}
-
-// A Defn represents a definition.
-type Defn struct {
-       Dict Dict   // Dict where definition was found
-       Word string // Word being defined
-       Text []byte // Definition text, typically multiple lines
-}
-
-// Define requests the definition of the given word.
-// The argument dict names the dictionary to use,
-// the Name field of a Dict returned by Dicts.
-//
-// The special dictionary name "*" means to look in all the
-// server's dictionaries.
-// The special dictionary name "!" means to look in all the
-// server's dictionaries in turn, stopping after finding the word
-// in one of them.
-func (c *Client) Define(dict, word string) ([]*Defn, error) {
-       id, err := c.text.Cmd("DEFINE %s %q", dict, word)
-       if err != nil {
-               return nil, err
-       }
-
-       c.text.StartResponse(id)
-       defer c.text.EndResponse(id)
-
-       _, line, err := c.text.ReadCodeLine(150)
-       if err != nil {
-               return nil, err
-       }
-       a, _ := fields(line)
-       if len(a) < 1 {
-               return nil, textproto.ProtocolError("malformed response: " + line)
-       }
-       n, err := strconv.Atoi(a[0])
-       if err != nil {
-               return nil, textproto.ProtocolError("invalid definition count: " + a[0])
-       }
-       def := make([]*Defn, n)
-       for i := 0; i < n; i++ {
-               _, line, err = c.text.ReadCodeLine(151)
-               if err != nil {
-                       return nil, err
-               }
-               a, _ := fields(line)
-               if len(a) < 3 {
-                       // skip it, to keep protocol in sync
-                       i--
-                       n--
-                       def = def[0:n]
-                       continue
-               }
-               d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}}
-               d.Text, err = c.text.ReadDotBytes()
-               if err != nil {
-                       return nil, err
-               }
-               def[i] = d
-       }
-       _, _, err = c.text.ReadCodeLine(250)
-       return def, err
-}
-
-// Fields returns the fields in s.
-// Fields are space separated unquoted words
-// or quoted with single or double quote.
-func fields(s string) ([]string, error) {
-       var v []string
-       i := 0
-       for {
-               for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
-                       i++
-               }
-               if i >= len(s) {
-                       break
-               }
-               if s[i] == '"' || s[i] == '\'' {
-                       q := s[i]
-                       // quoted string
-                       var j int
-                       for j = i + 1; ; j++ {
-                               if j >= len(s) {
-                                       return nil, textproto.ProtocolError("malformed quoted string")
-                               }
-                               if s[j] == '\\' {
-                                       j++
-                                       continue
-                               }
-                               if s[j] == q {
-                                       j++
-                                       break
-                               }
-                       }
-                       v = append(v, unquote(s[i+1:j-1]))
-                       i = j
-               } else {
-                       // atom
-                       var j int
-                       for j = i; j < len(s); j++ {
-                               if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' {
-                                       break
-                               }
-                       }
-                       v = append(v, s[i:j])
-                       i = j
-               }
-               if i < len(s) {
-                       c := s[i]
-                       if c != ' ' && c != '\t' {
-                               return nil, textproto.ProtocolError("quotes not on word boundaries")
-                       }
-               }
-       }
-       return v, nil
-}
-
-func unquote(s string) string {
-       if strings.Index(s, "\\") < 0 {
-               return s
-       }
-       b := []byte(s)
-       w := 0
-       for r := 0; r < len(b); r++ {
-               c := b[r]
-               if c == '\\' {
-                       r++
-                       c = b[r]
-               }
-               b[w] = c
-               w++
-       }
-       return string(b[0:w])
-}
index 7ecd135d20645c9ffa87e140336b1008e0756b47..495ef007fe20ea4a2b71efb2bd58f131155fe7ba 100644 (file)
@@ -22,15 +22,16 @@ type netFD struct {
        closing bool
 
        // immutable until Close
-       sysfd   int
-       family  int
-       sotype  int
-       sysfile *os.File
-       cr      chan bool
-       cw      chan bool
-       net     string
-       laddr   Addr
-       raddr   Addr
+       sysfd       int
+       family      int
+       sotype      int
+       isConnected bool
+       sysfile     *os.File
+       cr          chan bool
+       cw          chan bool
+       net         string
+       laddr       Addr
+       raddr       Addr
 
        // owned by client
        rdeadline int64
index 6e37b4eb6f1a26e231ab239754c3039a89504536..f00459f0bafe194f2c483429e2d789b6c34cabac 100644 (file)
@@ -228,14 +228,15 @@ type netFD struct {
        closing bool
 
        // immutable until Close
-       sysfd   syscall.Handle
-       family  int
-       sotype  int
-       net     string
-       laddr   Addr
-       raddr   Addr
-       resultc [2]chan ioResult // read/write completion results
-       errnoc  [2]chan error    // read/write submit or cancel operation errors
+       sysfd       syscall.Handle
+       family      int
+       sotype      int
+       isConnected bool
+       net         string
+       laddr       Addr
+       raddr       Addr
+       resultc     [2]chan ioResult // read/write completion results
+       errnoc      [2]chan error    // read/write submit or cancel operation errors
 
        // owned by client
        rdeadline int64
index 1d70672695c7ac1d717e7f119f4cd9b25c08b746..c9f024017573ea107bb42443a3b56f80badea05a 100644 (file)
@@ -116,6 +116,10 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
                return nil, errors.New("http: nil Request.URL")
        }
 
+       if req.RequestURI != "" {
+               return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
+       }
+
        // Most the callers of send (Get, Post, et al) don't need
        // Headers, leaving it uninitialized.  We guarantee to the
        // Transport that this has been initialized, though.
index c74611011a819f7661d882e2de843628f2ffb1f0..aa0bf4be676a23486a3074f15c93b9aa17a5ce46 100644 (file)
@@ -428,3 +428,15 @@ func TestClientInsecureTransport(t *testing.T) {
                }
        }
 }
+
+func TestClientErrorWithRequestURI(t *testing.T) {
+       req, _ := NewRequest("GET", "http://localhost:1234/", nil)
+       req.RequestURI = "/this/field/is/illegal/and/should/error/"
+       _, err := DefaultClient.Do(req)
+       if err == nil {
+               t.Fatalf("expected an error")
+       }
+       if !strings.Contains(err.Error(), "RequestURI") {
+               t.Errorf("wanted error mentioning RequestURI; got error: %v", err)
+       }
+}
index da3e4050fe11368b830df4b70bc62506507e2259..2e03c658aa90bdb6ada675e8970c61e558aaf185 100644 (file)
@@ -64,6 +64,7 @@ var reqTests = []reqTest{
                        Close:         false,
                        ContentLength: 7,
                        Host:          "www.techcrunch.com",
+                       RequestURI:    "http://www.techcrunch.com/",
                },
 
                "abcdef\n",
@@ -89,6 +90,7 @@ var reqTests = []reqTest{
                        Close:         false,
                        ContentLength: 0,
                        Host:          "foo.com",
+                       RequestURI:    "/",
                },
 
                noBody,
@@ -114,6 +116,7 @@ var reqTests = []reqTest{
                        Close:         false,
                        ContentLength: 0,
                        Host:          "test",
+                       RequestURI:    "//user@host/is/actually/a/path/",
                },
 
                noBody,
@@ -163,6 +166,7 @@ var reqTests = []reqTest{
                        Header:           Header{},
                        ContentLength:    -1,
                        Host:             "foo.com",
+                       RequestURI:       "/",
                },
 
                "foobar",
@@ -171,6 +175,78 @@ var reqTests = []reqTest{
                },
                noError,
        },
+
+       // CONNECT request with domain name:
+       {
+               "CONNECT www.google.com:443 HTTP/1.1\r\n\r\n",
+
+               &Request{
+                       Method: "CONNECT",
+                       URL: &url.URL{
+                               Host: "www.google.com:443",
+                       },
+                       Proto:         "HTTP/1.1",
+                       ProtoMajor:    1,
+                       ProtoMinor:    1,
+                       Header:        Header{},
+                       Close:         false,
+                       ContentLength: 0,
+                       Host:          "www.google.com:443",
+                       RequestURI:    "www.google.com:443",
+               },
+
+               noBody,
+               noTrailer,
+               noError,
+       },
+
+       // CONNECT request with IP address:
+       {
+               "CONNECT 127.0.0.1:6060 HTTP/1.1\r\n\r\n",
+
+               &Request{
+                       Method: "CONNECT",
+                       URL: &url.URL{
+                               Host: "127.0.0.1:6060",
+                       },
+                       Proto:         "HTTP/1.1",
+                       ProtoMajor:    1,
+                       ProtoMinor:    1,
+                       Header:        Header{},
+                       Close:         false,
+                       ContentLength: 0,
+                       Host:          "127.0.0.1:6060",
+                       RequestURI:    "127.0.0.1:6060",
+               },
+
+               noBody,
+               noTrailer,
+               noError,
+       },
+
+       // CONNECT request for RPC:
+       {
+               "CONNECT /_goRPC_ HTTP/1.1\r\n\r\n",
+
+               &Request{
+                       Method: "CONNECT",
+                       URL: &url.URL{
+                               Path: "/_goRPC_",
+                       },
+                       Proto:         "HTTP/1.1",
+                       ProtoMajor:    1,
+                       ProtoMinor:    1,
+                       Header:        Header{},
+                       Close:         false,
+                       ContentLength: 0,
+                       Host:          "",
+                       RequestURI:    "/_goRPC_",
+               },
+
+               noBody,
+               noTrailer,
+               noError,
+       },
 }
 
 func TestReadRequest(t *testing.T) {
index 5a4e739073ac9278ef481c11d77bc6a37ddad9a6..5f8c00086bee74b09b5da98c1b4c1df3f6deab91 100644 (file)
@@ -153,6 +153,12 @@ type Request struct {
        // This field is ignored by the HTTP client.
        RemoteAddr string
 
+       // RequestURI is the unmodified Request-URI of the
+       // Request-Line (RFC 2616, Section 5.1) as sent by the client
+       // to a server. Usually the URL field should be used instead.
+       // It is an error to set this field in an HTTP client request.
+       RequestURI string
+
        // TLS allows HTTP servers and other software to record
        // information about the TLS connection on which the request
        // was received. This field is not filled in by ReadRequest.
@@ -305,6 +311,9 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
        ruri := req.URL.RequestURI()
        if usingProxy && req.URL.Scheme != "" && req.URL.Opaque == "" {
                ruri = req.URL.Scheme + "://" + host + ruri
+       } else if req.Method == "CONNECT" && req.URL.Path == "" {
+               // CONNECT requests normally give just the host and port, not a full URL.
+               ruri = host
        }
        // TODO(bradfitz): escape at least newlines in ruri?
 
@@ -456,17 +465,36 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
        if f = strings.SplitN(s, " ", 3); len(f) < 3 {
                return nil, &badStringError{"malformed HTTP request", s}
        }
-       var rawurl string
-       req.Method, rawurl, req.Proto = f[0], f[1], f[2]
+       req.Method, req.RequestURI, req.Proto = f[0], f[1], f[2]
+       rawurl := req.RequestURI
        var ok bool
        if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
                return nil, &badStringError{"malformed HTTP version", req.Proto}
        }
 
+       // CONNECT requests are used two different ways, and neither uses a full URL:
+       // The standard use is to tunnel HTTPS through an HTTP proxy.
+       // It looks like "CONNECT www.google.com:443 HTTP/1.1", and the parameter is
+       // just the authority section of a URL. This information should go in req.URL.Host.
+       //
+       // The net/rpc package also uses CONNECT, but there the parameter is a path
+       // that starts with a slash. It can be parsed with the regular URL parser,
+       // and the path will end up in req.URL.Path, where it needs to be in order for
+       // RPC to work.
+       justAuthority := req.Method == "CONNECT" && !strings.HasPrefix(rawurl, "/")
+       if justAuthority {
+               rawurl = "http://" + rawurl
+       }
+
        if req.URL, err = url.ParseRequest(rawurl); err != nil {
                return nil, err
        }
 
+       if justAuthority {
+               // Strip the bogus "http://" back off.
+               req.URL.Scheme = ""
+       }
+
        // Subsequent lines: Key: value.
        mimeHeader, err := tp.ReadMIMEHeader()
        if err != nil {
@@ -584,7 +612,7 @@ func (r *Request) ParseForm() (err error) {
                        return errors.New("missing form body")
                }
                ct := r.Header.Get("Content-Type")
-               ct, _, err := mime.ParseMediaType(ct)
+               ct, _, err = mime.ParseMediaType(ct)
                switch {
                case ct == "application/x-www-form-urlencoded":
                        var reader io.Reader = r.Body
@@ -624,8 +652,6 @@ func (r *Request) ParseForm() (err error) {
                        // Clean this up and write more tests.
                        // request_test.go contains the start of this,
                        // in TestRequestMultipartCallOrder.
-               default:
-                       return &badStringError{"unknown Content-Type", ct}
                }
        }
        return err
index 7b78645169eb56d65fcc110d2a5c562d709a4067..7a3556d03674c0ed057eed03ee2dfb29e19dd8b3 100644 (file)
@@ -46,19 +46,19 @@ func TestPostQuery(t *testing.T) {
 
 type stringMap map[string][]string
 type parseContentTypeTest struct {
+       shouldError bool
        contentType stringMap
 }
 
 var parseContentTypeTests = []parseContentTypeTest{
-       {contentType: stringMap{"Content-Type": {"text/plain"}}},
-       {contentType: stringMap{}}, // Non-existent keys are not placed. The value nil is illegal.
-       {contentType: stringMap{"Content-Type": {"text/plain; boundary="}}},
-       {
-               contentType: stringMap{"Content-Type": {"application/unknown"}},
-       },
+       {false, stringMap{"Content-Type": {"text/plain"}}},
+       // Non-existent keys are not placed. The value nil is illegal.
+       {true, stringMap{}},
+       {true, stringMap{"Content-Type": {"text/plain; boundary="}}},
+       {false, stringMap{"Content-Type": {"application/unknown"}}},
 }
 
-func TestParseFormBadContentType(t *testing.T) {
+func TestParseFormUnknownContentType(t *testing.T) {
        for i, test := range parseContentTypeTests {
                req := &Request{
                        Method: "POST",
@@ -66,8 +66,11 @@ func TestParseFormBadContentType(t *testing.T) {
                        Body:   ioutil.NopCloser(bytes.NewBufferString("body")),
                }
                err := req.ParseForm()
-               if err == nil {
+               switch {
+               case err == nil && test.shouldError:
                        t.Errorf("test %d should have returned error", i)
+               case err != nil && !test.shouldError:
+                       t.Errorf("test %d should not have returned error, got %v", i, err)
                }
        }
 }
index 1b9ad1b85c55178264df1aa1bbb78739a7826f59..4de070f01f10d806c71db938b6d2a6ee80ed6b2b 100644 (file)
@@ -494,12 +494,6 @@ func (pc *persistConn) isBroken() bool {
        return pc.broken
 }
 
-func (pc *persistConn) expectingResponse() bool {
-       pc.lk.Lock()
-       defer pc.lk.Unlock()
-       return pc.numExpectedResponses > 0
-}
-
 var remoteSideClosedFunc func(error) bool // or nil to use default
 
 func remoteSideClosed(err error) bool {
@@ -518,14 +512,18 @@ func (pc *persistConn) readLoop() {
 
        for alive {
                pb, err := pc.br.Peek(1)
-               if !pc.expectingResponse() {
+
+               pc.lk.Lock()
+               if pc.numExpectedResponses == 0 {
+                       pc.closeLocked()
+                       pc.lk.Unlock()
                        if len(pb) > 0 {
                                log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
                                        string(pb), err)
                        }
-                       pc.close()
                        return
                }
+               pc.lk.Unlock()
 
                rc := <-pc.reqch
 
@@ -649,6 +647,10 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
 func (pc *persistConn) close() {
        pc.lk.Lock()
        defer pc.lk.Unlock()
+       pc.closeLocked()
+}
+
+func (pc *persistConn) closeLocked() {
        pc.broken = true
        pc.conn.Close()
        pc.mutateHeaderFunc = nil
index ff12fa2d01490962f3f9834217611eeebcaaa793..321da52e2781ab2b40bc08ebe8e6b89ae26e147f 100644 (file)
@@ -304,6 +304,62 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
        }
 }
 
+// Test for http://golang.org/issue/2616 (appropriate issue number)
+// This fails pretty reliably with GOMAXPROCS=100 or something high.
+func TestStressSurpriseServerCloses(t *testing.T) {
+       if testing.Short() {
+               t.Logf("skipping test in short mode")
+               return
+       }
+       ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               w.Header().Set("Content-Length", "5")
+               w.Header().Set("Content-Type", "text/plain")
+               w.Write([]byte("Hello"))
+               w.(Flusher).Flush()
+               conn, buf, _ := w.(Hijacker).Hijack()
+               buf.Flush()
+               conn.Close()
+       }))
+       defer ts.Close()
+
+       tr := &Transport{DisableKeepAlives: false}
+       c := &Client{Transport: tr}
+
+       // Do a bunch of traffic from different goroutines. Send to activityc
+       // after each request completes, regardless of whether it failed.
+       const (
+               numClients    = 50
+               reqsPerClient = 250
+       )
+       activityc := make(chan bool)
+       for i := 0; i < numClients; i++ {
+               go func() {
+                       for i := 0; i < reqsPerClient; i++ {
+                               res, err := c.Get(ts.URL)
+                               if err == nil {
+                                       // We expect errors since the server is
+                                       // hanging up on us after telling us to
+                                       // send more requests, so we don't
+                                       // actually care what the error is.
+                                       // But we want to close the body in cases
+                                       // where we won the race.
+                                       res.Body.Close()
+                               }
+                               activityc <- true
+                       }
+               }()
+       }
+
+       // Make sure all the request come back, one way or another.
+       for i := 0; i < numClients*reqsPerClient; i++ {
+               select {
+               case <-activityc:
+               case <-time.After(5 * time.Second):
+                       t.Fatalf("presumed deadlock; no HTTP client activity seen in awhile")
+               }
+       }
+}
+
 // TestTransportHeadResponses verifies that we deal with Content-Lengths
 // with no bodies properly
 func TestTransportHeadResponses(t *testing.T) {
index c74bfcd6c79c81b817c07d11745c6687b28a6fcc..f9401c1104e37c2b658e79367ddb1b71ff08e3e9 100644 (file)
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// TODO(cw): ListenPacket test, Read() test, ipv6 test &
-// Dial()/Listen() level tests
-
 package net
 
 import (
        "bytes"
-       "flag"
        "os"
        "testing"
        "time"
 )
 
-const ICMP_ECHO_REQUEST = 8
-const ICMP_ECHO_REPLY = 0
-
-// returns a suitable 'ping request' packet, with id & seq and a
-// payload length of pktlen
-func makePingRequest(id, seq, pktlen int, filler []byte) []byte {
-       p := make([]byte, pktlen)
-       copy(p[8:], bytes.Repeat(filler, (pktlen-8)/len(filler)+1))
-
-       p[0] = ICMP_ECHO_REQUEST // type
-       p[1] = 0                 // code
-       p[2] = 0                 // cksum
-       p[3] = 0                 // cksum
-       p[4] = uint8(id >> 8)    // id
-       p[5] = uint8(id & 0xff)  // id
-       p[6] = uint8(seq >> 8)   // sequence
-       p[7] = uint8(seq & 0xff) // sequence
-
-       // calculate icmp checksum
-       cklen := len(p)
-       s := uint32(0)
-       for i := 0; i < (cklen - 1); i += 2 {
-               s += uint32(p[i+1])<<8 | uint32(p[i])
-       }
-       if cklen&1 == 1 {
-               s += uint32(p[cklen-1])
-       }
-       s = (s >> 16) + (s & 0xffff)
-       s = s + (s >> 16)
-
-       // place checksum back in header; using ^= avoids the
-       // assumption the checksum bytes are zero
-       p[2] ^= uint8(^s & 0xff)
-       p[3] ^= uint8(^s >> 8)
-
-       return p
-}
-
-func parsePingReply(p []byte) (id, seq int) {
-       id = int(p[4])<<8 | int(p[5])
-       seq = int(p[6])<<8 | int(p[7])
-       return
+var icmpTests = []struct {
+       net   string
+       laddr string
+       raddr string
+       ipv6  bool
+}{
+       {"ip4:icmp", "", "127.0.0.1", false},
+       {"ip6:icmp", "", "::1", true},
 }
 
-var srchost = flag.String("srchost", "", "Source of the ICMP ECHO request")
-
-// 127.0.0.1 because this is an IPv4-specific test.
-var dsthost = flag.String("dsthost", "127.0.0.1", "Destination for the ICMP ECHO request")
-
-// test (raw) IP socket using ICMP
 func TestICMP(t *testing.T) {
        if os.Getuid() != 0 {
                t.Logf("test disabled; must be root")
                return
        }
 
-       var (
-               laddr *IPAddr
-               err   error
-       )
-       if *srchost != "" {
-               laddr, err = ResolveIPAddr("ip4", *srchost)
-               if err != nil {
-                       t.Fatalf(`net.ResolveIPAddr("ip4", %v") = %v, %v`, *srchost, laddr, err)
+       seqnum := 61455
+       for _, tt := range icmpTests {
+               if tt.ipv6 && !supportsIPv6 {
+                       continue
                }
+               id := os.Getpid() & 0xffff
+               seqnum++
+               echo := newICMPEchoRequest(tt.ipv6, id, seqnum, 128, []byte("Go Go Gadget Ping!!!"))
+               exchangeICMPEcho(t, tt.net, tt.laddr, tt.raddr, tt.ipv6, echo)
        }
+}
 
-       raddr, err := ResolveIPAddr("ip4", *dsthost)
+func exchangeICMPEcho(t *testing.T, net, laddr, raddr string, ipv6 bool, echo []byte) {
+       c, err := ListenPacket(net, laddr)
        if err != nil {
-               t.Fatalf(`net.ResolveIPAddr("ip4", %v") = %v, %v`, *dsthost, raddr, err)
+               t.Errorf("ListenPacket(%#q, %#q) failed: %v", net, laddr, err)
+               return
        }
+       c.SetDeadline(time.Now().Add(100 * time.Millisecond))
+       defer c.Close()
 
-       c, err := ListenIP("ip4:icmp", laddr)
+       ra, err := ResolveIPAddr(net, raddr)
        if err != nil {
-               t.Fatalf(`net.ListenIP("ip4:icmp", %v) = %v, %v`, *srchost, c, err)
+               t.Errorf("ResolveIPAddr(%#q, %#q) failed: %v", net, raddr, err)
+               return
        }
 
-       sendid := os.Getpid() & 0xffff
-       const sendseq = 61455
-       const pingpktlen = 128
-       sendpkt := makePingRequest(sendid, sendseq, pingpktlen, []byte("Go Go Gadget Ping!!!"))
+       waitForReady := make(chan bool)
+       go icmpEchoTransponder(t, net, raddr, ipv6, waitForReady)
+       <-waitForReady
 
-       n, err := c.WriteToIP(sendpkt, raddr)
-       if err != nil || n != pingpktlen {
-               t.Fatalf(`net.WriteToIP(..., %v) = %v, %v`, raddr, n, err)
+       _, err = c.WriteTo(echo, ra)
+       if err != nil {
+               t.Errorf("WriteTo failed: %v", err)
+               return
        }
 
+       reply := make([]byte, 256)
+       for {
+               _, _, err := c.ReadFrom(reply)
+               if err != nil {
+                       t.Errorf("ReadFrom failed: %v", err)
+                       return
+               }
+               if !ipv6 && reply[0] != ICMP4_ECHO_REPLY {
+                       continue
+               }
+               if ipv6 && reply[0] != ICMP6_ECHO_REPLY {
+                       continue
+               }
+               xid, xseqnum := parseICMPEchoReply(echo)
+               rid, rseqnum := parseICMPEchoReply(reply)
+               if rid != xid || rseqnum != xseqnum {
+                       t.Errorf("ID = %v, Seqnum = %v, want ID = %v, Seqnum = %v", rid, rseqnum, xid, xseqnum)
+                       return
+               }
+               break
+       }
+}
+
+func icmpEchoTransponder(t *testing.T, net, raddr string, ipv6 bool, waitForReady chan bool) {
+       c, err := Dial(net, raddr)
+       if err != nil {
+               waitForReady <- true
+               t.Errorf("Dial(%#q, %#q) failed: %v", net, raddr, err)
+               return
+       }
        c.SetDeadline(time.Now().Add(100 * time.Millisecond))
-       resp := make([]byte, 1024)
+       defer c.Close()
+       waitForReady <- true
+
+       echo := make([]byte, 256)
+       var nr int
        for {
-               n, from, err := c.ReadFrom(resp)
+               nr, err = c.Read(echo)
                if err != nil {
-                       t.Fatalf(`ReadFrom(...) = %v, %v, %v`, n, from, err)
+                       t.Errorf("Read failed: %v", err)
+                       return
                }
-               if resp[0] != ICMP_ECHO_REPLY {
+               if !ipv6 && echo[0] != ICMP4_ECHO_REQUEST {
                        continue
                }
-               rcvid, rcvseq := parsePingReply(resp)
-               if rcvid != sendid || rcvseq != sendseq {
-                       t.Fatalf(`Ping reply saw id,seq=0x%x,0x%x (expected 0x%x, 0x%x)`, rcvid, rcvseq, sendid, sendseq)
+               if ipv6 && echo[0] != ICMP6_ECHO_REQUEST {
+                       continue
                }
+               break
+       }
+
+       if !ipv6 {
+               echo[0] = ICMP4_ECHO_REPLY
+       } else {
+               echo[0] = ICMP6_ECHO_REPLY
+       }
+
+       _, err = c.Write(echo[:nr])
+       if err != nil {
+               t.Errorf("Write failed: %v", err)
                return
        }
-       t.Fatalf("saw no ping return")
+}
+
+const (
+       ICMP4_ECHO_REQUEST = 8
+       ICMP4_ECHO_REPLY   = 0
+       ICMP6_ECHO_REQUEST = 128
+       ICMP6_ECHO_REPLY   = 129
+)
+
+func newICMPEchoRequest(ipv6 bool, id, seqnum, msglen int, filler []byte) []byte {
+       if !ipv6 {
+               return newICMPv4EchoRequest(id, seqnum, msglen, filler)
+       }
+       return newICMPv6EchoRequest(id, seqnum, msglen, filler)
+}
+
+func newICMPv4EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
+       b := newICMPInfoMessage(id, seqnum, msglen, filler)
+       b[0] = ICMP4_ECHO_REQUEST
+
+       // calculate ICMP checksum
+       cklen := len(b)
+       s := uint32(0)
+       for i := 0; i < cklen-1; i += 2 {
+               s += uint32(b[i+1])<<8 | uint32(b[i])
+       }
+       if cklen&1 == 1 {
+               s += uint32(b[cklen-1])
+       }
+       s = (s >> 16) + (s & 0xffff)
+       s = s + (s >> 16)
+       // place checksum back in header; using ^= avoids the
+       // assumption the checksum bytes are zero
+       b[2] ^= uint8(^s & 0xff)
+       b[3] ^= uint8(^s >> 8)
+
+       return b
+}
+
+func newICMPv6EchoRequest(id, seqnum, msglen int, filler []byte) []byte {
+       b := newICMPInfoMessage(id, seqnum, msglen, filler)
+       b[0] = ICMP6_ECHO_REQUEST
+       return b
+}
+
+func newICMPInfoMessage(id, seqnum, msglen int, filler []byte) []byte {
+       b := make([]byte, msglen)
+       copy(b[8:], bytes.Repeat(filler, (msglen-8)/len(filler)+1))
+       b[0] = 0                    // type
+       b[1] = 0                    // code
+       b[2] = 0                    // checksum
+       b[3] = 0                    // checksum
+       b[4] = uint8(id >> 8)       // identifier
+       b[5] = uint8(id & 0xff)     // identifier
+       b[6] = uint8(seqnum >> 8)   // sequence number
+       b[7] = uint8(seqnum & 0xff) // sequence number
+       return b
+}
+
+func parseICMPEchoReply(b []byte) (id, seqnum int) {
+       id = int(b[4])<<8 | int(b[5])
+       seqnum = int(b[6])<<8 | int(b[7])
+       return
 }
index 58df607e3becd01f823d3b6d0c8d60641e967ab9..859153c2aad6449d6757bf3bf49434e251863db2 100644 (file)
@@ -32,13 +32,13 @@ func (c *IPConn) SetWriteDeadline(t time.Time) error {
 
 // Implementation of the Conn interface - see Conn for documentation.
 
-// Read implements the net.Conn Read method.
-func (c *IPConn) Read(b []byte) (n int, err error) {
+// Read implements the Conn Read method.
+func (c *IPConn) Read(b []byte) (int, error) {
        return 0, os.EPLAN9
 }
 
-// Write implements the net.Conn Write method.
-func (c *IPConn) Write(b []byte) (n int, err error) {
+// Write implements the Conn Write method.
+func (c *IPConn) Write(b []byte) (int, error) {
        return 0, os.EPLAN9
 }
 
@@ -59,10 +59,20 @@ func (c *IPConn) RemoteAddr() Addr {
 
 // IP-specific methods.
 
-// ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
-       err = os.EPLAN9
-       return
+// ReadFromIP reads a IP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromIP can be made to time out and return an error with
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
+       return 0, nil, os.EPLAN9
+}
+
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
+       return 0, nil, os.EPLAN9
 }
 
 // WriteToIP writes a IP packet to addr via c, copying the payload from b.
@@ -71,23 +81,18 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
 // an error with Timeout() == true after a fixed time limit;
 // see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err error) {
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
        return 0, os.EPLAN9
 }
 
-// WriteTo implements the net.PacketConn WriteTo method.
-func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
        return 0, os.EPLAN9
 }
 
-func splitNetProto(netProto string) (net string, proto int, err error) {
-       err = os.EPLAN9
-       return
-}
-
 // DialIP connects to the remote address raddr on the network protocol netProto,
 // which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
-func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
        return nil, os.EPLAN9
 }
 
@@ -95,6 +100,6 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send IP
 // packets with per-packet addressing.
-func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err error) {
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
        return nil, os.EPLAN9
 }
index e4f755bc785f049204dc97d9e17a416874b8a226..c34ffeb121df042295cddcf586234ed03bf7276f 100644 (file)
@@ -9,7 +9,6 @@
 package net
 
 import (
-       "errors"
        "os"
        "syscall"
        "time"
@@ -58,14 +57,14 @@ func (c *IPConn) ok() bool { return c != nil && c.fd != nil }
 
 // Implementation of the Conn interface - see Conn for documentation.
 
-// Read implements the net.Conn Read method.
-func (c *IPConn) Read(b []byte) (n int, err error) {
-       n, _, err = c.ReadFrom(b)
-       return
+// Read implements the Conn Read method.
+func (c *IPConn) Read(b []byte) (int, error) {
+       n, _, err := c.ReadFrom(b)
+       return n, err
 }
 
-// Write implements the net.Conn Write method.
-func (c *IPConn) Write(b []byte) (n int, err error) {
+// Write implements the Conn Write method.
+func (c *IPConn) Write(b []byte) (int, error) {
        if !c.ok() {
                return 0, os.EINVAL
        }
@@ -98,7 +97,7 @@ func (c *IPConn) RemoteAddr() Addr {
        return c.fd.raddr
 }
 
-// SetDeadline implements the net.Conn SetDeadline method.
+// SetDeadline implements the Conn SetDeadline method.
 func (c *IPConn) SetDeadline(t time.Time) error {
        if !c.ok() {
                return os.EINVAL
@@ -106,7 +105,7 @@ func (c *IPConn) SetDeadline(t time.Time) error {
        return setDeadline(c.fd, t)
 }
 
-// SetReadDeadline implements the net.Conn SetReadDeadline method.
+// SetReadDeadline implements the Conn SetReadDeadline method.
 func (c *IPConn) SetReadDeadline(t time.Time) error {
        if !c.ok() {
                return os.EINVAL
@@ -114,7 +113,7 @@ func (c *IPConn) SetReadDeadline(t time.Time) error {
        return setReadDeadline(c.fd, t)
 }
 
-// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+// SetWriteDeadline implements the Conn SetWriteDeadline method.
 func (c *IPConn) SetWriteDeadline(t time.Time) error {
        if !c.ok() {
                return os.EINVAL
@@ -149,12 +148,13 @@ func (c *IPConn) SetWriteBuffer(bytes int) error {
 // ReadFromIP can be made to time out and return an error with
 // Timeout() == true after a fixed time limit; see SetDeadline and
 // SetReadDeadline.
-func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err error) {
+func (c *IPConn) ReadFromIP(b []byte) (int, *IPAddr, error) {
        if !c.ok() {
                return 0, nil, os.EINVAL
        }
        // TODO(cw,rsc): consider using readv if we know the family
        // type to avoid the header trim/copy
+       var addr *IPAddr
        n, sa, err := c.fd.ReadFrom(b)
        switch sa := sa.(type) {
        case *syscall.SockaddrInet4:
@@ -167,11 +167,11 @@ func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err error) {
        case *syscall.SockaddrInet6:
                addr = &IPAddr{sa.Addr[0:]}
        }
-       return
+       return n, addr, err
 }
 
-// ReadFrom implements the net.PacketConn ReadFrom method.
-func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
+// ReadFrom implements the PacketConn ReadFrom method.
+func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
        if !c.ok() {
                return 0, nil, os.EINVAL
        }
@@ -185,52 +185,35 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
 // an error with Timeout() == true after a fixed time limit;
 // see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err error) {
+func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
        if !c.ok() {
                return 0, os.EINVAL
        }
-       sa, err1 := addr.sockaddr(c.fd.family)
-       if err1 != nil {
-               return 0, &OpError{Op: "write", Net: "ip", Addr: addr, Err: err1}
+       sa, err := addr.sockaddr(c.fd.family)
+       if err != nil {
+               return 0, &OpError{"write", c.fd.net, addr, err}
        }
        return c.fd.WriteTo(b, sa)
 }
 
-// WriteTo implements the net.PacketConn WriteTo method.
-func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+// WriteTo implements the PacketConn WriteTo method.
+func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
        if !c.ok() {
                return 0, os.EINVAL
        }
        a, ok := addr.(*IPAddr)
        if !ok {
-               return 0, &OpError{"writeto", "ip", addr, os.EINVAL}
+               return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
        }
        return c.WriteToIP(b, a)
 }
 
-func splitNetProto(netProto string) (net string, proto int, err error) {
-       i := last(netProto, ':')
-       if i < 0 { // no colon
-               return "", 0, errors.New("no IP protocol specified")
-       }
-       net = netProto[0:i]
-       protostr := netProto[i+1:]
-       proto, i, ok := dtoi(protostr, 0)
-       if !ok || i != len(protostr) {
-               proto, err = lookupProtocol(protostr)
-               if err != nil {
-                       return "", 0, err
-               }
-       }
-       return net, proto, nil
-}
-
 // DialIP connects to the remote address raddr on the network protocol netProto,
 // which must be "ip", "ip4", or "ip6" followed by a colon and a protocol number or name.
-func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
-       net, proto, err := splitNetProto(netProto)
+func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
+       net, proto, err := parseDialNetwork(netProto)
        if err != nil {
-               return
+               return nil, err
        }
        switch net {
        case "ip", "ip4", "ip6":
@@ -238,11 +221,11 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
                return nil, UnknownNetworkError(net)
        }
        if raddr == nil {
-               return nil, &OpError{"dial", "ip", nil, errMissingAddress}
+               return nil, &OpError{"dial", netProto, nil, errMissingAddress}
        }
-       fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
-       if e != nil {
-               return nil, e
+       fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+       if err != nil {
+               return nil, err
        }
        return newIPConn(fd), nil
 }
@@ -251,19 +234,19 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error) {
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send IP
 // packets with per-packet addressing.
-func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err error) {
-       net, proto, err := splitNetProto(netProto)
+func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
+       net, proto, err := parseDialNetwork(netProto)
        if err != nil {
-               return
+               return nil, err
        }
        switch net {
        case "ip", "ip4", "ip6":
        default:
                return nil, UnknownNetworkError(net)
        }
-       fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
-       if e != nil {
-               return nil, e
+       fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
+       if err != nil {
+               return nil, err
        }
        return newIPConn(fd), nil
 }
index 645aa6d2493e1762748e500da64235f7be42f0be..c0bb9225a7dc862502be3ff00674e431807c86bb 100644 (file)
@@ -69,6 +69,11 @@ func queryDNS(addr string, typ string) (res []string, err error) {
        return query("/net/dns", addr+" "+typ, 1024)
 }
 
+func lookupProtocol(name string) (proto int, err error) {
+       // TODO: Implement this
+       return 0, os.EPLAN9
+}
+
 func lookupHost(host string) (addrs []string, err error) {
        // Use /net/cs insead of /net/dns because cs knows about
        // host names in local network (e.g. from /lib/ndb/local)
index 6fb414e089cdeb9b25d0e00a8b0e85138af9019a..abc1e59cd510858c66b3c70ff33c7a9a2af09957 100644 (file)
@@ -145,6 +145,7 @@ func (call *Call) done() {
        default:
                // We don't want to block here.  It is the caller's responsibility to make
                // sure the channel has enough buffer space. See comment in Go().
+               log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
        }
 }
 
index ae688c0f8ca82e0ff3d76d1e60d61b6b525d09c7..b05c63c0563d747cf4d6be5dc4c33b8d67183025 100644 (file)
@@ -467,13 +467,16 @@ func TestCountMallocsOverHTTP(t *testing.T) {
        fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
 }
 
-type writeCrasher struct{}
+type writeCrasher struct {
+       done chan bool
+}
 
 func (writeCrasher) Close() error {
        return nil
 }
 
-func (writeCrasher) Read(p []byte) (int, error) {
+func (w *writeCrasher) Read(p []byte) (int, error) {
+       <-w.done
        return 0, io.EOF
 }
 
@@ -482,7 +485,8 @@ func (writeCrasher) Write(p []byte) (int, error) {
 }
 
 func TestClientWriteError(t *testing.T) {
-       c := NewClient(writeCrasher{})
+       w := &writeCrasher{done: make(chan bool)}
+       c := NewClient(w)
        res := false
        err := c.Call("foo", 1, &res)
        if err == nil {
@@ -491,6 +495,7 @@ func TestClientWriteError(t *testing.T) {
        if err.Error() != "fake write failure" {
                t.Error("unexpected value of error:", err)
        }
+       w.done <- true
 }
 
 func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
@@ -513,7 +518,7 @@ func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
                go func() {
                        reply := new(Reply)
                        for atomic.AddInt32(&N, -1) >= 0 {
-                               err = client.Call("Arith.Add", args, reply)
+                               err := client.Call("Arith.Add", args, reply)
                                if err != nil {
                                        b.Fatalf("rpc error: Add: expected no error but got string %q", err.Error())
                                }
index 2f3210b428891c214dd31c002494c5638336b6e6..867e328f12eb419a78d4f65e4d0798e7ab907d1d 100644 (file)
@@ -49,6 +49,7 @@ func socket(net string, f, t, p int, la, ra syscall.Sockaddr, toAddr func(syscal
                        fd.Close()
                        return nil, err
                }
+               fd.isConnected = true
        }
 
        sa, _ := syscall.Getsockname(s)
index 59f9af5f30adb334cec6a304476b4f22cf437fa2..3d0f8dd7a89622ecd6a72ca040b181b1c96b6d94 100644 (file)
@@ -117,12 +117,20 @@ func setWriteBuffer(fd *netFD, bytes int) error {
 }
 
 func setReadDeadline(fd *netFD, t time.Time) error {
-       fd.rdeadline = t.UnixNano()
+       if t.IsZero() {
+               fd.rdeadline = 0
+       } else {
+               fd.rdeadline = t.UnixNano()
+       }
        return nil
 }
 
 func setWriteDeadline(fd *netFD, t time.Time) error {
-       fd.wdeadline = t.UnixNano()
+       if t.IsZero() {
+               fd.wdeadline = 0
+       } else {
+               fd.wdeadline = t.UnixNano()
+       }
        return nil
 }
 
index 288ec056ab0e9e3dd659b0c94953be04ec1da5b1..f2444a4d96f9c331242ca1c0fc898d46f951e4c9 100644 (file)
@@ -60,7 +60,7 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
                return nil, UnknownNetworkError(net)
        }
        if raddr == nil {
-               return nil, &OpError{"dial", "tcp", nil, errMissingAddress}
+               return nil, &OpError{"dial", net, nil, errMissingAddress}
        }
        c1, err := dialPlan9(net, laddr, raddr)
        if err != nil {
@@ -87,7 +87,7 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
                return nil, UnknownNetworkError(net)
        }
        if laddr == nil {
-               return nil, &OpError{"listen", "tcp", nil, errMissingAddress}
+               return nil, &OpError{"listen", net, nil, errMissingAddress}
        }
        l1, err := listenPlan9(net, laddr)
        if err != nil {
index 91816fa9d46c8ae302d2b8ef682e291a000e510a..65ec493039cbd9a360f99b38cf3f3179b268faf6 100644 (file)
@@ -225,7 +225,7 @@ func (c *TCPConn) File() (f *os.File, err error) { return c.fd.dup() }
 // as the local address for the connection.
 func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error) {
        if raddr == nil {
-               return nil, &OpError{"dial", "tcp", nil, errMissingAddress}
+               return nil, &OpError{"dial", net, nil, errMissingAddress}
        }
        fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
        if e != nil {
@@ -253,7 +253,7 @@ func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err error) {
        err = syscall.Listen(fd.sysfd, listenerBacklog)
        if err != nil {
                closesocket(fd.sysfd)
-               return nil, &OpError{"listen", "tcp", laddr, err}
+               return nil, &OpError{"listen", net, laddr, err}
        }
        l = new(TCPListener)
        l.fd = fd
index 11db012ff576393fbfeb8c27d2e4ffd7e15e2026..bae37c86b2ed3b32fa511b387b5fca94b8f5c2d7 100644 (file)
@@ -77,3 +77,30 @@ func TestTimeoutTCP(t *testing.T) {
        testTimeout(t, "tcp", addr, false)
        <-done
 }
+
+func TestDeadlineReset(t *testing.T) {
+       if runtime.GOOS == "plan9" {
+               return
+       }
+       ln, err := Listen("tcp", "127.0.0.1:0")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer ln.Close()
+       tl := ln.(*TCPListener)
+       tl.SetDeadline(time.Now().Add(1 * time.Minute))
+       tl.SetDeadline(time.Time{}) // reset it
+       errc := make(chan error, 1)
+       go func() {
+               _, err := ln.Accept()
+               errc <- err
+       }()
+       select {
+       case <-time.After(50 * time.Millisecond):
+               // Pass.
+       case err := <-errc:
+               // Accept should never return; we never
+               // connected to it.
+               t.Errorf("unexpected return from Accept; err=%v", err)
+       }
+}
diff --git a/libgo/go/net/udp_test.go b/libgo/go/net/udp_test.go
new file mode 100644 (file)
index 0000000..6ba762b
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+       "runtime"
+       "testing"
+)
+
+func TestWriteToUDP(t *testing.T) {
+       if runtime.GOOS == "plan9" {
+               return
+       }
+
+       l, err := ListenPacket("udp", "127.0.0.1:0")
+       if err != nil {
+               t.Fatalf("Listen failed: %v", err)
+       }
+       defer l.Close()
+
+       testWriteToConn(t, l.LocalAddr().String())
+       testWriteToPacketConn(t, l.LocalAddr().String())
+}
+
+func testWriteToConn(t *testing.T, raddr string) {
+       c, err := Dial("udp", raddr)
+       if err != nil {
+               t.Fatalf("Dial failed: %v", err)
+       }
+       defer c.Close()
+
+       ra, err := ResolveUDPAddr("udp", raddr)
+       if err != nil {
+               t.Fatalf("ResolveUDPAddr failed: %v", err)
+       }
+
+       _, err = c.(*UDPConn).WriteToUDP([]byte("Connection-oriented mode socket"), ra)
+       if err == nil {
+               t.Fatal("WriteToUDP should be failed")
+       }
+       if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+               t.Fatalf("WriteToUDP should be failed as ErrWriteToConnected: %v", err)
+       }
+
+       _, err = c.(*UDPConn).WriteTo([]byte("Connection-oriented mode socket"), ra)
+       if err == nil {
+               t.Fatal("WriteTo should be failed")
+       }
+       if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+               t.Fatalf("WriteTo should be failed as ErrWriteToConnected: %v", err)
+       }
+
+       _, err = c.Write([]byte("Connection-oriented mode socket"))
+       if err != nil {
+               t.Fatalf("Write failed: %v", err)
+       }
+}
+
+func testWriteToPacketConn(t *testing.T, raddr string) {
+       c, err := ListenPacket("udp", "127.0.0.1:0")
+       if err != nil {
+               t.Fatalf("ListenPacket failed: %v", err)
+       }
+       defer c.Close()
+
+       ra, err := ResolveUDPAddr("udp", raddr)
+       if err != nil {
+               t.Fatalf("ResolveUDPAddr failed: %v", err)
+       }
+
+       _, err = c.(*UDPConn).WriteToUDP([]byte("Connection-less mode socket"), ra)
+       if err != nil {
+               t.Fatalf("WriteToUDP failed: %v", err)
+       }
+
+       _, err = c.WriteTo([]byte("Connection-less mode socket"), ra)
+       if err != nil {
+               t.Fatalf("WriteTo failed: %v", err)
+       }
+
+       _, err = c.(*UDPConn).Write([]byte("Connection-less mode socket"))
+       if err == nil {
+               t.Fatal("Write should be failed")
+       }
+}
index 246c9ad94b5b50caaf51ac790bfa08401f380f1b..573438f85de3ca1c6f2c05d00749ce8f62df96d2 100644 (file)
@@ -110,7 +110,7 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
        }
        a, ok := addr.(*UDPAddr)
        if !ok {
-               return 0, &OpError{"writeto", "udp", addr, os.EINVAL}
+               return 0, &OpError{"write", c.dir, addr, os.EINVAL}
        }
        return c.WriteToUDP(b, a)
 }
@@ -125,7 +125,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
                return nil, UnknownNetworkError(net)
        }
        if raddr == nil {
-               return nil, &OpError{"dial", "udp", nil, errMissingAddress}
+               return nil, &OpError{"dial", net, nil, errMissingAddress}
        }
        c1, err := dialPlan9(net, laddr, raddr)
        if err != nil {
@@ -173,7 +173,7 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
                return nil, UnknownNetworkError(net)
        }
        if laddr == nil {
-               return nil, &OpError{"listen", "udp", nil, errMissingAddress}
+               return nil, &OpError{"listen", net, nil, errMissingAddress}
        }
        l, err := listenPlan9(net, laddr)
        if err != nil {
index 0b5bc16f822f8fc95d7ba13d0bc589558f0c5c22..fa3d29adfa8cf21826bf2f81288b25b14a6afafc 100644 (file)
@@ -9,11 +9,14 @@
 package net
 
 import (
+       "errors"
        "os"
        "syscall"
        "time"
 )
 
+var ErrWriteToConnected = errors.New("use of WriteTo with pre-connected UDP")
+
 func sockaddrToUDP(sa syscall.Sockaddr) Addr {
        switch sa := sa.(type) {
        case *syscall.SockaddrInet4:
@@ -178,25 +181,28 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
 // an error with Timeout() == true after a fixed time limit;
 // see SetDeadline and SetWriteDeadline.
 // On packet-oriented connections, write timeouts are rare.
-func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
        if !c.ok() {
                return 0, os.EINVAL
        }
-       sa, err1 := addr.sockaddr(c.fd.family)
-       if err1 != nil {
-               return 0, &OpError{Op: "write", Net: "udp", Addr: addr, Err: err1}
+       if c.fd.isConnected {
+               return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
+       }
+       sa, err := addr.sockaddr(c.fd.family)
+       if err != nil {
+               return 0, &OpError{"write", c.fd.net, addr, err}
        }
        return c.fd.WriteTo(b, sa)
 }
 
 // WriteTo implements the net.PacketConn WriteTo method.
-func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
        if !c.ok() {
                return 0, os.EINVAL
        }
        a, ok := addr.(*UDPAddr)
        if !ok {
-               return 0, &OpError{"writeto", "udp", addr, os.EINVAL}
+               return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
        }
        return c.WriteToUDP(b, a)
 }
@@ -211,7 +217,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
                return nil, UnknownNetworkError(net)
        }
        if raddr == nil {
-               return nil, &OpError{"dial", "udp", nil, errMissingAddress}
+               return nil, &OpError{"dial", net, nil, errMissingAddress}
        }
        fd, e := internetSocket(net, laddr.toAddr(), raddr.toAddr(), syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
        if e != nil {
@@ -224,18 +230,18 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
 // local address laddr.  The returned connection c's ReadFrom
 // and WriteTo methods can be used to receive and send UDP
 // packets with per-packet addressing.
-func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
+func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
        switch net {
        case "udp", "udp4", "udp6":
        default:
                return nil, UnknownNetworkError(net)
        }
        if laddr == nil {
-               return nil, &OpError{"listen", "udp", nil, errMissingAddress}
+               return nil, &OpError{"listen", net, nil, errMissingAddress}
        }
-       fd, e := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
-       if e != nil {
-               return nil, e
+       fd, err := internetSocket(net, laddr.toAddr(), nil, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+       if err != nil {
+               return nil, err
        }
        return newUDPConn(fd), nil
 }
@@ -275,7 +281,7 @@ func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error {
 func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
        err := joinIPv4Group(c.fd, ifi, ip)
        if err != nil {
-               return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
+               return &OpError{"joinipv4group", c.fd.net, &IPAddr{ip}, err}
        }
        return nil
 }
@@ -283,7 +289,7 @@ func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
 func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
        err := leaveIPv4Group(c.fd, ifi, ip)
        if err != nil {
-               return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
+               return &OpError{"leaveipv4group", c.fd.net, &IPAddr{ip}, err}
        }
        return nil
 }
@@ -291,7 +297,7 @@ func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
 func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
        err := joinIPv6Group(c.fd, ifi, ip)
        if err != nil {
-               return &OpError{"joinipv6group", "udp", &IPAddr{ip}, err}
+               return &OpError{"joinipv6group", c.fd.net, &IPAddr{ip}, err}
        }
        return nil
 }
@@ -299,7 +305,7 @@ func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
 func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
        err := leaveIPv6Group(c.fd, ifi, ip)
        if err != nil {
-               return &OpError{"leaveipv6group", "udp", &IPAddr{ip}, err}
+               return &OpError{"leaveipv6group", c.fd.net, &IPAddr{ip}, err}
        }
        return nil
 }
index 5b8b2e4c7c67e76e2f0b2617cf3f3f6cb805bb2c..e500ddb4e0f30a80ff1280315c58f9bf0b90a155 100644 (file)
@@ -259,7 +259,7 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (n int, err error) {
        }
        a, ok := addr.(*UnixAddr)
        if !ok {
-               return 0, &OpError{"writeto", "unix", addr, os.EINVAL}
+               return 0, &OpError{"write", c.fd.net, addr, os.EINVAL}
        }
        return c.WriteToUnix(b, a)
 }
@@ -330,7 +330,7 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
        err = syscall.Listen(fd.sysfd, listenerBacklog)
        if err != nil {
                closesocket(fd.sysfd)
-               return nil, &OpError{Op: "listen", Net: "unix", Addr: laddr, Err: err}
+               return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
        }
        return &UnixListener{fd, laddr.Name}, nil
 }
@@ -412,7 +412,7 @@ func ListenUnixgram(net string, laddr *UnixAddr) (c *UDPConn, err error) {
                return nil, UnknownNetworkError(net)
        }
        if laddr == nil {
-               return nil, &OpError{"listen", "unixgram", nil, errMissingAddress}
+               return nil, &OpError{"listen", net, nil, errMissingAddress}
        }
        fd, e := unixSocket(net, laddr, nil, "listen")
        if e != nil {
index aa8f3934577406aaf6a55b58efbabd07d492bc94..7d136eb36868b8c2fed927c4f8fa14866ebfb3aa 100644 (file)
@@ -7,6 +7,7 @@ package os
 import (
        "runtime"
        "syscall"
+       "time"
 )
 
 // File represents an open file descriptor.
@@ -56,12 +57,27 @@ func epipecheck(file *File, e error) {
 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
 const DevNull = "/dev/null"
 
+// syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
+func syscallMode(i FileMode) (o uint32) {
+       o |= uint32(i.Perm())
+       if i&ModeAppend != 0 {
+               o |= syscall.DMAPPEND
+       }
+       if i&ModeExclusive != 0 {
+               o |= syscall.DMEXCL
+       }
+       if i&ModeTemporary != 0 {
+               o |= syscall.DMTMP
+       }
+       return
+}
+
 // OpenFile is the generalized open call; most users will use Open
 // or Create instead.  It opens the named file with specified flag
 // (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
 // methods on the returned File can be used for I/O.
 // It returns the File and an error, if any.
-func OpenFile(name string, flag int, perm uint32) (file *File, err error) {
+func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
        var (
                fd     int
                e      error
@@ -89,12 +105,12 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err error) {
 
        syscall.ForkLock.RLock()
        if (create && trunc) || excl {
-               fd, e = syscall.Create(name, flag, perm)
+               fd, e = syscall.Create(name, flag, syscallMode(perm))
        } else {
                fd, e = syscall.Open(name, flag)
                if e != nil && create {
                        var e1 error
-                       fd, e1 = syscall.Create(name, flag, perm)
+                       fd, e1 = syscall.Create(name, flag, syscallMode(perm))
                        if e1 == nil {
                                e = nil
                        }
@@ -162,18 +178,18 @@ func (f *File) Truncate(size int64) error {
        return nil
 }
 
+const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm)
+
 // Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) error {
+func (f *File) Chmod(mode FileMode) error {
        var d Dir
-       var mask = ^uint32(0777)
 
-       d.Null()
        odir, e := dirstat(f)
        if e != nil {
                return &PathError{"chmod", f.name, e}
        }
-
-       d.Mode = (odir.Mode & mask) | (mode &^ mask)
+       d.Null()
+       d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
        if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil {
                return &PathError{"chmod", f.name, e}
        }
@@ -266,17 +282,15 @@ func Rename(oldname, newname string) error {
 }
 
 // Chmod changes the mode of the named file to mode.
-func Chmod(name string, mode uint32) error {
+func Chmod(name string, mode FileMode) error {
        var d Dir
-       var mask = ^uint32(0777)
 
-       d.Null()
        odir, e := dirstat(name)
        if e != nil {
                return &PathError{"chmod", name, e}
        }
-
-       d.Mode = (odir.Mode & mask) | (mode &^ mask)
+       d.Null()
+       d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask
        if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
                return &PathError{"chmod", name, e}
        }
@@ -286,15 +300,14 @@ func Chmod(name string, mode uint32) error {
 // Chtimes changes the access and modification times of the named
 // file, similar to the Unix utime() or utimes() functions.
 //
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atimeNs int64, mtimeNs int64) error {
+// The underlying filesystem may truncate or round the values to a
+// less precise time unit.
+func Chtimes(name string, atime time.Time, mtime time.Time) error {
        var d Dir
        d.Null()
 
-       d.Atime = uint32(atimeNs / 1e9)
-       d.Mtime = uint32(mtimeNs / 1e9)
+       d.Atime = uint32(atime.Unix())
+       d.Mtime = uint32(mtime.Unix())
 
        if e := syscall.Wstat(name, pdir(nil, &d)); e != nil {
                return &PathError{"chtimes", name, e}
index 8d3b8a84d5c5b80557785d755b63f13c6de45dc9..f731e43740a8d268129e24439c2de2a7b626ed9c 100644 (file)
@@ -97,3 +97,8 @@ func Stat(name string) (FileInfo, error) {
 func Lstat(name string) (FileInfo, error) {
        return Stat(name)
 }
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+       return time.Unix(int64(fi.(*FileStat).Sys.(*Dir).Atime), 0)
+}
index 42fa557445f2c21476995473d75b8006352de080..10f5170a9c92666141340fcd50627373ee509871 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nocgo windows
+// +build !cgo windows
 
 package user
 
diff --git a/libgo/go/patch/apply.go b/libgo/go/patch/apply.go
deleted file mode 100644 (file)
index 7c4f4ad..0000000
+++ /dev/null
@@ -1,54 +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 patch
-
-import "os"
-
-// An Op is a single operation to execute to apply a patch.
-type Op struct {
-       Verb Verb   // action
-       Src  string // source file
-       Dst  string // destination file
-       Mode int    // mode for destination (if non-zero)
-       Data []byte // data for destination (if non-nil)
-}
-
-// Apply applies the patch set to the files named in the patch set,
-// constructing an in-memory copy of the new file state.
-// It is the client's job to write the changes to the file system
-// if desired.
-//
-// The function readFile should return the contents of the named file.
-// Typically this function will be io.ReadFile.
-//
-func (set *Set) Apply(readFile func(string) ([]byte, error)) ([]Op, error) {
-       op := make([]Op, len(set.File))
-
-       for i, f := range set.File {
-               o := &op[i]
-               o.Verb = f.Verb
-               o.Src = f.Src
-               o.Dst = f.Dst
-               o.Mode = f.NewMode
-               if f.Diff != NoDiff || o.Verb != Edit {
-                       // Clients assume o.Data == nil means no data diff.
-                       // Start with a non-nil data.
-                       var old []byte = make([]byte, 0) // not nil
-                       var err error
-                       if f.Src != "" {
-                               old, err = readFile(f.Src)
-                               if err != nil {
-                                       return nil, &os.PathError{string(f.Verb), f.Src, err}
-                               }
-                       }
-                       o.Data, err = f.Diff.Apply(old)
-                       if err != nil {
-                               return nil, &os.PathError{string(f.Verb), f.Src, err}
-                       }
-               }
-       }
-
-       return op, nil
-}
diff --git a/libgo/go/patch/git.go b/libgo/go/patch/git.go
deleted file mode 100644 (file)
index 5c233fb..0000000
+++ /dev/null
@@ -1,121 +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 patch
-
-import (
-       "bytes"
-       "compress/zlib"
-       "crypto/sha1"
-       "encoding/git85"
-       "errors"
-       "fmt"
-       "io"
-)
-
-func gitSHA1(data []byte) []byte {
-       if len(data) == 0 {
-               // special case: 0 length is all zeros sum
-               return make([]byte, 20)
-       }
-       h := sha1.New()
-       fmt.Fprintf(h, "blob %d\x00", len(data))
-       h.Write(data)
-       return h.Sum(nil)
-}
-
-// BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
-
-// GitBinaryLiteral represents a Git binary literal diff.
-type GitBinaryLiteral struct {
-       OldSHA1 []byte // if non-empty, the SHA1 hash of the original
-       New     []byte // the new contents
-}
-
-// Apply implements the Diff interface's Apply method.
-func (d *GitBinaryLiteral) Apply(old []byte) ([]byte, error) {
-       if sum := gitSHA1(old); !bytes.HasPrefix(sum, d.OldSHA1) {
-               return nil, ErrPatchFailure
-       }
-       return d.New, nil
-}
-
-func unhex(c byte) uint8 {
-       switch {
-       case '0' <= c && c <= '9':
-               return c - '0'
-       case 'a' <= c && c <= 'f':
-               return c - 'a' + 10
-       case 'A' <= c && c <= 'F':
-               return c - 'A' + 10
-       }
-       return 255
-}
-
-func getHex(s []byte) (data []byte, rest []byte) {
-       n := 0
-       for n < len(s) && unhex(s[n]) != 255 {
-               n++
-       }
-       n &^= 1 // Only take an even number of hex digits.
-       data = make([]byte, n/2)
-       for i := range data {
-               data[i] = unhex(s[2*i])<<4 | unhex(s[2*i+1])
-       }
-       rest = s[n:]
-       return
-}
-
-// ParseGitBinary parses raw as a Git binary patch.
-func ParseGitBinary(raw []byte) (Diff, error) {
-       var oldSHA1, newSHA1 []byte
-       var sawBinary bool
-
-       for {
-               var first []byte
-               first, raw, _ = getLine(raw, 1)
-               first = bytes.TrimSpace(first)
-               if s, ok := skip(first, "index "); ok {
-                       oldSHA1, s = getHex(s)
-                       if s, ok = skip(s, ".."); !ok {
-                               continue
-                       }
-                       newSHA1, s = getHex(s)
-                       continue
-               }
-               if _, ok := skip(first, "GIT binary patch"); ok {
-                       sawBinary = true
-                       continue
-               }
-               if n, _, ok := atoi(first, "literal ", 10); ok && sawBinary {
-                       data := make([]byte, n)
-                       d := git85.NewDecoder(bytes.NewBuffer(raw))
-                       z, err := zlib.NewReader(d)
-                       if err != nil {
-                               return nil, err
-                       }
-                       defer z.Close()
-                       if _, err = io.ReadFull(z, data); err != nil {
-                               if err == io.EOF {
-                                       err = io.ErrUnexpectedEOF
-                               }
-                               return nil, err
-                       }
-                       var buf [1]byte
-                       m, err := z.Read(buf[0:])
-                       if m != 0 || err != io.EOF {
-                               return nil, errors.New("Git binary literal longer than expected")
-                       }
-
-                       if sum := gitSHA1(data); !bytes.HasPrefix(sum, newSHA1) {
-                               return nil, errors.New("Git binary literal SHA1 mismatch")
-                       }
-                       return &GitBinaryLiteral{oldSHA1, data}, nil
-               }
-               if !sawBinary {
-                       return nil, errors.New("unexpected Git patch header: " + string(first))
-               }
-       }
-       panic("unreachable")
-}
diff --git a/libgo/go/patch/patch.go b/libgo/go/patch/patch.go
deleted file mode 100644 (file)
index 1d804f3..0000000
+++ /dev/null
@@ -1,321 +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 patch implements parsing and execution of the textual and
-// binary patch descriptions used by version control tools such as
-// CVS, Git, Mercurial, and Subversion.
-package patch
-
-import (
-       "bytes"
-       "path"
-       "strings"
-)
-
-// A Set represents a set of patches to be applied as a single atomic unit.
-// Patch sets are often preceded by a descriptive header.
-type Set struct {
-       Header string // free-form text
-       File   []*File
-}
-
-// A File represents a collection of changes to be made to a single file.
-type File struct {
-       Verb             Verb
-       Src              string // source for Verb == Copy, Verb == Rename
-       Dst              string
-       OldMode, NewMode int // 0 indicates not used
-       Diff                 // changes to data; == NoDiff if operation does not edit file
-}
-
-// A Verb is an action performed on a file.
-type Verb string
-
-const (
-       Add    Verb = "add"
-       Copy   Verb = "copy"
-       Delete Verb = "delete"
-       Edit   Verb = "edit"
-       Rename Verb = "rename"
-)
-
-// A Diff is any object that describes changes to transform
-// an old byte stream to a new one.
-type Diff interface {
-       // Apply applies the changes listed in the diff
-       // to the string s, returning the new version of the string.
-       // Note that the string s need not be a text string.
-       Apply(old []byte) (new []byte, err error)
-}
-
-// NoDiff is a no-op Diff implementation: it passes the
-// old data through unchanged.
-var NoDiff Diff = noDiffType(0)
-
-type noDiffType int
-
-func (noDiffType) Apply(old []byte) ([]byte, error) {
-       return old, nil
-}
-
-// A SyntaxError represents a syntax error encountered while parsing a patch.
-type SyntaxError string
-
-func (e SyntaxError) Error() string { return string(e) }
-
-var newline = []byte{'\n'}
-
-// Parse patches the patch text to create a patch Set.
-// The patch text typically comprises a textual header and a sequence
-// of file patches, as would be generated by CVS, Subversion,
-// Mercurial, or Git.
-func Parse(text []byte) (*Set, error) {
-       // Split text into files.
-       // CVS and Subversion begin new files with
-       //      Index: file name.
-       //      ==================
-       //      diff -u blah blah
-       //
-       // Mercurial and Git use
-       //      diff [--git] a/file/path b/file/path.
-       //
-       // First look for Index: lines.  If none, fall back on diff lines.
-       text, files := sections(text, "Index: ")
-       if len(files) == 0 {
-               text, files = sections(text, "diff ")
-       }
-
-       set := &Set{string(text), make([]*File, len(files))}
-
-       // Parse file header and then
-       // parse files into patch chunks.
-       // Each chunk begins with @@.
-       for i, raw := range files {
-               p := new(File)
-               set.File[i] = p
-
-               // First line of hdr is the Index: that
-               // begins the section.  After that is the file name.
-               s, raw, _ := getLine(raw, 1)
-               if hasPrefix(s, "Index: ") {
-                       p.Dst = string(bytes.TrimSpace(s[7:]))
-                       goto HaveName
-               } else if hasPrefix(s, "diff ") {
-                       str := string(bytes.TrimSpace(s))
-                       i := strings.LastIndex(str, " b/")
-                       if i >= 0 {
-                               p.Dst = str[i+3:]
-                               goto HaveName
-                       }
-               }
-               return nil, SyntaxError("unexpected patch header line: " + string(s))
-       HaveName:
-               p.Dst = path.Clean(p.Dst)
-               if strings.HasPrefix(p.Dst, "../") || strings.HasPrefix(p.Dst, "/") {
-                       return nil, SyntaxError("invalid path: " + p.Dst)
-               }
-
-               // Parse header lines giving file information:
-               //      new file mode %o        - file created
-               //      deleted file mode %o    - file deleted
-               //      old file mode %o        - file mode changed
-               //      new file mode %o        - file mode changed
-               //      rename from %s  - file renamed from other file
-               //      rename to %s
-               //      copy from %s            - file copied from other file
-               //      copy to %s
-               p.Verb = Edit
-               for len(raw) > 0 {
-                       oldraw := raw
-                       var l []byte
-                       l, raw, _ = getLine(raw, 1)
-                       l = bytes.TrimSpace(l)
-                       if m, s, ok := atoi(l, "new file mode ", 8); ok && len(s) == 0 {
-                               p.NewMode = m
-                               p.Verb = Add
-                               continue
-                       }
-                       if m, s, ok := atoi(l, "deleted file mode ", 8); ok && len(s) == 0 {
-                               p.OldMode = m
-                               p.Verb = Delete
-                               p.Src = p.Dst
-                               p.Dst = ""
-                               continue
-                       }
-                       if m, s, ok := atoi(l, "old file mode ", 8); ok && len(s) == 0 {
-                               // usually implies p.Verb = "rename" or "copy"
-                               // but we'll get that from the rename or copy line.
-                               p.OldMode = m
-                               continue
-                       }
-                       if m, s, ok := atoi(l, "old mode ", 8); ok && len(s) == 0 {
-                               p.OldMode = m
-                               continue
-                       }
-                       if m, s, ok := atoi(l, "new mode ", 8); ok && len(s) == 0 {
-                               p.NewMode = m
-                               continue
-                       }
-                       if s, ok := skip(l, "rename from "); ok && len(s) > 0 {
-                               p.Src = string(s)
-                               p.Verb = Rename
-                               continue
-                       }
-                       if s, ok := skip(l, "rename to "); ok && len(s) > 0 {
-                               p.Verb = Rename
-                               continue
-                       }
-                       if s, ok := skip(l, "copy from "); ok && len(s) > 0 {
-                               p.Src = string(s)
-                               p.Verb = Copy
-                               continue
-                       }
-                       if s, ok := skip(l, "copy to "); ok && len(s) > 0 {
-                               p.Verb = Copy
-                               continue
-                       }
-                       if s, ok := skip(l, "Binary file "); ok && len(s) > 0 {
-                               // Hg prints
-                               //      Binary file foo has changed
-                               // when deleting a binary file.
-                               continue
-                       }
-                       if s, ok := skip(l, "RCS file: "); ok && len(s) > 0 {
-                               // CVS prints
-                               //      RCS file: /cvs/plan9/bin/yesterday,v
-                               //      retrieving revision 1.1
-                               // for each file.
-                               continue
-                       }
-                       if s, ok := skip(l, "retrieving revision "); ok && len(s) > 0 {
-                               // CVS prints
-                               //      RCS file: /cvs/plan9/bin/yesterday,v
-                               //      retrieving revision 1.1
-                               // for each file.
-                               continue
-                       }
-                       if hasPrefix(l, "===") || hasPrefix(l, "---") || hasPrefix(l, "+++") || hasPrefix(l, "diff ") {
-                               continue
-                       }
-                       if hasPrefix(l, "@@ -") {
-                               diff, err := ParseTextDiff(oldraw)
-                               if err != nil {
-                                       return nil, err
-                               }
-                               p.Diff = diff
-                               break
-                       }
-                       if hasPrefix(l, "GIT binary patch") || (hasPrefix(l, "index ") && !hasPrefix(raw, "--- ")) {
-                               diff, err := ParseGitBinary(oldraw)
-                               if err != nil {
-                                       return nil, err
-                               }
-                               p.Diff = diff
-                               break
-                       }
-                       if hasPrefix(l, "index ") {
-                               continue
-                       }
-                       return nil, SyntaxError("unexpected patch header line: " + string(l))
-               }
-               if p.Diff == nil {
-                       p.Diff = NoDiff
-               }
-               if p.Verb == Edit {
-                       p.Src = p.Dst
-               }
-       }
-
-       return set, nil
-}
-
-// getLine returns the first n lines of data and the remainder.
-// If data has no newline, getLine returns data, nil, false
-func getLine(data []byte, n int) (first []byte, rest []byte, ok bool) {
-       rest = data
-       ok = true
-       for ; n > 0; n-- {
-               nl := bytes.Index(rest, newline)
-               if nl < 0 {
-                       rest = nil
-                       ok = false
-                       break
-               }
-               rest = rest[nl+1:]
-       }
-       first = data[0 : len(data)-len(rest)]
-       return
-}
-
-// sections returns a collection of file sections,
-// each of which begins with a line satisfying prefix.
-// text before the first instance of such a line is
-// returned separately.
-func sections(text []byte, prefix string) ([]byte, [][]byte) {
-       n := 0
-       for b := text; ; {
-               if hasPrefix(b, prefix) {
-                       n++
-               }
-               nl := bytes.Index(b, newline)
-               if nl < 0 {
-                       break
-               }
-               b = b[nl+1:]
-       }
-
-       sect := make([][]byte, n+1)
-       n = 0
-       for b := text; ; {
-               if hasPrefix(b, prefix) {
-                       sect[n] = text[0 : len(text)-len(b)]
-                       n++
-                       text = b
-               }
-               nl := bytes.Index(b, newline)
-               if nl < 0 {
-                       sect[n] = text
-                       break
-               }
-               b = b[nl+1:]
-       }
-       return sect[0], sect[1:]
-}
-
-// if s begins with the prefix t, skip returns
-// s with that prefix removed and ok == true.
-func skip(s []byte, t string) (ss []byte, ok bool) {
-       if len(s) < len(t) || string(s[0:len(t)]) != t {
-               return nil, false
-       }
-       return s[len(t):], true
-}
-
-// if s begins with the prefix t and then is a sequence
-// of digits in the given base, atoi returns the number
-// represented by the digits and s with the
-// prefix and the digits removed.
-func atoi(s []byte, t string, base int) (n int, ss []byte, ok bool) {
-       if s, ok = skip(s, t); !ok {
-               return
-       }
-       var i int
-       for i = 0; i < len(s) && '0' <= s[i] && s[i] <= byte('0'+base-1); i++ {
-               n = n*base + int(s[i]-'0')
-       }
-       if i == 0 {
-               return
-       }
-       return n, s[i:], true
-}
-
-// hasPrefix returns true if s begins with t.
-func hasPrefix(s []byte, t string) bool {
-       _, ok := skip(s, t)
-       return ok
-}
-
-// splitLines returns the result of splitting s into lines.
-// The \n on each line is preserved.
-func splitLines(s []byte) [][]byte { return bytes.SplitAfter(s, newline) }
diff --git a/libgo/go/patch/patch_test.go b/libgo/go/patch/patch_test.go
deleted file mode 100644 (file)
index 0a4aef7..0000000
+++ /dev/null
@@ -1,390 +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 patch
-
-// TODO(rsc): test Apply
-
-import "testing"
-
-type Test struct {
-       in   string
-       out  string
-       diff string
-}
-
-func TestFileApply(t *testing.T) {
-       for i, test := range tests {
-               set, err := Parse([]byte(test.diff))
-               if err != nil {
-                       t.Errorf("#%d: Parse: %s", i, err)
-                       continue
-               }
-               if len(set.File) != 1 {
-                       t.Errorf("#%d: Parse returned %d patches, want 1", i, len(set.File))
-                       continue
-               }
-               new, err := set.File[0].Apply([]byte(test.in))
-               if err != nil {
-                       t.Errorf("#%d: Apply: %s", i, err)
-                       continue
-               }
-               if s := string(new); s != test.out {
-                       t.Errorf("#%d:\n--- have\n%s--- want\n%s", i, s, test.out)
-               }
-       }
-}
-
-var tests = []Test{
-       {
-               "hello, world\n",
-               "goodbye, world\n",
-               "Index: a\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1 +1 @@\n" +
-                       "-hello, world\n" +
-                       "+goodbye, world\n",
-       },
-       {
-               "hello, world\n",
-               "goodbye, world\n",
-               "Index: a\n" +
-                       "index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1 +1 @@\n" +
-                       "-hello, world\n" +
-                       "+goodbye, world\n",
-       },
-       {
-               "hello, world\n",
-               "goodbye, world\n",
-               "diff a/a b/b\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1,1 +1,1 @@\n" +
-                       "-hello, world\n" +
-                       "+goodbye, world\n",
-       },
-       {
-               "hello, world",
-               "goodbye, world\n",
-               "diff --git a/a b/b\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1 +1 @@\n" +
-                       "-hello, world\n" +
-                       "\\ No newline at end of file\n" +
-                       "+goodbye, world\n",
-       },
-       {
-               "hello, world\n",
-               "goodbye, world",
-               "Index: a\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1 +1 @@\n" +
-                       "-hello, world\n" +
-                       "+goodbye, world\n" +
-                       "\\ No newline at end of file\n",
-       },
-       {
-               "hello, world",
-               "goodbye, world",
-               "Index: a\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1 +1 @@\n" +
-                       "-hello, world\n" +
-                       "\\ No newline at end of file\n" +
-                       "+goodbye, world\n" +
-                       "\\ No newline at end of file\n",
-       },
-       {
-               "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\n",
-               "a\nB\nC\nD\ne\nf\ng\nj\nk\nl\nm\nN\n",
-               "Index: a\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1,14 +1,12 @@\n" +
-                       " a\n" +
-                       "-b\n" +
-                       "-c\n" +
-                       "-d\n" +
-                       "+B\n" +
-                       "+C\n" +
-                       "+D\n" +
-                       " e\n" +
-                       " f\n" +
-                       " g\n" +
-                       "-h\n" +
-                       "-i\n" +
-                       " j\n" +
-                       " k\n" +
-                       " l\n" +
-                       " m\n" +
-                       "-n\n" +
-                       "+N\n",
-       },
-       {
-               "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-               "a\nb\nc\ng\nh\ni\nj\nk\nl\nm\nN\nO\np\nq\nr\ns\nt\nu\nv\nw\nd\ne\nf\nx\n",
-               "Index: a\n" +
-                       "--- a/a\n" +
-                       "+++ b/b\n" +
-                       "@@ -1,9 +1,6 @@\n" +
-                       " a\n" +
-                       " b\n" +
-                       " c\n" +
-                       "-d\n" +
-                       "-e\n" +
-                       "-f\n" +
-                       " g\n" +
-                       " h\n" +
-                       " i\n" +
-                       "@@ -11,8 +8,8 @@ j\n" +
-                       " k\n" +
-                       " l\n" +
-                       " m\n" +
-                       "-n\n" +
-                       "-o\n" +
-                       "+N\n" +
-                       "+O\n" +
-                       " p\n" +
-                       " q\n" +
-                       " r\n" +
-                       "\n" +
-                       "@@ -21,6 +18,7 @@ t\n" +
-                       " u\n" +
-                       " v\n" +
-                       " w\n" +
-                       "+d\n" +
-                       "+e\n" +
-                       "+f\n" +
-                       " x\n" +
-                       "-y\n" +
-                       "-z\n",
-       },
-       {
-               "a\nb\nc\ng\nh\ni\nj\nk\nl\nm\nN\nO\np\nq\nr\ns\nt\nu\nv\nw\nd\ne\nf\nx\n",
-               "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-               "Index: a\n" +
-                       "--- a/b\n" +
-                       "+++ b/a\n" +
-                       "@@ -1,6 +1,9 @@\n" +
-                       " a\n" +
-                       " b\n" +
-                       " c\n" +
-                       "+d\n" +
-                       "+e\n" +
-                       "+f\n" +
-                       " g\n" +
-                       " h\n" +
-                       " i\n" +
-                       "@@ -8,8 +11,8 @@ j\n" +
-                       " k\n" +
-                       " l\n" +
-                       " m\n" +
-                       "-N\n" +
-                       "-O\n" +
-                       "+n\n" +
-                       "+o\n" +
-                       " p\n" +
-                       " q\n" +
-                       " r\n" +
-                       "@@ -18,7 +21,6 @@ t\n" +
-                       " u\n" +
-                       " v\n" +
-                       " w\n" +
-                       "-d\n" +
-                       "-e\n" +
-                       "-f\n" +
-                       " x\n" +
-                       "+y\n" +
-                       "+z\n",
-       },
-       {
-               "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-               "",
-               "Index: a\n" +
-                       "deleted file mode 100644\n" +
-                       "--- a/a\n" +
-                       "+++ /dev/null\n" +
-                       "@@ -1,26 +0,0 @@\n" +
-                       "-a\n" +
-                       "-b\n" +
-                       "-c\n" +
-                       "-d\n" +
-                       "-e\n" +
-                       "-f\n" +
-                       "-g\n" +
-                       "-h\n" +
-                       "-i\n" +
-                       "-j\n" +
-                       "-k\n" +
-                       "-l\n" +
-                       "-m\n" +
-                       "-n\n" +
-                       "-o\n" +
-                       "-p\n" +
-                       "-q\n" +
-                       "-r\n" +
-                       "-s\n" +
-                       "-t\n" +
-                       "-u\n" +
-                       "-v\n" +
-                       "-w\n" +
-                       "-x\n" +
-                       "-y\n" +
-                       "-z\n",
-       },
-       {
-               "",
-               "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n",
-               "Index: a\n" +
-                       "new file mode 100644\n" +
-                       "--- /dev/null\n" +
-                       "+++ b/a\n" +
-                       "@@ -0,0 +1,26 @@\n" +
-                       "+a\n" +
-                       "+b\n" +
-                       "+c\n" +
-                       "+d\n" +
-                       "+e\n" +
-                       "+f\n" +
-                       "+g\n" +
-                       "+h\n" +
-                       "+i\n" +
-                       "+j\n" +
-                       "+k\n" +
-                       "+l\n" +
-                       "+m\n" +
-                       "+n\n" +
-                       "+o\n" +
-                       "+p\n" +
-                       "+q\n" +
-                       "+r\n" +
-                       "+s\n" +
-                       "+t\n" +
-                       "+u\n" +
-                       "+v\n" +
-                       "+w\n" +
-                       "+x\n" +
-                       "+y\n" +
-                       "+z\n",
-       },
-       {
-               "\xc2\xd8\xf9\x63\x8c\xf7\xc6\x9b\xb0\x3c\x39\xfa\x08\x8e\x42\x8f" +
-                       "\x1c\x7c\xaf\x54\x22\x87\xc3\xc5\x68\x9b\xe1\xbd\xbc\xc3\xe0\xda" +
-                       "\xcc\xe3\x96\xda\xc2\xaf\xbb\x75\x79\x64\x86\x60\x8a\x43\x9e\x07" +
-                       "\x9c\xaa\x92\x88\xd4\x30\xb9\x8b\x95\x04\x60\x71\xc7\xbb\x2d\x93" +
-                       "\x66\x73\x01\x24\xf3\x63\xbf\xe6\x1d\x38\x15\x56\x98\xc4\x1f\x85" +
-                       "\xc3\x60\x39\x3a\x0d\x57\x53\x0c\x29\x3f\xbb\x44\x7e\x56\x56\x9d" +
-                       "\x87\xcf\xf6\x88\xe8\x98\x05\x85\xf8\xfe\x44\x21\xfa\x33\xc9\xa4" +
-                       "\x22\xbe\x89\x05\x8b\x82\x76\xc9\x7c\xaf\x48\x28\xc4\x86\x15\x89" +
-                       "\xb9\x98\xfa\x41\xfc\x3d\x8d\x80\x29\x33\x17\x45\xa5\x7f\x67\x79" +
-                       "\x7f\x92\x3b\x2e\x4c\xc1\xd2\x1b\x9e\xcf\xed\x53\x56\xb2\x49\x58" +
-                       "\xd8\xe9\x9f\x98\xa3\xfe\x78\xe1\xe8\x74\x71\x04\x1a\x87\xd9\x68" +
-                       "\x18\x68\xd0\xae\x7b\xa4\x25\xe3\x06\x03\x7e\x8b\xd3\x50\x1f\xb1" +
-                       "\x67\x08\xe3\x93\xf4\x4f\xa1\xfb\x31\xcf\x99\x5a\x43\x9f\x4b\xc4" +
-                       "\xaa\x68\x1a\xf9\x8e\x97\x02\x80\x17\xf1\x25\x21\xdf\x94\xbf\x41" +
-                       "\x08\x59\x3d\xea\x36\x23\x03\xb5\x62\x4d\xb6\x8f\x9e\xdf\x1f\x03" +
-                       "\x7d\x70\xe0\x6f\x46\x08\x96\x79\x72\xb7\xae\x41\x2b\xbd\x2a\x95",
-
-               "\x8e\x5f\xf8\x79\x36\x8d\xbe\x68\xc4\x2c\x78\x8a\x46\x28\x40\x3e" +
-                       "\xcf\x3b\xb9\x14\xaf\xfa\x04\x9e\x4b\xa2\x52\x51\x51\xf0\xad\xd3" +
-                       "\x03\x1c\x03\x79\x5f\x53\xc7\x1a\xd5\x28\xe2\xd9\x19\x37\xa4\xfa" +
-                       "\xdd\xff\xac\xb5\xa9\x42\x4e\x17\xeb\xb4\x0d\x20\x67\x08\x43\x21" +
-                       "\x7d\x12\x27\xfa\x96\x7a\x85\xf8\x04\x5f\xf4\xfe\xda\x9f\x66\xf2" +
-                       "\xba\x04\x39\x00\xab\x3f\x23\x20\x84\x53\xb4\x88\xb6\xee\xa2\x9e" +
-                       "\xc1\xca\xd4\x09\x2a\x27\x89\x2f\xcb\xba\xa6\x41\xb6\xe9\xc5\x08" +
-                       "\xff\xf5\x95\x35\xab\xbb\x5c\x62\x96\xe7\x7c\x8f\xf2\x40\x12\xc9" +
-                       "\x2d\xfe\xff\x75\x4f\x70\x47\xc9\xcd\x15\x0a\x1c\x23\xe7\x0f\x15" +
-                       "\x95\x75\x30\x8f\x6e\x9f\x7e\xa5\x9d\xd1\x65\x1c\x4d\x4e\xf4\x32" +
-                       "\x49\x9b\xa1\x30\x44\x62\x6f\xe2\xe6\x69\x09\xf8\x7c\x7c\xbe\x07" +
-                       "\xa9\xb6\x14\x7a\x6b\x85\xe4\xbf\x48\xbe\x5b\x3b\x70\xb3\x79\x3b" +
-                       "\xc4\x35\x9d\x86\xf1\xfe\x2b\x6f\x80\x74\x50\xf3\x96\x59\x53\x1a" +
-                       "\x75\x46\x9d\x57\x72\xb3\xb1\x26\xf5\x81\xcd\x96\x08\xbc\x2b\x10" +
-                       "\xdc\x80\xbd\xd0\xdf\x03\x6d\x8d\xec\x30\x2b\x4c\xdb\x4d\x3b\xef" +
-                       "\x7d\x3a\x39\xc8\x5a\xc4\xcc\x24\x37\xde\xe2\x95\x2b\x04\x97\xb0",
-
-               // From git diff --binary
-               "Index: a\n" +
-                       "index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f 100644\n" +
-                       "GIT binary patch\n" +
-                       "literal 256\n" +
-                       "zcmV+b0ssDvU-)@8jlO8aEO?4WC_p~XJGm6E`UIX!qEb;&@U7DW90Pe@Q^y+BDB{@}\n" +
-                       "zH>CRA|E#sCLQWU!v<)C<2ty%#5-0kWdWHA|U-bUkpJwv91UUe!KO-Q7Q?!V-?xLQ-\n" +
-                       "z%G3!eCy6i1x~4(4>BR{D^_4ZNyIf+H=X{UyKoZF<{{MAPa7W3_6$%_9=MNQ?buf=^\n" +
-                       "zpMIsC(PbP>PV_QKo1rj7VsGN+X$kmze7*;%wiJ46h2+0TzFRwRvw1tjHJyg>{wr^Q\n" +
-                       "zbWrn_SyLKyMx9r3v#}=ifz6f(yekmgfW6S)18t4$Fe^;kO*`*>IyuN%#LOf&-r|)j\n" +
-                       "G1edVN^?m&S\n" +
-                       "\n" +
-                       "literal 256\n" +
-                       "zcmV+b0ssEO*!g3O_r{yBJURLZjzW(de6Lg@hr`8ao8i5@!{FM?<CfaOue)`5WQJgh\n" +
-                       "zL!Jkms*;G*Fu9AB1YmK;yDgJua{(mtW54DdI2Bfy#2<yjU^zMsS5pirKf6SJR#u&d\n" +
-                       "z&-RGum<5IS{zM`AGs&bPzKI2kf_BM#uSh7wh82mqnEFBdJ&k}VGZ#gre`k4rk~=O;\n" +
-                       "z!O|O^&+SuIvPoFj>7SUR{&?Z&ba4b4huLTtXwa^Eq$T491AdFsP#>{p2;-CVPoeuU\n" +
-                       "z&zV|7pG(B5Xd3yBmjZwn@g*VOl)pg;Sv~4DBLlT!O}3Ao-yZ{gaNuu72$p$rx2{1e\n" +
-                       "Gy(*Pb;D3Ms\n" +
-                       "\n",
-       },
-       {
-               "\xc2\xd8\xf9\x63\x8c\xf7\xc6\x9b\xb0\x3c\x39\xfa\x08\x8e\x42\x8f" +
-                       "\x1c\x7c\xaf\x54\x22\x87\xc3\xc5\x68\x9b\xe1\xbd\xbc\xc3\xe0\xda" +
-                       "\xcc\xe3\x96\xda\xc2\xaf\xbb\x75\x79\x64\x86\x60\x8a\x43\x9e\x07" +
-                       "\x9c\xaa\x92\x88\xd4\x30\xb9\x8b\x95\x04\x60\x71\xc7\xbb\x2d\x93" +
-                       "\x66\x73\x01\x24\xf3\x63\xbf\xe6\x1d\x38\x15\x56\x98\xc4\x1f\x85" +
-                       "\xc3\x60\x39\x3a\x0d\x57\x53\x0c\x29\x3f\xbb\x44\x7e\x56\x56\x9d" +
-                       "\x87\xcf\xf6\x88\xe8\x98\x05\x85\xf8\xfe\x44\x21\xfa\x33\xc9\xa4" +
-                       "\x22\xbe\x89\x05\x8b\x82\x76\xc9\x7c\xaf\x48\x28\xc4\x86\x15\x89" +
-                       "\xb9\x98\xfa\x41\xfc\x3d\x8d\x80\x29\x33\x17\x45\xa5\x7f\x67\x79" +
-                       "\x7f\x92\x3b\x2e\x4c\xc1\xd2\x1b\x9e\xcf\xed\x53\x56\xb2\x49\x58" +
-                       "\xd8\xe9\x9f\x98\xa3\xfe\x78\xe1\xe8\x74\x71\x04\x1a\x87\xd9\x68" +
-                       "\x18\x68\xd0\xae\x7b\xa4\x25\xe3\x06\x03\x7e\x8b\xd3\x50\x1f\xb1" +
-                       "\x67\x08\xe3\x93\xf4\x4f\xa1\xfb\x31\xcf\x99\x5a\x43\x9f\x4b\xc4" +
-                       "\xaa\x68\x1a\xf9\x8e\x97\x02\x80\x17\xf1\x25\x21\xdf\x94\xbf\x41" +
-                       "\x08\x59\x3d\xea\x36\x23\x03\xb5\x62\x4d\xb6\x8f\x9e\xdf\x1f\x03" +
-                       "\x7d\x70\xe0\x6f\x46\x08\x96\x79\x72\xb7\xae\x41\x2b\xbd\x2a\x95",
-
-               "\x8e\x5f\xf8\x79\x36\x8d\xbe\x68\xc4\x2c\x78\x8a\x46\x28\x40\x3e" +
-                       "\xcf\x3b\xb9\x14\xaf\xfa\x04\x9e\x4b\xa2\x52\x51\x51\xf0\xad\xd3" +
-                       "\x03\x1c\x03\x79\x5f\x53\xc7\x1a\xd5\x28\xe2\xd9\x19\x37\xa4\xfa" +
-                       "\xdd\xff\xac\xb5\xa9\x42\x4e\x17\xeb\xb4\x0d\x20\x67\x08\x43\x21" +
-                       "\x7d\x12\x27\xfa\x96\x7a\x85\xf8\x04\x5f\xf4\xfe\xda\x9f\x66\xf2" +
-                       "\xba\x04\x39\x00\xab\x3f\x23\x20\x84\x53\xb4\x88\xb6\xee\xa2\x9e" +
-                       "\xc1\xca\xd4\x09\x2a\x27\x89\x2f\xcb\xba\xa6\x41\xb6\xe9\xc5\x08" +
-                       "\xff\xf5\x95\x35\xab\xbb\x5c\x62\x96\xe7\x7c\x8f\xf2\x40\x12\xc9" +
-                       "\x2d\xfe\xff\x75\x4f\x70\x47\xc9\xcd\x15\x0a\x1c\x23\xe7\x0f\x15" +
-                       "\x95\x75\x30\x8f\x6e\x9f\x7e\xa5\x9d\xd1\x65\x1c\x4d\x4e\xf4\x32" +
-                       "\x49\x9b\xa1\x30\x44\x62\x6f\xe2\xe6\x69\x09\xf8\x7c\x7c\xbe\x07" +
-                       "\xa9\xb6\x14\x7a\x6b\x85\xe4\xbf\x48\xbe\x5b\x3b\x70\xb3\x79\x3b" +
-                       "\xc4\x35\x9d\x86\xf1\xfe\x2b\x6f\x80\x74\x50\xf3\x96\x59\x53\x1a" +
-                       "\x75\x46\x9d\x57\x72\xb3\xb1\x26\xf5\x81\xcd\x96\x08\xbc\x2b\x10" +
-                       "\xdc\x80\xbd\xd0\xdf\x03\x6d\x8d\xec\x30\x2b\x4c\xdb\x4d\x3b\xef" +
-                       "\x7d\x3a\x39\xc8\x5a\xc4\xcc\x24\x37\xde\xe2\x95\x2b\x04\x97\xb0",
-
-               // From hg diff --git
-               "Index: a\n" +
-                       "index cb34d9b1743b7c410fa750be8a58eb355987110b..0a01764bc1b2fd29da317f72208f462ad342400f\n" +
-                       "GIT binary patch\n" +
-                       "literal 256\n" +
-                       "zc$@(M0ssDvU-)@8jlO8aEO?4WC_p~XJGm6E`UIX!qEb;&@U7DW90Pe@Q^y+BDB{@}\n" +
-                       "zH>CRA|E#sCLQWU!v<)C<2ty%#5-0kWdWHA|U-bUkpJwv91UUe!KO-Q7Q?!V-?xLQ-\n" +
-                       "z%G3!eCy6i1x~4(4>BR{D^_4ZNyIf+H=X{UyKoZF<{{MAPa7W3_6$%_9=MNQ?buf=^\n" +
-                       "zpMIsC(PbP>PV_QKo1rj7VsGN+X$kmze7*;%wiJ46h2+0TzFRwRvw1tjHJyg>{wr^Q\n" +
-                       "zbWrn_SyLKyMx9r3v#}=ifz6f(yekmgfW6S)18t4$Fe^;kO*`*>IyuN%#LOf&-r|)j\n" +
-                       "G1edVN^?m&S\n" +
-                       "\n",
-       },
-       {
-               "",
-               "",
-               "Index: hello\n" +
-                       "===================================================================\n" +
-                       "old mode 100644\n" +
-                       "new mode 100755\n",
-       },
-}
diff --git a/libgo/go/patch/textdiff.go b/libgo/go/patch/textdiff.go
deleted file mode 100644 (file)
index c9cffee..0000000
+++ /dev/null
@@ -1,179 +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 patch
-
-import (
-       "bytes"
-       "errors"
-)
-
-type TextDiff []TextChunk
-
-// A TextChunk specifies an edit to a section of a file:
-// the text beginning at Line, which should be exactly Old,
-// is to be replaced with New.
-type TextChunk struct {
-       Line int
-       Old  []byte
-       New  []byte
-}
-
-func ParseTextDiff(raw []byte) (TextDiff, error) {
-       var chunkHeader []byte
-
-       // Copy raw so it is safe to keep references to slices.
-       _, chunks := sections(raw, "@@ -")
-       delta := 0
-       diff := make(TextDiff, len(chunks))
-       for i, raw := range chunks {
-               c := &diff[i]
-
-               // Parse start line: @@ -oldLine,oldCount +newLine,newCount @@ junk
-               chunk := splitLines(raw)
-               chunkHeader = chunk[0]
-               var ok bool
-               var oldLine, oldCount, newLine, newCount int
-               s := chunkHeader
-               if oldLine, s, ok = atoi(s, "@@ -", 10); !ok {
-                       goto ErrChunkHdr
-               }
-               if len(s) == 0 || s[0] != ',' {
-                       oldCount = 1
-               } else if oldCount, s, ok = atoi(s, ",", 10); !ok {
-                       goto ErrChunkHdr
-               }
-               if newLine, s, ok = atoi(s, " +", 10); !ok {
-                       goto ErrChunkHdr
-               }
-               if len(s) == 0 || s[0] != ',' {
-                       newCount = 1
-               } else if newCount, s, ok = atoi(s, ",", 10); !ok {
-                       goto ErrChunkHdr
-               }
-               if !hasPrefix(s, " @@") {
-                       goto ErrChunkHdr
-               }
-
-               // Special case: for created or deleted files, the empty half
-               // is given as starting at line 0.  Translate to line 1.
-               if oldCount == 0 && oldLine == 0 {
-                       oldLine = 1
-               }
-               if newCount == 0 && newLine == 0 {
-                       newLine = 1
-               }
-
-               // Count lines in text
-               var dropOldNL, dropNewNL bool
-               var nold, nnew int
-               var lastch byte
-               chunk = chunk[1:]
-               for _, l := range chunk {
-                       if nold == oldCount && nnew == newCount && (len(l) == 0 || l[0] != '\\') {
-                               if len(bytes.TrimSpace(l)) != 0 {
-                                       return nil, SyntaxError("too many chunk lines")
-                               }
-                               continue
-                       }
-                       if len(l) == 0 {
-                               return nil, SyntaxError("empty chunk line")
-                       }
-                       switch l[0] {
-                       case '+':
-                               nnew++
-                       case '-':
-                               nold++
-                       case ' ':
-                               nnew++
-                               nold++
-                       case '\\':
-                               if _, ok := skip(l, "\\ No newline at end of file"); ok {
-                                       switch lastch {
-                                       case '-':
-                                               dropOldNL = true
-                                       case '+':
-                                               dropNewNL = true
-                                       case ' ':
-                                               dropOldNL = true
-                                               dropNewNL = true
-                                       default:
-                                               return nil, SyntaxError("message `\\ No newline at end of file' out of context")
-                                       }
-                                       break
-                               }
-                               fallthrough
-                       default:
-                               return nil, SyntaxError("unexpected chunk line: " + string(l))
-                       }
-                       lastch = l[0]
-               }
-
-               // Does it match the header?
-               if nold != oldCount || nnew != newCount {
-                       return nil, SyntaxError("chunk header does not match line count: " + string(chunkHeader))
-               }
-               if oldLine+delta != newLine {
-                       return nil, SyntaxError("chunk delta is out of sync with previous chunks")
-               }
-               delta += nnew - nold
-               c.Line = oldLine
-
-               var old, new bytes.Buffer
-               nold = 0
-               nnew = 0
-               for _, l := range chunk {
-                       if nold == oldCount && nnew == newCount {
-                               break
-                       }
-                       ch, l := l[0], l[1:]
-                       if ch == '\\' {
-                               continue
-                       }
-                       if ch != '+' {
-                               old.Write(l)
-                               nold++
-                       }
-                       if ch != '-' {
-                               new.Write(l)
-                               nnew++
-                       }
-               }
-               c.Old = old.Bytes()
-               c.New = new.Bytes()
-               if dropOldNL {
-                       c.Old = c.Old[0 : len(c.Old)-1]
-               }
-               if dropNewNL {
-                       c.New = c.New[0 : len(c.New)-1]
-               }
-       }
-       return diff, nil
-
-ErrChunkHdr:
-       return nil, SyntaxError("unexpected chunk header line: " + string(chunkHeader))
-}
-
-var ErrPatchFailure = errors.New("patch did not apply cleanly")
-
-// Apply applies the changes listed in the diff
-// to the data, returning the new version.
-func (d TextDiff) Apply(data []byte) ([]byte, error) {
-       var buf bytes.Buffer
-       line := 1
-       for _, c := range d {
-               var ok bool
-               var prefix []byte
-               prefix, data, ok = getLine(data, c.Line-line)
-               if !ok || !bytes.HasPrefix(data, c.Old) {
-                       return nil, ErrPatchFailure
-               }
-               buf.Write(prefix)
-               data = data[len(c.Old):]
-               buf.Write(c.New)
-               line = c.Line + bytes.Count(c.Old, newline)
-       }
-       buf.Write(data)
-       return buf.Bytes(), nil
-}
index 63adcb88c46a94d98606b90a7bfb0855cc77cb3b..2601d1838487fd2a4c80c6c6c7ac3c193cf9286a 100644 (file)
@@ -295,6 +295,7 @@ func makeTree(t *testing.T) {
                        fd, err := os.Create(path)
                        if err != nil {
                                t.Errorf("makeTree: %v", err)
+                               return
                        }
                        fd.Close()
                } else {
@@ -344,10 +345,10 @@ func TestWalk(t *testing.T) {
        // Expect no errors.
        err := filepath.Walk(tree.name, markFn)
        if err != nil {
-               t.Errorf("no error expected, found: %s", err)
+               t.Fatalf("no error expected, found: %s", err)
        }
        if len(errors) != 0 {
-               t.Errorf("unexpected errors: %s", errors)
+               t.Fatalf("unexpected errors: %s", errors)
        }
        checkMarks(t, true)
        errors = errors[0:0]
@@ -369,7 +370,7 @@ func TestWalk(t *testing.T) {
                tree.entries[3].mark--
                err := filepath.Walk(tree.name, markFn)
                if err != nil {
-                       t.Errorf("expected no error return from Walk, %s", err)
+                       t.Fatalf("expected no error return from Walk, got %s", err)
                }
                if len(errors) != 2 {
                        t.Errorf("expected 2 errors, got %d: %s", len(errors), errors)
@@ -388,7 +389,7 @@ func TestWalk(t *testing.T) {
                clear = false // error will stop processing
                err = filepath.Walk(tree.name, markFn)
                if err == nil {
-                       t.Errorf("expected error return from Walk")
+                       t.Fatalf("expected error return from Walk")
                }
                if len(errors) != 1 {
                        t.Errorf("expected 1 error, got %d: %s", len(errors), errors)
@@ -660,11 +661,13 @@ func TestAbs(t *testing.T) {
                info, err := os.Stat(path)
                if err != nil {
                        t.Errorf("%s: %s", path, err)
+                       continue
                }
 
                abspath, err := filepath.Abs(path)
                if err != nil {
                        t.Errorf("Abs(%q) error: %v", path, err)
+                       continue
                }
                absinfo, err := os.Stat(abspath)
                if err != nil || !absinfo.(*os.FileStat).SameFile(info.(*os.FileStat)) {
index ef94fa09b118e7fb640e5976ee76e3582828d124..7aebd3728a3dc5a9da5b1b6661dd52e3a85f96db 100644 (file)
@@ -66,13 +66,6 @@ import (
 
 var debug = false
 
-// Error is the local type for a parsing error.
-type Error string
-
-func (e Error) Error() string {
-       return string(e)
-}
-
 // Regexp is the representation of a compiled regular expression.
 // The public interface is entirely through methods.
 // A Regexp is safe for concurrent use by multiple goroutines.
index 7cea906ceae6971b9b93d2fbc03a99e7d16eecfa..eb2c7c60d0cdc0bdeeee8924fa2296b27268d0eb 100644 (file)
@@ -371,3 +371,12 @@ func BenchmarkChanCreation(b *testing.B) {
                <-c
        }
 }
+
+func BenchmarkChanSem(b *testing.B) {
+       type Empty struct{}
+       c := make(chan Empty, 1)
+       for i := 0; i < b.N; i++ {
+               c <- Empty{}
+               <-c
+       }
+}
index c2b90566a9989e6f20b7e859e7b8dac01380afad..4f09146fac172640a9acf7280589e41b92d21098 100644 (file)
@@ -23,6 +23,9 @@ func UnlockOSThread()
 // This call will go away when the scheduler improves.
 func GOMAXPROCS(n int) int
 
+// NumCPU returns the number of logical CPUs on the local machine.
+func NumCPU() int
+
 // Cgocalls returns the number of cgo calls made by the current process.
 func Cgocalls() int64
 
index 88598cb7d4b116f4c6c95b7309639973e579388b..eafa2f19f19e929ddbaf17617ad49922eba602bd 100644 (file)
@@ -68,9 +68,6 @@ func funcline_go(*Func, uintptr) (string, int)
 // mid returns the current os thread (m) id.
 func mid() uint32
 
-// NumCPU returns the number of logical CPUs on the local machine.
-func NumCPU() int
-
 // Semacquire waits until *s > 0 and then atomically decrements it.
 // It is intended as a simple sleep primitive for use by the synchronization
 // library and should not be used directly.
diff --git a/libgo/go/websocket/client.go b/libgo/go/websocket/client.go
deleted file mode 100644 (file)
index 89cdcda..0000000
+++ /dev/null
@@ -1,137 +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 websocket
-
-import (
-       "bufio"
-       "crypto/tls"
-       "io"
-       "net"
-       "net/url"
-)
-
-// DialError is an error that occurs while dialling a websocket server.
-type DialError struct {
-       *Config
-       Err error
-}
-
-func (e *DialError) Error() string {
-       return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
-}
-
-// NewConfig creates a new WebSocket config for client connection.
-func NewConfig(server, origin string) (config *Config, err error) {
-       config = new(Config)
-       config.Version = ProtocolVersionHybi13
-       config.Location, err = url.ParseRequest(server)
-       if err != nil {
-               return
-       }
-       config.Origin, err = url.ParseRequest(origin)
-       if err != nil {
-               return
-       }
-       return
-}
-
-// NewClient creates a new WebSocket client connection over rwc.
-func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
-       br := bufio.NewReader(rwc)
-       bw := bufio.NewWriter(rwc)
-       switch config.Version {
-       case ProtocolVersionHixie75:
-               err = hixie75ClientHandshake(config, br, bw)
-       case ProtocolVersionHixie76, ProtocolVersionHybi00:
-               err = hixie76ClientHandshake(config, br, bw)
-       case ProtocolVersionHybi08, ProtocolVersionHybi13:
-               err = hybiClientHandshake(config, br, bw)
-       default:
-               err = ErrBadProtocolVersion
-       }
-       if err != nil {
-               return
-       }
-       buf := bufio.NewReadWriter(br, bw)
-       switch config.Version {
-       case ProtocolVersionHixie75, ProtocolVersionHixie76, ProtocolVersionHybi00:
-               ws = newHixieClientConn(config, buf, rwc)
-       case ProtocolVersionHybi08, ProtocolVersionHybi13:
-               ws = newHybiClientConn(config, buf, rwc)
-       }
-       return
-}
-
-/*
-Dial opens a new client connection to a WebSocket.
-
-A trivial example client:
-
-       package main
-
-       import (
-               "log"
-               "net/http"
-               "strings"
-               "websocket"
-       )
-
-       func main() {
-               origin := "http://localhost/"
-               url := "ws://localhost/ws" 
-               ws, err := websocket.Dial(url, "", origin)
-               if err != nil {
-                       log.Fatal(err)
-               }
-               if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
-                       log.Fatal(err)
-               }
-               var msg = make([]byte, 512);
-               if n, err := ws.Read(msg); err != nil {
-                       log.Fatal(err)
-               }
-               // use msg[0:n]
-       }
-*/
-func Dial(url_, protocol, origin string) (ws *Conn, err error) {
-       config, err := NewConfig(url_, origin)
-       if err != nil {
-               return nil, err
-       }
-       return DialConfig(config)
-}
-
-// DialConfig opens a new client connection to a WebSocket with a config.
-func DialConfig(config *Config) (ws *Conn, err error) {
-       var client net.Conn
-       if config.Location == nil {
-               return nil, &DialError{config, ErrBadWebSocketLocation}
-       }
-       if config.Origin == nil {
-               return nil, &DialError{config, ErrBadWebSocketOrigin}
-       }
-       switch config.Location.Scheme {
-       case "ws":
-               client, err = net.Dial("tcp", config.Location.Host)
-
-       case "wss":
-               client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
-
-       default:
-               err = ErrBadScheme
-       }
-       if err != nil {
-               goto Error
-       }
-
-       ws, err = NewClient(config, client)
-       if err != nil {
-               goto Error
-       }
-       return
-
-Error:
-       return nil, &DialError{config, err}
-}
diff --git a/libgo/go/websocket/hixie.go b/libgo/go/websocket/hixie.go
deleted file mode 100644 (file)
index 22dbc1f..0000000
+++ /dev/null
@@ -1,695 +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 websocket
-
-// This file implements a protocol of Hixie draft version 75 and 76
-// (draft 76 equals to hybi 00)
-
-import (
-       "bufio"
-       "bytes"
-       "crypto/md5"
-       "encoding/binary"
-       "fmt"
-       "io"
-       "io/ioutil"
-       "math/rand"
-       "net/http"
-       "net/url"
-       "strconv"
-       "strings"
-)
-
-// An aray of characters to be randomly inserted to construct Sec-WebSocket-Key
-// value. It holds characters from ranges U+0021 to U+002F and U+003A to U+007E.
-// See Step 21 in Section 4.1 Opening handshake.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#page-22
-var secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte
-
-func init() {
-       i := 0
-       for ch := byte(0x21); ch < 0x30; ch++ {
-               secKeyRandomChars[i] = ch
-               i++
-       }
-       for ch := byte(0x3a); ch < 0x7F; ch++ {
-               secKeyRandomChars[i] = ch
-               i++
-       }
-}
-
-type byteReader interface {
-       ReadByte() (byte, error)
-}
-
-// readHixieLength reads frame length for frame type 0x80-0xFF
-// as defined in Hixie draft.
-// See section 4.2 Data framing.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-4.2
-func readHixieLength(r byteReader) (length int64, lengthFields []byte, err error) {
-       for {
-               c, err := r.ReadByte()
-               if err != nil {
-                       return 0, nil, err
-               }
-               lengthFields = append(lengthFields, c)
-               length = length*128 + int64(c&0x7f)
-               if c&0x80 == 0 {
-                       break
-               }
-       }
-       return
-}
-
-// A hixieLengthFrameReader is a reader for frame type 0x80-0xFF
-// as defined in hixie draft.
-type hixieLengthFrameReader struct {
-       reader    io.Reader
-       FrameType byte
-       Length    int64
-       header    *bytes.Buffer
-       length    int
-}
-
-func (frame *hixieLengthFrameReader) Read(msg []byte) (n int, err error) {
-       return frame.reader.Read(msg)
-}
-
-func (frame *hixieLengthFrameReader) PayloadType() byte {
-       if frame.FrameType == '\xff' && frame.Length == 0 {
-               return CloseFrame
-       }
-       return UnknownFrame
-}
-
-func (frame *hixieLengthFrameReader) HeaderReader() io.Reader {
-       if frame.header == nil {
-               return nil
-       }
-       if frame.header.Len() == 0 {
-               frame.header = nil
-               return nil
-       }
-       return frame.header
-}
-
-func (frame *hixieLengthFrameReader) TrailerReader() io.Reader { return nil }
-
-func (frame *hixieLengthFrameReader) Len() (n int) { return frame.length }
-
-// A HixieSentinelFrameReader is a reader for frame type 0x00-0x7F
-// as defined in hixie draft.
-type hixieSentinelFrameReader struct {
-       reader      *bufio.Reader
-       FrameType   byte
-       header      *bytes.Buffer
-       data        []byte
-       seenTrailer bool
-       trailer     *bytes.Buffer
-}
-
-func (frame *hixieSentinelFrameReader) Read(msg []byte) (n int, err error) {
-       if len(frame.data) == 0 {
-               if frame.seenTrailer {
-                       return 0, io.EOF
-               }
-               frame.data, err = frame.reader.ReadSlice('\xff')
-               if err == nil {
-                       frame.seenTrailer = true
-                       frame.data = frame.data[:len(frame.data)-1] // trim \xff
-                       frame.trailer = bytes.NewBuffer([]byte{0xff})
-               }
-       }
-       n = copy(msg, frame.data)
-       frame.data = frame.data[n:]
-       return n, err
-}
-
-func (frame *hixieSentinelFrameReader) PayloadType() byte {
-       if frame.FrameType == 0 {
-               return TextFrame
-       }
-       return UnknownFrame
-}
-
-func (frame *hixieSentinelFrameReader) HeaderReader() io.Reader {
-       if frame.header == nil {
-               return nil
-       }
-       if frame.header.Len() == 0 {
-               frame.header = nil
-               return nil
-       }
-       return frame.header
-}
-
-func (frame *hixieSentinelFrameReader) TrailerReader() io.Reader {
-       if frame.trailer == nil {
-               return nil
-       }
-       if frame.trailer.Len() == 0 {
-               frame.trailer = nil
-               return nil
-       }
-       return frame.trailer
-}
-
-func (frame *hixieSentinelFrameReader) Len() int { return -1 }
-
-// A HixieFrameReaderFactory creates new frame reader based on its frame type.
-type hixieFrameReaderFactory struct {
-       *bufio.Reader
-}
-
-func (buf hixieFrameReaderFactory) NewFrameReader() (r frameReader, err error) {
-       var header []byte
-       var b byte
-       b, err = buf.ReadByte()
-       if err != nil {
-               return
-       }
-       header = append(header, b)
-       if b&0x80 == 0x80 {
-               length, lengthFields, err := readHixieLength(buf.Reader)
-               if err != nil {
-                       return nil, err
-               }
-               if length == 0 {
-                       return nil, io.EOF
-               }
-               header = append(header, lengthFields...)
-               return &hixieLengthFrameReader{
-                       reader:    io.LimitReader(buf.Reader, length),
-                       FrameType: b,
-                       Length:    length,
-                       header:    bytes.NewBuffer(header)}, err
-       }
-       return &hixieSentinelFrameReader{
-               reader:    buf.Reader,
-               FrameType: b,
-               header:    bytes.NewBuffer(header)}, err
-}
-
-type hixiFrameWriter struct {
-       writer *bufio.Writer
-}
-
-func (frame *hixiFrameWriter) Write(msg []byte) (n int, err error) {
-       frame.writer.WriteByte(0)
-       frame.writer.Write(msg)
-       frame.writer.WriteByte(0xff)
-       err = frame.writer.Flush()
-       return len(msg), err
-}
-
-func (frame *hixiFrameWriter) Close() error { return nil }
-
-type hixiFrameWriterFactory struct {
-       *bufio.Writer
-}
-
-func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
-       if payloadType != TextFrame {
-               return nil, ErrNotSupported
-       }
-       return &hixiFrameWriter{writer: buf.Writer}, nil
-}
-
-type hixiFrameHandler struct {
-       conn *Conn
-}
-
-func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
-       if header := frame.HeaderReader(); header != nil {
-               io.Copy(ioutil.Discard, header)
-       }
-       if frame.PayloadType() != TextFrame {
-               io.Copy(ioutil.Discard, frame)
-               return nil, nil
-       }
-       return frame, nil
-}
-
-func (handler *hixiFrameHandler) WriteClose(_ int) (err error) {
-       handler.conn.wio.Lock()
-       defer handler.conn.wio.Unlock()
-       closingFrame := []byte{'\xff', '\x00'}
-       handler.conn.buf.Write(closingFrame)
-       return handler.conn.buf.Flush()
-}
-
-// newHixiConn creates a new WebSocket connection speaking hixie draft protocol.
-func newHixieConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-       if buf == nil {
-               br := bufio.NewReader(rwc)
-               bw := bufio.NewWriter(rwc)
-               buf = bufio.NewReadWriter(br, bw)
-       }
-       ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
-               frameReaderFactory: hixieFrameReaderFactory{buf.Reader},
-               frameWriterFactory: hixiFrameWriterFactory{buf.Writer},
-               PayloadType:        TextFrame}
-       ws.frameHandler = &hixiFrameHandler{ws}
-       return ws
-}
-
-// getChallengeResponse computes the expected response from the
-// challenge as described in section 5.1 Opening Handshake steps 42 to
-// 43 of http://www.whatwg.org/specs/web-socket-protocol/
-func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err error) {
-       // 41. Let /challenge/ be the concatenation of /number_1/, expressed
-       // a big-endian 32 bit integer, /number_2/, expressed in a big-
-       // endian 32 bit integer, and the eight bytes of /key_3/ in the
-       // order they were sent to the wire.
-       challenge := make([]byte, 16)
-       binary.BigEndian.PutUint32(challenge[0:], number1)
-       binary.BigEndian.PutUint32(challenge[4:], number2)
-       copy(challenge[8:], key3)
-
-       // 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big-
-       // endian 128 bit string.
-       h := md5.New()
-       if _, err = h.Write(challenge); err != nil {
-               return
-       }
-       expected = h.Sum(nil)
-       return
-}
-
-// Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func generateKeyNumber() (key string, number uint32) {
-       // 16.  Let /spaces_n/ be a random integer from 1 to 12 inclusive.
-       spaces := rand.Intn(12) + 1
-
-       // 17. Let /max_n/ be the largest integer not greater than
-       //     4,294,967,295 divided by /spaces_n/
-       max := int(4294967295 / uint32(spaces))
-
-       // 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive.
-       number = uint32(rand.Intn(max + 1))
-
-       // 19. Let /product_n/ be the result of multiplying /number_n/ and
-       //     /spaces_n/ together.
-       product := number * uint32(spaces)
-
-       // 20. Let /key_n/ be a string consisting of /product_n/, expressed
-       // in base ten using the numerals in the range U+0030 DIGIT ZERO (0)
-       // to U+0039 DIGIT NINE (9).
-       key = fmt.Sprintf("%d", product)
-
-       // 21. Insert between one and twelve random characters from the ranges
-       //     U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
-       //     positions.
-       n := rand.Intn(12) + 1
-       for i := 0; i < n; i++ {
-               pos := rand.Intn(len(key)) + 1
-               ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))]
-               key = key[0:pos] + string(ch) + key[pos:]
-       }
-
-       // 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
-       //     positions other than the start or end of the string.
-       for i := 0; i < spaces; i++ {
-               pos := rand.Intn(len(key)-1) + 1
-               key = key[0:pos] + " " + key[pos:]
-       }
-
-       return
-}
-
-// Generates handshake key_3 as described in 4.1 Opening handshake step 26.
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func generateKey3() (key []byte) {
-       // 26. Let /key3/ be a string consisting of eight random bytes (or
-       //  equivalently, a random 64 bit integer encoded in big-endian order).
-       key = make([]byte, 8)
-       for i := 0; i < 8; i++ {
-               key[i] = byte(rand.Intn(256))
-       }
-       return
-}
-
-// Cilent handhake described in (soon obsolete)
-// draft-ietf-hybi-thewebsocket-protocol-00
-// (draft-hixie-thewebsocket-protocol-76) 
-func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
-       switch config.Version {
-       case ProtocolVersionHixie76, ProtocolVersionHybi00:
-       default:
-               panic("wrong protocol version.")
-       }
-       // 4.1. Opening handshake.
-       // Step 5.  send a request line.
-       bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
-
-       // Step 6-14. push request headers in fields.
-       fields := []string{
-               "Upgrade: WebSocket\r\n",
-               "Connection: Upgrade\r\n",
-               "Host: " + config.Location.Host + "\r\n",
-               "Origin: " + config.Origin.String() + "\r\n",
-       }
-       if len(config.Protocol) > 0 {
-               if len(config.Protocol) != 1 {
-                       return ErrBadWebSocketProtocol
-               }
-               fields = append(fields, "Sec-WebSocket-Protocol: "+config.Protocol[0]+"\r\n")
-       }
-       // TODO(ukai): Step 15. send cookie if any.
-
-       // Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
-       key1, number1 := generateKeyNumber()
-       key2, number2 := generateKeyNumber()
-       if config.handshakeData != nil {
-               key1 = config.handshakeData["key1"]
-               n, err := strconv.ParseUint(config.handshakeData["number1"], 10, 32)
-               if err != nil {
-                       panic(err)
-               }
-               number1 = uint32(n)
-               key2 = config.handshakeData["key2"]
-               n, err = strconv.ParseUint(config.handshakeData["number2"], 10, 32)
-               if err != nil {
-                       panic(err)
-               }
-               number2 = uint32(n)
-       }
-       fields = append(fields, "Sec-WebSocket-Key1: "+key1+"\r\n")
-       fields = append(fields, "Sec-WebSocket-Key2: "+key2+"\r\n")
-
-       // Step 24. shuffle fields and send them out.
-       for i := 1; i < len(fields); i++ {
-               j := rand.Intn(i)
-               fields[i], fields[j] = fields[j], fields[i]
-       }
-       for i := 0; i < len(fields); i++ {
-               bw.WriteString(fields[i])
-       }
-       // Step 25. send CRLF.
-       bw.WriteString("\r\n")
-
-       // Step 26. generate 8 bytes random key.
-       key3 := generateKey3()
-       if config.handshakeData != nil {
-               key3 = []byte(config.handshakeData["key3"])
-       }
-       // Step 27. send it out.
-       bw.Write(key3)
-       if err = bw.Flush(); err != nil {
-               return
-       }
-
-       // Step 28-29, 32-40. read response from server.
-       resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
-       if err != nil {
-               return err
-       }
-       // Step 30. check response code is 101.
-       if resp.StatusCode != 101 {
-               return ErrBadStatus
-       }
-
-       // Step 41. check websocket headers.
-       if resp.Header.Get("Upgrade") != "WebSocket" ||
-               strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
-               return ErrBadUpgrade
-       }
-
-       if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() {
-               return ErrBadWebSocketOrigin
-       }
-
-       if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() {
-               return ErrBadWebSocketLocation
-       }
-
-       if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] {
-               return ErrBadWebSocketProtocol
-       }
-
-       // Step 42-43. get expected data from challenge data.
-       expected, err := getChallengeResponse(number1, number2, key3)
-       if err != nil {
-               return err
-       }
-
-       // Step 44. read 16 bytes from server.
-       reply := make([]byte, 16)
-       if _, err = io.ReadFull(br, reply); err != nil {
-               return err
-       }
-
-       // Step 45. check the reply equals to expected data.
-       if !bytes.Equal(expected, reply) {
-               return ErrChallengeResponse
-       }
-       // WebSocket connection is established.
-       return
-}
-
-// Client Handshake described in (soon obsolete)
-// draft-hixie-thewebsocket-protocol-75.
-func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
-       if config.Version != ProtocolVersionHixie75 {
-               panic("wrong protocol version.")
-       }
-       bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
-       bw.WriteString("Upgrade: WebSocket\r\n")
-       bw.WriteString("Connection: Upgrade\r\n")
-       bw.WriteString("Host: " + config.Location.Host + "\r\n")
-       bw.WriteString("Origin: " + config.Origin.String() + "\r\n")
-       if len(config.Protocol) > 0 {
-               if len(config.Protocol) != 1 {
-                       return ErrBadWebSocketProtocol
-               }
-               bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
-       }
-       bw.WriteString("\r\n")
-       bw.Flush()
-       resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
-       if err != nil {
-               return
-       }
-       if resp.Status != "101 Web Socket Protocol Handshake" {
-               return ErrBadStatus
-       }
-       if resp.Header.Get("Upgrade") != "WebSocket" ||
-               resp.Header.Get("Connection") != "Upgrade" {
-               return ErrBadUpgrade
-       }
-       if resp.Header.Get("Websocket-Origin") != config.Origin.String() {
-               return ErrBadWebSocketOrigin
-       }
-       if resp.Header.Get("Websocket-Location") != config.Location.String() {
-               return ErrBadWebSocketLocation
-       }
-       if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] {
-               return ErrBadWebSocketProtocol
-       }
-       return
-}
-
-// newHixieClientConn returns new WebSocket connection speaking hixie draft protocol.
-func newHixieClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
-       return newHixieConn(config, buf, rwc, nil)
-}
-
-// Gets key number from Sec-WebSocket-Key<n>: field as described
-// in 5.2 Sending the server's opening handshake, 4.
-func getKeyNumber(s string) (r uint32) {
-       // 4. Let /key-number_n/ be the digits (characters in the range
-       // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/,
-       // interpreted as a base ten integer, ignoring all other characters
-       // in /key_n/.
-       r = 0
-       for i := 0; i < len(s); i++ {
-               if s[i] >= '0' && s[i] <= '9' {
-                       r = r*10 + uint32(s[i]) - '0'
-               }
-       }
-       return
-}
-
-// A Hixie76ServerHandshaker performs a server handshake using
-// hixie draft 76 protocol.
-type hixie76ServerHandshaker struct {
-       *Config
-       challengeResponse []byte
-}
-
-func (c *hixie76ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
-       c.Version = ProtocolVersionHybi00
-       if req.Method != "GET" {
-               return http.StatusMethodNotAllowed, ErrBadRequestMethod
-       }
-       // HTTP version can be safely ignored.
-
-       if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
-               strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
-               return http.StatusBadRequest, ErrNotWebSocket
-       }
-
-       // TODO(ukai): check Host
-       c.Origin, err = url.ParseRequest(req.Header.Get("Origin"))
-       if err != nil {
-               return http.StatusBadRequest, err
-       }
-
-       key1 := req.Header.Get("Sec-Websocket-Key1")
-       if key1 == "" {
-               return http.StatusBadRequest, ErrChallengeResponse
-       }
-       key2 := req.Header.Get("Sec-Websocket-Key2")
-       if key2 == "" {
-               return http.StatusBadRequest, ErrChallengeResponse
-       }
-       key3 := make([]byte, 8)
-       if _, err := io.ReadFull(buf, key3); err != nil {
-               return http.StatusBadRequest, ErrChallengeResponse
-       }
-
-       var scheme string
-       if req.TLS != nil {
-               scheme = "wss"
-       } else {
-               scheme = "ws"
-       }
-       c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RequestURI())
-       if err != nil {
-               return http.StatusBadRequest, err
-       }
-
-       // Step 4. get key number in Sec-WebSocket-Key<n> fields.
-       keyNumber1 := getKeyNumber(key1)
-       keyNumber2 := getKeyNumber(key2)
-
-       // Step 5. get number of spaces in Sec-WebSocket-Key<n> fields.
-       space1 := uint32(strings.Count(key1, " "))
-       space2 := uint32(strings.Count(key2, " "))
-       if space1 == 0 || space2 == 0 {
-               return http.StatusBadRequest, ErrChallengeResponse
-       }
-
-       // Step 6. key number must be an integral multiple of spaces.
-       if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 {
-               return http.StatusBadRequest, ErrChallengeResponse
-       }
-
-       // Step 7. let part be key number divided by spaces.
-       part1 := keyNumber1 / space1
-       part2 := keyNumber2 / space2
-
-       // Step 8. let challenge be concatenation of part1, part2 and key3.
-       // Step 9. get MD5 fingerprint of challenge.
-       c.challengeResponse, err = getChallengeResponse(part1, part2, key3)
-       if err != nil {
-               return http.StatusInternalServerError, err
-       }
-       protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
-       protocols := strings.Split(protocol, ",")
-       for i := 0; i < len(protocols); i++ {
-               c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
-       }
-
-       return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hixie76ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
-       if len(c.Protocol) > 0 {
-               if len(c.Protocol) != 1 {
-                       return ErrBadWebSocketProtocol
-               }
-       }
-
-       // Step 10. send response status line.
-       buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n")
-       // Step 11. send response headers.
-       buf.WriteString("Upgrade: WebSocket\r\n")
-       buf.WriteString("Connection: Upgrade\r\n")
-       buf.WriteString("Sec-WebSocket-Origin: " + c.Origin.String() + "\r\n")
-       buf.WriteString("Sec-WebSocket-Location: " + c.Location.String() + "\r\n")
-       if len(c.Protocol) > 0 {
-               buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
-       }
-       // Step 12. send CRLF.
-       buf.WriteString("\r\n")
-       // Step 13. send response data.
-       buf.Write(c.challengeResponse)
-       return buf.Flush()
-}
-
-func (c *hixie76ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
-       return newHixieServerConn(c.Config, buf, rwc, request)
-}
-
-// A hixie75ServerHandshaker performs a server handshake using
-// hixie draft 75 protocol.
-type hixie75ServerHandshaker struct {
-       *Config
-}
-
-func (c *hixie75ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
-       c.Version = ProtocolVersionHixie75
-       if req.Method != "GET" || req.Proto != "HTTP/1.1" {
-               return http.StatusMethodNotAllowed, ErrBadRequestMethod
-       }
-       if req.Header.Get("Upgrade") != "WebSocket" {
-               return http.StatusBadRequest, ErrNotWebSocket
-       }
-       if req.Header.Get("Connection") != "Upgrade" {
-               return http.StatusBadRequest, ErrNotWebSocket
-       }
-       c.Origin, err = url.ParseRequest(strings.TrimSpace(req.Header.Get("Origin")))
-       if err != nil {
-               return http.StatusBadRequest, err
-       }
-
-       var scheme string
-       if req.TLS != nil {
-               scheme = "wss"
-       } else {
-               scheme = "ws"
-       }
-       c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RequestURI())
-       if err != nil {
-               return http.StatusBadRequest, err
-       }
-       protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol"))
-       protocols := strings.Split(protocol, ",")
-       for i := 0; i < len(protocols); i++ {
-               c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
-       }
-
-       return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hixie75ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
-       if len(c.Protocol) > 0 {
-               if len(c.Protocol) != 1 {
-                       return ErrBadWebSocketProtocol
-               }
-       }
-
-       buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
-       buf.WriteString("Upgrade: WebSocket\r\n")
-       buf.WriteString("Connection: Upgrade\r\n")
-       buf.WriteString("WebSocket-Origin: " + c.Origin.String() + "\r\n")
-       buf.WriteString("WebSocket-Location: " + c.Location.String() + "\r\n")
-       if len(c.Protocol) > 0 {
-               buf.WriteString("WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
-       }
-       buf.WriteString("\r\n")
-       return buf.Flush()
-}
-
-func (c *hixie75ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
-       return newHixieServerConn(c.Config, buf, rwc, request)
-}
-
-// newHixieServerConn returns a new WebSocket connection speaking hixie draft protocol.
-func newHixieServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-       return newHixieConn(config, buf, rwc, request)
-}
diff --git a/libgo/go/websocket/hixie_test.go b/libgo/go/websocket/hixie_test.go
deleted file mode 100644 (file)
index bf537c0..0000000
+++ /dev/null
@@ -1,201 +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 websocket
-
-import (
-       "bufio"
-       "bytes"
-       "fmt"
-       "io"
-       "net/http"
-       "net/url"
-       "strings"
-       "testing"
-)
-
-// Test the getChallengeResponse function with values from section
-// 5.1 of the specification steps 18, 26, and 43 from
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
-func TestHixie76Challenge(t *testing.T) {
-       var part1 uint32 = 777007543
-       var part2 uint32 = 114997259
-       key3 := []byte{0x47, 0x30, 0x22, 0x2D, 0x5A, 0x3F, 0x47, 0x58}
-       expected := []byte("0st3Rl&q-2ZU^weu")
-
-       response, err := getChallengeResponse(part1, part2, key3)
-       if err != nil {
-               t.Errorf("getChallengeResponse: returned error %v", err)
-               return
-       }
-       if !bytes.Equal(expected, response) {
-               t.Errorf("getChallengeResponse: expected %q got %q", expected, response)
-       }
-}
-
-func TestHixie76ClientHandshake(t *testing.T) {
-       b := bytes.NewBuffer([]byte{})
-       bw := bufio.NewWriter(b)
-       br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 WebSocket Protocol Handshake
-Upgrade: WebSocket
-Connection: Upgrade
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Location: ws://example.com/demo
-Sec-WebSocket-Protocol: sample
-
-8jKS'y:G*Co,Wxa-`))
-
-       var err error
-       config := new(Config)
-       config.Location, err = url.ParseRequest("ws://example.com/demo")
-       if err != nil {
-               t.Fatal("location url", err)
-       }
-       config.Origin, err = url.ParseRequest("http://example.com")
-       if err != nil {
-               t.Fatal("origin url", err)
-       }
-       config.Protocol = append(config.Protocol, "sample")
-       config.Version = ProtocolVersionHixie76
-
-       config.handshakeData = map[string]string{
-               "key1":    "4 @1  46546xW%0l 1 5",
-               "number1": "829309203",
-               "key2":    "12998 5 Y3 1  .P00",
-               "number2": "259970620",
-               "key3":    "^n:ds[4U",
-       }
-       err = hixie76ClientHandshake(config, br, bw)
-       if err != nil {
-               t.Errorf("handshake failed: %v", err)
-       }
-       req, err := http.ReadRequest(bufio.NewReader(b))
-       if err != nil {
-               t.Fatalf("read request: %v", err)
-       }
-       if req.Method != "GET" {
-               t.Errorf("request method expected GET, but got %q", req.Method)
-       }
-       if req.URL.Path != "/demo" {
-               t.Errorf("request path expected /demo, but got %q", req.URL.Path)
-       }
-       if req.Proto != "HTTP/1.1" {
-               t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
-       }
-       if req.Host != "example.com" {
-               t.Errorf("request Host expected example.com, but got %v", req.Host)
-       }
-       var expectedHeader = map[string]string{
-               "Connection":             "Upgrade",
-               "Upgrade":                "WebSocket",
-               "Origin":                 "http://example.com",
-               "Sec-Websocket-Key1":     config.handshakeData["key1"],
-               "Sec-Websocket-Key2":     config.handshakeData["key2"],
-               "Sec-WebSocket-Protocol": config.Protocol[0],
-       }
-       for k, v := range expectedHeader {
-               if req.Header.Get(k) != v {
-                       t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
-               }
-       }
-}
-
-func TestHixie76ServerHandshake(t *testing.T) {
-       config := new(Config)
-       handshaker := &hixie76ServerHandshaker{Config: config}
-       br := bufio.NewReader(strings.NewReader(`GET /demo HTTP/1.1
-Host: example.com
-Connection: Upgrade
-Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
-Sec-WebSocket-Protocol: sample
-Upgrade: WebSocket
-Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
-Origin: http://example.com
-
-^n:ds[4U`))
-       req, err := http.ReadRequest(br)
-       if err != nil {
-               t.Fatal("request", err)
-       }
-       code, err := handshaker.ReadHandshake(br, req)
-       if err != nil {
-               t.Errorf("handshake failed: %v", err)
-       }
-       if code != http.StatusSwitchingProtocols {
-               t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
-       }
-       b := bytes.NewBuffer([]byte{})
-       bw := bufio.NewWriter(b)
-
-       err = handshaker.AcceptHandshake(bw)
-       if err != nil {
-               t.Errorf("handshake response failed: %v", err)
-       }
-       expectedResponse := strings.Join([]string{
-               "HTTP/1.1 101 WebSocket Protocol Handshake",
-               "Upgrade: WebSocket",
-               "Connection: Upgrade",
-               "Sec-WebSocket-Origin: http://example.com",
-               "Sec-WebSocket-Location: ws://example.com/demo",
-               "Sec-WebSocket-Protocol: sample",
-               "", ""}, "\r\n") + "8jKS'y:G*Co,Wxa-"
-       if b.String() != expectedResponse {
-               t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
-       }
-}
-
-func TestHixie76SkipLengthFrame(t *testing.T) {
-       b := []byte{'\x80', '\x01', 'x', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
-       buf := bytes.NewBuffer(b)
-       br := bufio.NewReader(buf)
-       bw := bufio.NewWriter(buf)
-       config := newConfig(t, "/")
-       ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
-       msg := make([]byte, 5)
-       n, err := ws.Read(msg)
-       if err != nil {
-               t.Errorf("Read: %v", err)
-       }
-       if !bytes.Equal(b[4:9], msg[0:n]) {
-               t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
-       }
-}
-
-func TestHixie76SkipNoUTF8Frame(t *testing.T) {
-       b := []byte{'\x01', 'n', '\xff', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
-       buf := bytes.NewBuffer(b)
-       br := bufio.NewReader(buf)
-       bw := bufio.NewWriter(buf)
-       config := newConfig(t, "/")
-       ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
-       msg := make([]byte, 5)
-       n, err := ws.Read(msg)
-       if err != nil {
-               t.Errorf("Read: %v", err)
-       }
-       if !bytes.Equal(b[4:9], msg[0:n]) {
-               t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
-       }
-}
-
-func TestHixie76ClosingFrame(t *testing.T) {
-       b := []byte{0, 'h', 'e', 'l', 'l', 'o', '\xff'}
-       buf := bytes.NewBuffer(b)
-       br := bufio.NewReader(buf)
-       bw := bufio.NewWriter(buf)
-       config := newConfig(t, "/")
-       ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
-       msg := make([]byte, 5)
-       n, err := ws.Read(msg)
-       if err != nil {
-               t.Errorf("read: %v", err)
-       }
-       if !bytes.Equal(b[1:6], msg[0:n]) {
-               t.Errorf("Read: expected %q got %q", b[1:6], msg[0:n])
-       }
-       n, err = ws.Read(msg)
-       if err != io.EOF {
-               t.Errorf("read: %v", err)
-       }
-}
diff --git a/libgo/go/websocket/hybi.go b/libgo/go/websocket/hybi.go
deleted file mode 100644 (file)
index 6b0c528..0000000
+++ /dev/null
@@ -1,549 +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 websocket
-
-// This file implements a protocol of hybi draft.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
-
-import (
-       "bufio"
-       "bytes"
-       "crypto/rand"
-       "crypto/sha1"
-       "encoding/base64"
-       "encoding/binary"
-       "fmt"
-       "io"
-       "io/ioutil"
-       "net/http"
-       "net/url"
-       "strings"
-)
-
-const (
-       websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
-
-       closeStatusNormal            = 1000
-       closeStatusGoingAway         = 1001
-       closeStatusProtocolError     = 1002
-       closeStatusUnsupportedData   = 1003
-       closeStatusFrameTooLarge     = 1004
-       closeStatusNoStatusRcvd      = 1005
-       closeStatusAbnormalClosure   = 1006
-       closeStatusBadMessageData    = 1007
-       closeStatusPolicyViolation   = 1008
-       closeStatusTooBigData        = 1009
-       closeStatusExtensionMismatch = 1010
-
-       maxControlFramePayloadLength = 125
-)
-
-var (
-       ErrBadMaskingKey         = &ProtocolError{"bad masking key"}
-       ErrBadPongMessage        = &ProtocolError{"bad pong message"}
-       ErrBadClosingStatus      = &ProtocolError{"bad closing status"}
-       ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
-       ErrNotImplemented        = &ProtocolError{"not implemented"}
-)
-
-// A hybiFrameHeader is a frame header as defined in hybi draft.
-type hybiFrameHeader struct {
-       Fin        bool
-       Rsv        [3]bool
-       OpCode     byte
-       Length     int64
-       MaskingKey []byte
-
-       data *bytes.Buffer
-}
-
-// A hybiFrameReader is a reader for hybi frame.
-type hybiFrameReader struct {
-       reader io.Reader
-
-       header hybiFrameHeader
-       pos    int64
-       length int
-}
-
-func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
-       n, err = frame.reader.Read(msg)
-       if err != nil {
-               return 0, err
-       }
-       if frame.header.MaskingKey != nil {
-               for i := 0; i < n; i++ {
-                       msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
-                       frame.pos++
-               }
-       }
-       return n, err
-}
-
-func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
-
-func (frame *hybiFrameReader) HeaderReader() io.Reader {
-       if frame.header.data == nil {
-               return nil
-       }
-       if frame.header.data.Len() == 0 {
-               return nil
-       }
-       return frame.header.data
-}
-
-func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
-
-func (frame *hybiFrameReader) Len() (n int) { return frame.length }
-
-// A hybiFrameReaderFactory creates new frame reader based on its frame type.
-type hybiFrameReaderFactory struct {
-       *bufio.Reader
-}
-
-// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
-// See Section 5.2 Base Frameing protocol for detail.
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
-func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
-       hybiFrame := new(hybiFrameReader)
-       frame = hybiFrame
-       var header []byte
-       var b byte
-       // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
-       b, err = buf.ReadByte()
-       if err != nil {
-               return
-       }
-       header = append(header, b)
-       hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
-       for i := 0; i < 3; i++ {
-               j := uint(6 - i)
-               hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
-       }
-       hybiFrame.header.OpCode = header[0] & 0x0f
-
-       // Second byte. Mask/Payload len(7bits)
-       b, err = buf.ReadByte()
-       if err != nil {
-               return
-       }
-       header = append(header, b)
-       mask := (b & 0x80) != 0
-       b &= 0x7f
-       lengthFields := 0
-       switch {
-       case b <= 125: // Payload length 7bits.
-               hybiFrame.header.Length = int64(b)
-       case b == 126: // Payload length 7+16bits
-               lengthFields = 2
-       case b == 127: // Payload length 7+64bits
-               lengthFields = 8
-       }
-       for i := 0; i < lengthFields; i++ {
-               b, err = buf.ReadByte()
-               if err != nil {
-                       return
-               }
-               header = append(header, b)
-               hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
-       }
-       if mask {
-               // Masking key. 4 bytes.
-               for i := 0; i < 4; i++ {
-                       b, err = buf.ReadByte()
-                       if err != nil {
-                               return
-                       }
-                       header = append(header, b)
-                       hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
-               }
-       }
-       hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
-       hybiFrame.header.data = bytes.NewBuffer(header)
-       hybiFrame.length = len(header) + int(hybiFrame.header.Length)
-       return
-}
-
-// A HybiFrameWriter is a writer for hybi frame.
-type hybiFrameWriter struct {
-       writer *bufio.Writer
-
-       header *hybiFrameHeader
-}
-
-func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
-       var header []byte
-       var b byte
-       if frame.header.Fin {
-               b |= 0x80
-       }
-       for i := 0; i < 3; i++ {
-               if frame.header.Rsv[i] {
-                       j := uint(6 - i)
-                       b |= 1 << j
-               }
-       }
-       b |= frame.header.OpCode
-       header = append(header, b)
-       if frame.header.MaskingKey != nil {
-               b = 0x80
-       } else {
-               b = 0
-       }
-       lengthFields := 0
-       length := len(msg)
-       switch {
-       case length <= 125:
-               b |= byte(length)
-       case length < 65536:
-               b |= 126
-               lengthFields = 2
-       default:
-               b |= 127
-               lengthFields = 8
-       }
-       header = append(header, b)
-       for i := 0; i < lengthFields; i++ {
-               j := uint((lengthFields - i - 1) * 8)
-               b = byte((length >> j) & 0xff)
-               header = append(header, b)
-       }
-       if frame.header.MaskingKey != nil {
-               if len(frame.header.MaskingKey) != 4 {
-                       return 0, ErrBadMaskingKey
-               }
-               header = append(header, frame.header.MaskingKey...)
-               frame.writer.Write(header)
-               var data []byte
-
-               for i := 0; i < length; i++ {
-                       data = append(data, msg[i]^frame.header.MaskingKey[i%4])
-               }
-               frame.writer.Write(data)
-               err = frame.writer.Flush()
-               return length, err
-       }
-       frame.writer.Write(header)
-       frame.writer.Write(msg)
-       err = frame.writer.Flush()
-       return length, err
-}
-
-func (frame *hybiFrameWriter) Close() error { return nil }
-
-type hybiFrameWriterFactory struct {
-       *bufio.Writer
-       needMaskingKey bool
-}
-
-func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
-       frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
-       if buf.needMaskingKey {
-               frameHeader.MaskingKey, err = generateMaskingKey()
-               if err != nil {
-                       return nil, err
-               }
-       }
-       return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
-}
-
-type hybiFrameHandler struct {
-       conn        *Conn
-       payloadType byte
-}
-
-func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
-       if handler.conn.IsServerConn() {
-               // The client MUST mask all frames sent to the server.
-               if frame.(*hybiFrameReader).header.MaskingKey == nil {
-                       handler.WriteClose(closeStatusProtocolError)
-                       return nil, io.EOF
-               }
-       } else {
-               // The server MUST NOT mask all frames.
-               if frame.(*hybiFrameReader).header.MaskingKey != nil {
-                       handler.WriteClose(closeStatusProtocolError)
-                       return nil, io.EOF
-               }
-       }
-       if header := frame.HeaderReader(); header != nil {
-               io.Copy(ioutil.Discard, header)
-       }
-       switch frame.PayloadType() {
-       case ContinuationFrame:
-               frame.(*hybiFrameReader).header.OpCode = handler.payloadType
-       case TextFrame, BinaryFrame:
-               handler.payloadType = frame.PayloadType()
-       case CloseFrame:
-               return nil, io.EOF
-       case PingFrame:
-               pingMsg := make([]byte, maxControlFramePayloadLength)
-               n, err := io.ReadFull(frame, pingMsg)
-               if err != nil && err != io.ErrUnexpectedEOF {
-                       return nil, err
-               }
-               io.Copy(ioutil.Discard, frame)
-               n, err = handler.WritePong(pingMsg[:n])
-               if err != nil {
-                       return nil, err
-               }
-               return nil, nil
-       case PongFrame:
-               return nil, ErrNotImplemented
-       }
-       return frame, nil
-}
-
-func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
-       handler.conn.wio.Lock()
-       defer handler.conn.wio.Unlock()
-       w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
-       if err != nil {
-               return err
-       }
-       msg := make([]byte, 2)
-       binary.BigEndian.PutUint16(msg, uint16(status))
-       _, err = w.Write(msg)
-       w.Close()
-       return err
-}
-
-func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
-       handler.conn.wio.Lock()
-       defer handler.conn.wio.Unlock()
-       w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
-       if err != nil {
-               return 0, err
-       }
-       n, err = w.Write(msg)
-       w.Close()
-       return n, err
-}
-
-// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
-func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-       if buf == nil {
-               br := bufio.NewReader(rwc)
-               bw := bufio.NewWriter(rwc)
-               buf = bufio.NewReadWriter(br, bw)
-       }
-       ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
-               frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
-               frameWriterFactory: hybiFrameWriterFactory{
-                       buf.Writer, request == nil},
-               PayloadType:        TextFrame,
-               defaultCloseStatus: closeStatusNormal}
-       ws.frameHandler = &hybiFrameHandler{conn: ws}
-       return ws
-}
-
-// generateMaskingKey generates a masking key for a frame.
-func generateMaskingKey() (maskingKey []byte, err error) {
-       maskingKey = make([]byte, 4)
-       if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
-               return
-       }
-       return
-}
-
-// genetateNonce geneates a nonce consisting of a randomly selected 16-byte
-// value that has been base64-encoded.
-func generateNonce() (nonce []byte) {
-       key := make([]byte, 16)
-       if _, err := io.ReadFull(rand.Reader, key); err != nil {
-               panic(err)
-       }
-       nonce = make([]byte, 24)
-       base64.StdEncoding.Encode(nonce, key)
-       return
-}
-
-// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
-// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
-func getNonceAccept(nonce []byte) (expected []byte, err error) {
-       h := sha1.New()
-       if _, err = h.Write(nonce); err != nil {
-               return
-       }
-       if _, err = h.Write([]byte(websocketGUID)); err != nil {
-               return
-       }
-       expected = make([]byte, 28)
-       base64.StdEncoding.Encode(expected, h.Sum(nil))
-       return
-}
-
-func isHybiVersion(version int) bool {
-       switch version {
-       case ProtocolVersionHybi08, ProtocolVersionHybi13:
-               return true
-       default:
-       }
-       return false
-}
-
-// Client handhake described in draft-ietf-hybi-thewebsocket-protocol-17
-func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
-       if !isHybiVersion(config.Version) {
-               panic("wrong protocol version.")
-       }
-
-       bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
-
-       bw.WriteString("Host: " + config.Location.Host + "\r\n")
-       bw.WriteString("Upgrade: websocket\r\n")
-       bw.WriteString("Connection: Upgrade\r\n")
-       nonce := generateNonce()
-       if config.handshakeData != nil {
-               nonce = []byte(config.handshakeData["key"])
-       }
-       bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
-       if config.Version == ProtocolVersionHybi13 {
-               bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
-       } else if config.Version == ProtocolVersionHybi08 {
-               bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
-       }
-       bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
-       if len(config.Protocol) > 0 {
-               bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
-       }
-       // TODO(ukai): send extensions.
-       // TODO(ukai): send cookie if any.
-
-       bw.WriteString("\r\n")
-       if err = bw.Flush(); err != nil {
-               return err
-       }
-
-       resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
-       if err != nil {
-               return err
-       }
-       if resp.StatusCode != 101 {
-               return ErrBadStatus
-       }
-       if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
-               strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
-               return ErrBadUpgrade
-       }
-       expectedAccept, err := getNonceAccept(nonce)
-       if err != nil {
-               return err
-       }
-       if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
-               return ErrChallengeResponse
-       }
-       if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
-               return ErrUnsupportedExtensions
-       }
-       offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
-       if offeredProtocol != "" {
-               protocolMatched := false
-               for i := 0; i < len(config.Protocol); i++ {
-                       if config.Protocol[i] == offeredProtocol {
-                               protocolMatched = true
-                               break
-                       }
-               }
-               if !protocolMatched {
-                       return ErrBadWebSocketProtocol
-               }
-               config.Protocol = []string{offeredProtocol}
-       }
-
-       return nil
-}
-
-// newHybiClientConn creates a client WebSocket connection after handshake.
-func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
-       return newHybiConn(config, buf, rwc, nil)
-}
-
-// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
-type hybiServerHandshaker struct {
-       *Config
-       accept []byte
-}
-
-func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
-       c.Version = ProtocolVersionHybi13
-       if req.Method != "GET" {
-               return http.StatusMethodNotAllowed, ErrBadRequestMethod
-       }
-       // HTTP version can be safely ignored.
-
-       if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
-               !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
-               return http.StatusBadRequest, ErrNotWebSocket
-       }
-
-       key := req.Header.Get("Sec-Websocket-Key")
-       if key == "" {
-               return http.StatusBadRequest, ErrChallengeResponse
-       }
-       version := req.Header.Get("Sec-Websocket-Version")
-       var origin string
-       switch version {
-       case "13":
-               c.Version = ProtocolVersionHybi13
-               origin = req.Header.Get("Origin")
-       case "8":
-               c.Version = ProtocolVersionHybi08
-               origin = req.Header.Get("Sec-Websocket-Origin")
-       default:
-               return http.StatusBadRequest, ErrBadWebSocketVersion
-       }
-       c.Origin, err = url.ParseRequest(origin)
-       if err != nil {
-               return http.StatusForbidden, err
-       }
-       var scheme string
-       if req.TLS != nil {
-               scheme = "wss"
-       } else {
-               scheme = "ws"
-       }
-       c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RequestURI())
-       if err != nil {
-               return http.StatusBadRequest, err
-       }
-       protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
-       protocols := strings.Split(protocol, ",")
-       for i := 0; i < len(protocols); i++ {
-               c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
-       }
-       c.accept, err = getNonceAccept([]byte(key))
-       if err != nil {
-               return http.StatusInternalServerError, err
-       }
-       return http.StatusSwitchingProtocols, nil
-}
-
-func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
-       if len(c.Protocol) > 0 {
-               if len(c.Protocol) != 1 {
-                       return ErrBadWebSocketProtocol
-               }
-       }
-       buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
-       buf.WriteString("Upgrade: websocket\r\n")
-       buf.WriteString("Connection: Upgrade\r\n")
-       buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
-       if len(c.Protocol) > 0 {
-               buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
-       }
-       // TODO(ukai): support extensions
-       buf.WriteString("\r\n")
-       return buf.Flush()
-}
-
-func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-       return newHybiServerConn(c.Config, buf, rwc, request)
-}
-
-// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
-func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
-       return newHybiConn(config, buf, rwc, request)
-}
diff --git a/libgo/go/websocket/hybi_test.go b/libgo/go/websocket/hybi_test.go
deleted file mode 100644 (file)
index 60375ff..0000000
+++ /dev/null
@@ -1,584 +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 websocket
-
-import (
-       "bufio"
-       "bytes"
-       "fmt"
-       "io"
-       "net/http"
-       "net/url"
-       "strings"
-       "testing"
-)
-
-// Test the getNonceAccept function with values in
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
-func TestSecWebSocketAccept(t *testing.T) {
-       nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
-       expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
-       accept, err := getNonceAccept(nonce)
-       if err != nil {
-               t.Errorf("getNonceAccept: returned error %v", err)
-               return
-       }
-       if !bytes.Equal(expected, accept) {
-               t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
-       }
-}
-
-func TestHybiClientHandshake(t *testing.T) {
-       b := bytes.NewBuffer([]byte{})
-       bw := bufio.NewWriter(b)
-       br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-Sec-WebSocket-Protocol: chat
-
-`))
-       var err error
-       config := new(Config)
-       config.Location, err = url.ParseRequest("ws://server.example.com/chat")
-       if err != nil {
-               t.Fatal("location url", err)
-       }
-       config.Origin, err = url.ParseRequest("http://example.com")
-       if err != nil {
-               t.Fatal("origin url", err)
-       }
-       config.Protocol = append(config.Protocol, "chat")
-       config.Protocol = append(config.Protocol, "superchat")
-       config.Version = ProtocolVersionHybi13
-
-       config.handshakeData = map[string]string{
-               "key": "dGhlIHNhbXBsZSBub25jZQ==",
-       }
-       err = hybiClientHandshake(config, br, bw)
-       if err != nil {
-               t.Errorf("handshake failed: %v", err)
-       }
-       req, err := http.ReadRequest(bufio.NewReader(b))
-       if err != nil {
-               t.Fatalf("read request: %v", err)
-       }
-       if req.Method != "GET" {
-               t.Errorf("request method expected GET, but got %q", req.Method)
-       }
-       if req.URL.Path != "/chat" {
-               t.Errorf("request path expected /chat, but got %q", req.URL.Path)
-       }
-       if req.Proto != "HTTP/1.1" {
-               t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
-       }
-       if req.Host != "server.example.com" {
-               t.Errorf("request Host expected server.example.com, but got %v", req.Host)
-       }
-       var expectedHeader = map[string]string{
-               "Connection":             "Upgrade",
-               "Upgrade":                "websocket",
-               "Sec-Websocket-Key":      config.handshakeData["key"],
-               "Origin":                 config.Origin.String(),
-               "Sec-Websocket-Protocol": "chat, superchat",
-               "Sec-Websocket-Version":  fmt.Sprintf("%d", ProtocolVersionHybi13),
-       }
-       for k, v := range expectedHeader {
-               if req.Header.Get(k) != v {
-                       t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
-               }
-       }
-}
-
-func TestHybiClientHandshakeHybi08(t *testing.T) {
-       b := bytes.NewBuffer([]byte{})
-       bw := bufio.NewWriter(b)
-       br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-Sec-WebSocket-Protocol: chat
-
-`))
-       var err error
-       config := new(Config)
-       config.Location, err = url.ParseRequest("ws://server.example.com/chat")
-       if err != nil {
-               t.Fatal("location url", err)
-       }
-       config.Origin, err = url.ParseRequest("http://example.com")
-       if err != nil {
-               t.Fatal("origin url", err)
-       }
-       config.Protocol = append(config.Protocol, "chat")
-       config.Protocol = append(config.Protocol, "superchat")
-       config.Version = ProtocolVersionHybi08
-
-       config.handshakeData = map[string]string{
-               "key": "dGhlIHNhbXBsZSBub25jZQ==",
-       }
-       err = hybiClientHandshake(config, br, bw)
-       if err != nil {
-               t.Errorf("handshake failed: %v", err)
-       }
-       req, err := http.ReadRequest(bufio.NewReader(b))
-       if err != nil {
-               t.Fatalf("read request: %v", err)
-       }
-       if req.Method != "GET" {
-               t.Errorf("request method expected GET, but got %q", req.Method)
-       }
-       if req.URL.Path != "/chat" {
-               t.Errorf("request path expected /demo, but got %q", req.URL.Path)
-       }
-       if req.Proto != "HTTP/1.1" {
-               t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
-       }
-       if req.Host != "server.example.com" {
-               t.Errorf("request Host expected example.com, but got %v", req.Host)
-       }
-       var expectedHeader = map[string]string{
-               "Connection":             "Upgrade",
-               "Upgrade":                "websocket",
-               "Sec-Websocket-Key":      config.handshakeData["key"],
-               "Sec-Websocket-Origin":   config.Origin.String(),
-               "Sec-Websocket-Protocol": "chat, superchat",
-               "Sec-Websocket-Version":  fmt.Sprintf("%d", ProtocolVersionHybi08),
-       }
-       for k, v := range expectedHeader {
-               if req.Header.Get(k) != v {
-                       t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
-               }
-       }
-}
-
-func TestHybiServerHandshake(t *testing.T) {
-       config := new(Config)
-       handshaker := &hybiServerHandshaker{Config: config}
-       br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 13
-
-`))
-       req, err := http.ReadRequest(br)
-       if err != nil {
-               t.Fatal("request", err)
-       }
-       code, err := handshaker.ReadHandshake(br, req)
-       if err != nil {
-               t.Errorf("handshake failed: %v", err)
-       }
-       if code != http.StatusSwitchingProtocols {
-               t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
-       }
-       b := bytes.NewBuffer([]byte{})
-       bw := bufio.NewWriter(b)
-
-       config.Protocol = []string{"chat"}
-
-       err = handshaker.AcceptHandshake(bw)
-       if err != nil {
-               t.Errorf("handshake response failed: %v", err)
-       }
-       expectedResponse := strings.Join([]string{
-               "HTTP/1.1 101 Switching Protocols",
-               "Upgrade: websocket",
-               "Connection: Upgrade",
-               "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
-               "Sec-WebSocket-Protocol: chat",
-               "", ""}, "\r\n")
-
-       if b.String() != expectedResponse {
-               t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
-       }
-}
-
-func TestHybiServerHandshakeHybi08(t *testing.T) {
-       config := new(Config)
-       handshaker := &hybiServerHandshaker{Config: config}
-       br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 8
-
-`))
-       req, err := http.ReadRequest(br)
-       if err != nil {
-               t.Fatal("request", err)
-       }
-       code, err := handshaker.ReadHandshake(br, req)
-       if err != nil {
-               t.Errorf("handshake failed: %v", err)
-       }
-       if code != http.StatusSwitchingProtocols {
-               t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
-       }
-       b := bytes.NewBuffer([]byte{})
-       bw := bufio.NewWriter(b)
-
-       config.Protocol = []string{"chat"}
-
-       err = handshaker.AcceptHandshake(bw)
-       if err != nil {
-               t.Errorf("handshake response failed: %v", err)
-       }
-       expectedResponse := strings.Join([]string{
-               "HTTP/1.1 101 Switching Protocols",
-               "Upgrade: websocket",
-               "Connection: Upgrade",
-               "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
-               "Sec-WebSocket-Protocol: chat",
-               "", ""}, "\r\n")
-
-       if b.String() != expectedResponse {
-               t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
-       }
-}
-
-func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
-       config := new(Config)
-       handshaker := &hybiServerHandshaker{Config: config}
-       br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: Upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Sec-WebSocket-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 9
-
-`))
-       req, err := http.ReadRequest(br)
-       if err != nil {
-               t.Fatal("request", err)
-       }
-       code, err := handshaker.ReadHandshake(br, req)
-       if err != ErrBadWebSocketVersion {
-               t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
-       }
-       if code != http.StatusBadRequest {
-               t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
-       }
-}
-
-func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
-       b := bytes.NewBuffer([]byte{})
-       frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
-       w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
-       w.(*hybiFrameWriter).header = frameHeader
-       _, err := w.Write(testPayload)
-       w.Close()
-       if err != nil {
-               t.Errorf("Write error %q", err)
-       }
-       var expectedFrame []byte
-       expectedFrame = append(expectedFrame, testHeader...)
-       expectedFrame = append(expectedFrame, testMaskedPayload...)
-       if !bytes.Equal(expectedFrame, b.Bytes()) {
-               t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
-       }
-       frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
-       r, err := frameReaderFactory.NewFrameReader()
-       if err != nil {
-               t.Errorf("Read error %q", err)
-       }
-       if header := r.HeaderReader(); header == nil {
-               t.Errorf("no header")
-       } else {
-               actualHeader := make([]byte, r.Len())
-               n, err := header.Read(actualHeader)
-               if err != nil {
-                       t.Errorf("Read header error %q", err)
-               } else {
-                       if n < len(testHeader) {
-                               t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
-                       }
-                       if !bytes.Equal(testHeader, actualHeader[:n]) {
-                               t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
-                       }
-               }
-       }
-       if trailer := r.TrailerReader(); trailer != nil {
-               t.Errorf("unexpected trailer %q", trailer)
-       }
-       frame := r.(*hybiFrameReader)
-       if frameHeader.Fin != frame.header.Fin ||
-               frameHeader.OpCode != frame.header.OpCode ||
-               len(testPayload) != int(frame.header.Length) {
-               t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
-       }
-       payload := make([]byte, len(testPayload))
-       _, err = r.Read(payload)
-       if err != nil {
-               t.Errorf("read %v", err)
-       }
-       if !bytes.Equal(testPayload, payload) {
-               t.Errorf("payload %q vs %q", testPayload, payload)
-       }
-}
-
-func TestHybiShortTextFrame(t *testing.T) {
-       frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
-       payload := []byte("hello")
-       testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
-
-       payload = make([]byte, 125)
-       testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiShortMaskedTextFrame(t *testing.T) {
-       frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
-               MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
-       payload := []byte("hello")
-       maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
-       header := []byte{0x81, 0x85}
-       header = append(header, frameHeader.MaskingKey...)
-       testHybiFrame(t, header, payload, maskedPayload, frameHeader)
-}
-
-func TestHybiShortBinaryFrame(t *testing.T) {
-       frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
-       payload := []byte("hello")
-       testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
-
-       payload = make([]byte, 125)
-       testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
-}
-
-func TestHybiControlFrame(t *testing.T) {
-       frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
-       payload := []byte("hello")
-       testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
-
-       frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
-       testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
-
-       frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
-       payload = []byte{0x03, 0xe8} // 1000
-       testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
-}
-
-func TestHybiLongFrame(t *testing.T) {
-       frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
-       payload := make([]byte, 126)
-       testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
-
-       payload = make([]byte, 65535)
-       testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
-
-       payload = make([]byte, 65536)
-       testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
-}
-
-func TestHybiClientRead(t *testing.T) {
-       wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
-               0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
-               0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
-       br := bufio.NewReader(bytes.NewBuffer(wireData))
-       bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-       conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
-       msg := make([]byte, 512)
-       n, err := conn.Read(msg)
-       if err != nil {
-               t.Errorf("read 1st frame, error %q", err)
-       }
-       if n != 5 {
-               t.Errorf("read 1st frame, expect 5, got %d", n)
-       }
-       if !bytes.Equal(wireData[2:7], msg[:n]) {
-               t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
-       }
-       n, err = conn.Read(msg)
-       if err != nil {
-               t.Errorf("read 2nd frame, error %q", err)
-       }
-       if n != 5 {
-               t.Errorf("read 2nd frame, expect 5, got %d", n)
-       }
-       if !bytes.Equal(wireData[16:21], msg[:n]) {
-               t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
-       }
-       n, err = conn.Read(msg)
-       if err == nil {
-               t.Errorf("read not EOF")
-       }
-       if n != 0 {
-               t.Errorf("expect read 0, got %d", n)
-       }
-}
-
-func TestHybiShortRead(t *testing.T) {
-       wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
-               0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
-               0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
-       br := bufio.NewReader(bytes.NewBuffer(wireData))
-       bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-       conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
-       step := 0
-       pos := 0
-       expectedPos := []int{2, 5, 16, 19}
-       expectedLen := []int{3, 2, 3, 2}
-       for {
-               msg := make([]byte, 3)
-               n, err := conn.Read(msg)
-               if step >= len(expectedPos) {
-                       if err == nil {
-                               t.Errorf("read not EOF")
-                       }
-                       if n != 0 {
-                               t.Errorf("expect read 0, got %d", n)
-                       }
-                       return
-               }
-               pos = expectedPos[step]
-               endPos := pos + expectedLen[step]
-               if err != nil {
-                       t.Errorf("read from %d, got error %q", pos, err)
-                       return
-               }
-               if n != endPos-pos {
-                       t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
-               }
-               if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
-                       t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
-               }
-               step++
-       }
-}
-
-func TestHybiServerRead(t *testing.T) {
-       wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
-               0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
-               0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
-               0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
-               0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
-               0x9a, 0xec, 0xc6, 0x48, 0x89, // world
-       }
-       br := bufio.NewReader(bytes.NewBuffer(wireData))
-       bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-       conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
-
-       expected := [][]byte{[]byte("hello"), []byte("world")}
-
-       msg := make([]byte, 512)
-       n, err := conn.Read(msg)
-       if err != nil {
-               t.Errorf("read 1st frame, error %q", err)
-       }
-       if n != 5 {
-               t.Errorf("read 1st frame, expect 5, got %d", n)
-       }
-       if !bytes.Equal(expected[0], msg[:n]) {
-               t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
-       }
-
-       n, err = conn.Read(msg)
-       if err != nil {
-               t.Errorf("read 2nd frame, error %q", err)
-       }
-       if n != 5 {
-               t.Errorf("read 2nd frame, expect 5, got %d", n)
-       }
-       if !bytes.Equal(expected[1], msg[:n]) {
-               t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
-       }
-
-       n, err = conn.Read(msg)
-       if err == nil {
-               t.Errorf("read not EOF")
-       }
-       if n != 0 {
-               t.Errorf("expect read 0, got %d", n)
-       }
-}
-
-func TestHybiServerReadWithoutMasking(t *testing.T) {
-       wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
-       br := bufio.NewReader(bytes.NewBuffer(wireData))
-       bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-       conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
-       // server MUST close the connection upon receiving a non-masked frame.
-       msg := make([]byte, 512)
-       _, err := conn.Read(msg)
-       if err != io.EOF {
-               t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
-       }
-}
-
-func TestHybiClientReadWithMasking(t *testing.T) {
-       wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
-               0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
-       }
-       br := bufio.NewReader(bytes.NewBuffer(wireData))
-       bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
-       conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
-
-       // client MUST close the connection upon receiving a masked frame.
-       msg := make([]byte, 512)
-       _, err := conn.Read(msg)
-       if err != io.EOF {
-               t.Errorf("read 1st frame, expect %q, but got %q", io.EOF, err)
-       }
-}
-
-// Test the hybiServerHandshaker supports firefox implementation and
-// checks Connection request header include (but it's not necessary 
-// equal to) "upgrade"   
-func TestHybiServerFirefoxHandshake(t *testing.T) {
-       config := new(Config)
-       handshaker := &hybiServerHandshaker{Config: config}
-       br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
-Host: server.example.com
-Upgrade: websocket
-Connection: keep-alive, upgrade
-Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-Origin: http://example.com
-Sec-WebSocket-Protocol: chat, superchat
-Sec-WebSocket-Version: 13
-
-`))
-       req, err := http.ReadRequest(br)
-       if err != nil {
-               t.Fatal("request", err)
-       }
-       code, err := handshaker.ReadHandshake(br, req)
-       if err != nil {
-               t.Errorf("handshake failed: %v", err)
-       }
-       if code != http.StatusSwitchingProtocols {
-               t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
-       }
-       b := bytes.NewBuffer([]byte{})
-       bw := bufio.NewWriter(b)
-
-       config.Protocol = []string{"chat"}
-
-       err = handshaker.AcceptHandshake(bw)
-       if err != nil {
-               t.Errorf("handshake response failed: %v", err)
-       }
-       expectedResponse := strings.Join([]string{
-               "HTTP/1.1 101 Switching Protocols",
-               "Upgrade: websocket",
-               "Connection: Upgrade",
-               "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
-               "Sec-WebSocket-Protocol: chat",
-               "", ""}, "\r\n")
-
-       if b.String() != expectedResponse {
-               t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
-       }
-}
diff --git a/libgo/go/websocket/server.go b/libgo/go/websocket/server.go
deleted file mode 100644 (file)
index 63f48e2..0000000
+++ /dev/null
@@ -1,102 +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 websocket
-
-import (
-       "bufio"
-       "fmt"
-       "io"
-       "net/http"
-)
-
-func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request) (conn *Conn, err error) {
-       config := new(Config)
-       var hs serverHandshaker = &hybiServerHandshaker{Config: config}
-       code, err := hs.ReadHandshake(buf.Reader, req)
-       if err == ErrBadWebSocketVersion {
-               fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
-               fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
-               buf.WriteString("\r\n")
-               buf.WriteString(err.Error())
-               buf.Flush()
-               return
-       }
-       if err != nil {
-               hs = &hixie76ServerHandshaker{Config: config}
-               code, err = hs.ReadHandshake(buf.Reader, req)
-       }
-       if err != nil {
-               hs = &hixie75ServerHandshaker{Config: config}
-               code, err = hs.ReadHandshake(buf.Reader, req)
-       }
-       if err != nil {
-               fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
-               buf.WriteString("\r\n")
-               buf.WriteString(err.Error())
-               buf.Flush()
-               return
-       }
-       config.Protocol = nil
-
-       err = hs.AcceptHandshake(buf.Writer)
-       if err != nil {
-               code = http.StatusBadRequest
-               fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
-               buf.WriteString("\r\n")
-               buf.Flush()
-               return
-       }
-       conn = hs.NewServerConn(buf, rwc, req)
-       return
-}
-
-/*
-Handler is an interface to a WebSocket.
-
-A trivial example server:
-
-       package main
-
-       import (
-               "io"
-               "net/http"
-               "websocket"
-       )
-
-       // Echo the data received on the WebSocket.
-       func EchoServer(ws *websocket.Conn) {
-               io.Copy(ws, ws);
-       }
-
-       func main() {
-               http.Handle("/echo", websocket.Handler(EchoServer));
-               err := http.ListenAndServe(":12345", nil);
-               if err != nil {
-                       panic("ListenAndServe: " + err.Error())
-               }
-       }
-*/
-type Handler func(*Conn)
-
-// ServeHTTP implements the http.Handler interface for a Web Socket
-func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
-       rwc, buf, err := w.(http.Hijacker).Hijack()
-       if err != nil {
-               panic("Hijack failed: " + err.Error())
-               return
-       }
-       // The server should abort the WebSocket connection if it finds
-       // the client did not send a handshake that matches with protocol
-       // specification.
-       defer rwc.Close()
-       conn, err := newServerConn(rwc, buf, req)
-       if err != nil {
-               return
-       }
-       if conn == nil {
-               panic("unepxected nil conn")
-       }
-       h(conn)
-}
diff --git a/libgo/go/websocket/websocket.go b/libgo/go/websocket/websocket.go
deleted file mode 100644 (file)
index f7aabc9..0000000
+++ /dev/null
@@ -1,412 +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 websocket implements a client and server for the WebSocket protocol.
-// The protocol is defined at http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol
-package websocket
-
-import (
-       "bufio"
-       "crypto/tls"
-       "encoding/json"
-       "errors"
-       "io"
-       "io/ioutil"
-       "net"
-       "net/http"
-       "net/url"
-       "sync"
-       "time"
-)
-
-const (
-       ProtocolVersionHixie75   = -75
-       ProtocolVersionHixie76   = -76
-       ProtocolVersionHybi00    = 0
-       ProtocolVersionHybi08    = 8
-       ProtocolVersionHybi13    = 13
-       ProtocolVersionHybi      = ProtocolVersionHybi13
-       SupportedProtocolVersion = "13, 8"
-
-       ContinuationFrame = 0
-       TextFrame         = 1
-       BinaryFrame       = 2
-       CloseFrame        = 8
-       PingFrame         = 9
-       PongFrame         = 10
-       UnknownFrame      = 255
-)
-
-// WebSocket protocol errors.
-type ProtocolError struct {
-       ErrorString string
-}
-
-func (err *ProtocolError) Error() string { return err.ErrorString }
-
-var (
-       ErrBadProtocolVersion   = &ProtocolError{"bad protocol version"}
-       ErrBadScheme            = &ProtocolError{"bad scheme"}
-       ErrBadStatus            = &ProtocolError{"bad status"}
-       ErrBadUpgrade           = &ProtocolError{"missing or bad upgrade"}
-       ErrBadWebSocketOrigin   = &ProtocolError{"missing or bad WebSocket-Origin"}
-       ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
-       ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
-       ErrBadWebSocketVersion  = &ProtocolError{"missing or bad WebSocket Version"}
-       ErrChallengeResponse    = &ProtocolError{"mismatch challenge/response"}
-       ErrBadFrame             = &ProtocolError{"bad frame"}
-       ErrBadFrameBoundary     = &ProtocolError{"not on frame boundary"}
-       ErrNotWebSocket         = &ProtocolError{"not websocket protocol"}
-       ErrBadRequestMethod     = &ProtocolError{"bad method"}
-       ErrNotSupported         = &ProtocolError{"not supported"}
-)
-
-// Addr is an implementation of net.Addr for WebSocket.
-type Addr struct {
-       *url.URL
-}
-
-// Network returns the network type for a WebSocket, "websocket".
-func (addr *Addr) Network() string { return "websocket" }
-
-// Config is a WebSocket configuration
-type Config struct {
-       // A WebSocket server address.
-       Location *url.URL
-
-       // A Websocket client origin.
-       Origin *url.URL
-
-       // WebSocket subprotocols.
-       Protocol []string
-
-       // WebSocket protocol version.
-       Version int
-
-       // TLS config for secure WebSocket (wss).
-       TlsConfig *tls.Config
-
-       handshakeData map[string]string
-}
-
-// serverHandshaker is an interface to handle WebSocket server side handshake.
-type serverHandshaker interface {
-       // ReadHandshake reads handshake request message from client.
-       // Returns http response code and error if any.
-       ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
-
-       // AcceptHandshake accepts the client handshake request and sends
-       // handshake response back to client.
-       AcceptHandshake(buf *bufio.Writer) (err error)
-
-       // NewServerConn creates a new WebSocket connection.
-       NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
-}
-
-// frameReader is an interface to read a WebSocket frame.
-type frameReader interface {
-       // Reader is to read payload of the frame.
-       io.Reader
-
-       // PayloadType returns payload type.
-       PayloadType() byte
-
-       // HeaderReader returns a reader to read header of the frame.
-       HeaderReader() io.Reader
-
-       // TrailerReader returns a reader to read trailer of the frame.
-       // If it returns nil, there is no trailer in the frame.
-       TrailerReader() io.Reader
-
-       // Len returns total length of the frame, including header and trailer.
-       Len() int
-}
-
-// frameReaderFactory is an interface to creates new frame reader.
-type frameReaderFactory interface {
-       NewFrameReader() (r frameReader, err error)
-}
-
-// frameWriter is an interface to write a WebSocket frame.
-type frameWriter interface {
-       // Writer is to write playload of the frame.
-       io.WriteCloser
-}
-
-// frameWriterFactory is an interface to create new frame writer.
-type frameWriterFactory interface {
-       NewFrameWriter(payloadType byte) (w frameWriter, err error)
-}
-
-type frameHandler interface {
-       HandleFrame(frame frameReader) (r frameReader, err error)
-       WriteClose(status int) (err error)
-}
-
-// Conn represents a WebSocket connection.
-type Conn struct {
-       config  *Config
-       request *http.Request
-
-       buf *bufio.ReadWriter
-       rwc io.ReadWriteCloser
-
-       rio sync.Mutex
-       frameReaderFactory
-       frameReader
-
-       wio sync.Mutex
-       frameWriterFactory
-
-       frameHandler
-       PayloadType        byte
-       defaultCloseStatus int
-}
-
-// Read implements the io.Reader interface:
-// it reads data of a frame from the WebSocket connection.
-// if msg is not large enough for the frame data, it fills the msg and next Read
-// will read the rest of the frame data.
-// it reads Text frame or Binary frame.
-func (ws *Conn) Read(msg []byte) (n int, err error) {
-       ws.rio.Lock()
-       defer ws.rio.Unlock()
-again:
-       if ws.frameReader == nil {
-               frame, err := ws.frameReaderFactory.NewFrameReader()
-               if err != nil {
-                       return 0, err
-               }
-               ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
-               if err != nil {
-                       return 0, err
-               }
-               if ws.frameReader == nil {
-                       goto again
-               }
-       }
-       n, err = ws.frameReader.Read(msg)
-       if err == io.EOF {
-               if trailer := ws.frameReader.TrailerReader(); trailer != nil {
-                       io.Copy(ioutil.Discard, trailer)
-               }
-               ws.frameReader = nil
-               goto again
-       }
-       return n, err
-}
-
-// Write implements the io.Writer interface:
-// it writes data as a frame to the WebSocket connection.
-func (ws *Conn) Write(msg []byte) (n int, err error) {
-       ws.wio.Lock()
-       defer ws.wio.Unlock()
-       w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
-       if err != nil {
-               return 0, err
-       }
-       n, err = w.Write(msg)
-       w.Close()
-       if err != nil {
-               return n, err
-       }
-       return n, err
-}
-
-// Close implements the io.Closer interface.
-func (ws *Conn) Close() error {
-       err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
-       if err != nil {
-               return err
-       }
-       return ws.rwc.Close()
-}
-
-func (ws *Conn) IsClientConn() bool { return ws.request == nil }
-func (ws *Conn) IsServerConn() bool { return ws.request != nil }
-
-// LocalAddr returns the WebSocket Origin for the connection for client, or
-// the WebSocket location for server.
-func (ws *Conn) LocalAddr() net.Addr {
-       if ws.IsClientConn() {
-               return &Addr{ws.config.Origin}
-       }
-       return &Addr{ws.config.Location}
-}
-
-// RemoteAddr returns the WebSocket location for the connection for client, or
-// the Websocket Origin for server.
-func (ws *Conn) RemoteAddr() net.Addr {
-       if ws.IsClientConn() {
-               return &Addr{ws.config.Location}
-       }
-       return &Addr{ws.config.Origin}
-}
-
-var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
-
-// SetDeadline sets the connection's network read & write deadlines.
-func (ws *Conn) SetDeadline(t time.Time) error {
-       if conn, ok := ws.rwc.(net.Conn); ok {
-               return conn.SetDeadline(t)
-       }
-       return errSetDeadline
-}
-
-// SetReadDeadline sets the connection's network read deadline.
-func (ws *Conn) SetReadDeadline(t time.Time) error {
-       if conn, ok := ws.rwc.(net.Conn); ok {
-               return conn.SetReadDeadline(t)
-       }
-       return errSetDeadline
-}
-
-// SetWriteDeadline sets the connection's network write deadline.
-func (ws *Conn) SetWriteDeadline(t time.Time) error {
-       if conn, ok := ws.rwc.(net.Conn); ok {
-               return conn.SetWriteDeadline(t)
-       }
-       return errSetDeadline
-}
-
-// Config returns the WebSocket config.
-func (ws *Conn) Config() *Config { return ws.config }
-
-// Request returns the http request upgraded to the WebSocket.
-// It is nil for client side.
-func (ws *Conn) Request() *http.Request { return ws.request }
-
-// Codec represents a symmetric pair of functions that implement a codec.
-type Codec struct {
-       Marshal   func(v interface{}) (data []byte, payloadType byte, err error)
-       Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
-}
-
-// Send sends v marshaled by cd.Marshal as single frame to ws.
-func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
-       if err != nil {
-               return err
-       }
-       data, payloadType, err := cd.Marshal(v)
-       if err != nil {
-               return err
-       }
-       ws.wio.Lock()
-       defer ws.wio.Unlock()
-       w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
-       _, err = w.Write(data)
-       w.Close()
-       return err
-}
-
-// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
-func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
-       ws.rio.Lock()
-       defer ws.rio.Unlock()
-       if ws.frameReader != nil {
-               _, err = io.Copy(ioutil.Discard, ws.frameReader)
-               if err != nil {
-                       return err
-               }
-               ws.frameReader = nil
-       }
-again:
-       frame, err := ws.frameReaderFactory.NewFrameReader()
-       if err != nil {
-               return err
-       }
-       frame, err = ws.frameHandler.HandleFrame(frame)
-       if err != nil {
-               return err
-       }
-       if frame == nil {
-               goto again
-       }
-       payloadType := frame.PayloadType()
-       data, err := ioutil.ReadAll(frame)
-       if err != nil {
-               return err
-       }
-       return cd.Unmarshal(data, payloadType, v)
-}
-
-func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
-       switch data := v.(type) {
-       case string:
-               return []byte(data), TextFrame, nil
-       case []byte:
-               return data, BinaryFrame, nil
-       }
-       return nil, UnknownFrame, ErrNotSupported
-}
-
-func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
-       switch data := v.(type) {
-       case *string:
-               *data = string(msg)
-               return nil
-       case *[]byte:
-               *data = msg
-               return nil
-       }
-       return ErrNotSupported
-}
-
-/*
-Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
-To send/receive text frame, use string type.
-To send/receive binary frame, use []byte type.
-
-Trivial usage:
-
-       import "websocket"
-
-       // receive text frame
-       var message string
-       websocket.Message.Receive(ws, &message)
-
-       // send text frame
-       message = "hello"
-       websocket.Message.Send(ws, message)
-
-       // receive binary frame
-       var data []byte
-       websocket.Message.Receive(ws, &data)
-
-       // send binary frame
-       data = []byte{0, 1, 2}
-       websocket.Message.Send(ws, data)
-
-*/
-var Message = Codec{marshal, unmarshal}
-
-func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
-       msg, err = json.Marshal(v)
-       return msg, TextFrame, err
-}
-
-func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
-       return json.Unmarshal(msg, v)
-}
-
-/*
-JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
-
-Trival usage:
-
-       import "websocket"
-
-       type T struct {
-               Msg string
-               Count int
-       }
-
-       // receive JSON type T
-       var data T
-       websocket.JSON.Receive(ws, &data)
-
-       // send JSON type T
-       websocket.JSON.Send(ws, data)
-*/
-var JSON = Codec{jsonMarshal, jsonUnmarshal}
diff --git a/libgo/go/websocket/websocket_test.go b/libgo/go/websocket/websocket_test.go
deleted file mode 100644 (file)
index f41c355..0000000
+++ /dev/null
@@ -1,274 +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 websocket
-
-import (
-       "bytes"
-       "fmt"
-       "io"
-       "log"
-       "net"
-       "net/http"
-       "net/http/httptest"
-       "net/url"
-       "strings"
-       "sync"
-       "testing"
-)
-
-var serverAddr string
-var once sync.Once
-
-func echoServer(ws *Conn) { io.Copy(ws, ws) }
-
-type Count struct {
-       S string
-       N int
-}
-
-func countServer(ws *Conn) {
-       for {
-               var count Count
-               err := JSON.Receive(ws, &count)
-               if err != nil {
-                       return
-               }
-               count.N++
-               count.S = strings.Repeat(count.S, count.N)
-               err = JSON.Send(ws, count)
-               if err != nil {
-                       return
-               }
-       }
-}
-
-func startServer() {
-       http.Handle("/echo", Handler(echoServer))
-       http.Handle("/count", Handler(countServer))
-       server := httptest.NewServer(nil)
-       serverAddr = server.Listener.Addr().String()
-       log.Print("Test WebSocket server listening on ", serverAddr)
-}
-
-func newConfig(t *testing.T, path string) *Config {
-       config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
-       return config
-}
-
-func TestEcho(t *testing.T) {
-       once.Do(startServer)
-
-       // websocket.Dial()
-       client, err := net.Dial("tcp", serverAddr)
-       if err != nil {
-               t.Fatal("dialing", err)
-       }
-       conn, err := NewClient(newConfig(t, "/echo"), client)
-       if err != nil {
-               t.Errorf("WebSocket handshake error: %v", err)
-               return
-       }
-
-       msg := []byte("hello, world\n")
-       if _, err := conn.Write(msg); err != nil {
-               t.Errorf("Write: %v", err)
-       }
-       var actual_msg = make([]byte, 512)
-       n, err := conn.Read(actual_msg)
-       if err != nil {
-               t.Errorf("Read: %v", err)
-       }
-       actual_msg = actual_msg[0:n]
-       if !bytes.Equal(msg, actual_msg) {
-               t.Errorf("Echo: expected %q got %q", msg, actual_msg)
-       }
-       conn.Close()
-}
-
-func TestAddr(t *testing.T) {
-       once.Do(startServer)
-
-       // websocket.Dial()
-       client, err := net.Dial("tcp", serverAddr)
-       if err != nil {
-               t.Fatal("dialing", err)
-       }
-       conn, err := NewClient(newConfig(t, "/echo"), client)
-       if err != nil {
-               t.Errorf("WebSocket handshake error: %v", err)
-               return
-       }
-
-       ra := conn.RemoteAddr().String()
-       if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
-               t.Errorf("Bad remote addr: %v", ra)
-       }
-       la := conn.LocalAddr().String()
-       if !strings.HasPrefix(la, "http://") {
-               t.Errorf("Bad local addr: %v", la)
-       }
-       conn.Close()
-}
-
-func TestCount(t *testing.T) {
-       once.Do(startServer)
-
-       // websocket.Dial()
-       client, err := net.Dial("tcp", serverAddr)
-       if err != nil {
-               t.Fatal("dialing", err)
-       }
-       conn, err := NewClient(newConfig(t, "/count"), client)
-       if err != nil {
-               t.Errorf("WebSocket handshake error: %v", err)
-               return
-       }
-
-       var count Count
-       count.S = "hello"
-       if err := JSON.Send(conn, count); err != nil {
-               t.Errorf("Write: %v", err)
-       }
-       if err := JSON.Receive(conn, &count); err != nil {
-               t.Errorf("Read: %v", err)
-       }
-       if count.N != 1 {
-               t.Errorf("count: expected %d got %d", 1, count.N)
-       }
-       if count.S != "hello" {
-               t.Errorf("count: expected %q got %q", "hello", count.S)
-       }
-       if err := JSON.Send(conn, count); err != nil {
-               t.Errorf("Write: %v", err)
-       }
-       if err := JSON.Receive(conn, &count); err != nil {
-               t.Errorf("Read: %v", err)
-       }
-       if count.N != 2 {
-               t.Errorf("count: expected %d got %d", 2, count.N)
-       }
-       if count.S != "hellohello" {
-               t.Errorf("count: expected %q got %q", "hellohello", count.S)
-       }
-       conn.Close()
-}
-
-func TestWithQuery(t *testing.T) {
-       once.Do(startServer)
-
-       client, err := net.Dial("tcp", serverAddr)
-       if err != nil {
-               t.Fatal("dialing", err)
-       }
-
-       config := newConfig(t, "/echo")
-       config.Location, err = url.ParseRequest(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
-       if err != nil {
-               t.Fatal("location url", err)
-       }
-
-       ws, err := NewClient(config, client)
-       if err != nil {
-               t.Errorf("WebSocket handshake: %v", err)
-               return
-       }
-       ws.Close()
-}
-
-func TestWithProtocol(t *testing.T) {
-       once.Do(startServer)
-
-       client, err := net.Dial("tcp", serverAddr)
-       if err != nil {
-               t.Fatal("dialing", err)
-       }
-
-       config := newConfig(t, "/echo")
-       config.Protocol = append(config.Protocol, "test")
-
-       ws, err := NewClient(config, client)
-       if err != nil {
-               t.Errorf("WebSocket handshake: %v", err)
-               return
-       }
-       ws.Close()
-}
-
-func TestHTTP(t *testing.T) {
-       once.Do(startServer)
-
-       // If the client did not send a handshake that matches the protocol
-       // specification, the server MUST return an HTTP respose with an
-       // appropriate error code (such as 400 Bad Request)
-       resp, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
-       if err != nil {
-               t.Errorf("Get: error %#v", err)
-               return
-       }
-       if resp == nil {
-               t.Error("Get: resp is null")
-               return
-       }
-       if resp.StatusCode != http.StatusBadRequest {
-               t.Errorf("Get: expected %q got %q", http.StatusBadRequest, resp.StatusCode)
-       }
-}
-
-func TestTrailingSpaces(t *testing.T) {
-       // http://code.google.com/p/go/issues/detail?id=955
-       // The last runs of this create keys with trailing spaces that should not be
-       // generated by the client.
-       once.Do(startServer)
-       config := newConfig(t, "/echo")
-       for i := 0; i < 30; i++ {
-               // body
-               ws, err := DialConfig(config)
-               if err != nil {
-                       t.Errorf("Dial #%d failed: %v", i, err)
-                       break
-               }
-               ws.Close()
-       }
-}
-
-func TestSmallBuffer(t *testing.T) {
-       // http://code.google.com/p/go/issues/detail?id=1145
-       // Read should be able to handle reading a fragment of a frame.
-       once.Do(startServer)
-
-       // websocket.Dial()
-       client, err := net.Dial("tcp", serverAddr)
-       if err != nil {
-               t.Fatal("dialing", err)
-       }
-       conn, err := NewClient(newConfig(t, "/echo"), client)
-       if err != nil {
-               t.Errorf("WebSocket handshake error: %v", err)
-               return
-       }
-
-       msg := []byte("hello, world\n")
-       if _, err := conn.Write(msg); err != nil {
-               t.Errorf("Write: %v", err)
-       }
-       var small_msg = make([]byte, 8)
-       n, err := conn.Read(small_msg)
-       if err != nil {
-               t.Errorf("Read: %v", err)
-       }
-       if !bytes.Equal(msg[:len(small_msg)], small_msg) {
-               t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
-       }
-       var second_msg = make([]byte, len(msg))
-       n, err = conn.Read(second_msg)
-       if err != nil {
-               t.Errorf("Read: %v", err)
-       }
-       second_msg = second_msg[0:n]
-       if !bytes.Equal(msg[len(small_msg):], second_msg) {
-               t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
-       }
-       conn.Close()
-}