OSDN Git Service

Update to current version of Go library.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 20 May 2011 00:18:15 +0000 (00:18 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 20 May 2011 00:18:15 +0000 (00:18 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@173931 138bc75d-0d04-0410-961f-82ee72b054a4

363 files changed:
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h
gcc/testsuite/go.test/test/convert.go
gcc/testsuite/go.test/test/fixedbugs/bug177.go
gcc/testsuite/go.test/test/fixedbugs/bug248.dir/bug2.go
gcc/testsuite/go.test/test/interface/fake.go
gcc/testsuite/go.test/test/ken/cplx3.go
libgo/MERGE
libgo/Makefile.am
libgo/Makefile.in
libgo/go/archive/tar/common.go
libgo/go/archive/tar/reader.go
libgo/go/archive/zip/reader.go
libgo/go/archive/zip/reader_test.go
libgo/go/asn1/asn1.go
libgo/go/asn1/asn1_test.go
libgo/go/asn1/common.go
libgo/go/asn1/marshal.go
libgo/go/asn1/marshal_test.go
libgo/go/big/int.go
libgo/go/big/nat.go
libgo/go/bufio/bufio.go
libgo/go/bufio/bufio_test.go
libgo/go/bytes/bytes.go
libgo/go/cmath/abs.go
libgo/go/compress/flate/deflate.go
libgo/go/compress/flate/deflate_test.go
libgo/go/compress/flate/inflate.go
libgo/go/compress/gzip/gunzip.go
libgo/go/compress/lzw/reader.go
libgo/go/compress/lzw/reader_test.go
libgo/go/compress/lzw/writer_test.go
libgo/go/compress/zlib/reader.go
libgo/go/compress/zlib/reader_test.go
libgo/go/compress/zlib/writer.go
libgo/go/compress/zlib/writer_test.go
libgo/go/container/heap/heap.go
libgo/go/container/heap/heap_test.go
libgo/go/container/list/list.go
libgo/go/container/ring/ring.go
libgo/go/container/vector/defs.go
libgo/go/crypto/aes/const.go
libgo/go/crypto/blowfish/cipher.go
libgo/go/crypto/cast5/cast5.go
libgo/go/crypto/cipher/cipher.go
libgo/go/crypto/crypto.go
libgo/go/crypto/elliptic/elliptic.go
libgo/go/crypto/hmac/hmac.go
libgo/go/crypto/md4/md4.go
libgo/go/crypto/md5/md5.go
libgo/go/crypto/ocsp/ocsp.go
libgo/go/crypto/openpgp/armor/armor.go
libgo/go/crypto/openpgp/armor/encode.go
libgo/go/crypto/openpgp/error/error.go
libgo/go/crypto/openpgp/keys.go
libgo/go/crypto/openpgp/packet/packet.go
libgo/go/crypto/openpgp/packet/private_key.go
libgo/go/crypto/openpgp/packet/public_key.go
libgo/go/crypto/openpgp/read.go
libgo/go/crypto/openpgp/read_test.go
libgo/go/crypto/openpgp/s2k/s2k.go
libgo/go/crypto/rc4/rc4.go
libgo/go/crypto/ripemd160/ripemd160.go
libgo/go/crypto/rsa/pkcs1v15.go
libgo/go/crypto/rsa/pkcs1v15_test.go
libgo/go/crypto/rsa/rsa.go
libgo/go/crypto/rsa/rsa_test.go
libgo/go/crypto/sha1/sha1.go
libgo/go/crypto/sha256/sha256.go
libgo/go/crypto/sha512/sha512.go
libgo/go/crypto/subtle/constant_time.go
libgo/go/crypto/tls/ca_set.go [deleted file]
libgo/go/crypto/tls/common.go
libgo/go/crypto/tls/conn.go
libgo/go/crypto/tls/handshake_client.go
libgo/go/crypto/tls/handshake_messages.go
libgo/go/crypto/tls/handshake_messages_test.go
libgo/go/crypto/tls/handshake_server.go
libgo/go/crypto/tls/handshake_server_test.go
libgo/go/crypto/tls/tls.go
libgo/go/crypto/twofish/twofish.go
libgo/go/crypto/x509/cert_pool.go [new file with mode: 0644]
libgo/go/crypto/x509/verify.go [new file with mode: 0644]
libgo/go/crypto/x509/verify_test.go [new file with mode: 0644]
libgo/go/crypto/x509/x509.go
libgo/go/crypto/x509/x509_test.go
libgo/go/crypto/xtea/cipher.go
libgo/go/debug/dwarf/open.go
libgo/go/debug/elf/elf.go
libgo/go/debug/elf/file.go
libgo/go/ebnf/ebnf.go
libgo/go/encoding/binary/binary.go
libgo/go/encoding/binary/binary_test.go
libgo/go/encoding/hex/hex.go
libgo/go/encoding/line/line.go
libgo/go/encoding/pem/pem.go
libgo/go/exec/exec.go
libgo/go/exec/exec_test.go
libgo/go/exp/datafmt/datafmt.go
libgo/go/exp/draw/draw.go
libgo/go/exp/draw/draw_test.go
libgo/go/exp/draw/x11/conn.go
libgo/go/exp/eval/bridge.go
libgo/go/exp/eval/type.go
libgo/go/exp/eval/world.go
libgo/go/exp/ogle/cmd.go
libgo/go/exp/ogle/process.go
libgo/go/exp/ogle/rruntime.go
libgo/go/exp/wingui/zwinapi.go
libgo/go/expvar/expvar.go
libgo/go/expvar/expvar_test.go
libgo/go/flag/flag.go
libgo/go/fmt/doc.go
libgo/go/fmt/fmt_test.go
libgo/go/fmt/print.go
libgo/go/fmt/scan.go
libgo/go/fmt/scan_test.go
libgo/go/go/ast/ast.go
libgo/go/go/ast/print.go
libgo/go/go/ast/print_test.go [new file with mode: 0644]
libgo/go/go/doc/doc.go
libgo/go/go/parser/parser.go
libgo/go/go/parser/parser_test.go
libgo/go/go/printer/nodes.go
libgo/go/go/printer/performance_test.go [new file with mode: 0644]
libgo/go/go/printer/printer.go
libgo/go/go/printer/testdata/declarations.golden
libgo/go/go/printer/testdata/declarations.input
libgo/go/go/printer/testdata/expressions.golden
libgo/go/go/printer/testdata/expressions.input
libgo/go/go/printer/testdata/expressions.raw
libgo/go/go/printer/testdata/parser.go [new file with mode: 0644]
libgo/go/go/scanner/scanner.go
libgo/go/go/token/position.go
libgo/go/go/token/token.go
libgo/go/go/typechecker/typechecker.go
libgo/go/go/types/const.go [new file with mode: 0644]
libgo/go/go/types/exportdata.go [new file with mode: 0644]
libgo/go/go/types/gcimporter.go [new file with mode: 0644]
libgo/go/go/types/gcimporter_test.go [new file with mode: 0644]
libgo/go/go/types/testdata/exports.go [new file with mode: 0644]
libgo/go/go/types/types.go [new file with mode: 0644]
libgo/go/go/types/universe.go [new file with mode: 0644]
libgo/go/gob/codec_test.go
libgo/go/gob/decode.go
libgo/go/gob/decoder.go
libgo/go/gob/doc.go
libgo/go/gob/encode.go
libgo/go/gob/encoder.go
libgo/go/gob/encoder_test.go
libgo/go/gob/error.go
libgo/go/gob/gobencdec_test.go
libgo/go/gob/type.go
libgo/go/gob/type_test.go
libgo/go/hash/adler32/adler32.go
libgo/go/hash/adler32/adler32_test.go
libgo/go/hash/crc32/crc32.go
libgo/go/hash/crc64/crc64.go
libgo/go/hash/fnv/fnv.go
libgo/go/hash/fnv/fnv_test.go
libgo/go/hash/hash.go
libgo/go/html/doc.go
libgo/go/html/parse_test.go
libgo/go/http/cgi/child.go
libgo/go/http/cgi/child_test.go
libgo/go/http/cgi/host.go
libgo/go/http/cgi/host_test.go
libgo/go/http/client.go
libgo/go/http/client_test.go
libgo/go/http/cookie.go
libgo/go/http/cookie_test.go
libgo/go/http/dump.go
libgo/go/http/export_test.go
libgo/go/http/fcgi/child.go [new file with mode: 0644]
libgo/go/http/fcgi/fcgi.go [new file with mode: 0644]
libgo/go/http/fcgi/fcgi_test.go [new file with mode: 0644]
libgo/go/http/fs.go
libgo/go/http/fs_test.go
libgo/go/http/header.go
libgo/go/http/header_test.go [new file with mode: 0644]
libgo/go/http/httptest/recorder.go
libgo/go/http/persist.go
libgo/go/http/pprof/pprof.go
libgo/go/http/proxy_test.go
libgo/go/http/request.go
libgo/go/http/request_test.go
libgo/go/http/requestwrite_test.go
libgo/go/http/response.go
libgo/go/http/response_test.go
libgo/go/http/reverseproxy.go [new file with mode: 0644]
libgo/go/http/reverseproxy_test.go [new file with mode: 0644]
libgo/go/http/serve_test.go
libgo/go/http/server.go
libgo/go/http/spdy/protocol.go [new file with mode: 0644]
libgo/go/http/spdy/protocol_test.go [new file with mode: 0644]
libgo/go/http/transfer.go
libgo/go/http/transport.go
libgo/go/http/transport_test.go
libgo/go/http/url.go
libgo/go/image/decode_test.go
libgo/go/image/format.go
libgo/go/image/gif/reader.go [new file with mode: 0644]
libgo/go/image/image.go
libgo/go/image/jpeg/fdct.go [new file with mode: 0644]
libgo/go/image/jpeg/idct.go
libgo/go/image/jpeg/reader.go
libgo/go/image/jpeg/writer.go [new file with mode: 0644]
libgo/go/image/jpeg/writer_test.go [new file with mode: 0644]
libgo/go/image/png/reader.go
libgo/go/image/png/reader_test.go
libgo/go/image/png/testdata/pngsuite/README
libgo/go/image/png/writer.go
libgo/go/image/png/writer_test.go
libgo/go/image/testdata/video-001.bmp [new file with mode: 0644]
libgo/go/image/testdata/video-001.gif [new file with mode: 0644]
libgo/go/image/testdata/video-001.jpeg [new file with mode: 0644]
libgo/go/image/testdata/video-001.png [new file with mode: 0644]
libgo/go/image/testdata/video-001.tiff [new file with mode: 0644]
libgo/go/image/tiff/buffer.go [new file with mode: 0644]
libgo/go/image/tiff/buffer_test.go [new file with mode: 0644]
libgo/go/image/tiff/consts.go [new file with mode: 0644]
libgo/go/image/tiff/reader.go [new file with mode: 0644]
libgo/go/image/ycbcr/ycbcr.go [new file with mode: 0644]
libgo/go/image/ycbcr/ycbcr_test.go [new file with mode: 0644]
libgo/go/index/suffixarray/suffixarray.go
libgo/go/io/io.go
libgo/go/io/io_test.go
libgo/go/io/ioutil/ioutil.go
libgo/go/io/multi.go
libgo/go/json/decode.go
libgo/go/json/decode_test.go
libgo/go/json/encode.go
libgo/go/json/scanner.go
libgo/go/json/stream.go
libgo/go/log/log.go
libgo/go/math/const.go
libgo/go/mime/mediatype.go
libgo/go/mime/mediatype_test.go
libgo/go/mime/multipart/formdata.go [new file with mode: 0644]
libgo/go/mime/multipart/formdata_test.go [new file with mode: 0644]
libgo/go/mime/multipart/multipart.go
libgo/go/mime/multipart/multipart_test.go
libgo/go/mime/type.go
libgo/go/net/cgo_bsd.go [new file with mode: 0644]
libgo/go/net/cgo_linux.go [new file with mode: 0644]
libgo/go/net/cgo_stub.go
libgo/go/net/cgo_unix.go [new file with mode: 0644]
libgo/go/net/dial.go
libgo/go/net/dialgoogle_test.go
libgo/go/net/dnsclient.go
libgo/go/net/dnsmsg.go
libgo/go/net/dnsmsg_test.go [new file with mode: 0644]
libgo/go/net/hosts_test.go
libgo/go/net/ip.go
libgo/go/net/ip_test.go
libgo/go/net/ipraw_test.go
libgo/go/net/iprawsock.go
libgo/go/net/ipsock.go
libgo/go/net/lookup.go
libgo/go/net/multicast_test.go
libgo/go/net/net.go
libgo/go/net/resolv_windows.go
libgo/go/net/server_test.go
libgo/go/net/sock.go
libgo/go/net/sock_bsd.go [new file with mode: 0644]
libgo/go/net/sock_linux.go [new file with mode: 0644]
libgo/go/net/sock_windows.go [new file with mode: 0644]
libgo/go/net/srv_test.go
libgo/go/net/tcpsock.go
libgo/go/net/textproto/textproto.go
libgo/go/net/udpsock.go
libgo/go/netchan/common.go
libgo/go/netchan/export.go
libgo/go/netchan/import.go
libgo/go/os/dir_plan9.go
libgo/go/os/env.go
libgo/go/os/env_unix.go
libgo/go/os/error_plan9.go
libgo/go/os/file.go
libgo/go/os/file_plan9.go
libgo/go/os/file_posix.go
libgo/go/os/file_unix.go
libgo/go/os/inotify/inotify_linux.go
libgo/go/os/inotify/inotify_linux_test.go
libgo/go/os/os_test.go
libgo/go/os/user/lookup_stubs.go [new file with mode: 0644]
libgo/go/os/user/lookup_unix.go [new file with mode: 0644]
libgo/go/os/user/user.go [new file with mode: 0644]
libgo/go/os/user/user_test.go [new file with mode: 0644]
libgo/go/path/filepath/path.go
libgo/go/path/path.go
libgo/go/reflect/all_test.go
libgo/go/reflect/deepequal.go
libgo/go/reflect/set_test.go [new file with mode: 0644]
libgo/go/reflect/tostring_test.go
libgo/go/reflect/type.go
libgo/go/reflect/value.go
libgo/go/rpc/server.go
libgo/go/rpc/server_test.go
libgo/go/runtime/debug/stack.go
libgo/go/runtime/extern.go
libgo/go/runtime/proc_test.go [new file with mode: 0644]
libgo/go/runtime/type.go
libgo/go/scanner/scanner.go
libgo/go/sort/sort.go
libgo/go/strconv/atof.go
libgo/go/strings/strings.go
libgo/go/sync/mutex.go
libgo/go/syslog/syslog.go
libgo/go/syslog/syslog_test.go
libgo/go/tabwriter/tabwriter.go
libgo/go/template/template.go
libgo/go/testing/iotest/reader.go
libgo/go/testing/quick/quick.go
libgo/go/testing/quick/quick_test.go
libgo/go/testing/script/script.go
libgo/go/testing/testing.go
libgo/go/time/time.go
libgo/go/try/try.go
libgo/go/unicode/letter.go
libgo/go/utf8/utf8.go
libgo/go/websocket/server.go
libgo/go/websocket/websocket.go
libgo/go/websocket/websocket_test.go
libgo/go/xml/read.go
libgo/go/xml/read_test.go
libgo/go/xml/xml.go
libgo/go/xml/xml_test.go
libgo/mksysinfo.sh
libgo/runtime/chan.goc
libgo/runtime/channel.h
libgo/runtime/go-eface-compare.c
libgo/runtime/go-eface-val-compare.c
libgo/runtime/go-interface-eface-compare.c
libgo/runtime/go-new-channel.c
libgo/runtime/go-rec-big.c
libgo/runtime/go-rec-nb-big.c
libgo/runtime/go-rec-nb-small.c
libgo/runtime/go-rec-small.c
libgo/runtime/go-reflect-call.c
libgo/runtime/go-reflect-chan.c
libgo/runtime/go-reflect-map.c
libgo/runtime/go-reflect.c
libgo/runtime/go-send-big.c
libgo/runtime/go-send-nb-big.c
libgo/runtime/go-send-nb-small.c
libgo/runtime/go-send-small.c
libgo/runtime/go-setenv.c [new file with mode: 0644]
libgo/runtime/go-signal.c
libgo/runtime/go-type-eface.c
libgo/runtime/go-type.h
libgo/runtime/go-unreflect.c
libgo/runtime/go-unsafe-new.c
libgo/runtime/go-unsafe-newarray.c
libgo/runtime/iface.goc
libgo/runtime/malloc.goc
libgo/runtime/mcache.c
libgo/runtime/mgc0.c
libgo/runtime/mheap.c
libgo/runtime/reflect.goc
libgo/runtime/runtime.h
libgo/syscalls/stringbyte.go
libgo/syscalls/syscall_unix.go

index e33b349..bf19216 100644 (file)
@@ -1432,7 +1432,7 @@ Type::methods_constructor(Gogo* gogo, Type* methods_type,
        p != smethods.end();
        ++p)
     vals->push_back(this->method_constructor(gogo, method_type, p->first,
-                                            p->second));
+                                            p->second, only_value_methods));
 
   return Expression::make_slice_composite_literal(methods_type, vals, bloc);
 }
