diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-08-03 16:54:30 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-08-03 16:54:30 +0200 |
commit | 28592ee1ea1f5cdffcf85472f9de0285d928cf12 (patch) | |
tree | 32944e18b23f7fe4a0818a694aa2a6dfb1835463 /src/pkg/go | |
parent | e836bee4716dc0d4d913537ad3ad1925a7ac32d0 (diff) | |
download | golang-28592ee1ea1f5cdffcf85472f9de0285d928cf12.tar.gz |
Imported Upstream version 59upstream/59
Diffstat (limited to 'src/pkg/go')
24 files changed, 360 insertions, 146 deletions
diff --git a/src/pkg/go/ast/print_test.go b/src/pkg/go/ast/print_test.go index 0820dcfce..30b396fcf 100644 --- a/src/pkg/go/ast/print_test.go +++ b/src/pkg/go/ast/print_test.go @@ -53,7 +53,7 @@ var tests = []struct { // Split s into lines, trim whitespace from all lines, and return // the concatenated non-empty lines. func trim(s string) string { - lines := strings.Split(s, "\n", -1) + lines := strings.Split(s, "\n") i := 0 for _, line := range lines { line = strings.TrimSpace(line) diff --git a/src/pkg/go/build/Makefile b/src/pkg/go/build/Makefile index 4411940ae..349e00e80 100644 --- a/src/pkg/go/build/Makefile +++ b/src/pkg/go/build/Makefile @@ -11,7 +11,7 @@ GOFILES=\ path.go\ syslist.go\ -CLEANFILES+=syslist.go +CLEANFILES+=syslist.go pkgtest/_obj cmdtest/_obj cgotest/_obj include ../../../Make.pkg diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go index 3cb8efe47..d83a6666e 100644 --- a/src/pkg/go/build/build.go +++ b/src/pkg/go/build/build.go @@ -11,34 +11,61 @@ import ( "fmt" "os" "path/filepath" + "regexp" "runtime" "strings" ) -func (d *DirInfo) Build(targ string) ([]*Cmd, os.Error) { - b := &build{obj: "_obj/"} +// Build produces a build Script for the given package. +func Build(tree *Tree, pkg string, info *DirInfo) (*Script, os.Error) { + s := &Script{} + b := &build{ + script: s, + path: filepath.Join(tree.SrcDir(), pkg), + } + b.obj = b.abs("_obj") + string(filepath.Separator) - goarch := runtime.GOARCH + b.goarch = runtime.GOARCH if g := os.Getenv("GOARCH"); g != "" { - goarch = g + b.goarch = g } var err os.Error - b.arch, err = ArchChar(goarch) + b.arch, err = ArchChar(b.goarch) if err != nil { return nil, err } - var gofiles = d.GoFiles // .go files to be built with gc - var ofiles []string // *.GOARCH files to be linked or packed + // add import object files to list of Inputs + for _, pkg := range info.Imports { + t, p, err := FindTree(pkg) + if err != nil && err != ErrNotFound { + // FindTree should always be able to suggest an import + // path and tree. The path must be malformed + // (for example, an absolute or relative path). + return nil, os.NewError("build: invalid import: " + pkg) + } + s.addInput(filepath.Join(t.PkgDir(), p+".a")) + } + + // .go files to be built with gc + gofiles := b.abss(info.GoFiles...) + s.addInput(gofiles...) + + var ofiles []string // object files to be linked or packed // make build directory b.mkdir(b.obj) + s.addIntermediate(b.obj) // cgo - if len(d.CgoFiles) > 0 { - outGo, outObj := b.cgo(d.CgoFiles) + if len(info.CgoFiles) > 0 { + cgoFiles := b.abss(info.CgoFiles...) + s.addInput(cgoFiles...) + outGo, outObj := b.cgo(cgoFiles) gofiles = append(gofiles, outGo...) ofiles = append(ofiles, outObj...) + s.addIntermediate(outGo...) + s.addIntermediate(outObj...) } // compile @@ -46,31 +73,136 @@ func (d *DirInfo) Build(targ string) ([]*Cmd, os.Error) { ofile := b.obj + "_go_." + b.arch b.gc(ofile, gofiles...) ofiles = append(ofiles, ofile) + s.addIntermediate(ofile) } // assemble - for _, sfile := range d.SFiles { + for _, sfile := range info.SFiles { ofile := b.obj + sfile[:len(sfile)-1] + b.arch + sfile = b.abs(sfile) + s.addInput(sfile) b.asm(ofile, sfile) ofiles = append(ofiles, ofile) + s.addIntermediate(ofile) } if len(ofiles) == 0 { return nil, os.NewError("make: no object files to build") } - if d.IsCommand() { + // choose target file + var targ string + if info.IsCommand() { + // use the last part of the import path as binary name + _, bin := filepath.Split(pkg) + if runtime.GOOS == "windows" { + bin += ".exe" + } + targ = filepath.Join(tree.BinDir(), bin) + } else { + targ = filepath.Join(tree.PkgDir(), pkg+".a") + } + + // make target directory + targDir, _ := filepath.Split(targ) + b.mkdir(targDir) + + // link binary or pack object + if info.IsCommand() { b.ld(targ, ofiles...) } else { b.gopack(targ, ofiles...) } + s.Output = append(s.Output, targ) + + return b.script, nil +} + +// A Script describes the build process for a Go package. +// The Input, Intermediate, and Output fields are lists of absolute paths. +type Script struct { + Cmd []*Cmd + Input []string + Intermediate []string + Output []string +} + +func (s *Script) addInput(file ...string) { + s.Input = append(s.Input, file...) +} + +func (s *Script) addIntermediate(file ...string) { + s.Intermediate = append(s.Intermediate, file...) +} + +// Run runs the Script's Cmds in order. +func (s *Script) Run() os.Error { + for _, c := range s.Cmd { + if err := c.Run(); err != nil { + return err + } + } + return nil +} + +// Stale returns true if the build's inputs are newer than its outputs. +func (s *Script) Stale() bool { + var latest int64 + // get latest mtime of outputs + for _, file := range s.Output { + fi, err := os.Stat(file) + if err != nil { + // any error reading output files means stale + return true + } + if m := fi.Mtime_ns; m > latest { + latest = m + } + } + for _, file := range s.Input { + fi, err := os.Stat(file) + if err != nil || fi.Mtime_ns > latest { + // any error reading input files means stale + // (attempt to rebuild to figure out why) + return true + } + } + return false +} + +// Clean removes the Script's Intermediate files. +// It tries to remove every file and returns the first error it encounters. +func (s *Script) Clean() (err os.Error) { + // Reverse order so that directories get removed after the files they contain. + for i := len(s.Intermediate) - 1; i >= 0; i-- { + if e := os.Remove(s.Intermediate[i]); err == nil { + err = e + } + } + return +} - return b.cmds, nil +// Clean removes the Script's Intermediate and Output files. +// It tries to remove every file and returns the first error it encounters. +func (s *Script) Nuke() (err os.Error) { + // Reverse order so that directories get removed after the files they contain. + for i := len(s.Output) - 1; i >= 0; i-- { + if e := os.Remove(s.Output[i]); err == nil { + err = e + } + } + if e := s.Clean(); err == nil { + err = e + } + return } +// A Cmd describes an individual build command. type Cmd struct { Args []string // command-line Stdout string // write standard output to this file, "" is passthrough + Dir string // working directory + Env []string // environment Input []string // file paths (dependencies) Output []string // file paths } @@ -79,14 +211,16 @@ func (c *Cmd) String() string { return strings.Join(c.Args, " ") } -func (c *Cmd) Run(dir string) os.Error { +// Run executes the Cmd. +func (c *Cmd) Run() os.Error { out := new(bytes.Buffer) cmd := exec.Command(c.Args[0], c.Args[1:]...) - cmd.Dir = dir + cmd.Dir = c.Dir + cmd.Env = c.Env cmd.Stdout = out cmd.Stderr = out if c.Stdout != "" { - f, err := os.Create(filepath.Join(dir, c.Stdout)) + f, err := os.Create(c.Stdout) if err != nil { return err } @@ -99,15 +233,6 @@ func (c *Cmd) Run(dir string) os.Error { return nil } -func (c *Cmd) Clean(dir string) (err os.Error) { - for _, fn := range c.Output { - if e := os.RemoveAll(fn); err == nil { - err = e - } - } - return -} - // ArchChar returns the architecture character for the given goarch. // For example, ArchChar("amd64") returns "6". func ArchChar(goarch string) (string, os.Error) { @@ -123,13 +248,30 @@ func ArchChar(goarch string) (string, os.Error) { } type build struct { - cmds []*Cmd - obj string - arch string + script *Script + path string + obj string + goarch string + arch string +} + +func (b *build) abs(file string) string { + if filepath.IsAbs(file) { + return file + } + return filepath.Join(b.path, file) +} + +func (b *build) abss(file ...string) []string { + s := make([]string, len(file)) + for i, f := range file { + s[i] = b.abs(f) + } + return s } func (b *build) add(c Cmd) { - b.cmds = append(b.cmds, &c) + b.script.Cmd = append(b.script.Cmd, &c) } func (b *build) mkdir(name string) { @@ -192,7 +334,7 @@ func (b *build) cc(ofile string, cfiles ...string) { func (b *build) gccCompile(ofile, cfile string) { b.add(Cmd{ - Args: gccArgs(b.arch, "-o", ofile, "-c", cfile), + Args: b.gccArgs("-o", ofile, "-c", cfile), Input: []string{cfile}, Output: []string{ofile}, }) @@ -200,21 +342,26 @@ func (b *build) gccCompile(ofile, cfile string) { func (b *build) gccLink(ofile string, ofiles ...string) { b.add(Cmd{ - Args: append(gccArgs(b.arch, "-o", ofile), ofiles...), + Args: append(b.gccArgs("-o", ofile), ofiles...), Input: ofiles, Output: []string{ofile}, }) } -func gccArgs(arch string, args ...string) []string { +func (b *build) gccArgs(args ...string) []string { // TODO(adg): HOST_CC - m := "-m32" - if arch == "6" { - m = "-m64" + a := []string{"gcc", "-I", b.path, "-g", "-fPIC", "-O2"} + switch b.arch { + case "8": + a = append(a, "-m32") + case "6": + a = append(a, "-m64") } - return append([]string{"gcc", m, "-I", ".", "-g", "-fPIC", "-O2"}, args...) + return append(a, args...) } +var cgoRe = regexp.MustCompile(`[/\\:]`) + func (b *build) cgo(cgofiles []string) (outGo, outObj []string) { // cgo // TODO(adg): CGOPKGPATH @@ -222,19 +369,24 @@ func (b *build) cgo(cgofiles []string) (outGo, outObj []string) { gofiles := []string{b.obj + "_cgo_gotypes.go"} cfiles := []string{b.obj + "_cgo_main.c", b.obj + "_cgo_export.c"} for _, fn := range cgofiles { - f := b.obj + fn[:len(fn)-2] + f := b.obj + cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") gofiles = append(gofiles, f+"cgo1.go") cfiles = append(cfiles, f+"cgo2.c") } defunC := b.obj + "_cgo_defun.c" - output := append([]string{defunC}, gofiles...) - output = append(output, cfiles...) + output := append([]string{defunC}, cfiles...) + output = append(output, gofiles...) b.add(Cmd{ Args: append([]string{"cgo", "--"}, cgofiles...), + Dir: b.path, + Env: append(os.Environ(), "GOARCH="+b.goarch), Input: cgofiles, Output: output, }) outGo = append(outGo, gofiles...) + exportH := filepath.Join(b.path, "_cgo_export.h") + b.script.addIntermediate(defunC, exportH, b.obj+"_cgo_flags") + b.script.addIntermediate(cfiles...) // cc _cgo_defun.c defunObj := b.obj + "_cgo_defun." + b.arch @@ -249,10 +401,13 @@ func (b *build) cgo(cgofiles []string) (outGo, outObj []string) { linkobj = append(linkobj, ofile) if !strings.HasSuffix(ofile, "_cgo_main.o") { outObj = append(outObj, ofile) + } else { + b.script.addIntermediate(ofile) } } - dynObj := b.obj + "_cgo1_.o" + dynObj := b.obj + "_cgo_.o" b.gccLink(dynObj, linkobj...) + b.script.addIntermediate(dynObj) // cgo -dynimport importC := b.obj + "_cgo_import.c" @@ -262,6 +417,7 @@ func (b *build) cgo(cgofiles []string) (outGo, outObj []string) { Input: []string{dynObj}, Output: []string{importC}, }) + b.script.addIntermediate(importC) // cc _cgo_import.ARCH importObj := b.obj + "_cgo_import." + b.arch diff --git a/src/pkg/go/build/build_test.go b/src/pkg/go/build/build_test.go index c543eddbd..e59d87672 100644 --- a/src/pkg/go/build/build_test.go +++ b/src/pkg/go/build/build_test.go @@ -5,53 +5,57 @@ package build import ( - "os" + "exec" "path/filepath" - "runtime" - "strings" "testing" ) -var buildDirs = []string{ - "pkg/path", - "cmd/gofix", - "pkg/big", - "pkg/go/build/cgotest", +var buildPkgs = []string{ + "go/build/pkgtest", + "go/build/cmdtest", + "go/build/cgotest", } +const cmdtestOutput = "3" + func TestBuild(t *testing.T) { - out, err := filepath.Abs("_test/out") - if err != nil { - t.Fatal(err) - } - for _, d := range buildDirs { - if runtime.GOARCH == "arm" && strings.Contains(d, "/cgo") { - // no cgo for arm, yet. + for _, pkg := range buildPkgs { + tree := Path[0] // Goroot + dir := filepath.Join(tree.SrcDir(), pkg) + + info, err := ScanDir(dir, true) + if err != nil { + t.Error("ScanDir:", err) continue } - dir := filepath.Join(runtime.GOROOT(), "src", d) - testBuild(t, dir, out) - } -} -func testBuild(t *testing.T, dir, targ string) { - d, err := ScanDir(dir, true) - if err != nil { - t.Error(err) - return - } - defer os.Remove(targ) - cmds, err := d.Build(targ) - if err != nil { - t.Error(err) - return - } - for _, c := range cmds { - t.Log("Run:", c) - err = c.Run(dir) + s, err := Build(tree, pkg, info) if err != nil { - t.Error(c, err) - return + t.Error("Build:", err) + continue + } + + if err := s.Run(); err != nil { + t.Error("Run:", err) + continue } + + if pkg == "go/build/cmdtest" { + bin := s.Output[0] + b, err := exec.Command(bin).CombinedOutput() + if err != nil { + t.Errorf("exec: %s: %v", bin, err) + continue + } + if string(b) != cmdtestOutput { + t.Errorf("cmdtest output: %s want: %s", b, cmdtestOutput) + } + } + + defer func(s *Script) { + if err := s.Nuke(); err != nil { + t.Errorf("nuking: %v", err) + } + }(s) } } diff --git a/src/pkg/go/build/cgotest/cgotest.go b/src/pkg/go/build/cgotest/cgotest.go new file mode 100644 index 000000000..32b931861 --- /dev/null +++ b/src/pkg/go/build/cgotest/cgotest.go @@ -0,0 +1,12 @@ +// 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 cgotest + +/* +char* greeting = "hello, world"; +*/ +import "C" + +var Greeting = C.GoString(C.greeting) diff --git a/src/pkg/go/build/cgotest/file.go b/src/pkg/go/build/cgotest/file.go deleted file mode 100644 index 3b2a2e7d9..000000000 --- a/src/pkg/go/build/cgotest/file.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -A trivial example of wrapping a C library in Go. -For a more complex example and explanation, -see ../gmp/gmp.go. -*/ - -package stdio - -/* -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <errno.h> - -char* greeting = "hello, world"; -*/ -import "C" -import "unsafe" - -type File C.FILE - -// TODO(brainman): uncomment once stdout and stderr references are working on Windows. -//var Stdout = (*File)(C.stdout) -//var Stderr = (*File)(C.stderr) - -// Test reference to library symbol. -// Stdout and stderr are too special to be a reliable test. -var myerr = C.sys_errlist - -func (f *File) WriteString(s string) { - p := C.CString(s) - C.fputs(p, (*C.FILE)(f)) - C.free(unsafe.Pointer(p)) - f.Flush() -} - -func (f *File) Flush() { - C.fflush((*C.FILE)(f)) -} - -var Greeting = C.GoString(C.greeting) diff --git a/src/pkg/go/build/cmdtest/main.go b/src/pkg/go/build/cmdtest/main.go new file mode 100644 index 000000000..bed4f485a --- /dev/null +++ b/src/pkg/go/build/cmdtest/main.go @@ -0,0 +1,12 @@ +// 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 main + +import "go/build/pkgtest" + +func main() { + pkgtest.Foo() + print(int(pkgtest.Sqrt(9))) +} diff --git a/src/pkg/go/build/dir.go b/src/pkg/go/build/dir.go index 77e80bff0..e0000b534 100644 --- a/src/pkg/go/build/dir.go +++ b/src/pkg/go/build/dir.go @@ -50,7 +50,6 @@ func ScanDir(dir string, allowMain bool) (info *DirInfo, err os.Error) { var di DirInfo imported := make(map[string]bool) - pkgName := "" fset := token.NewFileSet() for i := range dirs { d := &dirs[i] @@ -89,17 +88,17 @@ func ScanDir(dir string, allowMain bool) (info *DirInfo, err os.Error) { if s == "documentation" { continue } - if pkgName == "" { - pkgName = s - } else if pkgName != s { + if di.PkgName == "" { + di.PkgName = s + } else if di.PkgName != s { // Only if all files in the directory are in package main - // do we return pkgName=="main". + // do we return PkgName=="main". // A mix of main and another package reverts // to the original (allowMain=false) behaviour. - if s == "main" || pkgName == "main" { + if s == "main" || di.PkgName == "main" { return ScanDir(dir, false) } - return nil, os.ErrorString("multiple package names in " + dir) + return nil, os.NewError("multiple package names in " + dir) } isCgo := false for _, spec := range pf.Imports { @@ -140,7 +139,7 @@ func goodOSArch(filename string) bool { if dot := strings.Index(filename, "."); dot != -1 { filename = filename[:dot] } - l := strings.Split(filename, "_", -1) + l := strings.Split(filename, "_") n := len(l) if n == 0 { return true diff --git a/src/pkg/go/build/path.go b/src/pkg/go/build/path.go index 8ad39fb0f..ea588abbd 100644 --- a/src/pkg/go/build/path.go +++ b/src/pkg/go/build/path.go @@ -88,6 +88,9 @@ func FindTree(path string) (tree *Tree, pkg string, err os.Error) { if path, err = filepath.Abs(path); err != nil { return } + if path, err = filepath.EvalSymlinks(path); err != nil { + return + } for _, t := range Path { tpath := t.SrcDir() + string(filepath.Separator) if !strings.HasPrefix(path, tpath) { diff --git a/src/pkg/go/build/pkgtest/pkgtest.go b/src/pkg/go/build/pkgtest/pkgtest.go new file mode 100644 index 000000000..9322f5ebd --- /dev/null +++ b/src/pkg/go/build/pkgtest/pkgtest.go @@ -0,0 +1,9 @@ +// 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 pkgtest + +func Foo() {} + +func Sqrt(x float64) float64 diff --git a/src/pkg/go/build/pkgtest/sqrt_386.s b/src/pkg/go/build/pkgtest/sqrt_386.s new file mode 100644 index 000000000..d0a428d52 --- /dev/null +++ b/src/pkg/go/build/pkgtest/sqrt_386.s @@ -0,0 +1,10 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// func Sqrt(x float64) float64 +TEXT ·Sqrt(SB),7,$0 + FMOVD x+0(FP),F0 + FSQRT + FMOVDP F0,r+8(FP) + RET diff --git a/src/pkg/go/build/pkgtest/sqrt_amd64.s b/src/pkg/go/build/pkgtest/sqrt_amd64.s new file mode 100644 index 000000000..f5b329e70 --- /dev/null +++ b/src/pkg/go/build/pkgtest/sqrt_amd64.s @@ -0,0 +1,9 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// func Sqrt(x float64) float64 +TEXT ·Sqrt(SB),7,$0 + SQRTSD x+0(FP), X0 + MOVSD X0, r+8(FP) + RET diff --git a/src/pkg/go/build/pkgtest/sqrt_arm.s b/src/pkg/go/build/pkgtest/sqrt_arm.s new file mode 100644 index 000000000..befbb8a89 --- /dev/null +++ b/src/pkg/go/build/pkgtest/sqrt_arm.s @@ -0,0 +1,10 @@ +// 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. + +// func Sqrt(x float64) float64 +TEXT ·Sqrt(SB),7,$0 + MOVD x+0(FP),F0 + SQRTD F0,F0 + MOVD F0,r+8(FP) + RET diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go index f1ebfa97b..85640af79 100644 --- a/src/pkg/go/doc/comment.go +++ b/src/pkg/go/doc/comment.go @@ -58,7 +58,7 @@ func CommentText(comment *ast.CommentGroup) string { } // Split on newlines. - cl := strings.Split(c, "\n", -1) + cl := strings.Split(c, "\n") // Walk lines, stripping trailing white space and adding to list. for _, l := range cl { diff --git a/src/pkg/go/doc/doc.go b/src/pkg/go/doc/doc.go index a7a7e0a32..b26cd2bed 100644 --- a/src/pkg/go/doc/doc.go +++ b/src/pkg/go/doc/doc.go @@ -551,7 +551,7 @@ func (doc *docReader) newDoc(importpath string, filenames []string) *PackageDoc p := new(PackageDoc) p.PackageName = doc.pkgName p.ImportPath = importpath - sort.SortStrings(filenames) + sort.Strings(filenames) p.Filenames = filenames p.Doc = CommentText(doc.doc) // makeTypeDocs may extend the list of doc.values and diff --git a/src/pkg/go/parser/interface.go b/src/pkg/go/parser/interface.go index b4780e057..1764c38e4 100644 --- a/src/pkg/go/parser/interface.go +++ b/src/pkg/go/parser/interface.go @@ -42,7 +42,7 @@ func readSource(filename string, src interface{}) ([]byte, os.Error) { } return buf.Bytes(), nil default: - return nil, os.ErrorString("invalid source") + return nil, os.NewError("invalid source") } } diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go index 0fca8a161..f2b79d810 100644 --- a/src/pkg/go/printer/nodes.go +++ b/src/pkg/go/printer/nodes.go @@ -1158,8 +1158,14 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { case *ast.SelectStmt: p.print(token.SELECT, blank) - p.block(s.Body, 0) - *multiLine = true + body := s.Body + if len(body.List) == 0 && !p.commentBefore(p.fset.Position(body.Rbrace)) { + // print empty select statement w/o comments on one line + p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE) + } else { + p.block(body, 0) + *multiLine = true + } case *ast.ForStmt: p.print(token.FOR) diff --git a/src/pkg/go/printer/testdata/statements.golden b/src/pkg/go/printer/testdata/statements.golden index 290060269..0e4840441 100644 --- a/src/pkg/go/printer/testdata/statements.golden +++ b/src/pkg/go/printer/testdata/statements.golden @@ -111,6 +111,21 @@ func _() { } +// Formatting of selected select statements. +func _() { + select {} + select { /* this comment should not be tab-aligned because the closing } is on the same line */ + } + select { /* this comment should be tab-aligned */ + } + select { // this comment should be tab-aligned + } + select { + case <-c: + } +} + + // Formatting of for-statement headers. func _() { for { diff --git a/src/pkg/go/printer/testdata/statements.input b/src/pkg/go/printer/testdata/statements.input index 21e61efc4..86a753c5a 100644 --- a/src/pkg/go/printer/testdata/statements.input +++ b/src/pkg/go/printer/testdata/statements.input @@ -91,6 +91,19 @@ func _() { } +// Formatting of selected select statements. +func _() { + select { + } + select { /* this comment should not be tab-aligned because the closing } is on the same line */ } + select { /* this comment should be tab-aligned */ + } + select { // this comment should be tab-aligned + } + select { case <-c: } +} + + // Formatting of for-statement headers. func _() { for{} diff --git a/src/pkg/go/scanner/scanner.go b/src/pkg/go/scanner/scanner.go index 509abeca5..795f0ac15 100644 --- a/src/pkg/go/scanner/scanner.go +++ b/src/pkg/go/scanner/scanner.go @@ -22,6 +22,7 @@ package scanner import ( "bytes" + "fmt" "go/token" "path/filepath" "strconv" @@ -674,7 +675,7 @@ scanAgain: tok = S.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR) default: if S.mode&AllowIllegalChars == 0 { - S.error(offs, "illegal character "+strconv.QuoteRune(ch)) + S.error(offs, fmt.Sprintf("illegal character %#U", ch)) } insertSemi = S.insertSemi // preserve insertSemi info } diff --git a/src/pkg/go/scanner/scanner_test.go b/src/pkg/go/scanner/scanner_test.go index ee1e830a1..c096e2725 100644 --- a/src/pkg/go/scanner/scanner_test.go +++ b/src/pkg/go/scanner/scanner_test.go @@ -650,9 +650,9 @@ var errors = []struct { pos int err string }{ - {"\a", token.ILLEGAL, 0, "illegal character '\\a'"}, - {`#`, token.ILLEGAL, 0, "illegal character '#'"}, - {`…`, token.ILLEGAL, 0, "illegal character '…'"}, + {"\a", token.ILLEGAL, 0, "illegal character U+0007"}, + {`#`, token.ILLEGAL, 0, "illegal character U+0023 '#'"}, + {`…`, token.ILLEGAL, 0, "illegal character U+2026 '…'"}, {`' '`, token.CHAR, 0, ""}, {`''`, token.CHAR, 0, "illegal character literal"}, {`'\8'`, token.CHAR, 2, "unknown escape sequence"}, diff --git a/src/pkg/go/types/exportdata.go b/src/pkg/go/types/exportdata.go index cb08ffe18..f68133761 100644 --- a/src/pkg/go/types/exportdata.go +++ b/src/pkg/go/types/exportdata.go @@ -29,7 +29,7 @@ func readGopackHeader(buf *bufio.Reader) (name string, size int, err os.Error) { s := strings.TrimSpace(string(hdr[64+12+6+6+8:][:10])) size, err = strconv.Atoi(s) if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' { - err = os.ErrorString("invalid archive header") + err = os.NewError("invalid archive header") return } name = strings.TrimSpace(string(hdr[:64])) @@ -80,7 +80,7 @@ func ExportData(filename string) (rc io.ReadCloser, err os.Error) { return } if name != "__.SYMDEF" { - err = os.ErrorString("go archive does not begin with __.SYMDEF") + err = os.NewError("go archive does not begin with __.SYMDEF") return } const block = 4096 @@ -102,7 +102,7 @@ func ExportData(filename string) (rc io.ReadCloser, err os.Error) { return } if name != "__.PKGDEF" { - err = os.ErrorString("go archive is missing __.PKGDEF") + err = os.NewError("go archive is missing __.PKGDEF") return } @@ -117,7 +117,7 @@ func ExportData(filename string) (rc io.ReadCloser, err os.Error) { // Now at __.PKGDEF in archive or still at beginning of file. // Either way, line should begin with "go object ". if !strings.HasPrefix(string(line), "go object ") { - err = os.ErrorString("not a go object file") + err = os.NewError("not a go object file") return } diff --git a/src/pkg/go/types/gcimporter.go b/src/pkg/go/types/gcimporter.go index 2cfed7726..aa0bb9160 100644 --- a/src/pkg/go/types/gcimporter.go +++ b/src/pkg/go/types/gcimporter.go @@ -124,7 +124,7 @@ func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, e filename, id := findPkg(path) if filename == "" { - err = os.ErrorString("can't find import: " + id) + err = os.NewError("can't find import: " + id) return } @@ -166,7 +166,7 @@ func (e importError) String() string { func (p *gcParser) error(err interface{}) { if s, ok := err.(string); ok { - err = os.ErrorString(s) + err = os.NewError(s) } // panic with a runtime.Error if err is not an os.Error panic(importError{p.scanner.Pos(), err.(os.Error)}) diff --git a/src/pkg/go/types/testdata/exports.go b/src/pkg/go/types/testdata/exports.go index 1de2e00ad..035a13fb7 100644 --- a/src/pkg/go/types/testdata/exports.go +++ b/src/pkg/go/types/testdata/exports.go @@ -38,7 +38,7 @@ type ( T9 struct { a int b, c float32 - d []string "tag" + d []string `go:"tag"` } T10 struct { T8 |