diff options
51 files changed, 612 insertions, 168 deletions
diff --git a/libgo/MERGE b/libgo/MERGE index 13b0438ece6..e7e992c1e86 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -3cdba7b0650c +bce220d03774 The first line of this file holds the Mercurial revision number of the last merge done from the master library sources. diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go index c2db0dc4a7c..5f1d1b28a98 100644 --- a/libgo/go/archive/zip/reader_test.go +++ b/libgo/go/archive/zip/reader_test.go @@ -7,10 +7,12 @@ package zip import ( "bytes" "encoding/binary" + "encoding/hex" "io" "io/ioutil" "os" "path/filepath" + "regexp" "testing" "time" ) @@ -62,13 +64,14 @@ var tests = []ZipTest{ }, }, { - Name: "r.zip", + Name: "r.zip", + Source: returnRecursiveZip, File: []ZipTestFile{ { - Name: "r/r.zip", - File: "r.zip", - Mtime: "03-04-10 00:24:16", - Mode: 0666, + Name: "r/r.zip", + Content: rZipBytes(), + Mtime: "03-04-10 00:24:16", + Mode: 0666, }, }, }, @@ -415,3 +418,49 @@ func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) { // is what matters. }) } + +// rZipBytes returns the bytes of a recursive zip file, without +// putting it on disk and triggering certain virus scanners. +func rZipBytes() []byte { + s := ` +0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4 +0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f +0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00 +0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 +0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 +0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00 +0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8 +0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f +0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e +0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb +00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff +00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 +00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14 +00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21 +00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb +00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff +0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a +0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3 +0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06 +0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00 +0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf +0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06 +0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01 +0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89 +0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00 +0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a +00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00 +00001b0 00 00 6d 01 00 00 00 00` + s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "") + s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "") + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +func returnRecursiveZip() (r io.ReaderAt, size int64) { + b := rZipBytes() + return bytes.NewReader(b), int64(len(b)) +} diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go index 266eb8f578d..2877f17387d 100644 --- a/libgo/go/crypto/tls/handshake_client.go +++ b/libgo/go/crypto/tls/handshake_client.go @@ -166,8 +166,11 @@ func (c *Conn) clientHandshake() error { } var certToSend *Certificate + var certRequested bool certReq, ok := msg.(*certificateRequestMsg) if ok { + certRequested = true + // RFC 4346 on the certificateAuthorities field: // A list of the distinguished names of acceptable certificate // authorities. These distinguished names may specify a desired @@ -238,9 +241,14 @@ func (c *Conn) clientHandshake() error { } finishedHash.Write(shd.marshal()) - if certToSend != nil { + // If the server requested a certificate then we have to send a + // Certificate message, even if it's empty because we don't have a + // certificate to send. + if certRequested { certMsg = new(certificateMsg) - certMsg.certificates = certToSend.Certificate + if certToSend != nil { + certMsg.certificates = certToSend.Certificate + } finishedHash.Write(certMsg.marshal()) c.writeRecord(recordTypeHandshake, certMsg.marshal()) } diff --git a/libgo/go/encoding/gob/doc.go b/libgo/go/encoding/gob/doc.go index c9ad18e7641..96885f8ded4 100644 --- a/libgo/go/encoding/gob/doc.go +++ b/libgo/go/encoding/gob/doc.go @@ -226,7 +226,7 @@ where * signifies zero or more repetitions and the type id of a value must be predefined or be defined before the value in the stream. See "Gobs of data" for a design discussion of the gob wire format: -http://blog.golang.org/2011/03/gobs-of-data.html +http://golang.org/doc/articles/gobs_of_data.html */ package gob diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go index edbafcf65f1..14957b8487b 100644 --- a/libgo/go/encoding/json/encode.go +++ b/libgo/go/encoding/json/encode.go @@ -6,7 +6,7 @@ // RFC 4627. // // See "JSON and Go" for an introduction to this package: -// http://blog.golang.org/2011/01/json-and-go.html +// http://golang.org/doc/articles/json_and_go.html package json import ( diff --git a/libgo/go/exp/norm/normalize.go b/libgo/go/exp/norm/normalize.go index b5cd44abfa0..c1d74f89d01 100644 --- a/libgo/go/exp/norm/normalize.go +++ b/libgo/go/exp/norm/normalize.go @@ -356,7 +356,7 @@ func lastBoundary(fd *formInfo, b []byte) int { return -1 } if info.size == 0 { // ends with incomplete rune - if p == 0 { // starts wtih incomplete rune + if p == 0 { // starts with incomplete rune return -1 } i = p diff --git a/libgo/go/exp/types/universe.go b/libgo/go/exp/types/universe.go index 46cff31bce8..cb89397b2e5 100644 --- a/libgo/go/exp/types/universe.go +++ b/libgo/go/exp/types/universe.go @@ -102,11 +102,6 @@ func init() { defType("Pointer") defFun("Alignof") - defFun("New") - defFun("NewArray") defFun("Offsetof") - defFun("Reflect") defFun("Sizeof") - defFun("Typeof") - defFun("Unreflect") } diff --git a/libgo/go/flag/example_test.go b/libgo/go/flag/example_test.go new file mode 100644 index 00000000000..04a0d20ee4e --- /dev/null +++ b/libgo/go/flag/example_test.go @@ -0,0 +1,83 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// These examples demonstrate more intricate uses of the flag package. +package flag_test + +import ( + "errors" + "flag" + "fmt" + "strings" + "time" +) + +// Example 1: A single string flag called "species" with default value "gopher". +var species = flag.String("species", "gopher", "the species we are studying") + +// Example 2: Two flags sharing a variable, so we can have a shorthand. +// The order of initialization is undefined, so make sure both use the +// same default value. They must be set up with an init function. +var gopherType string + +func init() { + const ( + defaultGopher = "pocket" + usage = "the variety of gopher" + ) + flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage) + flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)") +} + +// Example 3: A user-defined flag type, a slice of durations. +type interval []time.Duration + +// String is the method to format the flag's value, part of the flag.Value interface. +// The String method's output will be used in diagnostics. +func (i *interval) String() string { + return fmt.Sprint(*i) +} + +// Set is the method to set the flag value, part of the flag.Value interface. +// Set's argument is a string to be parsed to set the flag. +// It's a comma-separated list, so we split it. +func (i *interval) Set(value string) error { + // If we wanted to allow the flag to be set multiple times, + // accumulating values, we would delete this if statement. + // That would permit usages such as + // -deltaT 10s -deltaT 15s + // and other combinations. + if len(*i) > 0 { + return errors.New("interval flag already set") + } + for _, dt := range strings.Split(value, ",") { + duration, err := time.ParseDuration(dt) + if err != nil { + return err + } + *i = append(*i, duration) + } + return nil +} + +// Define a flag to accumulate durations. Because it has a special type, +// we need to use the Var function and therefore create the flag during +// init. + +var intervalFlag interval + +func init() { + // Tie the command-line flag to the intervalFlag variable and + // set a usage message. + flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events") +} + +func Example() { + // All the interesting pieces are with the variables declared above, but + // to enable the flag package to see the flags defined there, one must + // execute, typically at the start of main (not init!): + // flag.Parse() + // We don't run it here because this is not a main function and + // the testing suite has already parsed the flags. +} diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go index 61b48f9cc6d..320857b73e2 100644 --- a/libgo/go/fmt/scan_test.go +++ b/libgo/go/fmt/scan_test.go @@ -810,7 +810,7 @@ func TestMultiLine(t *testing.T) { } } -// RecursiveInt accepts an string matching %d.%d.%d.... +// RecursiveInt accepts a string matching %d.%d.%d.... // and parses it into a linked list. // It allows us to benchmark recursive descent style scanners. type RecursiveInt struct { @@ -826,7 +826,7 @@ func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) { next := new(RecursiveInt) _, err = Fscanf(state, ".%v", next) if err != nil { - if err == errors.New("input does not match format") || err == io.ErrUnexpectedEOF { + if err == io.ErrUnexpectedEOF { err = nil } return diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go index dc9dcd1d652..d113dc135b1 100644 --- a/libgo/go/go/build/build.go +++ b/libgo/go/go/build/build.go @@ -328,22 +328,22 @@ func (e *NoGoError) Error() string { } // Import returns details about the Go package named by the import path, -// interpreting local import paths relative to the src directory. If the path -// is a local import path naming a package that can be imported using a -// standard import path, the returned package will set p.ImportPath to -// that path. +// interpreting local import paths relative to the srcDir directory. +// If the path is a local import path naming a package that can be imported +// using a standard import path, the returned package will set p.ImportPath +// to that path. // // In the directory containing the package, .go, .c, .h, and .s files are // considered part of the package except for: // // - .go files in package documentation -// - files starting with _ or . +// - files starting with _ or . (likely editor temporary files) // - files with build constraints not satisfied by the context // // If an error occurs, Import returns a non-nil error also returns a non-nil // *Package containing partial information. // -func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package, error) { +func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) { p := &Package{ ImportPath: path, } @@ -363,11 +363,12 @@ func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package, binaryOnly := false if IsLocalImport(path) { - if src == "" { + pkga = "" // local imports have no installed path + if srcDir == "" { return p, fmt.Errorf("import %q: import relative to unknown directory", path) } if !ctxt.isAbsPath(path) { - p.Dir = ctxt.joinPath(src, path) + p.Dir = ctxt.joinPath(srcDir, path) } // Determine canonical import path, if any. if ctxt.GOROOT != "" { @@ -640,8 +641,8 @@ func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.P } // Import is shorthand for Default.Import. -func Import(path, src string, mode ImportMode) (*Package, error) { - return Default.Import(path, src, mode) +func Import(path, srcDir string, mode ImportMode) (*Package, error) { + return Default.Import(path, srcDir, mode) } // ImportDir is shorthand for Default.ImportDir. @@ -874,7 +875,7 @@ func splitQuoted(s string) (r []string, err error) { // !cgo (if cgo is disabled) // tag (if tag is listed in ctxt.BuildTags) // !tag (if tag is not listed in ctxt.BuildTags) -// a slash-separated list of any of these +// a comma-separated list of any of these // func (ctxt *Context) match(name string) bool { if name == "" { @@ -888,11 +889,11 @@ func (ctxt *Context) match(name string) bool { return false } if strings.HasPrefix(name, "!") { // negation - return !ctxt.match(name[1:]) + return len(name) > 1 && !ctxt.match(name[1:]) } // Tags must be letters, digits, underscores. - // Unlike in Go identifiers, all digits is fine (e.g., "386"). + // Unlike in Go identifiers, all digits are fine (e.g., "386"). for _, c := range name { if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' { return false diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go index 06b8b0e94f8..560ebad5c97 100644 --- a/libgo/go/go/build/build_test.go +++ b/libgo/go/go/build/build_test.go @@ -36,6 +36,7 @@ func TestMatch(t *testing.T) { nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo") match(runtime.GOOS + "," + runtime.GOARCH + ",!bar") nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar") + nomatch("!") } func TestDotSlashImport(t *testing.T) { diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go index 6be3c09382e..727d2a37147 100644 --- a/libgo/go/go/printer/nodes.go +++ b/libgo/go/go/printer/nodes.go @@ -365,7 +365,7 @@ func (p *printer) setLineComment(text string) { } func (p *printer) isMultiLine(n ast.Node) bool { - return p.lineFor(n.End())-p.lineFor(n.Pos()) > 1 + return p.lineFor(n.End())-p.lineFor(n.Pos()) > 0 } func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) { diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden index 7ed7cb61ae5..71ed32ed145 100644 --- a/libgo/go/go/printer/testdata/declarations.golden +++ b/libgo/go/go/printer/testdata/declarations.golden @@ -500,7 +500,7 @@ type _ struct { type _ struct { a, b, - c, d int // this line should be indented + c, d int // this line should be indented u, v, w, x float // this line should be indented p, q, r, s float // this line should be indented @@ -562,10 +562,21 @@ var a2, b2, var ( a3, b3, - c3, d3 int // this line should be indented + c3, d3 int // this line should be indented a4, b4, c4 int // this line should be indented ) +// Test case from issue 3304: multi-line declarations must end +// a formatting section and not influence indentation of the +// next line. +var ( + minRefreshTimeSec = flag.Int64("min_refresh_time_sec", 604800, + "minimum time window between two refreshes for a given user.") + x = flag.Int64("refresh_user_rollout_percent", 100, + "temporary flag to ramp up the refresh user rpc") + aVeryLongVariableName = stats.GetVarInt("refresh-user-count") +) + func _() { var privateKey2 = &Block{Type: "RSA PRIVATE KEY", Headers: map[string]string{}, diff --git a/libgo/go/go/printer/testdata/declarations.input b/libgo/go/go/printer/testdata/declarations.input index df8c2b167e1..d74cff25d1f 100644 --- a/libgo/go/go/printer/testdata/declarations.input +++ b/libgo/go/go/printer/testdata/declarations.input @@ -577,6 +577,16 @@ c3, d3 int // this line should be indented a4, b4, c4 int // this line should be indented ) +// Test case from issue 3304: multi-line declarations must end +// a formatting section and not influence indentation of the +// next line. +var ( + minRefreshTimeSec = flag.Int64("min_refresh_time_sec", 604800, + "minimum time window between two refreshes for a given user.") + x = flag.Int64("refresh_user_rollout_percent", 100, + "temporary flag to ramp up the refresh user rpc") + aVeryLongVariableName = stats.GetVarInt("refresh-user-count") +) func _() { var privateKey2 = &Block{Type: "RSA PRIVATE KEY", diff --git a/libgo/go/html/template/clone_test.go b/libgo/go/html/template/clone_test.go index c612775d4f0..2663cddc24b 100644 --- a/libgo/go/html/template/clone_test.go +++ b/libgo/go/html/template/clone_test.go @@ -113,3 +113,36 @@ func TestClone(t *testing.T) { t.Errorf("t3: got %q want %q", got, want) } } + +func TestTemplates(t *testing.T) { + names := []string{"t0", "a", "lhs", "rhs"} + // Some template definitions borrowed from TestClone. + const tmpl = ` + {{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}} + {{define "lhs"}} <a href=" {{end}} + {{define "rhs"}} "></a> {{end}}` + t0 := Must(New("t0").Parse(tmpl)) + templates := t0.Templates() + if len(templates) != len(names) { + t.Errorf("expected %d templates; got %d", len(names), len(templates)) + } + for _, name := range names { + found := false + for _, tmpl := range templates { + if name == tmpl.text.Name() { + found = true + break + } + } + if !found { + t.Error("could not find template", name) + } + } +} + +// This used to crash; http://golang.org/issue/3281 +func TestCloneCrash(t *testing.T) { + t1 := New("all") + Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`)) + t1.Clone() +} diff --git a/libgo/go/html/template/content.go b/libgo/go/html/template/content.go index 539664f9729..c1bd2e4949b 100644 --- a/libgo/go/html/template/content.go +++ b/libgo/go/html/template/content.go @@ -26,10 +26,10 @@ type ( HTML string // HTMLAttr encapsulates an HTML attribute from a trusted source, - // for example: ` dir="ltr"`. + // for example, ` dir="ltr"`. HTMLAttr string - // JS encapsulates a known safe EcmaScript5 Expression, or example, + // JS encapsulates a known safe EcmaScript5 Expression, for example, // `(x + y * z())`. // Template authors are responsible for ensuring that typed expressions // do not break the intended precedence and that there is no diff --git a/libgo/go/html/template/escape.go b/libgo/go/html/template/escape.go index a058e20d7b3..5f0e28e8c1c 100644 --- a/libgo/go/html/template/escape.go +++ b/libgo/go/html/template/escape.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" "html" + "io" "text/template" "text/template/parse" ) @@ -751,3 +752,44 @@ func (e *escaper) template(name string) *template.Template { } return t } + +// Forwarding functions so that clients need only import this package +// to reach the general escaping functions of text/template. + +// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b. +func HTMLEscape(w io.Writer, b []byte) { + template.HTMLEscape(w, b) +} + +// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s. +func HTMLEscapeString(s string) string { + return template.HTMLEscapeString(s) +} + +// HTMLEscaper returns the escaped HTML equivalent of the textual +// representation of its arguments. +func HTMLEscaper(args ...interface{}) string { + return template.HTMLEscaper(args...) +} + +// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b. +func JSEscape(w io.Writer, b []byte) { + template.JSEscape(w, b) +} + +// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s. +func JSEscapeString(s string) string { + return template.JSEscapeString(s) +} + +// JSEscaper returns the escaped JavaScript equivalent of the textual +// representation of its arguments. +func JSEscaper(args ...interface{}) string { + return template.JSEscaper(args...) +} + +// URLQueryEscaper returns the escaped value of the textual representation of +// its arguments in a form suitable for embedding in a URL query. +func URLQueryEscaper(args ...interface{}) string { + return template.URLQueryEscaper(args...) +} diff --git a/libgo/go/html/template/escape_test.go b/libgo/go/html/template/escape_test.go index 2bbb1b1bc94..ce12c1795c2 100644 --- a/libgo/go/html/template/escape_test.go +++ b/libgo/go/html/template/escape_test.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/json" "fmt" + "os" "strings" "testing" "text/template" @@ -1637,6 +1638,14 @@ func TestIndirectPrint(t *testing.T) { } } +// This is a test for issue 3272. +func TestEmptyTemplate(t *testing.T) { + page := Must(New("page").ParseFiles(os.DevNull)) + if err := page.ExecuteTemplate(os.Stdout, "page", "nothing"); err == nil { + t.Fatal("expected error") + } +} + func BenchmarkEscapedExecute(b *testing.B) { tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`)) var buf bytes.Buffer diff --git a/libgo/go/html/template/template.go b/libgo/go/html/template/template.go index b0bae7a54fb..edac7335cfd 100644 --- a/libgo/go/html/template/template.go +++ b/libgo/go/html/template/template.go @@ -31,6 +31,20 @@ type nameSpace struct { set map[string]*Template } +// Templates returns a slice of the templates associated with t, including t +// itself. +func (t *Template) Templates() []*Template { + ns := t.nameSpace + ns.mu.Lock() + defer ns.mu.Unlock() + // Return a slice so we don't expose the map. + m := make([]*Template, 0, len(ns.set)) + for _, v := range ns.set { + m = append(m, v) + } + return m +} + // Execute applies a parsed template to the specified data object, // writing the output to wr. func (t *Template) Execute(wr io.Writer, data interface{}) (err error) { @@ -64,7 +78,13 @@ func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err err t.nameSpace.mu.Lock() defer t.nameSpace.mu.Unlock() tmpl = t.set[name] - if (tmpl == nil) != (t.text.Lookup(name) == nil) { + if tmpl == nil { + return nil, fmt.Errorf("html/template: %q is undefined", name) + } + if tmpl.text.Tree == nil || tmpl.text.Root == nil { + return nil, fmt.Errorf("html/template: %q is an incomplete template", name) + } + if t.text.Lookup(name) == nil { panic("html/template internal error: template escaping out of sync") } if tmpl != nil && !tmpl.escaped { @@ -160,9 +180,11 @@ func (t *Template) Clone() (*Template, error) { if src == nil || src.escaped { return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name()) } - x.Tree = &parse.Tree{ - Name: x.Tree.Name, - Root: x.Tree.Root.CopyList(), + if x.Tree != nil { + x.Tree = &parse.Tree{ + Name: x.Tree.Name, + Root: x.Tree.Root.CopyList(), + } } ret.set[name] = &Template{ false, @@ -274,7 +296,7 @@ func (t *Template) ParseFiles(filenames ...string) (*Template, error) { func parseFiles(t *Template, filenames ...string) (*Template, error) { if len(filenames) == 0 { // Not really a problem, but be consistent. - return nil, fmt.Errorf("template: no files named in call to ParseFiles") + return nil, fmt.Errorf("html/template: no files named in call to ParseFiles") } for _, filename := range filenames { b, err := ioutil.ReadFile(filename) @@ -331,7 +353,7 @@ func parseGlob(t *Template, pattern string) (*Template, error) { return nil, err } if len(filenames) == 0 { - return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern) + return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern) } return parseFiles(t, filenames...) } diff --git a/libgo/go/image/draw/draw.go b/libgo/go/image/draw/draw.go index 3b6679f7c7e..bef325c0c9d 100644 --- a/libgo/go/image/draw/draw.go +++ b/libgo/go/image/draw/draw.go @@ -5,7 +5,7 @@ // Package draw provides image composition functions. // // See "The Go image/draw package" for an introduction to this package: -// http://blog.golang.org/2011/09/go-imagedraw-package.html +// http://golang.org/doc/articles/image_draw.html package draw import ( diff --git a/libgo/go/index/suffixarray/qsufsort.go b/libgo/go/index/suffixarray/qsufsort.go index c69be43c2ac..9c36a98f82d 100644 --- a/libgo/go/index/suffixarray/qsufsort.go +++ b/libgo/go/index/suffixarray/qsufsort.go @@ -11,7 +11,7 @@ // Consecutive groups of suffixes in sa are labeled as sorted groups or // unsorted groups. For a given pass of the sorter, all suffixes are ordered // up to their first h characters, and sa is h-ordered. Suffixes in their -// final positions and unambiguouly sorted in h-order are in a sorted group. +// final positions and unambiguously sorted in h-order are in a sorted group. // Consecutive groups of suffixes with identical first h characters are an // unsorted group. In each pass of the algorithm, unsorted groups are sorted // according to the group number of their following suffix. @@ -78,7 +78,7 @@ func sortedByFirstByte(data []byte) []int { for _, b := range data { count[b]++ } - // make count[b] equal index of first occurence of b in sorted array + // make count[b] equal index of first occurrence of b in sorted array sum := 0 for b := range count { count[b], sum = sum, count[b]+sum diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go index 180afc2c221..f072b8c754a 100644 --- a/libgo/go/io/ioutil/ioutil.go +++ b/libgo/go/io/ioutil/ioutil.go @@ -53,10 +53,13 @@ func ReadFile(filename string) ([]byte, error) { defer f.Close() // It's a good but not certain bet that FileInfo will tell us exactly how much to // read, so let's try it but be prepared for the answer to be wrong. - fi, err := f.Stat() var n int64 - if size := fi.Size(); err == nil && size < 2e9 { // Don't preallocate a huge buffer, just in case. - n = size + + if fi, err := f.Stat(); err == nil { + // Don't preallocate a huge buffer, just in case. + if size := fi.Size(); size < 1e9 { + n = size + } } // As initial capacity for readAll, use n + a little extra in case Size is zero, // and to avoid another allocation after Read has filled the buffer. The readAll diff --git a/libgo/go/log/syslog/syslog_windows.go b/libgo/go/log/syslog/syslog_windows.go new file mode 100644 index 00000000000..8d99e2e594d --- /dev/null +++ b/libgo/go/log/syslog/syslog_windows.go @@ -0,0 +1,8 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package syslog provides a simple interface to the system log service. +package syslog + +// BUG(brainman): This package is not implemented on Windows yet. diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go index da1ac944c5c..0bc6572b962 100644 --- a/libgo/go/math/big/nat.go +++ b/libgo/go/math/big/nat.go @@ -826,7 +826,7 @@ func (x nat) string(charset string) string { // iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the // range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and // ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for -// specfic hardware. +// specific hardware. // func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) { // split larger blocks recursively diff --git a/libgo/go/math/erf.go b/libgo/go/math/erf.go index 87c70c2512f..c6f32bdbe28 100644 --- a/libgo/go/math/erf.go +++ b/libgo/go/math/erf.go @@ -248,7 +248,7 @@ func Erf(x float64) float64 { R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6))))) S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7)))))) } - z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precison x + z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S) if sign { return r/x - 1 @@ -321,7 +321,7 @@ func Erfc(x float64) float64 { R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6))))) S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7)))))) } - z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precison x + z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S) if sign { return 2 - r/x diff --git a/libgo/go/net/http/triv.go b/libgo/go/net/http/triv.go index 269af0ca3d5..232d6508906 100644 --- a/libgo/go/net/http/triv.go +++ b/libgo/go/net/http/triv.go @@ -15,7 +15,9 @@ import ( "log" "net/http" "os" + "os/exec" "strconv" + "sync" ) // hello world, the web server @@ -28,14 +30,21 @@ func HelloServer(w http.ResponseWriter, req *http.Request) { // Simple counter server. POSTing to it will set the value. type Counter struct { - n int + mu sync.Mutex // protects n + n int } // This makes Counter satisfy the expvar.Var interface, so we can export // it directly. -func (ctr *Counter) String() string { return fmt.Sprintf("%d", ctr.n) } +func (ctr *Counter) String() string { + ctr.mu.Lock() + defer ctr.mu.Unlock() + return fmt.Sprintf("%d", ctr.n) +} func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) { + ctr.mu.Lock() + defer ctr.mu.Unlock() switch req.Method { case "GET": ctr.n++ @@ -95,54 +104,36 @@ func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) { // exec a program, redirecting output func DateServer(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Content-Type", "text/plain; charset=utf-8") - r, w, err := os.Pipe() - if err != nil { - fmt.Fprintf(rw, "pipe: %s\n", err) - return - } - p, err := os.StartProcess("/bin/date", []string{"date"}, &os.ProcAttr{Files: []*os.File{nil, w, w}}) - defer r.Close() - w.Close() - if err != nil { - fmt.Fprintf(rw, "fork/exec: %s\n", err) - return - } - io.Copy(rw, r) - wait, err := p.Wait(0) + date, err := exec.Command("/bin/date").Output() if err != nil { - fmt.Fprintf(rw, "wait: %s\n", err) - return - } - if !wait.Exited() || wait.ExitStatus() != 0 { - fmt.Fprintf(rw, "date: %v\n", wait) + http.Error(rw, err.Error(), 500) return } + rw.Write(date) } func Logger(w http.ResponseWriter, req *http.Request) { - log.Print(req.URL.Raw) - w.WriteHeader(404) - w.Write([]byte("oops")) + log.Print(req.URL) + http.Error(w, "oops", 404) } -var webroot = flag.String("root", "/home/rsc", "web root directory") +var webroot = flag.String("root", os.Getenv("HOME"), "web root directory") func main() { flag.Parse() // The counter is published as a variable directly. ctr := new(Counter) - http.Handle("/counter", ctr) expvar.Publish("counter", ctr) - + http.Handle("/counter", ctr) http.Handle("/", http.HandlerFunc(Logger)) http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot)))) - http.Handle("/flags", http.HandlerFunc(FlagServer)) - http.Handle("/args", http.HandlerFunc(ArgServer)) - http.Handle("/go/hello", http.HandlerFunc(HelloServer)) http.Handle("/chan", ChanCreate()) - http.Handle("/date", http.HandlerFunc(DateServer)) + http.HandleFunc("/flags", FlagServer) + http.HandleFunc("/args", ArgServer) + http.HandleFunc("/go/hello", HelloServer) + http.HandleFunc("/date", DateServer) err := http.ListenAndServe(":12345", nil) if err != nil { log.Panicln("ListenAndServe:", err) diff --git a/libgo/go/net/interface_linux.go b/libgo/go/net/interface_linux.go index 8c9c3040874..825b20227ae 100644 --- a/libgo/go/net/interface_linux.go +++ b/libgo/go/net/interface_linux.go @@ -13,7 +13,7 @@ import ( ) // If the ifindex is zero, interfaceTable returns mappings of all -// network interfaces. Otheriwse it returns a mapping of a specific +// network interfaces. Otherwise it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC) diff --git a/libgo/go/net/interface_stub.go b/libgo/go/net/interface_stub.go index 4876b3af353..d4d7ce9c7f8 100644 --- a/libgo/go/net/interface_stub.go +++ b/libgo/go/net/interface_stub.go @@ -9,7 +9,7 @@ package net // If the ifindex is zero, interfaceTable returns mappings of all -// network interfaces. Otheriwse it returns a mapping of a specific +// network interfaces. Otherwise it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { return nil, nil diff --git a/libgo/go/net/interface_windows.go b/libgo/go/net/interface_windows.go index d0c97532699..4368b330621 100644 --- a/libgo/go/net/interface_windows.go +++ b/libgo/go/net/interface_windows.go @@ -56,7 +56,7 @@ func getInterfaceList() ([]syscall.InterfaceInfo, error) { } // If the ifindex is zero, interfaceTable returns mappings of all -// network interfaces. Otheriwse it returns a mapping of a specific +// network interfaces. Otherwise it returns a mapping of a specific // interface. func interfaceTable(ifindex int) ([]Interface, error) { ai, err := getAdapterList() diff --git a/libgo/go/net/unicast_test.go b/libgo/go/net/unicast_test.go index a23bc5adaf2..e5dd013db67 100644 --- a/libgo/go/net/unicast_test.go +++ b/libgo/go/net/unicast_test.go @@ -5,7 +5,6 @@ package net import ( - "io" "runtime" "syscall" "testing" @@ -67,7 +66,7 @@ func TestTCPListener(t *testing.T) { case syscall.AF_INET6: testIPv6UnicastSocketOptions(t, fd) } - l1.(io.Closer).Close() + l1.Close() } } @@ -112,7 +111,7 @@ func TestUDPListener(t *testing.T) { case syscall.AF_INET6: testIPv6UnicastSocketOptions(t, fd) } - l1.(io.Closer).Close() + l1.Close() } } @@ -134,7 +133,7 @@ func TestSimpleTCPListener(t *testing.T) { checkFirstListener(t, tt.net, tt.laddr+":"+port, l1) l2, err := Listen(tt.net, tt.laddr+":"+port) checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2) - l1.(io.Closer).Close() + l1.Close() } } @@ -169,7 +168,7 @@ func TestSimpleUDPListener(t *testing.T) { checkFirstListener(t, tt.net, tt.laddr+":"+port, l1) l2, err := ListenPacket(tt.net, tt.laddr+":"+port) checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2) - l1.(io.Closer).Close() + l1.Close() } } @@ -530,8 +529,9 @@ func TestProhibitionaryDialArgs(t *testing.T) { defer l.Close() for _, tt := range prohibitionaryDialArgTests { - _, err := Dial(tt.net, tt.addr+":"+port) + c, err := Dial(tt.net, tt.addr+":"+port) if err == nil { + c.Close() t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr) } } diff --git a/libgo/go/os/error.go b/libgo/go/os/error.go index e0b83b5c22c..b88e49400de 100644 --- a/libgo/go/os/error.go +++ b/libgo/go/os/error.go @@ -42,3 +42,21 @@ func NewSyscallError(syscall string, err error) error { } return &SyscallError{syscall, err} } + +// IsExist returns whether the error is known to report that a file or directory +// already exists. It is satisfied by ErrExist as well as some syscall errors. +func IsExist(err error) bool { + return isExist(err) +} + +// IsNotExist returns whether the error is known to report that a file or directory +// does not exist. It is satisfied by ErrNotExist as well as some syscall errors. +func IsNotExist(err error) bool { + return isNotExist(err) +} + +// IsPermission returns whether the error is known to report that permission is denied. +// It is satisfied by ErrPermission as well as some syscall errors. +func IsPermission(err error) bool { + return isPermission(err) +} diff --git a/libgo/go/os/error_plan9.go b/libgo/go/os/error_plan9.go index 159d685e7cd..3c9dfb0b158 100644 --- a/libgo/go/os/error_plan9.go +++ b/libgo/go/os/error_plan9.go @@ -4,24 +4,21 @@ package os -// IsExist returns whether the error is known to report that a file already exists. -func IsExist(err error) bool { +func isExist(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } return contains(err.Error(), " exists") } -// IsNotExist returns whether the error is known to report that a file does not exist. -func IsNotExist(err error) bool { +func isNotExist(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } return contains(err.Error(), "does not exist") } -// IsPermission returns whether the error is known to report that permission is denied. -func IsPermission(err error) bool { +func isPermission(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } diff --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go index d08ad5db167..1685c1f2132 100644 --- a/libgo/go/os/error_posix.go +++ b/libgo/go/os/error_posix.go @@ -8,27 +8,21 @@ package os import "syscall" -// IsExist returns whether the error is known to report that a file already exists. -// It is satisfied by ErrExist as well as some syscall errors. -func IsExist(err error) bool { +func isExist(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } return err == syscall.EEXIST || err == ErrExist } -// IsNotExist returns whether the error is known to report that a file does not exist. -// It is satisfied by ErrNotExist as well as some syscall errors. -func IsNotExist(err error) bool { +func isNotExist(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } return err == syscall.ENOENT || err == ErrNotExist } -// IsPermission returns whether the error is known to report that permission is denied. -// It is satisfied by ErrPermission as well as some syscall errors. -func IsPermission(err error) bool { +func isPermission(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } diff --git a/libgo/go/os/error_test.go b/libgo/go/os/error_test.go index 8218f861aff..42f846fa3c5 100644 --- a/libgo/go/os/error_test.go +++ b/libgo/go/os/error_test.go @@ -5,8 +5,10 @@ package os_test import ( + "fmt" "io/ioutil" "os" + "path/filepath" "testing" ) @@ -24,8 +26,56 @@ func TestErrIsExist(t *testing.T) { t.Fatal("Open should have failed") return } - if !os.IsExist(err) { - t.Fatalf("os.IsExist does not work as expected for %#v", err) + if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" { + t.Fatal(s) return } } + +func testErrNotExist(name string) string { + f, err := os.Open(name) + if err == nil { + f.Close() + return "Open should have failed" + } + if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" { + return s + } + + err = os.Chdir(name) + if err == nil { + return "Chdir should have failed" + } + if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" { + return s + } + return "" +} + +func TestErrIsNotExist(t *testing.T) { + tmpDir, err := ioutil.TempDir("", "_Go_ErrIsNotExist") + if err != nil { + t.Fatalf("create ErrIsNotExist tempdir: %s", err) + return + } + defer os.RemoveAll(tmpDir) + + name := filepath.Join(tmpDir, "NotExists") + if s := testErrNotExist(name); s != "" { + t.Fatal(s) + return + } + + name = filepath.Join(name, "NotExists2") + if s := testErrNotExist(name); s != "" { + t.Fatal(s) + return + } +} + +func checkErrorPredicate(predName string, pred func(error) bool, err error) string { + if !pred(err) { + return fmt.Sprintf("%s does not work as expected for %#v", predName, err) + } + return "" +} diff --git a/libgo/go/os/error_windows.go b/libgo/go/os/error_windows.go index 84bf5eae8ae..5d692b07362 100644 --- a/libgo/go/os/error_windows.go +++ b/libgo/go/os/error_windows.go @@ -6,30 +6,25 @@ package os import "syscall" -// IsExist returns whether the error is known to report that a file already exists. -// It is satisfied by ErrExist as well as some syscall errors. -func IsExist(err error) bool { +func isExist(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } - return err == syscall.EEXIST || err == syscall.ERROR_ALREADY_EXISTS || + return err == syscall.ERROR_ALREADY_EXISTS || err == syscall.ERROR_FILE_EXISTS || err == ErrExist } -// IsNotExist returns whether the error is known to report that a file does not exist. -// It is satisfied by ErrNotExist as well as some syscall errors. -func IsNotExist(err error) bool { +func isNotExist(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } - return err == syscall.ENOENT || err == ErrNotExist + return err == syscall.ERROR_FILE_NOT_FOUND || + err == syscall.ERROR_PATH_NOT_FOUND || err == ErrNotExist } -// IsPermission returns whether the error is known to report that permission is denied. -// It is satisfied by ErrPermission as well as some syscall errors. -func IsPermission(err error) bool { +func isPermission(err error) bool { if pe, ok := err.(*PathError); ok { err = pe.Err } - return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission + return err == ErrPermission } diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go index a69680cb8c9..b8fb2e22c98 100644 --- a/libgo/go/os/file_unix.go +++ b/libgo/go/os/file_unix.go @@ -179,7 +179,21 @@ func (f *File) pread(b []byte, off int64) (n int, err error) { // write writes len(b) bytes to the File. // It returns the number of bytes written and an error, if any. func (f *File) write(b []byte) (n int, err error) { - return syscall.Write(f.fd, b) + for { + m, err := syscall.Write(f.fd, b) + n += m + + // If the syscall wrote some data but not all (short write) + // or it returned EINTR, then assume it stopped early for + // reasons that are uninteresting to the caller, and try again. + if 0 < m && m < len(b) || err == syscall.EINTR { + b = b[m:] + continue + } + + return n, err + } + panic("not reached") } // pwrite writes len(b) bytes to the File starting at byte offset off. diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go index aa01669a5da..8d3f677fd4e 100644 --- a/libgo/go/os/os_test.go +++ b/libgo/go/os/os_test.go @@ -1045,3 +1045,22 @@ func TestSameFile(t *testing.T) { t.Errorf("files should be different") } } + +func TestDevNullFile(t *testing.T) { + f, err := Open(DevNull) + if err != nil { + t.Fatalf("Open(%s): %v", DevNull, err) + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + t.Fatalf("Stat(%s): %v", DevNull, err) + } + name := filepath.Base(DevNull) + if fi.Name() != name { + t.Fatalf("wrong file name have %v want %v", fi.Name(), name) + } + if fi.Size() != 0 { + t.Fatalf("wrong file size have %d want 0", fi.Size()) + } +} diff --git a/libgo/go/path/filepath/match.go b/libgo/go/path/filepath/match.go index 38d264fb97a..db8b0260ca8 100644 --- a/libgo/go/path/filepath/match.go +++ b/libgo/go/path/filepath/match.go @@ -7,6 +7,7 @@ package filepath import ( "errors" "os" + "runtime" "sort" "strings" "unicode/utf8" @@ -37,6 +38,9 @@ var ErrBadPattern = errors.New("syntax error in pattern") // The only possible returned error is ErrBadPattern, when pattern // is malformed. // +// On Windows, escaping is disabled. Instead, '\\' is treated as +// path separator. +// func Match(pattern, name string) (matched bool, err error) { Pattern: for len(pattern) > 0 { @@ -95,9 +99,11 @@ Scan: for i = 0; i < len(pattern); i++ { switch pattern[i] { case '\\': - // error check handled in matchChunk: bad pattern. - if i+1 < len(pattern) { - i++ + if runtime.GOOS != "windows" { + // error check handled in matchChunk: bad pattern. + if i+1 < len(pattern) { + i++ + } } case '[': inrange = true @@ -167,10 +173,12 @@ func matchChunk(chunk, s string) (rest string, ok bool, err error) { chunk = chunk[1:] case '\\': - chunk = chunk[1:] - if len(chunk) == 0 { - err = ErrBadPattern - return + if runtime.GOOS != "windows" { + chunk = chunk[1:] + if len(chunk) == 0 { + err = ErrBadPattern + return + } } fallthrough @@ -191,7 +199,7 @@ func getEsc(chunk string) (r rune, nchunk string, err error) { err = ErrBadPattern return } - if chunk[0] == '\\' { + if chunk[0] == '\\' && runtime.GOOS != "windows" { chunk = chunk[1:] if len(chunk) == 0 { err = ErrBadPattern diff --git a/libgo/go/path/filepath/match_test.go b/libgo/go/path/filepath/match_test.go index dc0fff2f5e0..e3d365881cc 100644 --- a/libgo/go/path/filepath/match_test.go +++ b/libgo/go/path/filepath/match_test.go @@ -7,6 +7,7 @@ package filepath_test import ( . "path/filepath" "runtime" + "strings" "testing" ) @@ -76,21 +77,26 @@ func errp(e error) string { } func TestMatch(t *testing.T) { - if runtime.GOOS == "windows" { - // XXX: Don't pass for windows. - return - } for _, tt := range matchTests { - ok, err := Match(tt.pattern, tt.s) + pattern := tt.pattern + s := tt.s + if runtime.GOOS == "windows" { + if strings.Index(pattern, "\\") >= 0 { + // no escape allowed on windows. + continue + } + pattern = Clean(pattern) + s = Clean(s) + } + ok, err := Match(pattern, s) if ok != tt.match || err != tt.err { - t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", tt.pattern, tt.s, ok, errp(err), tt.match, errp(tt.err)) + t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err)) } } } // contains returns true if vector contains the string s. func contains(vector []string, s string) bool { - s = ToSlash(s) for _, elem := range vector { if elem == s { return true @@ -110,18 +116,20 @@ var globTests = []struct { } func TestGlob(t *testing.T) { - if runtime.GOOS == "windows" { - // XXX: Don't pass for windows. - return - } for _, tt := range globTests { - matches, err := Glob(tt.pattern) + pattern := tt.pattern + result := tt.result + if runtime.GOOS == "windows" { + pattern = Clean(pattern) + result = Clean(result) + } + matches, err := Glob(pattern) if err != nil { - t.Errorf("Glob error for %q: %s", tt.pattern, err) + t.Errorf("Glob error for %q: %s", pattern, err) continue } - if !contains(matches, tt.result) { - t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result) + if !contains(matches, result) { + t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result) } } for _, pattern := range []string{"no_match", "../*/no_match"} { diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go index 92e84f43b06..7fe18a9d735 100644 --- a/libgo/go/reflect/type.go +++ b/libgo/go/reflect/type.go @@ -66,9 +66,10 @@ type Type interface { // It returns an empty string for unnamed types. Name() string - // PkgPath returns the type's package path. - // The package path is a full package import path like "encoding/base64". - // PkgPath returns an empty string for unnamed or predeclared types. + // PkgPath returns a named type's package path, that is, the import path + // that uniquely identifies the package, such as "encoding/base64". + // If the type was predeclared (string, error) or unnamed (*T, struct{}, []int), + // the package path will be the empty string. PkgPath() string // Size returns the number of bytes needed to store @@ -351,11 +352,18 @@ type structType struct { // Method represents a single method. type Method struct { - PkgPath string // empty for uppercase Name + // Name is the method name. + // PkgPath is the package path that qualifies a lower case (unexported) + // method name. It is empty for upper case (exported) method names. + // The combination of PkgPath and Name uniquely identifies a method + // in a method set. + // See http://golang.org/ref/spec#Uniqueness_of_identifiers Name string - Type Type - Func Value - Index int + PkgPath string + + Type Type // method type + Func Value // func with receiver as first argument + Index int // index for Type.Method } // High bit says whether type has @@ -695,14 +703,20 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) { return } +// A StructField describes a single field in a struct. type StructField struct { - PkgPath string // empty for uppercase Name - Name string - Type Type - Tag StructTag - Offset uintptr - Index []int - Anonymous bool + // Name is the field name. + // PkgPath is the package path that qualifies a lower case (unexported) + // field name. It is empty for upper case (exported) field names. + // See http://golang.org/ref/spec#Uniqueness_of_identifiers + Name string + PkgPath string + + Type Type // field type + Tag StructTag // field tag string + Offset uintptr // offset within struct, in bytes + Index []int // index sequence for Type.FieldByIndex + Anonymous bool // is an anonymous field } // A StructTag is the tag string in a struct field. diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go index f3a0a7cfde5..a12fcb2668f 100644 --- a/libgo/go/reflect/value.go +++ b/libgo/go/reflect/value.go @@ -1624,6 +1624,15 @@ func MakeSlice(typ Type, len, cap int) Value { if typ.Kind() != Slice { panic("reflect.MakeSlice of non-slice type") } + if len < 0 { + panic("reflect.MakeSlice: negative len") + } + if cap < 0 { + panic("reflect.MakeSlice: negative cap") + } + if len > cap { + panic("reflect.MakeSlice: len > cap") + } // Declare slice so that gc can see the base pointer in it. var x []byte diff --git a/libgo/go/sort/sort.go b/libgo/go/sort/sort.go index 31da3c83d0d..62a4d55e798 100644 --- a/libgo/go/sort/sort.go +++ b/libgo/go/sort/sort.go @@ -183,17 +183,21 @@ func quickSort(data Interface, a, b, maxDepth int) { } } +// Sort sorts data. +// It makes one call to data.Len to determine n, and O(n*log(n)) calls to +// data.Less and data.Swap. The sort is not guaranteed to be stable. func Sort(data Interface) { - // Switch to heapsort if depth of 2*ceil(lg(n)) is reached. + // Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached. n := data.Len() maxDepth := 0 - for 1<<uint(maxDepth) < n { + for i := n; i > 0; i >>= 1 { maxDepth++ } maxDepth *= 2 quickSort(data, 0, n, maxDepth) } +// IsSorted reports whether data is sorted. func IsSorted(data Interface) bool { n := data.Len() for i := n - 1; i > 0; i-- { diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go index ad0118e4e68..9a720cf43e3 100644 --- a/libgo/go/text/template/exec.go +++ b/libgo/go/text/template/exec.go @@ -369,6 +369,7 @@ func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields. value := s.varValue(v.Ident[0]) if len(v.Ident) == 1 { + s.notAFunction(args, final) return value } return s.evalFieldChain(dot, value, v.Ident[1:], args, final) diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go index 70ab39cad20..5446027ff7a 100644 --- a/libgo/go/text/template/exec_test.go +++ b/libgo/go/text/template/exec_test.go @@ -466,6 +466,10 @@ var execTests = []execTest{ {"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true}, {"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true}, {"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true}, + // Legal parse but illegal execution: non-function should have no arguments. + {"bug7a", "{{3 2}}", "", tVal, false}, + {"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false}, + {"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false}, } func zeroArgs() string { diff --git a/libgo/go/text/template/multi_test.go b/libgo/go/text/template/multi_test.go index 22dedc4f839..bd98bd047ec 100644 --- a/libgo/go/text/template/multi_test.go +++ b/libgo/go/text/template/multi_test.go @@ -93,7 +93,7 @@ var multiExecTests = []execTest{ {"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true}, {"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true}, {"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true}, - {"variable declared by template", `{{template "nested" $x=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true}, + {"variable declared by template", `{{template "nested" $x:=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true}, // User-defined function: test argument evaluator. {"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true}, diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go index 54e75ee0ca2..7705c0b88ff 100644 --- a/libgo/go/text/template/parse/lex.go +++ b/libgo/go/text/template/parse/lex.go @@ -347,6 +347,9 @@ Loop: default: l.backup() word := l.input[l.start:l.pos] + if !l.atTerminator() { + return l.errorf("unexpected character %+U", r) + } switch { case key[word] > itemKeyword: l.emit(key[word]) @@ -365,6 +368,28 @@ Loop: return lexInsideAction } +// atTerminator reports whether the input is at valid termination character to +// appear after an identifier. Mostly to catch cases like "$x+2" not being +// acceptable without a space, in case we decide one day to implement +// arithmetic. +func (l *lexer) atTerminator() bool { + r := l.peek() + if isSpace(r) { + return true + } + switch r { + case eof, ',', '|', ':': + return true + } + // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will + // succeed but should fail) but only in extremely rare cases caused by willfully + // bad choice of delimiter. + if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r { + return true + } + return false +} + // lexChar scans a character constant. The initial quote is already // scanned. Syntax checking is done by the parse. func lexChar(l *lexer) stateFn { diff --git a/libgo/go/text/template/parse/parse.go b/libgo/go/text/template/parse/parse.go index d67b3888085..c0087b2785b 100644 --- a/libgo/go/text/template/parse/parse.go +++ b/libgo/go/text/template/parse/parse.go @@ -326,7 +326,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) { for { if v := t.peek(); v.typ == itemVariable { t.next() - if next := t.peek(); next.typ == itemColonEquals || next.typ == itemChar { + if next := t.peek(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") { t.next() variable := newVariable(v.val) if len(variable.Ident) != 1 { diff --git a/libgo/go/text/template/parse/parse_test.go b/libgo/go/text/template/parse/parse_test.go index 18c0a8b835e..b2e788238d3 100644 --- a/libgo/go/text/template/parse/parse_test.go +++ b/libgo/go/text/template/parse/parse_test.go @@ -201,6 +201,10 @@ var parseTests = []parseTest{ `{{range .X | .M}}"true"{{else}}"false"{{end}}`}, {"range []int", "{{range .SI}}{{.}}{{end}}", noError, `{{range .SI}}{{.}}{{end}}`}, + {"range 1 var", "{{range $x := .SI}}{{.}}{{end}}", noError, + `{{range $x := .SI}}{{.}}{{end}}`}, + {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError, + `{{range $x, $y := .SI}}{{.}}{{end}}`}, {"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError, `{{range .SI 1 -3.2i true false 'a'}}{{end}}`}, {"template", "{{template `x`}}", noError, @@ -226,6 +230,17 @@ var parseTests = []parseTest{ {"invalid punctuation", "{{printf 3, 4}}", hasError, ""}, {"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""}, {"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""}, + // Equals (and other chars) do not assignments make (yet). + {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"}, + {"bug0b", "{{$x = 1}}{{$x}}", hasError, ""}, + {"bug0c", "{{$x ! 2}}{{$x}}", hasError, ""}, + {"bug0d", "{{$x % 3}}{{$x}}", hasError, ""}, + // Check the parse fails for := rather than comma. + {"bug0e", "{{range $x := $y := 3}}{{end}}", hasError, ""}, + // Another bug: variable read must ignore following punctuation. + {"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""}, // ! is just illegal here. + {"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""}, // $x+2 should not parse as ($x) (+2). + {"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space. } var builtins = map[string]interface{}{ diff --git a/libgo/merge.sh b/libgo/merge.sh index 32652118fe5..9e2ca01cc96 100755 --- a/libgo/merge.sh +++ b/libgo/merge.sh @@ -163,7 +163,7 @@ done done done -runtime="chan.c cpuprof.c goc2c.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc" +runtime="chan.c cpuprof.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc" for f in $runtime; do merge_c $f $f done diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 049f77eada2..dbcfa0fed6d 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -966,6 +966,11 @@ runtime_mstart(void* mp) } #endif + // Install signal handlers; after minit so that minit can + // prepare the thread to be able to handle the signals. + if(m == &runtime_m0) + runtime_initsig(); + schedule(nil); return nil; } diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c index d1ce26db499..a0dbf80b0a0 100644 --- a/libgo/runtime/runtime.c +++ b/libgo/runtime/runtime.c @@ -74,7 +74,7 @@ void runtime_panicstring(const char *s) { Eface err; - + if(runtime_m()->gcing) { runtime_printf("panic: %s\n", s); runtime_throw("panic during gc"); @@ -101,7 +101,7 @@ runtime_goargs(void) { String *s; int32 i; - + // for windows implementation see "os" package if(Windows) return; @@ -119,7 +119,7 @@ runtime_goenvs_unix(void) { String *s; int32 i, n; - + for(n=0; argv[argc+1+n] != 0; n++) ; @@ -195,8 +195,6 @@ void runtime_check(void) { __go_register_gc_roots(&runtime_roots); - - runtime_initsig (); } int64 |