@@ -1444,7 +1444,8 @@ Type::methods_constructor(Gogo* gogo, Type* methods_type,
 Expression*
 Type::method_constructor(Gogo*, Type* method_type,
                         const std::string& method_name,
-                        const Method* m) const
+                        const Method* m,
+                        bool only_value_methods) const
 {
   source_location bloc = BUILTINS_LOCATION;
 
@@ -1487,6 +1488,25 @@ Type::method_constructor(Gogo*, Type* method_type,
 
   ++p;
   go_assert(p->field_name() == "typ");
+  if (!only_value_methods && m->is_value_method())
+    {
+      // This is a value method on a pointer type.  Change the type of
+      // the method to use a pointer receiver.  The implementation
+      // always uses a pointer receiver anyhow.
+      Type* rtype = mtype->receiver()->type();
+      Type* prtype = Type::make_pointer_type(rtype);
+      Typed_identifier* receiver =
+       new Typed_identifier(mtype->receiver()->name(), prtype,
+                            mtype->receiver()->location());
+      mtype = Type::make_function_type(receiver,
+                                      (mtype->parameters() == NULL
+                                       ? NULL
+                                       : mtype->parameters()->copy()),
+                                      (mtype->results() == NULL
+                                       ? NULL
+                                       : mtype->results()->copy()),
+                                      mtype->location());
+    }
   vals->push_back(Expression::make_type_descriptor(mtype, bloc));
 
   ++p;
@@ -2779,14 +2799,7 @@ Function_type::type_descriptor_params(Type* params_type,
                + (receiver != NULL ? 1 : 0));
 
   if (receiver != NULL)
-    {
-      Type* rtype = receiver->type();
-      // The receiver is always passed as a pointer.  FIXME: Is this
-      // right?  Should that fact affect the type descriptor?
-      if (rtype->points_to() == NULL)
-       rtype = Type::make_pointer_type(rtype);
-      vals->push_back(Expression::make_type_descriptor(rtype, bloc));
-    }
+    vals->push_back(Expression::make_type_descriptor(receiver->type(), bloc));
 
   if (params != NULL)
     {
@@ -4822,9 +4835,10 @@ Array_type::make_array_type_descriptor_type()
       Type* uintptr_type = Type::lookup_integer_type("uintptr");
 
       Struct_type* sf =
-       Type::make_builtin_struct_type(3,
+       Type::make_builtin_struct_type(4,
                                       "", tdt,
                                       "elem", ptdt,
+                                      "slice", ptdt,
                                       "len", uintptr_type);
 
       ret = Type::make_builtin_named_type("ArrayType", sf);
@@ -4891,6 +4905,11 @@ Array_type::array_type_descriptor(Gogo* gogo, Named_type* name)
   vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
 
   ++p;
+  go_assert(p->field_name() == "slice");
+  Type* slice_type = Type::make_array_type(this->element_type_, NULL);
+  vals->push_back(Expression::make_type_descriptor(slice_type, bloc));
+
+  ++p;
   go_assert(p->field_name() == "len");
   vals->push_back(Expression::make_cast(p->type(), this->length_, bloc));
 
@@ -5375,8 +5394,9 @@ Channel_type::do_make_expression_tree(Translate_context* context,
   Gogo* gogo = context->gogo();
   tree channel_type = type_to_tree(this->get_backend(gogo));
 
-  tree element_tree = type_to_tree(this->element_type_->get_backend(gogo));
-  tree element_size_tree = size_in_bytes(element_tree);
+  Type* ptdt = Type::make_type_descriptor_ptr_type();
+  tree element_type_descriptor =
+    this->element_type_->type_descriptor_pointer(gogo);
 
   tree bad_index = NULL_TREE;
 
@@ -5402,8 +5422,8 @@ Channel_type::do_make_expression_tree(Translate_context* context,
                                "__go_new_channel",
                                2,
                                channel_type,
-                               sizetype,
-                               element_size_tree,
+                               type_to_tree(ptdt->get_backend(gogo)),
+                               element_type_descriptor,
                                sizetype,
                                expr_tree);
   if (ret == error_mark_node)
@@ -6242,7 +6262,16 @@ Interface_type::do_reflection(Gogo* gogo, std::string* ret) const
          if (p != this->methods_->begin())
            ret->append(";");
          ret->push_back(' ');
-         ret->append(Gogo::unpack_hidden_name(p->name()));
+         if (!Gogo::is_hidden_name(p->name()))
+           ret->append(p->name());
+         else
+           {
+             // This matches what the gc compiler does.
+             std::string prefix = Gogo::hidden_name_prefix(p->name());
+             ret->append(prefix.substr(prefix.find('.') + 1));
+             ret->push_back('.');
+             ret->append(Gogo::unpack_hidden_name(p->name()));
+           }
          std::string sub = p->type()->reflection(gogo);
          go_assert(sub.compare(0, 4, "func") == 0);
          sub = sub.substr(4);
index 913266b..3ada1b1 100644 (file)
@@ -1044,7 +1044,7 @@ class Type
   // Build a composite literal for one method.
   Expression*
   method_constructor(Gogo*, Type* method_type, const std::string& name,
-                    const Method*) const;
+                    const Method*, bool only_value_methods) const;
 
   static tree
   build_receive_return_type(tree type);
index e7361aa..0a75663 100644 (file)
@@ -8,7 +8,7 @@ package main
 
 import "reflect"
 
-func typeof(x interface{}) string { return reflect.Typeof(x).String() }
+func typeof(x interface{}) string { return reflect.TypeOf(x).String() }
 
 func f() int { return 0 }
 
index 84ff59d..a120ad0 100644 (file)
@@ -5,23 +5,26 @@
 // license that can be found in the LICENSE file.
 
 package main
+
 import "reflect"
-type S1 struct { i int }
-type S2 struct { S1 }
+
+type S1 struct{ i int }
+type S2 struct{ S1 }
+
 func main() {
-       typ := reflect.Typeof(S2{}).(*reflect.StructType);
-       f := typ.Field(0);
+       typ := reflect.TypeOf(S2{})
+       f := typ.Field(0)
        if f.Name != "S1" || f.Anonymous != true {
-               println("BUG: ", f.Name, f.Anonymous);
-               return;
+               println("BUG: ", f.Name, f.Anonymous)
+               return
        }
-       f, ok := typ.FieldByName("S1");
+       f, ok := typ.FieldByName("S1")
        if !ok {
-               println("BUG: missing S1");
-               return;
+               println("BUG: missing S1")
+               return
        }
        if !f.Anonymous {
-               println("BUG: S1 is not anonymous");
-               return;
+               println("BUG: S1 is not anonymous")
+               return
        }
 }
index 4ea187a..b6c816a 100644 (file)
@@ -38,11 +38,11 @@ func main() {
        // meaning that reflect data for v0, v1 didn't get confused.
 
        // path is full (rooted) path name.  check suffix for gc, prefix for gccgo
-       if s := reflect.Typeof(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
+       if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
                println("bad v0 path", len(s), s)
                panic("fail")
        }
-       if s := reflect.Typeof(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
+       if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
                println("bad v1 path", s)
                panic("fail")
        }
index 5cf3be0..bdc5b90 100644 (file)
@@ -46,34 +46,34 @@ func main() {
        x.t = add("abc", "def")
        x.u = 1
        x.v = 2
-       x.w = 1<<28
-       x.x = 2<<28
+       x.w = 1 << 28
+       x.x = 2 << 28
        x.y = 0x12345678
        x.z = x.y
 
        // check mem and string
-       v := reflect.NewValue(x)
-       i := v.(*reflect.StructValue).Field(0)
-       j := v.(*reflect.StructValue).Field(1)
+       v := reflect.ValueOf(x)
+       i := v.Field(0)
+       j := v.Field(1)
        assert(i.Interface() == j.Interface())
 
-       s := v.(*reflect.StructValue).Field(2)
-       t := v.(*reflect.StructValue).Field(3)
+       s := v.Field(2)
+       t := v.Field(3)
        assert(s.Interface() == t.Interface())
 
        // make sure different values are different.
        // make sure whole word is being compared,
        // not just a single byte.
-       i = v.(*reflect.StructValue).Field(4)
-       j = v.(*reflect.StructValue).Field(5)
+       i = v.Field(4)
+       j = v.Field(5)
        assert(i.Interface() != j.Interface())
 
-       i = v.(*reflect.StructValue).Field(6)
-       j = v.(*reflect.StructValue).Field(7)
+       i = v.Field(6)
+       j = v.Field(7)
        assert(i.Interface() != j.Interface())
 
-       i = v.(*reflect.StructValue).Field(8)
-       j = v.(*reflect.StructValue).Field(9)
+       i = v.Field(8)
+       j = v.Field(9)
        assert(i.Interface() == j.Interface())
 }
 
index 83acc15..fa6ff1d 100644 (file)
@@ -25,9 +25,9 @@ func main() {
        println(c)
 
        var a interface{}
-       switch c := reflect.NewValue(a).(type) {
-       case *reflect.ComplexValue:
-               v := c.Get()
+       switch c := reflect.ValueOf(a); c.Kind() {
+       case reflect.Complex64, reflect.Complex128:
+               v := c.Complex()
                _, _ = complex128(v), true
        }
 }
index 237a0c2..9cee703 100644 (file)
@@ -1,4 +1,4 @@
-f618e5e0991d
+aea0ba6e5935
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
index 05f1c99..ae6848f 100644 (file)
@@ -248,7 +248,8 @@ toolexeclibgogo_DATA = \
        go/printer.gox \
        go/scanner.gox \
        go/token.gox \
-       go/typechecker.gox
+       go/typechecker.gox \
+       go/types.gox
 
 toolexeclibgohashdir = $(toolexeclibgodir)/hash
 
@@ -262,14 +263,19 @@ toolexeclibgohttpdir = $(toolexeclibgodir)/http
 
 toolexeclibgohttp_DATA = \
        http/cgi.gox \
+       http/fcgi.gox \
        http/httptest.gox \
-       http/pprof.gox
+       http/pprof.gox \
+       http/spdy.gox
 
 toolexeclibgoimagedir = $(toolexeclibgodir)/image
 
 toolexeclibgoimage_DATA = \
+       image/gif.gox \
        image/jpeg.gox \
-       image/png.gox
+       image/png.gox \
+       image/tiff.gox \
+       image/ycbcr.gox
 
 toolexeclibgoindexdir = $(toolexeclibgodir)/index
 
@@ -303,6 +309,7 @@ endif
 
 toolexeclibgoos_DATA = \
        $(os_inotify_gox) \
+       os/user.gox \
        os/signal.gox
 
 toolexeclibgopathdir = $(toolexeclibgodir)/path
@@ -404,6 +411,7 @@ runtime_files = \
        runtime/go-send-nb-big.c \
        runtime/go-send-nb-small.c \
        runtime/go-send-small.c \
+       runtime/go-setenv.c \
        runtime/go-signal.c \
        runtime/go-strcmp.c \
        runtime/go-string-to-byte-array.c \
@@ -560,6 +568,7 @@ go_http_files = \
        go/http/persist.go \
        go/http/request.go \
        go/http/response.go \
+       go/http/reverseproxy.go \
        go/http/server.go \
        go/http/status.go \
        go/http/transfer.go \
@@ -656,8 +665,17 @@ go_net_newpollserver_file = go/net/newpollserver.go
 endif # !LIBGO_IS_LINUX
 endif # !LIBGO_IS_RTEMS
 
+if LIBGO_IS_LINUX
+go_net_cgo_file = go/net/cgo_linux.go
+go_net_sock_file = go/net/sock_linux.go
+else
+go_net_cgo_file = go/net/cgo_bsd.go
+go_net_sock_file = go/net/sock_bsd.go
+endif
+
 go_net_files = \
-       go/net/cgo_stub.go \
+       go/net/cgo_unix.go \
+       $(go_net_cgo_file) \
        go/net/dial.go \
        go/net/dnsclient.go \
        go/net/dnsconfig.go \
@@ -676,6 +694,7 @@ go_net_files = \
        go/net/pipe.go \
        go/net/port.go \
        go/net/sock.go \
+       $(go_net_sock_file) \
        go/net/tcpsock.go \
        go/net/udpsock.go \
        go/net/unixsock.go
@@ -1002,7 +1021,6 @@ go_crypto_subtle_files = \
        go/crypto/subtle/constant_time.go
 go_crypto_tls_files = \
        go/crypto/tls/alert.go \
-       go/crypto/tls/ca_set.go \
        go/crypto/tls/cipher_suites.go \
        go/crypto/tls/common.go \
        go/crypto/tls/conn.go \
@@ -1015,6 +1033,8 @@ go_crypto_tls_files = \
 go_crypto_twofish_files = \
        go/crypto/twofish/twofish.go
 go_crypto_x509_files = \
+       go/crypto/x509/cert_pool.go \
+       go/crypto/x509/verify.go \
        go/crypto/x509/x509.go
 go_crypto_xtea_files = \
        go/crypto/xtea/block.go \
@@ -1130,6 +1150,12 @@ go_go_typechecker_files = \
        go/go/typechecker/type.go \
        go/go/typechecker/typechecker.go \
        go/go/typechecker/universe.go
+go_go_types_files = \
+       go/go/types/const.go \
+       go/go/types/exportdata.go \
+       go/go/types/gcimporter.go \
+       go/go/types/types.go \
+       go/go/types/universe.go
 
 go_hash_adler32_files = \
        go/hash/adler32/adler32.go
@@ -1143,21 +1169,39 @@ go_hash_fnv_files = \
 go_http_cgi_files = \
        go/http/cgi/child.go \
        go/http/cgi/host.go
+go_http_fcgi_files = \
+       go/http/fcgi/child.go \
+       go/http/fcgi/fcgi.go
 go_http_httptest_files = \
        go/http/httptest/recorder.go \
        go/http/httptest/server.go
 go_http_pprof_files = \
        go/http/pprof/pprof.go
+go_http_spdy_files = \
+       go/http/spdy/protocol.go
+
+go_image_gif_files = \
+       go/image/gif/reader.go
 
 go_image_jpeg_files = \
+       go/image/jpeg/fdct.go \
        go/image/jpeg/huffman.go \
        go/image/jpeg/idct.go \
-       go/image/jpeg/reader.go
+       go/image/jpeg/reader.go \
+       go/image/jpeg/writer.go
 
 go_image_png_files = \
        go/image/png/reader.go \
        go/image/png/writer.go
 
+go_image_tiff_files = \
+       go/image/tiff/buffer.go \
+       go/image/tiff/consts.go \
+       go/image/tiff/reader.go
+
+go_image_ycbcr_files = \
+       go/image/ycbcr/ycbcr.go
+
 go_index_suffixarray_files = \
        go/index/suffixarray/qsufsort.go \
        go/index/suffixarray/suffixarray.go
@@ -1167,6 +1211,7 @@ go_io_ioutil_files = \
        go/io/ioutil/tempfile.go
 
 go_mime_multipart_files = \
+       go/mime/multipart/formdata.go \
        go/mime/multipart/multipart.go
 
 go_net_dict_files = \
@@ -1182,6 +1227,10 @@ go_net_textproto_files = \
 go_os_inotify_files = \
        go/os/inotify/inotify_linux.go
 
+go_os_user_files = \
+       go/os/user/user.go \
+       go/os/user/lookup_unix.go
+
 go_os_signal_files = \
        go/os/signal/signal.go \
        unix.go
@@ -1485,21 +1534,28 @@ libgo_go_objs = \
        go/scanner.lo \
        go/token.lo \
        go/typechecker.lo \
+       go/types.lo \
        hash/adler32.lo \
        hash/crc32.lo \
        hash/crc64.lo \
        hash/fnv.lo \
        http/cgi.lo \
+       http/fcgi.lo \
        http/httptest.lo \
        http/pprof.lo \
+       http/spdy.lo \
+       image/gif.lo \
        image/jpeg.lo \
        image/png.lo \
+       image/tiff.lo \
+       image/ycbcr.lo \
        index/suffixarray.lo \
        io/ioutil.lo \
        mime/multipart.lo \
        net/dict.lo \
        net/textproto.lo \
        $(os_lib_inotify_lo) \
+       os/user.lo \
        os/signal.lo \
        path/filepath.lo \
        rpc/jsonrpc.lo \
@@ -1711,11 +1767,12 @@ html/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: html/check
 
-http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \
-               crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \
-               io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \
-               net.gox net/textproto.gox os.gox path.gox path/filepath.gox \
-               sort.gox strconv.gox strings.gox sync.gox time.gox utf8.gox
+http/http.lo: $(go_http_files) bufio.gox bytes.gox compress/gzip.gox \
+               container/vector.gox crypto/rand.gox crypto/tls.gox \
+               encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \
+               mime.gox mime/multipart.gox net.gox net/textproto.gox os.gox \
+               path.gox path/filepath.gox sort.gox strconv.gox strings.gox \
+               sync.gox time.gox utf8.gox
        $(BUILDPACKAGE)
 http/check: $(CHECK_DEPS)
        @$(CHECK)
@@ -1755,7 +1812,7 @@ math/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: math/check
 
-mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox os.gox strings.gox \
+mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox fmt.gox os.gox strings.gox \
                sync.gox unicode.gox
        $(BUILDPACKAGE)
 mime/check: $(CHECK_DEPS)
@@ -1763,8 +1820,8 @@ mime/check: $(CHECK_DEPS)
 .PHONY: mime/check
 
 net/net.lo: $(go_net_files) bytes.gox fmt.gox io.gox os.gox rand.gox \
-               reflect.gox strconv.gox strings.gox sync.gox syscall.gox \
-               time.gox
+               reflect.gox sort.gox strconv.gox strings.gox sync.gox \
+               syscall.gox time.gox
        $(BUILDPACKAGE)
 net/check: $(CHECK_DEPS)
        @$(CHECK_ON_REQUEST)
@@ -1945,8 +2002,8 @@ xml/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: xml/check
 
-archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox os.gox strconv.gox \
-               strings.gox
+archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox io/ioutil.gox os.gox \
+               strconv.gox strings.gox
        $(BUILDPACKAGE)
 archive/tar/check: $(CHECK_DEPS)
        @$(MKDIR_P) archive/tar
@@ -2148,8 +2205,7 @@ crypto/ripemd160/check: $(CHECK_DEPS)
 .PHONY: crypto/ripemd160/check
 
 crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
-               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
-               sync.gox
+               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
        $(BUILDPACKAGE)
 crypto/rsa/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/rsa
@@ -2184,13 +2240,13 @@ crypto/subtle/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/subtle/check
 
-crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
-               container/list.gox crypto.gox crypto/aes.gox crypto/cipher.gox \
-               crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
-               crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
-               crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
-               crypto/x509.gox encoding/pem.gox fmt.gox hash.gox io.gox \
-               io/ioutil.gox net.gox os.gox strings.gox sync.gox time.gox
+crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
+               crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
+               crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
+               crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
+               crypto/x509.gox encoding/pem.gox hash.gox io.gox \
+               io/ioutil.gox net.gox os.gox strconv.gox strings.gox sync.gox \
+               time.gox
        $(BUILDPACKAGE)
 crypto/tls/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/tls
@@ -2204,9 +2260,10 @@ crypto/twofish/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/twofish/check
 
-crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \
-               crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \
-               strings.gox time.gox
+crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox bytes.gox \
+               container/vector.gox crypto.gox crypto/rsa.gox \
+               crypto/sha1.gox encoding/pem.gox hash.gox os.gox strings.gox \
+               time.gox
        $(BUILDPACKAGE)
 crypto/x509/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/x509
@@ -2220,9 +2277,8 @@ crypto/xtea/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/xtea/check
 
-crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bytes.gox \
-               crypto/openpgp/error.gox encoding/base64.gox \
-               encoding/line.gox io.gox os.gox
+crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bufio.gox bytes.gox \
+               crypto/openpgp/error.gox encoding/base64.gox io.gox os.gox
        $(BUILDPACKAGE)
 crypto/openpgp/armor/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/openpgp/armor
@@ -2374,7 +2430,7 @@ exp/datafmt/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: exp/datafmt/check
 
-exp/draw.lo: $(go_exp_draw_files) image.gox os.gox
+exp/draw.lo: $(go_exp_draw_files) image.gox image/ycbcr.gox os.gox
        $(BUILDPACKAGE)
 exp/draw/check: $(CHECK_DEPS)
        @$(MKDIR_P) exp/draw
@@ -2448,6 +2504,15 @@ go/typechecker/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: go/typechecker/check
 
+go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
+               go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
+               scanner.gox strconv.gox strings.gox
+       $(BUILDPACKAGE)
+go/types/check: $(CHECK_DEPS)
+       @$(MKDIR_P) go/types
+       @$(CHECK)
+.PHONY: go/types/check
+
 hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
        $(BUILDPACKAGE)
 hash/adler32/check: $(CHECK_DEPS)
@@ -2476,15 +2541,25 @@ hash/fnv/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: hash/fnv/check
 
-http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox encoding/line.gox \
-               exec.gox fmt.gox http.gox io.gox io/ioutil.gox log.gox \
-               os.gox path/filepath.gox regexp.gox strconv.gox strings.gox
+http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox crypto/tls.gox \
+               exec.gox fmt.gox http.gox net.gox io.gox io/ioutil.gox \
+               log.gox os.gox path/filepath.gox regexp.gox strconv.gox \
+               strings.gox
        $(BUILDPACKAGE)
 http/cgi/check: $(CHECK_DEPS)
        @$(MKDIR_P) http/cgi
        @$(CHECK)
 .PHONY: http/cgi/check
 
+http/fcgi.lo: $(go_http_fcgi_files) bufio.gox bytes.gox encoding/binary.gox \
+               fmt.gox http.gox http/cgi.gox io.gox net.gox os.gox sync.gox \
+               time.gox
+       $(BUILDPACKAGE)
+http/fcgi/check: $(CHECK_DEPS)
+       @$(MKDIR_P) http/fcgi
+       @$(CHECK)
+.PHONY: http/fcgi/check
+
 http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
                crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
        $(BUILDPACKAGE)
@@ -2493,15 +2568,33 @@ http/httptest/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: http/httptest/check
 
-http/pprof.lo: $(go_http_pprof_files) bufio.gox fmt.gox http.gox os.gox \
-               runtime.gox runtime/pprof.gox strconv.gox strings.gox
+http/pprof.lo: $(go_http_pprof_files) bufio.gox bytes.gox fmt.gox http.gox \
+               os.gox runtime.gox runtime/pprof.gox strconv.gox strings.gox
        $(BUILDPACKAGE)
 http/pprof/check: $(CHECK_DEPS)
        @$(MKDIR_P) http/pprof
        @$(CHECK)
 .PHONY: http/pprof/check
 
-image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox io.gox os.gox
+http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
+               encoding/binary.gox http.gox io.gox os.gox strconv.gox \
+               strings.gox sync.gox
+       $(BUILDPACKAGE)
+http/spdy/check: $(CHECK_DEPS)
+       @$(MKDIR_P) http/spdy
+       @$(CHECK)
+.PHONY: http/spdy/check
+
+image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
+               image.gox io.gox os.gox
+       $(BUILDPACKAGE)
+image/gif/check: $(CHECK_DEPS)
+       @$(MKDIR_P) image/gif
+       @$(CHECK)
+.PHONY: image/gif/check
+
+image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
+               io.gox os.gox
        $(BUILDPACKAGE)
 image/jpeg/check: $(CHECK_DEPS)
        @$(MKDIR_P) image/jpeg
@@ -2516,6 +2609,21 @@ image/png/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: image/png/check
 
+image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
+               encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
+       $(BUILDPACKAGE)
+image/tiff/check: $(CHECK_DEPS)
+       @$(MKDIR_P) image/tiff
+       @$(CHECK)
+.PHONY: image/tiff/check
+
+image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
+       $(BUILDPACKAGE)
+image/ycbcr/check: $(CHECK_DEPS)
+       @$(MKDIR_P) image/ycbcr
+       @$(CHECK)
+.PHONY: image/ycbcr/check
+
 index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
                sort.gox
        $(BUILDPACKAGE)
@@ -2532,8 +2640,9 @@ io/ioutil/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: io/ioutil/check
 
-mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox io.gox \
-               mime.gox net/textproto.gox os.gox regexp.gox strings.gox
+mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox fmt.gox \
+               io.gox io/ioutil.gox mime.gox net/textproto.gox os.gox \
+               regexp.gox
        $(BUILDPACKAGE)
 mime/multipart/check: $(CHECK_DEPS)
        @$(MKDIR_P) mime/multipart
@@ -2560,6 +2669,14 @@ os/inotify/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: os/inotify/check
 
+os/user.lo: $(go_os_user_files) fmt.gox os.gox runtime.gox strconv.gox \
+               strings.gox syscall.gox
+       $(BUILDPACKAGE)
+os/user/check: $(CHECK_DEPS)
+       @$(MKDIR_P) os/user
+       @$(CHECK)
+.PHONY: os/user/check
+
 os/signal.lo: $(go_os_signal_files) runtime.gox strconv.gox
        $(BUILDPACKAGE)
 os/signal/check: $(CHECK_DEPS)
@@ -2886,6 +3003,8 @@ go/token.gox: go/token.lo
        $(BUILDGOX)
 go/typechecker.gox: go/typechecker.lo
        $(BUILDGOX)
+go/types.gox: go/types.lo
+       $(BUILDGOX)
 
 hash/adler32.gox: hash/adler32.lo
        $(BUILDGOX)
@@ -2898,15 +3017,25 @@ hash/fnv.gox: hash/fnv.lo
 
 http/cgi.gox: http/cgi.lo
        $(BUILDGOX)
+http/fcgi.gox: http/fcgi.lo
+       $(BUILDGOX)
 http/httptest.gox: http/httptest.lo
        $(BUILDGOX)
 http/pprof.gox: http/pprof.lo
        $(BUILDGOX)
+http/spdy.gox: http/spdy.lo
+       $(BUILDGOX)
 
+image/gif.gox: image/gif.lo
+       $(BUILDGOX)
 image/jpeg.gox: image/jpeg.lo
        $(BUILDGOX)
 image/png.gox: image/png.lo
        $(BUILDGOX)
+image/tiff.gox: image/tiff.lo
+       $(BUILDGOX)
+image/ycbcr.gox: image/ycbcr.lo
+       $(BUILDGOX)
 
 index/suffixarray.gox: index/suffixarray.lo
        $(BUILDGOX)
@@ -2924,6 +3053,8 @@ net/textproto.gox: net/textproto.lo
 
 os/inotify.gox: os/inotify.lo
        $(BUILDGOX)
+os/user.gox: os/user.lo
+       $(BUILDGOX)
 os/signal.gox: os/signal.lo
        $(BUILDGOX)
 
@@ -3054,22 +3185,30 @@ TEST_PACKAGES = \
        exp/datafmt/check \
        exp/draw/check \
        exp/eval/check \
+       go/ast/check \
        go/parser/check \
        go/printer/check \
        go/scanner/check \
        go/token/check \
        go/typechecker/check \
+       $(go_types_check_omitted_since_it_calls_6g) \
        hash/adler32/check \
        hash/crc32/check \
        hash/crc64/check \
        hash/fnv/check \
        http/cgi/check \
+       http/fcgi/check \
+       http/spdy/check \
+       image/jpeg/check \
        image/png/check \
+       image/tiff/check \
+       image/ycbcr/check \
        index/suffixarray/check \
        io/ioutil/check \
        mime/multipart/check \
        net/textproto/check \
        $(os_inotify_check) \
+       os/user/check \
        os/signal/check \
        path/filepath/check \
        rpc/jsonrpc/check \
index cf84f73..10d0a4e 100644 (file)
@@ -155,15 +155,17 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
        encoding/binary.lo encoding/git85.lo encoding/hex.lo \
        encoding/line.lo encoding/pem.lo exp/datafmt.lo exp/draw.lo \
        exp/eval.lo go/ast.lo go/doc.lo go/parser.lo go/printer.lo \
-       go/scanner.lo go/token.lo go/typechecker.lo hash/adler32.lo \
-       hash/crc32.lo hash/crc64.lo hash/fnv.lo http/cgi.lo \
-       http/httptest.lo http/pprof.lo image/jpeg.lo image/png.lo \
-       index/suffixarray.lo io/ioutil.lo mime/multipart.lo \
-       net/dict.lo net/textproto.lo $(am__DEPENDENCIES_1) \
-       os/signal.lo path/filepath.lo rpc/jsonrpc.lo runtime/debug.lo \
-       runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
-       syscalls/syscall.lo syscalls/errno.lo testing/testing.lo \
-       testing/iotest.lo testing/quick.lo testing/script.lo
+       go/scanner.lo go/token.lo go/typechecker.lo go/types.lo \
+       hash/adler32.lo hash/crc32.lo hash/crc64.lo hash/fnv.lo \
+       http/cgi.lo http/fcgi.lo http/httptest.lo http/pprof.lo \
+       http/spdy.lo image/gif.lo image/jpeg.lo image/png.lo \
+       image/tiff.lo image/ycbcr.lo index/suffixarray.lo io/ioutil.lo \
+       mime/multipart.lo net/dict.lo net/textproto.lo \
+       $(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \
+       rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
+       sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \
+       syscalls/errno.lo testing/testing.lo testing/iotest.lo \
+       testing/quick.lo testing/script.lo
 libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1)
@@ -196,7 +198,7 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
        runtime/go-select.c runtime/go-semacquire.c \
        runtime/go-send-big.c runtime/go-send-nb-big.c \
        runtime/go-send-nb-small.c runtime/go-send-small.c \
-       runtime/go-signal.c runtime/go-strcmp.c \
+       runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \
        runtime/go-string-to-byte-array.c \
        runtime/go-string-to-int-array.c runtime/go-strplus.c \
        runtime/go-strslice.c runtime/go-trampoline.c \
@@ -233,7 +235,7 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
        go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
        go-runtime-error.lo go-sched.lo go-select.lo go-semacquire.lo \
        go-send-big.lo go-send-nb-big.lo go-send-nb-small.lo \
-       go-send-small.lo go-signal.lo go-strcmp.lo \
+       go-send-small.lo go-setenv.lo go-signal.lo go-strcmp.lo \
        go-string-to-byte-array.lo go-string-to-int-array.lo \
        go-strplus.lo go-strslice.lo go-trampoline.lo go-type-eface.lo \
        go-type-error.lo go-type-identity.lo go-type-interface.lo \
@@ -689,7 +691,8 @@ toolexeclibgogo_DATA = \
        go/printer.gox \
        go/scanner.gox \
        go/token.gox \
-       go/typechecker.gox
+       go/typechecker.gox \
+       go/types.gox
 
 toolexeclibgohashdir = $(toolexeclibgodir)/hash
 toolexeclibgohash_DATA = \
@@ -701,13 +704,18 @@ toolexeclibgohash_DATA = \
 toolexeclibgohttpdir = $(toolexeclibgodir)/http
 toolexeclibgohttp_DATA = \
        http/cgi.gox \
+       http/fcgi.gox \
        http/httptest.gox \
-       http/pprof.gox
+       http/pprof.gox \
+       http/spdy.gox
 
 toolexeclibgoimagedir = $(toolexeclibgodir)/image
 toolexeclibgoimage_DATA = \
+       image/gif.gox \
        image/jpeg.gox \
-       image/png.gox
+       image/png.gox \
+       image/tiff.gox \
+       image/ycbcr.gox
 
 toolexeclibgoindexdir = $(toolexeclibgodir)/index
 toolexeclibgoindex_DATA = \
@@ -733,6 +741,7 @@ toolexeclibgoosdir = $(toolexeclibgodir)/os
 @LIBGO_IS_LINUX_TRUE@os_inotify_gox = 
 toolexeclibgoos_DATA = \
        $(os_inotify_gox) \
+       os/user.gox \
        os/signal.gox
 
 toolexeclibgopathdir = $(toolexeclibgodir)/path
@@ -821,6 +830,7 @@ runtime_files = \
        runtime/go-send-nb-big.c \
        runtime/go-send-nb-small.c \
        runtime/go-send-small.c \
+       runtime/go-setenv.c \
        runtime/go-signal.c \
        runtime/go-strcmp.c \
        runtime/go-string-to-byte-array.c \
@@ -952,6 +962,7 @@ go_http_files = \
        go/http/persist.go \
        go/http/request.go \
        go/http/response.go \
+       go/http/reverseproxy.go \
        go/http/server.go \
        go/http/status.go \
        go/http/transfer.go \
@@ -1041,8 +1052,13 @@ go_mime_files = \
 @LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver.go
 @LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver.go
 @LIBGO_IS_RTEMS_TRUE@go_net_newpollserver_file = go/net/newpollserver_rtems.go
+@LIBGO_IS_LINUX_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
+@LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go
+@LIBGO_IS_LINUX_FALSE@go_net_sock_file = go/net/sock_bsd.go
+@LIBGO_IS_LINUX_TRUE@go_net_sock_file = go/net/sock_linux.go
 go_net_files = \
-       go/net/cgo_stub.go \
+       go/net/cgo_unix.go \
+       $(go_net_cgo_file) \
        go/net/dial.go \
        go/net/dnsclient.go \
        go/net/dnsconfig.go \
@@ -1061,6 +1077,7 @@ go_net_files = \
        go/net/pipe.go \
        go/net/port.go \
        go/net/sock.go \
+       $(go_net_sock_file) \
        go/net/tcpsock.go \
        go/net/udpsock.go \
        go/net/unixsock.go
@@ -1365,7 +1382,6 @@ go_crypto_subtle_files = \
 
 go_crypto_tls_files = \
        go/crypto/tls/alert.go \
-       go/crypto/tls/ca_set.go \
        go/crypto/tls/cipher_suites.go \
        go/crypto/tls/common.go \
        go/crypto/tls/conn.go \
@@ -1380,6 +1396,8 @@ go_crypto_twofish_files = \
        go/crypto/twofish/twofish.go
 
 go_crypto_x509_files = \
+       go/crypto/x509/cert_pool.go \
+       go/crypto/x509/verify.go \
        go/crypto/x509/x509.go
 
 go_crypto_xtea_files = \
@@ -1519,6 +1537,13 @@ go_go_typechecker_files = \
        go/go/typechecker/typechecker.go \
        go/go/typechecker/universe.go
 
+go_go_types_files = \
+       go/go/types/const.go \
+       go/go/types/exportdata.go \
+       go/go/types/gcimporter.go \
+       go/go/types/types.go \
+       go/go/types/universe.go
+
 go_hash_adler32_files = \
        go/hash/adler32/adler32.go
 
@@ -1535,6 +1560,10 @@ go_http_cgi_files = \
        go/http/cgi/child.go \
        go/http/cgi/host.go
 
+go_http_fcgi_files = \
+       go/http/fcgi/child.go \
+       go/http/fcgi/fcgi.go
+
 go_http_httptest_files = \
        go/http/httptest/recorder.go \
        go/http/httptest/server.go
@@ -1542,15 +1571,31 @@ go_http_httptest_files = \
 go_http_pprof_files = \
        go/http/pprof/pprof.go
 
+go_http_spdy_files = \
+       go/http/spdy/protocol.go
+
+go_image_gif_files = \
+       go/image/gif/reader.go
+
 go_image_jpeg_files = \
+       go/image/jpeg/fdct.go \
        go/image/jpeg/huffman.go \
        go/image/jpeg/idct.go \
-       go/image/jpeg/reader.go
+       go/image/jpeg/reader.go \
+       go/image/jpeg/writer.go
 
 go_image_png_files = \
        go/image/png/reader.go \
        go/image/png/writer.go
 
+go_image_tiff_files = \
+       go/image/tiff/buffer.go \
+       go/image/tiff/consts.go \
+       go/image/tiff/reader.go
+
+go_image_ycbcr_files = \
+       go/image/ycbcr/ycbcr.go
+
 go_index_suffixarray_files = \
        go/index/suffixarray/qsufsort.go \
        go/index/suffixarray/suffixarray.go
@@ -1560,6 +1605,7 @@ go_io_ioutil_files = \
        go/io/ioutil/tempfile.go
 
 go_mime_multipart_files = \
+       go/mime/multipart/formdata.go \
        go/mime/multipart/multipart.go
 
 go_net_dict_files = \
@@ -1575,6 +1621,10 @@ go_net_textproto_files = \
 go_os_inotify_files = \
        go/os/inotify/inotify_linux.go
 
+go_os_user_files = \
+       go/os/user/user.go \
+       go/os/user/lookup_unix.go
+
 go_os_signal_files = \
        go/os/signal/signal.go \
        unix.go
@@ -1816,21 +1866,28 @@ libgo_go_objs = \
        go/scanner.lo \
        go/token.lo \
        go/typechecker.lo \
+       go/types.lo \
        hash/adler32.lo \
        hash/crc32.lo \
        hash/crc64.lo \
        hash/fnv.lo \
        http/cgi.lo \
+       http/fcgi.lo \
        http/httptest.lo \
        http/pprof.lo \
+       http/spdy.lo \
+       image/gif.lo \
        image/jpeg.lo \
        image/png.lo \
+       image/tiff.lo \
+       image/ycbcr.lo \
        index/suffixarray.lo \
        io/ioutil.lo \
        mime/multipart.lo \
        net/dict.lo \
        net/textproto.lo \
        $(os_lib_inotify_lo) \
+       os/user.lo \
        os/signal.lo \
        path/filepath.lo \
        rpc/jsonrpc.lo \
@@ -2052,22 +2109,30 @@ TEST_PACKAGES = \
        exp/datafmt/check \
        exp/draw/check \
        exp/eval/check \
+       go/ast/check \
        go/parser/check \
        go/printer/check \
        go/scanner/check \
        go/token/check \
        go/typechecker/check \
+       $(go_types_check_omitted_since_it_calls_6g) \
        hash/adler32/check \
        hash/crc32/check \
        hash/crc64/check \
        hash/fnv/check \
        http/cgi/check \
+       http/fcgi/check \
+       http/spdy/check \
+       image/jpeg/check \
        image/png/check \
+       image/tiff/check \
+       image/ycbcr/check \
        index/suffixarray/check \
        io/ioutil/check \
        mime/multipart/check \
        net/textproto/check \
        $(os_inotify_check) \
+       os/user/check \
        os/signal/check \
        path/filepath/check \
        rpc/jsonrpc/check \
@@ -2270,6 +2335,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-big.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-small.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-small.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strcmp.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-string-to-byte-array.Plo@am__quote@
@@ -2750,6 +2816,13 @@ go-send-small.lo: runtime/go-send-small.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-small.lo `test -f 'runtime/go-send-small.c' || echo '$(srcdir)/'`runtime/go-send-small.c
 
+go-setenv.lo: runtime/go-setenv.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-setenv.lo -MD -MP -MF $(DEPDIR)/go-setenv.Tpo -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/go-setenv.Tpo $(DEPDIR)/go-setenv.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='runtime/go-setenv.c' object='go-setenv.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
+
 go-signal.lo: runtime/go-signal.c
 @am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-signal.lo -MD -MP -MF $(DEPDIR)/go-signal.Tpo -c -o go-signal.lo `test -f 'runtime/go-signal.c' || echo '$(srcdir)/'`runtime/go-signal.c
 @am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/go-signal.Tpo $(DEPDIR)/go-signal.Plo
@@ -4114,11 +4187,12 @@ html/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: html/check
 
-http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \
-               crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \
-               io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \
-               net.gox net/textproto.gox os.gox path.gox path/filepath.gox \
-               sort.gox strconv.gox strings.gox sync.gox time.gox utf8.gox
+http/http.lo: $(go_http_files) bufio.gox bytes.gox compress/gzip.gox \
+               container/vector.gox crypto/rand.gox crypto/tls.gox \
+               encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \
+               mime.gox mime/multipart.gox net.gox net/textproto.gox os.gox \
+               path.gox path/filepath.gox sort.gox strconv.gox strings.gox \
+               sync.gox time.gox utf8.gox
        $(BUILDPACKAGE)
 http/check: $(CHECK_DEPS)
        @$(CHECK)
@@ -4158,7 +4232,7 @@ math/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: math/check
 
-mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox os.gox strings.gox \
+mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox fmt.gox os.gox strings.gox \
                sync.gox unicode.gox
        $(BUILDPACKAGE)
 mime/check: $(CHECK_DEPS)
@@ -4166,8 +4240,8 @@ mime/check: $(CHECK_DEPS)
 .PHONY: mime/check
 
 net/net.lo: $(go_net_files) bytes.gox fmt.gox io.gox os.gox rand.gox \
-               reflect.gox strconv.gox strings.gox sync.gox syscall.gox \
-               time.gox
+               reflect.gox sort.gox strconv.gox strings.gox sync.gox \
+               syscall.gox time.gox
        $(BUILDPACKAGE)
 net/check: $(CHECK_DEPS)
        @$(CHECK_ON_REQUEST)
@@ -4348,8 +4422,8 @@ xml/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: xml/check
 
-archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox os.gox strconv.gox \
-               strings.gox
+archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox io/ioutil.gox os.gox \
+               strconv.gox strings.gox
        $(BUILDPACKAGE)
 archive/tar/check: $(CHECK_DEPS)
        @$(MKDIR_P) archive/tar
@@ -4551,8 +4625,7 @@ crypto/ripemd160/check: $(CHECK_DEPS)
 .PHONY: crypto/ripemd160/check
 
 crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
-               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
-               sync.gox
+               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
        $(BUILDPACKAGE)
 crypto/rsa/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/rsa
@@ -4587,13 +4660,13 @@ crypto/subtle/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/subtle/check
 
-crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
-               container/list.gox crypto.gox crypto/aes.gox crypto/cipher.gox \
-               crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
-               crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
-               crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
-               crypto/x509.gox encoding/pem.gox fmt.gox hash.gox io.gox \
-               io/ioutil.gox net.gox os.gox strings.gox sync.gox time.gox
+crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
+               crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
+               crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
+               crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
+               crypto/x509.gox encoding/pem.gox hash.gox io.gox \
+               io/ioutil.gox net.gox os.gox strconv.gox strings.gox sync.gox \
+               time.gox
        $(BUILDPACKAGE)
 crypto/tls/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/tls
@@ -4607,9 +4680,10 @@ crypto/twofish/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/twofish/check
 
-crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \
-               crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \
-               strings.gox time.gox
+crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox bytes.gox \
+               container/vector.gox crypto.gox crypto/rsa.gox \
+               crypto/sha1.gox encoding/pem.gox hash.gox os.gox strings.gox \
+               time.gox
        $(BUILDPACKAGE)
 crypto/x509/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/x509
@@ -4623,9 +4697,8 @@ crypto/xtea/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/xtea/check
 
-crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bytes.gox \
-               crypto/openpgp/error.gox encoding/base64.gox \
-               encoding/line.gox io.gox os.gox
+crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bufio.gox bytes.gox \
+               crypto/openpgp/error.gox encoding/base64.gox io.gox os.gox
        $(BUILDPACKAGE)
 crypto/openpgp/armor/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/openpgp/armor
@@ -4777,7 +4850,7 @@ exp/datafmt/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: exp/datafmt/check
 
-exp/draw.lo: $(go_exp_draw_files) image.gox os.gox
+exp/draw.lo: $(go_exp_draw_files) image.gox image/ycbcr.gox os.gox
        $(BUILDPACKAGE)
 exp/draw/check: $(CHECK_DEPS)
        @$(MKDIR_P) exp/draw
@@ -4851,6 +4924,15 @@ go/typechecker/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: go/typechecker/check
 
+go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
+               go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
+               scanner.gox strconv.gox strings.gox
+       $(BUILDPACKAGE)
+go/types/check: $(CHECK_DEPS)
+       @$(MKDIR_P) go/types
+       @$(CHECK)
+.PHONY: go/types/check
+
 hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
        $(BUILDPACKAGE)
 hash/adler32/check: $(CHECK_DEPS)
@@ -4879,15 +4961,25 @@ hash/fnv/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: hash/fnv/check
 
-http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox encoding/line.gox \
-               exec.gox fmt.gox http.gox io.gox io/ioutil.gox log.gox \
-               os.gox path/filepath.gox regexp.gox strconv.gox strings.gox
+http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox crypto/tls.gox \
+               exec.gox fmt.gox http.gox net.gox io.gox io/ioutil.gox \
+               log.gox os.gox path/filepath.gox regexp.gox strconv.gox \
+               strings.gox
        $(BUILDPACKAGE)
 http/cgi/check: $(CHECK_DEPS)
        @$(MKDIR_P) http/cgi
        @$(CHECK)
 .PHONY: http/cgi/check
 
+http/fcgi.lo: $(go_http_fcgi_files) bufio.gox bytes.gox encoding/binary.gox \
+               fmt.gox http.gox http/cgi.gox io.gox net.gox os.gox sync.gox \
+               time.gox
+       $(BUILDPACKAGE)
+http/fcgi/check: $(CHECK_DEPS)
+       @$(MKDIR_P) http/fcgi
+       @$(CHECK)
+.PHONY: http/fcgi/check
+
 http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
                crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
        $(BUILDPACKAGE)
@@ -4896,15 +4988,33 @@ http/httptest/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: http/httptest/check
 
-http/pprof.lo: $(go_http_pprof_files) bufio.gox fmt.gox http.gox os.gox \
-               runtime.gox runtime/pprof.gox strconv.gox strings.gox
+http/pprof.lo: $(go_http_pprof_files) bufio.gox bytes.gox fmt.gox http.gox \
+               os.gox runtime.gox runtime/pprof.gox strconv.gox strings.gox
        $(BUILDPACKAGE)
 http/pprof/check: $(CHECK_DEPS)
        @$(MKDIR_P) http/pprof
        @$(CHECK)
 .PHONY: http/pprof/check
 
-image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox io.gox os.gox
+http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
+               encoding/binary.gox http.gox io.gox os.gox strconv.gox \
+               strings.gox sync.gox
+       $(BUILDPACKAGE)
+http/spdy/check: $(CHECK_DEPS)
+       @$(MKDIR_P) http/spdy
+       @$(CHECK)
+.PHONY: http/spdy/check
+
+image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
+               image.gox io.gox os.gox
+       $(BUILDPACKAGE)
+image/gif/check: $(CHECK_DEPS)
+       @$(MKDIR_P) image/gif
+       @$(CHECK)
+.PHONY: image/gif/check
+
+image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
+               io.gox os.gox
        $(BUILDPACKAGE)
 image/jpeg/check: $(CHECK_DEPS)
        @$(MKDIR_P) image/jpeg
@@ -4919,6 +5029,21 @@ image/png/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: image/png/check
 
+image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
+               encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
+       $(BUILDPACKAGE)
+image/tiff/check: $(CHECK_DEPS)
+       @$(MKDIR_P) image/tiff
+       @$(CHECK)
+.PHONY: image/tiff/check
+
+image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
+       $(BUILDPACKAGE)
+image/ycbcr/check: $(CHECK_DEPS)
+       @$(MKDIR_P) image/ycbcr
+       @$(CHECK)
+.PHONY: image/ycbcr/check
+
 index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
                sort.gox
        $(BUILDPACKAGE)
@@ -4935,8 +5060,9 @@ io/ioutil/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: io/ioutil/check
 
-mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox io.gox \
-               mime.gox net/textproto.gox os.gox regexp.gox strings.gox
+mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox fmt.gox \
+               io.gox io/ioutil.gox mime.gox net/textproto.gox os.gox \
+               regexp.gox
        $(BUILDPACKAGE)
 mime/multipart/check: $(CHECK_DEPS)
        @$(MKDIR_P) mime/multipart
@@ -4963,6 +5089,14 @@ os/inotify/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: os/inotify/check
 
+os/user.lo: $(go_os_user_files) fmt.gox os.gox runtime.gox strconv.gox \
+               strings.gox syscall.gox
+       $(BUILDPACKAGE)
+os/user/check: $(CHECK_DEPS)
+       @$(MKDIR_P) os/user
+       @$(CHECK)
+.PHONY: os/user/check
+
 os/signal.lo: $(go_os_signal_files) runtime.gox strconv.gox
        $(BUILDPACKAGE)
 os/signal/check: $(CHECK_DEPS)
@@ -5284,6 +5418,8 @@ go/token.gox: go/token.lo
        $(BUILDGOX)
 go/typechecker.gox: go/typechecker.lo
        $(BUILDGOX)
+go/types.gox: go/types.lo
+       $(BUILDGOX)
 
 hash/adler32.gox: hash/adler32.lo
        $(BUILDGOX)
@@ -5296,15 +5432,25 @@ hash/fnv.gox: hash/fnv.lo
 
 http/cgi.gox: http/cgi.lo
        $(BUILDGOX)
+http/fcgi.gox: http/fcgi.lo
+       $(BUILDGOX)
 http/httptest.gox: http/httptest.lo
        $(BUILDGOX)
 http/pprof.gox: http/pprof.lo
        $(BUILDGOX)
+http/spdy.gox: http/spdy.lo
+       $(BUILDGOX)
 
+image/gif.gox: image/gif.lo
+       $(BUILDGOX)
 image/jpeg.gox: image/jpeg.lo
        $(BUILDGOX)
 image/png.gox: image/png.lo
        $(BUILDGOX)
+image/tiff.gox: image/tiff.lo
+       $(BUILDGOX)
+image/ycbcr.gox: image/ycbcr.lo
+       $(BUILDGOX)
 
 index/suffixarray.gox: index/suffixarray.lo
        $(BUILDGOX)
@@ -5322,6 +5468,8 @@ net/textproto.gox: net/textproto.lo
 
 os/inotify.gox: os/inotify.lo
        $(BUILDGOX)
+os/user.gox: os/user.lo
+       $(BUILDGOX)
 os/signal.gox: os/signal.lo
        $(BUILDGOX)
 
index 5b781ff..5288587 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.
 
-// The tar package implements access to tar archives.
+// Package tar implements access to tar archives.
 // It aims to cover most of the variations, including those produced
 // by GNU and BSD tars.
 //
index 1b41196..ad06b6d 100644 (file)
@@ -10,6 +10,7 @@ package tar
 import (
        "bytes"
        "io"
+       "io/ioutil"
        "os"
        "strconv"
 )
@@ -27,13 +28,13 @@ var (
 //     tr := tar.NewReader(r)
 //     for {
 //             hdr, err := tr.Next()
-//             if err != nil {
-//                     // handle error
-//             }
-//             if hdr == nil {
+//             if err == os.EOF {
 //                     // end of tar archive
 //                     break
 //             }
+//             if err != nil {
+//                     // handle error
+//             }
 //             io.Copy(data, tr)
 //     }
 type Reader struct {
@@ -84,12 +85,6 @@ func (tr *Reader) octal(b []byte) int64 {
        return int64(x)
 }
 
-type ignoreWriter struct{}
-
-func (ignoreWriter) Write(b []byte) (n int, err os.Error) {
-       return len(b), nil
-}
-
 // Skip any unread bytes in the existing file entry, as well as any alignment padding.
 func (tr *Reader) skipUnread() {
        nr := tr.nb + tr.pad // number of bytes to skip
@@ -99,7 +94,7 @@ func (tr *Reader) skipUnread() {
                        return
                }
        }
-       _, tr.err = io.Copyn(ignoreWriter{}, tr.r, nr)
+       _, tr.err = io.Copyn(ioutil.Discard, tr.r, nr)
 }
 
 func (tr *Reader) verifyChecksum(header []byte) bool {
index 543007a..17464c5 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 /*
-The zip package provides support for reading ZIP archives.
+Package zip provides support for reading ZIP archives.
 
 See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
 
@@ -35,6 +35,11 @@ type Reader struct {
        Comment string
 }
 
+type ReadCloser struct {
+       f *os.File
+       Reader
+}
+
 type File struct {
        FileHeader
        zipr         io.ReaderAt
@@ -47,43 +52,60 @@ func (f *File) hasDataDescriptor() bool {
        return f.Flags&0x8 != 0
 }
 
-// OpenReader will open the Zip file specified by name and return a Reader.
-func OpenReader(name string) (*Reader, os.Error) {
+// OpenReader will open the Zip file specified by name and return a ReaderCloser.
+func OpenReader(name string) (*ReadCloser, os.Error) {
        f, err := os.Open(name)
        if err != nil {
                return nil, err
        }
        fi, err := f.Stat()
        if err != nil {
+               f.Close()
+               return nil, err
+       }
+       r := new(ReadCloser)
+       if err := r.init(f, fi.Size); err != nil {
+               f.Close()
                return nil, err
        }
-       return NewReader(f, fi.Size)
+       return r, nil
 }
 
 // NewReader returns a new Reader reading from r, which is assumed to
 // have the given size in bytes.
 func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
-       end, err := readDirectoryEnd(r, size)
-       if err != nil {
+       zr := new(Reader)
+       if err := zr.init(r, size); err != nil {
                return nil, err
        }
-       z := &Reader{
-               r:       r,
-               File:    make([]*File, end.directoryRecords),
-               Comment: end.comment,
+       return zr, nil
+}
+
+func (z *Reader) init(r io.ReaderAt, size int64) os.Error {
+       end, err := readDirectoryEnd(r, size)
+       if err != nil {
+               return err
        }
+       z.r = r
+       z.File = make([]*File, end.directoryRecords)
+       z.Comment = end.comment
        rs := io.NewSectionReader(r, 0, size)
        if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
-               return nil, err
+               return err
        }
        buf := bufio.NewReader(rs)
        for i := range z.File {
                z.File[i] = &File{zipr: r, zipsize: size}
                if err := readDirectoryHeader(z.File[i], buf); err != nil {
-                       return nil, err
+                       return err
                }
        }
-       return z, nil
+       return nil
+}
+
+// Close closes the Zip file, rendering it unusable for I/O.
+func (rc *ReadCloser) Close() os.Error {
+       return rc.f.Close()
 }
 
 // Open returns a ReadCloser that provides access to the File's contents.
index 72e8ccc..c72cd9a 100644 (file)
@@ -76,6 +76,12 @@ func readTestZip(t *testing.T, zt ZipTest) {
                return
        }
 
+       // bail if file is not zip
+       if err == FormatError {
+               return
+       }
+       defer z.Close()
+
        // bail here if no Files expected to be tested
        // (there may actually be files in the zip, but we don't care)
        if zt.File == nil {
index c531451..5f470ae 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.
 
-// The asn1 package implements parsing of DER-encoded ASN.1 data structures,
+// Package asn1 implements parsing of DER-encoded ASN.1 data structures,
 // as defined in ITU-T Rec X.690.
 //
 // See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,''
@@ -373,7 +373,7 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
 // parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse
 // a number of ASN.1 values from the given byte array and returns them as a
 // slice of Go values of the given type.
-func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflect.Type) (ret *reflect.SliceValue, err os.Error) {
+func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err os.Error) {
        expectedTag, compoundType, ok := getUniversalType(elemType)
        if !ok {
                err = StructuralError{"unknown Go type for slice"}
@@ -409,7 +409,7 @@ func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflec
        params := fieldParameters{}
        offset := 0
        for i := 0; i < numElements; i++ {
-               offset, err = parseField(ret.Elem(i), bytes, offset, params)
+               offset, err = parseField(ret.Index(i), bytes, offset, params)
                if err != nil {
                        return
                }
@@ -418,13 +418,13 @@ func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflec
 }
 
 var (
-       bitStringType        = reflect.Typeof(BitString{})
-       objectIdentifierType = reflect.Typeof(ObjectIdentifier{})
-       enumeratedType       = reflect.Typeof(Enumerated(0))
-       flagType             = reflect.Typeof(Flag(false))
-       timeType             = reflect.Typeof(&time.Time{})
-       rawValueType         = reflect.Typeof(RawValue{})
-       rawContentsType      = reflect.Typeof(RawContent(nil))
+       bitStringType        = reflect.TypeOf(BitString{})
+       objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
+       enumeratedType       = reflect.TypeOf(Enumerated(0))
+       flagType             = reflect.TypeOf(Flag(false))
+       timeType             = reflect.TypeOf(&time.Time{})
+       rawValueType         = reflect.TypeOf(RawValue{})
+       rawContentsType      = reflect.TypeOf(RawContent(nil))
 )
 
 // invalidLength returns true iff offset + length > sliceLength, or if the
@@ -461,13 +461,12 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                }
                result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
                offset += t.length
-               v.(*reflect.StructValue).Set(reflect.NewValue(result).(*reflect.StructValue))
+               v.Set(reflect.ValueOf(result))
                return
        }
 
        // Deal with the ANY type.
-       if ifaceType, ok := fieldType.(*reflect.InterfaceType); ok && ifaceType.NumMethod() == 0 {
-               ifaceValue := v.(*reflect.InterfaceValue)
+       if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
                var t tagAndLength
                t, offset, err = parseTagAndLength(bytes, offset)
                if err != nil {
@@ -506,7 +505,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                        return
                }
                if result != nil {
-                       ifaceValue.Set(reflect.NewValue(result))
+                       v.Set(reflect.ValueOf(result))
                }
                return
        }
@@ -536,9 +535,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                                        err = StructuralError{"Zero length explicit tag was not an asn1.Flag"}
                                        return
                                }
-
-                               flagValue := v.(*reflect.BoolValue)
-                               flagValue.Set(true)
+                               v.SetBool(true)
                                return
                        }
                } else {
@@ -606,23 +603,20 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
        switch fieldType {
        case objectIdentifierType:
                newSlice, err1 := parseObjectIdentifier(innerBytes)
-               sliceValue := v.(*reflect.SliceValue)
-               sliceValue.Set(reflect.MakeSlice(sliceValue.Type().(*reflect.SliceType), len(newSlice), len(newSlice)))
+               v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
                if err1 == nil {
-                       reflect.Copy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue))
+                       reflect.Copy(v, reflect.ValueOf(newSlice))
                }
                err = err1
                return
        case bitStringType:
-               structValue := v.(*reflect.StructValue)
                bs, err1 := parseBitString(innerBytes)
                if err1 == nil {
-                       structValue.Set(reflect.NewValue(bs).(*reflect.StructValue))
+                       v.Set(reflect.ValueOf(bs))
                }
                err = err1
                return
        case timeType:
-               ptrValue := v.(*reflect.PtrValue)
                var time *time.Time
                var err1 os.Error
                if universalTag == tagUTCTime {
@@ -631,55 +625,53 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                        time, err1 = parseGeneralizedTime(innerBytes)
                }
                if err1 == nil {
-                       ptrValue.Set(reflect.NewValue(time).(*reflect.PtrValue))
+                       v.Set(reflect.ValueOf(time))
                }
                err = err1
                return
        case enumeratedType:
                parsedInt, err1 := parseInt(innerBytes)
-               enumValue := v.(*reflect.IntValue)
                if err1 == nil {
-                       enumValue.Set(int64(parsedInt))
+                       v.SetInt(int64(parsedInt))
                }
                err = err1
                return
        case flagType:
-               flagValue := v.(*reflect.BoolValue)
-               flagValue.Set(true)
+               v.SetBool(true)
                return
        }
-       switch val := v.(type) {
-       case *reflect.BoolValue:
+       switch val := v; val.Kind() {
+       case reflect.Bool:
                parsedBool, err1 := parseBool(innerBytes)
                if err1 == nil {
-                       val.Set(parsedBool)
+                       val.SetBool(parsedBool)
                }
                err = err1
                return
-       case *reflect.IntValue:
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
                switch val.Type().Kind() {
                case reflect.Int:
                        parsedInt, err1 := parseInt(innerBytes)
                        if err1 == nil {
-                               val.Set(int64(parsedInt))
+                               val.SetInt(int64(parsedInt))
                        }
                        err = err1
                        return
                case reflect.Int64:
                        parsedInt, err1 := parseInt64(innerBytes)
                        if err1 == nil {
-                               val.Set(parsedInt)
+                               val.SetInt(parsedInt)
                        }
                        err = err1
                        return
                }
-       case *reflect.StructValue:
-               structType := fieldType.(*reflect.StructType)
+       case reflect.Struct:
+               structType := fieldType
 
                if structType.NumField() > 0 &&
                        structType.Field(0).Type == rawContentsType {
                        bytes := bytes[initOffset:offset]
-                       val.Field(0).SetValue(reflect.NewValue(RawContent(bytes)))
+                       val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
                }
 
                innerOffset := 0
@@ -697,11 +689,11 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                // adding elements to the end has been used in X.509 as the
                // version numbers have increased.
                return
-       case *reflect.SliceValue:
-               sliceType := fieldType.(*reflect.SliceType)
+       case reflect.Slice:
+               sliceType := fieldType
                if sliceType.Elem().Kind() == reflect.Uint8 {
                        val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
-                       reflect.Copy(val, reflect.NewValue(innerBytes).(reflect.ArrayOrSliceValue))
+                       reflect.Copy(val, reflect.ValueOf(innerBytes))
                        return
                }
                newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
@@ -710,7 +702,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                }
                err = err1
                return
-       case *reflect.StringValue:
+       case reflect.String:
                var v string
                switch universalTag {
                case tagPrintableString:
@@ -729,7 +721,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
                        err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
                }
                if err == nil {
-                       val.Set(v)
+                       val.SetString(v)
                }
                return
        }
@@ -748,9 +740,9 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
        if params.defaultValue == nil {
                return
        }
-       switch val := v.(type) {
-       case *reflect.IntValue:
-               val.Set(*params.defaultValue)
+       switch val := v; val.Kind() {
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+               val.SetInt(*params.defaultValue)
        }
        return
 }
@@ -806,7 +798,7 @@ func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) {
 // UnmarshalWithParams allows field parameters to be specified for the
 // top-level element. The form of the params is the same as the field tags.
 func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) {
-       v := reflect.NewValue(val).(*reflect.PtrValue).Elem()
+       v := reflect.ValueOf(val).Elem()
        offset, err := parseField(v, b, 0, parseFieldParameters(params))
        if err != nil {
                return nil, err
index b776765..78f5628 100644 (file)
@@ -267,11 +267,6 @@ func TestParseFieldParameters(t *testing.T) {
        }
 }
 
-type unmarshalTest struct {
-       in  []byte
-       out interface{}
-}
-
 type TestObjectIdentifierStruct struct {
        OID ObjectIdentifier
 }
@@ -290,7 +285,10 @@ type TestElementsAfterString struct {
        A, B int
 }
 
-var unmarshalTestData []unmarshalTest = []unmarshalTest{
+var unmarshalTestData = []struct {
+       in  []byte
+       out interface{}
+}{
        {[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
        {[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
        {[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
@@ -309,9 +307,7 @@ var unmarshalTestData []unmarshalTest = []unmarshalTest{
 
 func TestUnmarshal(t *testing.T) {
        for i, test := range unmarshalTestData {
-               pv := reflect.MakeZero(reflect.NewValue(test.out).Type())
-               zv := reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem())
-               pv.(*reflect.PtrValue).PointTo(zv)
+               pv := reflect.New(reflect.TypeOf(test.out).Elem())
                val := pv.Interface()
                _, err := Unmarshal(test.in, val)
                if err != nil {
index f2254a4..1589877 100644 (file)
@@ -133,14 +133,14 @@ func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
        case enumeratedType:
                return tagEnum, false, true
        }
-       switch t := t.(type) {
-       case *reflect.BoolType:
+       switch t.Kind() {
+       case reflect.Bool:
                return tagBoolean, false, true
-       case *reflect.IntType:
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
                return tagInteger, false, true
-       case *reflect.StructType:
+       case reflect.Struct:
                return tagSequence, true, true
-       case *reflect.SliceType:
+       case reflect.Slice:
                if t.Elem().Kind() == reflect.Uint8 {
                        return tagOctetString, false, true
                }
@@ -148,7 +148,7 @@ func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
                        return tagSet, true, true
                }
                return tagSequence, true, true
-       case *reflect.StringType:
+       case reflect.String:
                return tagPrintableString, false, true
        }
        return 0, false, false
index 57b8f20..a3e1145 100644 (file)
@@ -125,6 +125,28 @@ func int64Length(i int64) (numBytes int) {
        return
 }
 
+func marshalLength(out *forkableWriter, i int) (err os.Error) {
+       n := lengthLength(i)
+
+       for ; n > 0; n-- {
+               err = out.WriteByte(byte(i >> uint((n-1)*8)))
+               if err != nil {
+                       return
+               }
+       }
+
+       return nil
+}
+
+func lengthLength(i int) (numBytes int) {
+       numBytes = 1
+       for i > 255 {
+               numBytes++
+               i >>= 8
+       }
+       return
+}
+
 func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err os.Error) {
        b := uint8(t.class) << 6
        if t.isCompound {
@@ -149,12 +171,12 @@ func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err os.Error) {
        }
 
        if t.length >= 128 {
-               l := int64Length(int64(t.length))
+               l := lengthLength(t.length)
                err = out.WriteByte(0x80 | byte(l))
                if err != nil {
                        return
                }
-               err = marshalInt64(out, int64(t.length))
+               err = marshalLength(out, t.length)
                if err != nil {
                        return
                }
@@ -314,28 +336,28 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
                return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
        }
 
-       switch v := value.(type) {
-       case *reflect.BoolValue:
-               if v.Get() {
+       switch v := value; v.Kind() {
+       case reflect.Bool:
+               if v.Bool() {
                        return out.WriteByte(255)
                } else {
                        return out.WriteByte(0)
                }
-       case *reflect.IntValue:
-               return marshalInt64(out, int64(v.Get()))
-       case *reflect.StructValue:
-               t := v.Type().(*reflect.StructType)
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+               return marshalInt64(out, int64(v.Int()))
+       case reflect.Struct:
+               t := v.Type()
 
                startingField := 0
 
                // If the first element of the structure is a non-empty
                // RawContents, then we don't bother serialising the rest.
                if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
-                       s := v.Field(0).(*reflect.SliceValue)
+                       s := v.Field(0)
                        if s.Len() > 0 {
                                bytes := make([]byte, s.Len())
                                for i := 0; i < s.Len(); i++ {
-                                       bytes[i] = uint8(s.Elem(i).(*reflect.UintValue).Get())
+                                       bytes[i] = uint8(s.Index(i).Uint())
                                }
                                /* The RawContents will contain the tag and
                                 * length fields but we'll also be writing
@@ -357,12 +379,12 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
                        }
                }
                return
-       case *reflect.SliceValue:
-               sliceType := v.Type().(*reflect.SliceType)
+       case reflect.Slice:
+               sliceType := v.Type()
                if sliceType.Elem().Kind() == reflect.Uint8 {
                        bytes := make([]byte, v.Len())
                        for i := 0; i < v.Len(); i++ {
-                               bytes[i] = uint8(v.Elem(i).(*reflect.UintValue).Get())
+                               bytes[i] = uint8(v.Index(i).Uint())
                        }
                        _, err = out.Write(bytes)
                        return
@@ -372,17 +394,17 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
                for i := 0; i < v.Len(); i++ {
                        var pre *forkableWriter
                        pre, out = out.fork()
-                       err = marshalField(pre, v.Elem(i), params)
+                       err = marshalField(pre, v.Index(i), params)
                        if err != nil {
                                return
                        }
                }
                return
-       case *reflect.StringValue:
+       case reflect.String:
                if params.stringType == tagIA5String {
-                       return marshalIA5String(out, v.Get())
+                       return marshalIA5String(out, v.String())
                } else {
-                       return marshalPrintableString(out, v.Get())
+                       return marshalPrintableString(out, v.String())
                }
                return
        }
@@ -392,7 +414,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
 
 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err os.Error) {
        // If the field is an interface{} then recurse into it.
-       if v, ok := v.(*reflect.InterfaceValue); ok && v.Type().(*reflect.InterfaceType).NumMethod() == 0 {
+       if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
                return marshalField(out, v.Elem(), params)
        }
 
@@ -406,7 +428,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
                return
        }
 
-       if params.optional && reflect.DeepEqual(v.Interface(), reflect.MakeZero(v.Type()).Interface()) {
+       if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
                return
        }
 
@@ -471,7 +493,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 // Marshal returns the ASN.1 encoding of val.
 func Marshal(val interface{}) ([]byte, os.Error) {
        var out bytes.Buffer
-       v := reflect.NewValue(val)
+       v := reflect.ValueOf(val)
        f := newForkableWriter()
        err := marshalField(f, v, fieldParameters{})
        if err != nil {
index 85eafc9..cd165d2 100644 (file)
@@ -77,6 +77,30 @@ var marshalTests = []marshalTest{
        {ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
        {ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"},
        {"test", "130474657374"},
+       {
+               "" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x'
+               "137f" +
+                       "7878787878787878787878787878787878787878787878787878787878787878" +
+                       "7878787878787878787878787878787878787878787878787878787878787878" +
+                       "7878787878787878787878787878787878787878787878787878787878787878" +
+                       "78787878787878787878787878787878787878787878787878787878787878",
+       },
+       {
+               "" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x'
+               "138180" +
+                       "7878787878787878787878787878787878787878787878787878787878787878" +
+                       "7878787878787878787878787878787878787878787878787878787878787878" +
+                       "7878787878787878787878787878787878787878787878787878787878787878" +
+                       "7878787878787878787878787878787878787878787878787878787878787878",
+       },
        {ia5StringTest{"test"}, "3006160474657374"},
        {printableStringTest{"test"}, "3006130474657374"},
        {printableStringTest{"test*"}, "30071305746573742a"},
index ecd70e0..f1ea7b1 100644 (file)
@@ -337,6 +337,10 @@ func fmtbase(ch int) int {
 // 'x' (hexadecimal).
 //
 func (x *Int) Format(s fmt.State, ch int) {
+       if x == nil {
+               fmt.Fprint(s, "<nil>")
+               return
+       }
        if x.neg {
                fmt.Fprint(s, "-")
        }
index a04d3b1..4848d42 100644 (file)
@@ -2,11 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This file contains operations on unsigned multi-precision integers.
-// These are the building blocks for the operations on signed integers
-// and rationals.
-
-// This package implements multi-precision arithmetic (big numbers).
+// Package big implements multi-precision arithmetic (big numbers).
 // The following numeric types are supported:
 //
 //     - Int   signed integers
 //
 package big
 
+// This file contains operations on unsigned multi-precision integers.
+// These are the building blocks for the operations on signed integers
+// and rationals.
+
 import "rand"
 
 // An unsigned integer x of the form
index cd08be3..eaae8bb 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.
 
-// This package implements buffered I/O.  It wraps an io.Reader or io.Writer
+// Package bufio implements buffered I/O.  It wraps an io.Reader or io.Writer
 // object, creating another object (Reader or Writer) that also implements
 // the interface but provides buffering and some help for textual I/O.
 package bufio
@@ -282,6 +282,33 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
        panic("not reached")
 }
 
+// ReadLine tries to return a single line, not including the end-of-line bytes.
+// If the line was too long for the buffer then isPrefix is set and the
+// beginning of the line is returned. The rest of the line will be returned
+// from future calls. isPrefix will be false when returning the last fragment
+// of the line. The returned buffer is only valid until the next call to
+// ReadLine. ReadLine either returns a non-nil line or it returns an error,
+// never both.
+func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
+       line, err = b.ReadSlice('\n')
+       if err == ErrBufferFull {
+               return line, true, nil
+       }
+
+       if len(line) == 0 {
+               return
+       }
+       err = nil
+
+       if line[len(line)-1] == '\n' {
+               line = line[:len(line)-1]
+       }
+       if len(line) > 0 && line[len(line)-1] == '\r' {
+               line = line[:len(line)-1]
+       }
+       return
+}
+
 // ReadBytes reads until the first occurrence of delim in the input,
 // returning a slice containing the data up to and including the delimiter.
 // If ReadBytes encounters an error before finding a delimiter,
index 8028e04..123adac 100644 (file)
@@ -9,6 +9,7 @@ import (
        "bytes"
        "fmt"
        "io"
+       "io/ioutil"
        "os"
        "strings"
        "testing"
@@ -570,3 +571,128 @@ func TestPeekThenUnreadRune(t *testing.T) {
        r.UnreadRune()
        r.ReadRune() // Used to panic here
 }
+
+var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
+var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
+var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")
+
+// 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 os.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 = os.EOF
+       }
+       return
+}
+
+func testReadLine(t *testing.T, input []byte) {
+       //for stride := 1; stride < len(input); stride++ {
+       for stride := 1; stride < 2; stride++ {
+               done := 0
+               reader := testReader{input, stride}
+               l, _ := NewReaderSize(&reader, len(input)+1)
+               for {
+                       line, isPrefix, err := l.ReadLine()
+                       if len(line) > 0 && err != nil {
+                               t.Errorf("ReadLine returned both data and error: %s", err)
+                       }
+                       if isPrefix {
+                               t.Errorf("ReadLine returned prefix")
+                       }
+                       if err != nil {
+                               if err != os.EOF {
+                                       t.Fatalf("Got unknown error: %s", err)
+                               }
+                               break
+                       }
+                       if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
+                               t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
+                       }
+                       done += len(line)
+               }
+               if done != len(testOutput) {
+                       t.Errorf("ReadLine didn't return everything: got: %d, want: %d (stride: %d)", done, len(testOutput), stride)
+               }
+       }
+}
+
+func TestReadLine(t *testing.T) {
+       testReadLine(t, testInput)
+       testReadLine(t, testInputrn)
+}
+
+func TestLineTooLong(t *testing.T) {
+       buf := bytes.NewBuffer([]byte("aaabbbcc\n"))
+       l, _ := NewReaderSize(buf, 3)
+       line, isPrefix, err := l.ReadLine()
+       if !isPrefix || !bytes.Equal(line, []byte("aaa")) || err != nil {
+               t.Errorf("bad result for first line: %x %s", line, err)
+       }
+       line, isPrefix, err = l.ReadLine()
+       if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil {
+               t.Errorf("bad result for second line: %x", line)
+       }
+       line, isPrefix, err = l.ReadLine()
+       if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil {
+               t.Errorf("bad result for third line: %x", line)
+       }
+       line, isPrefix, err = l.ReadLine()
+       if isPrefix || err == nil {
+               t.Errorf("expected no more lines: %x %s", line, err)
+       }
+}
+
+func TestReadAfterLines(t *testing.T) {
+       line1 := "line1"
+       restData := "line2\nline 3\n"
+       inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
+       outbuf := new(bytes.Buffer)
+       maxLineLength := len(line1) + len(restData)/2
+       l, _ := NewReaderSize(inbuf, maxLineLength)
+       line, isPrefix, err := l.ReadLine()
+       if isPrefix || err != nil || string(line) != line1 {
+               t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
+       }
+       n, err := io.Copy(outbuf, l)
+       if int(n) != len(restData) || err != nil {
+               t.Errorf("bad result for Read: n=%d err=%v", n, err)
+       }
+       if outbuf.String() != restData {
+               t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
+       }
+}
+
+func TestReadEmptyBuffer(t *testing.T) {
+       l, _ := NewReaderSize(bytes.NewBuffer(nil), 10)
+       line, isPrefix, err := l.ReadLine()
+       if err != os.EOF {
+               t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
+       }
+}
+
+func TestLinesAfterRead(t *testing.T) {
+       l, _ := NewReaderSize(bytes.NewBuffer([]byte("foo")), 10)
+       _, err := ioutil.ReadAll(l)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       line, isPrefix, err := l.ReadLine()
+       if err != os.EOF {
+               t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
+       }
+}
index c12a135..0f9ac98 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The bytes package implements functions for the manipulation of byte slices.
-// Analogous to the facilities of the strings package.
+// Package bytes implements functions for the manipulation of byte slices.
+// It is analogous to the facilities of the strings package.
 package bytes
 
 import (
index 725dc4e..f3199ca 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The cmath package provides basic constants
-// and mathematical functions for complex numbers.
+// Package cmath provides basic constants and mathematical functions for
+// complex numbers.
 package cmath
 
 import "math"
index 591b35c..a02a5e8 100644 (file)
@@ -143,10 +143,18 @@ func (d *compressor) fillWindow(index int) (int, os.Error) {
                        d.blockStart = math.MaxInt32
                }
                for i, h := range d.hashHead {
-                       d.hashHead[i] = max(h-wSize, -1)
+                       v := h - wSize
+                       if v < -1 {
+                               v = -1
+                       }
+                       d.hashHead[i] = v
                }
                for i, h := range d.hashPrev {
-                       d.hashPrev[i] = max(h-wSize, -1)
+                       v := -h - wSize
+                       if v < -1 {
+                               v = -1
+                       }
+                       d.hashPrev[i] = v
                }
        }
        count, err := d.r.Read(d.window[d.windowEnd:])
@@ -177,10 +185,18 @@ func (d *compressor) writeBlock(tokens []token, index int, eof bool) os.Error {
 // Try to find a match starting at index whose length is greater than prevSize.
 // We only look at chainCount possibilities before giving up.
 func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
-       win := d.window[0 : pos+min(maxMatchLength, lookahead)]
+       minMatchLook := maxMatchLength
+       if lookahead < minMatchLook {
+               minMatchLook = lookahead
+       }
+
+       win := d.window[0 : pos+minMatchLook]
 
        // We quit when we get a match that's at least nice long
-       nice := min(d.niceMatch, len(win)-pos)
+       nice := len(win) - pos
+       if d.niceMatch < nice {
+               nice = d.niceMatch
+       }
 
        // If we've got a match that's good enough, only look in 1/4 the chain.
        tries := d.maxChainLength
@@ -344,9 +360,12 @@ Loop:
                }
                prevLength := length
                prevOffset := offset
-               minIndex := max(index-maxOffset, 0)
                length = minMatchLength - 1
                offset = 0
+               minIndex := index - maxOffset
+               if minIndex < 0 {
+                       minIndex = 0
+               }
 
                if chainHead >= minIndex &&
                        (isFastDeflate && lookahead > minMatchLength-1 ||
@@ -477,6 +496,33 @@ func NewWriter(w io.Writer, level int) *Writer {
        return &Writer{pw, &d}
 }
 
+// NewWriterDict is like NewWriter but initializes the new
+// Writer with a preset dictionary.  The returned Writer behaves
+// as if the dictionary had been written to it without producing
+// any compressed output.  The compressed data written to w
+// can only be decompressed by a Reader initialized with the
+// same dictionary.
+func NewWriterDict(w io.Writer, level int, dict []byte) *Writer {
+       dw := &dictWriter{w, false}
+       zw := NewWriter(dw, level)
+       zw.Write(dict)
+       zw.Flush()
+       dw.enabled = true
+       return zw
+}
+
+type dictWriter struct {
+       w       io.Writer
+       enabled bool
+}
+
+func (w *dictWriter) Write(b []byte) (n int, err os.Error) {
+       if w.enabled {
+               return w.w.Write(b)
+       }
+       return len(b), nil
+}
+
 // A Writer takes data written to it and writes the compressed
 // form of that data to an underlying writer (see NewWriter).
 type Writer struct {
index ed5884a..650a805 100644 (file)
@@ -275,3 +275,49 @@ func TestDeflateInflateString(t *testing.T) {
        }
        testToFromWithLevel(t, 1, gold, "2.718281828...")
 }
+
+func TestReaderDict(t *testing.T) {
+       const (
+               dict = "hello world"
+               text = "hello again world"
+       )
+       var b bytes.Buffer
+       w := NewWriter(&b, 5)
+       w.Write([]byte(dict))
+       w.Flush()
+       b.Reset()
+       w.Write([]byte(text))
+       w.Close()
+
+       r := NewReaderDict(&b, []byte(dict))
+       data, err := ioutil.ReadAll(r)
+       if err != nil {
+               t.Fatal(err)
+       }
+       if string(data) != "hello again world" {
+               t.Fatalf("read returned %q want %q", string(data), text)
+       }
+}
+
+func TestWriterDict(t *testing.T) {
+       const (
+               dict = "hello world"
+               text = "hello again world"
+       )
+       var b bytes.Buffer
+       w := NewWriter(&b, 5)
+       w.Write([]byte(dict))
+       w.Flush()
+       b.Reset()
+       w.Write([]byte(text))
+       w.Close()
+
+       var b1 bytes.Buffer
+       w = NewWriterDict(&b1, 5, []byte(dict))
+       w.Write([]byte(text))
+       w.Close()
+
+       if !bytes.Equal(b1.Bytes(), b.Bytes()) {
+               t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
+       }
+}
index 7dc8cf9..320b80d 100644 (file)
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The flate package implements the DEFLATE compressed data
-// format, described in RFC 1951.  The gzip and zlib packages
-// implement access to DEFLATE-based file formats.
+// Package flate implements the DEFLATE compressed data format, described in
+// RFC 1951.  The gzip and zlib packages implement access to DEFLATE-based file
+// formats.
 package flate
 
 import (
@@ -526,6 +526,20 @@ func (f *decompressor) dataBlock() os.Error {
        return nil
 }
 
+func (f *decompressor) setDict(dict []byte) {
+       if len(dict) > len(f.hist) {
+               // Will only remember the tail.
+               dict = dict[len(dict)-len(f.hist):]
+       }
+
+       f.hp = copy(f.hist[:], dict)
+       if f.hp == len(f.hist) {
+               f.hp = 0
+               f.hfull = true
+       }
+       f.hw = f.hp
+}
+
 func (f *decompressor) moreBits() os.Error {
        c, err := f.r.ReadByte()
        if err != nil {
@@ -618,3 +632,16 @@ func NewReader(r io.Reader) io.ReadCloser {
        go func() { pw.CloseWithError(f.decompress(r, pw)) }()
        return pr
 }
+
+// NewReaderDict is like NewReader but initializes the reader
+// with a preset dictionary.  The returned Reader behaves as if
+// the uncompressed data stream started with the given dictionary,
+// which has already been read.  NewReaderDict is typically used
+// to read data compressed by NewWriterDict.
+func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
+       var f decompressor
+       f.setDict(dict)
+       pr, pw := io.Pipe()
+       go func() { pw.CloseWithError(f.decompress(r, pw)) }()
+       return pr
+}
index 3c0b3c5..b0ddc81 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The gzip package implements reading and writing of
-// gzip format compressed files, as specified in RFC 1952.
+// Package gzip implements reading and writing of gzip format compressed files,
+// as specified in RFC 1952.
 package gzip
 
 import (
index 8a540cb..a1cd2ab 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.
 
-// The lzw package implements the Lempel-Ziv-Welch compressed data format,
+// Package lzw implements the Lempel-Ziv-Welch compressed data format,
 // described in T. A. Welch, ``A Technique for High-Performance Data
 // Compression'', Computer, 17(6) (June 1984), pp 8-19.
 //
@@ -165,16 +165,19 @@ func decode1(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os
                        if _, err := w.Write(buf[i:]); err != nil {
                                return err
                        }
-                       // Save what the hi code expands to.
-                       suffix[hi] = uint8(c)
-                       prefix[hi] = last
+                       if last != invalidCode {
+                               // Save what the hi code expands to.
+                               suffix[hi] = uint8(c)
+                               prefix[hi] = last
+                       }
                default:
                        return os.NewError("lzw: invalid code")
                }
                last, hi = code, hi+1
-               if hi == overflow {
+               if hi >= overflow {
                        if d.width == maxWidth {
-                               return os.NewError("lzw: missing clear code")
+                               last = invalidCode
+                               continue
                        }
                        d.width++
                        overflow <<= 1
index 4b5dfaa..72121a6 100644 (file)
@@ -112,12 +112,6 @@ func TestReader(t *testing.T) {
        }
 }
 
-type devNull struct{}
-
-func (devNull) Write(p []byte) (int, os.Error) {
-       return len(p), nil
-}
-
 func benchmarkDecoder(b *testing.B, n int) {
        b.StopTimer()
        b.SetBytes(int64(n))
@@ -134,7 +128,7 @@ func benchmarkDecoder(b *testing.B, n int) {
        runtime.GC()
        b.StartTimer()
        for i := 0; i < b.N; i++ {
-               io.Copy(devNull{}, NewReader(bytes.NewBuffer(buf1), LSB, 8))
+               io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1), LSB, 8))
        }
 }
 
index e5815a0..82464ec 100644 (file)
@@ -113,7 +113,7 @@ func benchmarkEncoder(b *testing.B, n int) {
        runtime.GC()
        b.StartTimer()
        for i := 0; i < b.N; i++ {
-               w := NewWriter(devNull{}, LSB, 8)
+               w := NewWriter(ioutil.Discard, LSB, 8)
                w.Write(buf1)
                w.Close()
        }
index 721f6ec..8a3ef15 100644 (file)
@@ -3,8 +3,8 @@
 // license that can be found in the LICENSE file.
 
 /*
-The zlib package implements reading and writing of zlib
-format compressed data, as specified in RFC 1950.
+Package zlib implements reading and writing of zlib format compressed data,
+as specified in RFC 1950.
 
 The implementation provides filters that uncompress during reading
 and compress during writing.  For example, to write compressed data
@@ -36,7 +36,7 @@ const zlibDeflate = 8
 
 var ChecksumError os.Error = os.ErrorString("zlib checksum error")
 var HeaderError os.Error = os.ErrorString("invalid zlib header")
-var UnsupportedError os.Error = os.ErrorString("unsupported zlib format")
+var DictionaryError os.Error = os.ErrorString("invalid zlib dictionary")
 
 type reader struct {
        r            flate.Reader
@@ -50,6 +50,12 @@ type reader struct {
 // The implementation buffers input and may read more data than necessary from r.
 // It is the caller's responsibility to call Close on the ReadCloser when done.
 func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
+       return NewReaderDict(r, nil)
+}
+
+// NewReaderDict is like NewReader but uses a preset dictionary.
+// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
+func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, os.Error) {
        z := new(reader)
        if fr, ok := r.(flate.Reader); ok {
                z.r = fr
@@ -65,11 +71,19 @@ func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
                return nil, HeaderError
        }
        if z.scratch[1]&0x20 != 0 {
-               // BUG(nigeltao): The zlib package does not implement the FDICT flag.
-               return nil, UnsupportedError
+               _, err = io.ReadFull(z.r, z.scratch[0:4])
+               if err != nil {
+                       return nil, err
+               }
+               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
+               }
+               z.decompressor = flate.NewReaderDict(z.r, dict)
+       } else {
+               z.decompressor = flate.NewReader(z.r)
        }
        z.digest = adler32.New()
-       z.decompressor = flate.NewReader(z.r)
        return z, nil
 }
 
index eaefc3a..195db44 100644 (file)
@@ -15,6 +15,7 @@ type zlibTest struct {
        desc       string
        raw        string
        compressed []byte
+       dict       []byte
        err        os.Error
 }
 
@@ -27,6 +28,7 @@ var zlibTests = []zlibTest{
                "",
                []byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
                nil,
+               nil,
        },
        {
                "goodbye",
@@ -37,23 +39,27 @@ var zlibTests = []zlibTest{
                        0x01, 0x00, 0x28, 0xa5, 0x05, 0x5e,
                },
                nil,
+               nil,
        },
        {
                "bad header",
                "",
                []byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
+               nil,
                HeaderError,
        },
        {
                "bad checksum",
                "",
                []byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
+               nil,
                ChecksumError,
        },
        {
                "not enough data",
                "",
                []byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00},
+               nil,
                io.ErrUnexpectedEOF,
        },
        {
@@ -64,6 +70,33 @@ var zlibTests = []zlibTest{
                        0x78, 0x9c, 0xff,
                },
                nil,
+               nil,
+       },
+       {
+               "dictionary",
+               "Hello, World!\n",
+               []byte{
+                       0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
+                       0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
+                       0x12, 0x04, 0x74,
+               },
+               []byte{
+                       0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a,
+               },
+               nil,
+       },
+       {
+               "wrong dictionary",
+               "",
+               []byte{
+                       0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
+                       0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
+                       0x12, 0x04, 0x74,
+               },
+               []byte{
+                       0x48, 0x65, 0x6c, 0x6c,
+               },
+               DictionaryError,
        },
 }
 
@@ -71,7 +104,7 @@ func TestDecompressor(t *testing.T) {
        b := new(bytes.Buffer)
        for _, tt := range zlibTests {
                in := bytes.NewBuffer(tt.compressed)
-               zlib, err := NewReader(in)
+               zlib, err := NewReaderDict(in, tt.dict)
                if err != nil {
                        if err != tt.err {
                                t.Errorf("%s: NewReader: %s", tt.desc, err)
index 031586c..f1f9b28 100644 (file)
@@ -21,56 +21,80 @@ const (
        DefaultCompression = flate.DefaultCompression
 )
 
-type writer struct {
+// A Writer takes data written to it and writes the compressed
+// form of that data to an underlying writer (see NewWriter).
+type Writer struct {
        w          io.Writer
-       compressor io.WriteCloser
+       compressor *flate.Writer
        digest     hash.Hash32
        err        os.Error
        scratch    [4]byte
 }
 
 // NewWriter calls NewWriterLevel with the default compression level.
-func NewWriter(w io.Writer) (io.WriteCloser, os.Error) {
+func NewWriter(w io.Writer) (*Writer, os.Error) {
        return NewWriterLevel(w, DefaultCompression)
 }
 
-// NewWriterLevel creates a new io.WriteCloser that satisfies writes by compressing data written to w.
+// NewWriterLevel calls NewWriterDict with no dictionary.
+func NewWriterLevel(w io.Writer, level int) (*Writer, os.Error) {
+       return NewWriterDict(w, level, nil)
+}
+
+// NewWriterDict creates a new io.WriteCloser that satisfies writes by compressing data written to w.
 // It is the caller's responsibility to call Close on the WriteCloser when done.
 // level is the compression level, which can be DefaultCompression, NoCompression,
 // or any integer value between BestSpeed and BestCompression (inclusive).
-func NewWriterLevel(w io.Writer, level int) (io.WriteCloser, os.Error) {
-       z := new(writer)
+// dict is the preset dictionary to compress with, or nil to use no dictionary.
+func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, os.Error) {
+       z := new(Writer)
        // ZLIB has a two-byte header (as documented in RFC 1950).
        // The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
        // The next four bits is the CM (compression method), which is 8 for deflate.
        z.scratch[0] = 0x78
        // The next two bits is the FLEVEL (compression level). The four values are:
        // 0=fastest, 1=fast, 2=default, 3=best.
-       // The next bit, FDICT, is unused, in this implementation.
+       // The next bit, FDICT, is set if a dictionary is given.
        // The final five FCHECK bits form a mod-31 checksum.
        switch level {
        case 0, 1:
-               z.scratch[1] = 0x01
+               z.scratch[1] = 0 << 6
        case 2, 3, 4, 5:
-               z.scratch[1] = 0x5e
+               z.scratch[1] = 1 << 6
        case 6, -1:
-               z.scratch[1] = 0x9c
+               z.scratch[1] = 2 << 6
        case 7, 8, 9:
-               z.scratch[1] = 0xda
+               z.scratch[1] = 3 << 6
        default:
                return nil, os.NewError("level out of range")
        }
+       if dict != nil {
+               z.scratch[1] |= 1 << 5
+       }
+       z.scratch[1] += uint8(31 - (uint16(z.scratch[0])<<8+uint16(z.scratch[1]))%31)
        _, err := w.Write(z.scratch[0:2])
        if err != nil {
                return nil, err
        }
+       if dict != nil {
+               // The next four bytes are the Adler-32 checksum of the dictionary.
+               checksum := adler32.Checksum(dict)
+               z.scratch[0] = uint8(checksum >> 24)
+               z.scratch[1] = uint8(checksum >> 16)
+               z.scratch[2] = uint8(checksum >> 8)
+               z.scratch[3] = uint8(checksum >> 0)
+               _, err = w.Write(z.scratch[0:4])
+               if err != nil {
+                       return nil, err
+               }
+       }
        z.w = w
        z.compressor = flate.NewWriter(w, level)
        z.digest = adler32.New()
        return z, nil
 }
 
-func (z *writer) Write(p []byte) (n int, err os.Error) {
+func (z *Writer) Write(p []byte) (n int, err os.Error) {
        if z.err != nil {
                return 0, z.err
        }
@@ -86,8 +110,17 @@ func (z *writer) Write(p []byte) (n int, err os.Error) {
        return
 }
 
+// Flush flushes the underlying compressor.
+func (z *Writer) Flush() os.Error {
+       if z.err != nil {
+               return z.err
+       }
+       z.err = z.compressor.Flush()
+       return z.err
+}
+
 // Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
-func (z *writer) Close() os.Error {
+func (z *Writer) Close() os.Error {
        if z.err != nil {
                return z.err
        }
index 7eb1cd4..f94f284 100644 (file)
@@ -16,13 +16,19 @@ var filenames = []string{
        "../testdata/pi.txt",
 }
 
-// Tests that compressing and then decompressing the given file at the given compression level
+// Tests that compressing and then decompressing the given file at the given compression level and dictionary
 // yields equivalent bytes to the original file.
-func testFileLevel(t *testing.T, fn string, level int) {
+func testFileLevelDict(t *testing.T, fn string, level int, d string) {
+       // Read dictionary, if given.
+       var dict []byte
+       if d != "" {
+               dict = []byte(d)
+       }
+
        // Read the file, as golden output.
        golden, err := os.Open(fn)
        if err != nil {
-               t.Errorf("%s (level=%d): %v", fn, level, err)
+               t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
                return
        }
        defer golden.Close()
@@ -30,7 +36,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
        // Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
        raw, err := os.Open(fn)
        if err != nil {
-               t.Errorf("%s (level=%d): %v", fn, level, err)
+               t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
                return
        }
        piper, pipew := io.Pipe()
@@ -38,9 +44,9 @@ func testFileLevel(t *testing.T, fn string, level int) {
        go func() {
                defer raw.Close()
                defer pipew.Close()
-               zlibw, err := NewWriterLevel(pipew, level)
+               zlibw, err := NewWriterDict(pipew, level, dict)
                if err != nil {
-                       t.Errorf("%s (level=%d): %v", fn, level, err)
+                       t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
                        return
                }
                defer zlibw.Close()
@@ -48,7 +54,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
                for {
                        n, err0 := raw.Read(b[0:])
                        if err0 != nil && err0 != os.EOF {
-                               t.Errorf("%s (level=%d): %v", fn, level, err0)
+                               t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
                                return
                        }
                        _, err1 := zlibw.Write(b[0:n])
@@ -57,7 +63,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
                                return
                        }
                        if err1 != nil {
-                               t.Errorf("%s (level=%d): %v", fn, level, err1)
+                               t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
                                return
                        }
                        if err0 == os.EOF {
@@ -65,9 +71,9 @@ func testFileLevel(t *testing.T, fn string, level int) {
                        }
                }
        }()
-       zlibr, err := NewReader(piper)
+       zlibr, err := NewReaderDict(piper, dict)
        if err != nil {
-               t.Errorf("%s (level=%d): %v", fn, level, err)
+               t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
                return
        }
        defer zlibr.Close()
@@ -76,20 +82,20 @@ func testFileLevel(t *testing.T, fn string, level int) {
        b0, err0 := ioutil.ReadAll(golden)
        b1, err1 := ioutil.ReadAll(zlibr)
        if err0 != nil {
-               t.Errorf("%s (level=%d): %v", fn, level, err0)
+               t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
                return
        }
        if err1 != nil {
-               t.Errorf("%s (level=%d): %v", fn, level, err1)
+               t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
                return
        }
        if len(b0) != len(b1) {
-               t.Errorf("%s (level=%d): length mismatch %d versus %d", fn, level, len(b0), len(b1))
+               t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1))
                return
        }
        for i := 0; i < len(b0); i++ {
                if b0[i] != b1[i] {
-                       t.Errorf("%s (level=%d): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, i, b0[i], b1[i])
+                       t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i])
                        return
                }
        }
@@ -97,10 +103,21 @@ func testFileLevel(t *testing.T, fn string, level int) {
 
 func TestWriter(t *testing.T) {
        for _, fn := range filenames {
-               testFileLevel(t, fn, DefaultCompression)
-               testFileLevel(t, fn, NoCompression)
+               testFileLevelDict(t, fn, DefaultCompression, "")
+               testFileLevelDict(t, fn, NoCompression, "")
+               for level := BestSpeed; level <= BestCompression; level++ {
+                       testFileLevelDict(t, fn, level, "")
+               }
+       }
+}
+
+func TestWriterDict(t *testing.T) {
+       const dictionary = "0123456789."
+       for _, fn := range filenames {
+               testFileLevelDict(t, fn, DefaultCompression, dictionary)
+               testFileLevelDict(t, fn, NoCompression, dictionary)
                for level := BestSpeed; level <= BestCompression; level++ {
-                       testFileLevel(t, fn, level)
+                       testFileLevelDict(t, fn, level, dictionary)
                }
        }
 }
index 4435a57..f2b8a75 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.
 
-// This package provides heap operations for any type that implements
+// Package heap provides heap operations for any type that implements
 // heap.Interface.
 //
 package heap
index 89d444d..5eb5437 100644 (file)
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package heap
+package heap_test
 
 import (
        "testing"
        "container/vector"
+       . "container/heap"
 )
 
 
index c1ebcdd..a3fd4b3 100755 (executable)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The list package implements a doubly linked list.
+// Package list implements a doubly linked list.
 //
 // To iterate over a list (where l is a *List):
 //     for e := l.Front(); e != nil; e = e.Next() {
index 5925164..cc870ce 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.
 
-// The ring package implements operations on circular lists.
+// Package ring implements operations on circular lists.
 package ring
 
 // A Ring is an element of a circular list, or ring.
index a2febb6..bfb5481 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The vector package implements containers for managing sequences
-// of elements. Vectors grow and shrink dynamically as necessary.
+// Package vector implements containers for managing sequences of elements.
+// Vectors grow and shrink dynamically as necessary.
 package vector
 
 
index 97a5b64..25acd0d 100644 (file)
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// AES constants - 8720 bytes of initialized data.
-
-// This package implements AES encryption (formerly Rijndael),
-// as defined in U.S. Federal Information Processing Standards Publication 197.
+// Package aes implements AES encryption (formerly Rijndael), as defined in
+// U.S. Federal Information Processing Standards Publication 197.
 package aes
 
+// This file contains AES constants - 8720 bytes of initialized data.
+
 // http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
 
 // AES is based on the mathematical behavior of binary polynomials
index 947f762..f3c5175 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.
 
-// This package implements Bruce Schneier's Blowfish encryption algorithm.
+// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
 package blowfish
 
 // The code is a port of Bruce Schneier's C implementation.
index 35f3e64..cb62e31 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.
 
-// This package implements CAST5, as defined in RFC 2144. CAST5 is a common
+// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
 // OpenPGP cipher.
 package cast5
 
index 50516b2..1ffaa8c 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The cipher package implements standard block cipher modes
-// that can be wrapped around low-level block cipher implementations.
+// Package cipher implements standard block cipher modes that can be wrapped
+// around low-level block cipher implementations.
 // See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
 // and NIST Special Publication 800-38A.
 package cipher
index be6b34a..53672a4 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.
 
-// The crypto package collects common cryptographic constants.
+// Package crypto collects common cryptographic constants.
 package crypto
 
 import (
index 2296e96..335c964 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The elliptic package implements several standard elliptic curves over prime
-// fields
+// Package elliptic implements several standard elliptic curves over prime
+// fields.
 package elliptic
 
 // This package operates, internally, on Jacobian coordinates. For a given
index 298fb2c..04ec86e 100644 (file)
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The hmac package implements the Keyed-Hash Message Authentication Code (HMAC)
-// as defined in U.S. Federal Information Processing Standards Publication 198.
+// Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
+// defined in U.S. Federal Information Processing Standards Publication 198.
 // An HMAC is a cryptographic hash that uses a key to sign a message.
 // The receiver verifies the hash by recomputing it using the same key.
 package hmac
index ee46544..848d955 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.
 
-// This package implements the MD4 hash algorithm as defined in RFC 1320.
+// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
 package md4
 
 import (
index 8f93fc4..378faa6 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.
 
-// This package implements the MD5 hash algorithm as defined in RFC 1321.
+// Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
 package md5
 
 import (
index f42d808..acd75b8 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.
 
-// This package parses OCSP responses as specified in RFC 2560. OCSP responses
+// 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
index 0c5ae9d..8da612c 100644 (file)
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
+// 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/error"
        "encoding/base64"
-       "encoding/line"
        "io"
        "os"
 )
@@ -63,7 +63,7 @@ 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  *line.Reader
+       in  *bufio.Reader
        buf []byte
        eof bool
        crc uint32
@@ -156,7 +156,7 @@ func (r *openpgpReader) Read(p []byte) (n int, err os.Error) {
 // given Reader is not usable after calling this function: an arbitary amount
 // of data may have been read past the end of the block.
 func Decode(in io.Reader) (p *Block, err os.Error) {
-       r := line.NewReader(in, 100)
+       r, _ := bufio.NewReaderSize(in, 100)
        var line []byte
        ignoreNext := false
 
index 0f7de02..99dee37 100644 (file)
@@ -18,9 +18,9 @@ var armorEndOfLineOut = []byte("-----\n")
 // writeSlices writes its arguments to the given Writer.
 func writeSlices(out io.Writer, slices ...[]byte) (err os.Error) {
        for _, s := range slices {
-               _, err := out.Write(s)
+               _, err = out.Write(s)
                if err != nil {
-                       return
+                       return err
                }
        }
        return
index 053d159..3759ce1 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.
 
-// This package contains common error types for the OpenPGP packages.
+// Package error contains common error types for the OpenPGP packages.
 package error
 
 import (
index ecaa86f..6c03f88 100644 (file)
@@ -5,6 +5,7 @@
 package openpgp
 
 import (
+       "crypto/openpgp/armor"
        "crypto/openpgp/error"
        "crypto/openpgp/packet"
        "io"
@@ -13,6 +14,8 @@ import (
 
 // 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,
@@ -101,37 +104,50 @@ func (el EntityList) DecryptionKeys() (keys []Key) {
 
 // ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
 func ReadArmoredKeyRing(r io.Reader) (EntityList, os.Error) {
-       body, err := readArmored(r, PublicKeyType)
+       block, err := armor.Decode(r)
+       if err == os.EOF {
+               return nil, error.InvalidArgumentError("no armored data found")
+       }
        if err != nil {
                return nil, err
        }
+       if block.Type != PublicKeyType && block.Type != PrivateKeyType {
+               return nil, error.InvalidArgumentError("expected public or private key block, got: " + block.Type)
+       }
 
-       return ReadKeyRing(body)
+       return ReadKeyRing(block.Body)
 }
 
-// ReadKeyRing reads one or more public/private keys, ignoring unsupported keys.
+// 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 os.Error) {
        packets := packet.NewReader(r)
+       var lastUnsupportedError os.Error
 
        for {
                var e *Entity
                e, err = readEntity(packets)
                if err != nil {
                        if _, ok := err.(error.UnsupportedError); ok {
+                               lastUnsupportedError = err
                                err = readToNextPublicKey(packets)
                        }
                        if err == os.EOF {
                                err = nil
-                               return
+                               break
                        }
                        if err != nil {
                                el = nil
-                               return
+                               break
                        }
                } else {
                        el = append(el, e)
                }
        }
+
+       if len(el) == 0 && err == nil {
+               err = lastUnsupportedError
+       }
        return
 }
 
@@ -197,25 +213,28 @@ EachPacket:
                        current.Name = pkt.Id
                        current.UserId = pkt
                        e.Identities[pkt.Id] = current
-                       p, err = packets.Next()
-                       if err == os.EOF {
-                               err = io.ErrUnexpectedEOF
-                       }
-                       if err != nil {
-                               if _, ok := err.(error.UnsupportedError); ok {
+
+                       for {
+                               p, err = packets.Next()
+                               if err == os.EOF {
+                                       return nil, io.ErrUnexpectedEOF
+                               } else if err != nil {
                                        return nil, err
                                }
-                               return nil, error.StructuralError("identity self-signature invalid: " + err.String())
-                       }
-                       current.SelfSignature, ok = p.(*packet.Signature)
-                       if !ok {
-                               return nil, error.StructuralError("user ID packet not followed by self signature")
-                       }
-                       if current.SelfSignature.SigType != packet.SigTypePositiveCert {
-                               return nil, error.StructuralError("user ID self-signature with wrong type")
-                       }
-                       if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, current.SelfSignature); err != nil {
-                               return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
+
+                               sig, ok := p.(*packet.Signature)
+                               if !ok {
+                                       return nil, error.StructuralError("user ID packet not followed by self-signature")
+                               }
+
+                               if sig.SigType == packet.SigTypePositiveCert && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
+                                       if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
+                                               return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
+                                       }
+                                       current.SelfSignature = sig
+                                       break
+                               }
+                               current.Signatures = append(current.Signatures, sig)
                        }
                case *packet.Signature:
                        if current == nil {
index 57ff3af..c0ec44d 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.
 
-// This package implements parsing and serialisation of OpenPGP packets, as
+// Package packet implements parsing and serialisation of OpenPGP packets, as
 // specified in RFC 4880.
 package packet
 
index 6944823..fde2a99 100644 (file)
@@ -164,8 +164,10 @@ func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err os.Error) {
        }
 
        rsaPriv.D = new(big.Int).SetBytes(d)
-       rsaPriv.P = new(big.Int).SetBytes(p)
-       rsaPriv.Q = new(big.Int).SetBytes(q)
+       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
index ebef481..cd4a9ae 100644 (file)
@@ -15,6 +15,7 @@ import (
        "hash"
        "io"
        "os"
+       "strconv"
 )
 
 // PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
@@ -47,7 +48,7 @@ func (pk *PublicKey) parse(r io.Reader) (err os.Error) {
        case PubKeyAlgoDSA:
                err = pk.parseDSA(r)
        default:
-               err = error.UnsupportedError("public key type")
+               err = error.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
        }
        if err != nil {
                return
index ac6998f..4f84dff 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.
 
-// This openpgp package implements high level operations on OpenPGP messages.
+// Package openpgp implements high level operations on OpenPGP messages.
 package openpgp
 
 import (
index 6218d99..423c85b 100644 (file)
@@ -230,6 +230,23 @@ func TestDetachedSignatureDSA(t *testing.T) {
        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.(error.InvalidArgumentError); !ok {
+               t.Errorf("error was not an InvalidArgumentError: %s", err)
+       }
+}
+
 const testKey1KeyId = 0xA34D7E18C20C31BB
 const testKey3KeyId = 0x338934250CCC0360
 
@@ -259,3 +276,37 @@ const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f7
 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-----`
index 873b33d..93b7582 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.
 
-// This package implements the various OpenPGP string-to-key transforms as
+// Package s2k implements the various OpenPGP string-to-key transforms as
 // specified in RFC 4800 section 3.7.1.
 package s2k
 
index 65fd195..7ee4710 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.
 
-// This package implements RC4 encryption, as defined in Bruce Schneier's
+// Package rc4 implements RC4 encryption, as defined in Bruce Schneier's
 // Applied Cryptography.
 package rc4
 
index 6e88521..5aaca59 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.
 
-// This package implements the RIPEMD-160 hash algorithm.
+// Package ripemd160 implements the RIPEMD-160 hash algorithm.
 package ripemd160
 
 // RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
index 9a71841..3defa62 100644 (file)
@@ -149,10 +149,10 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
 // precompute a prefix of the digest value that makes a valid ASN1 DER string
 // with the correct contents.
 var hashPrefixes = map[crypto.Hash][]byte{
-       crypto.MD5:       []byte{0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
-       crypto.SHA1:      []byte{0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
-       crypto.SHA256:    []byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
-       crypto.SHA384:    []byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
+       crypto.MD5:       {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
+       crypto.SHA1:      {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
+       crypto.SHA256:    {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
+       crypto.SHA384:    {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
        crypto.SHA512:    {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
        crypto.MD5SHA1:   {}, // A special TLS case which doesn't use an ASN1 prefix.
        crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
index 30a4824..d69bacf 100644 (file)
@@ -197,12 +197,6 @@ func TestVerifyPKCS1v15(t *testing.T) {
        }
 }
 
-func bigFromString(s string) *big.Int {
-       ret := new(big.Int)
-       ret.SetString(s, 10)
-       return ret
-}
-
 // In order to generate new test vectors you'll need the PEM form of this key:
 // -----BEGIN RSA PRIVATE KEY-----
 // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
@@ -216,10 +210,12 @@ func bigFromString(s string) *big.Int {
 
 var rsaPrivateKey = &PrivateKey{
        PublicKey: PublicKey{
-               N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
+               N: fromBase10("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
                E: 65537,
        },
-       D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
-       P: bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
-       Q: bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+       D: fromBase10("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
+       Primes: []*big.Int{
+               fromBase10("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
+               fromBase10("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+       },
 }
index b3b212c..e1813db 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.
 
-// This package implements RSA encryption as specified in PKCS#1.
+// Package rsa implements RSA encryption as specified in PKCS#1.
 package rsa
 
 // TODO(agl): Add support for PSS padding.
@@ -13,7 +13,6 @@ import (
        "hash"
        "io"
        "os"
-       "sync"
 )
 
 var bigZero = big.NewInt(0)
@@ -90,50 +89,60 @@ type PublicKey struct {
 
 // A PrivateKey represents an RSA key
 type PrivateKey struct {
-       PublicKey          // public part.
-       D         *big.Int // private exponent
-       P, Q, R   *big.Int // prime factors of N (R may be nil)
-
-       rwMutex    sync.RWMutex // protects the following
-       dP, dQ, dR *big.Int     // D mod (P-1) (or mod Q-1 etc) 
-       qInv       *big.Int     // q^-1 mod p
-       pq         *big.Int     // P*Q
-       tr         *big.Int     // pq·tr ≡ 1 mod r
+       PublicKey            // public part.
+       D         *big.Int   // private exponent
+       Primes    []*big.Int // prime factors of N, has >= 2 elements.
+
+       // Precomputed contains precomputed values that speed up private
+       // operations, if availible.
+       Precomputed PrecomputedValues
+}
+
+type PrecomputedValues struct {
+       Dp, Dq *big.Int // D mod (P-1) (or mod Q-1) 
+       Qinv   *big.Int // Q^-1 mod Q
+
+       // CRTValues is used for the 3rd and subsequent primes. Due to a
+       // historical accident, the CRT for the first two primes is handled
+       // differently in PKCS#1 and interoperability is sufficiently
+       // important that we mirror this.
+       CRTValues []CRTValue
+}
+
+// CRTValue contains the precomputed chinese remainder theorem values.
+type CRTValue struct {
+       Exp   *big.Int // D mod (prime-1).
+       Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
+       R     *big.Int // product of primes prior to this (inc p and q).
 }
 
 // Validate performs basic sanity checks on the key.
 // It returns nil if the key is valid, or else an os.Error describing a problem.
 
 func (priv *PrivateKey) Validate() os.Error {
-       // Check that p, q and, maybe, r are prime. Note that this is just a
-       // sanity check. Since the random witnesses chosen by ProbablyPrime are
-       // deterministic, given the candidate number, it's easy for an attack
-       // to generate composites that pass this test.
-       if !big.ProbablyPrime(priv.P, 20) {
-               return os.ErrorString("P is composite")
-       }
-       if !big.ProbablyPrime(priv.Q, 20) {
-               return os.ErrorString("Q is composite")
-       }
-       if priv.R != nil && !big.ProbablyPrime(priv.R, 20) {
-               return os.ErrorString("R is composite")
+       // Check that the prime factors are actually prime. Note that this is
+       // just a sanity check. Since the random witnesses chosen by
+       // ProbablyPrime are deterministic, given the candidate number, it's
+       // easy for an attack to generate composites that pass this test.
+       for _, prime := range priv.Primes {
+               if !big.ProbablyPrime(prime, 20) {
+                       return os.ErrorString("Prime factor is composite")
+               }
        }
 
-       // Check that p*q*r == n.
-       modulus := new(big.Int).Mul(priv.P, priv.Q)
-       if priv.R != nil {
-               modulus.Mul(modulus, priv.R)
+       // Check that Πprimes == n.
+       modulus := new(big.Int).Set(bigOne)
+       for _, prime := range priv.Primes {
+               modulus.Mul(modulus, prime)
        }
        if modulus.Cmp(priv.N) != 0 {
                return os.ErrorString("invalid modulus")
        }
-       // Check that e and totient(p, q, r) are coprime.
-       pminus1 := new(big.Int).Sub(priv.P, bigOne)
-       qminus1 := new(big.Int).Sub(priv.Q, bigOne)
-       totient := new(big.Int).Mul(pminus1, qminus1)
-       if priv.R != nil {
-               rminus1 := new(big.Int).Sub(priv.R, bigOne)
-               totient.Mul(totient, rminus1)
+       // Check that e and totient(Πprimes) are coprime.
+       totient := new(big.Int).Set(bigOne)
+       for _, prime := range priv.Primes {
+               pminus1 := new(big.Int).Sub(prime, bigOne)
+               totient.Mul(totient, pminus1)
        }
        e := big.NewInt(int64(priv.E))
        gcd := new(big.Int)
@@ -143,7 +152,7 @@ func (priv *PrivateKey) Validate() os.Error {
        if gcd.Cmp(bigOne) != 0 {
                return os.ErrorString("invalid public exponent E")
        }
-       // Check that de ≡ 1 (mod totient(p, q, r))
+       // Check that de ≡ 1 (mod totient(Πprimes))
        de := new(big.Int).Mul(priv.D, e)
        de.Mod(de, totient)
        if de.Cmp(bigOne) != 0 {
@@ -154,6 +163,20 @@ func (priv *PrivateKey) Validate() os.Error {
 
 // GenerateKey generates an RSA keypair of the given bit size.
 func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
+       return GenerateMultiPrimeKey(rand, 2, bits)
+}
+
+// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
+// size, as suggested in [1]. Although the public keys are compatible
+// (actually, indistinguishable) from the 2-prime case, the private keys are
+// not. Thus it may not be possible to export multi-prime private keys in
+// certain formats or to subsequently import them into other code.
+//
+// Table 1 in [2] suggests maximum numbers of primes for a given size.
+//
+// [1] US patent 4405829 (1972, expired)
+// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
+func GenerateMultiPrimeKey(rand io.Reader, nprimes int, bits int) (priv *PrivateKey, err os.Error) {
        priv = new(PrivateKey)
        // Smaller public exponents lead to faster public key
        // operations. Since the exponent must be coprime to
@@ -165,100 +188,41 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
        // [1] http://marc.info/?l=cryptography&m=115694833312008&w=2
        priv.E = 3
 
-       pminus1 := new(big.Int)
-       qminus1 := new(big.Int)
-       totient := new(big.Int)
-
-       for {
-               p, err := randomPrime(rand, bits/2)
-               if err != nil {
-                       return nil, err
-               }
-
-               q, err := randomPrime(rand, bits/2)
-               if err != nil {
-                       return nil, err
-               }
-
-               if p.Cmp(q) == 0 {
-                       continue
-               }
-
-               n := new(big.Int).Mul(p, q)
-               pminus1.Sub(p, bigOne)
-               qminus1.Sub(q, bigOne)
-               totient.Mul(pminus1, qminus1)
-
-               g := new(big.Int)
-               priv.D = new(big.Int)
-               y := new(big.Int)
-               e := big.NewInt(int64(priv.E))
-               big.GcdInt(g, priv.D, y, e, totient)
-
-               if g.Cmp(bigOne) == 0 {
-                       priv.D.Add(priv.D, totient)
-                       priv.P = p
-                       priv.Q = q
-                       priv.N = n
-
-                       break
-               }
+       if nprimes < 2 {
+               return nil, os.ErrorString("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
        }
 
-       return
-}
-
-// Generate3PrimeKey generates a 3-prime RSA keypair of the given bit size, as
-// suggested in [1]. Although the public keys are compatible (actually,
-// indistinguishable) from the 2-prime case, the private keys are not. Thus it
-// may not be possible to export 3-prime private keys in certain formats or to
-// subsequently import them into other code.
-//
-// Table 1 in [2] suggests that size should be >= 1024 when using 3 primes.
-//
-// [1] US patent 4405829 (1972, expired)
-// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
-func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
-       priv = new(PrivateKey)
-       priv.E = 3
-
-       pminus1 := new(big.Int)
-       qminus1 := new(big.Int)
-       rminus1 := new(big.Int)
-       totient := new(big.Int)
+       primes := make([]*big.Int, nprimes)
 
+NextSetOfPrimes:
        for {
-               p, err := randomPrime(rand, bits/3)
-               if err != nil {
-                       return nil, err
-               }
-
-               todo := bits - p.BitLen()
-               q, err := randomPrime(rand, todo/2)
-               if err != nil {
-                       return nil, err
+               todo := bits
+               for i := 0; i < nprimes; i++ {
+                       primes[i], err = randomPrime(rand, todo/(nprimes-i))
+                       if err != nil {
+                               return nil, err
+                       }
+                       todo -= primes[i].BitLen()
                }
 
-               todo -= q.BitLen()
-               r, err := randomPrime(rand, todo)
-               if err != nil {
-                       return nil, err
+               // Make sure that primes is pairwise unequal.
+               for i, prime := range primes {
+                       for j := 0; j < i; j++ {
+                               if prime.Cmp(primes[j]) == 0 {
+                                       continue NextSetOfPrimes
+                               }
+                       }
                }
 
-               if p.Cmp(q) == 0 ||
-                       q.Cmp(r) == 0 ||
-                       r.Cmp(p) == 0 {
-                       continue
+               n := new(big.Int).Set(bigOne)
+               totient := new(big.Int).Set(bigOne)
+               pminus1 := new(big.Int)
+               for _, prime := range primes {
+                       n.Mul(n, prime)
+                       pminus1.Sub(prime, bigOne)
+                       totient.Mul(totient, pminus1)
                }
 
-               n := new(big.Int).Mul(p, q)
-               n.Mul(n, r)
-               pminus1.Sub(p, bigOne)
-               qminus1.Sub(q, bigOne)
-               rminus1.Sub(r, bigOne)
-               totient.Mul(pminus1, qminus1)
-               totient.Mul(totient, rminus1)
-
                g := new(big.Int)
                priv.D = new(big.Int)
                y := new(big.Int)
@@ -267,15 +231,14 @@ func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error
 
                if g.Cmp(bigOne) == 0 {
                        priv.D.Add(priv.D, totient)
-                       priv.P = p
-                       priv.Q = q
-                       priv.R = r
+                       priv.Primes = primes
                        priv.N = n
 
                        break
                }
        }
 
+       priv.Precompute()
        return
 }
 
@@ -409,23 +372,34 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
        return x, true
 }
 
-// precompute performs some calculations that speed up private key operations
+// Precompute performs some calculations that speed up private key operations
 // in the future.
-func (priv *PrivateKey) precompute() {
-       priv.dP = new(big.Int).Sub(priv.P, bigOne)
-       priv.dP.Mod(priv.D, priv.dP)
+func (priv *PrivateKey) Precompute() {
+       if priv.Precomputed.Dp != nil {
+               return
+       }
 
-       priv.dQ = new(big.Int).Sub(priv.Q, bigOne)
-       priv.dQ.Mod(priv.D, priv.dQ)
+       priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
+       priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
 
-       priv.qInv = new(big.Int).ModInverse(priv.Q, priv.P)
+       priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
+       priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
 
-       if priv.R != nil {
-               priv.dR = new(big.Int).Sub(priv.R, bigOne)
-               priv.dR.Mod(priv.D, priv.dR)
+       priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
 
-               priv.pq = new(big.Int).Mul(priv.P, priv.Q)
-               priv.tr = new(big.Int).ModInverse(priv.pq, priv.R)
+       r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
+       priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
+       for i := 2; i < len(priv.Primes); i++ {
+               prime := priv.Primes[i]
+               values := &priv.Precomputed.CRTValues[i-2]
+
+               values.Exp = new(big.Int).Sub(prime, bigOne)
+               values.Exp.Mod(priv.D, values.Exp)
+
+               values.R = new(big.Int).Set(r)
+               values.Coeff = new(big.Int).ModInverse(r, prime)
+
+               r.Mul(r, prime)
        }
 }
 
@@ -463,53 +437,41 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
                }
                bigE := big.NewInt(int64(priv.E))
                rpowe := new(big.Int).Exp(r, bigE, priv.N)
-               c.Mul(c, rpowe)
-               c.Mod(c, priv.N)
-       }
-
-       priv.rwMutex.RLock()
-
-       if priv.dP == nil && priv.P != nil {
-               priv.rwMutex.RUnlock()
-               priv.rwMutex.Lock()
-               if priv.dP == nil && priv.P != nil {
-                       priv.precompute()
-               }
-               priv.rwMutex.Unlock()
-               priv.rwMutex.RLock()
+               cCopy := new(big.Int).Set(c)
+               cCopy.Mul(cCopy, rpowe)
+               cCopy.Mod(cCopy, priv.N)
+               c = cCopy
        }
 
-       if priv.dP == nil {
+       if priv.Precomputed.Dp == nil {
                m = new(big.Int).Exp(c, priv.D, priv.N)
        } else {
                // We have the precalculated values needed for the CRT.
-               m = new(big.Int).Exp(c, priv.dP, priv.P)
-               m2 := new(big.Int).Exp(c, priv.dQ, priv.Q)
+               m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
+               m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
                m.Sub(m, m2)
                if m.Sign() < 0 {
-                       m.Add(m, priv.P)
+                       m.Add(m, priv.Primes[0])
                }
-               m.Mul(m, priv.qInv)
-               m.Mod(m, priv.P)
-               m.Mul(m, priv.Q)
+               m.Mul(m, priv.Precomputed.Qinv)
+               m.Mod(m, priv.Primes[0])
+               m.Mul(m, priv.Primes[1])
                m.Add(m, m2)
 
-               if priv.dR != nil {
-                       // 3-prime CRT.
-                       m2.Exp(c, priv.dR, priv.R)
+               for i, values := range priv.Precomputed.CRTValues {
+                       prime := priv.Primes[2+i]
+                       m2.Exp(c, values.Exp, prime)
                        m2.Sub(m2, m)
-                       m2.Mul(m2, priv.tr)
-                       m2.Mod(m2, priv.R)
+                       m2.Mul(m2, values.Coeff)
+                       m2.Mod(m2, prime)
                        if m2.Sign() < 0 {
-                               m2.Add(m2, priv.R)
+                               m2.Add(m2, prime)
                        }
-                       m2.Mul(m2, priv.pq)
+                       m2.Mul(m2, values.R)
                        m.Add(m, m2)
                }
        }
 
-       priv.rwMutex.RUnlock()
-
        if ir != nil {
                // Unblind.
                m.Mul(m, ir)
index d8a936e..c36bca1 100644 (file)
@@ -30,7 +30,20 @@ func Test3PrimeKeyGeneration(t *testing.T) {
        }
 
        size := 768
-       priv, err := Generate3PrimeKey(rand.Reader, size)
+       priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size)
+       if err != nil {
+               t.Errorf("failed to generate key")
+       }
+       testKeyBasics(t, priv)
+}
+
+func Test4PrimeKeyGeneration(t *testing.T) {
+       if testing.Short() {
+               return
+       }
+
+       size := 768
+       priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size)
        if err != nil {
                t.Errorf("failed to generate key")
        }
@@ -45,6 +58,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
        pub := &priv.PublicKey
        m := big.NewInt(42)
        c := encrypt(new(big.Int), pub, m)
+
        m2, err := decrypt(nil, priv, c)
        if err != nil {
                t.Errorf("error while decrypting: %s", err)
@@ -59,7 +73,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
                t.Errorf("error while decrypting (blind): %s", err)
        }
        if m.Cmp(m3) != 0 {
-               t.Errorf("(blind) got:%v, want:%v", m3, m)
+               t.Errorf("(blind) got:%v, want:%v (%#v)", m3, m, priv)
        }
 }
 
@@ -77,10 +91,12 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
                        E: 3,
                },
                D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
-               P: fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
-               Q: fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+               Primes: []*big.Int{
+                       fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
+                       fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+               },
        }
-       priv.precompute()
+       priv.Precompute()
 
        c := fromBase10("1000")
 
@@ -99,11 +115,13 @@ func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
                        E: 3,
                },
                D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
-               P: fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
-               Q: fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
-               R: fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+               Primes: []*big.Int{
+                       fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+                       fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+                       fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+               },
        }
-       priv.precompute()
+       priv.Precompute()
 
        c := fromBase10("1000")
 
index e6aa096..788d1ff 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.
 
-// This package implements the SHA1 hash algorithm as defined in RFC 3174.
+// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
 package sha1
 
 import (
index 69b356b..a2c058d 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the SHA224 and SHA256 hash algorithms as defined in FIPS 180-2.
+// Package sha256 implements the SHA224 and SHA256 hash algorithms as defined
+// in FIPS 180-2.
 package sha256
 
 import (
index 7e9f330..78f5fe2 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package implements the SHA384 and SHA512 hash algorithms as defined in FIPS 180-2.
+// Package sha512 implements the SHA384 and SHA512 hash algorithms as defined
+// in FIPS 180-2.
 package sha512
 
 import (
index a3d70b9..57dbe9d 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.
 
-// This package implements functions that are often useful in cryptographic
+// Package subtle implements functions that are often useful in cryptographic
 // code but require careful thought to use correctly.
 package subtle
 
diff --git a/libgo/go/crypto/tls/ca_set.go b/libgo/go/crypto/tls/ca_set.go
deleted file mode 100644 (file)
index ae00ac5..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 tls
-
-import (
-       "crypto/x509"
-       "encoding/pem"
-       "strings"
-)
-
-// A CASet is a set of certificates.
-type CASet struct {
-       bySubjectKeyId map[string][]*x509.Certificate
-       byName         map[string][]*x509.Certificate
-}
-
-// NewCASet returns a new, empty CASet.
-func NewCASet() *CASet {
-       return &CASet{
-               make(map[string][]*x509.Certificate),
-               make(map[string][]*x509.Certificate),
-       }
-}
-
-func nameToKey(name *x509.Name) string {
-       return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
-}
-
-// FindVerifiedParent attempts to find the certificate in s which has signed
-// the given certificate. If no such certificate can be found or the signature
-// doesn't match, it returns nil.
-func (s *CASet) FindVerifiedParent(cert *x509.Certificate) (parent *x509.Certificate) {
-       var candidates []*x509.Certificate
-
-       if len(cert.AuthorityKeyId) > 0 {
-               candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
-       }
-       if len(candidates) == 0 {
-               candidates = s.byName[nameToKey(&cert.Issuer)]
-       }
-
-       for _, c := range candidates {
-               if cert.CheckSignatureFrom(c) == nil {
-                       return c
-               }
-       }
-
-       return nil
-}
-
-// AddCert adds a certificate to the set
-func (s *CASet) AddCert(cert *x509.Certificate) {
-       if len(cert.SubjectKeyId) > 0 {
-               keyId := string(cert.SubjectKeyId)
-               s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], cert)
-       }
-       name := nameToKey(&cert.Subject)
-       s.byName[name] = append(s.byName[name], cert)
-}
-
-// SetFromPEM attempts to parse a series of PEM encoded root certificates. It
-// appends any certificates found to s and returns true if any certificates
-// were successfully parsed. On many Linux systems, /etc/ssl/cert.pem will
-// contains the system wide set of root CAs in a format suitable for this
-// function.
-func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
-       for len(pemCerts) > 0 {
-               var block *pem.Block
-               block, pemCerts = pem.Decode(pemCerts)
-               if block == nil {
-                       break
-               }
-               if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
-                       continue
-               }
-
-               cert, err := x509.ParseCertificate(block.Bytes)
-               if err != nil {
-                       continue
-               }
-
-               s.AddCert(cert)
-               ok = true
-       }
-
-       return
-}
index c779234..0b26aae 100644 (file)
@@ -100,6 +100,8 @@ type ConnectionState struct {
 
        // the certificate chain that was presented by the other side
        PeerCertificates []*x509.Certificate
+       // the verified certificate chains built from PeerCertificates.
+       VerifiedChains [][]*x509.Certificate
 }
 
 // A Config structure is used to configure a TLS client or server. After one
@@ -122,7 +124,7 @@ type Config struct {
        // RootCAs defines the set of root certificate authorities
        // that clients use when verifying server certificates.
        // If RootCAs is nil, TLS uses the host's root CA set.
-       RootCAs *CASet
+       RootCAs *x509.CertPool
 
        // NextProtos is a list of supported, application level protocols.
        NextProtos []string
@@ -158,7 +160,7 @@ func (c *Config) time() int64 {
        return t()
 }
 
-func (c *Config) rootCAs() *CASet {
+func (c *Config) rootCAs() *x509.CertPool {
        s := c.RootCAs
        if s == nil {
                s = defaultRoots()
@@ -178,6 +180,9 @@ func (c *Config) cipherSuites() []uint16 {
 type Certificate struct {
        Certificate [][]byte
        PrivateKey  *rsa.PrivateKey
+       // OCSPStaple contains an optional OCSP response which will be served
+       // to clients that request it.
+       OCSPStaple []byte
 }
 
 // A TLS record.
@@ -221,7 +226,7 @@ var certFiles = []string{
 
 var once sync.Once
 
-func defaultRoots() *CASet {
+func defaultRoots() *x509.CertPool {
        once.Do(initDefaults)
        return varDefaultRoots
 }
@@ -236,14 +241,14 @@ func initDefaults() {
        initDefaultCipherSuites()
 }
 
-var varDefaultRoots *CASet
+var varDefaultRoots *x509.CertPool
 
 func initDefaultRoots() {
-       roots := NewCASet()
+       roots := x509.NewCertPool()
        for _, file := range certFiles {
                data, err := ioutil.ReadFile(file)
                if err == nil {
-                       roots.SetFromPEM(data)
+                       roots.AppendCertsFromPEM(data)
                        break
                }
        }
@@ -255,7 +260,7 @@ var varDefaultCipherSuites []uint16
 func initDefaultCipherSuites() {
        varDefaultCipherSuites = make([]uint16, len(cipherSuites))
        i := 0
-       for id, _ := range cipherSuites {
+       for id := range cipherSuites {
                varDefaultCipherSuites[i] = id
                i++
        }
index b94e235..48d3f72 100644 (file)
@@ -34,6 +34,9 @@ type Conn struct {
        cipherSuite       uint16
        ocspResponse      []byte // stapled OCSP response
        peerCertificates  []*x509.Certificate
+       // verifedChains contains the certificate chains that we built, as
+       // opposed to the ones presented by the server.
+       verifiedChains [][]*x509.Certificate
 
        clientProtocol         string
        clientProtocolFallback bool
@@ -765,6 +768,7 @@ func (c *Conn) ConnectionState() ConnectionState {
                state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
                state.CipherSuite = c.cipherSuite
                state.PeerCertificates = c.peerCertificates
+               state.VerifiedChains = c.verifiedChains
        }
 
        return state
index 540b25c..c758c96 100644 (file)
@@ -88,7 +88,6 @@ func (c *Conn) clientHandshake() os.Error {
        finishedHash.Write(certMsg.marshal())
 
        certs := make([]*x509.Certificate, len(certMsg.certificates))
-       chain := NewCASet()
        for i, asn1Data := range certMsg.certificates {
                cert, err := x509.ParseCertificate(asn1Data)
                if err != nil {
@@ -96,47 +95,29 @@ func (c *Conn) clientHandshake() os.Error {
                        return os.ErrorString("failed to parse certificate from server: " + err.String())
                }
                certs[i] = cert
-               chain.AddCert(cert)
        }
 
        // If we don't have a root CA set configured then anything is accepted.
        // TODO(rsc): Find certificates for OS X 10.6.
-       for cur := certs[0]; c.config.RootCAs != nil; {
-               parent := c.config.RootCAs.FindVerifiedParent(cur)
-               if parent != nil {
-                       break
+       if c.config.RootCAs != nil {
+               opts := x509.VerifyOptions{
+                       Roots:         c.config.RootCAs,
+                       CurrentTime:   c.config.time(),
+                       DNSName:       c.config.ServerName,
+                       Intermediates: x509.NewCertPool(),
                }
 
-               parent = chain.FindVerifiedParent(cur)
-               if parent == nil {
-                       c.sendAlert(alertBadCertificate)
-                       return os.ErrorString("could not find root certificate for chain")
+               for i, cert := range certs {
+                       if i == 0 {
+                               continue
+                       }
+                       opts.Intermediates.AddCert(cert)
                }
-
-               if !parent.BasicConstraintsValid || !parent.IsCA {
+               c.verifiedChains, err = certs[0].Verify(opts)
+               if err != nil {
                        c.sendAlert(alertBadCertificate)
-                       return os.ErrorString("intermediate certificate does not have CA bit set")
+                       return err
                }
-               // KeyUsage status flags are ignored. From Engineering
-               // Security, Peter Gutmann: A European government CA marked its
-               // signing certificates as being valid for encryption only, but
-               // no-one noticed. Another European CA marked its signature
-               // keys as not being valid for signatures. A different CA
-               // marked its own trusted root certificate as being invalid for
-               // certificate signing.  Another national CA distributed a
-               // certificate to be used to encrypt data for the country’s tax
-               // authority that was marked as only being usable for digital
-               // signatures but not for encryption. Yet another CA reversed
-               // the order of the bit flags in the keyUsage due to confusion
-               // over encoding endianness, essentially setting a random
-               // keyUsage in certificates that it issued. Another CA created
-               // a self-invalidating certificate by adding a certificate
-               // policy statement stipulating that the certificate had to be
-               // used strictly as specified in the keyUsage, and a keyUsage
-               // containing a flag indicating that the RSA encryption key
-               // could only be used for Diffie-Hellman key agreement.
-
-               cur = parent
        }
 
        if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
@@ -145,7 +126,7 @@ func (c *Conn) clientHandshake() os.Error {
 
        c.peerCertificates = certs
 
-       if serverHello.certStatus {
+       if serverHello.ocspStapling {
                msg, err = c.readHandshake()
                if err != nil {
                        return err
index e5e8562..6645adc 100644 (file)
@@ -306,7 +306,7 @@ type serverHelloMsg struct {
        compressionMethod uint8
        nextProtoNeg      bool
        nextProtos        []string
-       certStatus        bool
+       ocspStapling      bool
 }
 
 func (m *serverHelloMsg) marshal() []byte {
@@ -327,7 +327,7 @@ func (m *serverHelloMsg) marshal() []byte {
                nextProtoLen += len(m.nextProtos)
                extensionsLength += nextProtoLen
        }
-       if m.certStatus {
+       if m.ocspStapling {
                numExtensions++
        }
        if numExtensions > 0 {
@@ -373,7 +373,7 @@ func (m *serverHelloMsg) marshal() []byte {
                        z = z[1+l:]
                }
        }
-       if m.certStatus {
+       if m.ocspStapling {
                z[0] = byte(extensionStatusRequest >> 8)
                z[1] = byte(extensionStatusRequest)
                z = z[4:]
@@ -406,7 +406,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
 
        m.nextProtoNeg = false
        m.nextProtos = nil
-       m.certStatus = false
+       m.ocspStapling = false
 
        if len(data) == 0 {
                // ServerHello is optionally followed by extension data
@@ -450,7 +450,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
                        if length > 0 {
                                return false
                        }
-                       m.certStatus = true
+                       m.ocspStapling = true
                }
                data = data[length:]
        }
index 0b93b89..23f729d 100644 (file)
@@ -32,7 +32,7 @@ type testMessage interface {
 func TestMarshalUnmarshal(t *testing.T) {
        rand := rand.New(rand.NewSource(0))
        for i, iface := range tests {
-               ty := reflect.NewValue(iface).Type()
+               ty := reflect.ValueOf(iface).Type()
 
                n := 100
                if testing.Short() {
@@ -121,11 +121,11 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        m.ocspStapling = rand.Intn(10) > 5
        m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
        m.supportedCurves = make([]uint16, rand.Intn(5)+1)
-       for i, _ := range m.supportedCurves {
+       for i := range m.supportedCurves {
                m.supportedCurves[i] = uint16(rand.Intn(30000))
        }
 
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -146,7 +146,7 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
                }
        }
 
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -156,7 +156,7 @@ func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        for i := 0; i < numCerts; i++ {
                m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
        }
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -167,13 +167,13 @@ func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value
        for i := 0; i < numCAs; i++ {
                m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
        }
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        m := &certificateVerifyMsg{}
        m.signature = randomBytes(rand.Intn(15)+1, rand)
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
@@ -184,23 +184,23 @@ func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        } else {
                m.statusType = 42
        }
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        m := &clientKeyExchangeMsg{}
        m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        m := &finishedMsg{}
        m.verifyData = randomBytes(12, rand)
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
 
 func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
        m := &nextProtoMsg{}
        m.proto = randomString(rand.Intn(255), rand)
-       return reflect.NewValue(m)
+       return reflect.ValueOf(m)
 }
index 809c8c1..37c8d15 100644 (file)
@@ -103,6 +103,9 @@ FindCipherSuite:
                hello.nextProtoNeg = true
                hello.nextProtos = config.NextProtos
        }
+       if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
+               hello.ocspStapling = true
+       }
 
        finishedHash.Write(hello.marshal())
        c.writeRecord(recordTypeHandshake, hello.marshal())
@@ -116,6 +119,14 @@ FindCipherSuite:
        finishedHash.Write(certMsg.marshal())
        c.writeRecord(recordTypeHandshake, certMsg.marshal())
 
+       if hello.ocspStapling {
+               certStatus := new(certificateStatusMsg)
+               certStatus.statusType = statusTypeOCSP
+               certStatus.response = config.Certificates[0].OCSPStaple
+               finishedHash.Write(certStatus.marshal())
+               c.writeRecord(recordTypeHandshake, certStatus.marshal())
+       }
+
        keyAgreement := suite.ka()
 
        skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
index 6beb6a9..5a1e754 100644 (file)
@@ -188,8 +188,10 @@ var testPrivateKey = &rsa.PrivateKey{
                E: 65537,
        },
        D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
-       P: bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
-       Q: bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+       Primes: []*big.Int{
+               bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
+               bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
+       },
 }
 
 // Script of interaction with gnutls implementation.
index 7de44bb..7d0bb9f 100644 (file)
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// This package partially implements the TLS 1.1 protocol, as specified in RFC 4346.
+// Package tls partially implements the TLS 1.1 protocol, as specified in RFC
+// 4346.
 package tls
 
 import (
index 62253e7..9303f03 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.
 
-// This package implements Bruce Schneier's Twofish encryption algorithm.
+// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
 package twofish
 
 // Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
diff --git a/libgo/go/crypto/x509/cert_pool.go b/libgo/go/crypto/x509/cert_pool.go
new file mode 100644 (file)
index 0000000..c295fd9
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+import (
+       "encoding/pem"
+       "strings"
+)
+
+// Roots is a set of certificates.
+type CertPool struct {
+       bySubjectKeyId map[string][]int
+       byName         map[string][]int
+       certs          []*Certificate
+}
+
+// NewCertPool returns a new, empty CertPool.
+func NewCertPool() *CertPool {
+       return &CertPool{
+               make(map[string][]int),
+               make(map[string][]int),
+               nil,
+       }
+}
+
+func nameToKey(name *Name) string {
+       return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
+}
+
+// findVerifiedParents attempts to find certificates in s which have signed the
+// given certificate. If no such certificate can be found or the signature
+// doesn't match, it returns nil.
+func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
+       var candidates []int
+
+       if len(cert.AuthorityKeyId) > 0 {
+               candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
+       }
+       if len(candidates) == 0 {
+               candidates = s.byName[nameToKey(&cert.Issuer)]
+       }
+
+       for _, c := range candidates {
+               if cert.CheckSignatureFrom(s.certs[c]) == nil {
+                       parents = append(parents, c)
+               }
+       }
+
+       return
+}
+
+// AddCert adds a certificate to a pool.
+func (s *CertPool) AddCert(cert *Certificate) {
+       if cert == nil {
+               panic("adding nil Certificate to CertPool")
+       }
+
+       // Check that the certificate isn't being added twice.
+       for _, c := range s.certs {
+               if c.Equal(cert) {
+                       return
+               }
+       }
+
+       n := len(s.certs)
+       s.certs = append(s.certs, cert)
+
+       if len(cert.SubjectKeyId) > 0 {
+               keyId := string(cert.SubjectKeyId)
+               s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
+       }
+       name := nameToKey(&cert.Subject)
+       s.byName[name] = append(s.byName[name], n)
+}
+
+// AppendCertsFromPEM attempts to parse a series of PEM encoded root
+// certificates. It appends any certificates found to s and returns true if any
+// certificates were successfully parsed.
+//
+// On many Linux systems, /etc/ssl/cert.pem will contains the system wide set
+// of root CAs in a format suitable for this function.
+func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
+       for len(pemCerts) > 0 {
+               var block *pem.Block
+               block, pemCerts = pem.Decode(pemCerts)
+               if block == nil {
+                       break
+               }
+               if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+                       continue
+               }
+
+               cert, err := ParseCertificate(block.Bytes)
+               if err != nil {
+                       continue
+               }
+
+               s.AddCert(cert)
+               ok = true
+       }
+
+       return
+}
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
new file mode 100644 (file)
index 0000000..9145880
--- /dev/null
@@ -0,0 +1,239 @@
+// 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 x509
+
+import (
+       "os"
+       "strings"
+       "time"
+)
+
+type InvalidReason int
+
+const (
+       // NotAuthorizedToSign results when a certificate is signed by another
+       // which isn't marked as a CA certificate.
+       NotAuthorizedToSign InvalidReason = iota
+       // Expired results when a certificate has expired, based on the time
+       // given in the VerifyOptions.
+       Expired
+       // CANotAuthorizedForThisName results when an intermediate or root
+       // certificate has a name constraint which doesn't include the name
+       // being checked.
+       CANotAuthorizedForThisName
+)
+
+// CertificateInvalidError results when an odd error occurs. Users of this
+// library probably want to handle all these errors uniformly.
+type CertificateInvalidError struct {
+       Cert   *Certificate
+       Reason InvalidReason
+}
+
+func (e CertificateInvalidError) String() string {
+       switch e.Reason {
+       case NotAuthorizedToSign:
+               return "x509: certificate is not authorized to sign other other certificates"
+       case Expired:
+               return "x509: certificate has expired or is not yet valid"
+       case CANotAuthorizedForThisName:
+               return "x509: a root or intermediate certificate is not authorized to sign in this domain"
+       }
+       return "x509: unknown error"
+}
+
+// HostnameError results when the set of authorized names doesn't match the
+// requested name.
+type HostnameError struct {
+       Certificate *Certificate
+       Host        string
+}
+
+func (h HostnameError) String() string {
+       var valid string
+       c := h.Certificate
+       if len(c.DNSNames) > 0 {
+               valid = strings.Join(c.DNSNames, ", ")
+       } else {
+               valid = c.Subject.CommonName
+       }
+       return "certificate is valid for " + valid + ", not " + h.Host
+}
+
+
+// UnknownAuthorityError results when the certificate issuer is unknown
+type UnknownAuthorityError struct {
+       cert *Certificate
+}
+
+func (e UnknownAuthorityError) String() string {
+       return "x509: certificate signed by unknown authority"
+}
+
+// VerifyOptions contains parameters for Certificate.Verify. It's a structure
+// because other PKIX verification APIs have ended up needing many options.
+type VerifyOptions struct {
+       DNSName       string
+       Intermediates *CertPool
+       Roots         *CertPool
+       CurrentTime   int64 // if 0, the current system time is used.
+}
+
+const (
+       leafCertificate = iota
+       intermediateCertificate
+       rootCertificate
+)
+
+// isValid performs validity checks on the c.
+func (c *Certificate) isValid(certType int, opts *VerifyOptions) os.Error {
+       if opts.CurrentTime < c.NotBefore.Seconds() ||
+               opts.CurrentTime > c.NotAfter.Seconds() {
+               return CertificateInvalidError{c, Expired}
+       }
+
+       if len(c.PermittedDNSDomains) > 0 {
+               for _, domain := range c.PermittedDNSDomains {
+                       if opts.DNSName == domain ||
+                               (strings.HasSuffix(opts.DNSName, domain) &&
+                                       len(opts.DNSName) >= 1+len(domain) &&
+                                       opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
+                               continue
+                       }
+
+                       return CertificateInvalidError{c, CANotAuthorizedForThisName}