aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-02-23 14:27:55 -0500
committerRuss Cox <rsc@golang.org>2015-02-23 14:28:54 -0500
commite8d9c8d1631d80aa96fdd8fe0587f09ed5a3332a (patch)
tree7d24106555c0ad685ae7134e44c4d943ac8583d6
parent20f9f544bfd8562cc6e186e0cb0335667d24fee6 (diff)
parent6a10f720f2f3bd48f37c5d357c41e02c8722033a (diff)
downloadgo-e8d9c8d1631d80aa96fdd8fe0587f09ed5a3332a.tar.gz
go-e8d9c8d1631d80aa96fdd8fe0587f09ed5a3332a.zip
[dev.cc] all: merge master (6a10f72) into dev.cc
To pick up darwin/arm fix and hopefully fix build. Change-Id: I06996d0b13b777e476f65405aee031482fc76439
-rw-r--r--src/cmd/go/test.go9
-rw-r--r--src/go/build/deps_test.go2
-rw-r--r--src/go/token/position.go6
-rw-r--r--src/internal/mime/header.go122
-rw-r--r--src/math/big/float.go58
-rw-r--r--src/math/big/float_test.go2
-rw-r--r--src/math/big/floatconv.go17
-rw-r--r--src/math/big/floatconv_test.go6
-rw-r--r--src/math/big/int.go2
-rw-r--r--src/math/big/natconv.go2
-rw-r--r--src/net/mail/message.go103
-rw-r--r--src/runtime/malloc.go6
12 files changed, 187 insertions, 148 deletions
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index a8110f385d..c44a2199dc 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -772,6 +772,10 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
recompileForTest(pmain, p, ptest, testDir)
}
+ if buildContext.GOOS == "darwin" && buildContext.GOARCH == "arm" {
+ t.NeedCgo = true
+ }
+
for _, cp := range pmain.imports {
if len(cp.coverVars) > 0 {
t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars})
@@ -1207,6 +1211,7 @@ type testFuncs struct {
NeedTest bool
ImportXtest bool
NeedXtest bool
+ NeedCgo bool
Cover []coverInfo
}
@@ -1310,6 +1315,10 @@ import (
{{range $i, $p := .Cover}}
_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
{{end}}
+
+{{if .NeedCgo}}
+ _ "runtime/cgo"
+{{end}}
)
var tests = []testing.InternalTest{
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 98201a5d96..d186a17e0e 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -252,7 +252,7 @@ var pkgDeps = map[string][]string{
// Uses of networking.
"log/syslog": {"L4", "OS", "net"},
- "net/mail": {"L4", "NET", "OS"},
+ "net/mail": {"L4", "NET", "OS", "internal/mime"},
"net/textproto": {"L4", "OS", "net"},
// Core crypto.
diff --git a/src/go/token/position.go b/src/go/token/position.go
index 82d90eeb72..17452bb3d5 100644
--- a/src/go/token/position.go
+++ b/src/go/token/position.go
@@ -21,7 +21,7 @@ type Position struct {
Filename string // filename, if any
Offset int // offset, starting at 0
Line int // line number, starting at 1
- Column int // column number, starting at 1 (character count)
+ Column int // column number, starting at 1 (byte count)
}
// IsValid returns true if the position is valid.
@@ -56,8 +56,8 @@ func (pos Position) String() string {
// where base and size are specified when adding the file to the file set via
// AddFile.
//
-// To create the Pos value for a specific source offset, first add
-// the respective file to the current file set (via FileSet.AddFile)
+// To create the Pos value for a specific source offset (measured in bytes),
+// first add the respective file to the current file set using FileSet.AddFile
// and then call File.Pos(offset) for that file. Given a Pos value p
// for a specific file set fset, the corresponding Position value is
// obtained by calling fset.Position(p).
diff --git a/src/internal/mime/header.go b/src/internal/mime/header.go
new file mode 100644
index 0000000000..9bc3e5e576
--- /dev/null
+++ b/src/internal/mime/header.go
@@ -0,0 +1,122 @@
+// Copyright 2015 The Go 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 mime
+
+import (
+ "bytes"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+// EncodeWord encodes a string into an RFC 2047 encoded-word.
+func EncodeWord(s string) string {
+ // UTF-8 "Q" encoding
+ b := bytes.NewBufferString("=?utf-8?q?")
+ for i := 0; i < len(s); i++ {
+ switch c := s[i]; {
+ case c == ' ':
+ b.WriteByte('_')
+ case isVchar(c) && c != '=' && c != '?' && c != '_':
+ b.WriteByte(c)
+ default:
+ fmt.Fprintf(b, "=%02X", c)
+ }
+ }
+ b.WriteString("?=")
+ return b.String()
+}
+
+// DecodeWord decodes an RFC 2047 encoded-word.
+func DecodeWord(s string) (string, error) {
+ fields := strings.Split(s, "?")
+ if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" {
+ return "", errors.New("address not RFC 2047 encoded")
+ }
+ charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2])
+ if charset != "us-ascii" && charset != "iso-8859-1" && charset != "utf-8" {
+ return "", fmt.Errorf("charset not supported: %q", charset)
+ }
+
+ in := bytes.NewBufferString(fields[3])
+ var r io.Reader
+ switch enc {
+ case "b":
+ r = base64.NewDecoder(base64.StdEncoding, in)
+ case "q":
+ r = qDecoder{r: in}
+ default:
+ return "", fmt.Errorf("RFC 2047 encoding not supported: %q", enc)
+ }
+
+ dec, err := ioutil.ReadAll(r)
+ if err != nil {
+ return "", err
+ }
+
+ switch charset {
+ case "us-ascii":
+ b := new(bytes.Buffer)
+ for _, c := range dec {
+ if c >= 0x80 {
+ b.WriteRune(unicode.ReplacementChar)
+ } else {
+ b.WriteRune(rune(c))
+ }
+ }
+ return b.String(), nil
+ case "iso-8859-1":
+ b := new(bytes.Buffer)
+ for _, c := range dec {
+ b.WriteRune(rune(c))
+ }
+ return b.String(), nil
+ case "utf-8":
+ return string(dec), nil
+ }
+ panic("unreachable")
+}
+
+type qDecoder struct {
+ r io.Reader
+ scratch [2]byte
+}
+
+func (qd qDecoder) Read(p []byte) (n int, err error) {
+ // This method writes at most one byte into p.
+ if len(p) == 0 {
+ return 0, nil
+ }
+ if _, err := qd.r.Read(qd.scratch[:1]); err != nil {
+ return 0, err
+ }
+ switch c := qd.scratch[0]; {
+ case c == '=':
+ if _, err := io.ReadFull(qd.r, qd.scratch[:2]); err != nil {
+ return 0, err
+ }
+ x, err := strconv.ParseInt(string(qd.scratch[:2]), 16, 64)
+ if err != nil {
+ return 0, fmt.Errorf("mime: invalid RFC 2047 encoding: %q", qd.scratch[:2])
+ }
+ p[0] = byte(x)
+ case c == '_':
+ p[0] = ' '
+ default:
+ p[0] = c
+ }
+ return 1, nil
+}
+
+// isVchar returns true if c is an RFC 5322 VCHAR character.
+func isVchar(c byte) bool {
+ // Visible (printing) characters.
+ return '!' <= c && c <= '~'
+}
diff --git a/src/math/big/float.go b/src/math/big/float.go
index 877379c901..47755f2719 100644
--- a/src/math/big/float.go
+++ b/src/math/big/float.go
@@ -39,10 +39,10 @@ const debugFloat = true // enable for debugging
// and according to its rounding mode, unless specified otherwise. If the
// result precision is 0 (see below), it is set to the precision of the
// argument with the largest precision value before any rounding takes
-// place. The rounding mode remains unchanged, thus uninitialized Floats
-// provided as result arguments will "inherit" a reasonble precision from
-// the incoming arguments and their mode is the zero value for RoundingMode
-// (ToNearestEven).
+// place, and the rounding mode remains unchanged. Thus, uninitialized Floats
+// provided as result arguments will have their precision set to a reasonable
+// value determined by the operands and their mode is the zero value for
+// RoundingMode (ToNearestEven).
//
// By setting the desired precision to 24 or 53 and using ToNearestEven
// rounding, Float operations produce the same results as the corresponding
@@ -62,6 +62,9 @@ type Float struct {
prec uint // TODO(gri) make this a 32bit field
}
+// TODO(gri) provide a couple of Example tests showing typical Float intialization
+// and use.
+
// Internal representation: The mantissa bits x.mant of a Float x are stored
// in a nat slice long enough to hold up to x.prec bits; the slice may (but
// doesn't have to) be shorter if the mantissa contains trailing 0 bits.
@@ -158,7 +161,7 @@ func (z *Float) SetPrec(prec uint) *Float {
// SetMode sets z's rounding mode to mode and returns an exact z.
// z remains unchanged otherwise.
func (z *Float) SetMode(mode RoundingMode) *Float {
- z.acc = Exact
+ z.acc = Exact // TODO(gri) should we not do this? what's the general rule for setting accuracy?
z.mode = mode
return z
}
@@ -274,23 +277,21 @@ func (z *Float) setExp(e int64) {
}
// debugging support
-func validate(args ...*Float) {
- for i, x := range args {
- const msb = 1 << (_W - 1)
- m := len(x.mant)
- if m == 0 {
- // 0.0 or Inf
- if x.exp != 0 && x.exp != infExp {
- panic(fmt.Sprintf("#%d: %empty matissa with invalid exponent %d", i, x.exp))
- }
- continue
- }
- if x.mant[m-1]&msb == 0 {
- panic(fmt.Sprintf("#%d: msb not set in last word %#x of %s", i, x.mant[m-1], x.Format('p', 0)))
- }
- if x.prec <= 0 {
- panic(fmt.Sprintf("#%d: invalid precision %d", i, x.prec))
+func validate(x *Float) {
+ const msb = 1 << (_W - 1)
+ m := len(x.mant)
+ if m == 0 {
+ // 0.0 or Inf
+ if x.exp != 0 && x.exp != infExp {
+ panic(fmt.Sprintf("%empty matissa with invalid exponent %d", x.exp))
}
+ return
+ }
+ if x.mant[m-1]&msb == 0 {
+ panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Format('p', 0)))
+ }
+ if x.prec <= 0 {
+ panic(fmt.Sprintf("invalid precision %d", x.prec))
}
}
@@ -1064,7 +1065,8 @@ func (x *Float) ucmp(y *Float) int {
// result.
func (z *Float) Add(x, y *Float) *Float {
if debugFloat {
- validate(x, y)
+ validate(x)
+ validate(y)
}
if z.prec == 0 {
@@ -1104,7 +1106,8 @@ func (z *Float) Add(x, y *Float) *Float {
// Precision, rounding, and accuracy reporting are as for Add.
func (z *Float) Sub(x, y *Float) *Float {
if debugFloat {
- validate(x, y)
+ validate(x)
+ validate(y)
}
if z.prec == 0 {
@@ -1143,7 +1146,8 @@ func (z *Float) Sub(x, y *Float) *Float {
// Precision, rounding, and accuracy reporting are as for Add.
func (z *Float) Mul(x, y *Float) *Float {
if debugFloat {
- validate(x, y)
+ validate(x)
+ validate(y)
}
if z.prec == 0 {
@@ -1171,7 +1175,8 @@ func (z *Float) Mul(x, y *Float) *Float {
// Precision, rounding, and accuracy reporting are as for Add.
func (z *Float) Quo(x, y *Float) *Float {
if debugFloat {
- validate(x, y)
+ validate(x)
+ validate(y)
}
if z.prec == 0 {
@@ -1251,7 +1256,8 @@ func (z *Float) Rsh(x *Float, s uint) *Float {
// Infinities with matching sign are equal.
func (x *Float) Cmp(y *Float) int {
if debugFloat {
- validate(x, y)
+ validate(x)
+ validate(y)
}
mx := x.ord()
diff --git a/src/math/big/float_test.go b/src/math/big/float_test.go
index 17247b1eb2..2789cfb9f3 100644
--- a/src/math/big/float_test.go
+++ b/src/math/big/float_test.go
@@ -1077,6 +1077,8 @@ func TestFloatQuoSmoke(t *testing.T) {
}
}
+// TODO(gri) Add tests that check correctness in the presence of aliasing.
+
// For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected
// by the sign of the value to be rounded. Test that rounding happens after
// the sign of a result has been set.
diff --git a/src/math/big/floatconv.go b/src/math/big/floatconv.go
index a857fa6513..e41d447db0 100644
--- a/src/math/big/floatconv.go
+++ b/src/math/big/floatconv.go
@@ -126,11 +126,9 @@ func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
}
// Parse is like z.Scan(r, base), but instead of reading from an
-// io.ByteScanner, it parses the string s. An error is returned if the
-// string contains invalid or trailing characters not belonging to the
-// number.
-//
-// TODO(gri) define possible errors more precisely
+// io.ByteScanner, it parses the string s. An error is returned if
+// the string contains invalid or trailing bytes not belonging to
+// the number.
func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
r := strings.NewReader(s)
@@ -139,11 +137,10 @@ func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
}
// entire string must have been consumed
- var ch byte
- if ch, err = r.ReadByte(); err != io.EOF {
- if err == nil {
- err = fmt.Errorf("expected end of string, found %q", ch)
- }
+ if ch, err2 := r.ReadByte(); err2 == nil {
+ err = fmt.Errorf("expected end of string, found %q", ch)
+ } else if err2 != io.EOF {
+ err = err2
}
return
diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go
index 11e5df448a..a22a1f7ddf 100644
--- a/src/math/big/floatconv_test.go
+++ b/src/math/big/floatconv_test.go
@@ -5,7 +5,6 @@
package big
import (
- "io"
"math"
"strconv"
"testing"
@@ -59,7 +58,7 @@ func TestFloatSetFloat64String(t *testing.T) {
{"+10000000000000000000000000000000000000000e-0", 1e40},
} {
var x Float
- x.prec = 53 // TODO(gri) find better solution
+ x.SetPrec(53)
_, ok := x.SetString(test.s)
if !ok {
t.Errorf("%s: parse error", test.s)
@@ -313,8 +312,7 @@ func TestFloatFormat(t *testing.T) {
{"3.14", 'x', 0, "%x"},
} {
f, _, err := ParseFloat(test.x, 0, 1000, ToNearestEven)
- // TODO(gri) should we return io.EOF at the end?
- if err != nil && err != io.EOF {
+ if err != nil {
t.Errorf("%v: %s", test, err)
continue
}
diff --git a/src/math/big/int.go b/src/math/big/int.go
index 5c1b2cd765..0695d78973 100644
--- a/src/math/big/int.go
+++ b/src/math/big/int.go
@@ -361,7 +361,7 @@ func (x *Int) Uint64() uint64 {
// and returns z and a boolean indicating success. If SetString fails,
// the value of z is undefined but the returned value is nil.
//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// The base argument must be 0 or a value between 2 and MaxBase. If the base
// is 0, the string prefix determines the actual conversion base. A prefix of
// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
diff --git a/src/math/big/natconv.go b/src/math/big/natconv.go
index b5c37731fa..022dcfe38c 100644
--- a/src/math/big/natconv.go
+++ b/src/math/big/natconv.go
@@ -60,7 +60,7 @@ func pow(x Word, n int) (p Word) {
// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
//
// Unless fracOk is set, the base argument must be 0 or a value between
-// 2 through MaxBase. If fracOk is set, the base argument must be one of
+// 2 and MaxBase. If fracOk is set, the base argument must be one of
// 0, 2, 10, or 16. Providing an invalid base argument leads to a run-
// time panic.
//
diff --git a/src/net/mail/message.go b/src/net/mail/message.go
index 19aa888d87..71fe74b9ca 100644
--- a/src/net/mail/message.go
+++ b/src/net/mail/message.go
@@ -18,17 +18,14 @@ package mail
import (
"bufio"
"bytes"
- "encoding/base64"
"errors"
"fmt"
+ "internal/mime"
"io"
- "io/ioutil"
"log"
"net/textproto"
- "strconv"
"strings"
"time"
- "unicode"
)
var debug = debugT(false)
@@ -180,21 +177,7 @@ func (a *Address) String() string {
return b.String()
}
- // UTF-8 "Q" encoding
- b := bytes.NewBufferString("=?utf-8?q?")
- for i := 0; i < len(a.Name); i++ {
- switch c := a.Name[i]; {
- case c == ' ':
- b.WriteByte('_')
- case isVchar(c) && c != '=' && c != '?' && c != '_':
- b.WriteByte(c)
- default:
- fmt.Fprintf(b, "=%02X", c)
- }
- }
- b.WriteString("?= ")
- b.WriteString(s)
- return b.String()
+ return mime.EncodeWord(a.Name) + " " + s
}
type addrParser []byte
@@ -352,7 +335,7 @@ func (p *addrParser) consumePhrase() (phrase string, err error) {
// RFC 2047 encoded-word starts with =?, ends with ?=, and has two other ?s.
if err == nil && strings.HasPrefix(word, "=?") && strings.HasSuffix(word, "?=") && strings.Count(word, "?") == 4 {
- word, err = decodeRFC2047Word(word)
+ word, err = mime.DecodeWord(word)
}
if err != nil {
@@ -440,86 +423,6 @@ func (p *addrParser) len() int {
return len(*p)
}
-func decodeRFC2047Word(s string) (string, error) {
- fields := strings.Split(s, "?")
- if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" {
- return "", errors.New("address not RFC 2047 encoded")
- }
- charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2])
- if charset != "us-ascii" && charset != "iso-8859-1" && charset != "utf-8" {
- return "", fmt.Errorf("charset not supported: %q", charset)
- }
-
- in := bytes.NewBufferString(fields[3])
- var r io.Reader
- switch enc {
- case "b":
- r = base64.NewDecoder(base64.StdEncoding, in)
- case "q":
- r = qDecoder{r: in}
- default:
- return "", fmt.Errorf("RFC 2047 encoding not supported: %q", enc)
- }
-
- dec, err := ioutil.ReadAll(r)
- if err != nil {
- return "", err
- }
-
- switch charset {
- case "us-ascii":
- b := new(bytes.Buffer)
- for _, c := range dec {
- if c >= 0x80 {
- b.WriteRune(unicode.ReplacementChar)
- } else {
- b.WriteRune(rune(c))
- }
- }
- return b.String(), nil
- case "iso-8859-1":
- b := new(bytes.Buffer)
- for _, c := range dec {
- b.WriteRune(rune(c))
- }
- return b.String(), nil
- case "utf-8":
- return string(dec), nil
- }
- panic("unreachable")
-}
-
-type qDecoder struct {
- r io.Reader
- scratch [2]byte
-}
-
-func (qd qDecoder) Read(p []byte) (n int, err error) {
- // This method writes at most one byte into p.
- if len(p) == 0 {
- return 0, nil
- }
- if _, err := qd.r.Read(qd.scratch[:1]); err != nil {
- return 0, err
- }
- switch c := qd.scratch[0]; {
- case c == '=':
- if _, err := io.ReadFull(qd.r, qd.scratch[:2]); err != nil {
- return 0, err
- }
- 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])
- }
- p[0] = byte(x)
- case c == '_':
- p[0] = ' '
- default:
- p[0] = c
- }
- return 1, nil
-}
-
var atextChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz" +
"0123456789" +
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 475f97fd05..fac5ca49ce 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -553,7 +553,8 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
}
s.freelist = v.ptr().next
s.ref++
- //TODO: prefetch v.next
+ // prefetchnta offers best performance, see change list message.
+ prefetchnta(uintptr(v.ptr().next))
x = unsafe.Pointer(v)
(*[2]uint64)(x)[0] = 0
(*[2]uint64)(x)[1] = 0
@@ -584,7 +585,8 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
}
s.freelist = v.ptr().next
s.ref++
- //TODO: prefetch
+ // prefetchnta offers best performance, see change list message.
+ prefetchnta(uintptr(v.ptr().next))
x = unsafe.Pointer(v)
if flags&flagNoZero == 0 {
v.ptr().next = 0