libgo: Update to weekly.2011-12-06.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Dec 2011 15:41:54 +0000 (15:41 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 14 Dec 2011 15:41:54 +0000 (15:41 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182338 138bc75d-0d04-0410-961f-82ee72b054a4

139 files changed:
gcc/testsuite/go.test/test/fixedbugs/bug120.go
gcc/testsuite/go.test/test/fixedbugs/bug260.go
libgo/MERGE
libgo/go/archive/tar/reader.go
libgo/go/archive/tar/reader_test.go
libgo/go/archive/tar/writer.go
libgo/go/archive/tar/writer_test.go
libgo/go/archive/zip/writer_test.go
libgo/go/compress/bzip2/bit_reader.go
libgo/go/compress/flate/deflate_test.go
libgo/go/compress/flate/flate_test.go
libgo/go/compress/flate/huffman_bit_writer.go
libgo/go/compress/flate/inflate.go
libgo/go/crypto/aes/aes_test.go
libgo/go/crypto/aes/block.go
libgo/go/crypto/hmac/hmac.go
libgo/go/crypto/md5/md5.go
libgo/go/crypto/openpgp/s2k/s2k.go
libgo/go/crypto/openpgp/write.go
libgo/go/crypto/ripemd160/ripemd160.go
libgo/go/crypto/rsa/rsa.go
libgo/go/crypto/sha1/sha1.go
libgo/go/crypto/sha256/sha256.go
libgo/go/crypto/sha512/sha512.go
libgo/go/crypto/tls/cipher_suites.go
libgo/go/crypto/tls/conn.go
libgo/go/crypto/tls/handshake_client.go
libgo/go/crypto/tls/handshake_server.go
libgo/go/crypto/tls/handshake_server_test.go
libgo/go/crypto/x509/x509.go
libgo/go/debug/dwarf/buf.go
libgo/go/debug/dwarf/const.go
libgo/go/debug/dwarf/type.go
libgo/go/debug/elf/elf.go
libgo/go/debug/macho/file_test.go
libgo/go/debug/macho/macho.go
libgo/go/debug/pe/file_test.go
libgo/go/encoding/ascii85/ascii85.go
libgo/go/encoding/asn1/asn1_test.go
libgo/go/encoding/asn1/common.go
libgo/go/encoding/base32/base32.go
libgo/go/encoding/base64/base64.go
libgo/go/encoding/git85/git.go
libgo/go/encoding/gob/encoder.go
libgo/go/encoding/gob/encoder_test.go
libgo/go/encoding/json/decode.go
libgo/go/encoding/json/decode_test.go
libgo/go/encoding/json/encode.go
libgo/go/encoding/xml/marshal.go
libgo/go/encoding/xml/marshal_test.go
libgo/go/encoding/xml/read.go
libgo/go/encoding/xml/xml.go
libgo/go/exp/norm/maketables.go
libgo/go/exp/norm/normregtest.go
libgo/go/exp/sql/convert.go
libgo/go/exp/sql/driver/types.go
libgo/go/exp/ssh/cipher.go
libgo/go/exp/ssh/client.go
libgo/go/exp/ssh/client_auth.go
libgo/go/exp/ssh/client_auth_test.go
libgo/go/exp/ssh/common_test.go
libgo/go/exp/ssh/session.go
libgo/go/exp/ssh/session_test.go
libgo/go/exp/ssh/tcpip.go
libgo/go/exp/types/gcimporter.go
libgo/go/expvar/expvar.go
libgo/go/flag/flag.go
libgo/go/fmt/doc.go
libgo/go/fmt/fmt_test.go
libgo/go/fmt/format.go
libgo/go/fmt/print.go
libgo/go/fmt/scan.go
libgo/go/go/ast/print_test.go
libgo/go/go/doc/comment.go
libgo/go/go/doc/comment_test.go
libgo/go/go/doc/headscan.go
libgo/go/go/parser/parser.go
libgo/go/go/printer/nodes.go
libgo/go/go/printer/testdata/parser.go
libgo/go/hash/hash.go
libgo/go/html/parse.go
libgo/go/html/parse_test.go
libgo/go/html/render_test.go
libgo/go/html/template/css_test.go
libgo/go/html/template/escape.go
libgo/go/html/template/escape_test.go
libgo/go/html/template/template.go
libgo/go/image/color/color.go
libgo/go/image/names.go
libgo/go/image/png/writer.go
libgo/go/math/sin.go
libgo/go/math/sincos.go
libgo/go/math/sinh.go
libgo/go/math/tan.go
libgo/go/math/tanh.go
libgo/go/net/http/cgi/child.go
libgo/go/net/http/chunked.go
libgo/go/net/http/cookie_test.go
libgo/go/net/http/fs.go
libgo/go/net/http/httputil/chunked.go
libgo/go/net/http/pprof/pprof.go
libgo/go/net/http/server.go
libgo/go/net/http/transfer.go
libgo/go/net/http/transport.go
libgo/go/net/http/transport_windows.go [deleted file]
libgo/go/net/iprawsock_posix.go
libgo/go/net/mail/message.go
libgo/go/net/mail/message_test.go
libgo/go/net/sock.go
libgo/go/net/udpsock_posix.go
libgo/go/old/template/parse.go
libgo/go/old/template/template_test.go
libgo/go/os/exec/lp_windows.go
libgo/go/path/filepath/path_test.go
libgo/go/reflect/all_test.go
libgo/go/reflect/tostring_test.go
libgo/go/regexp/syntax/prog.go
libgo/go/regexp/syntax/regexp.go
libgo/go/strconv/atob.go
libgo/go/strconv/atob_test.go
libgo/go/strconv/atof.go
libgo/go/strconv/atof_test.go
libgo/go/strconv/atoi.go
libgo/go/strconv/atoi_test.go
libgo/go/strconv/fp_test.go
libgo/go/strconv/ftoa.go
libgo/go/strconv/ftoa_test.go
libgo/go/strconv/itoa.go
libgo/go/strconv/itoa_test.go
libgo/go/strconv/quote.go
libgo/go/strconv/quote_test.go
libgo/go/text/template/multi_test.go
libgo/go/text/template/parse/node.go
libgo/go/text/template/parse/parse.go
libgo/go/text/template/parse/parse_test.go
libgo/go/text/template/template.go
libgo/go/time/time_test.go
libgo/go/unicode/graphic.go
libgo/go/websocket/hixie.go

index 2a71957..bf401bf 100644 (file)
@@ -41,16 +41,16 @@ func main() {
        ok := true
        for i := 0; i < len(tests); i++ {
                t := tests[i]
-               v := strconv.Ftoa64(t.f, 'g', -1)
+               v := strconv.FormatFloat(t.f, 'g', -1, 64)
                if v != t.out {
                        println("Bad float64 const:", t.in, "want", t.out, "got", v)
-                       x, err := strconv.Atof64(t.out)
+                       x, err := strconv.ParseFloat(t.out, 64)
                        if err != nil {
                                println("bug120: strconv.Atof64", t.out)
                                panic("fail")
                        }
-                       println("\twant exact:", strconv.Ftoa64(x, 'g', 1000))
-                       println("\tgot exact: ", strconv.Ftoa64(t.f, 'g', 1000))
+                       println("\twant exact:", strconv.FormatFloat(x, 'g', 1000, 64))
+                       println("\tgot exact: ", strconv.FormatFloat(t.f, 'g', 1000, 64))
                        ok = false
                }
        }
index 34757c7..91dc89f 100644 (file)
@@ -24,8 +24,8 @@ func main() {
        report := len(os.Args) > 1
        status := 0
        var b1 [10]T1
-       a0, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[0])[2:], 16)
-       a1, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[1])[2:], 16)
+       a0, _ := strconv.ParseUint(fmt.Sprintf("%p", &b1[0])[2:], 16, 64)
+       a1, _ := strconv.ParseUint(fmt.Sprintf("%p", &b1[1])[2:], 16, 64)
        if a1 != a0+1 {
                fmt.Println("FAIL")
                if report {
@@ -34,8 +34,8 @@ func main() {
                status = 1
        }
        var b2 [10]T2
-       a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[0])[2:], 16)
-       a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[1])[2:], 16)
+       a0, _ = strconv.ParseUint(fmt.Sprintf("%p", &b2[0])[2:], 16, 64)
+       a1, _ = strconv.ParseUint(fmt.Sprintf("%p", &b2[1])[2:], 16, 64)
        if a1 != a0+2 {
                if status == 0 {
                        fmt.Println("FAIL")
@@ -46,8 +46,8 @@ func main() {
                }
        }
        var b4 [10]T4
-       a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[0])[2:], 16)
-       a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[1])[2:], 16)
+       a0, _ = strconv.ParseUint(fmt.Sprintf("%p", &b4[0])[2:], 16, 64)
+       a1, _ = strconv.ParseUint(fmt.Sprintf("%p", &b4[1])[2:], 16, 64)
        if a1 != a0+4 {
                if status == 0 {
                        fmt.Println("FAIL")
index 9847f47..0bcb056 100644 (file)
@@ -1,4 +1,4 @@
-0beb796b4ef8
+0c39eee85b0d
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
index 76955e2..13fe270 100644 (file)
@@ -80,7 +80,7 @@ func (tr *Reader) octal(b []byte) int64 {
        for len(b) > 0 && (b[len(b)-1] == ' ' || b[len(b)-1] == '\x00') {
                b = b[0 : len(b)-1]
        }
-       x, err := strconv.Btoui64(cString(b), 8)
+       x, err := strconv.ParseUint(cString(b), 8, 64)
        if err != nil {
                tr.err = err
        }
index 5ca4212..5829d03 100644 (file)
@@ -24,7 +24,7 @@ type untarTest struct {
 var gnuTarTest = &untarTest{
        file: "testdata/gnu.tar",
        headers: []*Header{
-               &Header{
+               {
                        Name:     "small.txt",
                        Mode:     0640,
                        Uid:      73025,
@@ -35,7 +35,7 @@ var gnuTarTest = &untarTest{
                        Uname:    "dsymonds",
                        Gname:    "eng",
                },
-               &Header{
+               {
                        Name:     "small2.txt",
                        Mode:     0640,
                        Uid:      73025,
@@ -55,10 +55,10 @@ var gnuTarTest = &untarTest{
 
 var untarTests = []*untarTest{
        gnuTarTest,
-       &untarTest{
+       {
                file: "testdata/star.tar",
                headers: []*Header{
-                       &Header{
+                       {
                                Name:       "small.txt",
                                Mode:       0640,
                                Uid:        73025,
@@ -71,7 +71,7 @@ var untarTests = []*untarTest{
                                AccessTime: time.Unix(1244592783, 0),
                                ChangeTime: time.Unix(1244592783, 0),
                        },
-                       &Header{
+                       {
                                Name:       "small2.txt",
                                Mode:       0640,
                                Uid:        73025,
@@ -86,10 +86,10 @@ var untarTests = []*untarTest{
                        },
                },
        },
-       &untarTest{
+       {
                file: "testdata/v7.tar",
                headers: []*Header{
-                       &Header{
+                       {
                                Name:     "small.txt",
                                Mode:     0444,
                                Uid:      73025,
@@ -98,7 +98,7 @@ var untarTests = []*untarTest{
                                ModTime:  time.Unix(1244593104, 0),
                                Typeflag: '\x00',
                        },
-                       &Header{
+                       {
                                Name:     "small2.txt",
                                Mode:     0444,
                                Uid:      73025,
index b9310b3..d35726b 100644 (file)
@@ -79,7 +79,7 @@ func (tw *Writer) cString(b []byte, s string) {
 
 // Encode x as an octal ASCII string and write it into b with leading zeros.
 func (tw *Writer) octal(b []byte, x int64) {
-       s := strconv.Itob64(x, 8)
+       s := strconv.FormatInt(x, 8)
        // leading zeros, but leave room for a NUL.
        for len(s)+1 < len(b) {
                s = "0" + s
@@ -90,7 +90,7 @@ func (tw *Writer) octal(b []byte, x int64) {
 // Write x into b, either as octal or as binary (GNUtar/star extension).
 func (tw *Writer) numeric(b []byte, x int64) {
        // Try octal first.
-       s := strconv.Itob64(x, 8)
+       s := strconv.FormatInt(x, 8)
        if len(s) < len(b) {
                tw.octal(b, x)
                return
index 8d7ed32..0b41372 100644 (file)
@@ -29,10 +29,10 @@ var writerTests = []*writerTest{
        // tar (GNU tar) 1.26
        //   ln -s small.txt link.txt
        //   tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
-       &writerTest{
+       {
                file: "testdata/writer.tar",
                entries: []*writerTestEntry{
-                       &writerTestEntry{
+                       {
                                header: &Header{
                                        Name:     "small.txt",
                                        Mode:     0640,
@@ -46,7 +46,7 @@ var writerTests = []*writerTest{
                                },
                                contents: "Kilts",
                        },
-                       &writerTestEntry{
+                       {
                                header: &Header{
                                        Name:     "small2.txt",
                                        Mode:     0640,
@@ -60,7 +60,7 @@ var writerTests = []*writerTest{
                                },
                                contents: "Google.com\n",
                        },
-                       &writerTestEntry{
+                       {
                                header: &Header{
                                        Name:     "link.txt",
                                        Mode:     0777,
@@ -80,10 +80,10 @@ var writerTests = []*writerTest{
        // The truncated test file was produced using these commands:
        //   dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
        //   tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
-       &writerTest{
+       {
                file: "testdata/writer-big.tar",
                entries: []*writerTestEntry{
-                       &writerTestEntry{
+                       {
                                header: &Header{
                                        Name:     "tmp/16gig.txt",
                                        Mode:     0640,
index 25491dc..1188103 100644 (file)
@@ -21,12 +21,12 @@ type WriteTest struct {
 }
 
 var writeTests = []WriteTest{
-       WriteTest{
+       {
                Name:   "foo",
                Data:   []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
                Method: Store,
        },
-       WriteTest{
+       {
                Name:   "bar",
                Data:   nil, // large data set in the test
                Method: Deflate,
index b2c13e5..b35c69a 100644 (file)
@@ -20,7 +20,7 @@ type bitReader struct {
        err  error
 }
 
-// bitReader needs to read bytes from an io.Reader. We attempt to cast the
+// bitReader needs to read bytes from an io.Reader. We attempt to convert the
 // given io.Reader to this interface and, if it doesn't already fit, we wrap in
 // a bufio.Reader.
 type byteReader interface {
index db2d71d..b4876b0 100644 (file)
@@ -30,44 +30,44 @@ type reverseBitsTest struct {
 }
 
 var deflateTests = []*deflateTest{
-       &deflateTest{[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
-
-       &deflateTest{[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
+       {[]byte{}, 0, []byte{1, 0, 0, 255, 255}},
+       {[]byte{0x11}, -1, []byte{18, 4, 4, 0, 0, 255, 255}},
+       {[]byte{0x11}, DefaultCompression, []byte{18, 4, 4, 0, 0, 255, 255}},
+       {[]byte{0x11}, 4, []byte{18, 4, 4, 0, 0, 255, 255}},
+
+       {[]byte{0x11}, 0, []byte{0, 1, 0, 254, 255, 17, 1, 0, 0, 255, 255}},
+       {[]byte{0x11, 0x12}, 0, []byte{0, 2, 0, 253, 255, 17, 18, 1, 0, 0, 255, 255}},
+       {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 0,
                []byte{0, 8, 0, 247, 255, 17, 17, 17, 17, 17, 17, 17, 17, 1, 0, 0, 255, 255},
        },
-       &deflateTest{[]byte{}, 1, []byte{1, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
-       &deflateTest{[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
-       &deflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
+       {[]byte{}, 1, []byte{1, 0, 0, 255, 255}},
+       {[]byte{0x11}, 1, []byte{18, 4, 4, 0, 0, 255, 255}},
+       {[]byte{0x11, 0x12}, 1, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
+       {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 1, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
+       {[]byte{}, 9, []byte{1, 0, 0, 255, 255}},
+       {[]byte{0x11}, 9, []byte{18, 4, 4, 0, 0, 255, 255}},
+       {[]byte{0x11, 0x12}, 9, []byte{18, 20, 2, 4, 0, 0, 255, 255}},
+       {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, 9, []byte{18, 132, 2, 64, 0, 0, 0, 255, 255}},
 }
 
 var deflateInflateTests = []*deflateInflateTest{
-       &deflateInflateTest{[]byte{}},
-       &deflateInflateTest{[]byte{0x11}},
-       &deflateInflateTest{[]byte{0x11, 0x12}},
-       &deflateInflateTest{[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
-       &deflateInflateTest{[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
-       &deflateInflateTest{largeDataChunk()},
+       {[]byte{}},
+       {[]byte{0x11}},
+       {[]byte{0x11, 0x12}},
+       {[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}},
+       {[]byte{0x11, 0x10, 0x13, 0x41, 0x21, 0x21, 0x41, 0x13, 0x87, 0x78, 0x13}},
+       {largeDataChunk()},
 }
 
 var reverseBitsTests = []*reverseBitsTest{
-       &reverseBitsTest{1, 1, 1},
-       &reverseBitsTest{1, 2, 2},
-       &reverseBitsTest{1, 3, 4},
-       &reverseBitsTest{1, 4, 8},
-       &reverseBitsTest{1, 5, 16},
-       &reverseBitsTest{17, 5, 17},
-       &reverseBitsTest{257, 9, 257},
-       &reverseBitsTest{29, 5, 23},
+       {1, 1, 1},
+       {1, 2, 2},
+       {1, 3, 4},
+       {1, 4, 8},
+       {1, 5, 16},
+       {17, 5, 17},
+       {257, 9, 257},
+       {29, 5, 23},
 }
 
 func largeDataChunk() []byte {
index bfd3b83..94efc90 100644 (file)
@@ -52,7 +52,7 @@ type InitDecoderTest struct {
 
 var initDecoderTests = []*InitDecoderTest{
        // Example from Connell 1973,
-       &InitDecoderTest{
+       {
                []int{3, 5, 2, 4, 3, 5, 5, 4, 4, 3, 4, 5},
                huffmanDecoder{
                        2, 5,
@@ -68,7 +68,7 @@ var initDecoderTests = []*InitDecoderTest{
        },
 
        // Example from RFC 1951 section 3.2.2
-       &InitDecoderTest{
+       {
                []int{2, 1, 3, 3},
                huffmanDecoder{
                        1, 3,
@@ -80,7 +80,7 @@ var initDecoderTests = []*InitDecoderTest{
        },
 
        // Second example from RFC 1951 section 3.2.2
-       &InitDecoderTest{
+       {
                []int{3, 3, 3, 3, 3, 2, 4, 4},
                huffmanDecoder{
                        2, 4,
@@ -92,21 +92,21 @@ var initDecoderTests = []*InitDecoderTest{
        },
 
        // Static Huffman codes (RFC 1951 section 3.2.6)
-       &InitDecoderTest{
+       {
                fixedHuffmanBits[0:],
                fixedHuffmanDecoder,
                true,
        },
 
        // Illegal input.
-       &InitDecoderTest{
+       {
                []int{},
                huffmanDecoder{},
                false,
        },
 
        // Illegal input.
-       &InitDecoderTest{
+       {
                []int{0, 0, 0, 0, 0, 0, 0},
                huffmanDecoder{},
                false,
index efd99c6..8d0b4f9 100644 (file)
@@ -106,8 +106,8 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
 }
 
 func (err WrongValueError) Error() string {
-       return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.Itoa64(int64(err.from)) + ";" +
-               strconv.Itoa64(int64(err.to)) + "] but actual value is " + strconv.Itoa64(int64(err.value))
+       return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.FormatInt(int64(err.from), 10) + ";" +
+               strconv.FormatInt(int64(err.to), 10) + "] but actual value is " + strconv.FormatInt(int64(err.value), 10)
 }
 
 func (w *huffmanBitWriter) flushBits() {
index 3f0c948..3f2042b 100644 (file)
@@ -25,7 +25,7 @@ const (
 type CorruptInputError int64
 
 func (e CorruptInputError) Error() string {
-       return "flate: corrupt input before offset " + strconv.Itoa64(int64(e))
+       return "flate: corrupt input before offset " + strconv.FormatInt(int64(e), 10)
 }
 
 // An InternalError reports an error in the flate code itself.
@@ -40,7 +40,7 @@ type ReadError struct {
 }
 
 func (e *ReadError) Error() string {
-       return "flate: read error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Err.Error()
+       return "flate: read error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
 }
 
 // A WriteError reports an error encountered while writing output.
@@ -50,7 +50,7 @@ type WriteError struct {
 }
 
 func (e *WriteError) Error() string {
-       return "flate: write error at offset " + strconv.Itoa64(e.Offset) + ": " + e.Err.Error()
+       return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
 }
 
 // Huffman decoder is based on
index 2136d44..3505d33 100644 (file)
@@ -348,3 +348,17 @@ func TestCipherDecrypt(t *testing.T) {
                }
        }
 }
+
+func BenchmarkEncrypt(b *testing.B) {
+       b.StopTimer()
+       tt := encryptTests[0]
+       c, err := NewCipher(tt.key)
+       if err != nil {
+               panic("NewCipher")
+       }
+       out := make([]byte, len(tt.in))
+       b.StartTimer()
+       for i := 0; i < b.N; i++ {
+               c.Encrypt(out, tt.in)
+       }
+}
index 130cd01..37b0dd0 100644 (file)
@@ -56,10 +56,10 @@ func encryptBlock(xk []uint32, dst, src []byte) {
        nr := len(xk)/4 - 2 // - 2: one above, one more below
        k := 4
        for r := 0; r < nr; r++ {
-               t0 = xk[k+0] ^ te[0][s0>>24] ^ te[1][s1>>16&0xff] ^ te[2][s2>>8&0xff] ^ te[3][s3&0xff]
-               t1 = xk[k+1] ^ te[0][s1>>24] ^ te[1][s2>>16&0xff] ^ te[2][s3>>8&0xff] ^ te[3][s0&0xff]
-               t2 = xk[k+2] ^ te[0][s2>>24] ^ te[1][s3>>16&0xff] ^ te[2][s0>>8&0xff] ^ te[3][s1&0xff]
-               t3 = xk[k+3] ^ te[0][s3>>24] ^ te[1][s0>>16&0xff] ^ te[2][s1>>8&0xff] ^ te[3][s2&0xff]
+               t0 = xk[k+0] ^ te[0][uint8(s0>>24)] ^ te[1][uint8(s1>>16)] ^ te[2][uint8(s2>>8)] ^ te[3][uint8(s3)]
+               t1 = xk[k+1] ^ te[0][uint8(s1>>24)] ^ te[1][uint8(s2>>16)] ^ te[2][uint8(s3>>8)] ^ te[3][uint8(s0)]
+               t2 = xk[k+2] ^ te[0][uint8(s2>>24)] ^ te[1][uint8(s3>>16)] ^ te[2][uint8(s0>>8)] ^ te[3][uint8(s1)]
+               t3 = xk[k+3] ^ te[0][uint8(s3>>24)] ^ te[1][uint8(s0>>16)] ^ te[2][uint8(s1>>8)] ^ te[3][uint8(s2)]
                k += 4
                s0, s1, s2, s3 = t0, t1, t2, t3
        }
@@ -101,10 +101,10 @@ func decryptBlock(xk []uint32, dst, src []byte) {
        nr := len(xk)/4 - 2 // - 2: one above, one more below
        k := 4
        for r := 0; r < nr; r++ {
-               t0 = xk[k+0] ^ td[0][s0>>24] ^ td[1][s3>>16&0xff] ^ td[2][s2>>8&0xff] ^ td[3][s1&0xff]
-               t1 = xk[k+1] ^ td[0][s1>>24] ^ td[1][s0>>16&0xff] ^ td[2][s3>>8&0xff] ^ td[3][s2&0xff]
-               t2 = xk[k+2] ^ td[0][s2>>24] ^ td[1][s1>>16&0xff] ^ td[2][s0>>8&0xff] ^ td[3][s3&0xff]
-               t3 = xk[k+3] ^ td[0][s3>>24] ^ td[1][s2>>16&0xff] ^ td[2][s1>>8&0xff] ^ td[3][s0&0xff]
+               t0 = xk[k+0] ^ td[0][uint8(s0>>24)] ^ td[1][uint8(s3>>16)] ^ td[2][uint8(s2>>8)] ^ td[3][uint8(s1)]
+               t1 = xk[k+1] ^ td[0][uint8(s1>>24)] ^ td[1][uint8(s0>>16)] ^ td[2][uint8(s3>>8)] ^ td[3][uint8(s2)]
+               t2 = xk[k+2] ^ td[0][uint8(s2>>24)] ^ td[1][uint8(s1>>16)] ^ td[2][uint8(s0>>8)] ^ td[3][uint8(s3)]
+               t3 = xk[k+3] ^ td[0][uint8(s3>>24)] ^ td[1][uint8(s2>>16)] ^ td[2][uint8(s1>>8)] ^ td[3][uint8(s0)]
                k += 4
                s0, s1, s2, s3 = t0, t1, t2, t3
        }
index deaceaf..6e7dd87 100644 (file)
@@ -49,14 +49,13 @@ func (h *hmac) tmpPad(xor byte) {
 }
 
 func (h *hmac) Sum(in []byte) []byte {
-       sum := h.inner.Sum(nil)
+       origLen := len(in)
+       in = h.inner.Sum(in)
        h.tmpPad(0x5c)
-       for i, b := range sum {
-               h.tmp[padSize+i] = b
-       }
+       copy(h.tmp[padSize:], in[origLen:])
        h.outer.Reset()
        h.outer.Write(h.tmp)
-       return h.outer.Sum(in)
+       return h.outer.Sum(in[:origLen])
 }
 
 func (h *hmac) Write(p []byte) (n int, err error) {
index 182cfb8..f4e7b09 100644 (file)
@@ -79,8 +79,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 
 func (d0 *digest) Sum(in []byte) []byte {
        // Make a copy of d0 so that caller can keep writing and summing.
-       d := new(digest)
-       *d = *d0
+       d := *d0
 
        // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
        len := d.len
@@ -103,11 +102,13 @@ func (d0 *digest) Sum(in []byte) []byte {
                panic("d.nx != 0")
        }
 
-       for _, s := range d.s {
-               in = append(in, byte(s>>0))
-               in = append(in, byte(s>>8))
-               in = append(in, byte(s>>16))
-               in = append(in, byte(s>>24))
+       var digest [Size]byte
+       for i, s := range d.s {
+               digest[i*4] = byte(s)
+               digest[i*4+1] = byte(s >> 8)
+               digest[i*4+2] = byte(s >> 16)
+               digest[i*4+3] = byte(s >> 24)
        }
-       return in
+
+       return append(in, digest[:]...)
 }
index 83673e1..8bc0bb3 100644 (file)
@@ -26,6 +26,7 @@ var zero [1]byte
 // 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
 func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
        done := 0
+       var digest []byte
 
        for i := 0; done < len(out); i++ {
                h.Reset()
@@ -34,7 +35,8 @@ func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
                }
                h.Write(salt)
                h.Write(in)
-               n := copy(out[done:], h.Sum(nil))
+               digest = h.Sum(digest[:0])
+               n := copy(out[done:], digest)
                done += n
        }
 }
@@ -52,6 +54,7 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
        }
 
        done := 0
+       var digest []byte
        for i := 0; done < len(out); i++ {
                h.Reset()
                for j := 0; j < i; j++ {
@@ -68,7 +71,8 @@ func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
                                written += len(combined)
                        }
                }
-               n := copy(out[done:], h.Sum(nil))
+               digest = h.Sum(digest[:0])
+               n := copy(out[done:], digest)
                done += n
        }
 }
index 60dae01..bdee57d 100644 (file)
@@ -183,7 +183,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
        for i := range to {
                encryptKeys[i] = to[i].encryptionKey()
                if encryptKeys[i].PublicKey == nil {
-                       return nil, error_.InvalidArgumentError("cannot encrypt a message to key id " + strconv.Uitob64(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
+                       return nil, error_.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
                }
 
                sig := to[i].primaryIdentity().SelfSignature
index c128ee4..cd2cc39 100644 (file)
@@ -83,8 +83,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 
 func (d0 *digest) Sum(in []byte) []byte {
        // Make a copy of d0 so that caller can keep writing and summing.
-       d := new(digest)
-       *d = *d0
+       d := *d0
 
        // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
        tc := d.tc
@@ -107,11 +106,13 @@ func (d0 *digest) Sum(in []byte) []byte {
                panic("d.nx != 0")
        }
 
-       for _, s := range d.s {
-               in = append(in, byte(s))
-               in = append(in, byte(s>>8))
-               in = append(in, byte(s>>16))
-               in = append(in, byte(s>>24))
+       var digest [Size]byte
+       for i, s := range d.s {
+               digest[i*4] = byte(s)
+               digest[i*4+1] = byte(s >> 8)
+               digest[i*4+2] = byte(s >> 16)
+               digest[i*4+3] = byte(s >> 24)
        }
-       return in
+
+       return append(in, digest[:]...)
 }
index f74525c..c07e8f9 100644 (file)
@@ -189,12 +189,13 @@ func incCounter(c *[4]byte) {
 // specified in PKCS#1 v2.1.
 func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
        var counter [4]byte
+       var digest []byte
 
        done := 0
        for done < len(out) {
                hash.Write(seed)
                hash.Write(counter[0:4])
-               digest := hash.Sum(nil)
+               digest = hash.Sum(digest[:0])
                hash.Reset()
 
                for i := 0; i < len(digest) && done < len(out); i++ {
index f41cdb5..7bb68bb 100644 (file)
@@ -81,8 +81,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 
 func (d0 *digest) Sum(in []byte) []byte {
        // Make a copy of d0 so that caller can keep writing and summing.
-       d := new(digest)
-       *d = *d0
+       d := *d0
 
        // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
        len := d.len
@@ -105,11 +104,13 @@ func (d0 *digest) Sum(in []byte) []byte {
                panic("d.nx != 0")
        }
 
-       for _, s := range d.h {
-               in = append(in, byte(s>>24))
-               in = append(in, byte(s>>16))
-               in = append(in, byte(s>>8))
-               in = append(in, byte(s))
+       var digest [Size]byte
+       for i, s := range d.h {
+               digest[i*4] = byte(s >> 24)
+               digest[i*4+1] = byte(s >> 16)
+               digest[i*4+2] = byte(s >> 8)
+               digest[i*4+3] = byte(s)
        }
-       return in
+
+       return append(in, digest[:]...)
 }
index 34861f6..4525541 100644 (file)
@@ -125,8 +125,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 
 func (d0 *digest) Sum(in []byte) []byte {
        // Make a copy of d0 so that caller can keep writing and summing.
-       d := new(digest)
-       *d = *d0
+       d := *d0
 
        // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
        len := d.len
@@ -150,14 +149,19 @@ func (d0 *digest) Sum(in []byte) []byte {
        }
 
        h := d.h[:]
+       size := Size
        if d.is224 {
                h = d.h[:7]
+               size = Size224
        }
-       for _, s := range h {
-               in = append(in, byte(s>>24))
-               in = append(in, byte(s>>16))
-               in = append(in, byte(s>>8))
-               in = append(in, byte(s))
+
+       var digest [Size]byte
+       for i, s := range h {
+               digest[i*4] = byte(s >> 24)
+               digest[i*4+1] = byte(s >> 16)
+               digest[i*4+2] = byte(s >> 8)
+               digest[i*4+3] = byte(s)
        }
-       return in
+
+       return append(in, digest[:size]...)
 }
index 3cf65cb..927f28a 100644 (file)
@@ -150,18 +150,23 @@ func (d0 *digest) Sum(in []byte) []byte {
        }
 
        h := d.h[:]
+       size := Size
        if d.is384 {
                h = d.h[:6]
+               size = Size384
        }
-       for _, s := range h {
-               in = append(in, byte(s>>56))
-               in = append(in, byte(s>>48))
-               in = append(in, byte(s>>40))
-               in = append(in, byte(s>>32))
-               in = append(in, byte(s>>24))
-               in = append(in, byte(s>>16))
-               in = append(in, byte(s>>8))
-               in = append(in, byte(s))
+
+       var digest [Size]byte
+       for i, s := range h {
+               digest[i*8] = byte(s >> 56)
+               digest[i*8+1] = byte(s >> 48)
+               digest[i*8+2] = byte(s >> 40)
+               digest[i*8+3] = byte(s >> 32)
+               digest[i*8+4] = byte(s >> 24)
+               digest[i*8+5] = byte(s >> 16)
+               digest[i*8+6] = byte(s >> 8)
+               digest[i*8+7] = byte(s)
        }
-       return in
+
+       return append(in, digest[:size]...)
 }
index c0e8656..914491d 100644 (file)
@@ -52,12 +52,12 @@ type cipherSuite struct {
 }
 
 var cipherSuites = []*cipherSuite{
-       &cipherSuite{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
-       &cipherSuite{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
-       &cipherSuite{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
-       &cipherSuite{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
-       &cipherSuite{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
-       &cipherSuite{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
+       {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
+       {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
+       {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
+       {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
+       {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
+       {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
 }
 
 func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -96,7 +96,7 @@ func macSHA1(version uint16, key []byte) macFunction {
 
 type macFunction interface {
        Size() int
-       MAC(seq, data []byte) []byte
+       MAC(digestBuf, seq, data []byte) []byte
 }
 
 // ssl30MAC implements the SSLv3 MAC function, as defined in
@@ -114,7 +114,7 @@ var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0
 
 var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
 
-func (s ssl30MAC) MAC(seq, record []byte) []byte {
+func (s ssl30MAC) MAC(digestBuf, seq, record []byte) []byte {
        padLength := 48
        if s.h.Size() == 20 {
                padLength = 40
@@ -127,13 +127,13 @@ func (s ssl30MAC) MAC(seq, record []byte) []byte {
        s.h.Write(record[:1])
        s.h.Write(record[3:5])
        s.h.Write(record[recordHeaderLen:])
-       digest := s.h.Sum(nil)
+       digestBuf = s.h.Sum(digestBuf[:0])
 
        s.h.Reset()
        s.h.Write(s.key)
        s.h.Write(ssl30Pad2[:padLength])
-       s.h.Write(digest)
-       return s.h.Sum(nil)
+       s.h.Write(digestBuf)
+       return s.h.Sum(digestBuf[:0])
 }
 
 // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
@@ -145,11 +145,11 @@ func (s tls10MAC) Size() int {
        return s.h.Size()
 }
 
-func (s tls10MAC) MAC(seq, record []byte) []byte {
+func (s tls10MAC) MAC(digestBuf, seq, record []byte) []byte {
        s.h.Reset()
        s.h.Write(seq)
        s.h.Write(record)
-       return s.h.Sum(nil)
+       return s.h.Sum(digestBuf[:0])
 }
 
 func rsaKA() keyAgreement {
index b8fa273..6a03fa8 100644 (file)
@@ -118,6 +118,9 @@ type halfConn struct {
 
        nextCipher interface{} // next encryption state
        nextMac    macFunction // next MAC algorithm
+
+       // used to save allocating a new buffer for each MAC.
+       inDigestBuf, outDigestBuf []byte
 }
 
 // prepareCipherSpec sets the encryption and MAC states
@@ -280,12 +283,13 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
                b.data[4] = byte(n)
                b.resize(recordHeaderLen + n)
                remoteMAC := payload[n:]
-               localMAC := hc.mac.MAC(hc.seq[0:], b.data)
+               localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data)
                hc.incSeq()
 
                if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
                        return false, alertBadRecordMAC
                }
+               hc.inDigestBuf = localMAC
        }
 
        return true, 0
@@ -312,12 +316,13 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
 func (hc *halfConn) encrypt(b *block) (bool, alert) {
        // mac
        if hc.mac != nil {
-               mac := hc.mac.MAC(hc.seq[0:], b.data)
+               mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data)
                hc.incSeq()
 
                n := len(b.data)
                b.resize(n + len(mac))
                copy(b.data[n:], mac)
+               hc.outDigestBuf = mac
        }
 
        payload := b.data[recordHeaderLen:]
index b4337f2..e39e59c 100644 (file)
@@ -231,10 +231,10 @@ func (c *Conn) clientHandshake() error {
 
        if cert != nil {
                certVerify := new(certificateVerifyMsg)
-               var digest [36]byte
-               copy(digest[0:16], finishedHash.serverMD5.Sum(nil))
-               copy(digest[16:36], finishedHash.serverSHA1.Sum(nil))
-               signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest[0:])
+               digest := make([]byte, 0, 36)
+               digest = finishedHash.serverMD5.Sum(digest)
+               digest = finishedHash.serverSHA1.Sum(digest)
+               signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest)
                if err != nil {
                        return c.sendAlert(alertInternalError)
                }
index bbb23c0..89c000d 100644 (file)
@@ -234,9 +234,9 @@ FindCipherSuite:
                        return c.sendAlert(alertUnexpectedMessage)
                }
 
-               digest := make([]byte, 36)
-               copy(digest[0:16], finishedHash.serverMD5.Sum(nil))
-               copy(digest[16:36], finishedHash.serverSHA1.Sum(nil))
+               digest := make([]byte, 0, 36)
+               digest = finishedHash.serverMD5.Sum(digest)
+               digest = finishedHash.serverSHA1.Sum(digest)
                err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
                if err != nil {
                        c.sendAlert(alertBadCertificate)
index e00c32c..d98e13d 100644 (file)
@@ -159,7 +159,7 @@ func TestHandshakeServerSSLv3(t *testing.T) {
 
 var serve = flag.Bool("serve", false, "run a TLS server on :10443")
 var testCipherSuites = flag.String("ciphersuites",
-       "0x"+strconv.Itob(int(TLS_RSA_WITH_RC4_128_SHA), 16),
+       "0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
        "cipher suites to accept in serving mode")
 
 func TestRunServer(t *testing.T) {
@@ -170,7 +170,7 @@ func TestRunServer(t *testing.T) {
        suites := strings.Split(*testCipherSuites, ",")
        testConfig.CipherSuites = make([]uint16, len(suites))
        for i := range suites {
-               suite, err := strconv.Btoui64(suites[i], 0)
+               suite, err := strconv.ParseUint(suites[i], 0, 64)
                if err != nil {
                        panic(err)
                }
index 7e6b5c9..65ca315 100644 (file)
@@ -927,10 +927,15 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
                return
        }
 
-       asn1Issuer, err := asn1.Marshal(parent.Subject.ToRDNSequence())
-       if err != nil {
-               return
+       var asn1Issuer []byte
+       if len(parent.RawSubject) > 0 {
+               asn1Issuer = parent.RawSubject
+       } else {
+               if asn1Issuer, err = asn1.Marshal(parent.Subject.ToRDNSequence()); err != nil {
+                       return
+               }
        }
+
        asn1Subject, err := asn1.Marshal(template.Subject.ToRDNSequence())
        if err != nil {
                return
index 6b4af7d..6dc28d2 100644 (file)
@@ -149,5 +149,5 @@ type DecodeError struct {
 }
 
 func (e DecodeError) Error() string {
-       return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.Itob64(int64(e.Offset), 16) + ": " + e.Err
+       return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err
 }
index 1a3fec1..918b153 100644 (file)
@@ -178,7 +178,7 @@ func (a Attr) GoString() string {
                        return "dwarf.Attr" + s
                }
        }
-       return "dwarf.Attr(" + strconv.Itoa64(int64(a)) + ")"
+       return "dwarf.Attr(" + strconv.FormatInt(int64(a), 10) + ")"
 }
 
 // A format is a DWARF data encoding format.
@@ -347,7 +347,7 @@ func (t Tag) GoString() string {
                        return "dwarf.Tag" + s
                }
        }
-       return "dwarf.Tag(" + strconv.Itoa64(int64(t)) + ")"
+       return "dwarf.Tag(" + strconv.FormatInt(int64(t), 10) + ")"
 }
 
 // Location expression operators.
index e8ce8d5..9be6665 100644 (file)
@@ -110,7 +110,7 @@ type ArrayType struct {
 }
 
 func (t *ArrayType) String() string {
-       return "[" + strconv.Itoa64(t.Count) + "]" + t.Type.String()
+       return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String()
 }
 
 func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() }
@@ -171,10 +171,10 @@ func (t *StructType) Defn() string {
                        s += "; "
                }
                s += f.Name + " " + f.Type.String()
-               s += "@" + strconv.Itoa64(f.ByteOffset)
+               s += "@" + strconv.FormatInt(f.ByteOffset, 10)
                if f.BitSize > 0 {
-                       s += " : " + strconv.Itoa64(f.BitSize)
-                       s += "@" + strconv.Itoa64(f.BitOffset)
+                       s += " : " + strconv.FormatInt(f.BitSize, 10)
+                       s += "@" + strconv.FormatInt(f.BitOffset, 10)
                }
        }
        s += "}"
@@ -206,7 +206,7 @@ func (t *EnumType) String() string {
                if i > 0 {
                        s += "; "
                }
-               s += v.Name + "=" + strconv.Itoa64(v.Val)
+               s += v.Name + "=" + strconv.FormatInt(v.Val, 10)
        }
        s += "}"
        return s
index c71b230..03e42b0 100644 (file)
@@ -1490,11 +1490,11 @@ func stringName(i uint32, names []intName, goSyntax bool) string {
                        if goSyntax {
                                s = "elf." + s
                        }
-                       return s + "+" + strconv.Uitoa64(uint64(i-n.i))
+                       return s + "+" + strconv.FormatUint(uint64(i-n.i), 10)
                }
        }
 
-       return strconv.Uitoa64(uint64(i))
+       return strconv.FormatUint(uint64(i), 10)
 }
 
 func flagName(i uint32, names []intName, goSyntax bool) string {
@@ -1512,10 +1512,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string {
                }
        }
        if len(s) == 0 {
-               return "0x" + strconv.Uitob64(uint64(i), 16)
+               return "0x" + strconv.FormatUint(uint64(i), 16)
        }
        if i != 0 {
-               s += "+0x" + strconv.Uitob64(uint64(i), 16)
+               s += "+0x" + strconv.FormatUint(uint64(i), 16)
        }
        return s
 }
index 56d8a20..640225b 100644 (file)
@@ -21,11 +21,11 @@ var fileTests = []fileTest{
                "testdata/gcc-386-darwin-exec",
                FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85},
                []*SegmentHeader{
-                       &SegmentHeader{LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
-                       &SegmentHeader{LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0},
-                       &SegmentHeader{LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0},
-                       &SegmentHeader{LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0},
-                       &SegmentHeader{LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0},
+                       {LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+                       {LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0},
+                       {LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0},
+                       {LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0},
+                       {LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0},
                        nil,
                        nil,
                        nil,
@@ -35,21 +35,21 @@ var fileTests = []fileTest{
                        nil,
                },
                []*SectionHeader{
-                       &SectionHeader{"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400},
-                       &SectionHeader{"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2},
-                       &SectionHeader{"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
+                       {"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400},
+                       {"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2},
+                       {"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0},
+                       {"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0},
+                       {"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
                },
        },
        {
                "testdata/gcc-amd64-darwin-exec",
                FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85},
                []*SegmentHeader{
-                       &SegmentHeader{LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
-                       &SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0},
-                       &SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0},
-                       &SegmentHeader{LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0},
+                       {LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+                       {LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0},
+                       {LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0},
+                       {LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0},
                        nil,
                        nil,
                        nil,
@@ -59,14 +59,14 @@ var fileTests = []fileTest{
                        nil,
                },
                []*SectionHeader{
-                       &SectionHeader{"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400},
-                       &SectionHeader{"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408},
-                       &SectionHeader{"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2},
-                       &SectionHeader{"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b},
-                       &SectionHeader{"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
+                       {"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400},
+                       {"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408},
+                       {"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0},
+                       {"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2},
+                       {"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b},
+                       {"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0},
+                       {"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0},
+                       {"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
                },
        },
        {
@@ -74,26 +74,26 @@ var fileTests = []fileTest{
                FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0},
                []*SegmentHeader{
                        nil,
-                       &SegmentHeader{LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0},
-                       &SegmentHeader{LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0},
-                       &SegmentHeader{LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0},
+                       {LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0},
+                       {LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0},
+                       {LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0},
                },
                []*SectionHeader{
-                       &SectionHeader{"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400},
-                       &SectionHeader{"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408},
-                       &SectionHeader{"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
-                       &SectionHeader{"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b},
-                       &SectionHeader{"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7},
-                       &SectionHeader{"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0},
-                       &SectionHeader{"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
+                       {"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400},
+                       {"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408},
+                       {"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0},
+                       {"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
+                       {"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b},
+                       {"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
+                       {"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0},
+                       {"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7},
+                       {"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0},
+                       {"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0},
+                       {"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0},
+                       {"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0},
+                       {"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0},
+                       {"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0},
+                       {"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
                },
        },
 }
index 1386f5a..bc14226 100644 (file)
@@ -278,7 +278,7 @@ func stringName(i uint32, names []intName, goSyntax bool) string {
                        return n.s
                }
        }
-       return strconv.Uitoa64(uint64(i))
+       return strconv.FormatUint(uint64(i), 10)
 }
 
 func flagName(i uint32, names []intName, goSyntax bool) string {
@@ -296,10 +296,10 @@ func flagName(i uint32, names []intName, goSyntax bool) string {
                }
        }
        if len(s) == 0 {
-               return "0x" + strconv.Uitob64(uint64(i), 16)
+               return "0x" + strconv.FormatUint(uint64(i), 16)
        }
        if i != 0 {
-               s += "+0x" + strconv.Uitob64(uint64(i), 16)
+               s += "+0x" + strconv.FormatUint(uint64(i), 16)
        }
        return s
 }
index 2c5c25b..2815d72 100644 (file)
@@ -20,39 +20,39 @@ var fileTests = []fileTest{
                "testdata/gcc-386-mingw-obj",
                FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
                []*SectionHeader{
-                       &SectionHeader{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
-                       &SectionHeader{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
-                       &SectionHeader{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
-                       &SectionHeader{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
-                       &SectionHeader{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
-                       &SectionHeader{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
-                       &SectionHeader{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
-                       &SectionHeader{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
-                       &SectionHeader{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
-                       &SectionHeader{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
-                       &SectionHeader{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
-                       &SectionHeader{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
+                       {".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
+                       {".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
+                       {".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
+                       {".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
+                       {".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
+                       {".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
+                       {".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
+                       {".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
+                       {".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
+                       {".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
+                       {".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
+                       {".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
                },
        },
        {
                "testdata/gcc-386-mingw-exec",
                FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
                []*SectionHeader{
-                       &SectionHeader{Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060},
-                       &SectionHeader{Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-                       &SectionHeader{Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040},
-                       &SectionHeader{Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080},
-                       &SectionHeader{Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-                       &SectionHeader{Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-                       &SectionHeader{Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
-                       &SectionHeader{Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-                       &SectionHeader{Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-                       &SectionHeader{Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-                       &SectionHeader{Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-                       &SectionHeader{Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-                       &SectionHeader{Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
-                       &SectionHeader{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
-                       &SectionHeader{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+                       {Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060},
+                       {Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+                       {Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040},
+                       {Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080},
+                       {Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+                       {Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+                       {Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
+                       {Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+                       {Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+                       {Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+                       {Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+                       {Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+                       {Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+                       {Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
+                       {Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
                },
        },
 }
index 6f592f3..7d004b5 100644 (file)
@@ -168,7 +168,7 @@ func (e *encoder) Close() error {
 type CorruptInputError int64
 
 func (e CorruptInputError) Error() string {
-       return "illegal ascii85 data at input byte " + strconv.Itoa64(int64(e))
+       return "illegal ascii85 data at input byte " + strconv.FormatInt(int64(e), 10)
 }
 
 // Decode decodes src into dst, returning both the number
index 2e6fccf..09f9413 100644 (file)
@@ -225,19 +225,19 @@ func TestUTCTime(t *testing.T) {
                ret, err := parseUTCTime([]byte(test.in))
                if err != nil {
                        if test.ok {
-                               t.Errorf("#%d: parseUTCTime(%q) = error %v", i, err)
+                               t.Errorf("#%d: parseUTCTime(%q) = error %v", i, test.in, err)
                        }
                        continue
                }
                if !test.ok {
-                       t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i)
+                       t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i, test.in)
                        continue
                }
                const format = "Jan _2 15:04:05 -0700 2006" // ignore zone name, just offset
                have := ret.Format(format)
                want := test.out.Format(format)
                if have != want {
-                       t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", test.in, have, want)
+                       t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", i, test.in, have, want)
                }
        }
 }
index 01f4f7b..f7cb3ac 100644 (file)
@@ -98,7 +98,7 @@ func parseFieldParameters(str string) (ret fieldParameters) {
                case part == "printable":
                        ret.stringType = tagPrintableString
                case strings.HasPrefix(part, "default:"):
-                       i, err := strconv.Atoi64(part[8:])
+                       i, err := strconv.ParseInt(part[8:], 10, 64)
                        if err == nil {
                                ret.defaultValue = new(int64)
                                *ret.defaultValue = i
index 494c760..c75c7c1 100644 (file)
@@ -216,7 +216,7 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 4) / 5 * 8 }
 type CorruptInputError int64
 
 func (e CorruptInputError) Error() string {
-       return "illegal base32 data at input byte " + strconv.Itoa64(int64(e))
+       return "illegal base32 data at input byte " + strconv.FormatInt(int64(e), 10)
 }
 
 // decode is like Decode but returns an additional 'end' value, which
index 9451289..889b565 100644 (file)
@@ -203,7 +203,7 @@ func (enc *Encoding) EncodedLen(n int) int { return (n + 2) / 3 * 4 }
 type CorruptInputError int64
 
 func (e CorruptInputError) Error() string {
-       return "illegal base64 data at input byte " + strconv.Itoa64(int64(e))
+       return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
 }
 
 // decode is like Decode but returns an additional 'end' value, which
index b6ad6e2..d383213 100644 (file)
@@ -15,7 +15,7 @@ import (
 type CorruptInputError int64
 
 func (e CorruptInputError) Error() string {
-       return "illegal git85 data at input byte " + strconv.Itoa64(int64(e))
+       return "illegal git85 data at input byte " + strconv.FormatInt(int64(e), 10)
 }
 
 const encode = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"
index e4a48df..a15b5a1 100644 (file)
@@ -119,7 +119,9 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
        switch st := actual; st.Kind() {
        case reflect.Struct:
                for i := 0; i < st.NumField(); i++ {
-                       enc.sendType(w, state, st.Field(i).Type)
+                       if isExported(st.Field(i).Name) {
+                               enc.sendType(w, state, st.Field(i).Type)
+                       }
                }
        case reflect.Array, reflect.Slice:
                enc.sendType(w, state, st.Elem())
index bc5af12..5bc957b 100644 (file)
@@ -662,3 +662,19 @@ func TestSequentialDecoder(t *testing.T) {
                }
        }
 }
+
+// Should be able to have unrepresentable fields (chan, func) as long as they
+// are unexported.
+type Bug2 struct {
+       A int
+       b chan int
+}
+
+func TestUnexportedChan(t *testing.T) {
+       b := Bug2{23, make(chan int)}
+       var stream bytes.Buffer
+       enc := NewEncoder(&stream)
+       if err := enc.Encode(b); err != nil {
+               t.Fatalf("error encoding unexported channel: %s", err)
+       }
+}
index 2ea06c5..0a70092 100644 (file)
@@ -642,7 +642,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
                default:
                        d.error(&UnmarshalTypeError{"number", v.Type()})
                case reflect.Interface:
-                       n, err := strconv.Atof64(s)
+                       n, err := strconv.ParseFloat(s, 64)
                        if err != nil {
                                d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
                                break
@@ -650,7 +650,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
                        v.Set(reflect.ValueOf(n))
 
                case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-                       n, err := strconv.Atoi64(s)
+                       n, err := strconv.ParseInt(s, 10, 64)
                        if err != nil || v.OverflowInt(n) {
                                d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
                                break
@@ -658,7 +658,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
                        v.SetInt(n)
 
                case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-                       n, err := strconv.Atoui64(s)
+                       n, err := strconv.ParseUint(s, 10, 64)
                        if err != nil || v.OverflowUint(n) {
                                d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
                                break
@@ -666,7 +666,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value) {
                        v.SetUint(n)
 
                case reflect.Float32, reflect.Float64:
-                       n, err := strconv.AtofN(s, v.Type().Bits())
+                       n, err := strconv.ParseFloat(s, v.Type().Bits())
                        if err != nil || v.OverflowFloat(n) {
                                d.saveError(&UnmarshalTypeError{"number " + s, v.Type()})
                                break
@@ -798,7 +798,7 @@ func (d *decodeState) literalInterface() interface{} {
                if c != '-' && (c < '0' || c > '9') {
                        d.error(errPhase)
                }
-               n, err := strconv.Atof64(string(item))
+               n, err := strconv.ParseFloat(string(item), 64)
                if err != nil {
                        d.saveError(&UnmarshalTypeError{"number " + string(item), reflect.TypeOf(0.0)})
                }
@@ -813,7 +813,7 @@ func getu4(s []byte) rune {
        if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
                return -1
        }
-       r, err := strconv.Btoui64(string(s[2:6]), 16)
+       r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
        if err != nil {
                return -1
        }
index bd4326a..bf3953e 100644 (file)
@@ -345,12 +345,12 @@ var allValue = All{
                "18": {Tag: "tag18"},
        },
        MapP: map[string]*Small{
-               "19": &Small{Tag: "tag19"},
+               "19": {Tag: "tag19"},
                "20": nil,
        },
        EmptyMap:    map[string]Small{},
        Slice:       []Small{{Tag: "tag20"}, {Tag: "tag21"}},
-       SliceP:      []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}},
+       SliceP:      []*Small{{Tag: "tag22"}, nil, {Tag: "tag23"}},
        EmptySlice:  []Small{},
        StringSlice: []string{"str24", "str25", "str26"},
        ByteSlice:   []byte{27, 28, 29},
index 14284f5..69deaf2 100644 (file)
@@ -275,13 +275,13 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
                }
 
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-               writeString(e, strconv.Itoa64(v.Int()))
+               writeString(e, strconv.FormatInt(v.Int(), 10))
 
        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-               writeString(e, strconv.Uitoa64(v.Uint()))
+               writeString(e, strconv.FormatUint(v.Uint(), 10))
 
        case reflect.Float32, reflect.Float64:
-               writeString(e, strconv.FtoaN(v.Float(), 'g', -1, v.Type().Bits()))
+               writeString(e, strconv.FormatFloat(v.Float(), 'g', -1, v.Type().Bits()))
 
        case reflect.String:
                if quoted {
index 691b70d..e94fdbc 100644 (file)
@@ -173,15 +173,15 @@ func (p *printer) marshalValue(val reflect.Value, name string) error {
 
        switch k := val.Kind(); k {
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-               p.WriteString(strconv.Itoa64(val.Int()))
+               p.WriteString(strconv.FormatInt(val.Int(), 10))
        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-               p.WriteString(strconv.Uitoa64(val.Uint()))
+               p.WriteString(strconv.FormatUint(val.Uint(), 10))
        case reflect.Float32, reflect.Float64:
-               p.WriteString(strconv.Ftoa64(val.Float(), 'g', -1))
+               p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, 64))
        case reflect.String:
                Escape(p, []byte(val.String()))
        case reflect.Bool:
-               p.WriteString(strconv.Btoa(val.Bool()))
+               p.WriteString(strconv.FormatBool(val.Bool()))
        case reflect.Array:
                // will be [...]byte
                bytes := make([]byte, val.Len())
index a6f7d2d..8040765 100644 (file)
@@ -160,19 +160,19 @@ var marshalTests = []struct {
                        Age:   1,
                        Drive: ImprobabilityDrive,
                        Passenger: []*Passenger{
-                               &Passenger{
+                               {
                                        Name:   []string{"Zaphod", "Beeblebrox"},
                                        Weight: 7.25,
                                },
-                               &Passenger{
+                               {
                                        Name:   []string{"Trisha", "McMillen"},
                                        Weight: 5.5,
                                },
-                               &Passenger{
+                               {
                                        Name:   []string{"Ford", "Prefect"},
                                        Weight: 7,
                                },
-                               &Passenger{
+                               {
                                        Name:   []string{"Arthur", "Dent"},
                                        Weight: 6.75,
                                },
@@ -326,12 +326,12 @@ var marshalErrorTests = []struct {
                        "question": "What do you get when you multiply six by nine?",
                        "answer":   "42",
                },
-               Err:  "xml: unsupported type: map[string] string",
+               Err:  "xml: unsupported type: map[string]string",
                Kind: reflect.Map,
        },
        {
                Value: map[*Ship]bool{nil: false},
-               Err:   "xml: unsupported type: map[*xml.Ship] bool",
+               Err:   "xml: unsupported type: map[*xml.Ship]bool",
                Kind:  reflect.Map,
        },
 }
index c6a3d75..6dd3654 100644 (file)
@@ -486,19 +486,19 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
        // Helper functions for integer and unsigned integer conversions
        var itmp int64
        getInt64 := func() bool {
-               itmp, err = strconv.Atoi64(string(src))
+               itmp, err = strconv.ParseInt(string(src), 10, 64)
                // TODO: should check sizes
                return err == nil
        }
        var utmp uint64
        getUint64 := func() bool {
-               utmp, err = strconv.Atoui64(string(src))
+               utmp, err = strconv.ParseUint(string(src), 10, 64)
                // TODO: check for overflow?
                return err == nil
        }
        var ftmp float64
        getFloat64 := func() bool {
-               ftmp, err = strconv.Atof64(string(src))
+               ftmp, err = strconv.ParseFloat(string(src), 64)
                // TODO: check for overflow?
                return err == nil
        }
@@ -525,7 +525,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
                }
                t.SetFloat(ftmp)
        case reflect.Bool:
-               value, err := strconv.Atob(strings.TrimSpace(string(src)))
+               value, err := strconv.ParseBool(strings.TrimSpace(string(src)))
                if err != nil {
                        return err
                }
index d67a299..d001c40 100644 (file)
@@ -889,9 +889,9 @@ Input:
                                var n uint64
                                var err error
                                if i >= 3 && s[1] == 'x' {
-                                       n, err = strconv.Btoui64(s[2:], 16)
+                                       n, err = strconv.ParseUint(s[2:], 16, 64)
                                } else {
-                                       n, err = strconv.Btoui64(s[1:], 10)
+                                       n, err = strconv.ParseUint(s[1:], 10, 64)
                                }
                                if err == nil && n <= unicode.MaxRune {
                                        text = string(n)
index 39bab7f..9a97831 100644 (file)
@@ -226,7 +226,7 @@ func parseDecomposition(s string, skipfirst bool) (a []rune, e error) {
                decomp = decomp[1:]
        }
        for _, d := range decomp {
-               point, err := strconv.Btoui64(d, 16)
+               point, err := strconv.ParseUint(d, 16, 64)
                if err != nil {
                        return a, err
                }
@@ -240,7 +240,7 @@ func parseCharacter(line string) {
        if len(field) != NumField {
                logger.Fatalf("%5s: %d fields (expected %d)\n", line, len(field), NumField)
        }
-       x, err := strconv.Btoui64(field[FCodePoint], 16)
+       x, err := strconv.ParseUint(field[FCodePoint], 16, 64)
        point := int(x)
        if err != nil {
                logger.Fatalf("%.5s...: %s", line, err)
@@ -264,7 +264,7 @@ func parseCharacter(line string) {
        if state != SLast {
                firstChar = lastChar
        }
-       x, err = strconv.Atoui64(field[FCanonicalCombiningClass])
+       x, err = strconv.ParseUint(field[FCanonicalCombiningClass], 10, 64)
        if err != nil {
                logger.Fatalf("%U: bad ccc field: %s", int(x), err)
        }
@@ -336,7 +336,7 @@ func parseExclusion(line string) int {
        if len(matches) != 2 {
                logger.Fatalf("%s: %d matches (expected 1)\n", line, len(matches))
        }
-       point, err := strconv.Btoui64(matches[1], 16)
+       point, err := strconv.ParseUint(matches[1], 16, 64)
        if err != nil {
                logger.Fatalf("%.5s...: %s", line, err)
        }
@@ -792,13 +792,13 @@ func testDerived() {
                        continue
                }
                rng := strings.Split(qc[1], "..")
-               i, err := strconv.Btoui64(rng[0], 16)
+               i, err := strconv.ParseUint(rng[0], 16, 64)
                if err != nil {
                        log.Fatal(err)
                }
                j := i
                if len(rng) > 1 {
-                       j, err = strconv.Btoui64(rng[1], 16)
+                       j, err = strconv.ParseUint(rng[1], 16, 64)
                        if err != nil {
                                log.Fatal(err)
                        }
index 6610c25..d214ce1 100644 (file)
@@ -171,7 +171,7 @@ func loadTestData() {
                counter++
                for j := 1; j < len(m)-1; j++ {
                        for _, split := range strings.Split(m[j], " ") {
-                               r, err := strconv.Btoui64(split, 16)
+                               r, err := strconv.ParseUint(split, 16, 64)
                                if err != nil {
                                        logger.Fatal(err)
                                }
index 48e2812..24315a0 100644 (file)
@@ -95,7 +95,7 @@ func convertAssign(dest, src interface{}) error {
        switch dv.Kind() {
        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
                s := asString(src)
-               i64, err := strconv.Atoi64(s)
+               i64, err := strconv.ParseInt(s, 10, 64)
                if err != nil {
                        return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
                }
@@ -106,7 +106,7 @@ func convertAssign(dest, src interface{}) error {
                return nil
        case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
                s := asString(src)
-               u64, err := strconv.Atoui64(s)
+               u64, err := strconv.ParseUint(s, 10, 64)
                if err != nil {
                        return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
                }
@@ -117,7 +117,7 @@ func convertAssign(dest, src interface{}) error {
                return nil
        case reflect.Float32, reflect.Float64:
                s := asString(src)
-               f64, err := strconv.Atof64(s)
+               f64, err := strconv.ParseFloat(s, 64)
                if err != nil {
                        return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
                }
index 6e0ce43..086b529 100644 (file)
@@ -54,13 +54,13 @@ func (boolType) ConvertValue(src interface{}) (interface{}, error) {
        case bool:
                return s, nil
        case string:
-               b, err := strconv.Atob(s)
+               b, err := strconv.ParseBool(s)
                if err != nil {
                        return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
                }
                return b, nil
        case []byte:
-               b, err := strconv.Atob(string(s))
+               b, err := strconv.ParseBool(string(s))
                if err != nil {
                        return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
                }
index de4926d..d91929a 100644 (file)
@@ -77,12 +77,12 @@ var DefaultCipherOrder = []string{
 var cipherModes = map[string]*cipherMode{
        // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
        // are defined in the order specified in the RFC.
-       "aes128-ctr": &cipherMode{16, aes.BlockSize, 0, newAESCTR},
-       "aes192-ctr": &cipherMode{24, aes.BlockSize, 0, newAESCTR},
-       "aes256-ctr": &cipherMode{32, aes.BlockSize, 0, newAESCTR},
+       "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
+       "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
+       "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
 
        // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
        // They are defined in the order specified in the RFC.
-       "arcfour128": &cipherMode{16, 0, 1536, newRC4},
-       "arcfour256": &cipherMode{32, 0, 1536, newRC4},
+       "arcfour128": {16, 0, 1536, newRC4},
+       "arcfour256": {32, 0, 1536, newRC4},
 }
index 429dee9..d89b908 100644 (file)
@@ -200,7 +200,7 @@ func (c *ClientConn) mainLoop() {
                        peersId := uint32(packet[1])<<24 | uint32(packet[2])<<16 | uint32(packet[3])<<8 | uint32(packet[4])
                        if length := int(packet[5])<<24 | int(packet[6])<<16 | int(packet[7])<<8 | int(packet[8]); length > 0 {
                                packet = packet[9:]
-                               c.getChan(peersId).data <- packet[:length]
+                               c.getChan(peersId).stdout.data <- packet[:length]
                        }
                case msgChannelExtendedData:
                        if len(packet) < 13 {
@@ -215,7 +215,7 @@ func (c *ClientConn) mainLoop() {
                                // for stderr on interactive sessions. Other data types are
                                // silently discarded.
                                if datatype == 1 {
-                                       c.getChan(peersId).dataExt <- packet[:length]
+                                       c.getChan(peersId).stderr.data <- packet[:length]
                                }
                        }
                default:
@@ -228,9 +228,9 @@ func (c *ClientConn) mainLoop() {
                                c.getChan(msg.PeersId).msg <- msg
                        case *channelCloseMsg:
                                ch := c.getChan(msg.PeersId)
-                               close(ch.win)
-                               close(ch.data)
-                               close(ch.dataExt)
+                               close(ch.stdin.win)
+                               close(ch.stdout.data)
+                               close(ch.stderr.data)
                                c.chanlist.remove(msg.PeersId)
                        case *channelEOFMsg:
                                c.getChan(msg.PeersId).msg <- msg
@@ -241,7 +241,7 @@ func (c *ClientConn) mainLoop() {
                        case *channelRequestMsg:
                                c.getChan(msg.PeersId).msg <- msg
                        case *windowAdjustMsg:
-                               c.getChan(msg.PeersId).win <- int(msg.AdditionalBytes)
+                               c.getChan(msg.PeersId).stdin.win <- int(msg.AdditionalBytes)
                        default:
                                fmt.Printf("mainLoop: unhandled message %T: %v\n", msg, msg)
                        }
@@ -290,21 +290,49 @@ func (c *ClientConfig) rand() io.Reader {
 type clientChan struct {
        packetWriter
        id, peersId uint32
-       data        chan []byte      // receives the payload of channelData messages
-       dataExt     chan []byte      // receives the payload of channelExtendedData messages
-       win         chan int         // receives window adjustments
+       stdin       *chanWriter      // receives window adjustments
+       stdout      *chanReader      // receives the payload of channelData messages
+       stderr      *chanReader      // receives the payload of channelExtendedData messages
        msg         chan interface{} // incoming messages
 }
 
+// newClientChan returns a partially constructed *clientChan
+// using the local id provided. To be usable clientChan.peersId 
+// needs to be assigned once known.
 func newClientChan(t *transport, id uint32) *clientChan {
-       return &clientChan{
+       c := &clientChan{
                packetWriter: t,
                id:           id,
-               data:         make(chan []byte, 16),
-               dataExt:      make(chan []byte, 16),
-               win:          make(chan int, 16),
                msg:          make(chan interface{}, 16),
        }
+       c.stdin = &chanWriter{
+               win:        make(chan int, 16),
+               clientChan: c,
+       }
+       c.stdout = &chanReader{
+               data:       make(chan []byte, 16),
+               clientChan: c,
+       }
+       c.stderr = &chanReader{
+               data:       make(chan []byte, 16),
+               clientChan: c,
+       }
+       return c
+}
+
+// waitForChannelOpenResponse, if successful, fills out 
+// the peerId and records any initial window advertisement. 
+func (c *clientChan) waitForChannelOpenResponse() error {
+       switch msg := (<-c.msg).(type) {
+       case *channelOpenConfirmMsg:
+               // fixup peersId field
+               c.peersId = msg.MyId
+               c.stdin.win <- int(msg.MyWindow)
+               return nil
+       case *channelOpenFailureMsg:
+               return errors.New(safeString(msg.Message))
+       }
+       return errors.New("unexpected packet")
 }
 
 // Close closes the channel. This does not close the underlying connection.
@@ -355,10 +383,9 @@ func (c *chanlist) remove(id uint32) {
 
 // A chanWriter represents the stdin of a remote process.
 type chanWriter struct {
-       win          chan int // receives window adjustments
-       peersId      uint32   // the peer's id
-       rwin         int      // current rwin size
-       packetWriter          // for sending channelDataMsg
+       win        chan int    // receives window adjustments
+       rwin       int         // current rwin size
+       clientChan *clientChan // the channel backing this writer
 }
 
 // Write writes data to the remote process's standard input.
@@ -372,12 +399,13 @@ func (w *chanWriter) Write(data []byte) (n int, err error) {
                        w.rwin += win
                        continue
                }
+               peersId := w.clientChan.peersId
                n = len(data)
                packet := make([]byte, 0, 9+n)
                packet = append(packet, msgChannelData,
-                       byte(w.peersId>>24), byte(w.peersId>>16), byte(w.peersId>>8), byte(w.peersId),
+                       byte(peersId>>24), byte(peersId>>16), byte(peersId>>8), byte(peersId),
                        byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
-               err = w.writePacket(append(packet, data...))
+               err = w.clientChan.writePacket(append(packet, data...))
                w.rwin -= n
                return
        }
@@ -385,7 +413,7 @@ func (w *chanWriter) Write(data []byte) (n int, err error) {
 }
 
 func (w *chanWriter) Close() error {
-       return w.writePacket(marshal(msgChannelEOF, channelEOFMsg{w.peersId}))
+       return w.clientChan.writePacket(marshal(msgChannelEOF, channelEOFMsg{w.clientChan.peersId}))
 }
 
 // A chanReader represents stdout or stderr of a remote process.
@@ -393,10 +421,9 @@ type chanReader struct {
        // TODO(dfc) a fixed size channel may not be the right data structure.
        // If writes to this channel block, they will block mainLoop, making
        // it unable to receive new messages from the remote side.
-       data         chan []byte // receives data from remote
-       peersId      uint32      // the peer's id
-       packetWriter             // for sending windowAdjustMsg
-       buf          []byte
+       data       chan []byte // receives data from remote
+       clientChan *clientChan // the channel backing this reader
+       buf        []byte
 }
 
 // Read reads data from the remote process's stdout or stderr.
@@ -407,10 +434,10 @@ func (r *chanReader) Read(data []byte) (int, error) {
                        n := copy(data, r.buf)
                        r.buf = r.buf[n:]
                        msg := windowAdjustMsg{
-                               PeersId:         r.peersId,
+                               PeersId:         r.clientChan.peersId,
                                AdditionalBytes: uint32(n),
                        }
-                       return n, r.writePacket(marshal(msgChannelWindowAdjust, msg))
+                       return n, r.clientChan.writePacket(marshal(msgChannelWindowAdjust, msg))
                }
                r.buf, ok = <-r.data
                if !ok {
index 25f9e21..1a38235 100644 (file)
@@ -9,7 +9,7 @@ import (
        "io"
 )
 
-// authenticate authenticates with the remote server. See RFC 4252. 
+// authenticate authenticates with the remote server. See RFC 4252.
 func (c *ClientConn) authenticate(session []byte) error {
        // initiate user auth session
        if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
@@ -24,7 +24,7 @@ func (c *ClientConn) authenticate(session []byte) error {
                return err
        }
        // during the authentication phase the client first attempts the "none" method
-       // then any untried methods suggested by the server. 
+       // then any untried methods suggested by the server.
        tried, remain := make(map[string]bool), make(map[string]bool)
        for auth := ClientAuth(new(noneAuth)); auth != nil; {
                ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
@@ -57,9 +57,9 @@ func (c *ClientConn) authenticate(session []byte) error {
 
 // A ClientAuth represents an instance of an RFC 4252 authentication method.
 type ClientAuth interface {
-       // auth authenticates user over transport t. 
+       // auth authenticates user over transport t.
        // Returns true if authentication is successful.
-       // If authentication is not successful, a []string of alternative 
+       // If authentication is not successful, a []string of alternative
        // method names is returned.
        auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)
 
@@ -79,19 +79,7 @@ func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reade
                return false, nil, err
        }
 
-       packet, err := t.readPacket()
-       if err != nil {
-               return false, nil, err
-       }
-
-       switch packet[0] {
-       case msgUserAuthSuccess:
-               return true, nil, nil
-       case msgUserAuthFailure:
-               msg := decode(packet).(*userAuthFailureMsg)
-               return false, msg.Methods, nil
-       }
-       return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
+       return handleAuthResponse(t)
 }
 
 func (n *noneAuth) method() string {
@@ -127,19 +115,7 @@ func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.R
                return false, nil, err
        }
 
-       packet, err := t.readPacket()
-       if err != nil {
-               return false, nil, err
-       }
-
-       switch packet[0] {
-       case msgUserAuthSuccess:
-               return true, nil, nil
-       case msgUserAuthFailure:
-               msg := decode(packet).(*userAuthFailureMsg)
-               return false, msg.Methods, nil
-       }
-       return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
+       return handleAuthResponse(t)
 }
 
 func (p *passwordAuth) method() string {
@@ -159,7 +135,7 @@ func ClientAuthPassword(impl ClientPassword) ClientAuth {
 
 // ClientKeyring implements access to a client key ring.
 type ClientKeyring interface {
-       // Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if 
+       // Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if
        // no key exists at i.
        Key(i int) (key interface{}, err error)
 
@@ -173,27 +149,28 @@ type publickeyAuth struct {
        ClientKeyring
 }
 
+type publickeyAuthMsg struct {
+       User    string
+       Service string
+       Method  string
+       // HasSig indicates to the reciver packet that the auth request is signed and
+       // should be used for authentication of the request.
+       HasSig   bool
+       Algoname string
+       Pubkey   string
+       // Sig is defined as []byte so marshal will exclude it during validateKey
+       Sig []byte `ssh:"rest"`
+}
+
 func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
-       type publickeyAuthMsg struct {
-               User    string
-               Service string
-               Method  string
-               // HasSig indicates to the reciver packet that the auth request is signed and
-               // should be used for authentication of the request.
-               HasSig   bool
-               Algoname string
-               Pubkey   string
-               // Sig is defined as []byte so marshal will exclude it during the query phase
-               Sig []byte `ssh:"rest"`
-       }
 
        // Authentication is performed in two stages. The first stage sends an
        // enquiry to test if each key is acceptable to the remote. The second
-       // stage attempts to authenticate with the valid keys obtained in the 
+       // stage attempts to authenticate with the valid keys obtained in the
        // first stage.
 
        var index int
-       // a map of public keys to their index in the keyring 
+       // a map of public keys to their index in the keyring
        validKeys := make(map[int]interface{})
        for {
                key, err := p.Key(index)
@@ -204,33 +181,13 @@ func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.
                        // no more keys in the keyring
                        break
                }
-               pubkey := serializePublickey(key)
-               algoname := algoName(key)
-               msg := publickeyAuthMsg{
-                       User:     user,
-                       Service:  serviceSSH,
-                       Method:   p.method(),
-                       HasSig:   false,
-                       Algoname: algoname,
-                       Pubkey:   string(pubkey),
-               }
-               if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
-                       return false, nil, err
-               }
-               packet, err := t.readPacket()
-               if err != nil {
-                       return false, nil, err
-               }
-               switch packet[0] {
-               case msgUserAuthPubKeyOk:
-                       msg := decode(packet).(*userAuthPubKeyOkMsg)
-                       if msg.Algo != algoname || msg.PubKey != string(pubkey) {
-                               continue
-                       }
+
+               if ok, err := p.validateKey(key, user, t); ok {
                        validKeys[index] = key
-               case msgUserAuthFailure:
-               default:
-                       return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
+               } else {
+                       if err != nil {
+                               return false, nil, err
+                       }
                }
                index++
        }
@@ -265,24 +222,61 @@ func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.
                if err := t.writePacket(p); err != nil {
                        return false, nil, err
                }
-               packet, err := t.readPacket()
+               success, methods, err := handleAuthResponse(t)
                if err != nil {
                        return false, nil, err
                }
+               if success {
+                       return success, methods, err
+               }
+       }
+       return false, methods, nil
+}
+
+// validateKey validates the key provided it is acceptable to the server.
+func (p *publickeyAuth) validateKey(key interface{}, user string, t *transport) (bool, error) {
+       pubkey := serializePublickey(key)
+       algoname := algoName(key)
+       msg := publickeyAuthMsg{
+               User:     user,
+               Service:  serviceSSH,
+               Method:   p.method(),
+               HasSig:   false,
+               Algoname: algoname,
+               Pubkey:   string(pubkey),
+       }
+       if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
+               return false, err
+       }
+
+       return p.confirmKeyAck(key, t)
+}
+
+func (p *publickeyAuth) confirmKeyAck(key interface{}, t *transport) (bool, error) {
+       pubkey := serializePublickey(key)
+       algoname := algoName(key)
+
+       for {
+               packet, err := t.readPacket()
+               if err != nil {
+                       return false, err
+               }
                switch packet[0] {
-               case msgUserAuthSuccess:
-                       return true, nil, nil
+               case msgUserAuthBanner:
+                       // TODO(gpaul): add callback to present the banner to the user
+               case msgUserAuthPubKeyOk:
+                       msg := decode(packet).(*userAuthPubKeyOkMsg)
+                       if msg.Algo != algoname || msg.PubKey != string(pubkey) {
+                               return false, nil
+                       }
+                       return true, nil
                case msgUserAuthFailure:
-                       msg := decode(packet).(*userAuthFailureMsg)
-                       methods = msg.Methods
-                       continue
-               case msgDisconnect:
-                       return false, nil, io.EOF
+                       return false, nil
                default:
-                       return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
+                       return false, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
                }
        }
-       return false, methods, nil
+       panic("unreachable")
 }
 
 func (p *publickeyAuth) method() string {
@@ -293,3 +287,30 @@ func (p *publickeyAuth) method() string {
 func ClientAuthPublickey(impl ClientKeyring) ClientAuth {
        return &publickeyAuth{impl}
 }
+
+// handleAuthResponse returns whether the preceding authentication request succeeded
+// along with a list of remaining authentication methods to try next and
+// an error if an unexpected response was received.
+func handleAuthResponse(t *transport) (bool, []string, error) {
+       for {
+               packet, err := t.readPacket()
+               if err != nil {
+                       return false, nil, err
+               }
+
+               switch packet[0] {
+               case msgUserAuthBanner:
+                       // TODO: add callback to present the banner to the user
+               case msgUserAuthFailure:
+                       msg := decode(packet).(*userAuthFailureMsg)
+                       return false, msg.Methods, nil
+               case msgUserAuthSuccess:
+                       return true, nil, nil
+               case msgDisconnect:
+                       return false, nil, io.EOF
+               default:
+                       return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
+               }
+       }
+       panic("unreachable")
+}
index 4ef9213..2b89e97 100644 (file)
@@ -7,17 +7,20 @@ package ssh
 import (
        "bytes"
        "crypto"
-       "crypto/rand"
+       "crypto/dsa"
        "crypto/rsa"
+       _ "crypto/sha1"
        "crypto/x509"
        "encoding/pem"
        "errors"
        "io"
        "io/ioutil"
+       "math/big"
        "testing"
 )
 
-const _pem = `-----BEGIN RSA PRIVATE KEY-----
+// private key for mock server
+const testServerPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
 MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU
 70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx
 9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF
@@ -45,25 +48,32 @@ gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl
 NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw==
 -----END RSA PRIVATE KEY-----`
 
-// reused internally by tests
-var serverConfig = new(ServerConfig)
-
-func init() {
-       if err := serverConfig.SetRSAPrivateKey([]byte(_pem)); err != nil {
-               panic("unable to set private key: " + err.Error())
-       }
-}
+const testClientPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld
+r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
+tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
+nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
+2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
+y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
+rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
+-----END RSA PRIVATE KEY-----`
 
 // keychain implements the ClientPublickey interface
 type keychain struct {
-       keys []*rsa.PrivateKey
+       keys []interface{}
 }
 
 func (k *keychain) Key(i int) (interface{}, error) {
        if i < 0 || i >= len(k.keys) {
                return nil, nil
        }
-       return k.keys[i].PublicKey, nil
+       switch key := k.keys[i].(type) {
+       case *rsa.PrivateKey:
+               return key.PublicKey, nil
+       case *dsa.PrivateKey:
+               return key.PublicKey, nil
+       }
+       panic("unknown key type")
 }
 
 func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
@@ -71,7 +81,11 @@ func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err err
        h := hashFunc.New()
        h.Write(data)
        digest := h.Sum(nil)
-       return rsa.SignPKCS1v15(rand, k.keys[i], hashFunc, digest)
+       switch key := k.keys[i].(type) {
+       case *rsa.PrivateKey:
+               return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
+       }
+       return nil, errors.New("unknown key type")
 }
 
 func (k *keychain) loadPEM(file string) error {
@@ -91,158 +105,153 @@ func (k *keychain) loadPEM(file string) error {
        return nil
 }
 
-var pkey *rsa.PrivateKey
+// password implements the ClientPassword interface
+type password string
 
-func init() {
-       var err error
-       pkey, err = rsa.GenerateKey(rand.Reader, 512)
-       if err != nil {
-               panic("unable to generate public key")
-       }
+func (p password) Password(user string) (string, error) {
+       return string(p), nil
 }
 
-func TestClientAuthPublickey(t *testing.T) {
-       k := new(keychain)
-       k.keys = append(k.keys, pkey)
+// reused internally by tests
+var (
+       rsakey         *rsa.PrivateKey
+       dsakey         *dsa.PrivateKey
+       clientKeychain = new(keychain)
+       clientPassword = password("tiger")
+       serverConfig   = &ServerConfig{
+               PasswordCallback: func(user, pass string) bool {
+                       return user == "testuser" && pass == string(clientPassword)
+               },
+               PubKeyCallback: func(user, algo string, pubkey []byte) bool {
+                       key := clientKeychain.keys[0].(*rsa.PrivateKey).PublicKey
+                       expected := []byte(serializePublickey(key))
+                       algoname := algoName(key)
+                       return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
+               },
+       }
+)
 
-       serverConfig.PubKeyCallback = func(user, algo string, pubkey []byte) bool {
-               expected := []byte(serializePublickey(k.keys[0].PublicKey))
-               algoname := algoName(k.keys[0].PublicKey)
-               return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
+func init() {
+       if err := serverConfig.SetRSAPrivateKey([]byte(testServerPrivateKey)); err != nil {
+               panic("unable to set private key: " + err.Error())
        }
-       serverConfig.PasswordCallback = nil
 
+       block, _ := pem.Decode([]byte(testClientPrivateKey))
+       rsakey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
+
+       clientKeychain.keys = append(clientKeychain.keys, rsakey)
+       dsakey = new(dsa.PrivateKey)
+       // taken from crypto/dsa/dsa_test.go
+       dsakey.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
+       dsakey.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
+       dsakey.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
+       dsakey.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
+       dsakey.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
+}
+
+// newMockAuthServer creates a new Server bound to 
+// the loopback interface. The server exits after 
+// processing one handshake.
+func newMockAuthServer(t *testing.T) string {
        l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
        if err != nil {
-               t.Fatalf("unable to listen: %s", err)
+               t.Fatalf("unable to newMockAuthServer: %s", err)
        }
-       defer l.Close()
-
-       done := make(chan bool, 1)
        go func() {
+               defer l.Close()
                c, err := l.Accept()
+               defer c.Close()
                if err != nil {
-                       t.Fatal(err)
+                       t.Errorf("Unable to accept incoming connection: %v", err)
+                       return
                }
-               defer c.Close()
                if err := c.Handshake(); err != nil {
-                       t.Error(err)
+                       // not Errorf because this is expected to
+                       // fail for some tests.
+                       t.Logf("Handshaking error: %v", err)
+                       return
                }
-               done <- true
        }()
+       return l.Addr().String()
+}
 
+func TestClientAuthPublickey(t *testing.T) {
        config := &ClientConfig{
                User: "testuser",
                Auth: []ClientAuth{
-                       ClientAuthPublickey(k),
+                       ClientAuthPublickey(clientKeychain),
                },
        }
-
-       c, err := Dial("tcp", l.Addr().String(), config)
+       c, err := Dial("tcp", newMockAuthServer(t), config)
        if err != nil {
                t.Fatalf("unable to dial remote side: %s", err)
        }
-       defer c.Close()
-       <-done
-}
-
-// password implements the ClientPassword interface
-type password string
-
-func (p password) Password(user string) (string, error) {
-       return string(p), nil
+       c.Close()
 }
 
 func TestClientAuthPassword(t *testing.T) {
-       pw := password("tiger")
-
-       serverConfig.PasswordCallback = func(user, pass string) bool {
-               return user == "testuser" && pass == string(pw)
+       config := &ClientConfig{
+               User: "testuser",
+               Auth: []ClientAuth{
+                       ClientAuthPassword(clientPassword),
+               },
        }
-       serverConfig.PubKeyCallback = nil
 
-       l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
+       c, err := Dial("tcp", newMockAuthServer(t), config)
        if err != nil {
-               t.Fatalf("unable to listen: %s", err)
+               t.Fatalf("unable to dial remote side: %s", err)
        }
-       defer l.Close()
-
-       done := make(chan bool)
-       go func() {
-               c, err := l.Accept()
-               if err != nil {
-                       t.Fatal(err)
-               }
-               if err := c.Handshake(); err != nil {
-                       t.Error(err)
-               }
-               defer c.Close()
-               done <- true
-       }()
+       c.Close()
+}
 
+func TestClientAuthWrongPassword(t *testing.T) {
+       wrongPw := password("wrong")
        config := &ClientConfig{
                User: "testuser",
                Auth: []ClientAuth{
-                       ClientAuthPassword(pw),
+                       ClientAuthPassword(wrongPw),
+                       ClientAuthPublickey(clientKeychain),
                },
        }
 
-       c, err := Dial("tcp", l.Addr().String(), config)
+       c, err := Dial("tcp", newMockAuthServer(t), config)
        if err != nil {
                t.Fatalf("unable to dial remote side: %s", err)
        }
-       defer c.Close()
-       <-done
+       c.Close()
 }
 
-func TestClientAuthPasswordAndPublickey(t *testing.T) {
-       pw := password("tiger")
-
-       serverConfig.PasswordCallback = func(user, pass string) bool {
-               return user == "testuser" && pass == string(pw)
-       }
-
-       k := new(keychain)
-       k.keys = append(k.keys, pkey)
-
-       serverConfig.PubKeyCallback = func(user, algo string, pubkey []byte) bool {
-               expected := []byte(serializePublickey(k.keys[0].PublicKey))
-               algoname := algoName(k.keys[0].PublicKey)
-               return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
+// the mock server will only authenticate ssh-rsa keys
+func TestClientAuthInvalidPublickey(t *testing.T) {
+       kc := new(keychain)
+       kc.keys = append(kc.keys, dsakey)
+       config := &ClientConfig{
+               User: "testuser",
+               Auth: []ClientAuth{
+                       ClientAuthPublickey(kc),
+               },
        }
 
-       l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
-       if err != nil {
-               t.Fatalf("unable to listen: %s", err)
+       c, err := Dial("tcp", newMockAuthServer(t), config)
+       if err == nil {
+               c.Close()
+               t.Fatalf("dsa private key should not have authenticated with rsa public key")
        }
-       defer l.Close()
-
-       done := make(chan bool)
-       go func() {
-               c, err := l.Accept()
-               if err != nil {
-                       t.Fatal(err)
-               }
-               if err := c.Handshake(); err != nil {
-                       t.Error(err)
-               }
-               defer c.Close()
-               done <- true
-       }()
+}
 
-       wrongPw := password("wrong")
+// the client should authenticate with the second key
+func TestClientAuthRSAandDSA(t *testing.T) {
+       kc := new(keychain)
+       kc.keys = append(kc.keys, dsakey, rsakey)
        config := &ClientConfig{
                User: "testuser",
                Auth: []ClientAuth{
-                       ClientAuthPassword(wrongPw),
-                       ClientAuthPublickey(k),
+                       ClientAuthPublickey(kc),
                },
        }
-
-       c, err := Dial("tcp", l.Addr().String(), config)
+       c, err := Dial("tcp", newMockAuthServer(t), config)
        if err != nil {
-               t.Fatalf("unable to dial remote side: %s", err)
+               t.Fatalf("client could not authenticate with rsa key: %v", err)
        }
-       defer c.Close()
-       <-done
+       c.Close()
 }
index 2f4448a..058fb04 100644 (file)
@@ -8,15 +8,15 @@ import (
        "testing"
 )
 
-var strings = map[string]string{
-       "\x20\x0d\x0a":  "\x20\x0d\x0a",
-       "flibble":       "flibble",
-       "new\x20line":   "new\x20line",
-       "123456\x07789": "123456 789",
-       "\t\t\x10\r\n":  "\t\t \r\n",
-}
-
 func TestSafeString(t *testing.T) {
+       strings := map[string]string{
+               "\x20\x0d\x0a":  "\x20\x0d\x0a",
+               "flibble":       "flibble",
+               "new\x20line":   "new\x20line",
+               "123456\x07789": "123456 789",
+               "\t\t\x10\r\n":  "\t\t \r\n",
+       }
+
        for s, expected := range strings {
                actual := safeString(s)
                if expected != actual {
index 5f98a8d..23ea18c 100644 (file)
@@ -285,13 +285,8 @@ func (s *Session) stdin() error {
                s.Stdin = new(bytes.Buffer)
        }
        s.copyFuncs = append(s.copyFuncs, func() error {
-               w := &chanWriter{
-                       packetWriter: s,
-                       peersId:      s.peersId,
-                       win:          s.win,
-               }
-               _, err := io.Copy(w, s.Stdin)
-               if err1 := w.Close(); err == nil {
+               _, err := io.Copy(s.clientChan.stdin, s.Stdin)
+               if err1 := s.clientChan.stdin.Close(); err == nil {
                        err = err1
                }
                return err
@@ -304,12 +299,7 @@ func (s *Session) stdout() error {
                s.Stdout = ioutil.Discard
        }
        s.copyFuncs = append(s.copyFuncs, func() error {
-               r := &chanReader{
-                       packetWriter: s,
-                       peersId:      s.peersId,
-                       data:         s.data,
-               }
-               _, err := io.Copy(s.Stdout, r)
+               _, err := io.Copy(s.Stdout, s.clientChan.stdout)
                return err
        })
        return nil
@@ -320,12 +310,7 @@ func (s *Session) stderr() error {
                s.Stderr = ioutil.Discard
        }
        s.copyFuncs = append(s.copyFuncs, func() error {
-               r := &chanReader{
-                       packetWriter: s,
-                       peersId:      s.peersId,
-                       data:         s.dataExt,
-               }
-               _, err := io.Copy(s.Stderr, r)
+               _, err := io.Copy(s.Stderr, s.clientChan.stderr)
                return err
        })
        return nil
@@ -398,19 +383,11 @@ func (c *ClientConn) NewSession() (*Session, error) {
                c.chanlist.remove(ch.id)
                return nil, err
        }
-       // wait for response
-       msg := <-ch.msg
-       switch msg := msg.(type) {
-       case *channelOpenConfirmMsg:
-               ch.peersId = msg.MyId
-               ch.win <- int(msg.MyWindow)
-               return &Session{
-                       clientChan: ch,
-               }, nil
-       case *channelOpenFailureMsg:
+       if err := ch.waitForChannelOpenResponse(); err != nil {
                c.chanlist.remove(ch.id)
-               return nil, fmt.Errorf("ssh: channel open failed: %s", msg.Message)
+               return nil, fmt.Errorf("ssh: unable to open session: %v", err)
        }
-       c.chanlist.remove(ch.id)
-       return nil, fmt.Errorf("ssh: unexpected message %T: %v", msg, msg)
+       return &Session{
+               clientChan: ch,
+       }, nil
 }
index 4be7746..d4818c2 100644 (file)
@@ -61,7 +61,7 @@ func dial(t *testing.T) *ClientConn {
                                        WantReply bool
                                        Status    uint32
                                }
-                               // TODO(dfc) casting to the concrete type should not be
+                               // TODO(dfc) converting to the concrete type should not be
                                // necessary to send a packet.
                                msg := exitMsg{
                                        PeersId:   ch.(*channel).theirId,
index f3bbac5..a85044a 100644 (file)
@@ -6,6 +6,7 @@ package ssh
 
 import (
        "errors"
+       "fmt"
        "io"
        "net"
 )
@@ -42,20 +43,21 @@ func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, err
        }, nil
 }
 
+// RFC 4254 7.2
+type channelOpenDirectMsg struct {
+       ChanType      string
+       PeersId       uint32
+       PeersWindow   uint32
+       MaxPacketSize uint32
+       raddr         string
+       rport         uint32
+       laddr         string
+       lport         uint32
+}
+
 // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
 // strings and are expected to be resolveable at the remote end.
 func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpchan, error) {
-       // RFC 4254 7.2
-       type channelOpenDirectMsg struct {
-               ChanType      string
-               PeersId       uint32
-               PeersWindow   uint32
-               MaxPacketSize uint32
-               raddr         string
-               rport         uint32
-               laddr         string
-               lport         uint32
-       }
        ch := c.newChan(c.transport)
        if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
                ChanType:      "direct-tcpip",
@@ -70,30 +72,14 @@ func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tc
                c.chanlist.remove(ch.id)
                return nil, err
        }
-       // wait for response
-       switch msg := (<-ch.msg).(type) {
-       case *channelOpenConfirmMsg:
-               ch.peersId = msg.MyId
-               ch.win <- int(msg.MyWindow)
-       case *channelOpenFailureMsg:
-               c.chanlist.remove(ch.id)
-               return nil, errors.New("ssh: error opening remote TCP connection: " + msg.Message)
-       default:
+       if err := ch.waitForChannelOpenResponse(); err != nil {
                c.chanlist.remove(ch.id)
-               return nil, errors.New("ssh: unexpected packet")
+               return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
        }
        return &tcpchan{
                clientChan: ch,
-               Reader: &chanReader{
-                       packetWriter: ch,
-                       peersId:      ch.peersId,
-                       data:         ch.data,
-               },
-               Writer: &chanWriter{
-                       packetWriter: ch,
-                       peersId:      ch.peersId,
-                       win:          ch.win,
-               },
+               Reader:     ch.stdout,
+               Writer:     ch.stdin,
        }, nil
 }
 
index 16a8667..6adcc2a 100644 (file)
@@ -305,7 +305,7 @@ func (p *gcParser) parseArrayType() Type {
        lit := p.expect(scanner.Int)
        p.expect(']')
        elt := p.parseType()
-       n, err := strconv.Atoui64(lit)
+       n, err := strconv.ParseUint(lit, 10, 64)
        if err != nil {
                p.error(err)
        }
@@ -323,7 +323,7 @@ func (p *gcParser) parseMapType() Type {
        return &Map{Key: key, Elt: elt}
 }
 
-// Name = identifier | "?" .
+// Name = identifier | "?" | ExportedName  .
 //
 func (p *gcParser) parseName() (name string) {
        switch p.tok {
@@ -333,6 +333,9 @@ func (p *gcParser) parseName() (name string) {
        case '?':
                // anonymous
                p.next()
+       case '@':
+               // exported name prefixed with package path
+               _, name = p.parseExportedName()
        default:
                p.error("name expected")
        }
@@ -619,10 +622,11 @@ func (p *gcParser) parseNumber() Const {
                // exponent (base 2)
                p.next()
                sign, val = p.parseInt()
-               exp, err := strconv.Atoui(val)
+               exp64, err := strconv.ParseUint(val, 10, 0)
                if err != nil {
                        p.error(err)
                }
+               exp := uint(exp64)
                if sign == "-" {
                        denom := big.NewInt(1)
                        denom.Lsh(denom, exp)
@@ -747,7 +751,7 @@ func (p *gcParser) parseFuncDecl() {
        }
 }
 
-// MethodDecl = "func" Receiver identifier Signature .
+// MethodDecl = "func" Receiver Name Signature .
 // Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
 //
 func (p *gcParser) parseMethodDecl() {
@@ -755,7 +759,7 @@ func (p *gcParser) parseMethodDecl() {
        p.expect('(')
        p.parseParameter() // receiver
        p.expect(')')
-       p.expect(scanner.Ident)
+       p.parseName() // unexported method names in imports are qualified with their package.
        p.parseSignature()
        if p.tok == '{' {
                p.parseFuncBody()
index 629280a..40f5441 100644 (file)
@@ -44,7 +44,7 @@ type Int struct {
        mu sync.Mutex
 }
 
-func (v *Int) String() string { return strconv.Itoa64(v.i) }
+func (v *Int) String() string { return strconv.FormatInt(v.i, 10) }
 
 func (v *Int) Add(delta int64) {
        v.mu.Lock()
@@ -64,7 +64,7 @@ type Float struct {
        mu sync.Mutex
 }
 
-func (v *Float) String() string { return strconv.Ftoa64(v.f, 'g', -1) }
+func (v *Float) String() string { return strconv.FormatFloat(v.f, 'g', -1, 64) }
 
 // Add adds delta to v.
 func (v *Float) Add(delta float64) {
index 9f115d5..406ea77 100644 (file)
@@ -79,7 +79,7 @@ func newBoolValue(val bool, p *bool) *boolValue {
 }
 
 func (b *boolValue) Set(s string) bool {
-       v, err := strconv.Atob(s)
+       v, err := strconv.ParseBool(s)
        *b = boolValue(v)
        return err == nil
 }
@@ -95,7 +95,7 @@ func newIntValue(val int, p *int) *intValue {
 }
 
 func (i *intValue) Set(s string) bool {
-       v, err := strconv.Btoi64(s, 0)
+       v, err := strconv.ParseInt(s, 0, 64)
        *i = intValue(v)
        return err == nil
 }
@@ -111,7 +111,7 @@ func newInt64Value(val int64, p *int64) *int64Value {
 }
 
 func (i *int64Value) Set(s string) bool {
-       v, err := strconv.Btoi64(s, 0)
+       v, err := strconv.ParseInt(s, 0, 64)
        *i = int64Value(v)
        return err == nil
 }
@@ -127,7 +127,7 @@ func newUintValue(val uint, p *uint) *uintValue {
 }
 
 func (i *uintValue) Set(s string) bool {
-       v, err := strconv.Btoui64(s, 0)
+       v, err := strconv.ParseUint(s, 0, 64)
        *i = uintValue(v)
        return err == nil
 }
@@ -143,7 +143,7 @@ func newUint64Value(val uint64, p *uint64) *uint64Value {
 }
 
 func (i *uint64Value) Set(s string) bool {
-       v, err := strconv.Btoui64(s, 0)
+       v, err := strconv.ParseUint(s, 0, 64)
        *i = uint64Value(v)
        return err == nil
 }
@@ -174,7 +174,7 @@ func newFloat64Value(val float64, p *float64) *float64Value {
 }
 
 func (f *float64Value) Set(s string) bool {
-       v, err := strconv.Atof64(s)
+       v, err := strconv.ParseFloat(s, 64)
        *f = float64Value(v)
        return err == nil
 }
index 6713f0a..11e9f19 100644 (file)
        If an operand implements interface Formatter, that interface
        can be used for fine control of formatting.
 
-       Next, if an operand implements the error interface, the Error method
+       If the format (which is implicitly %v for Println etc.) is valid
+       for a string (%s %q %v %x %X), the following two rules also apply:
+
+       1. If an operand implements the error interface, the Error method
        will be used to convert the object to a string, which will then
        be formatted as required by the verb (if any).
 
-       Finally, if an operand implements method String() string that method
+       2. If an operand implements method String() string, that method
        will be used to convert the object to a string, which will then
        be formatted as required by the verb (if any).
+
        To avoid recursion in cases such as
-               type X int
-               func (x X) String() string { return Sprintf("%d", x) }
-       cast the value before recurring:
-               func (x X) String() string { return Sprintf("%d", int(x)) }
+               type X string
+               func (x X) String() string { return Sprintf("<%s>", x) }
+       convert the value before recurring:
+               func (x X) String() string { return Sprintf("<%s>", string(x)) }
 
        Format errors:
 
index 00aac79..63c3338 100644 (file)
@@ -12,6 +12,7 @@ import (
        "runtime" // for the malloc count test only
        "strings"
        "testing"
+       "time"
 )
 
 type (
@@ -352,7 +353,7 @@ var fmttests = []struct {
        {"%s", I(23), `<23>`},
        {"%q", I(23), `"<23>"`},
        {"%x", I(23), `3c32333e`},
-       {"%d", I(23), `%!d(string=<23>)`},
+       {"%d", I(23), `23`}, // Stringer applies only to string formats.
 
        // go syntax
        {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
@@ -361,8 +362,8 @@ var fmttests = []struct {
        {"%#v", make(chan int), "(chan int)(0xPTR)"},
        {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
        {"%#v", 1000000000, "1000000000"},
-       {"%#v", map[string]int{"a": 1}, `map[string] int{"a":1}`},
-       {"%#v", map[string]B{"a": {1, 2}}, `map[string] fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
+       {"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`},
+       {"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
        {"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
        {"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`},
        {"%#v", []int(nil), `[]int(nil)`},
@@ -371,8 +372,8 @@ var fmttests = []struct {
        {"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`},
        {"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
        {"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
-       {"%#v", map[int]byte(nil), `map[int] uint8(nil)`},
-       {"%#v", map[int]byte{}, `map[int] uint8{}`},
+       {"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
+       {"%#v", map[int]byte{}, `map[int]uint8{}`},
 
        // slices with other formats
        {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
@@ -430,6 +431,10 @@ var fmttests = []struct {
        {"%p", make([]int, 1), "0xPTR"},
        {"%p", 27, "%!p(int=27)"}, // not a pointer at all
 
+       // %d on Stringer should give integer if possible
+       {"%s", time.Time{}.Month(), "January"},
+       {"%d", time.Time{}.Month(), "1"},
+
        // erroneous things
        {"%s %", "hello", "hello %!(NOVERB)"},
        {"%s %.2", "hello", "hello %!(NOVERB)"},
@@ -495,69 +500,84 @@ func BenchmarkSprintfPrefixedInt(b *testing.B) {
        }
 }
 
+func BenchmarkSprintfFloat(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               Sprintf("%g", 5.23184)
+       }
+}
+
 func TestCountMallocs(t *testing.T) {
        if testing.Short() {
                return
        }
+       const N = 100
        runtime.UpdateMemStats()
        mallocs := 0 - runtime.MemStats.Mallocs
-       for i := 0; i < 100; i++ {
+       for i := 0; i < N; i++ {
                Sprintf("")
        }
        runtime.UpdateMemStats()
        mallocs += runtime.MemStats.Mallocs
-       Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/100)
+       Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/N)
        runtime.UpdateMemStats()
        mallocs = 0 - runtime.MemStats.Mallocs
-       for i := 0; i < 100; i++ {
+       for i := 0; i < N; i++ {
                Sprintf("xxx")
        }
        runtime.UpdateMemStats()
        mallocs += runtime.MemStats.Mallocs
-       Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/100)
+       Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/N)
        runtime.UpdateMemStats()
        mallocs = 0 - runtime.MemStats.Mallocs
-       for i := 0; i < 100; i++ {
+       for i := 0; i < N; i++ {
                Sprintf("%x", i)
        }
        runtime.UpdateMemStats()
        mallocs += runtime.MemStats.Mallocs
-       Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/100)
+       Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/N)
        runtime.UpdateMemStats()
        mallocs = 0 - runtime.MemStats.Mallocs
-       for i := 0; i < 100; i++ {
+       for i := 0; i < N; i++ {
                Sprintf("%s", "hello")
        }
        runtime.UpdateMemStats()
        mallocs += runtime.MemStats.Mallocs
-       Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/100)
+       Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/N)
        runtime.UpdateMemStats()
        mallocs = 0 - runtime.MemStats.Mallocs
-       for i := 0; i < 100; i++ {
+       for i := 0; i < N; i++ {
                Sprintf("%x %x", i, i)
        }
        runtime.UpdateMemStats()
        mallocs += runtime.MemStats.Mallocs
-       Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/100)
+       Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/N)
+       runtime.UpdateMemStats()
+       mallocs = 0 - runtime.MemStats.Mallocs
+       for i := 0; i < N; i++ {
+               Sprintf("%g", 3.14159)
+       }
+       runtime.UpdateMemStats()
+       mallocs += runtime.MemStats.Mallocs
+       Printf("mallocs per Sprintf(\"%%g\"): %d\n", mallocs/N)
        buf := new(bytes.Buffer)
        runtime.UpdateMemStats()
        mallocs = 0 - runtime.MemStats.Mallocs
-       for i := 0; i < 100; i++ {
+       for i := 0; i < N; i++ {
                buf.Reset()
                Fprintf(buf, "%x %x %x", i, i, i)
        }
        runtime.UpdateMemStats()
        mallocs += runtime.MemStats.Mallocs
-       Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/100)
+       Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/N)
        runtime.UpdateMemStats()
        mallocs = 0 - runtime.MemStats.Mallocs
-       for i := 0; i < 100; i++ {
+       for i := 0; i < N; i++ {
                buf.Reset()
                Fprintf(buf, "%s", "hello")
        }
        runtime.UpdateMemStats()
        mallocs += runtime.MemStats.Mallocs
-       Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/100)
+       Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/N)
 }
 
 type flagPrinter struct{}
@@ -772,9 +792,9 @@ var panictests = []struct {
        out string
 }{
        // String
-       {"%d", (*Panic)(nil), "<nil>"}, // nil pointer special case
-       {"%d", Panic{io.ErrUnexpectedEOF}, "%d(PANIC=unexpected EOF)"},
-       {"%d", Panic{3}, "%d(PANIC=3)"},
+       {"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case
+       {"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
+       {"%s", Panic{3}, "%s(PANIC=3)"},
        // GoString
        {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
        {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"},
index 3957a5a..fbafa9d 100644 (file)
@@ -360,44 +360,44 @@ func (f *fmt) plusSpace(s string) {
 }
 
 // fmt_e64 formats a float64 in the form -1.23e+12.
-func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) }
+func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'e', doPrec(f, 6), 64)) }
 
 // fmt_E64 formats a float64 in the form -1.23E+12.
-func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) }
+func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'E', doPrec(f, 6), 64)) }
 
 // fmt_f64 formats a float64 in the form -1.23.
-func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) }
+func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'f', doPrec(f, 6), 64)) }
 
 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
-func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) }
+func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'g', doPrec(f, -1), 64)) }
 
 // fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
-func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) }
+func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'G', doPrec(f, -1), 64)) }
 
 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
-func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) }
+func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'b', 0, 64)) }
 
 // float32
 // cannot defer to float64 versions
 // because it will get rounding wrong in corner cases.
 
 // fmt_e32 formats a float32 in the form -1.23e+12.
-func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) }
+func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'e', doPrec(f, 6), 32)) }
 
 // fmt_E32 formats a float32 in the form -1.23E+12.
-func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) }
+func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'E', doPrec(f, 6), 32)) }
 
 // fmt_f32 formats a float32 in the form -1.23.
-func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) }
+func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'f', doPrec(f, 6), 32)) }
 
 // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
-func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) }
+func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'g', doPrec(f, -1), 32)) }
 
 // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
-func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) }
+func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'G', doPrec(f, -1), 32)) }
 
 // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
-func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) }
+func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.FormatFloat(float64(v), 'b', 0, 32)) }
 
 // fmt_c64 formats a complex64 according to the verb.
 func (f *fmt) fmt_c64(v complex64, verb rune) {
index e5ca117..8b15a82 100644 (file)
@@ -631,24 +631,30 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
                        return
                }
        } else {
-               // Is it an error or Stringer?
-               // The duplication in the bodies is necessary:
-               // setting wasString and handled and deferring catchPanic
-               // must happen before calling the method.
-               switch v := p.field.(type) {
-               case error:
-                       wasString = false
-                       handled = true
-                       defer p.catchPanic(p.field, verb)
-                       p.printField(v.Error(), verb, plus, false, depth)
-                       return
-
-               case Stringer:
-                       wasString = false
-                       handled = true
-                       defer p.catchPanic(p.field, verb)
-                       p.printField(v.String(), verb, plus, false, depth)
-                       return
+               // If a string is acceptable according to the format, see if
+               // the value satisfies one of the string-valued interfaces.
+               // Println etc. set verb to %v, which is "stringable".
+               switch verb {
+               case 'v', 's', 'x', 'X', 'q':
+                       // Is it an error or Stringer?
+                       // The duplication in the bodies is necessary:
+                       // setting wasString and handled, and deferring catchPanic,
+                       // must happen before calling the method.
+                       switch v := p.field.(type) {
+                       case error:
+                               wasString = false
+                               handled = true
+                               defer p.catchPanic(p.field, verb)
+                               p.printField(v.Error(), verb, plus, false, depth)
+                               return
+
+                       case Stringer:
+                               wasString = false
+                               handled = true
+                               defer p.catchPanic(p.field, verb)
+                               p.printField(v.String(), verb, plus, false, depth)
+                               return
+                       }
                }
        }
        handled = false
index 85571e8..2815251 100644 (file)
@@ -613,7 +613,7 @@ func (s *ss) scanInt(verb rune, bitSize int) int64 {
                }
        }
        tok := s.scanNumber(digits, haveDigits)
-       i, err := strconv.Btoi64(tok, base)
+       i, err := strconv.ParseInt(tok, base, 64)
        if err != nil {
                s.error(err)
        }
@@ -643,7 +643,7 @@ func (s *ss) scanUint(verb rune, bitSize int) uint64 {
                base, digits, haveDigits = s.scanBasePrefix()
        }
        tok := s.scanNumber(digits, haveDigits)
-       i, err := strconv.Btoui64(tok, base)
+       i, err := strconv.ParseUint(tok, base, 64)
        if err != nil {
                s.error(err)
        }
@@ -719,7 +719,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
        if p := strings.Index(str, "p"); p >= 0 {
                // Atof doesn't handle power-of-2 exponents,
                // but they're easy to evaluate.
-               f, err := strconv.AtofN(str[:p], n)
+               f, err := strconv.ParseFloat(str[:p], n)
                if err != nil {
                        // Put full string into error.
                        if e, ok := err.(*strconv.NumError); ok {
@@ -737,7 +737,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
                }
                return math.Ldexp(f, n)
        }
-       f, err := strconv.AtofN(str, n)
+       f, err := strconv.ParseFloat(str, n)
        if err != nil {
                s.error(err)
        }
index c3153ed..89d5af1 100644 (file)
@@ -24,7 +24,7 @@ var tests = []struct {
 
        // maps
        {map[string]int{"a": 1},
-               `0  map[string] int (len = 1) {
+               `0  map[string]int (len = 1) {
                1  .  "a": 1
                2  }`},
 
index d7bb384..c9fb55b 100644 (file)
@@ -7,7 +7,6 @@
 package doc
 
 import (
-       "bytes"
        "go/ast"
        "io"
        "regexp"
@@ -85,39 +84,6 @@ func CommentText(comment *ast.CommentGroup) string {
        return strings.Join(lines, "\n")
 }
 
-// Split bytes into lines.
-func split(text []byte) [][]byte {
-       // count lines
-       n := 0
-       last := 0
-       for i, c := range text {
-               if c == '\n' {
-                       last = i + 1
-                       n++
-               }
-       }
-       if last < len(text) {
-               n++
-       }
-
-       // split
-       out := make([][]byte, n)
-       last = 0
-       n = 0
-       for i, c := range text {
-               if c == '\n' {
-                       out[n] = text[last : i+1]
-                       last = i + 1
-                       n++
-               }
-       }
-       if last < len(text) {
-               out[n] = text[last:]
-       }
-
-       return out
-}
-
 var (
        ldquo = []byte("&ldquo;")
        rdquo = []byte("&rdquo;")
@@ -125,13 +91,13 @@ var (
 
 // Escape comment text for HTML. If nice is set,
 // also turn `` into &ldquo; and '' into &rdquo;.
-func commentEscape(w io.Writer, s []byte, nice bool) {
+func commentEscape(w io.Writer, text string, nice bool) {
        last := 0
        if nice {
-               for i := 0; i < len(s)-1; i++ {
-                       ch := s[i]
-                       if ch == s[i+1] && (ch == '`' || ch == '\'') {
-                               template.HTMLEscape(w, s[last:i])
+               for i := 0; i < len(text)-1; i++ {
+                       ch := text[i]
+                       if ch == text[i+1] && (ch == '`' || ch == '\'') {
+                               template.HTMLEscape(w, []byte(text[last:i]))
                                last = i + 2
                                switch ch {
                                case '`':
@@ -143,7 +109,7 @@ func commentEscape(w io.Writer, s []byte, nice bool) {
                        }
                }
        }
-       template.HTMLEscape(w, s[last:])
+       template.HTMLEscape(w, []byte(text[last:]))
 }
 
 const (
@@ -183,9 +149,9 @@ var (
 // and the word is converted into a link. If nice is set, the remaining text's
 // appearance is improved where it makes sense (e.g., `` is turned into &ldquo;
 // and '' into &rdquo;).
-func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) {
+func emphasize(w io.Writer, line string, words map[string]string, nice bool) {
        for {
-               m := matchRx.FindSubmatchIndex(line)
+               m := matchRx.FindStringSubmatchIndex(line)
                if m == nil {
                        break
                }
@@ -233,7 +199,7 @@ func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) {
        commentEscape(w, line, nice)
 }
 
-func indentLen(s []byte) int {
+func indentLen(s string) int {
        i := 0
        for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
                i++
@@ -241,9 +207,11 @@ func indentLen(s []byte) int {
        return i
 }
 
-func isBlank(s []byte) bool { return len(s) == 0 || (len(s) == 1 && s[0] == '\n') }
+func isBlank(s string) bool {
+       return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
+}
 
-func commonPrefix(a, b []byte) []byte {
+func commonPrefix(a, b string) string {
        i := 0
        for i < len(a) && i < len(b) && a[i] == b[i] {
                i++
@@ -251,7 +219,7 @@ func commonPrefix(a, b []byte) []byte {
        return a[0:i]
 }
 
-func unindent(block [][]byte) {
+func unindent(block []string) {
        if len(block) == 0 {
                return
        }
@@ -273,44 +241,39 @@ func unindent(block [][]byte) {
        }
 }
 
-// heading returns the (possibly trimmed) line if it passes as a valid section
-// heading; otherwise it returns nil
-func heading(line []byte) []byte {
-       line = bytes.TrimSpace(line)
+// heading returns the trimmed line if it passes as a section heading;
+// otherwise it returns the empty string
+func heading(line string) string {
+       line = strings.TrimSpace(line)
        if len(line) == 0 {
-               return nil
+               return ""
        }
 
        // a heading must start with an uppercase letter
-       r, _ := utf8.DecodeRune(line)
+       r, _ := utf8.DecodeRuneInString(line)
        if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
-               return nil
-       }
-
-       // it must end in a letter, digit or ':'
-       r, _ = utf8.DecodeLastRune(line)
-       if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != ':' {
-               return nil
+               return ""
        }
 
-       // strip trailing ':', if any
-       if r == ':' {
-               line = line[0 : len(line)-1]
+       // it must end in a letter or digit:
+       r, _ = utf8.DecodeLastRuneInString(line)
+       if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
+               return ""
        }
 
        // exclude lines with illegal characters
-       if bytes.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
-               return nil
+       if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
+               return ""
        }
 
        // allow "'" for possessive "'s" only
        for b := line; ; {
-               i := bytes.IndexRune(b, '\'')
+               i := strings.IndexRune(b, '\'')
                if i < 0 {
                        break
                }
                if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
-                       return nil // not followed by "s "
+                       return "" // not followed by "s "
                }
                b = b[i+2:]
        }
@@ -335,7 +298,7 @@ func heading(line []byte) []byte {
 // Go identifiers that appear in the words map are italicized; if the corresponding
 // map value is not the empty string, it is considered a URL and the word is converted
 // into a link.
-func ToHTML(w io.Writer, s []byte, words map[string]string) {
+func ToHTML(w io.Writer, text string, words map[string]string) {
        inpara := false
        lastWasBlank := false
        lastWasHeading := false
@@ -353,7 +316,7 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) {
                }
        }
 
-       lines := split(s)
+       lines := strings.SplitAfter(text, "\n")
        unindent(lines)
        for i := 0; i < len(lines); {
                line := lines[i]
@@ -397,10 +360,10 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) {
                        // current line is non-blank, sourounded by blank lines
                        // and the next non-blank line is not indented: this
                        // might be a heading.
-                       if head := heading(line); head != nil {
+                       if head := heading(line); head != "" {
                                close()
                                w.Write(html_h)
-                               template.HTMLEscape(w, head)
+                               commentEscape(w, head, true) // nice text formatting
                                w.Write(html_endh)
                                i += 2
                                lastWasHeading = true
index 870660a..6424053 100644 (file)
@@ -18,7 +18,8 @@ var headingTests = []struct {
        {"Foo 42", true},
        {"", false},
        {"section", false},
-       {"A typical usage:", true},
+       {"A typical usage:", false},
+       {"This code:", false},
        {"δ is Greek", false},
        {"Foo Â§", false},
        {"Fermat's Last Sentence", true},
@@ -26,13 +27,13 @@ var headingTests = []struct {
        {"'sX", false},
        {"Ted 'Too' Bar", false},
        {"Use n+m", false},
-       {"Scanning:", true},
+       {"Scanning:", false},
        {"N:M", false},
 }
 
 func TestIsHeading(t *testing.T) {
        for _, tt := range headingTests {
-               if h := heading([]byte(tt.line)); (h != nil) != tt.ok {
+               if h := heading(tt.line); (len(h) > 0) != tt.ok {
                        t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok)
                }
        }
index 83f2462..838223b 100644 (file)
@@ -43,7 +43,7 @@ func isGoFile(fi os.FileInfo) bool {
 
 func appendHeadings(list []string, comment string) []string {
        var buf bytes.Buffer
-       doc.ToHTML(&buf, []byte(comment), nil)
+       doc.ToHTML(&buf, comment, nil)
        for s := buf.String(); ; {
                i := strings.Index(s, html_h)
                if i < 0 {
index 55b8998..f0a8055 100644 (file)
@@ -2026,7 +2026,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
        // must have exactly one receiver
        if par.NumFields() != 1 {
                p.errorExpected(par.Opening, "exactly one receiver")
-               par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{par.Opening, par.Closing + 1}}}
+               par.List = []*ast.Field{{Type: &ast.BadExpr{par.Opening, par.Closing + 1}}}
                return par
        }
 
@@ -2035,7 +2035,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
        base := deref(recv.Type)
        if _, isIdent := base.(*ast.Ident); !isIdent {
                p.errorExpected(base.Pos(), "(unqualified) identifier")
-               par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
+               par.List = []*ast.Field{{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
        }
 
        return par
index 53f3609..b2a48c2 100644 (file)
@@ -354,7 +354,7 @@ func (p *printer) isOneLineFieldList(list []*ast.Field) bool {
 }
 
 func (p *printer) setLineComment(text string) {
-       p.setComment(&ast.CommentGroup{[]*ast.Comment{&ast.Comment{token.NoPos, text}}})
+       p.setComment(&ast.CommentGroup{[]*ast.Comment{{token.NoPos, text}}})
 }
 
 func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
index 2d27af4..89e341c 100644 (file)
@@ -1999,7 +1999,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
        if par.NumFields() != 1 {
                p.errorExpected(pos, "exactly one receiver")
                // TODO determine a better range for BadExpr below
-               par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{pos, pos}}}
+               par.List = []*ast.Field{{Type: &ast.BadExpr{pos, pos}}}
                return par
        }
 
@@ -2008,7 +2008,7 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
        base := deref(recv.Type)
        if _, isIdent := base.(*ast.Ident); !isIdent {
                p.errorExpected(base.Pos(), "(unqualified) identifier")
-               par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
+               par.List = []*ast.Field{{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
        }
 
        return par
index 0d7765d..8598f4e 100644 (file)
@@ -13,9 +13,9 @@ type Hash interface {
        // It never returns an error.
        io.Writer
 
-       // Sum appends the current hash in the same manner as append(), without
-       // changing the underlying hash state.
-       Sum(in []byte) []byte
+       // Sum appends the current hash to b and returns the resulting slice.
+       // It does not change the underlying hash state.
+       Sum(b []byte) []byte
 
        // Reset resets the hash to one with zero bytes written.
        Reset()
index 97fbc51..dd2d816 100644 (file)
@@ -515,7 +515,19 @@ func afterHeadIM(p *parser) bool {
                implied    bool
        )
        switch p.tok.Type {
-       case ErrorToken, TextToken:
+       case ErrorToken:
+               implied = true
+               framesetOK = true
+       case TextToken:
+               s := strings.TrimLeft(p.tok.Data, whitespace)
+               if len(s) < len(p.tok.Data) {
+                       // Add the initial whitespace to the current node.
+                       p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+                       if s == "" {
+                               return true
+                       }
+                       p.tok.Data = s
+               }
                implied = true
                framesetOK = true
        case StartTagToken:
@@ -535,7 +547,8 @@ func afterHeadIM(p *parser) bool {
                        defer p.oe.pop()
                        return inHeadIM(p)
                case "head":
-                       // TODO.
+                       // Ignore the token.
+                       return true
                default:
                        implied = true
                        framesetOK = true
index e0c19cf..5062a6e 100644 (file)
@@ -167,6 +167,7 @@ func TestParser(t *testing.T) {
                {"tests3.dat", -1},
                {"tests4.dat", -1},
                {"tests5.dat", -1},
+               {"tests6.dat", 7},
        }
        for _, tf := range testFiles {
                f, err := os.Open("testdata/webkit/" + tf.filename)
index d166a3b..0584f35 100644 (file)
@@ -14,63 +14,63 @@ func TestRenderer(t *testing.T) {
                Type: ElementNode,
                Data: "html",
                Child: []*Node{
-                       &Node{
+                       {
                                Type: ElementNode,
                                Data: "head",
                        },
-                       &Node{
+                       {
                                Type: ElementNode,
                                Data: "body",
                                Child: []*Node{
-                                       &Node{
+                                       {
                                                Type: TextNode,
                                                Data: "0<1",
                                        },
-                                       &Node{
+                                       {
                                                Type: ElementNode,
                                                Data: "p",
                                                Attr: []Attribute{
-                                                       Attribute{
+                                                       {
                                                                Key: "id",
                                                                Val: "A",
                                                        },
-                                                       Attribute{
+                                                       {
                                                                Key: "foo",
                                                                Val: `abc"def`,
                                                        },
                                                },
                                                Child: []*Node{
-                                                       &Node{
+                                                       {
                                                                Type: TextNode,
                                                                Data: "2",
                                                        },
-                                                       &Node{
+                                                       {
                                                                Type: ElementNode,
                                                                Data: "b",
                                                                Attr: []Attribute{
-                                                                       Attribute{
+                                                                       {
                                                                                Key: "empty",
                                                                                Val: "",
                                                                        },
                                                                },
                                                                Child: []*Node{
-                                                                       &Node{
+                                                                       {
                                                                                Type: TextNode,
                                                                                Data: "3",
                                                                        },
                                                                },
                                                        },
-                                                       &Node{
+                                                       {
                                                                Type: ElementNode,
                                                                Data: "i",
                                                                Attr: []Attribute{
-                                                                       Attribute{
+                                                                       {
                                                                                Key: "backslash",
                                                                                Val: `\`,
                                                                        },
                                                                },
                                                                Child: []*Node{
-                                                                       &Node{
+                                                                       {
                                                                                Type: TextNode,
                                                                                Data: "&4",
                                                                        },
@@ -78,19 +78,19 @@ func TestRenderer(t *testing.T) {
                                                        },
                                                },
                                        },
-                                       &Node{
+                                       {
                                                Type: TextNode,
                                                Data: "5",
                                        },
-                                       &Node{
+                                       {
                                                Type: ElementNode,
                                                Data: "blockquote",
                                        },
-                                       &Node{
+                                       {
                                                Type: ElementNode,
                                                Data: "br",
                                        },
-                                       &Node{
+                                       {
                                                Type: TextNode,
                                                Data: "6",
                                        },
index 0d94bdc..a735638 100644 (file)
@@ -113,7 +113,7 @@ func TestDecodeCSS(t *testing.T) {
 
 func TestHexDecode(t *testing.T) {
        for i := 0; i < 0x200000; i += 101 /* coprime with 16 */ {
-               s := strconv.Itob(i, 16)
+               s := strconv.FormatInt(int64(i), 16)
                if got := int(hexDecode([]byte(s))); got != i {
                        t.Errorf("%s: want %d but got %d", s, i, got)
                }
index 4a7a935..2f6be3b 100644 (file)
@@ -716,7 +716,7 @@ func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {
 // commit applies changes to actions and template calls needed to contextually
 // autoescape content and adds any derived templates to the set.
 func (e *escaper) commit() {
-       for name, _ := range e.output {
+       for name := range e.output {
                e.template(name).Funcs(funcMap)
        }
        for _, t := range e.derived {
index b4daca7..cdeed48 100644 (file)
@@ -689,11 +689,11 @@ func TestEscapeSet(t *testing.T) {
 
        data := dataItem{
                Children: []*dataItem{
-                       &dataItem{X: "foo"},
-                       &dataItem{X: "<bar>"},
-                       &dataItem{
+                       {X: "foo"},
+                       {X: "<bar>"},
+                       {
                                Children: []*dataItem{
-                                       &dataItem{X: "baz"},
+                                       {X: "baz"},
                                },
                        },
                },
@@ -1597,7 +1597,7 @@ func TestRedundantFuncs(t *testing.T) {
 
        for n0, m := range redundantFuncs {
                f0 := funcMap[n0].(func(...interface{}) string)
-               for n1, _ := range m {
+               for n1 := range m {
                        f1 := funcMap[n1].(func(...interface{}) string)
                        for _, input := range inputs {
                                want := f0(input)
index f05ca19..fa2ed18 100644 (file)
@@ -47,23 +47,22 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
        return t.text.Execute(wr, data)
 }
 
-// ExecuteTemplate applies the template associated with t that has the given name
-// to the specified data object and writes the output to wr.
+// ExecuteTemplate applies the template associated with t that has the given
+// name to the specified data object and writes the output to wr.
 func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) (err error) {
        t.nameSpace.mu.Lock()
        tmpl := t.set[name]
-       if tmpl == nil {
-               t.nameSpace.mu.Unlock()
-               return fmt.Errorf("template: no template %q associated with template %q", name, t.Name())
+       if (tmpl == nil) != (t.text.Lookup(name) == nil) {
+               panic("html/template internal error: template escaping out of sync")
        }
-       if !tmpl.escaped {
+       if tmpl != nil && !tmpl.escaped {
                err = escapeTemplates(tmpl, name)
        }
        t.nameSpace.mu.Unlock()
        if err != nil {
                return
        }
-       return tmpl.text.ExecuteTemplate(wr, name, data)
+       return t.text.ExecuteTemplate(wr, name, data)
 }
 
 // Parse parses a string into a template. Nested template definitions
@@ -106,7 +105,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) error {
 
 // Clone is unimplemented.
 func (t *Template) Clone(name string) error {
-       return fmt.Errorf("html/template: Add unimplemented")
+       return fmt.Errorf("html/template: Clone unimplemented")
 }
 
 // New allocates a new HTML template with the given name.
index 4a0fae5..2948db7 100644 (file)
@@ -134,13 +134,22 @@ type Model interface {
        Convert(c Color) Color
 }
 
-// ModelFunc is an adapter type to allow the use of a color conversion
-// function as a Model. If f is such a function, ModelFunc(f) is a Model that
-// invokes f to implement the conversion.
-type ModelFunc func(Color) Color
+// ModelFunc returns a Model that invokes f to implement the conversion.
+func ModelFunc(f func(Color) Color) Model {
+       // Note: using *modelFunc as the implementation
+       // means that callers can still use comparisons
+       // like m == RGBAModel.  This is not possible if
+       // we use the func value directly, because funcs
+       // are no longer comparable.
+       return &modelFunc{f}
+}
+
+type modelFunc struct {
+       f func(Color) Color
+}
 
-func (f ModelFunc) Convert(c Color) Color {
-       return f(c)
+func (m *modelFunc) Convert(c Color) Color {
+       return m.f(c)
 }
 
 // RGBAModel is the Model for RGBA colors.
index a7ad51d..a7d1a57 100644 (file)
@@ -20,7 +20,7 @@ var (
 )
 
 // Uniform is an infinite-sized Image of uniform color.
-// It implements both the color.Color and Image interfaces.
+// It implements the color.Color, color.ColorModel, and Image interfaces.
 type Uniform struct {
        C color.Color
 }
@@ -30,7 +30,11 @@ func (c *Uniform) RGBA() (r, g, b, a uint32) {
 }
 
 func (c *Uniform) ColorModel() color.Model {
-       return color.ModelFunc(func(color.Color) color.Color { return c.C })
+       return c
+}
+
+func (c *Uniform) Convert(color.Color) color.Color {
+       return c.C
 }
 
 func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
index 48089ff..641eae1 100644 (file)
@@ -429,7 +429,7 @@ func Encode(w io.Writer, m image.Image) error {
        // also rejected.
        mw, mh := int64(m.Bounds().Dx()), int64(m.Bounds().Dy())
        if mw <= 0 || mh <= 0 || mw >= 1<<32 || mh >= 1<<32 {
-               return FormatError("invalid image size: " + strconv.Itoa64(mw) + "x" + strconv.Itoa64(mw))
+               return FormatError("invalid image size: " + strconv.FormatInt(mw, 10) + "x" + strconv.FormatInt(mw, 10))
        }
 
        var e encoder
index 9e553a2..b2a3f8a 100644 (file)
@@ -110,7 +110,7 @@ var _cos = [...]float64{
 
 // Cos returns the cosine of x.
 //
-// Special conditions are:
+// Special cases are:
 //     Cos(±Inf) = NaN
 //     Cos(NaN) = NaN
 func Cos(x float64) float64 {
index f5412fd..7429425 100644 (file)
@@ -8,7 +8,7 @@ package math
 
 // Sincos(x) returns Sin(x), Cos(x).
 //
-// Special conditions are:
+// Special cases are:
 //     Sincos(±0) = Â±0, 1
 //     Sincos(±Inf) = NaN, NaN
 //     Sincos(NaN) = NaN, NaN
index eaf28a5..139b911 100644 (file)
@@ -17,6 +17,11 @@ package math
 */
 
 // Sinh returns the hyperbolic sine of x.
+//
+// Special cases are:
+//     Sinh(±0) = Â±0
+//     Sinh(±Inf) = Â±Inf
+//     Sinh(NaN) = NaN
 func Sinh(x float64) float64 {
        // The coefficients are #2029 from Hart & Cheney. (20.36D)
        const (
@@ -56,6 +61,11 @@ func Sinh(x float64) float64 {
 }
 
 // Cosh returns the hyperbolic cosine of x.
+//
+// Special cases are:
+//     Cosh(±0) = 1
+//     Cosh(±Inf) = +Inf
+//     Cosh(NaN) = NaN
 func Cosh(x float64) float64 {
        if x < 0 {
                x = -x
index 739ee80..76131fc 100644 (file)
@@ -75,7 +75,7 @@ var _tanQ = [...]float64{
 
 // Tan returns the tangent of x.
 //
-// Special conditions are:
+// Special cases are:
 //     Tan(±0) = Â±0
 //     Tan(±Inf) = NaN
 //     Tan(NaN) = NaN
index f4a8a5a..03a641b 100644 (file)
@@ -12,6 +12,11 @@ package math
 */
 
 // Tanh computes the hyperbolic tangent of x.
+//
+// Special cases are:
+//     Tanh(±0) = Â±0
+//     Tanh(±Inf) = Â±1
+//     Tanh(NaN) = NaN
 func Tanh(x float64) float64 {
        if x < 0 {
                x = -x
index e188cd4..e6c3ef9 100644 (file)
@@ -70,7 +70,7 @@ func RequestFromMap(params map[string]string) (*http.Request, error) {
        r.Host = params["HTTP_HOST"]
 
        if lenstr := params["CONTENT_LENGTH"]; lenstr != "" {
-               clen, err := strconv.Atoi64(lenstr)
+               clen, err := strconv.ParseInt(lenstr, 10, 64)
                if err != nil {
                        return nil, errors.New("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
                }
index 74c41aa..60a478f 100644 (file)
@@ -48,7 +48,7 @@ func (cr *chunkedReader) beginChunk() {
        if cr.err != nil {
                return
        }
-       cr.n, cr.err = strconv.Btoui64(line, 16)
+       cr.n, cr.err = strconv.ParseUint(line, 16, 64)
        if cr.err != nil {
                return
        }
@@ -147,7 +147,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
                return 0, nil
        }
 
-       head := strconv.Itob(len(data), 16) + "\r\n"
+       head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
 
        if _, err = io.WriteString(cw.Wire, head); err != nil {
                return 0, err
index 26bff93..712350d 100644 (file)
@@ -81,14 +81,14 @@ var addCookieTests = []struct {
                "",
        },
        {
-               []*Cookie{&Cookie{Name: "cookie-1", Value: "v$1"}},
+               []*Cookie{{Name: "cookie-1", Value: "v$1"}},
                "cookie-1=v$1",
        },
        {
                []*Cookie{
-                       &Cookie{Name: "cookie-1", Value: "v$1"},
-                       &Cookie{Name: "cookie-2", Value: "v$2"},
-                       &Cookie{Name: "cookie-3", Value: "v$3"},
+                       {Name: "cookie-1", Value: "v$1"},
+                       {Name: "cookie-2", Value: "v$2"},
+                       {Name: "cookie-3", Value: "v$3"},
                },
                "cookie-1=v$1; cookie-2=v$2; cookie-3=v$3",
        },
@@ -113,11 +113,11 @@ var readSetCookiesTests = []struct {
 }{
        {
                Header{"Set-Cookie": {"Cookie-1=v$1"}},
-               []*Cookie{&Cookie{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
+               []*Cookie{{Name: "Cookie-1", Value: "v$1", Raw: "Cookie-1=v$1"}},
        },
        {
                Header{"Set-Cookie": {"NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly"}},
-               []*Cookie{&Cookie{
+               []*Cookie{{
                        Name:       "NID",
                        Value:      "99=YsDT5i3E-CXax-",
                        Path:       "/",
@@ -159,30 +159,30 @@ var readCookiesTests = []struct {
                Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
                "",
                []*Cookie{
-                       &Cookie{Name: "Cookie-1", Value: "v$1"},
-                       &Cookie{Name: "c2", Value: "v2"},
+                       {Name: "Cookie-1", Value: "v$1"},
+                       {Name: "c2", Value: "v2"},
                },
        },
        {
                Header{"Cookie": {"Cookie-1=v$1", "c2=v2"}},
                "c2",
                []*Cookie{
-                       &Cookie{Name: "c2", Value: "v2"},
+                       {Name: "c2", Value: "v2"},
                },
        },
        {
                Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
                "",
                []*Cookie{
-                       &Cookie{Name: "Cookie-1", Value: "v$1"},
-                       &Cookie{Name: "c2", Value: "v2"},
+                       {Name: "Cookie-1", Value: "v$1"},
+                       {Name: "c2", Value: "v2"},
                },
        },
        {
                Header{"Cookie": {"Cookie-1=v$1; c2=v2"}},
                "c2",
                []*Cookie{
-                       &Cookie{Name: "c2", Value: "v2"},
+                       {Name: "c2", Value: "v2"},
                },
        },
 }
index 70e7849..1392ca6 100644 (file)
@@ -220,7 +220,7 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
 
        w.Header().Set("Accept-Ranges", "bytes")
        if w.Header().Get("Content-Encoding") == "" {
-               w.Header().Set("Content-Length", strconv.Itoa64(size))
+               w.Header().Set("Content-Length", strconv.FormatInt(size, 10))
        }
 
        w.WriteHeader(code)
@@ -295,7 +295,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
                if start == "" {
                        // If no start is specified, end specifies the
                        // range start relative to the end of the file.
-                       i, err := strconv.Atoi64(end)
+                       i, err := strconv.ParseInt(end, 10, 64)
                        if err != nil {
                                return nil, errors.New("invalid range")
                        }
@@ -305,7 +305,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
                        r.start = size - i
                        r.length = size - r.start
                } else {
-                       i, err := strconv.Atoi64(start)
+                       i, err := strconv.ParseInt(start, 10, 64)
                        if err != nil || i > size || i < 0 {
                                return nil, errors.New("invalid range")
                        }
@@ -314,7 +314,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
                                // If no end is specified, range extends to end of the file.
                                r.length = size - r.start
                        } else {
-                               i, err := strconv.Atoi64(end)
+                               i, err := strconv.ParseInt(end, 10, 64)
                                if err != nil || r.start > i {
                                        return nil, errors.New("invalid range")
                                }
index 69bcc0e..29eaf34 100644 (file)
@@ -50,7 +50,7 @@ func (cr *chunkedReader) beginChunk() {
        if cr.err != nil {
                return
        }
-       cr.n, cr.err = strconv.Btoui64(line, 16)
+       cr.n, cr.err = strconv.ParseUint(line, 16, 64)
        if cr.err != nil {
                return
        }
@@ -149,7 +149,7 @@ func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
                return 0, nil
        }
 
-       head := strconv.Itob(len(data), 16) + "\r\n"
+       head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
 
        if _, err = io.WriteString(cw.Wire, head); err != nil {
                return 0, err
index 2de1475..21eac47 100644 (file)
@@ -63,7 +63,7 @@ func Heap(w http.ResponseWriter, r *http.Request) {
 // Profile responds with the pprof-formatted cpu profile.
 // The package initialization registers it as /debug/pprof/profile.
 func Profile(w http.ResponseWriter, r *http.Request) {
-       sec, _ := strconv.Atoi64(r.FormValue("seconds"))
+       sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
        if sec == 0 {
                sec = 30
        }
@@ -111,7 +111,7 @@ func Symbol(w http.ResponseWriter, r *http.Request) {
                if err == nil {
                        word = word[0 : len(word)-1] // trim +
                }
-               pc, _ := strconv.Btoui64(string(word), 0)
+               pc, _ := strconv.ParseUint(string(word), 0, 64)
                if pc != 0 {
                        f := runtime.FuncForPC(uintptr(pc))
                        if f != nil {
index 125f3f2..c100e4d 100644 (file)
@@ -288,7 +288,7 @@ func (w *response) WriteHeader(code int) {
        var contentLength int64
        if clenStr := w.header.Get("Content-Length"); clenStr != "" {
                var err error
-               contentLength, err = strconv.Atoi64(clenStr)
+               contentLength, err = strconv.ParseInt(clenStr, 10, 64)
                if err == nil {
                        hasCL = true
                } else {
index d25c8fc..ef9564a 100644 (file)
@@ -147,7 +147,7 @@ func (t *transferWriter) WriteHeader(w io.Writer) (err error) {
        // TransferEncoding)
        if t.shouldSendContentLength() {
                io.WriteString(w, "Content-Length: ")
-               _, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
+               _, err = io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n")
                if err != nil {
                        return
                }
@@ -432,7 +432,7 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
        // Logic based on Content-Length
        cl := strings.TrimSpace(header.Get("Content-Length"))
        if cl != "" {
-               n, err := strconv.Atoi64(cl)
+               n, err := strconv.ParseInt(cl, 10, 64)
                if err != nil || n < 0 {
                        return -1, &badStringError{"bad Content-Length", cl}
                }
index e622e41..dc70be4 100644 (file)
@@ -519,17 +519,11 @@ func (pc *persistConn) readLoop() {
 
        for alive {
                pb, err := pc.br.Peek(1)
-               if err != nil {
-                       if remoteSideClosed(err) && !pc.expectingResponse() {
-                               // Remote side closed on us.  (We probably hit their
-                               // max idle timeout)
-                               pc.close()
-                               return
-                       }
-               }
                if !pc.expectingResponse() {
-                       log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
-                               string(pb), err)
+                       if len(pb) > 0 {
+                               log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
+                                       string(pb), err)
+                       }
                        pc.close()
                        return
                }
diff --git a/libgo/go/net/http/transport_windows.go b/libgo/go/net/http/transport_windows.go
deleted file mode 100644 (file)
index c9ef2c2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http
-
-import (
-       "net"
-       "syscall"
-)
-
-func init() {
-       remoteSideClosedFunc = func(err error) (out bool) {
-               op, ok := err.(*net.OpError)
-               if ok && op.Op == "WSARecv" && op.Net == "tcp" && op.Err == syscall.Errno(10058) {
-                       // TODO(brainman,rsc): Fix whatever is generating this.
-                       return true
-               }
-               return false
-       }
-}
index 3bb99f9..d3cb38a 100644 (file)
@@ -267,16 +267,6 @@ func ListenIP(netProto string, laddr *IPAddr) (c *IPConn, err error) {
        return newIPConn(fd), nil
 }
 
-// BindToDevice binds an IPConn to a network interface.
-func (c *IPConn) BindToDevice(device string) error {
-       if !c.ok() {
-               return os.EINVAL
-       }
-       c.fd.incref()
-       defer c.fd.decref()
-       return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device))
-}
-
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.
index e1afa32..bf22c71 100644 (file)
@@ -481,7 +481,7 @@ func (qd qDecoder) Read(p []byte) (n int, err error) {
                if _, err := io.ReadFull(qd.r, qd.scratch[:2]); err != nil {
                        return 0, err
                }
-               x, err := strconv.Btoi64(string(qd.scratch[:2]), 16)
+               x, err := strconv.ParseInt(string(qd.scratch[:2]), 16, 64)
                if err != nil {
                        return 0, fmt.Errorf("mail: invalid RFC 2047 encoding: %q", qd.scratch[:2])
                }
index 1f71cc4..671ff2e 100644 (file)
@@ -105,7 +105,7 @@ func TestDateParsing(t *testing.T) {
                        t.Errorf("Failed parsing %q: %v", test.dateStr, err)
                        continue
                }
-               if !reflect.DeepEqual(date, test.exp) {
+               if !date.Equal(test.exp) {
                        t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp)
                }
        }
@@ -119,14 +119,14 @@ func TestAddressParsing(t *testing.T) {
                // Bare address
                {
                        `jdoe@machine.example`,
-                       []*Address{&Address{
+                       []*Address{{
                                Address: "jdoe@machine.example",
                        }},
                },
                // RFC 5322, Appendix A.1.1
                {
                        `John Doe <jdoe@machine.example>`,
-                       []*Address{&Address{
+                       []*Address{{
                                Name:    "John Doe",
                                Address: "jdoe@machine.example",
                        }},
@@ -134,7 +134,7 @@ func TestAddressParsing(t *testing.T) {
                // RFC 5322, Appendix A.1.2
                {
                        `"Joe Q. Public" <john.q.public@example.com>`,
-                       []*Address{&Address{
+                       []*Address{{
                                Name:    "Joe Q. Public",
                                Address: "john.q.public@example.com",
                        }},
@@ -142,14 +142,14 @@ func TestAddressParsing(t *testing.T) {
                {
                        `Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>`,
                        []*Address{
-                               &Address{
+                               {
                                        Name:    "Mary Smith",
                                        Address: "mary@x.test",
                                },
-                               &Address{
+                               {
                                        Address: "jdoe@example.org",
                                },
-                               &Address{
+                               {
                                        Name:    "Who?",
                                        Address: "one@y.test",
                                },
@@ -158,10 +158,10 @@ func TestAddressParsing(t *testing.T) {
                {
                        `<boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>`,
                        []*Address{
-                               &Address{
+                               {
                                        Address: "boss@nil.test",
                                },
-                               &Address{
+                               {
                                        Name:    `Giant; "Big" Box`,
                                        Address: "sysservices@example.net",
                                },
@@ -174,7 +174,7 @@ func TestAddressParsing(t *testing.T) {
                {
                        `=?iso-8859-1?q?J=F6rg_Doe?= <joerg@example.com>`,
                        []*Address{
-                               &Address{
+                               {
                                        Name:    `Jörg Doe`,
                                        Address: "joerg@example.com",
                                },
@@ -184,7 +184,7 @@ func TestAddressParsing(t *testing.T) {
                {
                        `=?utf-8?q?J=C3=B6rg_Doe?= <joerg@example.com>`,
                        []*Address{
-                               &Address{
+                               {
                                        Name:    `Jörg Doe`,
                                        Address: "joerg@example.com",
                                },
@@ -194,7 +194,7 @@ func TestAddressParsing(t *testing.T) {
                {
                        `=?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>`,
                        []*Address{
-                               &Address{
+                               {
                                        Name:    `André Pirard`,
                                        Address: "PIRARD@vm1.ulg.ac.be",
                                },
@@ -204,7 +204,7 @@ func TestAddressParsing(t *testing.T) {
                {
                        `=?ISO-8859-1?B?SvZyZw==?= <joerg@example.com>`,
                        []*Address{
-                               &Address{
+                               {
                                        Name:    `Jörg`,
                                        Address: "joerg@example.com",
                                },
@@ -214,7 +214,7 @@ func TestAddressParsing(t *testing.T) {
                {
                        `=?UTF-8?B?SsO2cmc=?= <joerg@example.com>`,
                        []*Address{
-                               &Address{
+                               {
                                        Name:    `Jörg`,
                                        Address: "joerg@example.com",
                                },
index 33f11f2..777f204 100644 (file)
@@ -111,11 +111,6 @@ func setReuseAddr(fd *netFD, reuse bool) error {
        return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
 }
 
-func bindToDevice(fd *netFD, dev string) error {
-       // TODO(rsc): call setsockopt with null-terminated string pointer
-       return os.EINVAL
-}
-
 func setDontRoute(fd *netFD, dontroute bool) error {
        fd.incref()
        defer fd.decref()
index 2cfcc60..c25ec9c 100644 (file)
@@ -240,16 +240,6 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
        return newUDPConn(fd), nil
 }
 
-// BindToDevice binds a UDPConn to a network interface.
-func (c *UDPConn) BindToDevice(device string) error {
-       if !c.ok() {
-               return os.EINVAL
-       }
-       c.fd.incref()
-       defer c.fd.decref()
-       return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device))
-}
-
 // File returns a copy of the underlying os.File, set to blocking mode.
 // It is the caller's responsibility to close f when finished.
 // Closing c does not affect f, and closing f does not affect c.
index b8c8064..e1bfa47 100644 (file)
@@ -424,11 +424,11 @@ func (t *Template) newVariable(words []string) *variableElement {
                        }
 
                case '.', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
-                       v, err := strconv.Btoi64(word, 0)
+                       v, err := strconv.ParseInt(word, 0, 64)
                        if err == nil {
                                args[i] = v
                        } else {
-                               v, err := strconv.Atof64(word)
+                               v, err := strconv.ParseFloat(word, 64)
                                args[i], lerr = v, err
                        }
 
index 9462c7e..a6e0c3e 100644 (file)
@@ -105,108 +105,108 @@ var formatters = FormatterMap{
 
 var tests = []*Test{
        // Simple
-       &Test{"", "", ""},
-       &Test{"abc", "abc", ""},
-       &Test{"abc\ndef\n", "abc\ndef\n", ""},
-       &Test{" {.meta-left}   \n", "{", ""},
-       &Test{" {.meta-right}   \n", "}", ""},
-       &Test{" {.space}   \n", " ", ""},
-       &Test{" {.tab}   \n", "\t", ""},
-       &Test{"     {#comment}   \n", "", ""},
-       &Test{"\tSome Text\t\n", "\tSome Text\t\n", ""},
-       &Test{" {.meta-right} {.meta-right} {.meta-right} \n", " } } } \n", ""},
+       {"", "", ""},
+       {"abc", "abc", ""},
+       {"abc\ndef\n", "abc\ndef\n", ""},
+       {" {.meta-left}   \n", "{", ""},
+       {" {.meta-right}   \n", "}", ""},
+       {" {.space}   \n", " ", ""},
+       {" {.tab}   \n", "\t", ""},
+       {"     {#comment}   \n", "", ""},
+       {"\tSome Text\t\n", "\tSome Text\t\n", ""},
+       {" {.meta-right} {.meta-right} {.meta-right} \n", " } } } \n", ""},
 
        // Variables at top level
-       &Test{
+       {
                in: "{Header}={Integer}\n",
 
                out: "Header=77\n",
        },
 
-       &Test{
+       {
                in: "Pointers: {*HeaderPtr}={*IntegerPtr}\n",
 
                out: "Pointers: Header=77\n",
        },
 
-       &Test{
+       {
                in: "Stars but not pointers: {*Header}={*Integer}\n",
 
                out: "Stars but not pointers: Header=77\n",
        },
 
-       &Test{
+       {
                in: "nil pointer: {*NilPtr}={*Integer}\n",
 
                out: "nil pointer: <nil>=77\n",
        },
 
-       &Test{
+       {
                in: `{"Strings" ":"} {""} {"|"} {"\t\u0123 \x23\\"} {"\"}{\\"}`,
 
                out: "Strings:  | \t\u0123 \x23\\ \"}{\\",
        },
 
-       &Test{
+       {
                in: "{`Raw strings` `:`} {``} {`|`} {`\\t\\u0123 \\x23\\`} {`}{\\`}",
 
                out: "Raw strings:  | \\t\\u0123 \\x23\\ }{\\",
        },
 
-       &Test{
+       {
                in: "Characters: {'a'} {'\\u0123'} {' '} {'{'} {'|'} {'}'}",
 
                out: "Characters: 97 291 32 123 124 125",
        },
 
-       &Test{
+       {
                in: "Integers: {1} {-2} {+42} {0777} {0x0a}",
 
                out: "Integers: 1 -2 42 511 10",
        },
 
-       &Test{
+       {
                in: "Floats: {.5} {-.5} {1.1} {-2.2} {+42.1} {1e10} {1.2e-3} {1.2e3} {-1.2e3}",
 
                out: "Floats: 0.5 -0.5 1.1 -2.2 42.1 1e+10 0.0012 1200 -1200",
        },
 
        // Method at top level
-       &Test{
+       {
                in: "ptrmethod={PointerMethod}\n",
 
                out: "ptrmethod=ptrmethod!\n",
        },
 
-       &Test{
+       {
                in: "valmethod={ValueMethod}\n",
 
                out: "valmethod=valmethod!\n",
        },
 
        // Section
-       &Test{
+       {
                in: "{.section Data }\n" +
                        "some text for the section\n" +
                        "{.end}\n",
 
                out: "some text for the section\n",
        },
-       &Test{
+       {
                in: "{.section Data }\n" +
                        "{Header}={Integer}\n" +
                        "{.end}\n",
 
                out: "Header=77\n",
        },
-       &Test{
+       {
                in: "{.section Pdata }\n" +
                        "{Header}={Integer}\n" +
                        "{.end}\n",
 
                out: "Header=77\n",
        },
-       &Test{
+       {
                in: "{.section Pdata }\n" +
                        "data present\n" +
                        "{.or}\n" +
@@ -215,7 +215,7 @@ var tests = []*Test{
 
                out: "data present\n",
        },
-       &Test{
+       {
                in: "{.section Empty }\n" +
                        "data present\n" +
                        "{.or}\n" +
@@ -224,7 +224,7 @@ var tests = []*Test{
 
                out: "data not present\n",
        },
-       &Test{
+       {
                in: "{.section Null }\n" +
                        "data present\n" +
                        "{.or}\n" +
@@ -233,7 +233,7 @@ var tests = []*Test{
 
                out: "data not present\n",
        },
-       &Test{
+       {
                in: "{.section Pdata }\n" +
                        "{Header}={Integer}\n" +
                        "{.section @ }\n" +
@@ -245,20 +245,20 @@ var tests = []*Test{
                        "Header=77\n",
        },
 
-       &Test{
+       {
                in: "{.section Data}{.end} {Header}\n",
 
                out: " Header\n",
        },
 
-       &Test{
+       {
                in: "{.section Integer}{@}{.end}",
 
                out: "77",
        },
 
        // Repeated
-       &Test{
+       {
                in: "{.section Pdata }\n" +
                        "{.repeated section @ }\n" +
                        "{Item}={Value}\n" +
@@ -268,7 +268,7 @@ var tests = []*Test{
                out: "ItemNumber1=ValueNumber1\n" +
                        "ItemNumber2=ValueNumber2\n",
        },
-       &Test{
+       {
                in: "{.section Pdata }\n" +
                        "{.repeated section @ }\n" +
                        "{Item}={Value}\n" +
@@ -280,7 +280,7 @@ var tests = []*Test{
                out: "ItemNumber1=ValueNumber1\n" +
                        "ItemNumber2=ValueNumber2\n",
        },
-       &Test{
+       {
                in: "{.section @ }\n" +
                        "{.repeated section Empty }\n" +
                        "{Item}={Value}\n" +
@@ -291,7 +291,7 @@ var tests = []*Test{
 
                out: "this should appear: empty field\n",
        },
-       &Test{
+       {
                in: "{.repeated section Pdata }\n" +
                        "{Item}\n" +
                        "{.alternates with}\n" +
@@ -302,7 +302,7 @@ var tests = []*Test{
                        "is\nover\nmultiple\nlines\n" +
                        "ItemNumber2\n",
        },
-       &Test{
+       {
                in: "{.repeated section Pdata }\n" +
                        "{Item}\n" +
                        "{.alternates with}\n" +
@@ -313,7 +313,7 @@ var tests = []*Test{
                        "is\nover\nmultiple\nlines\n" +
                        "ItemNumber2\n",
        },
-       &Test{
+       {
                in: "{.section Pdata }\n" +
                        "{.repeated section @ }\n" +
                        "{Item}={Value}\n" +
@@ -327,7 +327,7 @@ var tests = []*Test{
                        "DIVIDER\n" +
                        "ItemNumber2=ValueNumber2\n",
        },
-       &Test{
+       {
                in: "{.repeated section Vec }\n" +
                        "{@}\n" +
                        "{.end}\n",
@@ -336,27 +336,27 @@ var tests = []*Test{
                        "elt2\n",
        },
        // Same but with a space before {.end}: was a bug.
-       &Test{
+       {
                in: "{.repeated section Vec }\n" +
                        "{@} {.end}\n",
 
                out: "elt1 elt2 \n",
        },
-       &Test{
+       {
                in: "{.repeated section Integer}{.end}",
 
                err: "line 1: .repeated: cannot repeat Integer (type int)",
        },
 
        // Nested names
-       &Test{
+       {
                in: "{.section @ }\n" +
                        "{InnerT.Item}={InnerT.Value}\n" +
                        "{.end}",
 
                out: "ItemNumber1=ValueNumber1\n",
        },
-       &Test{
+       {
                in: "{.section @ }\n" +
                        "{InnerT.Item}={.section InnerT}{.section Value}{@}{.end}{.end}\n" +
                        "{.end}",
@@ -364,14 +364,14 @@ var tests = []*Test{
                out: "ItemNumber1=ValueNumber1\n",
        },
 
-       &Test{
+       {
                in: "{.section Emptystring}emptystring{.end}\n" +
                        "{.section Header}header{.end}\n",
 
                out: "\nheader\n",
        },
 
-       &Test{
+       {
                in: "{.section True}1{.or}2{.end}\n" +
                        "{.section False}3{.or}4{.end}\n",
 
@@ -380,32 +380,32 @@ var tests = []*Test{
 
        // Maps
 
-       &Test{
+       {
                in: "{Mp.mapkey}\n",
 
                out: "Ahoy!\n",
        },
-       &Test{
+       {
                in: "{Innermap.Mp.innerkey}\n",
 
                out: "55\n",
        },
-       &Test{
+       {
                in: "{.section Innermap}{.section Mp}{innerkey}{.end}{.end}\n",
 
                out: "55\n",
        },
-       &Test{
+       {
                in: "{.section JSON}{.repeated section maps}{a}{b}{.end}{.end}\n",
 
                out: "1234\n",
        },
-       &Test{
+       {
                in: "{Stringmap.stringkey1}\n",
 
                out: "stringresult\n",
        },
-       &Test{
+       {
                in: "{.repeated section Stringmap}\n" +
                        "{@}\n" +
                        "{.end}",
@@ -413,7 +413,7 @@ var tests = []*Test{
                out: "stringresult\n" +
                        "stringresult\n",
        },
-       &Test{
+       {
                in: "{.repeated section Stringmap}\n" +
                        "\t{@}\n" +
                        "{.end}",
@@ -421,12 +421,12 @@ var tests = []*Test{
                out: "\tstringresult\n" +
                        "\tstringresult\n",
        },
-       &Test{
+       {
                in: "{*Ptrmap.stringkey1}\n",
 
                out: "pointedToString\n",
        },
-       &Test{
+       {
                in: "{.repeated section Ptrmap}\n" +
                        "{*@}\n" +
                        "{.end}",
@@ -437,22 +437,22 @@ var tests = []*Test{
 
        // Interface values
 
-       &Test{
+       {
                in: "{Iface}",
 
                out: "[1 2 3]",
        },
-       &Test{
+       {
                in: "{.repeated section Iface}{@}{.alternates with} {.end}",
 
                out: "1 2 3",
        },
-       &Test{
+       {
                in: "{.section Iface}{@}{.end}",
 
                out: "[1 2 3]",
        },
-       &Test{
+       {
                in: "{.section Ifaceptr}{Item} {Value}{.end}",
 
                out: "Item Value",
index ef5bd92..d09e839 100644 (file)
@@ -63,11 +63,10 @@ func LookPath(file string) (f string, err error) {
                }
                return ``, &Error{file, err}
        }
-       if pathenv := os.Getenv(`PATH`); pathenv == `` {
-               if f, err = findExecutable(`.\`+file, exts); err == nil {
-                       return
-               }
-       } else {
+       if f, err = findExecutable(`.\`+file, exts); err == nil {
+               return
+       }
+       if pathenv := os.Getenv(`PATH`); pathenv != `` {
                for _, dir := range strings.Split(pathenv, `;`) {
                        if f, err = findExecutable(dir+`\`+file, exts); err == nil {
                                return
index 2bd62d3..b5b0ded 100644 (file)
@@ -259,19 +259,19 @@ type Node struct {
 var tree = &Node{
        "testdata",
        []*Node{
-               &Node{"a", nil, 0},
-               &Node{"b", []*Node{}, 0},
-               &Node{"c", nil, 0},
-               &Node{
+               {"a", nil, 0},
+               {"b", []*Node{}, 0},
+               {"c", nil, 0},
+               {
                        "d",
                        []*Node{
-                               &Node{"x", nil, 0},
-                               &Node{"y", []*Node{}, 0},
-                               &Node{
+                               {"x", nil, 0},
+                               {"y", []*Node{}, 0},
+                               {
                                        "z",
                                        []*Node{
-                                               &Node{"u", nil, 0},
-                                               &Node{"v", nil, 0},
+                                               {"u", nil, 0},
+                                               {"v", nil, 0},
                                        },
                                        0,
                                },
index cf31d1b..7d1cb09 100644 (file)
@@ -64,7 +64,7 @@ var typeTests = []pair{
        {struct{ x (**integer) }{}, "**reflect_test.integer"},
        {struct{ x ([32]int32) }{}, "[32]int32"},
        {struct{ x ([]int8) }{}, "[]int8"},
-       {struct{ x (map[string]int32) }{}, "map[string] int32"},
+       {struct{ x (map[string]int32) }{}, "map[string]int32"},
        {struct{ x (chan<- string) }{}, "chan<- string"},
        {struct {
                x struct {
@@ -180,7 +180,7 @@ var valueTests = []pair{
        {new(**int8), "**int8(0)"},
        {new([5]int32), "[5]int32{0, 0, 0, 0, 0}"},
        {new(**integer), "**reflect_test.integer(0)"},
-       {new(map[string]int32), "map[string] int32{<can't iterate on maps>}"},
+       {new(map[string]int32), "map[string]int32{<can't iterate on maps>}"},
        {new(chan<- string), "chan<- string"},
        {new(func(a int8, b int32)), "func(int8, int32)(0)"},
        {new(struct {
@@ -419,7 +419,7 @@ func TestAll(t *testing.T) {
        testType(t, 8, typ.Elem(), "int32")
 
        typ = TypeOf((map[string]*int32)(nil))
-       testType(t, 9, typ, "map[string] *int32")
+       testType(t, 9, typ, "map[string]*int32")
        mtyp := typ
        testType(t, 10, mtyp.Key(), "string")
        testType(t, 11, mtyp.Elem(), "*int32")
@@ -468,8 +468,8 @@ func TestInterfaceValue(t *testing.T) {
 func TestFunctionValue(t *testing.T) {
        var x interface{} = func() {}
        v := ValueOf(x)
-       if v.Interface() != v.Interface() || v.Interface() != x {
-               t.Fatalf("TestFunction != itself")
+       if fmt.Sprint(v.Interface()) != fmt.Sprint(x) {
+               t.Fatalf("TestFunction returned wrong pointer")
        }
        assert(t, v.Type().String(), "func()")
 }
index 5f5c52b..7486a9b 100644 (file)
@@ -23,14 +23,14 @@ func valueToString(val Value) string {
        typ := val.Type()
        switch val.Kind() {
        case Int, Int8, Int16, Int32, Int64:
-               return strconv.Itoa64(val.Int())
+               return strconv.FormatInt(val.Int(), 10)
        case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
-               return strconv.Uitoa64(val.Uint())
+               return strconv.FormatUint(val.Uint(), 10)
        case Float32, Float64:
-               return strconv.Ftoa64(val.Float(), 'g', -1)
+               return strconv.FormatFloat(val.Float(), 'g', -1, 64)
        case Complex64, Complex128:
                c := val.Complex()
-               return strconv.Ftoa64(real(c), 'g', -1) + "+" + strconv.Ftoa64(imag(c), 'g', -1) + "i"
+               return strconv.FormatFloat(real(c), 'g', -1, 64) + "+" + strconv.FormatFloat(imag(c), 'g', -1, 64) + "i"
        case String:
                return val.String()
        case Bool:
@@ -88,7 +88,7 @@ func valueToString(val Value) string {
                return typ.String() + "(" + valueToString(val.Elem()) + ")"
        case Func:
                v := val
-               return typ.String() + "(" + strconv.Uitoa64(uint64(v.Pointer())) + ")"
+               return typ.String() + "(" + strconv.FormatUint(uint64(v.Pointer()), 10) + ")"
        default:
                panic("valueToString: can't print type " + typ.String())
        }
index f5b697a..84ebb83 100644 (file)
@@ -267,7 +267,7 @@ func dumpProg(b *bytes.Buffer, p *Prog) {
 }
 
 func u32(i uint32) string {
-       return strconv.Uitoa64(uint64(i))
+       return strconv.FormatUint(uint64(i), 10)
 }
 
 func dumpInst(b *bytes.Buffer, i *Inst) {
index b5ddab1..adcfe29 100644 (file)
@@ -277,7 +277,7 @@ func escape(b *bytes.Buffer, r rune, force bool) {
        default:
                if r < 0x100 {
                        b.WriteString(`\x`)
-                       s := strconv.Itob(int(r), 16)
+                       s := strconv.FormatInt(int64(r), 16)
                        if len(s) == 1 {
                                b.WriteRune('0')
                        }
@@ -285,7 +285,7 @@ func escape(b *bytes.Buffer, r rune, force bool) {
                        break
                }
                b.WriteString(`\x{`)
-               b.WriteString(strconv.Itob(int(r), 16))
+               b.WriteString(strconv.FormatInt(int64(r), 16))
                b.WriteString(`}`)
        }
 }
index e2d87bc..1508118 100644 (file)
@@ -4,10 +4,10 @@
 
 package strconv
 
-// Atob returns the boolean value represented by the string.
+// ParseBool returns the boolean value represented by the string.
 // It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
 // Any other value returns an error.
-func Atob(str string) (value bool, err error) {
+func ParseBool(str string) (value bool, err error) {
        switch str {
        case "1", "t", "T", "true", "TRUE", "True":
                return true, nil
@@ -17,10 +17,19 @@ func Atob(str string) (value bool, err error) {
        return false, &NumError{str, ErrSyntax}
 }
 
-// Btoa returns "true" or "false" according to the value of the boolean argument
-func Btoa(b bool) string {
+// FormatBool returns "true" or "false" according to the value of b
+func FormatBool(b bool) string {
        if b {
                return "true"
        }
        return "false"
 }
+
+// AppendBool appends "true" or "false", according to the value of b,
+// to dst and returns the extended buffer.
+func AppendBool(dst []byte, b bool) []byte {
+       if b {
+               return append(dst, "true"...)
+       }
+       return append(dst, "false"...)
+}
index 2f31eb5..a7c1454 100644 (file)
@@ -32,9 +32,9 @@ var atobtests = []atobTest{
        {"True", true, nil},
 }
 
-func TestAtob(t *testing.T) {
+func TestParseBool(t *testing.T) {
        for _, test := range atobtests {
-               b, e := Atob(test.in)
+               b, e := ParseBool(test.in)
                if test.err != nil {
                        // expect an error
                        if e == nil {
index 06dae85..1642c18 100644 (file)
@@ -338,21 +338,7 @@ func (d *decimal) atof32() (f float32, ok bool) {
        return
 }
 
-// Atof32 converts the string s to a 32-bit floating-point number.
-//
-// If s is well-formed and near a valid floating point number,
-// Atof32 returns the nearest floating point number rounded
-// using IEEE754 unbiased rounding.
-//
-// The errors that Atof32 returns have concrete type *NumError
-// and include err.Num = s.
-//
-// If s is not syntactically well-formed, Atof32 returns err.Error = ErrSyntax.
-//
-// If s is syntactically well-formed but is more than 1/2 ULP
-// away from the largest floating point number of the given size,
-// Atof32 returns f = Â±Inf, err.Error = ErrRange.
-func Atof32(s string) (f float32, err error) {
+func atof32(s string) (f float32, err error) {
        if val, ok := special(s); ok {
                return float32(val), nil
        }
@@ -374,10 +360,7 @@ func Atof32(s string) (f float32, err error) {
        return f, err
 }
 
-// Atof64 converts the string s to a 64-bit floating-point number.
-// Except for the type of its result, its definition is the same as that
-// of Atof32.
-func Atof64(s string) (f float64, err error) {
+func atof64(s string) (f float64, err error) {
        if val, ok := special(s); ok {
                return val, nil
        }
@@ -399,14 +382,28 @@ func Atof64(s string) (f float64, err error) {
        return f, err
 }
 
-// AtofN converts the string s to a 64-bit floating-point number,
-// but it rounds the result assuming that it will be stored in a value
-// of n bits (32 or 64).
-func AtofN(s string, n int) (f float64, err error) {
-       if n == 32 {
-               f1, err1 := Atof32(s)
+// ParseFloat converts the string s to a floating-point number
+// with the precision specified by bitSize: 32 for float32, or 64 for float64.
+// When bitSize=32, the result still has type float64, but it will be
+// convertible to float32 without changing its value.
+//
+// If s is well-formed and near a valid floating point number,
+// ParseFloat returns the nearest floating point number rounded
+// using IEEE754 unbiased rounding.
+//
+// The errors that ParseFloat returns have concrete type *NumError
+// and include err.Num = s.
+//
+// If s is not syntactically well-formed, ParseFloat returns err.Error = ErrSyntax.
+//
+// If s is syntactically well-formed but is more than 1/2 ULP
+// away from the largest floating point number of the given size,
+// ParseFloat returns f = Â±Inf, err.Error = ErrRange.
+func ParseFloat(s string, bitSize int) (f float64, err error) {
+       if bitSize == 32 {
+               f1, err1 := atof32(s)
                return float64(f1), err1
        }
-       f1, err1 := Atof64(s)
+       f1, err1 := atof64(s)
        return f1, err1
 }
index 871bf0c..a9820d1 100644 (file)
@@ -128,33 +128,23 @@ func testAtof(t *testing.T, opt bool) {
        oldopt := SetOptimize(opt)
        for i := 0; i < len(atoftests); i++ {
                test := &atoftests[i]
-               out, err := Atof64(test.in)
-               outs := Ftoa64(out, 'g', -1)
+               out, err := ParseFloat(test.in, 64)
+               outs := FormatFloat(out, 'g', -1, 64)
                if outs != test.out || !reflect.DeepEqual(err, test.err) {
-                       t.Errorf("Atof64(%v) = %v, %v want %v, %v",
-                               test.in, out, err, test.out, test.err)
-               }
-
-               out, err = AtofN(test.in, 64)
-               outs = FtoaN(out, 'g', -1, 64)
-               if outs != test.out || !reflect.DeepEqual(err, test.err) {
-                       t.Errorf("AtofN(%v, 64) = %v, %v want %v, %v",
+                       t.Errorf("ParseFloat(%v, 64) = %v, %v want %v, %v",
                                test.in, out, err, test.out, test.err)
                }
 
                if float64(float32(out)) == out {
-                       out32, err := Atof32(test.in)
-                       outs := Ftoa32(out32, 'g', -1)
-                       if outs != test.out || !reflect.DeepEqual(err, test.err) {
-                               t.Errorf("Atof32(%v) = %v, %v want %v, %v  # %v",
-                                       test.in, out32, err, test.out, test.err, out)
+                       out, err := ParseFloat(test.in, 32)
+                       out32 := float32(out)
+                       if float64(out32) != out {
+                               t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32))
+                               continue
                        }
-
-                       out, err := AtofN(test.in, 32)
-                       out32 = float32(out)
-                       outs = FtoaN(float64(out32), 'g', -1, 32)
+                       outs := FormatFloat(float64(out32), 'g', -1, 32)
                        if outs != test.out || !reflect.DeepEqual(err, test.err) {
-                               t.Errorf("AtofN(%v, 32) = %v, %v want %v, %v  # %v",
+                               t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v  # %v",
                                        test.in, out32, err, test.out, test.err, out)
                        }
                }
@@ -168,24 +158,24 @@ func TestAtofSlow(t *testing.T) { testAtof(t, false) }
 
 func BenchmarkAtof64Decimal(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atof64("33909")
+               ParseFloat("33909", 64)
        }
 }
 
 func BenchmarkAtof64Float(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atof64("339.7784")
+               ParseFloat("339.7784", 64)
        }
 }
 
 func BenchmarkAtof64FloatExp(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atof64("-5.09e75")
+               ParseFloat("-5.09e75", 64)
        }
 }
 
 func BenchmarkAtof64Big(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atof64("123456789123456789123456789")
+               ParseFloat("123456789123456789123456789", 64)
        }
 }
index 2c6c3d5..438d496 100644 (file)
@@ -20,15 +20,9 @@ type NumError struct {
 
 func (e *NumError) Error() string { return `parsing "` + e.Num + `": ` + e.Err.Error() }
 
-func computeIntsize() uint {
-       siz := uint(8)
-       for 1<<siz != 0 {
-               siz *= 2
-       }
-       return siz
-}
+const intSize = 32 << uint(^uint(0)>>63)
 
-var IntSize = computeIntsize()
+const IntSize = intSize // number of bits in int, uint (32 or 64)
 
 // Return the first number n such that n*base >= 1<<64.
 func cutoff64(base int) uint64 {
@@ -38,17 +32,13 @@ func cutoff64(base int) uint64 {
        return (1<<64-1)/uint64(base) + 1
 }
 
-// Btoui64 interprets a string s in an arbitrary base b (2 to 36)
-// and returns the corresponding value n.  If b == 0, the base
-// is taken from the string prefix: base 16 for "0x", base 8 for "0",
-// and base 10 otherwise.
-//
-// The errors that Btoui64 returns have concrete type *NumError
-// and include err.Num = s.  If s is empty or contains invalid
-// digits, err.Error = ErrSyntax; if the value corresponding
-// to s cannot be represented by a uint64, err.Error = ErrRange.
-func Btoui64(s string, b int) (n uint64, err error) {
-       var cutoff uint64
+// ParseUint is like ParseInt but for unsigned numbers.
+func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
+       var cutoff, maxVal uint64
+
+       if bitSize == 0 {
+               bitSize = int(IntSize)
+       }
 
        s0 := s
        switch {
@@ -82,6 +72,7 @@ func Btoui64(s string, b int) (n uint64, err error) {
 
        n = 0
        cutoff = cutoff64(b)
+       maxVal = 1<<uint(bitSize) - 1
 
        for i := 0; i < len(s); i++ {
                var v byte
@@ -113,7 +104,7 @@ func Btoui64(s string, b int) (n uint64, err error) {
                n *= uint64(b)
 
                n1 := n + uint64(v)
-               if n1 < n {
+               if n1 < n || n1 > maxVal {
                        // n+v overflows
                        n = 1<<64 - 1
                        err = ErrRange
@@ -128,18 +119,25 @@ Error:
        return n, &NumError{s0, err}
 }
 
-// Atoui64 interprets a string s as a decimal number and
-// returns the corresponding value n.
+// ParseInt interprets a string s in an arbitrary base b (2 to 36)
+// and returns the corresponding value n.  If b == 0, the base
+// is taken from the string prefix: base 16 for "0x", base 8 for "0",
+// and base 10 otherwise.
 //
-// Atoui64 returns err.Error = ErrSyntax if s is empty or contains invalid digits.
-// It returns err.Error = ErrRange if s cannot be represented by a uint64.
-func Atoui64(s string) (n uint64, err error) {
-       return Btoui64(s, 10)
-}
+// The bitSize argument specifies the integer type
+// that the result must fit into.  Bit sizes 0, 8, 16, 32, and 64
+// correspond to int, int8, int16, int32, and int64.
+//
+// The errors that ParseInt returns have concrete type *NumError
+// and include err.Num = s.  If s is empty or contains invalid
+// digits, err.Error = ErrSyntax; if the value corresponding
+// to s cannot be represented by a signed integer of the
+// given size, err.Error = ErrRange.
+func ParseInt(s string, base int, bitSize int) (i int64, err error) {
+       if bitSize == 0 {
+               bitSize = int(IntSize)
+       }
 
-// Btoi64 is like Btoui64 but allows signed numbers and
-// returns its result in an int64.
-func Btoi64(s string, base int) (i int64, err error) {
        // Empty string bad.
        if len(s) == 0 {
                return 0, &NumError{s, ErrSyntax}
@@ -157,16 +155,17 @@ func Btoi64(s string, base int) (i int64, err error) {
 
        // Convert unsigned and check range.
        var un uint64
-       un, err = Btoui64(s, base)
+       un, err = ParseUint(s, base, bitSize)
        if err != nil && err.(*NumError).Err != ErrRange {
                err.(*NumError).Num = s0
                return 0, err
        }
-       if !neg && un >= 1<<63 {
-               return 1<<63 - 1, &NumError{s0, ErrRange}
+       cutoff := uint64(1 << uint(bitSize-1))
+       if !neg && un >= cutoff {
+               return int64(cutoff - 1), &NumError{s0, ErrRange}
        }
-       if neg && un > 1<<63 {
-               return -1 << 63, &NumError{s0, ErrRange}
+       if neg && un > cutoff {
+               return -int64(cutoff), &NumError{s0, ErrRange}
        }
        n := int64(un)
        if neg {
@@ -175,35 +174,8 @@ func Btoi64(s string, base int) (i int64, err error) {
        return n, nil
 }
 
-// Atoi64 is like Atoui64 but allows signed numbers and
-// returns its result in an int64.
-func Atoi64(s string) (i int64, err error) { return Btoi64(s, 10) }
-
-// Atoui is like Atoui64 but returns its result as a uint.
-func Atoui(s string) (i uint, err error) {
-       i1, e1 := Atoui64(s)
-       if e1 != nil && e1.(*NumError).Err != ErrRange {
-               return 0, e1
-       }
-       i = uint(i1)
-       if uint64(i) != i1 {
-               return ^uint(0), &NumError{s, ErrRange}
-       }
-       return i, nil
-}
-
-// Atoi is like Atoi64 but returns its result as an int.
+// Atoi is shorthand for ParseInt(s, 10, 0).
 func Atoi(s string) (i int, err error) {
-       i1, e1 := Atoi64(s)
-       if e1 != nil && e1.(*NumError).Err != ErrRange {
-               return 0, e1
-       }
-       i = int(i1)
-       if int64(i) != i1 {
-               if i1 < 0 {
-                       return -1 << (IntSize - 1), &NumError{s, ErrRange}
-               }
-               return 1<<(IntSize-1) - 1, &NumError{s, ErrRange}
-       }
-       return i, nil
+       i64, err := ParseInt(s, 10, 0)
+       return int(i64), err
 }
index 9ee11b7..2d06efe 100644 (file)
@@ -187,10 +187,10 @@ func init() {
        }
 }
 
-func TestAtoui64(t *testing.T) {
+func TestParseUint64(t *testing.T) {
        for i := range atoui64tests {
                test := &atoui64tests[i]
-               out, err := Atoui64(test.in)
+               out, err := ParseUint(test.in, 10, 64)
                if test.out != out || !reflect.DeepEqual(test.err, err) {
                        t.Errorf("Atoui64(%q) = %v, %v want %v, %v",
                                test.in, out, err, test.out, test.err)
@@ -198,21 +198,21 @@ func TestAtoui64(t *testing.T) {
        }
 }
 
-func TestBtoui64(t *testing.T) {
+func TestParseUint64Base(t *testing.T) {
        for i := range btoui64tests {
                test := &btoui64tests[i]
-               out, err := Btoui64(test.in, 0)
+               out, err := ParseUint(test.in, 0, 64)
                if test.out != out || !reflect.DeepEqual(test.err, err) {
-                       t.Errorf("Btoui64(%q) = %v, %v want %v, %v",
+                       t.Errorf("ParseUint(%q) = %v, %v want %v, %v",
                                test.in, out, err, test.out, test.err)
                }
        }
 }
 
-func TestAtoi64(t *testing.T) {
+func TestParseInt64(t *testing.T) {
        for i := range atoi64tests {
                test := &atoi64tests[i]
-               out, err := Atoi64(test.in)
+               out, err := ParseInt(test.in, 10, 64)
                if test.out != out || !reflect.DeepEqual(test.err, err) {
                        t.Errorf("Atoi64(%q) = %v, %v want %v, %v",
                                test.in, out, err, test.out, test.err)
@@ -220,23 +220,23 @@ func TestAtoi64(t *testing.T) {
        }
 }
 
-func TestBtoi64(t *testing.T) {
+func TestParseInt64Base(t *testing.T) {
        for i := range btoi64tests {
                test := &btoi64tests[i]
-               out, err := Btoi64(test.in, 0)
+               out, err := ParseInt(test.in, 0, 64)
                if test.out != out || !reflect.DeepEqual(test.err, err) {
-                       t.Errorf("Btoi64(%q) = %v, %v want %v, %v",
+                       t.Errorf("ParseInt(%q) = %v, %v want %v, %v",
                                test.in, out, err, test.out, test.err)
                }
        }
 }
 
-func TestAtoui(t *testing.T) {
+func TestParseUint(t *testing.T) {
        switch IntSize {
        case 32:
                for i := range atoui32tests {
                        test := &atoui32tests[i]
-                       out, err := Atoui(test.in)
+                       out, err := ParseUint(test.in, 10, 0)
                        if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) {
                                t.Errorf("Atoui(%q) = %v, %v want %v, %v",
                                        test.in, out, err, test.out, test.err)
@@ -245,7 +245,7 @@ func TestAtoui(t *testing.T) {
        case 64:
                for i := range atoui64tests {
                        test := &atoui64tests[i]
-                       out, err := Atoui(test.in)
+                       out, err := ParseUint(test.in, 10, 0)
                        if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) {
                                t.Errorf("Atoui(%q) = %v, %v want %v, %v",
                                        test.in, out, err, test.out, test.err)
@@ -254,12 +254,12 @@ func TestAtoui(t *testing.T) {
        }
 }
 
-func TestAtoi(t *testing.T) {
+func TestParseInt(t *testing.T) {
        switch IntSize {
        case 32:
                for i := range atoi32tests {
                        test := &atoi32tests[i]
-                       out, err := Atoi(test.in)
+                       out, err := ParseInt(test.in, 10, 0)
                        if test.out != int32(out) || !reflect.DeepEqual(test.err, err) {
                                t.Errorf("Atoi(%q) = %v, %v want %v, %v",
                                        test.in, out, err, test.out, test.err)
@@ -268,7 +268,7 @@ func TestAtoi(t *testing.T) {
        case 64:
                for i := range atoi64tests {
                        test := &atoi64tests[i]
-                       out, err := Atoi(test.in)
+                       out, err := ParseInt(test.in, 10, 0)
                        if test.out != int64(out) || !reflect.DeepEqual(test.err, err) {
                                t.Errorf("Atoi(%q) = %v, %v want %v, %v",
                                        test.in, out, err, test.out, test.err)
@@ -279,24 +279,24 @@ func TestAtoi(t *testing.T) {
 
 func BenchmarkAtoi(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atoi("12345678")
+               ParseInt("12345678", 10, 0)
        }
 }
 
 func BenchmarkAtoiNeg(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atoi("-12345678")
+               ParseInt("-12345678", 10, 0)
        }
 }
 
 func BenchmarkAtoi64(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atoi64("12345678901234")
+               ParseInt("12345678901234", 10, 64)
        }
 }
 
 func BenchmarkAtoi64Neg(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Atoi64("-12345678901234")
+               ParseInt("-12345678901234", 10, 64)
        }
 }
index 9785ca6..47877e3 100644 (file)
@@ -31,7 +31,7 @@ func pow2(i int) float64 {
 func myatof64(s string) (f float64, ok bool) {
        a := strings.SplitN(s, "p", 2)
        if len(a) == 2 {
-               n, err := strconv.Atoi64(a[0])
+               n, err := strconv.ParseInt(a[0], 10, 64)
                if err != nil {
                        return 0, false
                }
@@ -63,7 +63,7 @@ func myatof64(s string) (f float64, ok bool) {
                }
                return v * pow2(e), true
        }
-       f1, err := strconv.Atof64(s)
+       f1, err := strconv.ParseFloat(s, 64)
        if err != nil {
                return 0, false
        }
@@ -87,7 +87,8 @@ func myatof32(s string) (f float32, ok bool) {
                }
                return float32(float64(n) * pow2(e)), true
        }
-       f1, err1 := strconv.Atof32(s)
+       f64, err1 := strconv.ParseFloat(s, 32)
+       f1 := float32(f64)
        if err1 != nil {
                return 0, false
        }
index 8342b6a..e1ea0a3 100644 (file)
@@ -22,8 +22,10 @@ type floatInfo struct {
 var float32info = floatInfo{23, 8, -127}
 var float64info = floatInfo{52, 11, -1023}
 
-// Ftoa32 converts the 32-bit floating-point number f to a string,
-// according to the format fmt and precision prec.
+// FormatFloat converts the floating-point number f to a string,
+// according to the format fmt and precision prec.  It rounds the
+// result assuming that the original was obtained from a floating-point
+// value of bitSize bits (32 for float32, 64 for float64).
 //
 // The format fmt is one of
 // 'b' (-ddddp±ddd, a binary exponent),
@@ -43,24 +45,17 @@ var float64info = floatInfo{52, 11, -1023}
 // Ftoa32(f) is not the same as Ftoa64(float32(f)),
 // because correct rounding and the number of digits
 // needed to identify f depend on the precision of the representation.
-func Ftoa32(f float32, fmt byte, prec int) string {
-       return genericFtoa(uint64(math.Float32bits(f)), fmt, prec, &float32info)
-}
-
-// Ftoa64 is like Ftoa32 but converts a 64-bit floating-point number.
-func Ftoa64(f float64, fmt byte, prec int) string {
+func FormatFloat(f float64, fmt byte, prec int, n int) string {
+       if n == 32 {
+               return genericFtoa(uint64(math.Float32bits(float32(f))), fmt, prec, &float32info)
+       }
        return genericFtoa(math.Float64bits(f), fmt, prec, &float64info)
 }
 
-// FtoaN converts the 64-bit floating-point number f to a string,
-// according to the format fmt and precision prec, but it rounds the
-// result assuming that it was obtained from a floating-point value
-// of n bits (32 or 64).
-func FtoaN(f float64, fmt byte, prec int, n int) string {
-       if n == 32 {
-               return Ftoa32(float32(f), fmt, prec)
-       }
-       return Ftoa64(f, fmt, prec)
+// AppendFloat appends the string form of the floating-point number f,
+// as generated by FormatFloat, to dst and returns the extended buffer.
+func AppendFloat(dst []byte, f float64, fmt byte, prec int, n int) []byte {
+       return append(dst, FormatFloat(f, fmt, prec, n)...)
 }
 
 func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
index 8bac5da..02206d5 100644 (file)
@@ -128,47 +128,47 @@ var ftoatests = []ftoaTest{
 func TestFtoa(t *testing.T) {
        for i := 0; i < len(ftoatests); i++ {
                test := &ftoatests[i]
-               s := Ftoa64(test.f, test.fmt, test.prec)
-               if s != test.s {
-                       t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
-               }
-               s = FtoaN(test.f, test.fmt, test.prec, 64)
+               s := FormatFloat(test.f, test.fmt, test.prec, 64)
                if s != test.s {
                        t.Error("testN=64", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
                }
+               x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 64)
+               if string(x) != "abc"+test.s {
+                       t.Error("AppendFloat testN=64", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+               }
                if float64(float32(test.f)) == test.f && test.fmt != 'b' {
-                       s := Ftoa32(float32(test.f), test.fmt, test.prec)
-                       if s != test.s {
-                               t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
-                       }
-                       s = FtoaN(test.f, test.fmt, test.prec, 32)
+                       s := FormatFloat(test.f, test.fmt, test.prec, 32)
                        if s != test.s {
                                t.Error("testN=32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
                        }
+                       x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 32)
+                       if string(x) != "abc"+test.s {
+                               t.Error("AppendFloat testN=32", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+                       }
                }
        }
 }
 
 func BenchmarkFtoa64Decimal(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Ftoa64(33909, 'g', -1)
+               FormatFloat(33909, 'g', -1, 64)
        }
 }
 
 func BenchmarkFtoa64Float(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Ftoa64(339.7784, 'g', -1)
+               FormatFloat(339.7784, 'g', -1, 64)
        }
 }
 
 func BenchmarkFtoa64FloatExp(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Ftoa64(-5.09e75, 'g', -1)
+               FormatFloat(-5.09e75, 'g', -1, 64)
        }
 }
 
 func BenchmarkFtoa64Big(b *testing.B) {
        for i := 0; i < b.N; i++ {
-               Ftoa64(123456789123456789123456789, 'g', -1)
+               FormatFloat(123456789123456789123456789, 'g', -1, 64)
        }
 }
index a0a7496..65229f7 100644 (file)
 
 package strconv
 
-// Uitob64 returns the string representation of i in the given base.
-func Uitob64(u uint64, base uint) string {
-       if base < 2 || 36 < base {
-               panic("invalid base " + Uitoa(base))
-       }
-       if u == 0 {
-               return "0"
-       }
+// FormatUint returns the string representation of i in the given base.
+func FormatUint(i uint64, base int) string {
+       _, s := formatBits(nil, i, base, false, false)
+       return s
+}
 
-       // Assemble decimal in reverse order.
-       var buf [64]byte
-       j := len(buf)
-       b := uint64(base)
-       for u > 0 {
-               j--
-               buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b]
-               u /= b
-       }
+// FormatInt returns the string representation of i in the given base.
+func FormatInt(i int64, base int) string {
+       _, s := formatBits(nil, uint64(i), base, i < 0, false)
+       return s
+}
+
+// Itoa is shorthand for FormatInt(i, 10).
+func Itoa(i int) string {
+       return FormatInt(int64(i), 10)
+}
+
+// AppendInt appends the string form of the integer i,
+// as generated by FormatInt, to dst and returns the extended buffer.
+func AppendInt(dst []byte, i int64, base int) []byte {
+       dst, _ = formatBits(dst, uint64(i), base, i < 0, true)
+       return dst
+}
 
-       return string(buf[j:])
+// AppendUint appends the string form of the unsigned integer i,
+// as generated by FormatUint, to dst and returns the extended buffer.
+func AppendUint(dst []byte, i uint64, base int) []byte {
+       dst, _ = formatBits(dst, i, base, false, true)
+       return dst
 }
 
-// Itob64 returns the string representation of i in the given base.
-func Itob64(i int64, base uint) string {
-       if i == 0 {
-               return "0"
+const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
+
+var shifts = [len(digits) + 1]uint{
+       1 << 1: 1,
+       1 << 2: 2,
+       1 << 3: 3,
+       1 << 4: 4,
+       1 << 5: 5,
+}
+
+// formatBits computes the string representation of u in the given base.
+// If negative is set, u is treated as negative int64 value. If append_
+// is set, the string is appended to dst and the resulting byte slice is
+// returned as the first result value; otherwise the string is returned
+// as the second result value.
+//
+func formatBits(dst []byte, u uint64, base int, negative, append_ bool) (d []byte, s string) {
+       if base < 2 || base > len(digits) {
+               panic("invalid base")
        }
+       // 2 <= base && base <= len(digits)
 
-       if i < 0 {
-               return "-" + Uitob64(-uint64(i), base)
+       var a [64 + 1]byte // +1 for sign of 64bit value in base 2
+       i := len(a)
+
+       if negative {
+               u = -u
        }
-       return Uitob64(uint64(i), base)
-}
 
-// Itoa64 returns the decimal string representation of i.
-func Itoa64(i int64) string { return Itob64(i, 10) }
+       // convert bits
+       if base == 10 {
+               // common case: use constant 10 for / and % because
+               // the compiler can optimize it into a multiply+shift
+               for u >= 10 {
+                       i--
+                       a[i] = digits[u%10]
+                       u /= 10
+               }
 
-// Uitoa64 returns the decimal string representation of i.
-func Uitoa64(i uint64) string { return Uitob64(i, 10) }
+       } else if s := shifts[base]; s > 0 {
+               // base is power of 2: use shifts and masks instead of / and %
+               b := uint64(base)
+               m := uintptr(b) - 1 // == 1<<s - 1
+               for u >= b {
+                       i--
+                       a[i] = digits[uintptr(u)&m]
+                       u >>= s
+               }
 
-// Uitob returns the string representation of i in the given base.
-func Uitob(i uint, base uint) string { return Uitob64(uint64(i), base) }
+       } else {
+               // general case
+               b := uint64(base)
+               for u >= b {
+                       i--
+                       a[i] = digits[u%b]
+                       u /= b
+               }
+       }
 
-// Itob returns the string representation of i in the given base.
-func Itob(i int, base uint) string { return Itob64(int64(i), base) }
+       // u < base
+       i--
+       a[i] = digits[uintptr(u)]
 
-// Itoa returns the decimal string representation of i.
-func Itoa(i int) string { return Itob64(int64(i), 10) }
+       // add sign, if any
+       if negative {
+               i--
+               a[i] = '-'
+       }
 
-// Uitoa returns the decimal string representation of i.
-func Uitoa(i uint) string { return Uitob64(uint64(i), 10) }
+       if append_ {
+               d = append(dst, a[i:]...)
+               return
+       }
+       s = string(a[i:])
+       return
+}
index 8514b21..e0213ae 100644 (file)
@@ -11,7 +11,7 @@ import (
 
 type itob64Test struct {
        in   int64
-       base uint
+       base int
        out  string
 }
 
@@ -60,73 +60,43 @@ var itob64tests = []itob64Test{
 
 func TestItoa(t *testing.T) {
        for _, test := range itob64tests {
-               s := Itob64(test.in, test.base)
+               s := FormatInt(test.in, test.base)
                if s != test.out {
-                       t.Errorf("Itob64(%v, %v) = %v want %v",
+                       t.Errorf("FormatInt(%v, %v) = %v want %v",
                                test.in, test.base, s, test.out)
                }
-
-               if test.in >= 0 {
-                       s := Uitob64(uint64(test.in), test.base)
-                       if s != test.out {
-                               t.Errorf("Uitob64(%v, %v) = %v want %v",
-                                       test.in, test.base, s, test.out)
-                       }
+               x := AppendInt([]byte("abc"), test.in, test.base)
+               if string(x) != "abc"+test.out {
+                       t.Errorf("AppendInt(%q, %v, %v) = %q want %v",
+                               "abc", test.in, test.base, x, test.out)
                }
 
-               if int64(int(test.in)) == test.in {
-                       s := Itob(int(test.in), test.base)
+               if test.in >= 0 {
+                       s := FormatUint(uint64(test.in), test.base)
                        if s != test.out {
-                               t.Errorf("Itob(%v, %v) = %v want %v",
+                               t.Errorf("FormatUint(%v, %v) = %v want %v",
                                        test.in, test.base, s, test.out)
                        }
-
-                       if test.in >= 0 {
-                               s := Uitob(uint(test.in), test.base)
-                               if s != test.out {
-                                       t.Errorf("Uitob(%v, %v) = %v want %v",
-                                               test.in, test.base, s, test.out)
-                               }
+                       x := AppendUint(nil, uint64(test.in), test.base)
+                       if string(x) != test.out {
+                               t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+                                       "abc", uint64(test.in), test.base, x, test.out)
                        }
                }
 
-               if test.base == 10 {
-                       s := Itoa64(test.in)
+               if test.base == 10 && int64(int(test.in)) == test.in {
+                       s := Itoa(int(test.in))
                        if s != test.out {
-                               t.Errorf("Itoa64(%v) = %v want %v",
+                               t.Errorf("Itoa(%v) = %v want %v",
                                        test.in, s, test.out)
                        }
-
-                       if test.in >= 0 {
-                               s := Uitob64(uint64(test.in), test.base)
-                               if s != test.out {
-                                       t.Errorf("Uitob64(%v, %v) = %v want %v",
-                                               test.in, test.base, s, test.out)
-                               }
-                       }
-
-                       if int64(int(test.in)) == test.in {
-                               s := Itoa(int(test.in))
-                               if s != test.out {
-                                       t.Errorf("Itoa(%v) = %v want %v",
-                                               test.in, s, test.out)
-                               }
-
-                               if test.in >= 0 {
-                                       s := Uitoa(uint(test.in))
-                                       if s != test.out {
-                                               t.Errorf("Uitoa(%v) = %v want %v",
-                                                       test.in, s, test.out)
-                                       }
-                               }
-                       }
                }
        }
 }
 
 type uitob64Test struct {
        in   uint64
-       base uint
+       base int
        out  string
 }
 
@@ -141,34 +111,50 @@ var uitob64tests = []uitob64Test{
 
 func TestUitoa(t *testing.T) {
        for _, test := range uitob64tests {
-               s := Uitob64(test.in, test.base)
+               s := FormatUint(test.in, test.base)
                if s != test.out {
-                       t.Errorf("Uitob64(%v, %v) = %v want %v",
+                       t.Errorf("FormatUint(%v, %v) = %v want %v",
                                test.in, test.base, s, test.out)
                }
+               x := AppendUint([]byte("abc"), test.in, test.base)
+               if string(x) != "abc"+test.out {
+                       t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+                               "abc", test.in, test.base, x, test.out)
+               }
 
-               if uint64(uint(test.in)) == test.in {
-                       s := Uitob(uint(test.in), test.base)
-                       if s != test.out {
-                               t.Errorf("Uitob(%v, %v) = %v want %v",
-                                       test.in, test.base, s, test.out)
-                       }
+       }
+}
+
+func BenchmarkFormatInt(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               for _, test := range itob64tests {
+                       FormatInt(test.in, test.base)
                }
+       }
+}
 
-               if test.base == 10 {
-                       s := Uitoa64(test.in)
-                       if s != test.out {
-                               t.Errorf("Uitoa64(%v) = %v want %v",
-                                       test.in, s, test.out)
-                       }
+func BenchmarkAppendInt(b *testing.B) {
+       dst := make([]byte, 0, 30)
+       for i := 0; i < b.N; i++ {
+               for _, test := range itob64tests {
+                       AppendInt(dst, test.in, test.base)
+               }
+       }
+}
 
-                       if uint64(uint(test.in)) == test.in {
-                               s := Uitoa(uint(test.in))
-                               if s != test.out {
-                                       t.Errorf("Uitoa(%v) = %v want %v",
-                                               test.in, s, test.out)
-                               }
-                       }
+func BenchmarkFormatUint(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               for _, test := range uitob64tests {
+                       FormatUint(test.in, test.base)
+               }
+       }
+}
+
+func BenchmarkAppendUint(b *testing.B) {
+       dst := make([]byte, 0, 30)
+       for i := 0; i < b.N; i++ {
+               for _, test := range uitob64tests {
+                       AppendUint(dst, test.in, test.base)
                }
        }
 }
index 9b48c07..30b384d 100644 (file)
@@ -92,6 +92,12 @@ func Quote(s string) string {
        return quoteWith(s, '"', false)
 }
 
+// AppendQuote appends a double-quoted Go string literal representing s,
+// as generated by Quote, to dst and returns the extended buffer.
+func AppendQuote(dst []byte, s string) []byte {
+       return append(dst, Quote(s)...)
+}
+
 // QuoteToASCII returns a double-quoted Go string literal representing s.
 // The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
 // non-ASCII characters and non-printable characters as defined by
@@ -100,6 +106,12 @@ func QuoteToASCII(s string) string {
        return quoteWith(s, '"', true)
 }
 
+// AppendQuoteToASCII appends a double-quoted Go string literal representing s,
+// as generated by QuoteToASCII, to dst and returns the extended buffer.
+func AppendQuoteToASCII(dst []byte, s string) []byte {
+       return append(dst, QuoteToASCII(s)...)
+}
+
 // QuoteRune returns a single-quoted Go character literal representing the
 // rune.  The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
 // for control characters and non-printable characters as defined by
@@ -109,6 +121,12 @@ func QuoteRune(rune int) string {
        return quoteWith(string(rune), '\'', false)
 }
 
+// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRune, to dst and returns the extended buffer.
+func AppendQuoteRune(dst []byte, rune int) []byte {
+       return append(dst, QuoteRune(rune)...)
+}
+
 // QuoteRuneToASCII returns a single-quoted Go character literal representing
 // the rune.  The returned string uses Go escape sequences (\t, \n, \xFF,
 // \u0100) for non-ASCII characters and non-printable characters as defined
@@ -118,6 +136,12 @@ func QuoteRuneToASCII(rune int) string {
        return quoteWith(string(rune), '\'', true)
 }
 
+// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRuneToASCII, to dst and returns the extended buffer.
+func AppendQuoteRuneToASCII(dst []byte, rune int) []byte {
+       return append(dst, QuoteRuneToASCII(rune)...)
+}
+
 // CanBackquote returns whether the string s would be
 // a valid Go string literal if enclosed in backquotes.
 func CanBackquote(s string) bool {
index 9a59770..e440797 100644 (file)
@@ -29,6 +29,9 @@ func TestQuote(t *testing.T) {
                if out := Quote(tt.in); out != tt.out {
                        t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
                }
+               if out := AppendQuote([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+                       t.Errorf("AppendQuote(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+               }
        }
 }
 
@@ -37,6 +40,9 @@ func TestQuoteToASCII(t *testing.T) {
                if out := QuoteToASCII(tt.in); out != tt.ascii {
                        t.Errorf("QuoteToASCII(%s) = %s, want %s", tt.in, out, tt.ascii)
                }
+               if out := AppendQuoteToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+                       t.Errorf("AppendQuoteToASCII(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+               }
        }
 }
 
@@ -63,6 +69,9 @@ func TestQuoteRune(t *testing.T) {
                if out := QuoteRune(tt.in); out != tt.out {
                        t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
                }
+               if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+                       t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+               }
        }
 }
 
@@ -71,6 +80,9 @@ func TestQuoteRuneToASCII(t *testing.T) {
                if out := QuoteRuneToASCII(tt.in); out != tt.ascii {
                        t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii)
                }
+               if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+                       t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+               }
        }
 }
 
index 7b35d26..3abb51f 100644 (file)
@@ -13,35 +13,6 @@ import (
        "text/template/parse"
 )
 
-type isEmptyTest struct {
-       name  string
-       input string
-       empty bool
-}
-
-var isEmptyTests = []isEmptyTest{
-       {"empty", ``, true},
-       {"nonempty", `hello`, false},
-       {"spaces only", " \t\n \t\n", true},
-       {"definition", `{{define "x"}}something{{end}}`, true},
-       {"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
-       {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n}}", false},
-       {"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
-}
-
-func TestIsEmpty(t *testing.T) {
-       for _, test := range isEmptyTests {
-               template, err := New("root").Parse(test.input)
-               if err != nil {
-                       t.Errorf("%q: unexpected error: %v", test.name, err)
-                       continue
-               }
-               if empty := isEmpty(template.Root); empty != test.empty {
-                       t.Errorf("%q: expected %t got %t", test.name, test.empty, empty)
-               }
-       }
-}
-
 const (
        noError  = true
        hasError = false
index a4e5514..4f43424 100644 (file)
@@ -267,7 +267,7 @@ func newNumber(text string, typ itemType) (*NumberNode, error) {
        }
        // Imaginary constants can only be complex unless they are zero.
        if len(text) > 0 && text[len(text)-1] == 'i' {
-               f, err := strconv.Atof64(text[:len(text)-1])
+               f, err := strconv.ParseFloat(text[:len(text)-1], 64)
                if err == nil {
                        n.IsComplex = true
                        n.Complex128 = complex(0, f)
@@ -276,12 +276,12 @@ func newNumber(text string, typ itemType) (*NumberNode, error) {
                }
        }
        // Do integer test first so we get 0x123 etc.
-       u, err := strconv.Btoui64(text, 0) // will fail for -0; fixed below.
+       u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below.
        if err == nil {
                n.IsUint = true
                n.Uint64 = u
        }
-       i, err := strconv.Btoi64(text, 0)
+       i, err := strconv.ParseInt(text, 0, 64)
        if err == nil {
                n.IsInt = true
                n.Int64 = i
@@ -298,7 +298,7 @@ func newNumber(text string, typ itemType) (*NumberNode, error) {
                n.IsFloat = true
                n.Float64 = float64(n.Uint64)
        } else {
-               f, err := strconv.Atof64(text)
+               f, err := strconv.ParseFloat(text, 64)
                if err == nil {
                        n.IsFloat = true
                        n.Float64 = f
index 346f613..4da7566 100644 (file)
@@ -7,6 +7,7 @@
 package parse
 
 import (
+       "bytes"
        "fmt"
        "runtime"
        "strconv"
@@ -177,10 +178,37 @@ func (t *Tree) Parse(s, leftDelim, rightDelim string, treeSet map[string]*Tree,
 
 // add adds tree to the treeSet.
 func (t *Tree) add(treeSet map[string]*Tree) {
-       if _, present := treeSet[t.Name]; present {
+       tree := treeSet[t.Name]
+       if tree == nil || IsEmptyTree(tree.Root) {
+               treeSet[t.Name] = t
+               return
+       }
+       if !IsEmptyTree(t.Root) {
                t.errorf("template: multiple definition of template %q", t.Name)
        }
-       treeSet[t.Name] = t
+}
+
+// IsEmptyTree reports whether this tree (node) is empty of everything but space.
+func IsEmptyTree(n Node) bool {
+       switch n := n.(type) {
+       case *ActionNode:
+       case *IfNode:
+       case *ListNode:
+               for _, node := range n.Nodes {
+                       if !IsEmptyTree(node) {
+                               return false
+                       }
+               }
+               return true
+       case *RangeNode:
+       case *TemplateNode:
+       case *TextNode:
+               return len(bytes.TrimSpace(n.Text)) == 0
+       case *WithNode:
+       default:
+               panic("unknown node: " + n.String())
+       }
+       return false
 }
 
 // parse is the top-level parser for a template, essentially the same
index fc93455..b70c214 100644 (file)
@@ -257,3 +257,32 @@ func TestParse(t *testing.T) {
                }
        }
 }
+
+type isEmptyTest struct {
+       name  string
+       input string
+       empty bool
+}
+
+var isEmptyTests = []isEmptyTest{
+       {"empty", ``, true},
+       {"nonempty", `hello`, false},
+       {"spaces only", " \t\n \t\n", true},
+       {"definition", `{{define "x"}}something{{end}}`, true},
+       {"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
+       {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n}}", false},
+       {"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
+}
+
+func TestIsEmpty(t *testing.T) {
+       for _, test := range isEmptyTests {
+               tree, err := New("root").Parse(test.input, "", "", make(map[string]*Tree), nil)
+               if err != nil {
+                       t.Errorf("%q: unexpected error: %v", test.name, err)
+                       continue
+               }
+               if empty := IsEmptyTree(tree.Root); empty != test.empty {
+                       t.Errorf("%q: expected %t got %t", test.name, test.empty, empty)
+               }
+       }
+}
index 04fca40..cbc6808 100644 (file)
@@ -5,7 +5,6 @@
 package template
 
 import (
-       "bytes"
        "fmt"
        "reflect"
        "text/template/parse"
@@ -198,8 +197,8 @@ func (t *Template) associate(new *Template) error {
        }
        name := new.name
        if old := t.tmpl[name]; old != nil {
-               oldIsEmpty := isEmpty(old.Root)
-               newIsEmpty := isEmpty(new.Root)
+               oldIsEmpty := parse.IsEmptyTree(old.Root)
+               newIsEmpty := parse.IsEmptyTree(new.Root)
                if !oldIsEmpty && !newIsEmpty {
                        return fmt.Errorf("template: redefinition of template %q", name)
                }
@@ -211,26 +210,3 @@ func (t *Template) associate(new *Template) error {
        t.tmpl[name] = new
        return nil
 }
-
-// isEmpty reports whether this tree (node) is empty of everything but space.
-func isEmpty(n parse.Node) bool {
-       switch n := n.(type) {
-       case *parse.ActionNode:
-       case *parse.IfNode:
-       case *parse.ListNode:
-               for _, node := range n.Nodes {
-                       if !isEmpty(node) {
-                               return false
-                       }
-               }
-               return true
-       case *parse.RangeNode:
-       case *parse.TemplateNode:
-       case *parse.TextNode:
-               return len(bytes.TrimSpace(n.Text)) == 0
-       case *parse.WithNode:
-       default:
-               panic("unknown node: " + n.String())
-       }
-       return false
-}
index 9590e28..6d1e79b 100644 (file)
@@ -339,7 +339,7 @@ func checkTime(time Time, test *ParseTest, t *testing.T) {
                t.Errorf("%s: bad second: %d not %d", test.name, time.Second(), 57)
        }
        // Nanoseconds must be checked against the precision of the input.
-       nanosec, err := strconv.Atoui("012345678"[:test.fracDigits] + "000000000"[:9-test.fracDigits])
+       nanosec, err := strconv.ParseUint("012345678"[:test.fracDigits]+"000000000"[:9-test.fracDigits], 10, 0)
        if err != nil {
                panic(err)
        }
index 9343bc9..2904da6 100644 (file)
@@ -32,8 +32,8 @@ var PrintRanges = []*RangeTable{
 // Such characters include letters, marks, numbers, punctuation, symbols, and
 // spaces, from categories L, M, N, P, S, Zs.
 func IsGraphic(r rune) bool {
-       // We cast to uint32 to avoid the extra test for negative,
-       // and in the index we cast to uint8 to avoid the range check.
+       // We convert to uint32 to avoid the extra test for negative,
+       // and in the index we convert to uint8 to avoid the range check.
        if uint32(r) <= MaxLatin1 {
                return properties[uint8(r)]&pg != 0
        }
index ec7b7ae..d0ddbee 100644 (file)
@@ -365,13 +365,13 @@ func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer)
        key2, number2 := generateKeyNumber()
        if config.handshakeData != nil {
                key1 = config.handshakeData["key1"]
-               n, err := strconv.Atoui(config.handshakeData["number1"])
+               n, err := strconv.ParseUint(config.handshakeData["number1"], 10, 32)
                if err != nil {
                        panic(err)
                }
                number1 = uint32(n)
                key2 = config.handshakeData["key2"]
-               n, err = strconv.Atoui(config.handshakeData["number2"])
+               n, err = strconv.ParseUint(config.handshakeData["number2"], 10, 32)
                if err != nil {
                        panic(err)
                }