libgo: Add sources for go, cgo, and gofmt commands.
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 6 Jan 2015 23:26:02 +0000 (23:26 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 6 Jan 2015 23:26:02 +0000 (23:26 +0000)
The new commands are not yet built.  That will be done
separately.

Also include a few changes to go/build to support them.

From-SVN: r219272

135 files changed:
libgo/Makefile.am
libgo/Makefile.in
libgo/go/cmd/cgo/ast.go [new file with mode: 0644]
libgo/go/cmd/cgo/doc.go [new file with mode: 0644]
libgo/go/cmd/cgo/gcc.go [new file with mode: 0644]
libgo/go/cmd/cgo/godefs.go [new file with mode: 0644]
libgo/go/cmd/cgo/main.go [new file with mode: 0644]
libgo/go/cmd/cgo/out.go [new file with mode: 0644]
libgo/go/cmd/cgo/util.go [new file with mode: 0644]
libgo/go/cmd/go/bootstrap.go [new file with mode: 0644]
libgo/go/cmd/go/build.go [new file with mode: 0644]
libgo/go/cmd/go/clean.go [new file with mode: 0644]
libgo/go/cmd/go/context.go [new file with mode: 0644]
libgo/go/cmd/go/discovery.go [new file with mode: 0644]
libgo/go/cmd/go/doc.go [new file with mode: 0644]
libgo/go/cmd/go/env.go [new file with mode: 0644]
libgo/go/cmd/go/fix.go [new file with mode: 0644]
libgo/go/cmd/go/fmt.go [new file with mode: 0644]
libgo/go/cmd/go/get.go [new file with mode: 0644]
libgo/go/cmd/go/go11.go [new file with mode: 0644]
libgo/go/cmd/go/help.go [new file with mode: 0644]
libgo/go/cmd/go/http.go [new file with mode: 0644]
libgo/go/cmd/go/list.go [new file with mode: 0644]
libgo/go/cmd/go/main.go [new file with mode: 0644]
libgo/go/cmd/go/match_test.go [new file with mode: 0644]
libgo/go/cmd/go/mkdoc.sh [new file with mode: 0644]
libgo/go/cmd/go/pkg.go [new file with mode: 0644]
libgo/go/cmd/go/pkg_test.go [new file with mode: 0644]
libgo/go/cmd/go/run.go [new file with mode: 0644]
libgo/go/cmd/go/script [new file with mode: 0644]
libgo/go/cmd/go/script.txt [new file with mode: 0644]
libgo/go/cmd/go/signal.go [new file with mode: 0644]
libgo/go/cmd/go/signal_notunix.go [new file with mode: 0644]
libgo/go/cmd/go/signal_unix.go [new file with mode: 0644]
libgo/go/cmd/go/tag_test.go [new file with mode: 0644]
libgo/go/cmd/go/test.bash [new file with mode: 0644]
libgo/go/cmd/go/test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/cgocover/p.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/cgocover/p_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/dep_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/example1_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/example2_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/local/easy.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/local/easysub/easysub.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/local/easysub/main.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/local/hard.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/local/sub/sub.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/local/sub/sub/subsub.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/badpkg/x.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/cgotest/m.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/go-cmd-test/helloworld.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/main_test/m.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/main_test/m_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/notest/hello.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/syntaxerror/x.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/xtestonly/f.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/src/xtestonly/f_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/standalone_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/testimport/p.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/testimport/p1/p1.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/testimport/p2/p2.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/testimport/p_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/testimport/x_test.go [new file with mode: 0644]
libgo/go/cmd/go/testdata/testonly/p_test.go [new file with mode: 0644]
libgo/go/cmd/go/testflag.go [new file with mode: 0644]
libgo/go/cmd/go/tool.go [new file with mode: 0644]
libgo/go/cmd/go/vcs.go [new file with mode: 0644]
libgo/go/cmd/go/version.go [new file with mode: 0644]
libgo/go/cmd/go/vet.go [new file with mode: 0644]
libgo/go/cmd/gofmt/doc.go [new file with mode: 0644]
libgo/go/cmd/gofmt/gofmt.go [new file with mode: 0644]
libgo/go/cmd/gofmt/gofmt_test.go [new file with mode: 0644]
libgo/go/cmd/gofmt/long_test.go [new file with mode: 0644]
libgo/go/cmd/gofmt/rewrite.go [new file with mode: 0644]
libgo/go/cmd/gofmt/simplify.go [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/comments.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/comments.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/composites.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/composites.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/crlf.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/crlf.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/import.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/import.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/old.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/old.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite1.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite1.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite2.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite2.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite3.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite3.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite4.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite4.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite5.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite5.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite6.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite6.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite7.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite7.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite8.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/rewrite8.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/slices1.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/slices1.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/slices2.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/slices2.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin1.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin1.golden.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin1.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin1.input.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin2.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin2.golden.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin2.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin2.input.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin3.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin3.golden.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin3.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin3.input.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin4.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin4.golden.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin4.input [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/stdin4.input.gofmt [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/typeswitch.golden [new file with mode: 0644]
libgo/go/cmd/gofmt/testdata/typeswitch.input [new file with mode: 0644]
libgo/go/go/build/build.go
libgo/go/runtime/extern.go
libgo/merge.sh

index 380caf53c6b7bd6ce5a62f863baae04a08899b68..526b656a30954716b54720df9020f4f44ca53969 100644 (file)
@@ -26,6 +26,7 @@ STAMP = echo timestamp >
 toolexecdir = $(glibgo_toolexecdir)
 toolexeclibdir = $(glibgo_toolexeclibdir)
 toolexeclibgodir = $(nover_glibgo_toolexeclibdir)/go/$(gcc_version)/$(target_alias)
+libexecsubdir = $(libexecdir)/gcc/$(target_alias)/$(gcc_version)
 
 LIBFFI = @LIBFFI@
 LIBFFIINCS = @LIBFFIINCS@
@@ -1007,6 +1008,7 @@ s-version: Makefile
        echo 'const theVersion = "'`$(GOC) --version | sed 1q`'"' >> version.go.tmp
        echo 'const theGoarch = "'$(GOARCH)'"' >> version.go.tmp
        echo 'const theGoos = "'$(GOOS)'"' >> version.go.tmp
+       echo 'const theGccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go
        $(STAMP) $@
 
index d495bf66dd768de59f262dbc2b55b2a12e6cfa22..2254478aebe27ad2b8e1f202ce37d582ac7bee2b 100644 (file)
@@ -454,6 +454,7 @@ STAMP = echo timestamp >
 toolexecdir = $(glibgo_toolexecdir)
 toolexeclibdir = $(glibgo_toolexeclibdir)
 toolexeclibgodir = $(nover_glibgo_toolexeclibdir)/go/$(gcc_version)/$(target_alias)
+libexecsubdir = $(libexecdir)/gcc/$(target_alias)/$(gcc_version)
 WARN_CFLAGS = $(WARN_FLAGS) $(WERROR)
 
 # -I/-D flags to pass when compiling.
@@ -4392,6 +4393,7 @@ s-version: Makefile
        echo 'const theVersion = "'`$(GOC) --version | sed 1q`'"' >> version.go.tmp
        echo 'const theGoarch = "'$(GOARCH)'"' >> version.go.tmp
        echo 'const theGoos = "'$(GOOS)'"' >> version.go.tmp
+       echo 'const theGccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp
        $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go
        $(STAMP) $@
 
diff --git a/libgo/go/cmd/cgo/ast.go b/libgo/go/cmd/cgo/ast.go
new file mode 100644 (file)
index 0000000..7757efa
--- /dev/null
@@ -0,0 +1,460 @@
+// 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.
+
+// Parse input AST and prepare Prog structure.
+
+package main
+
+import (
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "go/scanner"
+       "go/token"
+       "os"
+       "path/filepath"
+       "strings"
+)
+
+func parse(name string, flags parser.Mode) *ast.File {
+       ast1, err := parser.ParseFile(fset, name, nil, flags)
+       if err != nil {
+               if list, ok := err.(scanner.ErrorList); ok {
+                       // If err is a scanner.ErrorList, its String will print just
+                       // the first error and then (+n more errors).
+                       // Instead, turn it into a new Error that will return
+                       // details for all the errors.
+                       for _, e := range list {
+                               fmt.Fprintln(os.Stderr, e)
+                       }
+                       os.Exit(2)
+               }
+               fatalf("parsing %s: %s", name, err)
+       }
+       return ast1
+}
+
+func sourceLine(n ast.Node) int {
+       return fset.Position(n.Pos()).Line
+}
+
+// ReadGo populates f with information learned from reading the
+// Go source file with the given file name.  It gathers the C preamble
+// attached to the import "C" comment, a list of references to C.xxx,
+// a list of exported functions, and the actual AST, to be rewritten and
+// printed.
+func (f *File) ReadGo(name string) {
+       // Create absolute path for file, so that it will be used in error
+       // messages and recorded in debug line number information.
+       // This matches the rest of the toolchain. See golang.org/issue/5122.
+       if aname, err := filepath.Abs(name); err == nil {
+               name = aname
+       }
+
+       // Two different parses: once with comments, once without.
+       // The printer is not good enough at printing comments in the
+       // right place when we start editing the AST behind its back,
+       // so we use ast1 to look for the doc comments on import "C"
+       // and on exported functions, and we use ast2 for translating
+       // and reprinting.
+       ast1 := parse(name, parser.ParseComments)
+       ast2 := parse(name, 0)
+
+       f.Package = ast1.Name.Name
+       f.Name = make(map[string]*Name)
+
+       // In ast1, find the import "C" line and get any extra C preamble.
+       sawC := false
+       for _, decl := range ast1.Decls {
+               d, ok := decl.(*ast.GenDecl)
+               if !ok {
+                       continue
+               }
+               for _, spec := range d.Specs {
+                       s, ok := spec.(*ast.ImportSpec)
+                       if !ok || string(s.Path.Value) != `"C"` {
+                               continue
+                       }
+                       sawC = true
+                       if s.Name != nil {
+                               error_(s.Path.Pos(), `cannot rename import "C"`)
+                       }
+                       cg := s.Doc
+                       if cg == nil && len(d.Specs) == 1 {
+                               cg = d.Doc
+                       }
+                       if cg != nil {
+                               f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
+                               f.Preamble += commentText(cg) + "\n"
+                       }
+               }
+       }
+       if !sawC {
+               error_(token.NoPos, `cannot find import "C"`)
+       }
+
+       // In ast2, strip the import "C" line.
+       w := 0
+       for _, decl := range ast2.Decls {
+               d, ok := decl.(*ast.GenDecl)
+               if !ok {
+                       ast2.Decls[w] = decl
+                       w++
+                       continue
+               }
+               ws := 0
+               for _, spec := range d.Specs {
+                       s, ok := spec.(*ast.ImportSpec)
+                       if !ok || string(s.Path.Value) != `"C"` {
+                               d.Specs[ws] = spec
+                               ws++
+                       }
+               }
+               if ws == 0 {
+                       continue
+               }
+               d.Specs = d.Specs[0:ws]
+               ast2.Decls[w] = d
+               w++
+       }
+       ast2.Decls = ast2.Decls[0:w]
+
+       // Accumulate pointers to uses of C.x.
+       if f.Ref == nil {
+               f.Ref = make([]*Ref, 0, 8)
+       }
+       f.walk(ast2, "prog", (*File).saveRef)
+
+       // Accumulate exported functions.
+       // The comments are only on ast1 but we need to
+       // save the function bodies from ast2.
+       // The first walk fills in ExpFunc, and the
+       // second walk changes the entries to
+       // refer to ast2 instead.
+       f.walk(ast1, "prog", (*File).saveExport)
+       f.walk(ast2, "prog", (*File).saveExport2)
+
+       f.Comments = ast1.Comments
+       f.AST = ast2
+}
+
+// Like ast.CommentGroup's Text method but preserves
+// leading blank lines, so that line numbers line up.
+func commentText(g *ast.CommentGroup) string {
+       if g == nil {
+               return ""
+       }
+       var pieces []string
+       for _, com := range g.List {
+               c := string(com.Text)
+               // Remove comment markers.
+               // The parser has given us exactly the comment text.
+               switch c[1] {
+               case '/':
+                       //-style comment (no newline at the end)
+                       c = c[2:] + "\n"
+               case '*':
+                       /*-style comment */
+                       c = c[2 : len(c)-2]
+               }
+               pieces = append(pieces, c)
+       }
+       return strings.Join(pieces, "")
+}
+
+// Save references to C.xxx for later processing.
+func (f *File) saveRef(x interface{}, context string) {
+       n, ok := x.(*ast.Expr)
+       if !ok {
+               return
+       }
+       if sel, ok := (*n).(*ast.SelectorExpr); ok {
+               // For now, assume that the only instance of capital C is
+               // when used as the imported package identifier.
+               // The parser should take care of scoping in the future,
+               // so that we will be able to distinguish a "top-level C"
+               // from a local C.
+               if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
+                       if context == "as2" {
+                               context = "expr"
+                       }
+                       if context == "embed-type" {
+                               error_(sel.Pos(), "cannot embed C type")
+                       }
+                       goname := sel.Sel.Name
+                       if goname == "errno" {
+                               error_(sel.Pos(), "cannot refer to errno directly; see documentation")
+                               return
+                       }
+                       if goname == "_CMalloc" {
+                               error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
+                               return
+                       }
+                       if goname == "malloc" {
+                               goname = "_CMalloc"
+                       }
+                       name := f.Name[goname]
+                       if name == nil {
+                               name = &Name{
+                                       Go: goname,
+                               }
+                               f.Name[goname] = name
+                       }
+                       f.Ref = append(f.Ref, &Ref{
+                               Name:    name,
+                               Expr:    n,
+                               Context: context,
+                       })
+                       return
+               }
+       }
+}
+
+// If a function should be exported add it to ExpFunc.
+func (f *File) saveExport(x interface{}, context string) {
+       n, ok := x.(*ast.FuncDecl)
+       if !ok {
+               return
+       }
+
+       if n.Doc == nil {
+               return
+       }
+       for _, c := range n.Doc.List {
+               if !strings.HasPrefix(string(c.Text), "//export ") {
+                       continue
+               }
+
+               name := strings.TrimSpace(string(c.Text[9:]))
+               if name == "" {
+                       error_(c.Pos(), "export missing name")
+               }
+
+               if name != n.Name.Name {
+                       error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
+               }
+
+               f.ExpFunc = append(f.ExpFunc, &ExpFunc{
+                       Func:    n,
+                       ExpName: name,
+               })
+               break
+       }
+}
+
+// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
+func (f *File) saveExport2(x interface{}, context string) {
+       n, ok := x.(*ast.FuncDecl)
+       if !ok {
+               return
+       }
+
+       for _, exp := range f.ExpFunc {
+               if exp.Func.Name.Name == n.Name.Name {
+                       exp.Func = n
+                       break
+               }
+       }
+}
+
+// walk walks the AST x, calling visit(f, x, context) for each node.
+func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) {
+       visit(f, x, context)
+       switch n := x.(type) {
+       case *ast.Expr:
+               f.walk(*n, context, visit)
+
+       // everything else just recurs
+       default:
+               error_(token.NoPos, "unexpected type %T in walk", x, visit)
+               panic("unexpected type")
+
+       case nil:
+
+       // These are ordered and grouped to match ../../pkg/go/ast/ast.go
+       case *ast.Field:
+               if len(n.Names) == 0 && context == "field" {
+                       f.walk(&n.Type, "embed-type", visit)
+               } else {
+                       f.walk(&n.Type, "type", visit)
+               }
+       case *ast.FieldList:
+               for _, field := range n.List {
+                       f.walk(field, context, visit)
+               }
+       case *ast.BadExpr:
+       case *ast.Ident:
+       case *ast.Ellipsis:
+       case *ast.BasicLit:
+       case *ast.FuncLit:
+               f.walk(n.Type, "type", visit)
+               f.walk(n.Body, "stmt", visit)
+       case *ast.CompositeLit:
+               f.walk(&n.Type, "type", visit)
+               f.walk(n.Elts, "expr", visit)
+       case *ast.ParenExpr:
+               f.walk(&n.X, context, visit)
+       case *ast.SelectorExpr:
+               f.walk(&n.X, "selector", visit)
+       case *ast.IndexExpr:
+               f.walk(&n.X, "expr", visit)
+               f.walk(&n.Index, "expr", visit)
+       case *ast.SliceExpr:
+               f.walk(&n.X, "expr", visit)
+               if n.Low != nil {
+                       f.walk(&n.Low, "expr", visit)
+               }
+               if n.High != nil {
+                       f.walk(&n.High, "expr", visit)
+               }
+       case *ast.TypeAssertExpr:
+               f.walk(&n.X, "expr", visit)
+               f.walk(&n.Type, "type", visit)
+       case *ast.CallExpr:
+               if context == "as2" {
+                       f.walk(&n.Fun, "call2", visit)
+               } else {
+                       f.walk(&n.Fun, "call", visit)
+               }
+               f.walk(n.Args, "expr", visit)
+       case *ast.StarExpr:
+               f.walk(&n.X, context, visit)
+       case *ast.UnaryExpr:
+               f.walk(&n.X, "expr", visit)
+       case *ast.BinaryExpr:
+               f.walk(&n.X, "expr", visit)
+               f.walk(&n.Y, "expr", visit)
+       case *ast.KeyValueExpr:
+               f.walk(&n.Key, "expr", visit)
+               f.walk(&n.Value, "expr", visit)
+
+       case *ast.ArrayType:
+               f.walk(&n.Len, "expr", visit)
+               f.walk(&n.Elt, "type", visit)
+       case *ast.StructType:
+               f.walk(n.Fields, "field", visit)
+       case *ast.FuncType:
+               f.walk(n.Params, "param", visit)
+               if n.Results != nil {
+                       f.walk(n.Results, "param", visit)
+               }
+       case *ast.InterfaceType:
+               f.walk(n.Methods, "field", visit)
+       case *ast.MapType:
+               f.walk(&n.Key, "type", visit)
+               f.walk(&n.Value, "type", visit)
+       case *ast.ChanType:
+               f.walk(&n.Value, "type", visit)
+
+       case *ast.BadStmt:
+       case *ast.DeclStmt:
+               f.walk(n.Decl, "decl", visit)
+       case *ast.EmptyStmt:
+       case *ast.LabeledStmt:
+               f.walk(n.Stmt, "stmt", visit)
+       case *ast.ExprStmt:
+               f.walk(&n.X, "expr", visit)
+       case *ast.SendStmt:
+               f.walk(&n.Chan, "expr", visit)
+               f.walk(&n.Value, "expr", visit)
+       case *ast.IncDecStmt:
+               f.walk(&n.X, "expr", visit)
+       case *ast.AssignStmt:
+               f.walk(n.Lhs, "expr", visit)
+               if len(n.Lhs) == 2 && len(n.Rhs) == 1 {
+                       f.walk(n.Rhs, "as2", visit)
+               } else {
+                       f.walk(n.Rhs, "expr", visit)
+               }
+       case *ast.GoStmt:
+               f.walk(n.Call, "expr", visit)
+       case *ast.DeferStmt:
+               f.walk(n.Call, "expr", visit)
+       case *ast.ReturnStmt:
+               f.walk(n.Results, "expr", visit)
+       case *ast.BranchStmt:
+       case *ast.BlockStmt:
+               f.walk(n.List, context, visit)
+       case *ast.IfStmt:
+               f.walk(n.Init, "stmt", visit)
+               f.walk(&n.Cond, "expr", visit)
+               f.walk(n.Body, "stmt", visit)
+               f.walk(n.Else, "stmt", visit)
+       case *ast.CaseClause:
+               if context == "typeswitch" {
+                       context = "type"
+               } else {
+                       context = "expr"
+               }
+               f.walk(n.List, context, visit)
+               f.walk(n.Body, "stmt", visit)
+       case *ast.SwitchStmt:
+               f.walk(n.Init, "stmt", visit)
+               f.walk(&n.Tag, "expr", visit)
+               f.walk(n.Body, "switch", visit)
+       case *ast.TypeSwitchStmt:
+               f.walk(n.Init, "stmt", visit)
+               f.walk(n.Assign, "stmt", visit)
+               f.walk(n.Body, "typeswitch", visit)
+       case *ast.CommClause:
+               f.walk(n.Comm, "stmt", visit)
+               f.walk(n.Body, "stmt", visit)
+       case *ast.SelectStmt:
+               f.walk(n.Body, "stmt", visit)
+       case *ast.ForStmt:
+               f.walk(n.Init, "stmt", visit)
+               f.walk(&n.Cond, "expr", visit)
+               f.walk(n.Post, "stmt", visit)
+               f.walk(n.Body, "stmt", visit)
+       case *ast.RangeStmt:
+               f.walk(&n.Key, "expr", visit)
+               f.walk(&n.Value, "expr", visit)
+               f.walk(&n.X, "expr", visit)
+               f.walk(n.Body, "stmt", visit)
+
+       case *ast.ImportSpec:
+       case *ast.ValueSpec:
+               f.walk(&n.Type, "type", visit)
+               f.walk(n.Values, "expr", visit)
+       case *ast.TypeSpec:
+               f.walk(&n.Type, "type", visit)
+
+       case *ast.BadDecl:
+       case *ast.GenDecl:
+               f.walk(n.Specs, "spec", visit)
+       case *ast.FuncDecl:
+               if n.Recv != nil {
+                       f.walk(n.Recv, "param", visit)
+               }
+               f.walk(n.Type, "type", visit)
+               if n.Body != nil {
+                       f.walk(n.Body, "stmt", visit)
+               }
+
+       case *ast.File:
+               f.walk(n.Decls, "decl", visit)
+
+       case *ast.Package:
+               for _, file := range n.Files {
+                       f.walk(file, "file", visit)
+               }
+
+       case []ast.Decl:
+               for _, d := range n {
+                       f.walk(d, context, visit)
+               }
+       case []ast.Expr:
+               for i := range n {
+                       f.walk(&n[i], context, visit)
+               }
+       case []ast.Stmt:
+               for _, s := range n {
+                       f.walk(s, context, visit)
+               }
+       case []ast.Spec:
+               for _, s := range n {
+                       f.walk(s, context, visit)
+               }
+       }
+}
diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go
new file mode 100644 (file)
index 0000000..69c7ce8
--- /dev/null
@@ -0,0 +1,748 @@
+// 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.
+
+/*
+
+Cgo enables the creation of Go packages that call C code.
+
+Using cgo with the go command
+
+To use cgo write normal Go code that imports a pseudo-package "C".
+The Go code can then refer to types such as C.size_t, variables such
+as C.stdout, or functions such as C.putchar.
+
+If the import of "C" is immediately preceded by a comment, that
+comment, called the preamble, is used as a header when compiling
+the C parts of the package.  For example:
+
+       // #include <stdio.h>
+       // #include <errno.h>
+       import "C"
+
+See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples.  See
+"C? Go? Cgo!" for an introduction to using cgo:
+http://golang.org/doc/articles/c_go_cgo.html.
+
+CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo
+directives within these comments to tweak the behavior of the C or C++
+compiler.  Values defined in multiple directives are concatenated
+together.  The directive can include a list of build constraints limiting its
+effect to systems satisfying one of the constraints
+(see http://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
+For example:
+
+       // #cgo CFLAGS: -DPNG_DEBUG=1
+       // #cgo amd64 386 CFLAGS: -DX86=1
+       // #cgo LDFLAGS: -lpng
+       // #include <png.h>
+       import "C"
+
+Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config
+tool using a '#cgo pkg-config:' directive followed by the package names.
+For example:
+
+       // #cgo pkg-config: png cairo
+       // #include <png.h>
+       import "C"
+
+When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS and
+CGO_LDFLAGS environment variables are added to the flags derived from
+these directives.  Package-specific flags should be set using the
+directives, not the environment variables, so that builds work in
+unmodified environments.
+
+All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and
+used to compile C files in that package.  All the CPPFLAGS and CXXFLAGS
+directives in a package are concatenated and used to compile C++ files in that
+package.  All the LDFLAGS directives in any package in the program are
+concatenated and used at link time.  All the pkg-config directives are
+concatenated and sent to pkg-config simultaneously to add to each appropriate
+set of command-line flags.
+
+When the Go tool sees that one or more Go files use the special import
+"C", it will look for other non-Go files in the directory and compile
+them as part of the Go package.  Any .c, .s, or .S files will be
+compiled with the C compiler.  Any .cc, .cpp, or .cxx files will be
+compiled with the C++ compiler.  Any .h, .hh, .hpp, or .hxx files will
+not be compiled separately, but, if these header files are changed,
+the C and C++ files will be recompiled.  The default C and C++
+compilers may be changed by the CC and CXX environment variables,
+respectively; those environment variables may include command line
+options.
+
+To enable cgo during cross compiling builds, set the CGO_ENABLED
+environment variable to 1 when building the Go tools with make.bash.
+Also, set CC_FOR_TARGET to the C cross compiler for the target.  CC will
+be used for compiling for the host.
+
+After the Go tools are built, when running the go command, CC_FOR_TARGET is
+ignored.  The value of CC_FOR_TARGET when running make.bash is the default
+compiler.  However, you can set the environment variable CC, not CC_FOR_TARGET,
+to control the compiler when running the go tool.
+
+CXX_FOR_TARGET works in a similar way for C++ code.
+
+Go references to C
+
+Within the Go file, C's struct field names that are keywords in Go
+can be accessed by prefixing them with an underscore: if x points at a C
+struct with a field named "type", x._type accesses the field.
+C struct fields that cannot be expressed in Go, such as bit fields
+or misaligned data, are omitted in the Go struct, replaced by
+appropriate padding to reach the next field or the end of the struct.
+
+The standard C numeric types are available under the names
+C.char, C.schar (signed char), C.uchar (unsigned char),
+C.short, C.ushort (unsigned short), C.int, C.uint (unsigned int),
+C.long, C.ulong (unsigned long), C.longlong (long long),
+C.ulonglong (unsigned long long), C.float, C.double.
+The C type void* is represented by Go's unsafe.Pointer.
+
+To access a struct, union, or enum type directly, prefix it with
+struct_, union_, or enum_, as in C.struct_stat.
+
+As Go doesn't have support for C's union type in the general case,
+C's union types are represented as a Go byte array with the same length.
+
+Go structs cannot embed fields with C types.
+
+Cgo translates C types into equivalent unexported Go types.
+Because the translations are unexported, a Go package should not
+expose C types in its exported API: a C type used in one Go package
+is different from the same C type used in another.
+
+Any C function (even void functions) may be called in a multiple
+assignment context to retrieve both the return value (if any) and the
+C errno variable as an error (use _ to skip the result value if the
+function returns void).  For example:
+
+       n, err := C.sqrt(-1)
+       _, err := C.voidFunc()
+
+Calling C function pointers is currently not supported, however you can
+declare Go variables which hold C function pointers and pass them
+back and forth between Go and C. C code may call function pointers
+received from Go. For example:
+
+       package main
+
+       // typedef int (*intFunc) ();
+       //
+       // int
+       // bridge_int_func(intFunc f)
+       // {
+       //              return f();
+       // }
+       //
+       // int fortytwo()
+       // {
+       //          return 42;
+       // }
+       import "C"
+       import "fmt"
+
+       func main() {
+               f := C.intFunc(C.fortytwo)
+               fmt.Println(int(C.bridge_int_func(f)))
+               // Output: 42
+       }
+
+In C, a function argument written as a fixed size array
+actually requires a pointer to the first element of the array.
+C compilers are aware of this calling convention and adjust
+the call accordingly, but Go cannot.  In Go, you must pass
+the pointer to the first element explicitly: C.f(&x[0]).
+
+A few special functions convert between Go and C types
+by making copies of the data.  In pseudo-Go definitions:
+
+       // Go string to C string
+       // The C string is allocated in the C heap using malloc.
+       // It is the caller's responsibility to arrange for it to be
+       // freed, such as by calling C.free (be sure to include stdlib.h
+       // if C.free is needed).
+       func C.CString(string) *C.char
+
+       // C string to Go string
+       func C.GoString(*C.char) string
+
+       // C string, length to Go string
+       func C.GoStringN(*C.char, C.int) string
+
+       // C pointer, length to Go []byte
+       func C.GoBytes(unsafe.Pointer, C.int) []byte
+
+C references to Go
+
+Go functions can be exported for use by C code in the following way:
+
+       //export MyFunction
+       func MyFunction(arg1, arg2 int, arg3 string) int64 {...}
+
+       //export MyFunction2
+       func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...}
+
+They will be available in the C code as:
+
+       extern int64 MyFunction(int arg1, int arg2, GoString arg3);
+       extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
+
+found in the _cgo_export.h generated header, after any preambles
+copied from the cgo input files. Functions with multiple
+return values are mapped to functions returning a struct.
+Not all Go types can be mapped to C types in a useful way.
+
+Using //export in a file places a restriction on the preamble:
+since it is copied into two different C output files, it must not
+contain any definitions, only declarations. Definitions must be
+placed in preambles in other files, or in C source files.
+
+Using cgo directly
+
+Usage:
+       go tool cgo [cgo options] [-- compiler options] file.go
+
+Cgo transforms the input file.go into four output files: two Go source
+files, a C file for 6c (or 8c or 5c), and a C file for gcc.
+
+The compiler options are passed through uninterpreted when
+invoking the C compiler to compile the C parts of the package.
+
+The following options are available when running cgo directly:
+
+       -dynimport file
+               Write list of symbols imported by file. Write to
+               -dynout argument or to standard output. Used by go
+               build when building a cgo package.
+       -dynout file
+               Write -dynimport output to file.
+       -dynlinker
+               Write dynamic linker as part of -dynimport output.
+       -godefs
+               Write out input file in Go syntax replacing C package
+               names with real values. Used to generate files in the
+               syscall package when bootstrapping a new target.
+       -cdefs
+               Like -godefs, but write file in C syntax.
+               Used to generate files in the runtime package when
+               bootstrapping a new target.
+       -objdir directory
+               Put all generated files in directory.
+       -gccgo
+               Generate output for the gccgo compiler rather than the
+               gc compiler.
+       -gccgoprefix prefix
+               The -fgo-prefix option to be used with gccgo.
+       -gccgopkgpath path
+               The -fgo-pkgpath option to be used with gccgo.
+       -import_runtime_cgo
+               If set (which it is by default) import runtime/cgo in
+               generated output.
+       -import_syscall
+               If set (which it is by default) import syscall in
+               generated output.
+       -debug-define
+               Debugging option. Print #defines.
+       -debug-gcc
+               Debugging option. Trace C compiler execution and output.
+*/
+package main
+
+/*
+Implementation details.
+
+Cgo provides a way for Go programs to call C code linked into the same
+address space. This comment explains the operation of cgo.
+
+Cgo reads a set of Go source files and looks for statements saying
+import "C". If the import has a doc comment, that comment is
+taken as literal C code to be used as a preamble to any C code
+generated by cgo. A typical preamble #includes necessary definitions:
+
+       // #include <stdio.h>
+       import "C"
+
+For more details about the usage of cgo, see the documentation
+comment at the top of this file.
+
+Understanding C
+
+Cgo scans the Go source files that import "C" for uses of that
+package, such as C.puts. It collects all such identifiers. The next
+step is to determine each kind of name. In C.xxx the xxx might refer
+to a type, a function, a constant, or a global variable. Cgo must
+decide which.
+
+The obvious thing for cgo to do is to process the preamble, expanding
+#includes and processing the corresponding C code. That would require
+a full C parser and type checker that was also aware of any extensions
+known to the system compiler (for example, all the GNU C extensions) as
+well as the system-specific header locations and system-specific
+pre-#defined macros. This is certainly possible to do, but it is an
+enormous amount of work.
+
+Cgo takes a different approach. It determines the meaning of C
+identifiers not by parsing C code but by feeding carefully constructed
+programs into the system C compiler and interpreting the generated
+error messages, debug information, and object files. In practice,
+parsing these is significantly less work and more robust than parsing
+C source.
+
+Cgo first invokes gcc -E -dM on the preamble, in order to find out
+about simple #defines for constants and the like. These are recorded
+for later use.
+
+Next, cgo needs to identify the kinds for each identifier. For the
+identifiers C.foo and C.bar, cgo generates this C program:
+
+       <preamble>
+       #line 1 "not-declared"
+       void __cgo_f_xxx_1(void) { __typeof__(foo) *__cgo_undefined__; }
+       #line 1 "not-type"
+       void __cgo_f_xxx_2(void) { foo *__cgo_undefined__; }
+       #line 1 "not-const"
+       void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (foo)*1 }; }
+       #line 2 "not-declared"
+       void __cgo_f_xxx_1(void) { __typeof__(bar) *__cgo_undefined__; }
+       #line 2 "not-type"
+       void __cgo_f_xxx_2(void) { bar *__cgo_undefined__; }
+       #line 2 "not-const"
+       void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (bar)*1 }; }
+
+This program will not compile, but cgo can use the presence or absence
+of an error message on a given line to deduce the information it
+needs. The program is syntactically valid regardless of whether each
+name is a type or an ordinary identifier, so there will be no syntax
+errors that might stop parsing early.
+
+An error on not-declared:1 indicates that foo is undeclared.
+An error on not-type:1 indicates that foo is not a type (if declared at all, it is an identifier).
+An error on not-const:1 indicates that foo is not an integer constant.
+
+The line number specifies the name involved. In the example, 1 is foo and 2 is bar.
+
+Next, cgo must learn the details of each type, variable, function, or
+constant. It can do this by reading object files. If cgo has decided
+that t1 is a type, v2 and v3 are variables or functions, and c4, c5,
+and c6 are constants, it generates:
+
+       <preamble>
+       __typeof__(t1) *__cgo__1;
+       __typeof__(v2) *__cgo__2;
+       __typeof__(v3) *__cgo__3;
+       __typeof__(c4) *__cgo__4;
+       enum { __cgo_enum__4 = c4 };
+       __typeof__(c5) *__cgo__5;
+       enum { __cgo_enum__5 = c5 };
+       __typeof__(c6) *__cgo__6;
+       enum { __cgo_enum__6 = c6 };
+
+       long long __cgo_debug_data[] = {
+               0, // t1
+               0, // v2
+               0, // v3
+               c4,
+               c5,
+               c6,
+               1
+       };
+
+and again invokes the system C compiler, to produce an object file
+containing debug information. Cgo parses the DWARF debug information
+for __cgo__N to learn the type of each identifier. (The types also
+distinguish functions from global variables.) If using a standard gcc,
+cgo can parse the DWARF debug information for the __cgo_enum__N to
+learn the identifier's value. The LLVM-based gcc on OS X emits
+incomplete DWARF information for enums; in that case cgo reads the
+constant values from the __cgo_debug_data from the object file's data
+segment.
+
+At this point cgo knows the meaning of each C.xxx well enough to start
+the translation process.
+
+Translating Go
+
+[The rest of this comment refers to 6g and 6c, the Go and C compilers
+that are part of the amd64 port of the gc Go toolchain. Everything here
+applies to another architecture's compilers as well.]
+
+Given the input Go files x.go and y.go, cgo generates these source
+files:
+
+       x.cgo1.go       # for 6g
+       y.cgo1.go       # for 6g
+       _cgo_gotypes.go # for 6g
+       _cgo_defun.c    # for 6c
+       x.cgo2.c        # for gcc
+       y.cgo2.c        # for gcc
+       _cgo_export.c   # for gcc
+       _cgo_main.c     # for gcc
+
+The file x.cgo1.go is a copy of x.go with the import "C" removed and
+references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx.
+The definitions of those identifiers, written as Go functions, types,
+or variables, are provided in _cgo_gotypes.go.
+
+Here is a _cgo_gotypes.go containing definitions for C.flush (provided
+in the preamble) and C.puts (from stdio):
+
+       type _Ctype_char int8
+       type _Ctype_int int32
+       type _Ctype_void [0]byte
+
+       func _Cfunc_CString(string) *_Ctype_char
+       func _Cfunc_flush() _Ctype_void
+       func _Cfunc_puts(*_Ctype_char) _Ctype_int
+
+For functions, cgo only writes an external declaration in the Go
+output. The implementation is in a combination of C for 6c (meaning
+any gc-toolchain compiler) and C for gcc.
+
+The 6c file contains the definitions of the functions. They all have
+similar bodies that invoke runtime·cgocall to make a switch from the
+Go runtime world to the system C (GCC-based) world.
+
+For example, here is the definition of _Cfunc_puts:
+
+       void _cgo_be59f0f25121_Cfunc_puts(void*);
+
+       void
+       Â·_Cfunc_puts(struct{uint8 x[1];}p)
+       {
+               runtime·cgocall(_cgo_be59f0f25121_Cfunc_puts, &p);
+       }
+
+The hexadecimal number is a hash of cgo's input, chosen to be
+deterministic yet unlikely to collide with other uses. The actual
+function _cgo_be59f0f25121_Cfunc_puts is implemented in a C source
+file compiled by gcc, the file x.cgo2.c:
+
+       void
+       _cgo_be59f0f25121_Cfunc_puts(void *v)
+       {
+               struct {
+                       char* p0;
+                       int r;
+                       char __pad12[4];
+               } __attribute__((__packed__, __gcc_struct__)) *a = v;
+               a->r = puts((void*)a->p0);
+       }
+
+It extracts the arguments from the pointer to _Cfunc_puts's argument
+frame, invokes the system C function (in this case, puts), stores the
+result in the frame, and returns.
+
+Linking
+
+Once the _cgo_export.c and *.cgo2.c files have been compiled with gcc,
+they need to be linked into the final binary, along with the libraries
+they might depend on (in the case of puts, stdio). 6l has been
+extended to understand basic ELF files, but it does not understand ELF
+in the full complexity that modern C libraries embrace, so it cannot
+in general generate direct references to the system libraries.
+
+Instead, the build process generates an object file using dynamic
+linkage to the desired libraries. The main function is provided by
+_cgo_main.c:
+
+       int main() { return 0; }
+       void crosscall2(void(*fn)(void*, int), void *a, int c) { }
+       void _cgo_allocate(void *a, int c) { }
+       void _cgo_panic(void *a, int c) { }
+
+The extra functions here are stubs to satisfy the references in the C
+code generated for gcc. The build process links this stub, along with
+_cgo_export.c and *.cgo2.c, into a dynamic executable and then lets
+cgo examine the executable. Cgo records the list of shared library
+references and resolved names and writes them into a new file
+_cgo_import.c, which looks like:
+
+       #pragma cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2"
+       #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
+       #pragma cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6"
+       #pragma cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6"
+       #pragma cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6"
+       #pragma cgo_import_dynamic _ _ "libpthread.so.0"
+       #pragma cgo_import_dynamic _ _ "libc.so.6"
+
+In the end, the compiled Go package, which will eventually be
+presented to 6l as part of a larger program, contains:
+
+       _go_.6        # 6g-compiled object for _cgo_gotypes.go *.cgo1.go
+       _cgo_defun.6  # 6c-compiled object for _cgo_defun.c
+       _all.o        # gcc-compiled object for _cgo_export.c, *.cgo2.c
+       _cgo_import.6 # 6c-compiled object for _cgo_import.c
+
+The final program will be a dynamic executable, so that 6l can avoid
+needing to process arbitrary .o files. It only needs to process the .o
+files generated from C files that cgo writes, and those are much more
+limited in the ELF or other features that they use.
+
+In essence, the _cgo_import.6 file includes the extra linking
+directives that 6l is not sophisticated enough to derive from _all.o
+on its own. Similarly, the _all.o uses dynamic references to real
+system object code because 6l is not sophisticated enough to process
+the real code.
+
+The main benefits of this system are that 6l remains relatively simple
+(it does not need to implement a complete ELF and Mach-O linker) and
+that gcc is not needed after the package is compiled. For example,
+package net uses cgo for access to name resolution functions provided
+by libc. Although gcc is needed to compile package net, gcc is not
+needed to link programs that import package net.
+
+Runtime
+
+When using cgo, Go must not assume that it owns all details of the
+process. In particular it needs to coordinate with C in the use of
+threads and thread-local storage. The runtime package, in its own
+(6c-compiled) C code, declares a few uninitialized (default bss)
+variables:
+
+       bool    runtime·iscgo;
+       void    (*libcgo_thread_start)(void*);
+       void    (*initcgo)(G*);
+
+Any package using cgo imports "runtime/cgo", which provides
+initializations for these variables. It sets iscgo to 1, initcgo to a
+gcc-compiled function that can be called early during program startup,
+and libcgo_thread_start to a gcc-compiled function that can be used to
+create a new thread, in place of the runtime's usual direct system
+calls.
+
+Internal and External Linking
+
+The text above describes "internal" linking, in which 6l parses and
+links host object files (ELF, Mach-O, PE, and so on) into the final
+executable itself. Keeping 6l simple means we cannot possibly
+implement the full semantics of the host linker, so the kinds of
+objects that can be linked directly into the binary is limited (other
+code can only be used as a dynamic library). On the other hand, when
+using internal linking, 6l can generate Go binaries by itself.
+
+In order to allow linking arbitrary object files without requiring
+dynamic libraries, cgo will soon support an "external" linking mode
+too. In external linking mode, 6l does not process any host object
+files. Instead, it collects all the Go code and writes a single go.o
+object file containing it. Then it invokes the host linker (usually
+gcc) to combine the go.o object file and any supporting non-Go code
+into a final executable. External linking avoids the dynamic library
+requirement but introduces a requirement that the host linker be
+present to create such a binary.
+
+Most builds both compile source code and invoke the linker to create a
+binary. When cgo is involved, the compile step already requires gcc, so
+it is not problematic for the link step to require gcc too.
+
+An important exception is builds using a pre-compiled copy of the
+standard library. In particular, package net uses cgo on most systems,
+and we want to preserve the ability to compile pure Go code that
+imports net without requiring gcc to be present at link time. (In this
+case, the dynamic library requirement is less significant, because the
+only library involved is libc.so, which can usually be assumed
+present.)
+
+This conflict between functionality and the gcc requirement means we
+must support both internal and external linking, depending on the
+circumstances: if net is the only cgo-using package, then internal
+linking is probably fine, but if other packages are involved, so that there
+are dependencies on libraries beyond libc, external linking is likely
+to work better. The compilation of a package records the relevant
+information to support both linking modes, leaving the decision
+to be made when linking the final binary.
+
+Linking Directives
+
+In either linking mode, package-specific directives must be passed
+through to 6l. These are communicated by writing #pragma directives
+in a C source file compiled by 6c. The directives are copied into the .6 object file
+and then processed by the linker.
+
+The directives are:
+
+#pragma cgo_import_dynamic <local> [<remote> ["<library>"]]
+
+       In internal linking mode, allow an unresolved reference to
+       <local>, assuming it will be resolved by a dynamic library
+       symbol. The optional <remote> specifies the symbol's name and
+       possibly version in the dynamic library, and the optional "<library>"
+       names the specific library where the symbol should be found.
+
+       In the <remote>, # or @ can be used to introduce a symbol version.
+
+       Examples:
+       #pragma cgo_import_dynamic puts
+       #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5
+       #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
+
+       A side effect of the cgo_import_dynamic directive with a
+       library is to make the final binary depend on that dynamic
+       library. To get the dependency without importing any specific
+       symbols, use _ for local and remote.
+
+       Example:
+       #pragma cgo_import_dynamic _ _ "libc.so.6"
+
+       For compatibility with current versions of SWIG,
+       #pragma dynimport is an alias for #pragma cgo_import_dynamic.
+
+#pragma cgo_dynamic_linker "<path>"
+
+       In internal linking mode, use "<path>" as the dynamic linker
+       in the final binary. This directive is only needed from one
+       package when constructing a binary; by convention it is
+       supplied by runtime/cgo.
+
+       Example:
+       #pragma cgo_dynamic_linker "/lib/ld-linux.so.2"
+
+#pragma cgo_export_dynamic <local> <remote>
+
+       In internal linking mode, put the Go symbol
+       named <local> into the program's exported symbol table as
+       <remote>, so that C code can refer to it by that name. This
+       mechanism makes it possible for C code to call back into Go or
+       to share Go's data.
+
+       For compatibility with current versions of SWIG,
+       #pragma dynexport is an alias for #pragma cgo_export_dynamic.
+
+#pragma cgo_import_static <local>
+
+       In external linking mode, allow unresolved references to
+       <local> in the go.o object file prepared for the host linker,
+       under the assumption that <local> will be supplied by the
+       other object files that will be linked with go.o.
+
+       Example:
+       #pragma cgo_import_static puts_wrapper
+
+#pragma cgo_export_static <local> <remote>
+
+       In external linking mode, put the Go symbol
+       named <local> into the program's exported symbol table as
+       <remote>, so that C code can refer to it by that name. This
+       mechanism makes it possible for C code to call back into Go or
+       to share Go's data.
+
+#pragma cgo_ldflag "<arg>"
+
+       In external linking mode, invoke the host linker (usually gcc)
+       with "<arg>" as a command-line argument following the .o files.
+       Note that the arguments are for "gcc", not "ld".
+
+       Example:
+       #pragma cgo_ldflag "-lpthread"
+       #pragma cgo_ldflag "-L/usr/local/sqlite3/lib"
+
+A package compiled with cgo will include directives for both
+internal and external linking; the linker will select the appropriate
+subset for the chosen linking mode.
+
+Example
+
+As a simple example, consider a package that uses cgo to call C.sin.
+The following code will be generated by cgo:
+
+       // compiled by 6g
+
+       type _Ctype_double float64
+       func _Cfunc_sin(_Ctype_double) _Ctype_double
+
+       // compiled by 6c
+
+       #pragma cgo_import_dynamic sin sin#GLIBC_2.2.5 "libm.so.6"
+
+       #pragma cgo_import_static _cgo_gcc_Cfunc_sin
+       #pragma cgo_ldflag "-lm"
+
+       void _cgo_gcc_Cfunc_sin(void*);
+
+       void
+       Â·_Cfunc_sin(struct{uint8 x[16];}p)
+       {
+               runtime·cgocall(_cgo_gcc_Cfunc_sin, &p);
+       }
+
+       // compiled by gcc, into foo.cgo2.o
+
+       void
+       _cgo_gcc_Cfunc_sin(void *v)
+       {
+               struct {
+                       double p0;
+                       double r;
+               } __attribute__((__packed__)) *a = v;
+               a->r = sin(a->p0);
+       }
+
+What happens at link time depends on whether the final binary is linked
+using the internal or external mode. If other packages are compiled in
+"external only" mode, then the final link will be an external one.
+Otherwise the link will be an internal one.
+
+The directives in the 6c-compiled file are used according to the kind
+of final link used.
+
+In internal mode, 6l itself processes all the host object files, in
+particular foo.cgo2.o. To do so, it uses the cgo_import_dynamic and
+cgo_dynamic_linker directives to learn that the otherwise undefined
+reference to sin in foo.cgo2.o should be rewritten to refer to the
+symbol sin with version GLIBC_2.2.5 from the dynamic library
+"libm.so.6", and the binary should request "/lib/ld-linux.so.2" as its
+runtime dynamic linker.
+
+In external mode, 6l does not process any host object files, in
+particular foo.cgo2.o. It links together the 6g- and 6c-generated
+object files, along with any other Go code, into a go.o file. While
+doing that, 6l will discover that there is no definition for
+_cgo_gcc_Cfunc_sin, referred to by the 6c-compiled source file. This
+is okay, because 6l also processes the cgo_import_static directive and
+knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host
+object file, so 6l does not treat the missing symbol as an error when
+creating go.o. Indeed, the definition for _cgo_gcc_Cfunc_sin will be
+provided to the host linker by foo2.cgo.o, which in turn will need the
+symbol 'sin'. 6l also processes the cgo_ldflag directives, so that it
+knows that the eventual host link command must include the -lm
+argument, so that the host linker will be able to find 'sin' in the
+math library.
+
+6l Command Line Interface
+
+The go command and any other Go-aware build systems invoke 6l
+to link a collection of packages into a single binary. By default, 6l will
+present the same interface it does today:
+
+       6l main.a
+
+produces a file named 6.out, even if 6l does so by invoking the host
+linker in external linking mode.
+
+By default, 6l will decide the linking mode as follows: if the only
+packages using cgo are those on a whitelist of standard library
+packages (net, os/user, runtime/cgo), 6l will use internal linking
+mode. Otherwise, there are non-standard cgo packages involved, and 6l
+will use external linking mode. The first rule means that a build of
+the godoc binary, which uses net but no other cgo, can run without
+needing gcc available. The second rule means that a build of a
+cgo-wrapped library like sqlite3 can generate a standalone executable
+instead of needing to refer to a dynamic library. The specific choice
+can be overridden using a command line flag: 6l -linkmode=internal or
+6l -linkmode=external.
+
+In an external link, 6l will create a temporary directory, write any
+host object files found in package archives to that directory (renamed
+to avoid conflicts), write the go.o file to that directory, and invoke
+the host linker. The default value for the host linker is $CC, split
+into fields, or else "gcc". The specific host linker command line can
+be overridden using command line flags: 6l -extld=clang
+-extldflags='-ggdb -O3'.  If any package in a build includes a .cc or
+other file compiled by the C++ compiler, the go tool will use the
+-extld option to set the host linker to the C++ compiler.
+
+These defaults mean that Go-aware build systems can ignore the linking
+changes and keep running plain '6l' and get reasonable results, but
+they can also control the linking details if desired.
+
+*/
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
new file mode 100644 (file)
index 0000000..f55cfba
--- /dev/null
@@ -0,0 +1,1728 @@
+// 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.
+
+// Annotate Ref in Prog with C types by parsing gcc debug output.
+// Conversion of debug output to Go types.
+
+package main
+
+import (
+       "bytes"
+       "debug/dwarf"
+       "debug/elf"
+       "debug/macho"
+       "debug/pe"
+       "encoding/binary"
+       "errors"
+       "flag"
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "go/token"
+       "os"
+       "strconv"
+       "strings"
+       "unicode"
+       "unicode/utf8"
+)
+
+var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
+var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")
+
+var nameToC = map[string]string{
+       "schar":         "signed char",
+       "uchar":         "unsigned char",
+       "ushort":        "unsigned short",
+       "uint":          "unsigned int",
+       "ulong":         "unsigned long",
+       "longlong":      "long long",
+       "ulonglong":     "unsigned long long",
+       "complexfloat":  "float complex",
+       "complexdouble": "double complex",
+}
+
+// cname returns the C name to use for C.s.
+// The expansions are listed in nameToC and also
+// struct_foo becomes "struct foo", and similarly for
+// union and enum.
+func cname(s string) string {
+       if t, ok := nameToC[s]; ok {
+               return t
+       }
+
+       if strings.HasPrefix(s, "struct_") {
+               return "struct " + s[len("struct_"):]
+       }
+       if strings.HasPrefix(s, "union_") {
+               return "union " + s[len("union_"):]
+       }
+       if strings.HasPrefix(s, "enum_") {
+               return "enum " + s[len("enum_"):]
+       }
+       if strings.HasPrefix(s, "sizeof_") {
+               return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
+       }
+       return s
+}
+
+// DiscardCgoDirectives processes the import C preamble, and discards
+// all #cgo CFLAGS and LDFLAGS directives, so they don't make their
+// way into _cgo_export.h.
+func (f *File) DiscardCgoDirectives() {
+       linesIn := strings.Split(f.Preamble, "\n")
+       linesOut := make([]string, 0, len(linesIn))
+       for _, line := range linesIn {
+               l := strings.TrimSpace(line)
+               if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
+                       linesOut = append(linesOut, line)
+               } else {
+                       linesOut = append(linesOut, "")
+               }
+       }
+       f.Preamble = strings.Join(linesOut, "\n")
+}
+
+// addToFlag appends args to flag.  All flags are later written out onto the
+// _cgo_flags file for the build system to use.
+func (p *Package) addToFlag(flag string, args []string) {
+       p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
+       if flag == "CFLAGS" {
+               // We'll also need these when preprocessing for dwarf information.
+               p.GccOptions = append(p.GccOptions, args...)
+       }
+}
+
+// splitQuoted splits the string s around each instance of one or more consecutive
+// white space characters while taking into account quotes and escaping, and
+// returns an array of substrings of s or an empty list if s contains only white space.
+// Single quotes and double quotes are recognized to prevent splitting within the
+// quoted region, and are removed from the resulting substrings. If a quote in s
+// isn't closed err will be set and r will have the unclosed argument as the
+// last element.  The backslash is used for escaping.
+//
+// For example, the following string:
+//
+//     `a b:"c d" 'e''f'  "g\""`
+//
+// Would be parsed as:
+//
+//     []string{"a", "b:c d", "ef", `g"`}
+//
+func splitQuoted(s string) (r []string, err error) {
+       var args []string
+       arg := make([]rune, len(s))
+       escaped := false
+       quoted := false
+       quote := '\x00'
+       i := 0
+       for _, r := range s {
+               switch {
+               case escaped:
+                       escaped = false
+               case r == '\\':
+                       escaped = true
+                       continue
+               case quote != 0:
+                       if r == quote {
+                               quote = 0
+                               continue
+                       }
+               case r == '"' || r == '\'':
+                       quoted = true
+                       quote = r
+                       continue
+               case unicode.IsSpace(r):
+                       if quoted || i > 0 {
+                               quoted = false
+                               args = append(args, string(arg[:i]))
+                               i = 0
+                       }
+                       continue
+               }
+               arg[i] = r
+               i++
+       }
+       if quoted || i > 0 {
+               args = append(args, string(arg[:i]))
+       }
+       if quote != 0 {
+               err = errors.New("unclosed quote")
+       } else if escaped {
+               err = errors.New("unfinished escaping")
+       }
+       return args, err
+}
+
+var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
+
+func safeName(s string) bool {
+       if s == "" {
+               return false
+       }
+       for i := 0; i < len(s); i++ {
+               if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+                       return false
+               }
+       }
+       return true
+}
+
+// Translate rewrites f.AST, the original Go input, to remove
+// references to the imported package C, replacing them with
+// references to the equivalent Go types, functions, and variables.
+func (p *Package) Translate(f *File) {
+       for _, cref := range f.Ref {
+               // Convert C.ulong to C.unsigned long, etc.
+               cref.Name.C = cname(cref.Name.Go)
+       }
+       p.loadDefines(f)
+       needType := p.guessKinds(f)
+       if len(needType) > 0 {
+               p.loadDWARF(f, needType)
+       }
+       p.rewriteRef(f)
+}
+
+// loadDefines coerces gcc into spitting out the #defines in use
+// in the file f and saves relevant renamings in f.Name[name].Define.
+func (p *Package) loadDefines(f *File) {
+       var b bytes.Buffer
+       b.WriteString(f.Preamble)
+       b.WriteString(builtinProlog)
+       stdout := p.gccDefines(b.Bytes())
+
+       for _, line := range strings.Split(stdout, "\n") {
+               if len(line) < 9 || line[0:7] != "#define" {
+                       continue
+               }
+
+               line = strings.TrimSpace(line[8:])
+
+               var key, val string
+               spaceIndex := strings.Index(line, " ")
+               tabIndex := strings.Index(line, "\t")
+
+               if spaceIndex == -1 && tabIndex == -1 {
+                       continue
+               } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) {
+                       key = line[0:spaceIndex]
+                       val = strings.TrimSpace(line[spaceIndex:])
+               } else {
+                       key = line[0:tabIndex]
+                       val = strings.TrimSpace(line[tabIndex:])
+               }
+
+               if n := f.Name[key]; n != nil {
+                       if *debugDefine {
+                               fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
+                       }
+                       n.Define = val
+               }
+       }
+}
+
+// guessKinds tricks gcc into revealing the kind of each
+// name xxx for the references C.xxx in the Go input.
+// The kind is either a constant, type, or variable.
+func (p *Package) guessKinds(f *File) []*Name {
+       // Determine kinds for names we already know about,
+       // like #defines or 'struct foo', before bothering with gcc.
+       var names, needType []*Name
+       for _, n := range f.Name {
+               // If we've already found this name as a #define
+               // and we can translate it as a constant value, do so.
+               if n.Define != "" {
+                       isConst := false
+                       if _, err := strconv.Atoi(n.Define); err == nil {
+                               isConst = true
+                       } else if n.Define[0] == '"' || n.Define[0] == '\'' {
+                               if _, err := parser.ParseExpr(n.Define); err == nil {
+                                       isConst = true
+                               }
+                       }
+                       if isConst {
+                               n.Kind = "const"
+                               // Turn decimal into hex, just for consistency
+                               // with enum-derived constants.  Otherwise
+                               // in the cgo -godefs output half the constants
+                               // are in hex and half are in whatever the #define used.
+                               i, err := strconv.ParseInt(n.Define, 0, 64)
+                               if err == nil {
+                                       n.Const = fmt.Sprintf("%#x", i)
+                               } else {
+                                       n.Const = n.Define
+                               }
+                               continue
+                       }
+
+                       if isName(n.Define) {
+                               n.C = n.Define
+                       }
+               }
+
+               needType = append(needType, n)
+
+               // If this is a struct, union, or enum type name, no need to guess the kind.
+               if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
+                       n.Kind = "type"
+                       continue
+               }
+
+               // Otherwise, we'll need to find out from gcc.
+               names = append(names, n)
+       }
+
+       // Bypass gcc if there's nothing left to find out.
+       if len(names) == 0 {
+               return needType
+       }
+
+       // Coerce gcc into telling us whether each name is a type, a value, or undeclared.
+       // For names, find out whether they are integer constants.
+       // We used to look at specific warning or error messages here, but that tied the
+       // behavior too closely to specific versions of the compilers.
+       // Instead, arrange that we can infer what we need from only the presence or absence
+       // of an error on a specific line.
+       //
+       // For each name, we generate these lines, where xxx is the index in toSniff plus one.
+       //
+       //      #line xxx "not-declared"
+       //      void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
+       //      #line xxx "not-type"
+       //      void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
+       //      #line xxx "not-const"
+       //      void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
+       //
+       // If we see an error at not-declared:xxx, the corresponding name is not declared.
+       // If we see an error at not-type:xxx, the corresponding name is a type.
+       // If we see an error at not-const:xxx, the corresponding name is not an integer constant.
+       // If we see no errors, we assume the name is an expression but not a constant
+       // (so a variable or a function).
+       //
+       // The specific input forms are chosen so that they are valid C syntax regardless of
+       // whether name denotes a type or an expression.
+
+       var b bytes.Buffer
+       b.WriteString(f.Preamble)
+       b.WriteString(builtinProlog)
+
+       for i, n := range names {
+               fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
+                       "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
+                       "#line %d \"not-type\"\n"+
+                       "void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
+                       "#line %d \"not-const\"\n"+
+                       "void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
+                       i+1, i+1, n.C,
+                       i+1, i+1, n.C,
+                       i+1, i+1, n.C)
+       }
+       fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
+               "int __cgo__1 = __cgo__2;\n")
+
+       stderr := p.gccErrors(b.Bytes())
+       if stderr == "" {
+               fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
+       }
+
+       completed := false
+       sniff := make([]int, len(names))
+       const (
+               notType = 1 << iota
+               notConst
+       )
+       for _, line := range strings.Split(stderr, "\n") {
+               if !strings.Contains(line, ": error:") {
+                       // we only care about errors.
+                       // we tried to turn off warnings on the command line, but one never knows.
+                       continue
+               }
+
+               c1 := strings.Index(line, ":")
+               if c1 < 0 {
+                       continue
+               }
+               c2 := strings.Index(line[c1+1:], ":")
+               if c2 < 0 {
+                       continue
+               }
+               c2 += c1 + 1
+
+               filename := line[:c1]
+               i, _ := strconv.Atoi(line[c1+1 : c2])
+               i--
+               if i < 0 || i >= len(names) {
+                       continue
+               }
+
+               switch filename {
+               case "completed":
+                       // Strictly speaking, there is no guarantee that seeing the error at completed:1
+                       // (at the end of the file) means we've seen all the errors from earlier in the file,
+                       // but usually it does. Certainly if we don't see the completed:1 error, we did
+                       // not get all the errors we expected.
+                       completed = true
+
+               case "not-declared":
+                       error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
+               case "not-type":
+                       sniff[i] |= notType
+               case "not-const":
+                       sniff[i] |= notConst
+               }
+       }
+
+       if !completed {
+               fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
+       }
+
+       for i, n := range names {
+               switch sniff[i] {
+               case 0:
+                       error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
+               case notType:
+                       n.Kind = "const"
+               case notConst:
+                       n.Kind = "type"
+               case notConst | notType:
+                       n.Kind = "not-type"
+               }
+       }
+       if nerrors > 0 {
+               fatalf("unresolved names")
+       }
+
+       needType = append(needType, names...)
+       return needType
+}
+
+// loadDWARF parses the DWARF debug information generated
+// by gcc to learn the details of the constants, variables, and types
+// being referred to as C.xxx.
+func (p *Package) loadDWARF(f *File, names []*Name) {
+       // Extract the types from the DWARF section of an object
+       // from a well-formed C program.  Gcc only generates DWARF info
+       // for symbols in the object file, so it is not enough to print the
+       // preamble and hope the symbols we care about will be there.
+       // Instead, emit
+       //      __typeof__(names[i]) *__cgo__i;
+       // for each entry in names and then dereference the type we
+       // learn for __cgo__i.
+       var b bytes.Buffer
+       b.WriteString(f.Preamble)
+       b.WriteString(builtinProlog)
+       for i, n := range names {
+               fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
+               if n.Kind == "const" {
+                       fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
+               }
+       }
+
+       // Apple's LLVM-based gcc does not include the enumeration
+       // names and values in its DWARF debug output.  In case we're
+       // using such a gcc, create a data block initialized with the values.
+       // We can read them out of the object file.
+       fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
+       for _, n := range names {
+               if n.Kind == "const" {
+                       fmt.Fprintf(&b, "\t%s,\n", n.C)
+               } else {
+                       fmt.Fprintf(&b, "\t0,\n")
+               }
+       }
+       // for the last entry, we can not use 0, otherwise
+       // in case all __cgodebug_data is zero initialized,
+       // LLVM-based gcc will place the it in the __DATA.__common
+       // zero-filled section (our debug/macho doesn't support
+       // this)
+       fmt.Fprintf(&b, "\t1\n")
+       fmt.Fprintf(&b, "};\n")
+
+       d, bo, debugData := p.gccDebug(b.Bytes())
+       enumVal := make([]int64, len(debugData)/8)
+       for i := range enumVal {
+               enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
+       }
+
+       // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
+       types := make([]dwarf.Type, len(names))
+       enums := make([]dwarf.Offset, len(names))
+       nameToIndex := make(map[*Name]int)
+       for i, n := range names {
+               nameToIndex[n] = i
+       }
+       nameToRef := make(map[*Name]*Ref)
+       for _, ref := range f.Ref {
+               nameToRef[ref.Name] = ref
+       }
+       r := d.Reader()
+       for {
+               e, err := r.Next()
+               if err != nil {
+                       fatalf("reading DWARF entry: %s", err)
+               }
+               if e == nil {
+                       break
+               }
+               switch e.Tag {
+               case dwarf.TagEnumerationType:
+                       offset := e.Offset
+                       for {
+                               e, err := r.Next()
+                               if err != nil {
+                                       fatalf("reading DWARF entry: %s", err)
+                               }
+                               if e.Tag == 0 {
+                                       break
+                               }
+                               if e.Tag == dwarf.TagEnumerator {
+                                       entryName := e.Val(dwarf.AttrName).(string)
+                                       if strings.HasPrefix(entryName, "__cgo_enum__") {
+                                               n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):])
+                                               if 0 <= n && n < len(names) {
+                                                       enums[n] = offset
+                                               }
+                                       }
+                               }
+                       }
+               case dwarf.TagVariable:
+                       name, _ := e.Val(dwarf.AttrName).(string)
+                       typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
+                       if name == "" || typOff == 0 {
+                               fatalf("malformed DWARF TagVariable entry")
+                       }
+                       if !strings.HasPrefix(name, "__cgo__") {
+                               break
+                       }
+                       typ, err := d.Type(typOff)
+                       if err != nil {
+                               fatalf("loading DWARF type: %s", err)
+                       }
+                       t, ok := typ.(*dwarf.PtrType)
+                       if !ok || t == nil {
+                               fatalf("internal error: %s has non-pointer type", name)
+                       }
+                       i, err := strconv.Atoi(name[7:])
+                       if err != nil {
+                               fatalf("malformed __cgo__ name: %s", name)
+                       }
+                       if enums[i] != 0 {
+                               t, err := d.Type(enums[i])
+                               if err != nil {
+                                       fatalf("loading DWARF type: %s", err)
+                               }
+                               types[i] = t
+                       } else {
+                               types[i] = t.Type
+                       }
+               }
+               if e.Tag != dwarf.TagCompileUnit {
+                       r.SkipChildren()
+               }
+       }
+
+       // Record types and typedef information.
+       var conv typeConv
+       conv.Init(p.PtrSize, p.IntSize)
+       for i, n := range names {
+               if types[i] == nil {
+                       continue
+               }
+               pos := token.NoPos
+               if ref, ok := nameToRef[n]; ok {
+                       pos = ref.Pos()
+               }
+               f, fok := types[i].(*dwarf.FuncType)
+               if n.Kind != "type" && fok {
+                       n.Kind = "func"
+                       n.FuncType = conv.FuncType(f, pos)
+               } else {
+                       n.Type = conv.Type(types[i], pos)
+                       if enums[i] != 0 && n.Type.EnumValues != nil {
+                               k := fmt.Sprintf("__cgo_enum__%d", i)
+                               n.Kind = "const"
+                               n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
+                               // Remove injected enum to ensure the value will deep-compare
+                               // equally in future loads of the same constant.
+                               delete(n.Type.EnumValues, k)
+                       }
+                       // Prefer debug data over DWARF debug output, if we have it.
+                       if n.Kind == "const" && i < len(enumVal) {
+                               n.Const = fmt.Sprintf("%#x", enumVal[i])
+                       }
+               }
+               conv.FinishType(pos)
+       }
+}
+
+// mangleName does name mangling to translate names
+// from the original Go source files to the names
+// used in the final Go files generated by cgo.
+func (p *Package) mangleName(n *Name) {
+       // When using gccgo variables have to be
+       // exported so that they become global symbols
+       // that the C code can refer to.
+       prefix := "_C"
+       if *gccgo && n.IsVar() {
+               prefix = "C"
+       }
+       n.Mangle = prefix + n.Kind + "_" + n.Go
+}
+
+// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
+// Go equivalents, now that we have figured out the meaning of all
+// the xxx.  In *godefs or *cdefs mode, rewriteRef replaces the names
+// with full definitions instead of mangled names.
+func (p *Package) rewriteRef(f *File) {
+       // Keep a list of all the functions, to remove the ones
+       // only used as expressions and avoid generating bridge
+       // code for them.
+       functions := make(map[string]bool)
+
+       // Assign mangled names.
+       for _, n := range f.Name {
+               if n.Kind == "not-type" {
+                       n.Kind = "var"
+               }
+               if n.Mangle == "" {
+                       p.mangleName(n)
+               }
+               if n.Kind == "func" {
+                       functions[n.Go] = false
+               }
+       }
+
+       // Now that we have all the name types filled in,
+       // scan through the Refs to identify the ones that
+       // are trying to do a ,err call.  Also check that
+       // functions are only used in calls.
+       for _, r := range f.Ref {
+               if r.Name.Kind == "const" && r.Name.Const == "" {
+                       error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
+               }
+               var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
+               switch r.Context {
+               case "call", "call2":
+                       if r.Name.Kind != "func" {
+                               if r.Name.Kind == "type" {
+                                       r.Context = "type"
+                                       expr = r.Name.Type.Go
+                                       break
+                               }
+                               error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
+                               break
+                       }
+                       functions[r.Name.Go] = true
+                       if r.Context == "call2" {
+                               if r.Name.Go == "_CMalloc" {
+                                       error_(r.Pos(), "no two-result form for C.malloc")
+                                       break
+                               }
+                               // Invent new Name for the two-result function.
+                               n := f.Name["2"+r.Name.Go]
+                               if n == nil {
+                                       n = new(Name)
+                                       *n = *r.Name
+                                       n.AddError = true
+                                       n.Mangle = "_C2func_" + n.Go
+                                       f.Name["2"+r.Name.Go] = n
+                               }
+                               expr = ast.NewIdent(n.Mangle)
+                               r.Name = n
+                               break
+                       }
+               case "expr":
+                       if r.Name.Kind == "func" {
+                               // Function is being used in an expression, to e.g. pass around a C function pointer.
+                               // Create a new Name for this Ref which causes the variable to be declared in Go land.
+                               fpName := "fp_" + r.Name.Go
+                               name := f.Name[fpName]
+                               if name == nil {
+                                       name = &Name{
+                                               Go:   fpName,
+                                               C:    r.Name.C,
+                                               Kind: "fpvar",
+                                               Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
+                                       }
+                                       p.mangleName(name)
+                                       f.Name[fpName] = name
+                               }
+                               r.Name = name
+                               expr = ast.NewIdent(name.Mangle)
+                       } else if r.Name.Kind == "type" {
+                               // Okay - might be new(T)
+                               expr = r.Name.Type.Go
+                       } else if r.Name.Kind == "var" {
+                               expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
+                       }
+
+               case "type":
+                       if r.Name.Kind != "type" {
+                               error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
+                       } else if r.Name.Type == nil {
+                               // Use of C.enum_x, C.struct_x or C.union_x without C definition.
+                               // GCC won't raise an error when using pointers to such unknown types.
+                               error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
+                       } else {
+                               expr = r.Name.Type.Go
+                       }
+               default:
+                       if r.Name.Kind == "func" {
+                               error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
+                       }
+               }
+               if *godefs || *cdefs {
+                       // Substitute definition for mangled type name.
+                       if id, ok := expr.(*ast.Ident); ok {
+                               if t := typedef[id.Name]; t != nil {
+                                       expr = t.Go
+                               }
+                               if id.Name == r.Name.Mangle && r.Name.Const != "" {
+                                       expr = ast.NewIdent(r.Name.Const)
+                               }
+                       }
+               }
+
+               // Copy position information from old expr into new expr,
+               // in case expression being replaced is first on line.
+               // See golang.org/issue/6563.
+               pos := (*r.Expr).Pos()
+               switch x := expr.(type) {
+               case *ast.Ident:
+                       expr = &ast.Ident{NamePos: pos, Name: x.Name}
+               }
+
+               *r.Expr = expr
+       }
+
+       // Remove functions only used as expressions, so their respective
+       // bridge functions are not generated.
+       for name, used := range functions {
+               if !used {
+                       delete(f.Name, name)
+               }
+       }
+}
+
+// gccBaseCmd returns the start of the compiler command line.
+// It uses $CC if set, or else $GCC, or else the compiler recorded
+// during the initial build as defaultCC.
+// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
+func (p *Package) gccBaseCmd() []string {
+       // Use $CC if set, since that's what the build uses.
+       if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
+               return ret
+       }
+       // Try $GCC if set, since that's what we used to use.
+       if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
+               return ret
+       }
+       return strings.Fields(defaultCC)
+}
+
+// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
+func (p *Package) gccMachine() []string {
+       switch goarch {
+       case "amd64":
+               return []string{"-m64"}
+       case "386":
+               return []string{"-m32"}
+       case "arm":
+               return []string{"-marm"} // not thumb
+       }
+       return nil
+}
+
+func gccTmp() string {
+       return *objDir + "_cgo_.o"
+}
+
+// gccCmd returns the gcc command line to use for compiling
+// the input.
+func (p *Package) gccCmd() []string {
+       c := append(p.gccBaseCmd(),
+               "-w",          // no warnings
+               "-Wno-error",  // warnings are not errors
+               "-o"+gccTmp(), // write object to tmp
+               "-gdwarf-2",   // generate DWARF v2 debugging symbols
+               "-c",          // do not link
+               "-xc",         // input language is C
+       )
+       if strings.Contains(c[0], "clang") {
+               c = append(c,
+                       "-ferror-limit=0",
+                       // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
+                       // doesn't have -Wno-unneeded-internal-declaration, so we need yet another
+                       // flag to disable the warning. Yes, really good diagnostics, clang.
+                       "-Wno-unknown-warning-option",
+                       "-Wno-unneeded-internal-declaration",
+                       "-Wno-unused-function",
+                       "-Qunused-arguments",
+                       // Clang embeds prototypes for some builtin functions,
+                       // like malloc and calloc, but all size_t parameters are
+                       // incorrectly typed unsigned long. We work around that
+                       // by disabling the builtin functions (this is safe as
+                       // it won't affect the actual compilation of the C code).
+                       // See: http://golang.org/issue/6506.
+                       "-fno-builtin",
+               )
+       }
+
+       c = append(c, p.GccOptions...)
+       c = append(c, p.gccMachine()...)
+       c = append(c, "-") //read input from standard input
+       return c
+}
+
+// gccDebug runs gcc -gdwarf-2 over the C program stdin and
+// returns the corresponding DWARF data and, if present, debug data block.
+func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
+       runGcc(stdin, p.gccCmd())
+
+       isDebugData := func(s string) bool {
+               // Some systems use leading _ to denote non-assembly symbols.
+               return s == "__cgodebug_data" || s == "___cgodebug_data"
+       }
+
+       if f, err := macho.Open(gccTmp()); err == nil {
+               defer f.Close()
+               d, err := f.DWARF()
+               if err != nil {
+                       fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
+               }
+               var data []byte
+               if f.Symtab != nil {
+                       for i := range f.Symtab.Syms {
+                               s := &f.Symtab.Syms[i]
+                               if isDebugData(s.Name) {
+                                       // Found it.  Now find data section.
+                                       if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
+                                               sect := f.Sections[i]
+                                               if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+                                                       if sdat, err := sect.Data(); err == nil {
+                                                               data = sdat[s.Value-sect.Addr:]
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return d, f.ByteOrder, data
+       }
+
+       if f, err := elf.Open(gccTmp()); err == nil {
+               defer f.Close()
+               d, err := f.DWARF()
+               if err != nil {
+                       fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
+               }
+               var data []byte
+               symtab, err := f.Symbols()
+               if err == nil {
+                       for i := range symtab {
+                               s := &symtab[i]
+                               if isDebugData(s.Name) {
+                                       // Found it.  Now find data section.
+                                       if i := int(s.Section); 0 <= i && i < len(f.Sections) {
+                                               sect := f.Sections[i]
+                                               if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+                                                       if sdat, err := sect.Data(); err == nil {
+                                                               data = sdat[s.Value-sect.Addr:]
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return d, f.ByteOrder, data
+       }
+
+       if f, err := pe.Open(gccTmp()); err == nil {
+               defer f.Close()
+               d, err := f.DWARF()
+               if err != nil {
+                       fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
+               }
+               var data []byte
+               for _, s := range f.Symbols {
+                       if isDebugData(s.Name) {
+                               if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
+                                       sect := f.Sections[i]
+                                       if s.Value < sect.Size {
+                                               if sdat, err := sect.Data(); err == nil {
+                                                       data = sdat[s.Value:]
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return d, binary.LittleEndian, data
+       }
+
+       fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
+       panic("not reached")
+}
+
+// gccDefines runs gcc -E -dM -xc - over the C program stdin
+// and returns the corresponding standard output, which is the
+// #defines that gcc encountered while processing the input
+// and its included files.
+func (p *Package) gccDefines(stdin []byte) string {
+       base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
+       base = append(base, p.gccMachine()...)
+       stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
+       return stdout
+}
+
+// gccErrors runs gcc over the C program stdin and returns
+// the errors that gcc prints.  That is, this function expects
+// gcc to fail.
+func (p *Package) gccErrors(stdin []byte) string {
+       // TODO(rsc): require failure
+       args := p.gccCmd()
+
+       if *debugGcc {
+               fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
+               os.Stderr.Write(stdin)
+               fmt.Fprint(os.Stderr, "EOF\n")
+       }
+       stdout, stderr, _ := run(stdin, args)
+       if *debugGcc {
+               os.Stderr.Write(stdout)
+               os.Stderr.Write(stderr)
+       }
+       return string(stderr)
+}
+
+// runGcc runs the gcc command line args with stdin on standard input.
+// If the command exits with a non-zero exit status, runGcc prints
+// details about what was run and exits.
+// Otherwise runGcc returns the data written to standard output and standard error.
+// Note that for some of the uses we expect useful data back
+// on standard error, but for those uses gcc must still exit 0.
+func runGcc(stdin []byte, args []string) (string, string) {
+       if *debugGcc {
+               fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
+               os.Stderr.Write(stdin)
+               fmt.Fprint(os.Stderr, "EOF\n")
+       }
+       stdout, stderr, ok := run(stdin, args)
+       if *debugGcc {
+               os.Stderr.Write(stdout)
+               os.Stderr.Write(stderr)
+       }
+       if !ok {
+               os.Stderr.Write(stderr)
+               os.Exit(2)
+       }
+       return string(stdout), string(stderr)
+}
+
+// A typeConv is a translator from dwarf types to Go types
+// with equivalent memory layout.
+type typeConv struct {
+       // Cache of already-translated or in-progress types.
+       m       map[dwarf.Type]*Type
+       typedef map[string]ast.Expr
+
+       // Map from types to incomplete pointers to those types.
+       ptrs map[dwarf.Type][]*Type
+
+       // Fields to be processed by godefsField after completing pointers.
+       todoFlds [][]*ast.Field
+
+       // Predeclared types.
+       bool                                   ast.Expr
+       byte                                   ast.Expr // denotes padding
+       int8, int16, int32, int64              ast.Expr
+       uint8, uint16, uint32, uint64, uintptr ast.Expr
+       float32, float64                       ast.Expr
+       complex64, complex128                  ast.Expr
+       void                                   ast.Expr
+       unsafePointer                          ast.Expr
+       string                                 ast.Expr
+       goVoid                                 ast.Expr // _Ctype_void, denotes C's void
+
+       ptrSize int64
+       intSize int64
+}
+
+var tagGen int
+var typedef = make(map[string]*Type)
+var goIdent = make(map[string]*ast.Ident)
+
+func (c *typeConv) Init(ptrSize, intSize int64) {
+       c.ptrSize = ptrSize
+       c.intSize = intSize
+       c.m = make(map[dwarf.Type]*Type)
+       c.ptrs = make(map[dwarf.Type][]*Type)
+       c.bool = c.Ident("bool")
+       c.byte = c.Ident("byte")
+       c.int8 = c.Ident("int8")
+       c.int16 = c.Ident("int16")
+       c.int32 = c.Ident("int32")
+       c.int64 = c.Ident("int64")
+       c.uint8 = c.Ident("uint8")
+       c.uint16 = c.Ident("uint16")
+       c.uint32 = c.Ident("uint32")
+       c.uint64 = c.Ident("uint64")
+       c.uintptr = c.Ident("uintptr")
+       c.float32 = c.Ident("float32")
+       c.float64 = c.Ident("float64")
+       c.complex64 = c.Ident("complex64")
+       c.complex128 = c.Ident("complex128")
+       c.unsafePointer = c.Ident("unsafe.Pointer")
+       c.void = c.Ident("void")
+       c.string = c.Ident("string")
+       c.goVoid = c.Ident("_Ctype_void")
+}
+
+// base strips away qualifiers and typedefs to get the underlying type
+func base(dt dwarf.Type) dwarf.Type {
+       for {
+               if d, ok := dt.(*dwarf.QualType); ok {
+                       dt = d.Type
+                       continue
+               }
+               if d, ok := dt.(*dwarf.TypedefType); ok {
+                       dt = d.Type
+                       continue
+               }
+               break
+       }
+       return dt
+}
+
+// Map from dwarf text names to aliases we use in package "C".
+var dwarfToName = map[string]string{
+       "long int":               "long",
+       "long unsigned int":      "ulong",
+       "unsigned int":           "uint",
+       "short unsigned int":     "ushort",
+       "short int":              "short",
+       "long long int":          "longlong",
+       "long long unsigned int": "ulonglong",
+       "signed char":            "schar",
+       "float complex":          "complexfloat",
+       "double complex":         "complexdouble",
+}
+
+const signedDelta = 64
+
+// String returns the current type representation.  Format arguments
+// are assembled within this method so that any changes in mutable
+// values are taken into account.
+func (tr *TypeRepr) String() string {
+       if len(tr.Repr) == 0 {
+               return ""
+       }
+       if len(tr.FormatArgs) == 0 {
+               return tr.Repr
+       }
+       return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
+}
+
+// Empty returns true if the result of String would be "".
+func (tr *TypeRepr) Empty() bool {
+       return len(tr.Repr) == 0
+}
+
+// Set modifies the type representation.
+// If fargs are provided, repr is used as a format for fmt.Sprintf.
+// Otherwise, repr is used unprocessed as the type representation.
+func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
+       tr.Repr = repr
+       tr.FormatArgs = fargs
+}
+
+// FinishType completes any outstanding type mapping work.
+// In particular, it resolves incomplete pointer types and also runs
+// godefsFields on any new struct types.
+func (c *typeConv) FinishType(pos token.Pos) {
+       // Completing one pointer type might produce more to complete.
+       // Keep looping until they're all done.
+       for len(c.ptrs) > 0 {
+               for dtype := range c.ptrs {
+                       // Note Type might invalidate c.ptrs[dtype].
+                       t := c.Type(dtype, pos)
+                       for _, ptr := range c.ptrs[dtype] {
+                               ptr.Go.(*ast.StarExpr).X = t.Go
+                               ptr.C.Set("%s*", t.C)
+                       }
+                       delete(c.ptrs, dtype)
+               }
+       }
+
+       // Now that pointer types are completed, we can invoke godefsFields
+       // to rewrite struct definitions.
+       for _, fld := range c.todoFlds {
+               godefsFields(fld)
+       }
+       c.todoFlds = nil
+}
+
+// Type returns a *Type with the same memory layout as
+// dtype when used as the type of a variable or a struct field.
+func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
+       if t, ok := c.m[dtype]; ok {
+               if t.Go == nil {
+                       fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
+               }
+               return t
+       }
+
+       // clang won't generate DW_AT_byte_size for pointer types,
+       // so we have to fix it here.
+       if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 {
+               dt.ByteSize = c.ptrSize
+       }
+
+       t := new(Type)
+       t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
+       t.Align = -1
+       t.C = &TypeRepr{Repr: dtype.Common().Name}
+       c.m[dtype] = t
+
+       switch dt := dtype.(type) {
+       default:
+               fatalf("%s: unexpected type: %s", lineno(pos), dtype)
+
+       case *dwarf.AddrType:
+               if t.Size != c.ptrSize {
+                       fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
+               }
+               t.Go = c.uintptr
+               t.Align = t.Size
+
+       case *dwarf.ArrayType:
+               if dt.StrideBitSize > 0 {
+                       // Cannot represent bit-sized elements in Go.
+                       t.Go = c.Opaque(t.Size)
+                       break
+               }
+               sub := c.Type(dt.Type, pos)
+               t.Align = sub.Align
+               t.Go = &ast.ArrayType{
+                       Len: c.intExpr(dt.Count),
+                       Elt: sub.Go,
+               }
+               t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
+
+       case *dwarf.BoolType:
+               t.Go = c.bool
+               t.Align = 1
+
+       case *dwarf.CharType:
+               if t.Size != 1 {
+                       fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
+               }
+               t.Go = c.int8
+               t.Align = 1
+
+       case *dwarf.EnumType:
+               if t.Align = t.Size; t.Align >= c.ptrSize {
+                       t.Align = c.ptrSize
+               }
+               t.C.Set("enum " + dt.EnumName)
+               signed := 0
+               t.EnumValues = make(map[string]int64)
+               for _, ev := range dt.Val {
+                       t.EnumValues[ev.Name] = ev.Val
+                       if ev.Val < 0 {
+                               signed = signedDelta
+                       }
+               }
+               switch t.Size + int64(signed) {
+               default:
+                       fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
+               case 1:
+                       t.Go = c.uint8
+               case 2:
+                       t.Go = c.uint16
+               case 4:
+                       t.Go = c.uint32
+               case 8:
+                       t.Go = c.uint64
+               case 1 + signedDelta:
+                       t.Go = c.int8
+               case 2 + signedDelta:
+                       t.Go = c.int16
+               case 4 + signedDelta:
+                       t.Go = c.int32
+               case 8 + signedDelta:
+                       t.Go = c.int64
+               }
+
+       case *dwarf.FloatType:
+               switch t.Size {
+               default:
+                       fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
+               case 4:
+                       t.Go = c.float32
+               case 8:
+                       t.Go = c.float64
+               }
+               if t.Align = t.Size; t.Align >= c.ptrSize {
+                       t.Align = c.ptrSize
+               }
+
+       case *dwarf.ComplexType:
+               switch t.Size {
+               default:
+                       fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
+               case 8:
+                       t.Go = c.complex64
+               case 16:
+                       t.Go = c.complex128
+               }
+               if t.Align = t.Size; t.Align >= c.ptrSize {
+                       t.Align = c.ptrSize
+               }
+
+       case *dwarf.FuncType:
+               // No attempt at translation: would enable calls
+               // directly between worlds, but we need to moderate those.
+               t.Go = c.uintptr
+               t.Align = c.ptrSize
+
+       case *dwarf.IntType:
+               if dt.BitSize > 0 {
+                       fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
+               }
+               switch t.Size {
+               default:
+                       fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
+               case 1:
+                       t.Go = c.int8
+               case 2:
+                       t.Go = c.int16
+               case 4:
+                       t.Go = c.int32
+               case 8:
+                       t.Go = c.int64
+               }
+               if t.Align = t.Size; t.Align >= c.ptrSize {
+                       t.Align = c.ptrSize
+               }
+
+       case *dwarf.PtrType:
+               t.Align = c.ptrSize
+
+               // Translate void* as unsafe.Pointer
+               if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
+                       t.Go = c.unsafePointer
+                       t.C.Set("void*")
+                       break
+               }
+
+               // Placeholder initialization; completed in FinishType.
+               t.Go = &ast.StarExpr{}
+               t.C.Set("<incomplete>*")
+               c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
+
+       case *dwarf.QualType:
+               // Ignore qualifier.
+               t = c.Type(dt.Type, pos)
+               c.m[dtype] = t
+               return t
+
+       case *dwarf.StructType:
+               // Convert to Go struct, being careful about alignment.
+               // Have to give it a name to simulate C "struct foo" references.
+               tag := dt.StructName
+               if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
+                       break
+               }
+               if tag == "" {
+                       tag = "__" + strconv.Itoa(tagGen)
+                       tagGen++
+               } else if t.C.Empty() {
+                       t.C.Set(dt.Kind + " " + tag)
+               }
+               name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
+               t.Go = name // publish before recursive calls
+               goIdent[name.Name] = name
+               if dt.ByteSize < 0 {
+                       // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
+                       // so execute the basic things that the struct case would do
+                       // other than try to determine a Go representation.
+                       tt := *t
+                       tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
+                       tt.Go = c.Ident("struct{}")
+                       typedef[name.Name] = &tt
+                       break
+               }
+               switch dt.Kind {
+               case "class", "union":
+                       t.Go = c.Opaque(t.Size)
+                       if t.C.Empty() {
+                               t.C.Set("__typeof__(unsigned char[%d])", t.Size)
+                       }
+                       t.Align = 1 // TODO: should probably base this on field alignment.
+                       typedef[name.Name] = t
+               case "struct":
+                       g, csyntax, align := c.Struct(dt, pos)
+                       if t.C.Empty() {
+                               t.C.Set(csyntax)
+                       }
+                       t.Align = align
+                       tt := *t
+                       if tag != "" {
+                               tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
+                       }
+                       tt.Go = g
+                       typedef[name.Name] = &tt
+               }
+
+       case *dwarf.TypedefType:
+               // Record typedef for printing.
+               if dt.Name == "_GoString_" {
+                       // Special C name for Go string type.
+                       // Knows string layout used by compilers: pointer plus length,
+                       // which rounds up to 2 pointers after alignment.
+                       t.Go = c.string
+                       t.Size = c.ptrSize * 2
+                       t.Align = c.ptrSize
+                       break
+               }
+               if dt.Name == "_GoBytes_" {
+                       // Special C name for Go []byte type.
+                       // Knows slice layout used by compilers: pointer, length, cap.
+                       t.Go = c.Ident("[]byte")
+                       t.Size = c.ptrSize + 4 + 4
+                       t.Align = c.ptrSize
+                       break
+               }
+               name := c.Ident("_Ctype_" + dt.Name)
+               goIdent[name.Name] = name
+               sub := c.Type(dt.Type, pos)
+               t.Go = name
+               t.Size = sub.Size
+               t.Align = sub.Align
+               oldType := typedef[name.Name]
+               if oldType == nil {
+                       tt := *t
+                       tt.Go = sub.Go
+                       typedef[name.Name] = &tt
+               }
+
+               // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
+               // use that as the Go form for this typedef too, so that the typedef will be interchangeable
+               // with the base type.
+               // In -godefs and -cdefs mode, do this for all typedefs.
+               if isStructUnionClass(sub.Go) || *godefs || *cdefs {
+                       t.Go = sub.Go
+
+                       if isStructUnionClass(sub.Go) {
+                               // Use the typedef name for C code.
+                               typedef[sub.Go.(*ast.Ident).Name].C = t.C
+                       }
+
+                       // If we've seen this typedef before, and it
+                       // was an anonymous struct/union/class before
+                       // too, use the old definition.
+                       // TODO: it would be safer to only do this if
+                       // we verify that the types are the same.
+                       if oldType != nil && isStructUnionClass(oldType.Go) {
+                               t.Go = oldType.Go
+                       }
+               }
+
+       case *dwarf.UcharType:
+               if t.Size != 1 {
+                       fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
+               }
+               t.Go = c.uint8
+               t.Align = 1
+
+       case *dwarf.UintType:
+               if dt.BitSize > 0 {
+                       fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
+               }
+               switch t.Size {
+               default:
+                       fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
+               case 1:
+                       t.Go = c.uint8
+               case 2:
+                       t.Go = c.uint16
+               case 4:
+                       t.Go = c.uint32
+               case 8:
+                       t.Go = c.uint64
+               }
+               if t.Align = t.Size; t.Align >= c.ptrSize {
+                       t.Align = c.ptrSize
+               }
+
+       case *dwarf.VoidType:
+               t.Go = c.goVoid
+               t.C.Set("void")
+               t.Align = 1
+       }
+
+       switch dtype.(type) {
+       case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
+               s := dtype.Common().Name
+               if s != "" {
+                       if ss, ok := dwarfToName[s]; ok {
+                               s = ss
+                       }
+                       s = strings.Join(strings.Split(s, " "), "") // strip spaces
+                       name := c.Ident("_Ctype_" + s)
+                       tt := *t
+                       typedef[name.Name] = &tt
+                       if !*godefs && !*cdefs {
+                               t.Go = name
+                       }
+               }
+       }
+
+       if t.Size <= 0 {
+               // Clang does not record the size of a pointer in its DWARF entry,
+               // so if dtype is an array, the call to dtype.Size at the top of the function
+               // computed the size as the array length * 0 = 0.
+               // The type switch called Type (this function) recursively on the pointer
+               // entry, and the code near the top of the function updated the size to
+               // be correct, so calling dtype.Size again will produce the correct value.
+               t.Size = dtype.Size()
+               if t.Size < 0 {
+                       // Unsized types are [0]byte, unless they're typedefs of other types
+                       // or structs with tags.
+                       // if so, use the name we've already defined.
+                       t.Size = 0
+                       switch dt := dtype.(type) {
+                       case *dwarf.TypedefType:
+                               // ok
+                       case *dwarf.StructType:
+                               if dt.StructName != "" {
+                                       break
+                               }
+                               t.Go = c.Opaque(0)
+                       default:
+                               t.Go = c.Opaque(0)
+                       }
+                       if t.C.Empty() {
+                               t.C.Set("void")
+                       }
+                       return t
+               }
+       }
+
+       if t.C.Empty() {
+               fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
+       }
+
+       return t
+}
+
+// isStructUnionClass reports whether the type described by the Go syntax x
+// is a struct, union, or class with a tag.
+func isStructUnionClass(x ast.Expr) bool {
+       id, ok := x.(*ast.Ident)
+       if !ok {
+               return false
+       }
+       name := id.Name
+       return strings.HasPrefix(name, "_Ctype_struct_") ||
+               strings.HasPrefix(name, "_Ctype_union_") ||
+               strings.HasPrefix(name, "_Ctype_class_")
+}
+
+// FuncArg returns a Go type with the same memory layout as
+// dtype when used as the type of a C function argument.
+func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
+       t := c.Type(dtype, pos)
+       switch dt := dtype.(type) {
+       case *dwarf.ArrayType:
+               // Arrays are passed implicitly as pointers in C.
+               // In Go, we must be explicit.
+               tr := &TypeRepr{}
+               tr.Set("%s*", t.C)
+               return &Type{
+                       Size:  c.ptrSize,
+                       Align: c.ptrSize,
+                       Go:    &ast.StarExpr{X: t.Go},
+                       C:     tr,
+               }
+       case *dwarf.TypedefType:
+               // C has much more relaxed rules than Go for
+               // implicit type conversions.  When the parameter
+               // is type T defined as *X, simulate a little of the
+               // laxness of C by making the argument *X instead of T.
+               if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
+                       // Unless the typedef happens to point to void* since
+                       // Go has special rules around using unsafe.Pointer.
+                       if _, void := base(ptr.Type).(*dwarf.VoidType); void {
+                               break
+                       }
+
+                       t = c.Type(ptr, pos)
+                       if t == nil {
+                               return nil
+                       }
+
+                       // Remember the C spelling, in case the struct
+                       // has __attribute__((unavailable)) on it.  See issue 2888.
+                       t.Typedef = dt.Name
+               }
+       }
+       return t
+}
+
+// FuncType returns the Go type analogous to dtype.
+// There is no guarantee about matching memory layout.
+func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
+       p := make([]*Type, len(dtype.ParamType))
+       gp := make([]*ast.Field, len(dtype.ParamType))
+       for i, f := range dtype.ParamType {
+               // gcc's DWARF generator outputs a single DotDotDotType parameter for
+               // function pointers that specify no parameters (e.g. void
+               // (*__cgo_0)()).  Treat this special case as void.  This case is
+               // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
+               // legal).
+               if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
+                       p, gp = nil, nil
+                       break
+               }
+               p[i] = c.FuncArg(f, pos)
+               gp[i] = &ast.Field{Type: p[i].Go}
+       }
+       var r *Type
+       var gr []*ast.Field
+       if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
+               gr = []*ast.Field{{Type: c.goVoid}}
+       } else if dtype.ReturnType != nil {
+               r = c.Type(dtype.ReturnType, pos)
+               gr = []*ast.Field{{Type: r.Go}}
+       }
+       return &FuncType{
+               Params: p,
+               Result: r,
+               Go: &ast.FuncType{
+                       Params:  &ast.FieldList{List: gp},
+                       Results: &ast.FieldList{List: gr},
+               },
+       }
+}
+
+// Identifier
+func (c *typeConv) Ident(s string) *ast.Ident {
+       return ast.NewIdent(s)
+}
+
+// Opaque type of n bytes.
+func (c *typeConv) Opaque(n int64) ast.Expr {
+       return &ast.ArrayType{
+               Len: c.intExpr(n),
+               Elt: c.byte,
+       }
+}
+
+// Expr for integer n.
+func (c *typeConv) intExpr(n int64) ast.Expr {
+       return &ast.BasicLit{
+               Kind:  token.INT,
+               Value: strconv.FormatInt(n, 10),
+       }
+}
+
+// Add padding of given size to fld.
+func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
+       n := len(fld)
+       fld = fld[0 : n+1]
+       fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
+       return fld
+}
+
+// Struct conversion: return Go and (6g) C syntax for type.
+func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
+       var buf bytes.Buffer
+       buf.WriteString("struct {")
+       fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
+       off := int64(0)
+
+       // Rename struct fields that happen to be named Go keywords into
+       // _{keyword}.  Create a map from C ident -> Go ident.  The Go ident will
+       // be mangled.  Any existing identifier that already has the same name on
+       // the C-side will cause the Go-mangled version to be prefixed with _.
+       // (e.g. in a struct with fields '_type' and 'type', the latter would be
+       // rendered as '__type' in Go).
+       ident := make(map[string]string)
+       used := make(map[string]bool)
+       for _, f := range dt.Field {
+               ident[f.Name] = f.Name
+               used[f.Name] = true
+       }
+
+       if !*godefs && !*cdefs {
+               for cid, goid := range ident {
+                       if token.Lookup(goid).IsKeyword() {
+                               // Avoid keyword
+                               goid = "_" + goid
+
+                               // Also avoid existing fields
+                               for _, exist := used[goid]; exist; _, exist = used[goid] {
+                                       goid = "_" + goid
+                               }
+
+                               used[goid] = true
+                               ident[cid] = goid
+                       }
+               }
+       }
+
+       anon := 0
+       for _, f := range dt.Field {
+               if f.ByteOffset > off {
+                       fld = c.pad(fld, f.ByteOffset-off)
+                       off = f.ByteOffset
+               }
+               t := c.Type(f.Type, pos)
+               tgo := t.Go
+               size := t.Size
+               talign := t.Align
+               if f.BitSize > 0 {
+                       if f.BitSize%8 != 0 {
+                               continue
+                       }
+                       size = f.BitSize / 8
+                       name := tgo.(*ast.Ident).String()
+                       if strings.HasPrefix(name, "int") {
+                               name = "int"
+                       } else {
+                               name = "uint"
+                       }
+                       tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
+                       talign = size
+               }
+
+               if talign > 0 && f.ByteOffset%talign != 0 {
+                       // Drop misaligned fields, the same way we drop integer bit fields.
+                       // The goal is to make available what can be made available.
+                       // Otherwise one bad and unneeded field in an otherwise okay struct
+                       // makes the whole program not compile. Much of the time these
+                       // structs are in system headers that cannot be corrected.
+                       continue
+               }
+               n := len(fld)
+               fld = fld[0 : n+1]
+               name := f.Name
+               if name == "" {
+                       name = fmt.Sprintf("anon%d", anon)
+                       anon++
+                       ident[name] = name
+               }
+               fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
+               off += size
+               buf.WriteString(t.C.String())
+               buf.WriteString(" ")
+               buf.WriteString(name)
+               buf.WriteString("; ")
+               if talign > align {
+                       align = talign
+               }
+       }
+       if off < dt.ByteSize {
+               fld = c.pad(fld, dt.ByteSize-off)
+               off = dt.ByteSize
+       }
+       if off != dt.ByteSize {
+               fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
+       }
+       buf.WriteString("}")
+       csyntax = buf.String()
+
+       if *godefs || *cdefs {
+               c.todoFlds = append(c.todoFlds, fld)
+       }
+       expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
+       return
+}
+
+func upper(s string) string {
+       if s == "" {
+               return ""
+       }
+       r, size := utf8.DecodeRuneInString(s)
+       if r == '_' {
+               return "X" + s
+       }
+       return string(unicode.ToUpper(r)) + s[size:]
+}
+
+// godefsFields rewrites field names for use in Go or C definitions.
+// It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
+// converts names to upper case, and rewrites _ into Pad_godefs_n,
+// so that all fields are exported.
+func godefsFields(fld []*ast.Field) {
+       prefix := fieldPrefix(fld)
+       npad := 0
+       for _, f := range fld {
+               for _, n := range f.Names {
+                       if n.Name != prefix {
+                               n.Name = strings.TrimPrefix(n.Name, prefix)
+                       }
+                       if n.Name == "_" {
+                               // Use exported name instead.
+                               n.Name = "Pad_cgo_" + strconv.Itoa(npad)
+                               npad++
+                       }
+                       if !*cdefs {
+                               n.Name = upper(n.Name)
+                       }
+               }
+               p := &f.Type
+               t := *p
+               if star, ok := t.(*ast.StarExpr); ok {
+                       star = &ast.StarExpr{X: star.X}
+                       *p = star
+                       p = &star.X
+                       t = *p
+               }
+               if id, ok := t.(*ast.Ident); ok {
+                       if id.Name == "unsafe.Pointer" {
+                               *p = ast.NewIdent("*byte")
+                       }
+               }
+       }
+}
+
+// fieldPrefix returns the prefix that should be removed from all the
+// field names when generating the C or Go code.  For generated
+// C, we leave the names as is (tv_sec, tv_usec), since that's what
+// people are used to seeing in C.  For generated Go code, such as
+// package syscall's data structures, we drop a common prefix
+// (so sec, usec, which will get turned into Sec, Usec for exporting).
+func fieldPrefix(fld []*ast.Field) string {
+       if *cdefs {
+               return ""
+       }
+       prefix := ""
+       for _, f := range fld {
+               for _, n := range f.Names {
+                       // Ignore field names that don't have the prefix we're
+                       // looking for.  It is common in C headers to have fields
+                       // named, say, _pad in an otherwise prefixed header.
+                       // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
+                       // still want to remove the tv_ prefix.
+                       // The check for "orig_" here handles orig_eax in the
+                       // x86 ptrace register sets, which otherwise have all fields
+                       // with reg_ prefixes.
+                       if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
+                               continue
+                       }
+                       i := strings.Index(n.Name, "_")
+                       if i < 0 {
+                               continue
+                       }
+                       if prefix == "" {
+                               prefix = n.Name[:i+1]
+                       } else if prefix != n.Name[:i+1] {
+                               return ""
+                       }
+               }
+       }
+       return prefix
+}
diff --git a/libgo/go/cmd/cgo/godefs.go b/libgo/go/cmd/cgo/godefs.go
new file mode 100644 (file)
index 0000000..ce5ac27
--- /dev/null
@@ -0,0 +1,294 @@
+// 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 (
+       "bytes"
+       "fmt"
+       "go/ast"
+       "go/printer"
+       "go/token"
+       "os"
+       "strings"
+)
+
+// godefs returns the output for -godefs mode.
+func (p *Package) godefs(f *File, srcfile string) string {
+       var buf bytes.Buffer
+
+       fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n")
+       fmt.Fprintf(&buf, "// %s\n", strings.Join(os.Args, " "))
+       fmt.Fprintf(&buf, "\n")
+
+       override := make(map[string]string)
+
+       // Allow source file to specify override mappings.
+       // For example, the socket data structures refer
+       // to in_addr and in_addr6 structs but we want to be
+       // able to treat them as byte arrays, so the godefs
+       // inputs in package syscall say
+       //
+       //      // +godefs map struct_in_addr [4]byte
+       //      // +godefs map struct_in_addr6 [16]byte
+       //
+       for _, g := range f.Comments {
+               for _, c := range g.List {
+                       i := strings.Index(c.Text, "+godefs map")
+                       if i < 0 {
+                               continue
+                       }
+                       s := strings.TrimSpace(c.Text[i+len("+godefs map"):])
+                       i = strings.Index(s, " ")
+                       if i < 0 {
+                               fmt.Fprintf(os.Stderr, "invalid +godefs map comment: %s\n", c.Text)
+                               continue
+                       }
+                       override["_Ctype_"+strings.TrimSpace(s[:i])] = strings.TrimSpace(s[i:])
+               }
+       }
+       for _, n := range f.Name {
+               if s := override[n.Go]; s != "" {
+                       override[n.Mangle] = s
+               }
+       }
+
+       // Otherwise, if the source file says type T C.whatever,
+       // use "T" as the mangling of C.whatever,
+       // except in the definition (handled at end of function).
+       refName := make(map[*ast.Expr]*Name)
+       for _, r := range f.Ref {
+               refName[r.Expr] = r.Name
+       }
+       for _, d := range f.AST.Decls {
+               d, ok := d.(*ast.GenDecl)
+               if !ok || d.Tok != token.TYPE {
+                       continue
+               }
+               for _, s := range d.Specs {
+                       s := s.(*ast.TypeSpec)
+                       n := refName[&s.Type]
+                       if n != nil && n.Mangle != "" {
+                               override[n.Mangle] = s.Name.Name
+                       }
+               }
+       }
+
+       // Extend overrides using typedefs:
+       // If we know that C.xxx should format as T
+       // and xxx is a typedef for yyy, make C.yyy format as T.
+       for typ, def := range typedef {
+               if new := override[typ]; new != "" {
+                       if id, ok := def.Go.(*ast.Ident); ok {
+                               override[id.Name] = new
+                       }
+               }
+       }
+
+       // Apply overrides.
+       for old, new := range override {
+               if id := goIdent[old]; id != nil {
+                       id.Name = new
+               }
+       }
+
+       // Any names still using the _C syntax are not going to compile,
+       // although in general we don't know whether they all made it
+       // into the file, so we can't warn here.
+       //
+       // The most common case is union types, which begin with
+       // _Ctype_union and for which typedef[name] is a Go byte
+       // array of the appropriate size (such as [4]byte).
+       // Substitute those union types with byte arrays.
+       for name, id := range goIdent {
+               if id.Name == name && strings.Contains(name, "_Ctype_union") {
+                       if def := typedef[name]; def != nil {
+                               id.Name = gofmt(def)
+                       }
+               }
+       }
+
+       conf.Fprint(&buf, fset, f.AST)
+
+       return buf.String()
+}
+
+// cdefs returns the output for -cdefs mode.
+// The easiest way to do this is to translate the godefs Go to C.
+func (p *Package) cdefs(f *File, srcfile string) string {
+       godefsOutput := p.godefs(f, srcfile)
+
+       lines := strings.Split(godefsOutput, "\n")
+       lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"
+
+       for i, line := range lines {
+               lines[i] = strings.TrimSpace(line)
+       }
+
+       var out bytes.Buffer
+       printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) }
+
+       didTypedef := false
+       for i := 0; i < len(lines); i++ {
+               line := lines[i]
+
+               // Delete
+               //      package x
+               if strings.HasPrefix(line, "package ") {
+                       continue
+               }
+
+               // Convert
+               //      const (
+               //              A = 1
+               //              B = 2
+               //      )
+               //
+               // to
+               //
+               //      enum {
+               //              A = 1,
+               //              B = 2,
+               //      };
+               if line == "const (" {
+                       printf("enum {\n")
+                       for i++; i < len(lines) && lines[i] != ")"; i++ {
+                               line = lines[i]
+                               if line != "" {
+                                       printf("\t%s,", line)
+                               }
+                               printf("\n")
+                       }
+                       printf("};\n")
+                       continue
+               }
+
+               // Convert
+               //      const A = 1
+               // to
+               //      enum { A = 1 };
+               if strings.HasPrefix(line, "const ") {
+                       printf("enum { %s };\n", line[len("const "):])
+                       continue
+               }
+
+               // On first type definition, typedef all the structs
+               // in case there are dependencies between them.
+               if !didTypedef && strings.HasPrefix(line, "type ") {
+                       didTypedef = true
+                       for _, line := range lines {
+                               line = strings.TrimSpace(line)
+                               if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
+                                       s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {")
+                                       printf("typedef struct %s %s;\n", s, s)
+                               }
+                       }
+                       printf("\n")
+                       printf("#pragma pack on\n")
+                       printf("\n")
+               }
+
+               // Convert
+               //      type T struct {
+               //              X int64
+               //              Y *int32
+               //              Z [4]byte
+               //      }
+               //
+               // to
+               //
+               //      struct T {
+               //              int64 X;
+               //              int32 *Y;
+               //              byte Z[4];
+               //      }
+               if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
+                       if len(lines) > i+1 && lines[i+1] == "}" {
+                               // do not output empty struct
+                               i++
+                               continue
+                       }
+                       s := line[len("type ") : len(line)-len(" struct {")]
+                       printf("struct %s {\n", s)
+                       for i++; i < len(lines) && lines[i] != "}"; i++ {
+                               line := lines[i]
+                               if line != "" {
+                                       f := strings.Fields(line)
+                                       if len(f) != 2 {
+                                               fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line)
+                                               nerrors++
+                                               continue
+                                       }
+                                       printf("\t%s;", cdecl(f[0], f[1]))
+                               }
+                               printf("\n")
+                       }
+                       printf("};\n")
+                       continue
+               }
+
+               // Convert
+               //      type T int
+               // to
+               //      typedef int T;
+               if strings.HasPrefix(line, "type ") {
+                       f := strings.Fields(line[len("type "):])
+                       if len(f) != 2 {
+                               fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line)
+                               nerrors++
+                               continue
+                       }
+                       printf("typedef\t%s;\n", cdecl(f[0], f[1]))
+                       continue
+               }
+
+               printf("%s\n", line)
+       }
+
+       if didTypedef {
+               printf("\n")
+               printf("#pragma pack off\n")
+       }
+
+       return out.String()
+}
+
+// cdecl returns the C declaration for the given Go name and type.
+// It only handles the specific cases necessary for converting godefs output.
+func cdecl(name, typ string) string {
+       // X *[0]byte -> X *void
+       if strings.HasPrefix(typ, "*[0]") {
+               typ = "*void"
+       }
+       // X [4]byte -> X[4] byte
+       for strings.HasPrefix(typ, "[") {
+               i := strings.Index(typ, "]") + 1
+               name = name + typ[:i]
+               typ = typ[i:]
+       }
+       // X *byte -> *X byte
+       for strings.HasPrefix(typ, "*") {
+               name = "*" + name
+               typ = typ[1:]
+       }
+       // X T -> T X
+       // Handle the special case: 'unsafe.Pointer' is 'void *'
+       if typ == "unsafe.Pointer" {
+               typ = "void"
+               name = "*" + name
+       }
+       return typ + "\t" + name
+}
+
+var gofmtBuf bytes.Buffer
+
+// gofmt returns the gofmt-formatted string for an AST node.
+func gofmt(n interface{}) string {
+       gofmtBuf.Reset()
+       err := printer.Fprint(&gofmtBuf, fset, n)
+       if err != nil {
+               return "<" + err.Error() + ">"
+       }
+       return gofmtBuf.String()
+}
diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go
new file mode 100644 (file)
index 0000000..ea4b9c2
--- /dev/null
@@ -0,0 +1,360 @@
+// 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.
+
+// Cgo; see gmp.go for an overview.
+
+// TODO(rsc):
+//     Emit correct line number annotations.
+//     Make 6g understand the annotations.
+
+package main
+
+import (
+       "crypto/md5"
+       "flag"
+       "fmt"
+       "go/ast"
+       "go/printer"
+       "go/token"
+       "io"
+       "os"
+       "path/filepath"
+       "reflect"
+       "runtime"
+       "sort"
+       "strings"
+)
+
+// A Package collects information about the package we're going to write.
+type Package struct {
+       PackageName string // name of package
+       PackagePath string
+       PtrSize     int64
+       IntSize     int64
+       GccOptions  []string
+       CgoFlags    map[string][]string // #cgo flags (CFLAGS, LDFLAGS)
+       Written     map[string]bool
+       Name        map[string]*Name // accumulated Name from Files
+       ExpFunc     []*ExpFunc       // accumulated ExpFunc from Files
+       Decl        []ast.Decl
+       GoFiles     []string // list of Go files
+       GccFiles    []string // list of gcc output files
+       Preamble    string   // collected preamble for _cgo_export.h
+}
+
+// A File collects information about a single Go input file.
+type File struct {
+       AST      *ast.File           // parsed AST
+       Comments []*ast.CommentGroup // comments from file
+       Package  string              // Package name
+       Preamble string              // C preamble (doc comment on import "C")
+       Ref      []*Ref              // all references to C.xxx in AST
+       ExpFunc  []*ExpFunc          // exported functions for this file
+       Name     map[string]*Name    // map from Go name to Name
+}
+
+func nameKeys(m map[string]*Name) []string {
+       var ks []string
+       for k := range m {
+               ks = append(ks, k)
+       }
+       sort.Strings(ks)
+       return ks
+}
+
+// A Ref refers to an expression of the form C.xxx in the AST.
+type Ref struct {
+       Name    *Name
+       Expr    *ast.Expr
+       Context string // "type", "expr", "call", or "call2"
+}
+
+func (r *Ref) Pos() token.Pos {
+       return (*r.Expr).Pos()
+}
+
+// A Name collects information about C.xxx.
+type Name struct {
+       Go       string // name used in Go referring to package C
+       Mangle   string // name used in generated Go
+       C        string // name used in C
+       Define   string // #define expansion
+       Kind     string // "const", "type", "var", "fpvar", "func", "not-type"
+       Type     *Type  // the type of xxx
+       FuncType *FuncType
+       AddError bool
+       Const    string // constant definition
+}
+
+// IsVar returns true if Kind is either "var" or "fpvar"
+func (n *Name) IsVar() bool {
+       return n.Kind == "var" || n.Kind == "fpvar"
+}
+
+// A ExpFunc is an exported function, callable from C.
+// Such functions are identified in the Go input file
+// by doc comments containing the line //export ExpName
+type ExpFunc struct {
+       Func    *ast.FuncDecl
+       ExpName string // name to use from C
+}
+
+// A TypeRepr contains the string representation of a type.
+type TypeRepr struct {
+       Repr       string
+       FormatArgs []interface{}
+}
+
+// A Type collects information about a type in both the C and Go worlds.
+type Type struct {
+       Size       int64
+       Align      int64
+       C          *TypeRepr
+       Go         ast.Expr
+       EnumValues map[string]int64
+       Typedef    string
+}
+
+// A FuncType collects information about a function type in both the C and Go worlds.
+type FuncType struct {
+       Params []*Type
+       Result *Type
+       Go     *ast.FuncType
+}
+
+func usage() {
+       fmt.Fprint(os.Stderr, "usage: cgo -- [compiler options] file.go ...\n")
+       flag.PrintDefaults()
+       os.Exit(2)
+}
+
+var ptrSizeMap = map[string]int64{
+       "386":   4,
+       "amd64": 8,
+       "arm":   4,
+       "ppc64": 8,
+       "ppc64le": 8,
+       "s390x": 8,
+}
+
+var intSizeMap = map[string]int64{
+       "386":   4,
+       "amd64": 8,
+       "arm":   4,
+       "ppc64": 8,
+       "ppc64le": 8,
+       "s390x": 8,
+}
+
+var cPrefix string
+
+var fset = token.NewFileSet()
+
+var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
+var dynout = flag.String("dynout", "", "write -dynobj output to this file")
+var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
+
+// These flags are for bootstrapping a new Go implementation,
+// to generate Go and C headers that match the data layout and
+// constant values used in the host's C libraries and system calls.
+var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output")
+var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C file to standard output")
+var objDir = flag.String("objdir", "", "object directory")
+
+var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
+var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
+var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
+var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
+var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code")
+var goarch, goos string
+
+func main() {
+       flag.Usage = usage
+       flag.Parse()
+
+       if *dynobj != "" {
+               // cgo -dynimport is essentially a separate helper command
+               // built into the cgo binary.  It scans a gcc-produced executable
+               // and dumps information about the imported symbols and the
+               // imported libraries.  The 'go build' rules for cgo prepare an
+               // appropriate executable and then use its import information
+               // instead of needing to make the linkers duplicate all the
+               // specialized knowledge gcc has about where to look for imported
+               // symbols and which ones to use.
+               dynimport(*dynobj)
+               return
+       }
+
+       if *godefs && *cdefs {
+               fmt.Fprintf(os.Stderr, "cgo: cannot use -cdefs and -godefs together\n")
+               os.Exit(2)
+       }
+
+       if *godefs || *cdefs {
+               // Generating definitions pulled from header files,
+               // to be checked into Go repositories.
+               // Line numbers are just noise.
+               conf.Mode &^= printer.SourcePos
+       }
+
+       args := flag.Args()
+       if len(args) < 1 {
+               usage()
+       }
+
+       // Find first arg that looks like a go file and assume everything before
+       // that are options to pass to gcc.
+       var i int
+       for i = len(args); i > 0; i-- {
+               if !strings.HasSuffix(args[i-1], ".go") {
+                       break
+               }
+       }
+       if i == len(args) {
+               usage()
+       }
+
+       goFiles := args[i:]
+
+       p := newPackage(args[:i])
+
+       // Record CGO_LDFLAGS from the environment for external linking.
+       if ldflags := os.Getenv("CGO_LDFLAGS"); ldflags != "" {
+               args, err := splitQuoted(ldflags)
+               if err != nil {
+                       fatalf("bad CGO_LDFLAGS: %q (%s)", ldflags, err)
+               }
+               p.addToFlag("LDFLAGS", args)
+       }
+
+       // Need a unique prefix for the global C symbols that
+       // we use to coordinate between gcc and ourselves.
+       // We already put _cgo_ at the beginning, so the main
+       // concern is other cgo wrappers for the same functions.
+       // Use the beginning of the md5 of the input to disambiguate.
+       h := md5.New()
+       for _, input := range goFiles {
+               f, err := os.Open(input)
+               if err != nil {
+                       fatalf("%s", err)
+               }
+               io.Copy(h, f)
+               f.Close()
+       }
+       cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6])
+
+       fs := make([]*File, len(goFiles))
+       for i, input := range goFiles {
+               f := new(File)
+               f.ReadGo(input)
+               f.DiscardCgoDirectives()
+               fs[i] = f
+       }
+
+       if *objDir == "" {
+               // make sure that _obj directory exists, so that we can write
+               // all the output files there.
+               os.Mkdir("_obj", 0777)
+               *objDir = "_obj"
+       }
+       *objDir += string(filepath.Separator)
+
+       for i, input := range goFiles {
+               f := fs[i]
+               p.Translate(f)
+               for _, cref := range f.Ref {
+                       switch cref.Context {
+                       case "call", "call2":
+                               if cref.Name.Kind != "type" {
+                                       break
+                               }
+                               *cref.Expr = cref.Name.Type.Go
+                       }
+               }
+               if nerrors > 0 {
+                       os.Exit(2)
+               }
+               pkg := f.Package
+               if dir := os.Getenv("CGOPKGPATH"); dir != "" {
+                       pkg = filepath.Join(dir, pkg)
+               }
+               p.PackagePath = pkg
+               p.Record(f)
+               if *godefs {
+                       os.Stdout.WriteString(p.godefs(f, input))
+               } else if *cdefs {
+                       os.Stdout.WriteString(p.cdefs(f, input))
+               } else {
+                       p.writeOutput(f, input)
+               }
+       }
+
+       if !*godefs && !*cdefs {
+               p.writeDefs()
+       }
+       if nerrors > 0 {
+               os.Exit(2)
+       }
+}
+
+// newPackage returns a new Package that will invoke
+// gcc with the additional arguments specified in args.
+func newPackage(args []string) *Package {
+       goarch = runtime.GOARCH
+       if s := os.Getenv("GOARCH"); s != "" {
+               goarch = s
+       }
+       goos = runtime.GOOS
+       if s := os.Getenv("GOOS"); s != "" {
+               goos = s
+       }
+       ptrSize := ptrSizeMap[goarch]
+       if ptrSize == 0 {
+               fatalf("unknown ptrSize for $GOARCH %q", goarch)
+       }
+       intSize := intSizeMap[goarch]
+       if intSize == 0 {
+               fatalf("unknown intSize for $GOARCH %q", goarch)
+       }
+
+       // Reset locale variables so gcc emits English errors [sic].
+       os.Setenv("LANG", "en_US.UTF-8")
+       os.Setenv("LC_ALL", "C")
+
+       p := &Package{
+               PtrSize:  ptrSize,
+               IntSize:  intSize,
+               CgoFlags: make(map[string][]string),
+               Written:  make(map[string]bool),
+       }
+       p.addToFlag("CFLAGS", args)
+       return p
+}
+
+// Record what needs to be recorded about f.
+func (p *Package) Record(f *File) {
+       if p.PackageName == "" {
+               p.PackageName = f.Package
+       } else if p.PackageName != f.Package {
+               error_(token.NoPos, "inconsistent package names: %s, %s", p.PackageName, f.Package)
+       }
+
+       if p.Name == nil {
+               p.Name = f.Name
+       } else {
+               for k, v := range f.Name {
+                       if p.Name[k] == nil {
+                               p.Name[k] = v
+                       } else if !reflect.DeepEqual(p.Name[k], v) {
+                               error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
+                       }
+               }
+       }
+
+       if f.ExpFunc != nil {
+               p.ExpFunc = append(p.ExpFunc, f.ExpFunc...)
+               p.Preamble += "\n" + f.Preamble
+       }
+       p.Decl = append(p.Decl, f.AST.Decls...)
+}
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go
new file mode 100644 (file)
index 0000000..76c7247
--- /dev/null
@@ -0,0 +1,1299 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "bytes"
+       "debug/elf"
+       "debug/macho"
+       "debug/pe"
+       "fmt"
+       "go/ast"
+       "go/printer"
+       "go/token"
+       "os"
+       "sort"
+       "strings"
+)
+
+var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
+
+// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
+// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
+func (p *Package) writeDefs() {
+       fgo2 := creat(*objDir + "_cgo_gotypes.go")
+       fc := creat(*objDir + "_cgo_defun.c")
+       fm := creat(*objDir + "_cgo_main.c")
+
+       var gccgoInit bytes.Buffer
+
+       fflg := creat(*objDir + "_cgo_flags")
+       for k, v := range p.CgoFlags {
+               fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
+               if k == "LDFLAGS" && !*gccgo {
+                       for _, arg := range v {
+                               fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
+                       }
+               }
+       }
+       fflg.Close()
+
+       // Write C main file for using gcc to resolve imports.
+       fmt.Fprintf(fm, "int main() { return 0; }\n")
+       if *importRuntimeCgo {
+               fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
+       } else {
+               // If we're not importing runtime/cgo, we *are* runtime/cgo,
+               // which provides crosscall2.  We just need a prototype.
+               fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
+       }
+       fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
+       fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
+
+       // Write second Go output: definitions of _C_xxx.
+       // In a separate file so that the import of "unsafe" does not
+       // pollute the original file.
+       fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
+       fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
+       fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
+       if *importSyscall {
+               fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
+       }
+       if !*gccgo && *importRuntimeCgo {
+               fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
+       }
+       fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
+       if *importSyscall {
+               fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int32) { *dst = syscall.Errno(x) }\n")
+       }
+
+       typedefNames := make([]string, 0, len(typedef))
+       for name := range typedef {
+               typedefNames = append(typedefNames, name)
+       }
+       sort.Strings(typedefNames)
+       for _, name := range typedefNames {
+               def := typedef[name]
+               fmt.Fprintf(fgo2, "type %s ", name)
+               conf.Fprint(fgo2, fset, def.Go)
+               fmt.Fprintf(fgo2, "\n\n")
+       }
+       if *gccgo {
+               fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
+       } else {
+               fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
+       }
+
+       if *gccgo {
+               fmt.Fprintf(fc, p.cPrologGccgo())
+       } else {
+               fmt.Fprintf(fc, cProlog)
+       }
+
+       gccgoSymbolPrefix := p.gccgoSymbolPrefix()
+
+       cVars := make(map[string]bool)
+       for _, key := range nameKeys(p.Name) {
+               n := p.Name[key]
+               if !n.IsVar() {
+                       continue
+               }
+
+               if !cVars[n.C] {
+                       fmt.Fprintf(fm, "extern char %s[];\n", n.C)
+                       fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
+
+                       if !*gccgo {
+                               fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
+                       }
+
+                       fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
+
+                       cVars[n.C] = true
+               }
+               var amp string
+               var node ast.Node
+               if n.Kind == "var" {
+                       amp = "&"
+                       node = &ast.StarExpr{X: n.Type.Go}
+               } else if n.Kind == "fpvar" {
+                       node = n.Type.Go
+                       if *gccgo {
+                               amp = "&"
+                       }
+               } else {
+                       panic(fmt.Errorf("invalid var kind %q", n.Kind))
+               }
+               if *gccgo {
+                       fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
+                       fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
+               } else {
+                       fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
+               }
+               fmt.Fprintf(fc, "\n")
+
+               fmt.Fprintf(fgo2, "var %s ", n.Mangle)
+               conf.Fprint(fgo2, fset, node)
+               fmt.Fprintf(fgo2, "\n")
+       }
+       fmt.Fprintf(fc, "\n")
+
+       for _, key := range nameKeys(p.Name) {
+               n := p.Name[key]
+               if n.Const != "" {
+                       fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
+               }
+       }
+       fmt.Fprintf(fgo2, "\n")
+
+       for _, key := range nameKeys(p.Name) {
+               n := p.Name[key]
+               if n.FuncType != nil {
+                       p.writeDefsFunc(fc, fgo2, n)
+               }
+       }
+
+       if *gccgo {
+               p.writeGccgoExports(fgo2, fc, fm)
+       } else {
+               p.writeExports(fgo2, fc, fm)
+       }
+
+       init := gccgoInit.String()
+       if init != "" {
+               fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
+               fmt.Fprintln(fc, "static void init(void) {")
+               fmt.Fprint(fc, init)
+               fmt.Fprintln(fc, "}")
+       }
+
+       fgo2.Close()
+       fc.Close()
+}
+
+func dynimport(obj string) {
+       stdout := os.Stdout
+       if *dynout != "" {
+               f, err := os.Create(*dynout)
+               if err != nil {
+                       fatalf("%s", err)
+               }
+               stdout = f
+       }
+
+       if f, err := elf.Open(obj); err == nil {
+               if *dynlinker {
+                       // Emit the cgo_dynamic_linker line.
+                       if sec := f.Section(".interp"); sec != nil {
+                               if data, err := sec.Data(); err == nil && len(data) > 1 {
+                                       // skip trailing \0 in data
+                                       fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
+                               }
+                       }
+               }
+               sym, err := f.ImportedSymbols()
+               if err != nil {
+                       fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
+               }
+               for _, s := range sym {
+                       targ := s.Name
+                       if s.Version != "" {
+                               targ += "#" + s.Version
+                       }
+                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
+               }
+               lib, err := f.ImportedLibraries()
+               if err != nil {
+                       fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
+               }
+               for _, l := range lib {
+                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
+               }
+               return
+       }
+
+       if f, err := macho.Open(obj); err == nil {
+               sym, err := f.ImportedSymbols()
+               if err != nil {
+                       fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
+               }
+               for _, s := range sym {
+                       if len(s) > 0 && s[0] == '_' {
+                               s = s[1:]
+                       }
+                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
+               }
+               lib, err := f.ImportedLibraries()
+               if err != nil {
+                       fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
+               }
+               for _, l := range lib {
+                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
+               }
+               return
+       }
+
+       if f, err := pe.Open(obj); err == nil {
+               sym, err := f.ImportedSymbols()
+               if err != nil {
+                       fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
+               }
+               for _, s := range sym {
+                       ss := strings.Split(s, ":")
+                       name := strings.Split(ss[0], "@")[0]
+                       fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
+               }
+               return
+       }
+
+       fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
+}
+
+// Construct a gcc struct matching the 6c argument frame.
+// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
+// These assumptions are checked by the gccProlog.
+// Also assumes that 6c convention is to word-align the
+// input and output parameters.
+func (p *Package) structType(n *Name) (string, int64) {
+       var buf bytes.Buffer
+       fmt.Fprint(&buf, "struct {\n")
+       off := int64(0)
+       for i, t := range n.FuncType.Params {
+               if off%t.Align != 0 {
+                       pad := t.Align - off%t.Align
+                       fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+                       off += pad
+               }
+               c := t.Typedef
+               if c == "" {
+                       c = t.C.String()
+               }
+               fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
+               off += t.Size
+       }
+       if off%p.PtrSize != 0 {
+               pad := p.PtrSize - off%p.PtrSize
+               fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+               off += pad
+       }
+       if t := n.FuncType.Result; t != nil {
+               if off%t.Align != 0 {
+                       pad := t.Align - off%t.Align
+                       fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+                       off += pad
+               }
+               qual := ""
+               if c := t.C.String(); c[len(c)-1] == '*' {
+                       qual = "const "
+               }
+               fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
+               off += t.Size
+       }
+       if off%p.PtrSize != 0 {
+               pad := p.PtrSize - off%p.PtrSize
+               fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+               off += pad
+       }
+       if n.AddError {
+               fmt.Fprint(&buf, "\t\tint e[2*sizeof(void *)/sizeof(int)]; /* error */\n")
+               off += 2 * p.PtrSize
+       }
+       if off == 0 {
+               fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
+       }
+       fmt.Fprintf(&buf, "\t}")
+       return buf.String(), off
+}
+
+func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
+       name := n.Go
+       gtype := n.FuncType.Go
+       void := gtype.Results == nil || len(gtype.Results.List) == 0
+       if n.AddError {
+               // Add "error" to return type list.
+               // Type list is known to be 0 or 1 element - it's a C function.
+               err := &ast.Field{Type: ast.NewIdent("error")}
+               l := gtype.Results.List
+               if len(l) == 0 {
+                       l = []*ast.Field{err}
+               } else {
+                       l = []*ast.Field{l[0], err}
+               }
+               t := new(ast.FuncType)
+               *t = *gtype
+               t.Results = &ast.FieldList{List: l}
+               gtype = t
+       }
+
+       // Go func declaration.
+       d := &ast.FuncDecl{
+               Name: ast.NewIdent(n.Mangle),
+               Type: gtype,
+       }
+
+       // Builtins defined in the C prolog.
+       inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc"
+
+       if *gccgo {
+               // Gccgo style hooks.
+               fmt.Fprint(fgo2, "\n")
+               cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
+               paramnames := []string(nil)
+               for i, param := range d.Type.Params.List {
+                       paramName := fmt.Sprintf("p%d", i)
+                       param.Names = []*ast.Ident{ast.NewIdent(paramName)}
+                       paramnames = append(paramnames, paramName)
+               }
+
+               conf.Fprint(fgo2, fset, d)
+               fmt.Fprint(fgo2, " {\n")
+               if !inProlog {
+                       fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
+                       fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
+               }
+               if n.AddError {
+                       fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
+               }
+               fmt.Fprint(fgo2, "\t")
+               if !void {
+                       fmt.Fprint(fgo2, "r := ")
+               }
+               fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))
+
+               if n.AddError {
+                       fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n")
+                       fmt.Fprint(fgo2, "\tif e != 0 {\n")
+                       fmt.Fprint(fgo2, "\t\treturn ")
+                       if !void {
+                               fmt.Fprint(fgo2, "r, ")
+                       }
+                       fmt.Fprint(fgo2, "e\n")
+                       fmt.Fprint(fgo2, "\t}\n")
+                       fmt.Fprint(fgo2, "\treturn ")
+                       if !void {
+                               fmt.Fprint(fgo2, "r, ")
+                       }
+                       fmt.Fprint(fgo2, "nil\n")
+               } else if !void {
+                       fmt.Fprint(fgo2, "\treturn r\n")
+               }
+
+               fmt.Fprint(fgo2, "}\n")
+
+               // declare the C function.
+               fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
+               d.Name = ast.NewIdent(cname)
+               if n.AddError {
+                       l := d.Type.Results.List
+                       d.Type.Results.List = l[:len(l)-1]
+               }
+               conf.Fprint(fgo2, fset, d)
+               fmt.Fprint(fgo2, "\n")
+
+               return
+       }
+       conf.Fprint(fgo2, fset, d)
+       fmt.Fprint(fgo2, "\n")
+
+       if inProlog {
+               return
+       }
+
+       var argSize int64
+       _, argSize = p.structType(n)
+
+       // C wrapper calls into gcc, passing a pointer to the argument frame.
+       fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangle)
+       fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
+       fmt.Fprintf(fc, "\n")
+       fmt.Fprintf(fc, "void\n")
+       if argSize == 0 {
+               argSize++
+       }
+       // TODO(rsc): The struct here should declare pointers only where
+       // there are pointers in the actual argument frame.
+       // This is a workaround for golang.org/issue/6397.
+       fmt.Fprintf(fc, "·%s(struct{", n.Mangle)
+       if n := argSize / p.PtrSize; n > 0 {
+               fmt.Fprintf(fc, "void *y[%d];", n)
+       }
+       if n := argSize % p.PtrSize; n > 0 {
+               fmt.Fprintf(fc, "uint8 x[%d];", n)
+       }
+       fmt.Fprintf(fc, "}p)\n")
+       fmt.Fprintf(fc, "{\n")
+       fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
+       if n.AddError {
+               // gcc leaves errno in first word of interface at end of p.
+               // check whether it is zero; if so, turn interface into nil.
+               // if not, turn interface into errno.
+               // Go init function initializes Â·_Cerrno with an os.Errno
+               // for us to copy.
+               fmt.Fprintln(fc, `      {
+                       int32 e;
+                       void **v;
+                       v = (void**)(&p+1) - 2; /* v = final two void* of p */
+                       e = *(int32*)v;
+                       v[0] = (void*)0xdeadbeef;
+                       v[1] = (void*)0xdeadbeef;
+                       if(e == 0) {
+                               /* nil interface */
+                               v[0] = 0;
+                               v[1] = 0;
+                       } else {
+                               Â·_Cerrno(v, e);        /* fill in v as error for errno e */
+                       }
+               }`)
+       }
+       fmt.Fprintf(fc, "}\n")
+       fmt.Fprintf(fc, "\n")
+}
+
+// writeOutput creates stubs for a specific source file to be compiled by 6g
+// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
+func (p *Package) writeOutput(f *File, srcfile string) {
+       base := srcfile
+       if strings.HasSuffix(base, ".go") {
+               base = base[0 : len(base)-3]
+       }
+       base = strings.Map(slashToUnderscore, base)
+       fgo1 := creat(*objDir + base + ".cgo1.go")
+       fgcc := creat(*objDir + base + ".cgo2.c")
+
+       p.GoFiles = append(p.GoFiles, base+".cgo1.go")
+       p.GccFiles = append(p.GccFiles, base+".cgo2.c")
+
+       // Write Go output: Go input with rewrites of C.xxx to _C_xxx.
+       fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
+       conf.Fprint(fgo1, fset, f.AST)
+
+       // While we process the vars and funcs, also write 6c and gcc output.
+       // Gcc output starts with the preamble.
+       fmt.Fprintf(fgcc, "%s\n", f.Preamble)
+       fmt.Fprintf(fgcc, "%s\n", gccProlog)
+
+       for _, key := range nameKeys(f.Name) {
+               n := f.Name[key]
+               if n.FuncType != nil {
+                       p.writeOutputFunc(fgcc, n)
+               }
+       }
+
+       fgo1.Close()
+       fgcc.Close()
+}
+
+// fixGo converts the internal Name.Go field into the name we should show
+// to users in error messages. There's only one for now: on input we rewrite
+// C.malloc into C._CMalloc, so change it back here.
+func fixGo(name string) string {
+       if name == "_CMalloc" {
+               return "malloc"
+       }
+       return name
+}
+
+var isBuiltin = map[string]bool{
+       "_Cfunc_CString":   true,
+       "_Cfunc_GoString":  true,
+       "_Cfunc_GoStringN": true,
+       "_Cfunc_GoBytes":   true,
+       "_Cfunc__CMalloc":  true,
+}
+
+func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
+       name := n.Mangle
+       if isBuiltin[name] || p.Written[name] {
+               // The builtins are already defined in the C prolog, and we don't
+               // want to duplicate function definitions we've already done.
+               return
+       }
+       p.Written[name] = true
+
+       if *gccgo {
+               p.writeGccgoOutputFunc(fgcc, n)
+               return
+       }
+
+       ctype, _ := p.structType(n)
+
+       // Gcc wrapper unpacks the C argument struct
+       // and calls the actual C function.
+       fmt.Fprintf(fgcc, "void\n")
+       fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
+       fmt.Fprintf(fgcc, "{\n")
+       if n.AddError {
+               fmt.Fprintf(fgcc, "\terrno = 0;\n")
+       }
+       // We're trying to write a gcc struct that matches 6c/8c/5c's layout.
+       // Use packed attribute to force no padding in this struct in case
+       // gcc has different packing requirements.
+       fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
+       fmt.Fprintf(fgcc, "\t")
+       if t := n.FuncType.Result; t != nil {
+               fmt.Fprintf(fgcc, "a->r = ")
+               if c := t.C.String(); c[len(c)-1] == '*' {
+                       fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
+               }
+       }
+       fmt.Fprintf(fgcc, "%s(", n.C)
+       for i, t := range n.FuncType.Params {
+               if i > 0 {
+                       fmt.Fprintf(fgcc, ", ")
+               }
+               // We know the type params are correct, because
+               // the Go equivalents had good type params.
+               // However, our version of the type omits the magic
+               // words const and volatile, which can provoke
+               // C compiler warnings.  Silence them by casting
+               // all pointers to void*.  (Eventually that will produce
+               // other warnings.)
+               if c := t.C.String(); c[len(c)-1] == '*' {
+                       fmt.Fprintf(fgcc, "(void*)")
+               }
+               fmt.Fprintf(fgcc, "a->p%d", i)
+       }
+       fmt.Fprintf(fgcc, ");\n")
+       if n.AddError {
+               fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
+       }
+       fmt.Fprintf(fgcc, "}\n")
+       fmt.Fprintf(fgcc, "\n")
+}
+
+// Write out a wrapper for a function when using gccgo.  This is a
+// simple wrapper that just calls the real function.  We only need a
+// wrapper to support static functions in the prologue--without a
+// wrapper, we can't refer to the function, since the reference is in
+// a different file.
+func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
+       if t := n.FuncType.Result; t != nil {
+               fmt.Fprintf(fgcc, "%s\n", t.C.String())
+       } else {
+               fmt.Fprintf(fgcc, "void\n")
+       }
+       fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
+       for i, t := range n.FuncType.Params {
+               if i > 0 {
+                       fmt.Fprintf(fgcc, ", ")
+               }
+               c := t.Typedef
+               if c == "" {
+                       c = t.C.String()
+               }
+               fmt.Fprintf(fgcc, "%s p%d", c, i)
+       }
+       fmt.Fprintf(fgcc, ")\n")
+       fmt.Fprintf(fgcc, "{\n")
+       fmt.Fprintf(fgcc, "\t")
+       if t := n.FuncType.Result; t != nil {
+               fmt.Fprintf(fgcc, "return ")
+               // Cast to void* to avoid warnings due to omitted qualifiers.
+               if c := t.C.String(); c[len(c)-1] == '*' {
+                       fmt.Fprintf(fgcc, "(void*)")
+               }
+       }
+       fmt.Fprintf(fgcc, "%s(", n.C)
+       for i, t := range n.FuncType.Params {
+               if i > 0 {
+                       fmt.Fprintf(fgcc, ", ")
+               }
+               // Cast to void* to avoid warnings due to omitted qualifiers.
+               if c := t.C.String(); c[len(c)-1] == '*' {
+                       fmt.Fprintf(fgcc, "(void*)")
+               }
+               fmt.Fprintf(fgcc, "p%d", i)
+       }
+       fmt.Fprintf(fgcc, ");\n")
+       fmt.Fprintf(fgcc, "}\n")
+       fmt.Fprintf(fgcc, "\n")
+}
+
+// packedAttribute returns host compiler struct attribute that will be
+// used to match 6c/8c/5c's struct layout. For example, on 386 Windows,
+// gcc wants to 8-align int64s, but 8c does not.
+// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
+// and http://golang.org/issue/5603.
+func (p *Package) packedAttribute() string {
+       s := "__attribute__((__packed__"
+       if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
+               s += ", __gcc_struct__"
+       }
+       return s + "))"
+}
+
+// Write out the various stubs we need to support functions exported
+// from Go so that they are callable from C.
+func (p *Package) writeExports(fgo2, fc, fm *os.File) {
+       fgcc := creat(*objDir + "_cgo_export.c")
+       fgcch := creat(*objDir + "_cgo_export.h")
+
+       fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
+       fmt.Fprintf(fgcch, "%s\n", p.Preamble)
+       fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
+
+       fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
+       fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
+
+       fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
+
+       for _, exp := range p.ExpFunc {
+               fn := exp.Func
+
+               // Construct a gcc struct matching the 6c argument and
+               // result frame.  The gcc struct will be compiled with
+               // __attribute__((packed)) so all padding must be accounted
+               // for explicitly.
+               ctype := "struct {\n"
+               off := int64(0)
+               npad := 0
+               if fn.Recv != nil {
+                       t := p.cgoType(fn.Recv.List[0].Type)
+                       ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
+                       off += t.Size
+               }
+               fntype := fn.Type
+               forFieldList(fntype.Params,
+                       func(i int, atype ast.Expr) {
+                               t := p.cgoType(atype)
+                               if off%t.Align != 0 {
+                                       pad := t.Align - off%t.Align
+                                       ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+                                       off += pad
+                                       npad++
+                               }
+                               ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
+                               off += t.Size
+                       })
+               if off%p.PtrSize != 0 {
+                       pad := p.PtrSize - off%p.PtrSize
+                       ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+                       off += pad
+                       npad++
+               }
+               forFieldList(fntype.Results,
+                       func(i int, atype ast.Expr) {
+                               t := p.cgoType(atype)
+                               if off%t.Align != 0 {
+                                       pad := t.Align - off%t.Align
+                                       ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+                                       off += pad
+                                       npad++
+                               }
+                               ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
+                               off += t.Size
+                       })
+               if off%p.PtrSize != 0 {
+                       pad := p.PtrSize - off%p.PtrSize
+                       ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+                       off += pad
+                       npad++
+               }
+               if ctype == "struct {\n" {
+                       ctype += "\t\tchar unused;\n" // avoid empty struct
+               }
+               ctype += "\t}"
+
+               // Get the return type of the wrapper function
+               // compiled by gcc.
+               gccResult := ""
+               if fntype.Results == nil || len(fntype.Results.List) == 0 {
+                       gccResult = "void"
+               } else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
+                       gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
+               } else {
+                       fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
+                       fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
+                       forFieldList(fntype.Results,
+                               func(i int, atype ast.Expr) {
+                                       fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i)
+                               })
+                       fmt.Fprintf(fgcch, "};\n")
+                       gccResult = "struct " + exp.ExpName + "_return"
+               }
+
+               // Build the wrapper function compiled by gcc.
+               s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
+               if fn.Recv != nil {
+                       s += p.cgoType(fn.Recv.List[0].Type).C.String()
+                       s += " recv"
+               }
+               forFieldList(fntype.Params,
+                       func(i int, atype ast.Expr) {
+                               if i > 0 || fn.Recv != nil {
+                                       s += ", "
+                               }
+                               s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
+                       })
+               s += ")"
+               fmt.Fprintf(fgcch, "\nextern %s;\n", s)
+
+               fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
+               fmt.Fprintf(fgcc, "\n%s\n", s)
+               fmt.Fprintf(fgcc, "{\n")
+               fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
+               if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
+                       fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
+               }
+               if fn.Recv != nil {
+                       fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
+               }
+               forFieldList(fntype.Params,
+                       func(i int, atype ast.Expr) {
+                               fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
+                       })
+               fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
+               if gccResult != "void" {
+                       if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
+                               fmt.Fprintf(fgcc, "\treturn a.r0;\n")
+                       } else {
+                               forFieldList(fntype.Results,
+                                       func(i int, atype ast.Expr) {
+                                               fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
+                                       })
+                               fmt.Fprintf(fgcc, "\treturn r;\n")
+                       }
+               }
+               fmt.Fprintf(fgcc, "}\n")
+
+               // Build the wrapper function compiled by 6c/8c
+               goname := exp.Func.Name.Name
+               if fn.Recv != nil {
+                       goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
+               }
+               fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
+               fmt.Fprintf(fc, "extern void Â·%s();\n\n", goname)
+               fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
+               fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
+               fmt.Fprintf(fc, "void\n")
+               fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
+               fmt.Fprintf(fc, "{\n")
+               fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
+               fmt.Fprintf(fc, "}\n")
+
+               fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
+
+               // Calling a function with a receiver from C requires
+               // a Go wrapper function.
+               if fn.Recv != nil {
+                       fmt.Fprintf(fgo2, "func %s(recv ", goname)
+                       conf.Fprint(fgo2, fset, fn.Recv.List[0].Type)
+                       forFieldList(fntype.Params,
+                               func(i int, atype ast.Expr) {
+                                       fmt.Fprintf(fgo2, ", p%d ", i)
+                                       conf.Fprint(fgo2, fset, atype)
+                               })
+                       fmt.Fprintf(fgo2, ")")
+                       if gccResult != "void" {
+                               fmt.Fprint(fgo2, " (")
+                               forFieldList(fntype.Results,
+                                       func(i int, atype ast.Expr) {
+                                               if i > 0 {
+                                                       fmt.Fprint(fgo2, ", ")
+                                               }
+                                               conf.Fprint(fgo2, fset, atype)
+                                       })
+                               fmt.Fprint(fgo2, ")")
+                       }
+                       fmt.Fprint(fgo2, " {\n")
+                       fmt.Fprint(fgo2, "\t")
+                       if gccResult != "void" {
+                               fmt.Fprint(fgo2, "return ")
+                       }
+                       fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name)
+                       forFieldList(fntype.Params,
+                               func(i int, atype ast.Expr) {
+                                       if i > 0 {
+                                               fmt.Fprint(fgo2, ", ")
+                                       }
+                                       fmt.Fprintf(fgo2, "p%d", i)
+                               })
+                       fmt.Fprint(fgo2, ")\n")
+                       fmt.Fprint(fgo2, "}\n")
+               }
+       }
+}
+
+// Write out the C header allowing C code to call exported gccgo functions.
+func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
+       fgcc := creat(*objDir + "_cgo_export.c")
+       fgcch := creat(*objDir + "_cgo_export.h")
+
+       gccgoSymbolPrefix := p.gccgoSymbolPrefix()
+
+       fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
+       fmt.Fprintf(fgcch, "%s\n", p.Preamble)
+       fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
+
+       fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
+       fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
+
+       fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
+
+       for _, exp := range p.ExpFunc {
+               fn := exp.Func
+               fntype := fn.Type
+
+               cdeclBuf := new(bytes.Buffer)
+               resultCount := 0
+               forFieldList(fntype.Results,
+                       func(i int, atype ast.Expr) { resultCount++ })
+               switch resultCount {
+               case 0:
+                       fmt.Fprintf(cdeclBuf, "void")
+               case 1:
+                       forFieldList(fntype.Results,
+                               func(i int, atype ast.Expr) {
+                                       t := p.cgoType(atype)
+                                       fmt.Fprintf(cdeclBuf, "%s", t.C)
+                               })
+               default:
+                       // Declare a result struct.
+                       fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
+                       forFieldList(fntype.Results,
+                               func(i int, atype ast.Expr) {
+                                       t := p.cgoType(atype)
+                                       fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i)
+                               })
+                       fmt.Fprintf(fgcch, "};\n")
+                       fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
+               }
+
+               cRet := cdeclBuf.String()
+
+               cdeclBuf = new(bytes.Buffer)
+               fmt.Fprintf(cdeclBuf, "(")
+               if fn.Recv != nil {
+                       fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String())
+               }
+               // Function parameters.
+               forFieldList(fntype.Params,
+                       func(i int, atype ast.Expr) {
+                               if i > 0 || fn.Recv != nil {
+                                       fmt.Fprintf(cdeclBuf, ", ")
+                               }
+                               t := p.cgoType(atype)
+                               fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
+                       })
+               fmt.Fprintf(cdeclBuf, ")")
+               cParams := cdeclBuf.String()
+
+               // We need to use a name that will be exported by the
+               // Go code; otherwise gccgo will make it static and we
+               // will not be able to link against it from the C
+               // code.
+               goName := "Cgoexp_" + exp.ExpName
+               fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
+               fmt.Fprint(fgcch, "\n")
+
+               // Use a #define so that the C code that includes
+               // cgo_export.h will be able to refer to the Go
+               // function using the expected name.
+               fmt.Fprintf(fgcch, "#define %s %s\n", exp.ExpName, goName)
+
+               // Use a #undef in _cgo_export.c so that we ignore the
+               // #define from cgo_export.h, since here we are
+               // defining the real function.
+               fmt.Fprintf(fgcc, "#undef %s\n", exp.ExpName)
+
+               fmt.Fprint(fgcc, "\n")
+               fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
+               fmt.Fprint(fgcc, "\t")
+               if resultCount > 0 {
+                       fmt.Fprint(fgcc, "return ")
+               }
+               fmt.Fprintf(fgcc, "%s(", goName)
+               if fn.Recv != nil {
+                       fmt.Fprint(fgcc, "recv")
+               }
+               forFieldList(fntype.Params,
+                       func(i int, atype ast.Expr) {
+                               if i > 0 || fn.Recv != nil {
+                                       fmt.Fprintf(fgcc, ", ")
+                               }
+                               fmt.Fprintf(fgcc, "p%d", i)
+                       })
+               fmt.Fprint(fgcc, ");\n")
+               fmt.Fprint(fgcc, "}\n")
+
+               // Dummy declaration for _cgo_main.c
+               fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
+
+               // For gccgo we use a wrapper function in Go, in order
+               // to call CgocallBack and CgocallBackDone.
+
+               // This code uses printer.Fprint, not conf.Fprint,
+               // because we don't want //line comments in the middle
+               // of the function types.
+               fmt.Fprint(fgo2, "\n")
+               fmt.Fprintf(fgo2, "func %s(", goName)
+               if fn.Recv != nil {
+                       fmt.Fprint(fgo2, "recv ")
+                       printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
+               }
+               forFieldList(fntype.Params,
+                       func(i int, atype ast.Expr) {
+                               if i > 0 || fn.Recv != nil {
+                                       fmt.Fprintf(fgo2, ", ")
+                               }
+                               fmt.Fprintf(fgo2, "p%d ", i)
+                               printer.Fprint(fgo2, fset, atype)
+                       })
+               fmt.Fprintf(fgo2, ")")
+               if resultCount > 0 {
+                       fmt.Fprintf(fgo2, " (")
+                       forFieldList(fntype.Results,
+                               func(i int, atype ast.Expr) {
+                                       if i > 0 {
+                                               fmt.Fprint(fgo2, ", ")
+                                       }
+                                       printer.Fprint(fgo2, fset, atype)
+                               })
+                       fmt.Fprint(fgo2, ")")
+               }
+               fmt.Fprint(fgo2, " {\n")
+               fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n")
+               fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n")
+               fmt.Fprint(fgo2, "\t")
+               if resultCount > 0 {
+                       fmt.Fprint(fgo2, "return ")
+               }
+               if fn.Recv != nil {
+                       fmt.Fprint(fgo2, "recv.")
+               }
+               fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
+               forFieldList(fntype.Params,
+                       func(i int, atype ast.Expr) {
+                               if i > 0 {
+                                       fmt.Fprint(fgo2, ", ")
+                               }
+                               fmt.Fprintf(fgo2, "p%d", i)
+                       })
+               fmt.Fprint(fgo2, ")\n")
+               fmt.Fprint(fgo2, "}\n")
+       }
+}
+
+// Return the package prefix when using gccgo.
+func (p *Package) gccgoSymbolPrefix() string {
+       if !*gccgo {
+               return ""
+       }
+
+       clean := func(r rune) rune {
+               switch {
+               case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
+                       '0' <= r && r <= '9':
+                       return r
+               }
+               return '_'
+       }
+
+       if *gccgopkgpath != "" {
+               return strings.Map(clean, *gccgopkgpath)
+       }
+       if *gccgoprefix == "" && p.PackageName == "main" {
+               return "main"
+       }
+       prefix := strings.Map(clean, *gccgoprefix)
+       if prefix == "" {
+               prefix = "go"
+       }
+       return prefix + "." + p.PackageName
+}
+
+// Call a function for each entry in an ast.FieldList, passing the
+// index into the list and the type.
+func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
+       if fl == nil {
+               return
+       }
+       i := 0
+       for _, r := range fl.List {
+               if r.Names == nil {
+                       fn(i, r.Type)
+                       i++
+               } else {
+                       for _ = range r.Names {
+                               fn(i, r.Type)
+                               i++
+                       }
+               }
+       }
+}
+
+func c(repr string, args ...interface{}) *TypeRepr {
+       return &TypeRepr{repr, args}
+}
+
+// Map predeclared Go types to Type.
+var goTypes = map[string]*Type{
+       "bool":       {Size: 1, Align: 1, C: c("GoUint8")},
+       "byte":       {Size: 1, Align: 1, C: c("GoUint8")},
+       "int":        {Size: 0, Align: 0, C: c("GoInt")},
+       "uint":       {Size: 0, Align: 0, C: c("GoUint")},
+       "rune":       {Size: 4, Align: 4, C: c("GoInt32")},
+       "int8":       {Size: 1, Align: 1, C: c("GoInt8")},
+       "uint8":      {Size: 1, Align: 1, C: c("GoUint8")},
+       "int16":      {Size: 2, Align: 2, C: c("GoInt16")},
+       "uint16":     {Size: 2, Align: 2, C: c("GoUint16")},
+       "int32":      {Size: 4, Align: 4, C: c("GoInt32")},
+       "uint32":     {Size: 4, Align: 4, C: c("GoUint32")},
+       "int64":      {Size: 8, Align: 8, C: c("GoInt64")},
+       "uint64":     {Size: 8, Align: 8, C: c("GoUint64")},
+       "float32":    {Size: 4, Align: 4, C: c("GoFloat32")},
+       "float64":    {Size: 8, Align: 8, C: c("GoFloat64")},
+       "complex64":  {Size: 8, Align: 8, C: c("GoComplex64")},
+       "complex128": {Size: 16, Align: 16, C: c("GoComplex128")},
+}
+
+// Map an ast type to a Type.
+func (p *Package) cgoType(e ast.Expr) *Type {
+       switch t := e.(type) {
+       case *ast.StarExpr:
+               x := p.cgoType(t.X)
+               return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
+       case *ast.ArrayType:
+               if t.Len == nil {
+                       // Slice: pointer, len, cap.
+                       return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")}
+               }
+       case *ast.StructType:
+               // TODO
+       case *ast.FuncType:
+               return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
+       case *ast.InterfaceType:
+               return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
+       case *ast.MapType:
+               return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
+       case *ast.ChanType:
+               return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
+       case *ast.Ident:
+               // Look up the type in the top level declarations.
+               // TODO: Handle types defined within a function.
+               for _, d := range p.Decl {
+                       gd, ok := d.(*ast.GenDecl)
+                       if !ok || gd.Tok != token.TYPE {
+                               continue
+                       }
+                       for _, spec := range gd.Specs {
+                               ts, ok := spec.(*ast.TypeSpec)
+                               if !ok {
+                                       continue
+                               }
+                               if ts.Name.Name == t.Name {
+                                       return p.cgoType(ts.Type)
+                               }
+                       }
+               }
+               if def := typedef[t.Name]; def != nil {
+                       return def
+               }
+               if t.Name == "uintptr" {
+                       return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
+               }
+               if t.Name == "string" {
+                       // The string data is 1 pointer + 1 (pointer-sized) int.
+                       return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
+               }
+               if t.Name == "error" {
+                       return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
+               }
+               if r, ok := goTypes[t.Name]; ok {
+                       if r.Size == 0 { // int or uint
+                               rr := new(Type)
+                               *rr = *r
+                               rr.Size = p.IntSize
+                               rr.Align = p.IntSize
+                               r = rr
+                       }
+                       if r.Align > p.PtrSize {
+                               r.Align = p.PtrSize
+                       }
+                       return r
+               }
+               error_(e.Pos(), "unrecognized Go type %s", t.Name)
+               return &Type{Size: 4, Align: 4, C: c("int")}
+       case *ast.SelectorExpr:
+               id, ok := t.X.(*ast.Ident)
+               if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
+                       return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
+               }
+       }
+       error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
+       return &Type{Size: 4, Align: 4, C: c("int")}
+}
+
+const gccProlog = `
+// Usual nonsense: if x and y are not equal, the type will be invalid
+// (have a negative array count) and an inscrutable error will come
+// out of the compiler and hopefully mention "name".
+#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
+
+// Check at compile time that the sizes we use match our expectations.
+#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)
+
+__cgo_size_assert(char, 1)
+__cgo_size_assert(short, 2)
+__cgo_size_assert(int, 4)
+typedef long long __cgo_long_long;
+__cgo_size_assert(__cgo_long_long, 8)
+__cgo_size_assert(float, 4)
+__cgo_size_assert(double, 8)
+
+#include <errno.h>
+#include <string.h>
+`
+
+const builtinProlog = `
+#include <sys/types.h> /* for size_t below */
+
+/* Define intgo when compiling with GCC.  */
+#ifdef __PTRDIFF_TYPE__
+typedef __PTRDIFF_TYPE__ intgo;
+#elif defined(_LP64)
+typedef long long intgo;
+#else
+typedef int intgo;
+#endif
+
+typedef struct { char *p; intgo n; } _GoString_;
+typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
+_GoString_ GoString(char *p);
+_GoString_ GoStringN(char *p, int l);
+_GoBytes_ GoBytes(void *p, int n);
+char *CString(_GoString_);
+void *_CMalloc(size_t);
+`
+
+const cProlog = `
+#include "runtime.h"
+#include "cgocall.h"
+
+void Â·_Cerrno(void*, int32);
+
+void
+·_Cfunc_GoString(int8 *p, String s)
+{
+       s = runtime·gostring((byte*)p);
+       FLUSH(&s);
+}
+
+void
+·_Cfunc_GoStringN(int8 *p, int32 l, String s)
+{
+       s = runtime·gostringn((byte*)p, l);
+       FLUSH(&s);
+}
+
+void
+·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
+{
+       s = runtime·gobytes((byte*)p, l);
+       FLUSH(&s);
+}
+
+void
+·_Cfunc_CString(String s, int8 *p)
+{
+       p = runtime·cmalloc(s.len+1);
+       runtime·memmove((byte*)p, s.str, s.len);
+       p[s.len] = 0;
+       FLUSH(&p);
+}
+
+void
+·_Cfunc__CMalloc(uintptr n, int8 *p)
+{
+       p = runtime·cmalloc(n);
+       FLUSH(&p);
+}
+`
+
+func (p *Package) cPrologGccgo() string {
+       return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
+}
+
+const cPrologGccgo = `
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char byte;
+typedef intptr_t intgo;
+
+struct __go_string {
+       const unsigned char *__data;
+       intgo __length;
+};
+
+typedef struct __go_open_array {
+       void* __values;
+       intgo __count;
+       intgo __capacity;
+} Slice;
+
+struct __go_string __go_byte_array_to_string(const void* p, intgo len);
+struct __go_open_array __go_string_to_byte_array (struct __go_string str);
+
+const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
+       char *p = malloc(s.__length+1);
+       memmove(p, s.__data, s.__length);
+       p[s.__length] = 0;
+       return p;
+}
+
+struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
+       intgo len = (p != NULL) ? strlen(p) : 0;
+       return __go_byte_array_to_string(p, len);
+}
+
+struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) {
+       return __go_byte_array_to_string(p, n);
+}
+
+Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
+       struct __go_string s = { (const unsigned char *)p, n };
+       return __go_string_to_byte_array(s);
+}
+
+extern void runtime_throw(const char *);
+void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
+        void *p = malloc(n);
+        if(p == NULL && n == 0)
+                p = malloc(1);
+        if(p == NULL)
+                runtime_throw("runtime: C malloc failed");
+        return p;
+}
+`
+
+func (p *Package) gccExportHeaderProlog() string {
+       return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
+}
+
+const gccExportHeaderProlog = `
+typedef signed char GoInt8;
+typedef unsigned char GoUint8;
+typedef short GoInt16;
+typedef unsigned short GoUint16;
+typedef int GoInt32;
+typedef unsigned int GoUint32;
+typedef long long GoInt64;
+typedef unsigned long long GoUint64;
+typedef GoIntGOINTBITS GoInt;
+typedef GoUintGOINTBITS GoUint;
+typedef __SIZE_TYPE__ GoUintptr;
+typedef float GoFloat32;
+typedef double GoFloat64;
+typedef __complex float GoComplex64;
+typedef __complex double GoComplex128;
+
+typedef struct { char *p; GoInt n; } GoString;
+typedef void *GoMap;
+typedef void *GoChan;
+typedef struct { void *t; void *v; } GoInterface;
+typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
+`
diff --git a/libgo/go/cmd/cgo/util.go b/libgo/go/cmd/cgo/util.go
new file mode 100644 (file)
index 0000000..4e7800d
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "go/token"
+       "os"
+       "os/exec"
+)
+
+// run runs the command argv, feeding in stdin on standard input.
+// It returns the output to standard output and standard error.
+// ok indicates whether the command exited successfully.
+func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
+       p := exec.Command(argv[0], argv[1:]...)
+       p.Stdin = bytes.NewReader(stdin)
+       var bout, berr bytes.Buffer
+       p.Stdout = &bout
+       p.Stderr = &berr
+       err := p.Run()
+       if _, ok := err.(*exec.ExitError); err != nil && !ok {
+               fatalf("%s", err)
+       }
+       ok = p.ProcessState.Success()
+       stdout, stderr = bout.Bytes(), berr.Bytes()
+       return
+}
+
+func lineno(pos token.Pos) string {
+       return fset.Position(pos).String()
+}
+
+// Die with an error message.
+func fatalf(msg string, args ...interface{}) {
+       // If we've already printed other errors, they might have
+       // caused the fatal condition.  Assume they're enough.
+       if nerrors == 0 {
+               fmt.Fprintf(os.Stderr, msg+"\n", args...)
+       }
+       os.Exit(2)
+}
+
+var nerrors int
+
+func error_(pos token.Pos, msg string, args ...interface{}) {
+       nerrors++
+       if pos.IsValid() {
+               fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String())
+       }
+       fmt.Fprintf(os.Stderr, msg, args...)
+       fmt.Fprintf(os.Stderr, "\n")
+}
+
+// isName returns true if s is a valid C identifier
+func isName(s string) bool {
+       for i, v := range s {
+               if v != '_' && (v < 'A' || v > 'Z') && (v < 'a' || v > 'z') && (v < '0' || v > '9') {
+                       return false
+               }
+               if i == 0 && '0' <= v && v <= '9' {
+                       return false
+               }
+       }
+       return s != ""
+}
+
+func creat(name string) *os.File {
+       f, err := os.Create(name)
+       if err != nil {
+               fatalf("%s", err)
+       }
+       return f
+}
+
+func slashToUnderscore(c rune) rune {
+       if c == '/' || c == '\\' || c == ':' {
+               c = '_'
+       }
+       return c
+}
diff --git a/libgo/go/cmd/go/bootstrap.go b/libgo/go/cmd/go/bootstrap.go
new file mode 100644 (file)
index 0000000..dc7ed5f
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+// +build cmd_go_bootstrap
+
+// This code is compiled only into the bootstrap 'go' binary.
+// These stubs avoid importing packages with large dependency
+// trees, like the use of "net/http" in vcs.go.
+
+package main
+
+import (
+       "errors"
+       "io"
+)
+
+var errHTTP = errors.New("no http in bootstrap go command")
+
+func httpGET(url string) ([]byte, error) {
+       return nil, errHTTP
+}
+
+func httpsOrHTTP(importPath string) (string, io.ReadCloser, error) {
+       return "", nil, errHTTP
+}
+
+func parseMetaGoImports(r io.Reader) ([]metaImport, error) {
+       panic("unreachable")
+}
diff --git a/libgo/go/cmd/go/build.go b/libgo/go/cmd/go/build.go
new file mode 100644 (file)
index 0000000..c995793
--- /dev/null
@@ -0,0 +1,2594 @@
+// 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 (
+       "bufio"
+       "bytes"
+       "container/heap"
+       "errors"
+       "flag"
+       "fmt"
+       "go/build"
+       "io"
+       "io/ioutil"
+       "log"
+       "os"
+       "os/exec"
+       "path"
+       "path/filepath"
+       "regexp"
+       "runtime"
+       "strconv"
+       "strings"
+       "sync"
+       "time"
+)
+
+var cmdBuild = &Command{
+       UsageLine: "build [-o output] [-i] [build flags] [packages]",
+       Short:     "compile packages and dependencies",
+       Long: `
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+If the arguments are a list of .go files, build treats them as a list
+of source files specifying a single package.
+
+When the command line specifies a single main package,
+build writes the resulting executable to output.
+Otherwise build compiles the packages but discards the results,
+serving only as a check that the packages can be built.
+
+The -o flag specifies the output file name. If not specified, the
+output file name depends on the arguments and derives from the name
+of the package, such as p.a for package p, unless p is 'main'. If
+the package is main and file names are provided, the file name
+derives from the first file name mentioned, such as f1 for 'go build
+f1.go f2.go'; with no files provided ('go build'), the output file
+name is the base name of the containing directory.
+
+The -i flag installs the packages that are dependencies of the target.
+
+The build flags are shared by the build, clean, get, install, list, run,
+and test commands:
+
+       -a
+               force rebuilding of packages that are already up-to-date.
+       -n
+               print the commands but do not run them.
+       -p n
+               the number of builds that can be run in parallel.
+               The default is the number of CPUs available.
+       -race
+               enable data race detection.
+               Supported only on linux/amd64, darwin/amd64 and windows/amd64.
+       -v
+               print the names of packages as they are compiled.
+       -work
+               print the name of the temporary work directory and
+               do not delete it when exiting.
+       -x
+               print the commands.
+
+       -ccflags 'arg list'
+               arguments to pass on each 5c, 6c, or 8c compiler invocation.
+       -compiler name
+               name of compiler to use, as in runtime.Compiler (gccgo or gc).
+       -gccgoflags 'arg list'
+               arguments to pass on each gccgo compiler/linker invocation.
+       -gcflags 'arg list'
+               arguments to pass on each 5g, 6g, or 8g compiler invocation.
+       -installsuffix suffix
+               a suffix to use in the name of the package installation directory,
+               in order to keep output separate from default builds.
+               If using the -race flag, the install suffix is automatically set to race
+               or, if set explicitly, has _race appended to it.
+       -ldflags 'flag list'
+               arguments to pass on each 5l, 6l, or 8l linker invocation.
+       -tags 'tag list'
+               a list of build tags to consider satisfied during the build.
+               For more information about build tags, see the description of
+               build constraints in the documentation for the go/build package.
+
+The list flags accept a space-separated list of strings. To embed spaces
+in an element in the list, surround it with either single or double quotes.
+
+For more about specifying packages, see 'go help packages'.
+For more about where packages and binaries are installed,
+run 'go help gopath'.  For more about calling between Go and C/C++,
+run 'go help c'.
+
+See also: go install, go get, go clean.
+       `,
+}
+
+func init() {
+       // break init cycle
+       cmdBuild.Run = runBuild
+       cmdInstall.Run = runInstall
+
+       cmdBuild.Flag.BoolVar(&buildI, "i", false, "")
+
+       addBuildFlags(cmdBuild)
+       addBuildFlags(cmdInstall)
+}
+
+// Flags set by multiple commands.
+var buildA bool               // -a flag
+var buildN bool               // -n flag
+var buildP = runtime.NumCPU() // -p flag
+var buildV bool               // -v flag
+var buildX bool               // -x flag
+var buildI bool               // -i flag
+var buildO = cmdBuild.Flag.String("o", "", "output file")
+var buildWork bool           // -work flag
+var buildGcflags []string    // -gcflags flag
+var buildCcflags []string    // -ccflags flag
+var buildLdflags []string    // -ldflags flag
+var buildGccgoflags []string // -gccgoflags flag
+var buildRace bool           // -race flag
+
+var reqPkgSrc bool           // req src for Imports
+var buildContext = build.Default
+var buildToolchain toolchain = noToolchain{}
+
+// buildCompiler implements flag.Var.
+// It implements Set by updating both
+// buildToolchain and buildContext.Compiler.
+type buildCompiler struct{}
+
+func (c buildCompiler) Set(value string) error {
+       switch value {
+       case "gc":
+               buildToolchain = gcToolchain{}
+       case "gccgo":
+               buildToolchain = gccgoToolchain{}
+       default:
+               return fmt.Errorf("unknown compiler %q", value)
+       }
+       buildContext.Compiler = value
+       return nil
+}
+
+func (c buildCompiler) String() string {
+       return buildContext.Compiler
+}
+
+func init() {
+       switch build.Default.Compiler {
+       case "gc":
+               buildToolchain = gcToolchain{}
+       case "gccgo":
+               buildToolchain = gccgoToolchain{}
+       }
+}
+
+// addBuildFlags adds the flags common to the build, clean, get,
+// install, list, run, and test commands.
+func addBuildFlags(cmd *Command) {
+       // NOTE: If you add flags here, also add them to testflag.go.
+       cmd.Flag.BoolVar(&buildA, "a", false, "")
+       cmd.Flag.BoolVar(&buildN, "n", false, "")
+       cmd.Flag.IntVar(&buildP, "p", buildP, "")
+       cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
+       cmd.Flag.BoolVar(&buildV, "v", false, "")
+       cmd.Flag.BoolVar(&buildX, "x", false, "")
+       cmd.Flag.BoolVar(&buildWork, "work", false, "")
+       cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "")
+       cmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "")
+       cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
+       cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
+       cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
+       cmd.Flag.Var(buildCompiler{}, "compiler", "")
+       cmd.Flag.BoolVar(&buildRace, "race", false, "")
+       switch build.Default.Compiler {
+       case "gc":
+               reqPkgSrc = true
+       case "gccgo":
+               reqPkgSrc = false
+       }
+}
+
+func addBuildFlagsNX(cmd *Command) {
+       cmd.Flag.BoolVar(&buildN, "n", false, "")
+       cmd.Flag.BoolVar(&buildX, "x", false, "")
+}
+
+func isSpaceByte(c byte) bool {
+       return c == ' ' || c == '\t' || c == '\n' || c == '\r'
+}
+
+// fileExtSplit expects a filename and returns the name
+// and ext (without the dot). If the file has no
+// extension, ext will be empty.
+func fileExtSplit(file string) (name, ext string) {
+       dotExt := filepath.Ext(file)
+       name = file[:len(file)-len(dotExt)]
+       if dotExt != "" {
+               ext = dotExt[1:]
+       }
+       return
+}
+
+type stringsFlag []string
+
+func (v *stringsFlag) Set(s string) error {
+       var err error
+       *v, err = splitQuotedFields(s)
+       if *v == nil {
+               *v = []string{}
+       }
+       return err
+}
+
+func splitQuotedFields(s string) ([]string, error) {
+       // Split fields allowing '' or "" around elements.
+       // Quotes further inside the string do not count.
+       var f []string
+       for len(s) > 0 {
+               for len(s) > 0 && isSpaceByte(s[0]) {
+                       s = s[1:]
+               }
+               if len(s) == 0 {
+                       break
+               }
+               // Accepted quoted string. No unescaping inside.
+               if s[0] == '"' || s[0] == '\'' {
+                       quote := s[0]
+                       s = s[1:]
+                       i := 0
+                       for i < len(s) && s[i] != quote {
+                               i++
+                       }
+                       if i >= len(s) {
+                               return nil, fmt.Errorf("unterminated %c string", quote)
+                       }
+                       f = append(f, s[:i])
+                       s = s[i+1:]
+                       continue
+               }
+               i := 0
+               for i < len(s) && !isSpaceByte(s[i]) {
+                       i++
+               }
+               f = append(f, s[:i])
+               s = s[i:]
+       }
+       return f, nil
+}
+
+func (v *stringsFlag) String() string {
+       return "<stringsFlag>"
+}
+
+func runBuild(cmd *Command, args []string) {
+       raceInit()
+       var b builder
+       b.init()
+
+       pkgs := packagesForBuild(args)
+
+       if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" {
+               _, *buildO = path.Split(pkgs[0].ImportPath)
+               *buildO += exeSuffix
+       }
+
+       // sanity check some often mis-used options
+       switch buildContext.Compiler {
+       case "gccgo":
+               if len(buildGcflags) != 0 {
+                       fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
+               }
+               if len(buildLdflags) != 0 {
+                       fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
+               }
+       case "gc":
+               if len(buildGccgoflags) != 0 {
+                       fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
+               }
+       }
+
+       if *buildO != "" {
+               if len(pkgs) > 1 {
+                       fatalf("go build: cannot use -o with multiple packages")
+               }
+               p := pkgs[0]
+               p.target = "" // must build - not up to date
+               a := b.action(modeInstall, modeBuild, p)
+               a.target = *buildO
+               b.do(a)
+               return
+       }
+
+       a := &action{}
+       depMode := modeBuild
+       if buildI {
+               depMode = modeInstall
+       }
+       for _, p := range packages(args) {
+               a.deps = append(a.deps, b.action(modeBuild, depMode, p))
+       }
+       b.do(a)
+}
+
+var cmdInstall = &Command{
+       UsageLine: "install [build flags] [packages]",
+       Short:     "compile and install packages and dependencies",
+       Long: `
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+For more about the build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
+
+See also: go build, go get, go clean.
+       `,
+}
+
+func runInstall(cmd *Command, args []string) {
+       raceInit()
+       pkgs := packagesForBuild(args)
+
+       for _, p := range pkgs {
+               if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
+                       if p.cmdline {
+                               errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
+                       } else if p.ConflictDir != "" {
+                               errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
+                       } else {
+                               errorf("go install: no install location for directory %s outside GOPATH", p.Dir)
+                       }
+               }
+       }
+       exitIfErrors()
+
+       var b builder
+       b.init()
+       a := &action{}
+       for _, p := range pkgs {
+               a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
+       }
+       b.do(a)
+}
+
+// Global build parameters (used during package load)
+var (
+       goarch    string
+       goos      string
+       archChar  string
+       exeSuffix string
+)
+
+func init() {
+       goarch = buildContext.GOARCH
+       goos = buildContext.GOOS
+       if goos == "windows" {
+               exeSuffix = ".exe"
+       }
+       var err error
+       archChar, err = build.ArchChar(goarch)
+       if err != nil {
+               if _, isgc := buildToolchain.(gcToolchain); isgc {
+                       fatalf("%s", err)
+               }
+               // archChar is only required for gcToolchain, if we're using
+               // another toolchain leave it blank.
+               archChar = ""
+       }
+}
+
+// A builder holds global state about a build.
+// It does not hold per-package state, because we
+// build packages in parallel, and the builder is shared.
+type builder struct {
+       work        string               // the temporary work directory (ends in filepath.Separator)
+       actionCache map[cacheKey]*action // a cache of already-constructed actions
+       mkdirCache  map[string]bool      // a cache of created directories
+       print       func(args ...interface{}) (int, error)
+
+       output    sync.Mutex
+       scriptDir string // current directory in printed script
+
+       exec      sync.Mutex
+       readySema chan bool
+       ready     actionQueue
+}
+
+// An action represents a single action in the action graph.
+type action struct {
+       p          *Package      // the package this action works on
+       deps       []*action     // actions that must happen before this one
+       triggers   []*action     // inverse of deps
+       cgo        *action       // action for cgo binary if needed
+       args       []string      // additional args for runProgram
+       testOutput *bytes.Buffer // test output buffer
+
+       f          func(*builder, *action) error // the action itself (nil = no-op)
+       ignoreFail bool                          // whether to run f even if dependencies fail
+
+       // Generated files, directories.
+       link   bool   // target is executable, not just package
+       pkgdir string // the -I or -L argument to use when importing this package
+       objdir string // directory for intermediate objects
+       objpkg string // the intermediate package .a file created during the action
+       target string // goal of the action: the created package or executable
+
+       // Execution state.
+       pending  int  // number of deps yet to complete
+       priority int  // relative execution priority
+       failed   bool // whether the action failed
+}
+
+// cacheKey is the key for the action cache.
+type cacheKey struct {
+       mode buildMode
+       p    *Package
+}
+
+// buildMode specifies the build mode:
+// are we just building things or also installing the results?
+type buildMode int
+
+const (
+       modeBuild buildMode = iota
+       modeInstall
+)
+
+var (
+       goroot       = filepath.Clean(runtime.GOROOT())
+       gobin        = os.Getenv("GOBIN")
+       gorootBin    = filepath.Join(goroot, "bin")
+       gorootSrcPkg = filepath.Join(goroot, "src/pkg")
+       gorootPkg    = filepath.Join(goroot, "pkg")
+       gorootSrc    = filepath.Join(goroot, "src")
+)
+
+func (b *builder) init() {
+       var err error
+       b.print = func(a ...interface{}) (int, error) {
+               return fmt.Fprint(os.Stderr, a...)
+       }
+       b.actionCache = make(map[cacheKey]*action)
+       b.mkdirCache = make(map[string]bool)
+
+       if buildN {
+               b.work = "$WORK"
+       } else {
+               b.work, err = ioutil.TempDir("", "go-build")
+               if err != nil {
+                       fatalf("%s", err)
+               }
+               if buildX || buildWork {
+                       fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work)
+               }
+               if !buildWork {
+                       workdir := b.work
+                       atexit(func() { os.RemoveAll(workdir) })
+               }
+       }
+}
+
+// goFilesPackage creates a package for building a collection of Go files
+// (typically named on the command line).  The target is named p.a for
+// package p or named after the first Go file for package main.
+func goFilesPackage(gofiles []string) *Package {
+       // TODO: Remove this restriction.
+       for _, f := range gofiles {
+               if !strings.HasSuffix(f, ".go") {
+                       fatalf("named files must be .go files")
+               }
+       }
+
+       var stk importStack
+       ctxt := buildContext
+       ctxt.UseAllFiles = true
+
+       // Synthesize fake "directory" that only shows the named files,
+       // to make it look like this is a standard package or
+       // command directory.  So that local imports resolve
+       // consistently, the files must all be in the same directory.
+       var dirent []os.FileInfo
+       var dir string
+       for _, file := range gofiles {
+               fi, err := os.Stat(file)
+               if err != nil {
+                       fatalf("%s", err)
+               }
+               if fi.IsDir() {
+                       fatalf("%s is a directory, should be a Go file", file)
+               }
+               dir1, _ := filepath.Split(file)
+               if dir == "" {
+                       dir = dir1
+               } else if dir != dir1 {
+                       fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
+               }
+               dirent = append(dirent, fi)
+       }
+       ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
+
+       if !filepath.IsAbs(dir) {
+               dir = filepath.Join(cwd, dir)
+       }
+
+       bp, err := ctxt.ImportDir(dir, 0)
+       pkg := new(Package)
+       pkg.local = true
+       pkg.cmdline = true
+       pkg.load(&stk, bp, err)
+       pkg.localPrefix = dirToImportPath(dir)
+       pkg.ImportPath = "command-line-arguments"
+       pkg.target = ""
+
+       if pkg.Name == "main" {
+               _, elem := filepath.Split(gofiles[0])
+               exe := elem[:len(elem)-len(".go")] + exeSuffix
+               if *buildO == "" {
+                       *buildO = exe
+               }
+               if gobin != "" {
+                       pkg.target = filepath.Join(gobin, exe)
+               }
+       } else {
+               if *buildO == "" {
+                       *buildO = pkg.Name + ".a"
+               }
+       }
+       pkg.Target = pkg.target
+       pkg.Stale = true
+
+       computeStale(pkg)
+       return pkg
+}
+
+// action returns the action for applying the given operation (mode) to the package.
+// depMode is the action to use when building dependencies.
+func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
+       key := cacheKey{mode, p}
+       a := b.actionCache[key]
+       if a != nil {
+               return a
+       }
+
+       a = &action{p: p, pkgdir: p.build.PkgRoot}
+       if p.pkgdir != "" { // overrides p.t
+               a.pkgdir = p.pkgdir
+       }
+
+       b.actionCache[key] = a
+
+       for _, p1 := range p.imports {
+               a.deps = append(a.deps, b.action(depMode, depMode, p1))
+       }
+
+       // If we are not doing a cross-build, then record the binary we'll
+       // generate for cgo as a dependency of the build of any package
+       // using cgo, to make sure we do not overwrite the binary while
+       // a package is using it.  If this is a cross-build, then the cgo we
+       // are writing is not the cgo we need to use.
+
+       if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
+               if reqPkgSrc {
+                       if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" {
+                               var stk importStack
+                               p1 := loadPackage("cmd/cgo", &stk)
+                               if p1.Error != nil {
+                                       fatalf("load cmd/cgo: %v", p1.Error)
+                               }
+                               a.cgo = b.action(depMode, depMode, p1)
+                               a.deps = append(a.deps, a.cgo)
+                       }
+               }
+       }
+
+       if p.Standard {
+               switch p.ImportPath {
+               case "builtin", "unsafe":
+                       // Fake packages - nothing to build.
+                       return a
+               }
+               // gccgo standard library is "fake" too.
+               if _, ok := buildToolchain.(gccgoToolchain); ok {
+                       // the target name is needed for cgo.
+                       a.target = p.target
+                       return a
+               }
+       }
+
+       if !p.Stale && p.target != "" {
+               // p.Stale==false implies that p.target is up-to-date.
+               // Record target name for use by actions depending on this one.
+               a.target = p.target
+               return a
+       }
+
+       if p.local && p.target == "" {
+               // Imported via local path.  No permanent target.
+               mode = modeBuild
+       }
+       work := p.pkgdir
+       if work == "" {
+               work = b.work
+       }
+       a.objdir = filepath.Join(work, a.p.ImportPath, "_obj") + string(filepath.Separator)
+       a.objpkg = buildToolchain.pkgpath(work, a.p)
+       a.link = p.Name == "main"
+
+       switch mode {
+       case modeInstall:
+               a.f = (*builder).install
+               a.deps = []*action{b.action(modeBuild, depMode, p)}
+               a.target = a.p.target
+       case modeBuild:
+               a.f = (*builder).build
+               a.target = a.objpkg
+               if a.link {
+                       // An executable file. (This is the name of a temporary file.)
+                       // Because we run the temporary file in 'go run' and 'go test',
+                       // the name will show up in ps listings. If the caller has specified
+                       // a name, use that instead of a.out. The binary is generated
+                       // in an otherwise empty subdirectory named exe to avoid
+                       // naming conflicts.  The only possible conflict is if we were
+                       // to create a top-level package named exe.
+                       name := "a.out"
+                       if p.exeName != "" {
+                               name = p.exeName
+                       }
+                       a.target = a.objdir + filepath.Join("exe", name) + exeSuffix
+               }
+       }
+
+       return a
+}
+
+// actionList returns the list of actions in the dag rooted at root
+// as visited in a depth-first post-order traversal.
+func actionList(root *action) []*action {
+       seen := map[*action]bool{}
+       all := []*action{}
+       var walk func(*action)
+       walk = func(a *action) {
+               if seen[a] {
+                       return
+               }
+               seen[a] = true
+               for _, a1 := range a.deps {
+                       walk(a1)
+               }
+               all = append(all, a)
+       }
+       walk(root)
+       return all
+}
+
+// do runs the action graph rooted at root.
+func (b *builder) do(root *action) {
+       // Build list of all actions, assigning depth-first post-order priority.
+       // The original implementation here was a true queue
+       // (using a channel) but it had the effect of getting
+       // distracted by low-level leaf actions to the detriment
+       // of completing higher-level actions.  The order of
+       // work does not matter much to overall execution time,
+       // but when running "go test std" it is nice to see each test
+       // results as soon as possible.  The priorities assigned
+       // ensure that, all else being equal, the execution prefers
+       // to do what it would have done first in a simple depth-first
+       // dependency order traversal.
+       all := actionList(root)
+       for i, a := range all {
+               a.priority = i
+       }
+
+       b.readySema = make(chan bool, len(all))
+
+       // Initialize per-action execution state.
+       for _, a := range all {
+               for _, a1 := range a.deps {
+                       a1.triggers = append(a1.triggers, a)
+               }
+               a.pending = len(a.deps)
+               if a.pending == 0 {
+                       b.ready.push(a)
+                       b.readySema <- true
+               }
+       }
+
+       // Handle runs a single action and takes care of triggering
+       // any actions that are runnable as a result.
+       handle := func(a *action) {
+               var err error
+               if a.f != nil && (!a.failed || a.ignoreFail) {
+                       err = a.f(b, a)
+               }
+
+               // The actions run in parallel but all the updates to the
+               // shared work state are serialized through b.exec.
+               b.exec.Lock()
+               defer b.exec.Unlock()
+
+               if err != nil {
+                       if err == errPrintedOutput {
+                               setExitStatus(2)
+                       } else {
+                               errorf("%s", err)
+                       }
+                       a.failed = true
+               }
+
+               for _, a0 := range a.triggers {
+                       if a.failed {
+                               a0.failed = true
+                       }
+                       if a0.pending--; a0.pending == 0 {
+                               b.ready.push(a0)
+                               b.readySema <- true
+                       }
+               }
+
+               if a == root {
+                       close(b.readySema)
+               }
+       }
+
+       var wg sync.WaitGroup
+
+       // Kick off goroutines according to parallelism.
+       // If we are using the -n flag (just printing commands)
+       // drop the parallelism to 1, both to make the output
+       // deterministic and because there is no real work anyway.
+       par := buildP
+       if buildN {
+               par = 1
+       }
+       for i := 0; i < par; i++ {
+               wg.Add(1)
+               go func() {
+                       defer wg.Done()
+                       for {
+                               select {
+                               case _, ok := <-b.readySema:
+                                       if !ok {
+                                               return
+                                       }
+                                       // Receiving a value from b.readySema entitles
+                                       // us to take from the ready queue.
+                                       b.exec.Lock()
+                                       a := b.ready.pop()
+                                       b.exec.Unlock()
+                                       handle(a)
+                               case <-interrupted:
+                                       setExitStatus(1)
+                                       return
+                               }
+                       }
+               }()
+       }
+
+       wg.Wait()
+}
+
+// hasString reports whether s appears in the list of strings.
+func hasString(strings []string, s string) bool {
+       for _, t := range strings {
+               if s == t {
+                       return true
+               }
+       }
+       return false
+}
+
+// build is the action for building a single package or command.
+func (b *builder) build(a *action) (err error) {
+       // Return an error if the package has CXX files but it's not using
+       // cgo nor SWIG, since the CXX files can only be processed by cgo
+       // and SWIG (it's possible to have packages with C files without
+       // using cgo, they will get compiled with the plan9 C compiler and
+       // linked with the rest of the package).
+       if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+               return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG",
+                       a.p.ImportPath, strings.Join(a.p.CXXFiles, ","))
+       }
+       // Same as above for Objective-C files
+       if len(a.p.MFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+               return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG",
+                       a.p.ImportPath, strings.Join(a.p.MFiles, ","))
+       }
+       defer func() {
+               if err != nil && err != errPrintedOutput {
+                       err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
+               }
+       }()
+       if buildN {
+               // In -n mode, print a banner between packages.
+               // The banner is five lines so that when changes to
+               // different sections of the bootstrap script have to
+               // be merged, the banners give patch something
+               // to use to find its context.
+               fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath)
+       }
+
+       if buildV {
+               fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
+       }
+
+       if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
+               !hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") {
+               return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix())
+       }
+
+       // Make build directory.
+       obj := a.objdir
+       if err := b.mkdir(obj); err != nil {
+               return err
+       }
+
+       // make target directory
+       dir, _ := filepath.Split(a.target)
+       if dir != "" {
+               if err := b.mkdir(dir); err != nil {
+                       return err
+               }
+       }
+
+       var gofiles, cfiles, sfiles, objects, cgoObjects []string
+
+       gofiles = append(gofiles, a.p.GoFiles...)
+       cfiles = append(cfiles, a.p.CFiles...)
+       sfiles = append(sfiles, a.p.SFiles...)
+
+       // Run cgo.
+       if a.p.usesCgo() {
+               // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
+               // There is one exception: runtime/cgo's job is to bridge the
+               // cgo and non-cgo worlds, so it necessarily has files in both.
+               // In that case gcc only gets the gcc_* files.
+               var gccfiles []string
+               if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
+                       filter := func(files, nongcc, gcc []string) ([]string, []string) {
+                               for _, f := range files {
+                                       if strings.HasPrefix(f, "gcc_") {
+                                               gcc = append(gcc, f)
+                                       } else {
+                                               nongcc = append(nongcc, f)
+                                       }
+                               }
+                               return nongcc, gcc
+                       }
+                       cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles)
+                       sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
+               } else {
+                       gccfiles = append(cfiles, sfiles...)
+                       cfiles = nil
+                       sfiles = nil
+               }
+
+               cgoExe := tool("cgo")
+               if a.cgo != nil && a.cgo.target != "" {
+                       cgoExe = a.cgo.target
+               }
+               outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles, a.p.CXXFiles, a.p.MFiles)
+               if err != nil {
+                       return err
+               }
+               cgoObjects = append(cgoObjects, outObj...)
+               gofiles = append(gofiles, outGo...)
+       }
+
+       // Run SWIG.
+       if a.p.usesSwig() {
+               // In a package using SWIG, any .c or .s files are
+               // compiled with gcc.
+               gccfiles := append(cfiles, sfiles...)
+               cfiles = nil
+               sfiles = nil
+               outGo, outObj, err := b.swig(a.p, obj, gccfiles, a.p.CXXFiles, a.p.MFiles)
+               if err != nil {
+                       return err
+               }
+               cgoObjects = append(cgoObjects, outObj...)
+               gofiles = append(gofiles, outGo...)
+       }
+
+       if len(gofiles) == 0 {
+               return &build.NoGoError{a.p.Dir}
+       }
+
+       // If we're doing coverage, preprocess the .go files and put them in the work directory
+       if a.p.coverMode != "" {
+               for i, file := range gofiles {
+                       var sourceFile string
+                       var coverFile string
+                       var key string
+                       if strings.HasSuffix(file, ".cgo1.go") {
+                               // cgo files have absolute paths
+                               base := filepath.Base(file)
+                               sourceFile = file
+                               coverFile = filepath.Join(obj, base)
+                               key = strings.TrimSuffix(base, ".cgo1.go") + ".go"
+                       } else {
+                               sourceFile = filepath.Join(a.p.Dir, file)
+                               coverFile = filepath.Join(obj, file)
+                               key = file
+                       }
+                       cover := a.p.coverVars[key]
+                       if cover == nil || isTestFile(file) {
+                               // Not covering this file.
+                               continue
+                       }
+                       if err := b.cover(a, coverFile, sourceFile, 0666, cover.Var); err != nil {
+                               return err
+                       }
+                       gofiles[i] = coverFile
+               }
+       }
+
+       // Prepare Go import path list.
+       inc := b.includeArgs("-I", a.deps)
+
+       // Compile Go.
+       ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, inc, gofiles)
+       if len(out) > 0 {
+               b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out))
+               if err != nil {
+                       return errPrintedOutput
+               }
+       }
+       if err != nil {
+               return err
+       }
+       if ofile != a.objpkg {
+               objects = append(objects, ofile)
+       }
+
+       // Copy .h files named for goos or goarch or goos_goarch
+       // to names using GOOS and GOARCH.
+       // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
+       _goos_goarch := "_" + goos + "_" + goarch
+       _goos := "_" + goos
+       _goarch := "_" + goarch
+       for _, file := range a.p.HFiles {
+               name, ext := fileExtSplit(file)
+               switch {
+               case strings.HasSuffix(name, _goos_goarch):
+                       targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
+                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil {
+                               return err
+                       }
+               case strings.HasSuffix(name, _goarch):
+                       targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
+                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil {
+                               return err
+                       }
+               case strings.HasSuffix(name, _goos):
+                       targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
+                       if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil {
+                               return err
+                       }
+               }
+       }
+
+       objExt := archChar
+       if _, ok := buildToolchain.(gccgoToolchain); ok {
+               objExt = "o"
+       }
+
+       for _, file := range cfiles {
+               out := file[:len(file)-len(".c")] + "." + objExt
+               if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil {
+                       return err
+               }
+               objects = append(objects, out)
+       }
+
+       // Assemble .s files.
+       for _, file := range sfiles {
+               out := file[:len(file)-len(".s")] + "." + objExt
+               if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil {
+                       return err
+               }
+               objects = append(objects, out)
+       }
+
+       // NOTE(rsc): On Windows, it is critically important that the
+       // gcc-compiled objects (cgoObjects) be listed after the ordinary
+       // objects in the archive.  I do not know why this is.
+       // http://golang.org/issue/2601
+       objects = append(objects, cgoObjects...)
+
+       // Add system object files.
+       for _, syso := range a.p.SysoFiles {
+               objects = append(objects, filepath.Join(a.p.Dir, syso))
+       }
+
+       // Pack into archive in obj directory.
+       // If the Go compiler wrote an archive, we only need to add the
+       // object files for non-Go sources to the archive.
+       // If the Go compiler wrote an archive and the package is entirely
+       // Go sources, there is no pack to execute at all.
+       if len(objects) > 0 {
+               if err := buildToolchain.pack(b, a.p, obj, a.objpkg, objects); err != nil {
+                       return err
+               }
+       }
+
+       // Link if needed.
+       if a.link {
+               // The compiler only cares about direct imports, but the
+               // linker needs the whole dependency tree.
+               all := actionList(a)
+               all = all[:len(all)-1] // drop a
+               if err := buildToolchain.ld(b, a.p, a.target, all, a.objpkg, objects); err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
+// install is the action for installing a single package or executable.
+func (b *builder) install(a *action) (err error) {
+       defer func() {
+               if err != nil && err != errPrintedOutput {
+                       err = fmt.Errorf("go install %s: %v", a.p.ImportPath, err)
+               }
+       }()
+       a1 := a.deps[0]
+       perm := os.FileMode(0644)
+       if a1.link {
+               perm = 0755
+       }
+
+       // make target directory
+       dir, _ := filepath.Split(a.target)
+       if dir != "" {
+               if err := b.mkdir(dir); err != nil {
+                       return err
+               }
+       }
+
+       // remove object dir to keep the amount of
+       // garbage down in a large build.  On an operating system
+       // with aggressive buffering, cleaning incrementally like
+       // this keeps the intermediate objects from hitting the disk.
+       if !buildWork {
+               defer os.RemoveAll(a1.objdir)
+               defer os.Remove(a1.target)
+       }
+
+       return b.moveOrCopyFile(a, a.target, a1.target, perm)
+}
+
+// includeArgs returns the -I or -L directory list for access
+// to the results of the list of actions.
+func (b *builder) includeArgs(flag string, all []*action) []string {
+       inc := []string{}
+       incMap := map[string]bool{
+               b.work:    true, // handled later
+               gorootPkg: true,
+               "":        true, // ignore empty strings
+       }
+
+       // Look in the temporary space for results of test-specific actions.
+       // This is the $WORK/my/package/_test directory for the
+       // package being built, so there are few of these.
+       for _, a1 := range all {
+               if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] {
+                       incMap[dir] = true
+                       inc = append(inc, flag, dir)
+               }
+       }
+
+       // Also look in $WORK for any non-test packages that have
+       // been built but not installed.
+       inc = append(inc, flag, b.work)
+
+       // Finally, look in the installed package directories for each action.
+       for _, a1 := range all {
+               if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
+                       incMap[dir] = true
+                       if _, ok := buildToolchain.(gccgoToolchain); ok {
+                               dir = filepath.Join(dir, "gccgo_"+goos+"_"+goarch)
+                       } else {
+                               dir = filepath.Join(dir, goos+"_"+goarch)
+                               if buildContext.InstallSuffix != "" {
+                                       dir += "_" + buildContext.InstallSuffix
+                               }
+                       }
+                       inc = append(inc, flag, dir)
+               }
+       }
+
+       return inc
+}
+
+// moveOrCopyFile is like 'mv src dst' or 'cp src dst'.
+func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode) error {
+       if buildN {
+               b.showcmd("", "mv %s %s", src, dst)
+               return nil
+       }
+
+       // If we can update the mode and rename to the dst, do it.
+       // Otherwise fall back to standard copy.
+       if err := os.Chmod(src, perm); err == nil {
+               if err := os.Rename(src, dst); err == nil {
+                       if buildX {
+                               b.showcmd("", "mv %s %s", src, dst)
+                       }
+                       return nil
+               }
+       }
+
+       return b.copyFile(a, dst, src, perm)
+}
+
+// copyFile is like 'cp src dst'.
+func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode) error {
+       if buildN || buildX {
+               b.showcmd("", "cp %s %s", src, dst)
+               if buildN {
+                       return nil
+               }
+       }
+
+       sf, err := os.Open(src)
+       if err != nil {
+               return err
+       }
+       defer sf.Close()
+
+       // Be careful about removing/overwriting dst.
+       // Do not remove/overwrite if dst exists and is a directory
+       // or a non-object file.
+       if fi, err := os.Stat(dst); err == nil {
+               if fi.IsDir() {
+                       return fmt.Errorf("build output %q already exists and is a directory", dst)
+               }
+               if !isObject(dst) {
+                       return fmt.Errorf("build output %q already exists and is not an object file", dst)
+               }
+       }
+
+       // On Windows, remove lingering ~ file from last attempt.
+       if toolIsWindows {
+               if _, err := os.Stat(dst + "~"); err == nil {
+                       os.Remove(dst + "~")
+               }
+       }
+
+       os.Remove(dst)
+       df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+       if err != nil && toolIsWindows {
+               // Windows does not allow deletion of a binary file
+               // while it is executing.  Try to move it out of the way.
+               // If the move fails, which is likely, we'll try again the
+               // next time we do an install of this binary.
+               if err := os.Rename(dst, dst+"~"); err == nil {
+                       os.Remove(dst + "~")
+               }
+               df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+       }
+       if err != nil {
+               return err
+       }
+
+       _, err = io.Copy(df, sf)
+       df.Close()
+       if err != nil {
+               os.Remove(dst)
+               return fmt.Errorf("copying %s to %s: %v", src, dst, err)
+       }
+       return nil
+}
+
+// cover runs, in effect,
+//     go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
+func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error {
+       return b.run(a.objdir, "cover "+a.p.ImportPath, nil,
+               tool("cover"),
+               "-mode", a.p.coverMode,
+               "-var", varName,
+               "-o", dst,
+               src)
+}
+
+var objectMagic = [][]byte{
+       {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'},        // Package archive
+       {'\x7F', 'E', 'L', 'F'},                          // ELF
+       {0xFE, 0xED, 0xFA, 0xCE},                         // Mach-O big-endian 32-bit
+       {0xFE, 0xED, 0xFA, 0xCF},                         // Mach-O big-endian 64-bit
+       {0xCE, 0xFA, 0xED, 0xFE},                         // Mach-O little-endian 32-bit
+       {0xCF, 0xFA, 0xED, 0xFE},                         // Mach-O little-endian 64-bit
+       {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x04, 0x00}, // PE (Windows) as generated by 6l/8l
+       {0x00, 0x00, 0x01, 0xEB},                         // Plan 9 i386
+       {0x00, 0x00, 0x8a, 0x97},                         // Plan 9 amd64
+}
+
+func isObject(s string) bool {
+       f, err := os.Open(s)
+       if err != nil {
+               return false
+       }
+       defer f.Close()
+       buf := make([]byte, 64)
+       io.ReadFull(f, buf)
+       for _, magic := range objectMagic {
+               if bytes.HasPrefix(buf, magic) {
+                       return true
+               }
+       }
+       return false
+}
+
+// fmtcmd formats a command in the manner of fmt.Sprintf but also:
+//
+//     If dir is non-empty and the script is not in dir right now,
+//     fmtcmd inserts "cd dir\n" before the command.
+//
+//     fmtcmd replaces the value of b.work with $WORK.
+//     fmtcmd replaces the value of goroot with $GOROOT.
+//     fmtcmd replaces the value of b.gobin with $GOBIN.
+//
+//     fmtcmd replaces the name of the current directory with dot (.)
+//     but only when it is at the beginning of a space-separated token.
+//
+func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string {
+       cmd := fmt.Sprintf(format, args...)
+       if dir != "" && dir != "/" {
+               cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:]
+               if b.scriptDir != dir {
+                       b.scriptDir = dir
+                       cmd = "cd " + dir + "\n" + cmd
+               }
+       }
+       if b.work != "" {
+               cmd = strings.Replace(cmd, b.work, "$WORK", -1)
+       }
+       return cmd
+}
+
+// showcmd prints the given command to standard output
+// for the implementation of -n or -x.
+func (b *builder) showcmd(dir string, format string, args ...interface{}) {
+       b.output.Lock()
+       defer b.output.Unlock()
+       b.print(b.fmtcmd(dir, format, args...) + "\n")
+}
+
+// showOutput prints "# desc" followed by the given output.
+// The output is expected to contain references to 'dir', usually
+// the source directory for the package that has failed to build.
+// showOutput rewrites mentions of dir with a relative path to dir
+// when the relative path is shorter.  This is usually more pleasant.
+// For example, if fmt doesn't compile and we are in src/pkg/html,
+// the output is
+//
+//     $ go build
+//     # fmt
+//     ../fmt/print.go:1090: undefined: asdf
+//     $
+//
+// instead of
+//
+//     $ go build
+//     # fmt
+//     /usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf
+//     $
+//
+// showOutput also replaces references to the work directory with $WORK.
+//
+func (b *builder) showOutput(dir, desc, out string) {
+       prefix := "# " + desc
+       suffix := "\n" + out
+       if reldir := shortPath(dir); reldir != dir {
+               suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1)
+               suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1)
+       }
+       suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1)
+
+       b.output.Lock()
+       defer b.output.Unlock()
+       b.print(prefix, suffix)
+}
+
+// shortPath returns an absolute or relative name for path, whatever is shorter.
+func shortPath(path string) string {
+       if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
+               return rel
+       }
+       return path
+}
+
+// relPaths returns a copy of paths with absolute paths
+// made relative to the current directory if they would be shorter.
+func relPaths(paths []string) []string {
+       var out []string
+       pwd, _ := os.Getwd()
+       for _, p := range paths {
+               rel, err := filepath.Rel(pwd, p)
+               if err == nil && len(rel) < len(p) {
+                       p = rel
+               }
+               out = append(out, p)
+       }
+       return out
+}
+
+// errPrintedOutput is a special error indicating that a command failed
+// but that it generated output as well, and that output has already
+// been printed, so there's no point showing 'exit status 1' or whatever
+// the wait status was.  The main executor, builder.do, knows not to
+// print this error.
+var errPrintedOutput = errors.New("already printed output - no need to show error")
+
+var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`)
+var cgoTypeSigRe = regexp.MustCompile(`\b_Ctype_\B`)
+
+// run runs the command given by cmdline in the directory dir.
+// If the command fails, run prints information about the failure
+// and returns a non-nil error.
+func (b *builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error {
+       out, err := b.runOut(dir, desc, env, cmdargs...)
+       if len(out) > 0 {
+               if desc == "" {
+                       desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
+               }
+               b.showOutput(dir, desc, b.processOutput(out))
+               if err != nil {
+                       err = errPrintedOutput
+               }
+       }
+       return err
+}
+
+// processOutput prepares the output of runOut to be output to the console.
+func (b *builder) processOutput(out []byte) string {
+       if out[len(out)-1] != '\n' {
+               out = append(out, '\n')
+       }
+       messages := string(out)
+       // Fix up output referring to cgo-generated code to be more readable.
+       // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
+       // Replace *[100]_Ctype_foo with *[100]C.foo.
+       // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
+       if !buildX && cgoLine.MatchString(messages) {
+               messages = cgoLine.ReplaceAllString(messages, "")
+               messages = cgoTypeSigRe.ReplaceAllString(messages, "C.")
+       }
+       return messages
+}
+
+// runOut runs the command given by cmdline in the directory dir.
+// It returns the command output and any errors that occurred.
+func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
+       cmdline := stringList(cmdargs...)
+       if buildN || buildX {
+               var envcmdline string
+               for i := range env {
+                       envcmdline += env[i]
+                       envcmdline += " "
+               }
+               envcmdline += joinUnambiguously(cmdline)
+               b.showcmd(dir, "%s", envcmdline)
+               if buildN {
+                       return nil, nil
+               }
+       }
+
+       nbusy := 0
+       for {
+               var buf bytes.Buffer
+               cmd := exec.Command(cmdline[0], cmdline[1:]...)
+               cmd.Stdout = &buf
+               cmd.Stderr = &buf
+               cmd.Dir = dir
+               cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir))
+               err := cmd.Run()
+
+               // cmd.Run will fail on Unix if some other process has the binary
+               // we want to run open for writing.  This can happen here because
+               // we build and install the cgo command and then run it.
+               // If another command was kicked off while we were writing the
+               // cgo binary, the child process for that command may be holding
+               // a reference to the fd, keeping us from running exec.
+               //
+               // But, you might reasonably wonder, how can this happen?
+               // The cgo fd, like all our fds, is close-on-exec, so that we need
+               // not worry about other processes inheriting the fd accidentally.
+               // The answer is that running a command is fork and exec.
+               // A child forked while the cgo fd is open inherits that fd.
+               // Until the child has called exec, it holds the fd open and the
+               // kernel will not let us run cgo.  Even if the child were to close
+               // the fd explicitly, it would still be open from the time of the fork
+               // until the time of the explicit close, and the race would remain.
+               //
+               // On Unix systems, this results in ETXTBSY, which formats
+               // as "text file busy".  Rather than hard-code specific error cases,
+               // we just look for that string.  If this happens, sleep a little
+               // and try again.  We let this happen three times, with increasing
+               // sleep lengths: 100+200+400 ms = 0.7 seconds.
+               //
+               // An alternate solution might be to split the cmd.Run into
+               // separate cmd.Start and cmd.Wait, and then use an RWLock
+               // to make sure that copyFile only executes when no cmd.Start
+               // call is in progress.  However, cmd.Start (really syscall.forkExec)
+               // only guarantees that when it returns, the exec is committed to
+               // happen and succeed.  It uses a close-on-exec file descriptor
+               // itself to determine this, so we know that when cmd.Start returns,
+               // at least one close-on-exec file descriptor has been closed.
+               // However, we cannot be sure that all of them have been closed,
+               // so the program might still encounter ETXTBSY even with such
+               // an RWLock.  The race window would be smaller, perhaps, but not
+               // guaranteed to be gone.
+               //
+               // Sleeping when we observe the race seems to be the most reliable
+               // option we have.
+               //
+               // http://golang.org/issue/3001
+               //
+               if err != nil && nbusy < 3 && strings.Contains(err.Error(), "text file busy") {
+                       time.Sleep(100 * time.Millisecond << uint(nbusy))
+                       nbusy++
+                       continue
+               }
+
+               return buf.Bytes(), err
+       }
+}
+
+// joinUnambiguously prints the slice, quoting where necessary to make the
+// output unambiguous.
+// TODO: See issue 5279. The printing of commands needs a complete redo.
+func joinUnambiguously(a []string) string {
+       var buf bytes.Buffer
+       for i, s := range a {
+               if i > 0 {
+                       buf.WriteByte(' ')
+               }
+               q := strconv.Quote(s)
+               if s == "" || strings.Contains(s, " ") || len(q) > len(s)+2 {
+                       buf.WriteString(q)
+               } else {
+                       buf.WriteString(s)
+               }
+       }
+       return buf.String()
+}
+
+// mkdir makes the named directory.
+func (b *builder) mkdir(dir string) error {
+       b.exec.Lock()
+       defer b.exec.Unlock()
+       // We can be a little aggressive about being
+       // sure directories exist.  Skip repeated calls.
+       if b.mkdirCache[dir] {
+               return nil
+       }
+       b.mkdirCache[dir] = true
+
+       if buildN || buildX {
+               b.showcmd("", "mkdir -p %s", dir)
+               if buildN {
+                       return nil
+               }
+       }
+
+       if err := os.MkdirAll(dir, 0777); err != nil {
+               return err
+       }
+       return nil
+}
+
+// mkAbs returns an absolute path corresponding to
+// evaluating f in the directory dir.
+// We always pass absolute paths of source files so that
+// the error messages will include the full path to a file
+// in need of attention.
+func mkAbs(dir, f string) string {
+       // Leave absolute paths alone.
+       // Also, during -n mode we use the pseudo-directory $WORK
+       // instead of creating an actual work directory that won't be used.
+       // Leave paths beginning with $WORK alone too.
+       if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") {
+               return f
+       }
+       return filepath.Join(dir, f)
+}
+
+type toolchain interface {
+       // gc runs the compiler in a specific directory on a set of files
+       // and returns the name of the generated output file.
+       // The compiler runs in the directory dir.
+       gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
+       // cc runs the toolchain's C compiler in a directory on a C file
+       // to produce an output file.
+       cc(b *builder, p *Package, objdir, ofile, cfile string) error
+       // asm runs the assembler in a specific directory on a specific file
+       // to generate the named output file.
+       asm(b *builder, p *Package, obj, ofile, sfile string) error
+       // pkgpath builds an appropriate path for a temporary package file.
+       pkgpath(basedir string, p *Package) string
+       // pack runs the archive packer in a specific directory to create
+       // an archive from a set of object files.
+       // typically it is run in the object directory.
+       pack(b *builder, p *Package, objDir, afile string, ofiles []string) error
+       // ld runs the linker to create a package starting at mainpkg.
+       ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error
+
+       compiler() string
+       linker() string
+}
+
+type noToolchain struct{}
+
+func noCompiler() error {
+       log.Fatalf("unknown compiler %q", buildContext.Compiler)
+       return nil
+}
+
+func (noToolchain) compiler() string {
+       noCompiler()
+       return ""
+}
+
+func (noToolchain) linker() string {
+       noCompiler()
+       return ""
+}
+
+func (noToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
+       return "", nil, noCompiler()
+}
+
+func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+       return noCompiler()
+}
+
+func (noToolchain) pkgpath(basedir string, p *Package) string {
+       noCompiler()
+       return ""
+}
+
+func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+       return noCompiler()
+}
+
+func (noToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
+       return noCompiler()
+}
+
+func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+       return noCompiler()
+}
+
+// The Go toolchain.
+type gcToolchain struct{}
+
+func (gcToolchain) compiler() string {
+       return tool(archChar + "g")
+}
+
+func (gcToolchain) linker() string {
+       return tool(archChar + "l")
+}
+
+func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+       if archive != "" {
+               ofile = archive
+       } else {
+               out := "_go_." + archChar
+               ofile = obj + out
+       }
+
+       gcargs := []string{"-p", p.ImportPath}
+       if p.Standard && p.ImportPath == "runtime" {
+               // runtime compiles with a special 6g flag to emit
+               // additional reflect type data.
+               gcargs = append(gcargs, "-+")
+       }
+
+       // If we're giving the compiler the entire package (no C etc files), tell it that,
+       // so that it can give good error messages about forward declarations.
+       // Exceptions: a few standard packages have forward declarations for
+       // pieces supplied behind-the-scenes by package runtime.
+       extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
+       if p.Standard {
+               switch p.ImportPath {
+               case "os", "runtime/pprof", "sync", "time":
+                       extFiles++
+               }
+       }
+       if extFiles == 0 {
+               gcargs = append(gcargs, "-complete")
+       }
+       if buildContext.InstallSuffix != "" {
+               gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix)
+       }
+
+       args := stringList(tool(archChar+"g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs)
+       if ofile == archive {
+               args = append(args, "-pack")
+       }
+       for _, f := range gofiles {
+               args = append(args, mkAbs(p.Dir, f))
+       }
+
+       output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
+       return ofile, output, err
+}
+
+func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+       sfile = mkAbs(p.Dir, sfile)
+       return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)
+}
+
+func (gcToolchain) pkgpath(basedir string, p *Package) string {
+       end := filepath.FromSlash(p.ImportPath + ".a")
+       return filepath.Join(basedir, end)
+}
+
+func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+       var absOfiles []string
+       for _, f := range ofiles {
+               absOfiles = append(absOfiles, mkAbs(objDir, f))
+       }
+       cmd := "c"
+       absAfile := mkAbs(objDir, afile)
+       appending := false
+       if _, err := os.Stat(absAfile); err == nil {
+               appending = true
+               cmd = "r"
+       }
+
+       cmdline := stringList("pack", cmd, absAfile, absOfiles)
+
+       if appending {
+               if buildN || buildX {
+                       b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
+               }
+               if buildN {
+                       return nil
+               }
+               if err := packInternal(b, absAfile, absOfiles); err != nil {
+                       b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n")
+                       return errPrintedOutput
+               }
+               return nil
+       }
+
+       // Need actual pack.
+       cmdline[0] = tool("pack")
+       return b.run(p.Dir, p.ImportPath, nil, cmdline)
+}
+
+func packInternal(b *builder, afile string, ofiles []string) error {
+       dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0)
+       if err != nil {
+               return err
+       }
+       defer dst.Close() // only for error returns or panics
+       w := bufio.NewWriter(dst)
+
+       for _, ofile := range ofiles {
+               src, err := os.Open(ofile)
+               if err != nil {
+                       return err
+               }
+               fi, err := src.Stat()
+               if err != nil {
+                       src.Close()
+                       return err
+               }
+               // Note: Not using %-16.16s format because we care
+               // about bytes, not runes.
+               name := fi.Name()
+               if len(name) > 16 {
+                       name = name[:16]
+               } else {
+                       name += strings.Repeat(" ", 16-len(name))
+               }
+               size := fi.Size()
+               fmt.Fprintf(w, "%s%-12d%-6d%-6d%-8o%-10d`\n",
+                       name, 0, 0, 0, 0644, size)
+               n, err := io.Copy(w, src)
+               src.Close()
+               if err == nil && n < size {
+                       err = io.ErrUnexpectedEOF
+               } else if err == nil && n > size {
+                       err = fmt.Errorf("file larger than size reported by stat")
+               }
+               if err != nil {
+                       return fmt.Errorf("copying %s to %s: %v", ofile, afile, err)
+               }
+               if size&1 != 0 {
+                       w.WriteByte(0)
+               }
+       }
+
+       if err := w.Flush(); err != nil {
+               return err
+       }
+       return dst.Close()
+}
+
+func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
+       importArgs := b.includeArgs("-L", allactions)
+       cxx := false
+       for _, a := range allactions {
+               if a.p != nil && len(a.p.CXXFiles) > 0 {
+                       cxx = true
+               }
+       }
+       ldflags := buildLdflags
+       // Limit slice capacity so that concurrent appends do not race on the shared array.
+       ldflags = ldflags[:len(ldflags):len(ldflags)]
+       if buildContext.InstallSuffix != "" {
+               ldflags = append(ldflags, "-installsuffix", buildContext.InstallSuffix)
+       }
+       if p.omitDWARF {
+               ldflags = append(ldflags, "-w")
+       }
+
+       // If the user has not specified the -extld option, then specify the
+       // appropriate linker. In case of C++ code, use the compiler named
+       // by the CXX environment variable or defaultCXX if CXX is not set.
+       // Else, use the CC environment variable and defaultCC as fallback.
+       extld := false
+       for _, f := range ldflags {
+               if f == "-extld" || strings.HasPrefix(f, "-extld=") {
+                       extld = true
+                       break
+               }
+       }
+       if !extld {
+               var compiler []string
+               if cxx {
+                       compiler = envList("CXX", defaultCXX)
+               } else {
+                       compiler = envList("CC", defaultCC)
+               }
+               ldflags = append(ldflags, "-extld="+compiler[0])
+               if len(compiler) > 1 {
+                       extldflags := false
+                       add := strings.Join(compiler[1:], " ")
+                       for i, f := range ldflags {
+                               if f == "-extldflags" && i+1 < len(ldflags) {
+                                       ldflags[i+1] = add + " " + ldflags[i+1]
+                                       extldflags = true
+                                       break
+                               } else if strings.HasPrefix(f, "-extldflags=") {
+                                       ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):]
+                                       extldflags = true
+                                       break
+                               }
+                       }
+                       if !extldflags {
+                               ldflags = append(ldflags, "-extldflags="+add)
+                       }
+               }
+       }
+       return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg)
+}
+
+func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+       inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
+       cfile = mkAbs(p.Dir, cfile)
+       args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
+       return b.run(p.Dir, p.ImportPath, nil, args)
+}
+
+// The Gccgo toolchain.
+type gccgoToolchain struct{}
+
+var gccgoBin, _ = exec.LookPath("gccgo")
+
+func (gccgoToolchain) compiler() string {
+       return gccgoBin
+}
+
+func (gccgoToolchain) linker() string {
+       return gccgoBin
+}
+
+func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+       out := p.Name + ".o"
+       ofile = obj + out
+       gcargs := []string{"-g"}
+       gcargs = append(gcargs, b.gccArchArgs()...)
+       if pkgpath := gccgoPkgpath(p); pkgpath != "" {
+               gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath)
+       }
+       if p.localPrefix != "" {
+               gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
+       }
+       args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
+       for _, f := range gofiles {
+               args = append(args, mkAbs(p.Dir, f))
+       }
+
+       output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
+       return ofile, output, err
+}
+
+func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+       sfile = mkAbs(p.Dir, sfile)
+       defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+       if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
+               defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
+       }
+       defs = append(defs, b.gccArchArgs()...)
+       return b.run(p.Dir, p.ImportPath, nil, "gccgo", "-I", obj, "-o", ofile, defs, sfile)
+}
+
+func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
+       end := filepath.FromSlash(p.ImportPath + ".a")
+       afile := filepath.Join(basedir, end)
+       // add "lib" to the final element
+       return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
+}
+
+func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+       var absOfiles []string
+       for _, f := range ofiles {
+               absOfiles = append(absOfiles, mkAbs(objDir, f))
+       }
+       return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles)
+}
+
+func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
+       // gccgo needs explicit linking with all package dependencies,
+       // and all LDFLAGS from cgo dependencies.
+       apackagesSeen := make(map[*Package]bool)
+       afiles := []string{}
+       ldflags := b.gccArchArgs()
+       cgoldflags := []string{}
+       usesCgo := false
+       cxx := false
+       objc := false
+
+       // Prefer the output of an install action to the output of a build action,
+       // because the install action will delete the output of the build action.
+       // Iterate over the list backward (reverse dependency order) so that we
+       // always see the install before the build.
+       for i := len(allactions) - 1; i >= 0; i-- {
+               a := allactions[i]
+               if !a.p.Standard {
+                       if a.p != nil && !apackagesSeen[a.p] {
+                               apackagesSeen[a.p] = true
+                               if a.p.fake {
+                                       // move _test files to the top of the link order
+                                       afiles = append([]string{a.target}, afiles...)
+                               } else {
+                                       afiles = append(afiles, a.target)
+                               }
+                       }
+               }
+       }
+
+       for _, a := range allactions {
+               if a.p != nil {
+                       cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...)
+                       if len(a.p.CgoFiles) > 0 {
+                               usesCgo = true
+                       }
+                       if a.p.usesSwig() {
+                               usesCgo = true
+                       }
+                       if len(a.p.CXXFiles) > 0 {
+                               cxx = true
+                       }
+                       if len(a.p.MFiles) > 0 {
+                               objc = true
+                       }
+               }
+       }
+       ldflags = append(ldflags, afiles...)
+       ldflags = append(ldflags, cgoldflags...)
+       ldflags = append(ldflags, p.CgoLDFLAGS...)
+       if usesCgo && goos == "linux" {
+               ldflags = append(ldflags, "-Wl,-E")
+       }
+       if cxx {
+               ldflags = append(ldflags, "-lstdc++")
+       }
+       if objc {
+               ldflags = append(ldflags, "-lobjc")
+       }
+       return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
+}
+
+func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+       inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
+       cfile = mkAbs(p.Dir, cfile)
+       defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+       defs = append(defs, b.gccArchArgs()...)
+       if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
+               defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
+       }
+       // TODO: Support using clang here (during gccgo build)?
+       return b.run(p.Dir, p.ImportPath, nil, "gcc", "-Wall", "-g",
+               "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
+}
+
+func gccgoPkgpath(p *Package) string {
+       if p.build.IsCommand() && !p.forceLibrary {
+               return ""
+       }
+       return p.ImportPath
+}
+
+func gccgoCleanPkgpath(p *Package) string {
+       clean := func(r rune) rune {
+               switch {
+               case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
+                       '0' <= r && r <= '9':
+                       return r
+               }
+               return '_'
+       }
+       return strings.Map(clean, gccgoPkgpath(p))
+}
+
+// libgcc returns the filename for libgcc, as determined by invoking gcc with
+// the -print-libgcc-file-name option.
+func (b *builder) libgcc(p *Package) (string, error) {
+       var buf bytes.Buffer
+
+       gccCmd := b.gccCmd(p.Dir)
+
+       prev := b.print
+       if buildN {
+               // In -n mode we temporarily swap out the builder's
+               // print function to capture the command-line. This
+               // let's us assign it to $LIBGCC and produce a valid
+               // buildscript for cgo packages.
+               b.print = func(a ...interface{}) (int, error) {
+                       return fmt.Fprint(&buf, a...)
+               }
+       }
+       f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name")
+       if err != nil {
+               return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f)
+       }
+       if buildN {
+               s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1))
+               b.print = prev
+               b.print(s)
+               return "$LIBGCC", nil
+       }
+
+       // clang might not be able to find libgcc, and in that case,
+       // it will simply return "libgcc.a", which is of no use to us.
+       if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) {
+               return "", nil
+       }
+
+       return strings.Trim(string(f), "\r\n"), nil
+}
+
+// gcc runs the gcc C compiler to create an object from a single C file.
+func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
+       return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
+}
+
+// gxx runs the g++ C++ compiler to create an object from a single C++ file.
+func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error {
+       return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
+}
+
+// ccompile runs the given C or C++ compiler and creates an object from a single source file.
+func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error {
+       file = mkAbs(p.Dir, file)
+       return b.run(p.Dir, p.ImportPath, nil, compiler, flags, "-o", out, "-c", file)
+}
+
+// gccld runs the gcc linker to create an executable from a set of object files.
+func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error {
+       var cmd []string
+       if len(p.CXXFiles) > 0 {
+               cmd = b.gxxCmd(p.Dir)
+       } else {
+               cmd = b.gccCmd(p.Dir)
+       }
+       return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags)
+}
+
+// gccCmd returns a gcc command line prefix
+// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
+func (b *builder) gccCmd(objdir string) []string {
+       return b.ccompilerCmd("CC", defaultCC, objdir)
+}
+
+// gxxCmd returns a g++ command line prefix
+// defaultCXX is defined in zdefaultcc.go, written by cmd/dist.
+func (b *builder) gxxCmd(objdir string) []string {
+       return b.ccompilerCmd("CXX", defaultCXX, objdir)
+}
+
+// ccompilerCmd returns a command line prefix for the given environment
+// variable and using the default command when the variable is empty.
+func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
+       // NOTE: env.go's mkEnv knows that the first three
+       // strings returned are "gcc", "-I", objdir (and cuts them off).
+
+       compiler := envList(envvar, defcmd)
+       a := []string{compiler[0], "-I", objdir}
+       a = append(a, compiler[1:]...)
+
+       // Definitely want -fPIC but on Windows gcc complains
+       // "-fPIC ignored for target (all code is position independent)"
+       if goos != "windows" {
+               a = append(a, "-fPIC")
+       }
+       a = append(a, b.gccArchArgs()...)
+       // gcc-4.5 and beyond require explicit "-pthread" flag
+       // for multithreading with pthread library.
+       if buildContext.CgoEnabled {
+               switch goos {
+               case "windows":
+                       a = append(a, "-mthreads")
+               default:
+                       a = append(a, "-pthread")
+               }
+       }
+
+       if strings.Contains(a[0], "clang") {
+               // disable ASCII art in clang errors, if possible
+               a = append(a, "-fno-caret-diagnostics")
+               // clang is too smart about command-line arguments
+               a = append(a, "-Qunused-arguments")
+       }
+
+       // disable word wrapping in error messages
+       a = append(a, "-fmessage-length=0")
+
+       // On OS X, some of the compilers behave as if -fno-common
+       // is always set, and the Mach-O linker in 6l/8l assumes this.
+       // See http://golang.org/issue/3253.
+       if goos == "darwin" {
+               a = append(a, "-fno-common")
+       }
+
+       return a
+}
+
+// gccArchArgs returns arguments to pass to gcc based on the architecture.
+func (b *builder) gccArchArgs() []string {
+       switch archChar {
+       case "8":
+               return []string{"-m32"}
+       case "6":
+               return []string{"-m64"}
+       case "5":
+               return []string{"-marm"} // not thumb
+       }
+       return nil
+}
+
+// envList returns the value of the given environment variable broken
+// into fields, using the default value when the variable is empty.
+func envList(key, def string) []string {
+       v := os.Getenv(key)
+       if v == "" {
+               v = def
+       }
+       return strings.Fields(v)
+}
+
+// Return the flags to use when invoking the C or C++ compilers, or cgo.
+func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {
+       var defaults string
+       if def {
+               defaults = "-g -O2"
+       }
+
+       cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
+       cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
+       cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
+       ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
+       return
+}
+
+var cgoRe = regexp.MustCompile(`[/\\:]`)
+
+var (
+       cgoLibGccFile     string
+       cgoLibGccErr      error
+       cgoLibGccFileOnce sync.Once
+)
+
+func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
+       cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true)
+       _, cgoexeCFLAGS, _, _ := b.cflags(p, false)
+
+       // If we are compiling Objective-C code, then we need to link against libobjc
+       if len(mfiles) > 0 {
+               cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
+       }
+
+       if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
+               out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs)
+               if err != nil {
+                       b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out))
+                       b.print(err.Error() + "\n")
+                       return nil, nil, errPrintedOutput
+               }
+               if len(out) > 0 {
+                       cgoCPPFLAGS = append(cgoCPPFLAGS, strings.Fields(string(out))...)
+               }
+               out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs)
+               if err != nil {
+                       b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out))
+                       b.print(err.Error() + "\n")
+                       return nil, nil, errPrintedOutput
+               }
+               if len(out) > 0 {
+                       cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(out))...)
+               }
+       }
+
+       // Allows including _cgo_export.h from .[ch] files in the package.
+       cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
+
+       // cgo
+       // TODO: CGOPKGPATH, CGO_FLAGS?
+       gofiles := []string{obj + "_cgo_gotypes.go"}
+       cfiles := []string{"_cgo_main.c", "_cgo_export.c"}
+       for _, fn := range p.CgoFiles {
+               f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
+               gofiles = append(gofiles, obj+f+"cgo1.go")
+               cfiles = append(cfiles, f+"cgo2.c")
+       }
+       defunC := obj + "_cgo_defun.c"
+
+       cgoflags := []string{}
+       // TODO: make cgo not depend on $GOARCH?
+
+       objExt := archChar
+
+       if p.Standard && p.ImportPath == "runtime/cgo" {
+               cgoflags = append(cgoflags, "-import_runtime_cgo=false")
+       }
+       if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") {
+               cgoflags = append(cgoflags, "-import_syscall=false")
+       }
+
+       // Update $CGO_LDFLAGS with p.CgoLDFLAGS.
+       var cgoenv []string
+       if len(cgoLDFLAGS) > 0 {
+               flags := make([]string, len(cgoLDFLAGS))
+               for i, f := range cgoLDFLAGS {
+                       flags[i] = strconv.Quote(f)
+               }
+               cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
+       }
+
+       if _, ok := buildToolchain.(gccgoToolchain); ok {
+               cgoflags = append(cgoflags, "-gccgo")
+               if pkgpath := gccgoPkgpath(p); pkgpath != "" {
+                       cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
+               }
+               objExt = "o"
+       }
+       if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil {
+               return nil, nil, err
+       }
+       outGo = append(outGo, gofiles...)
+
+       // cc _cgo_defun.c
+       defunObj := obj + "_cgo_defun." + objExt
+       if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
+               return nil, nil, err
+       }
+       outObj = append(outObj, defunObj)
+
+       // gcc
+       var linkobj []string
+
+       var bareLDFLAGS []string
+       // filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X
+       for i := 0; i < len(cgoLDFLAGS); i++ {
+               f := cgoLDFLAGS[i]
+               switch {
+               // skip "-lc" or "-l somelib"
+               case strings.HasPrefix(f, "-l"):
+                       if f == "-l" {
+                               i++
+                       }
+               // skip "-framework X" on Darwin
+               case goos == "darwin" && f == "-framework":
+                       i++
+               // skip "*.{dylib,so,dll}"
+               case strings.HasSuffix(f, ".dylib"),
+                       strings.HasSuffix(f, ".so"),
+                       strings.HasSuffix(f, ".dll"):
+                       continue
+               default:
+                       bareLDFLAGS = append(bareLDFLAGS, f)
+               }
+       }
+
+       cgoLibGccFileOnce.Do(func() {
+               cgoLibGccFile, cgoLibGccErr = b.libgcc(p)
+       })
+       if cgoLibGccFile == "" && cgoLibGccErr != nil {
+               return nil, nil, err
+       }
+
+       var staticLibs []string
+       if goos == "windows" {
+               // libmingw32 and libmingwex might also use libgcc, so libgcc must come last,
+               // and they also have some inter-dependencies, so must use linker groups.
+               staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"}
+       }
+       if cgoLibGccFile != "" {
+               staticLibs = append(staticLibs, cgoLibGccFile)
+       }
+
+       cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
+       for _, cfile := range cfiles {
+               ofile := obj + cfile[:len(cfile)-1] + "o"
+               if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil {
+                       return nil, nil, err
+               }
+               linkobj = append(linkobj, ofile)
+               if !strings.HasSuffix(ofile, "_cgo_main.o") {
+                       outObj = append(outObj, ofile)
+               }
+       }
+
+       for _, file := range gccfiles {
+               ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
+               if err := b.gcc(p, ofile, cflags, file); err != nil {
+                       return nil, nil, err
+               }
+               linkobj = append(linkobj, ofile)
+               outObj = append(outObj, ofile)
+       }
+
+       cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
+       for _, file := range gxxfiles {
+               // Append .o to the file, just in case the pkg has file.c and file.cpp
+               ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
+               if err := b.gxx(p, ofile, cxxflags, file); err != nil {
+                       return nil, nil, err
+               }
+               linkobj = append(linkobj, ofile)
+               outObj = append(outObj, ofile)
+       }
+
+       for _, file := range mfiles {
+               // Append .o to the file, just in case the pkg has file.c and file.m
+               ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
+               if err := b.gcc(p, ofile, cflags, file); err != nil {
+                       return nil, nil, err
+               }
+               linkobj = append(linkobj, ofile)
+               outObj = append(outObj, ofile)
+       }
+
+       linkobj = append(linkobj, p.SysoFiles...)
+       dynobj := obj + "_cgo_.o"
+       if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux/ARM to get accurate imported sym
+               cgoLDFLAGS = append(cgoLDFLAGS, "-pie")
+       }
+       if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil {
+               return nil, nil, err
+       }
+       if goarch == "arm" && goos == "linux" { // but we don't need -pie for normal cgo programs
+               cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1]
+       }
+
+       if _, ok := buildToolchain.(gccgoToolchain); ok {
+               // we don't use dynimport when using gccgo.
+               return outGo, outObj, nil
+       }
+
+       // cgo -dynimport
+       importC := obj + "_cgo_import.c"
+       cgoflags = []string{}
+       if p.Standard && p.ImportPath == "runtime/cgo" {
+               cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker
+       }
+       if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil {
+               return nil, nil, err
+       }
+
+       // cc _cgo_import.ARCH
+       importObj := obj + "_cgo_import." + objExt
+       if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil {
+               return nil, nil, err
+       }
+
+       ofile := obj + "_all.o"
+       var gccObjs, nonGccObjs []string
+       for _, f := range outObj {
+               if strings.HasSuffix(f, ".o") {
+                       gccObjs = append(gccObjs, f)
+               } else {
+                       nonGccObjs = append(nonGccObjs, f)
+               }
+       }
+       if err := b.gccld(p, ofile, stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs), gccObjs); err != nil {
+               return nil, nil, err
+       }
+
+       // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
+       // must be processed before the gcc-generated objects.
+       // Put it first.  http://golang.org/issue/2601
+       outObj = stringList(importObj, nonGccObjs, ofile)
+
+       return outGo, outObj, nil
+}
+
+// Run SWIG on all SWIG input files.
+// TODO: Don't build a shared library, once SWIG emits the necessary
+// pragmas for external linking.
+func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
+       cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true)
+       cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
+       cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
+
+       for _, file := range gccfiles {
+               ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
+               if err := b.gcc(p, ofile, cflags, file); err != nil {
+                       return nil, nil, err
+               }
+               outObj = append(outObj, ofile)
+       }
+
+       for _, file := range gxxfiles {
+               // Append .o to the file, just in case the pkg has file.c and file.cpp
+               ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
+               if err := b.gxx(p, ofile, cxxflags, file); err != nil {
+                       return nil, nil, err
+               }
+               outObj = append(outObj, ofile)
+       }
+
+       for _, file := range mfiles {
+               // Append .o to the file, just in case the pkg has file.c and file.cpp
+               ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
+               if err := b.gcc(p, ofile, cflags, file); err != nil {
+                       return nil, nil, err
+               }
+               outObj = append(outObj, ofile)
+       }
+
+       if err := b.swigVersionCheck(); err != nil {
+               return nil, nil, err
+       }
+
+       intgosize, err := b.swigIntSize(obj)
+       if err != nil {
+               return nil, nil, err
+       }
+
+       for _, f := range p.SwigFiles {
+               goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, false, intgosize)
+               if err != nil {
+                       return nil, nil, err
+               }
+               if goFile != "" {
+                       outGo = append(outGo, goFile)
+               }
+               if objFile != "" {
+                       outObj = append(outObj, objFile)
+               }
+               if gccObjFile != "" {
+                       outObj = append(outObj, gccObjFile)
+               }
+       }
+       for _, f := range p.SwigCXXFiles {
+               goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, true, intgosize)
+               if err != nil {
+                       return nil, nil, err
+               }
+               if goFile != "" {
+                       outGo = append(outGo, goFile)
+               }
+               if objFile != "" {
+                       outObj = append(outObj, objFile)
+               }
+               if gccObjFile != "" {
+                       outObj = append(outObj, gccObjFile)
+               }
+       }
+       return outGo, outObj, nil
+}
+
+// Make sure SWIG is new enough.
+var (
+       swigCheckOnce sync.Once
+       swigCheck     error
+)
+
+func (b *builder) swigDoVersionCheck() error {
+       out, err := b.runOut("", "", nil, "swig", "-version")
+       if err != nil {
+               return err
+       }
+       re := regexp.MustCompile(`[vV]ersion +([\d])`)
+       matches := re.FindSubmatch(out)
+       if matches == nil {
+               // Can't find version number; hope for the best.
+               return nil
+       }
+       major, err := strconv.Atoi(string(matches[1]))
+       if err != nil {
+               // Can't find version number; hope for the best.
+               return nil
+       }
+       if major < 3 {
+               return errors.New("must have SWIG version >= 3.0")
+       }
+       return nil
+}
+
+func (b *builder) swigVersionCheck() error {
+       swigCheckOnce.Do(func() {
+               swigCheck = b.swigDoVersionCheck()
+       })
+       return swigCheck
+}
+
+// This code fails to build if sizeof(int) <= 32
+const swigIntSizeCode = `
+package main
+const i int = 1 << 32
+`
+
+// Determine the size of int on the target system for the -intgosize option
+// of swig >= 2.0.9
+func (b *builder) swigIntSize(obj string) (intsize string, err error) {
+       if buildN {
+               return "$INTBITS", nil
+       }
+       src := filepath.Join(b.work, "swig_intsize.go")
+       if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil {
+               return
+       }
+       srcs := []string{src}
+
+       p := goFilesPackage(srcs)
+
+       if _, _, e := buildToolchain.gc(b, p, "", obj, nil, srcs); e != nil {
+               return "32", nil
+       }
+       return "64", nil
+}
+
+// Run SWIG on one SWIG input file.
+func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) {
+       cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true)
+       var cflags []string
+       if cxx {
+               cflags = stringList(cgoCPPFLAGS, cgoCXXFLAGS)
+       } else {
+               cflags = stringList(cgoCPPFLAGS, cgoCFLAGS)
+       }
+
+       n := 5 // length of ".swig"
+       if cxx {
+               n = 8 // length of ".swigcxx"
+       }
+       base := file[:len(file)-n]
+       goFile := base + ".go"
+       cBase := base + "_gc."
+       gccBase := base + "_wrap."
+       gccExt := "c"
+       if cxx {
+               gccExt = "cxx"
+       }
+
+       _, gccgo := buildToolchain.(gccgoToolchain)
+
+       // swig
+       args := []string{
+               "-go",
+               "-intgosize", intgosize,
+               "-module", base,
+               "-o", obj + gccBase + gccExt,
+               "-outdir", obj,
+       }
+       if gccgo {
+               args = append(args, "-gccgo")
+               if pkgpath := gccgoPkgpath(p); pkgpath != "" {
+                       args = append(args, "-go-pkgpath", pkgpath)
+               }
+       }
+       if cxx {
+               args = append(args, "-c++")
+       }
+
+       if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); err != nil {
+               if len(out) > 0 {
+                       if bytes.Contains(out, []byte("Unrecognized option -intgosize")) {
+                               return "", "", "", errors.New("must have SWIG version >= 3.0")
+                       }
+                       b.showOutput(p.Dir, p.ImportPath, b.processOutput(out))
+                       return "", "", "", errPrintedOutput
+               }
+               return "", "", "", err
+       }
+
+       var cObj string
+       if !gccgo {
+               // cc
+               cObj = obj + cBase + archChar
+               if err := buildToolchain.cc(b, p, obj, cObj, obj+cBase+"c"); err != nil {
+                       return "", "", "", err
+               }
+       }
+
+       // gcc
+       gccObj := obj + gccBase + "o"
+       if !cxx {
+               if err := b.gcc(p, gccObj, cflags, obj+gccBase+gccExt); err != nil {
+                       return "", "", "", err
+               }
+       } else {
+               if err := b.gxx(p, gccObj, cflags, obj+gccBase+gccExt); err != nil {
+                       return "", "", "", err
+               }
+       }
+
+       return obj + goFile, cObj, gccObj, nil
+}
+
+// An actionQueue is a priority queue of actions.
+type actionQueue []*action
+
+// Implement heap.Interface
+func (q *actionQueue) Len() int           { return len(*q) }
+func (q *actionQueue) Swap(i, j int)      { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
+func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
+func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) }
+func (q *actionQueue) Pop() interface{} {
+       n := len(*q) - 1
+       x := (*q)[n]
+       *q = (*q)[:n]
+       return x
+}
+
+func (q *actionQueue) push(a *action) {
+       heap.Push(q, a)
+}
+
+func (q *actionQueue) pop() *action {
+       return heap.Pop(q).(*action)
+}
+
+func raceInit() {
+       if !buildRace {
+               return
+       }
+       if goarch != "amd64" || goos != "linux" && goos != "darwin" && goos != "windows" {
+               fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
+               os.Exit(2)
+       }
+       buildGcflags = append(buildGcflags, "-race")
+       buildLdflags = append(buildLdflags, "-race")
+       buildCcflags = append(buildCcflags, "-D", "RACE")
+       if buildContext.InstallSuffix != "" {
+               buildContext.InstallSuffix += "_"
+       }
+       buildContext.InstallSuffix += "race"
+       buildContext.BuildTags = append(buildContext.BuildTags, "race")
+}
+
+// defaultSuffix returns file extension used for command files in
+// current os environment.
+func defaultSuffix() string {
+       switch runtime.GOOS {
+       case "windows":
+               return ".bat"
+       case "plan9":
+               return ".rc"
+       default:
+               return ".bash"
+       }
+}
diff --git a/libgo/go/cmd/go/clean.go b/libgo/go/cmd/go/clean.go
new file mode 100644 (file)
index 0000000..16054a5
--- /dev/null
@@ -0,0 +1,248 @@
+// 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 main
+
+import (
+       "fmt"
+       "io/ioutil"
+       "os"
+       "path/filepath"
+       "strings"
+)
+
+var cmdClean = &Command{
+       UsageLine: "clean [-i] [-r] [-n] [-x] [build flags] [packages]",
+       Short:     "remove object files",
+       Long: `
+Clean removes object files from package source directories.
+The go command builds most objects in a temporary directory,
+so go clean is mainly concerned with object files left by other
+tools or by manual invocations of go build.
+
+Specifically, clean removes the following files from each of the
+source directories corresponding to the import paths:
+
+       _obj/            old object directory, left from Makefiles
+       _test/           old test directory, left from Makefiles
+       _testmain.go     old gotest file, left from Makefiles
+       test.out         old test log, left from Makefiles
+       build.out        old test log, left from Makefiles
+       *.[568ao]        object files, left from Makefiles
+
+       DIR(.exe)        from go build
+       DIR.test(.exe)   from go test -c
+       MAINFILE(.exe)   from go build MAINFILE.go
+       *.so             from SWIG
+
+In the list, DIR represents the final path element of the
+directory, and MAINFILE is the base name of any Go source
+file in the directory that is not included when building
+the package.
+
+The -i flag causes clean to remove the corresponding installed
+archive or binary (what 'go install' would create).
+
+The -n flag causes clean to print the remove commands it would execute,
+but not run them.
+
+The -r flag causes clean to be applied recursively to all the
+dependencies of the packages named by the import paths.
+
+The -x flag causes clean to print remove commands as it executes them.
+
+For more about build flags, see 'go help build'.
+
+For more about specifying packages, see 'go help packages'.
+       `,
+}
+
+var cleanI bool // clean -i flag
+var cleanR bool // clean -r flag
+
+func init() {
+       // break init cycle
+       cmdClean.Run = runClean
+
+       cmdClean.Flag.BoolVar(&cleanI, "i", false, "")
+       cmdClean.Flag.BoolVar(&cleanR, "r", false, "")
+       // -n and -x are important enough to be
+       // mentioned explicitly in the docs but they
+       // are part of the build flags.
+
+       addBuildFlags(cmdClean)
+}
+
+func runClean(cmd *Command, args []string) {
+       for _, pkg := range packagesAndErrors(args) {
+               clean(pkg)
+       }
+}
+
+var cleaned = map[*Package]bool{}
+
+// TODO: These are dregs left by Makefile-based builds.
+// Eventually, can stop deleting these.
+var cleanDir = map[string]bool{
+       "_test": true,
+       "_obj":  true,
+}
+
+var cleanFile = map[string]bool{
+       "_testmain.go": true,
+       "test.out":     true,
+       "build.out":    true,
+       "a.out":        true,
+}
+
+var cleanExt = map[string]bool{
+       ".5":  true,
+       ".6":  true,
+       ".8":  true,
+       ".a":  true,
+       ".o":  true,
+       ".so": true,
+}
+
+func clean(p *Package) {
+       if cleaned[p] {
+               return
+       }
+       cleaned[p] = true
+
+       if p.Dir == "" {
+               errorf("can't load package: %v", p.Error)
+               return
+       }
+       dirs, err := ioutil.ReadDir(p.Dir)
+       if err != nil {
+               errorf("go clean %s: %v", p.Dir, err)
+               return
+       }
+
+       var b builder
+       b.print = fmt.Print
+
+       packageFile := map[string]bool{}
+       if p.Name != "main" {
+               // Record which files are not in package main.
+               // The others are.
+               keep := func(list []string) {
+                       for _, f := range list {
+                               packageFile[f] = true
+                       }
+               }
+               keep(p.GoFiles)
+               keep(p.CgoFiles)
+               keep(p.TestGoFiles)
+               keep(p.XTestGoFiles)
+       }
+
+       _, elem := filepath.Split(p.Dir)
+       var allRemove []string
+
+       // Remove dir-named executable only if this is package main.
+       if p.Name == "main" {
+               allRemove = append(allRemove,
+                       elem,
+                       elem+".exe",
+               )
+       }
+
+       // Remove package test executables.
+       allRemove = append(allRemove,
+               elem+".test",
+               elem+".test.exe",
+       )
+
+       // Remove a potential executable for each .go file in the directory that
+       // is not part of the directory's package.
+       for _, dir := range dirs {
+               name := dir.Name()
+               if packageFile[name] {
+                       continue
+               }
+               if !dir.IsDir() && strings.HasSuffix(name, ".go") {
+                       // TODO(adg,rsc): check that this .go file is actually
+                       // in "package main", and therefore capable of building
+                       // to an executable file.
+                       base := name[:len(name)-len(".go")]
+                       allRemove = append(allRemove, base, base+".exe")
+               }
+       }
+
+       if buildN || buildX {
+               b.showcmd(p.Dir, "rm -f %s", strings.Join(allRemove, " "))
+       }
+
+       toRemove := map[string]bool{}
+       for _, name := range allRemove {
+               toRemove[name] = true
+       }
+       for _, dir := range dirs {
+               name := dir.Name()
+               if dir.IsDir() {
+                       // TODO: Remove once Makefiles are forgotten.
+                       if cleanDir[name] {
+                               if buildN || buildX {
+                                       b.showcmd(p.Dir, "rm -r %s", name)
+                                       if buildN {
+                                               continue
+                                       }
+                               }
+                               if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil {
+                                       errorf("go clean: %v", err)
+                               }
+                       }
+                       continue
+               }
+
+               if buildN {
+                       continue
+               }
+
+               if cleanFile[name] || cleanExt[filepath.Ext(name)] || toRemove[name] {
+                       removeFile(filepath.Join(p.Dir, name))
+               }
+       }
+
+       if cleanI && p.target != "" {
+               if buildN || buildX {
+                       b.showcmd("", "rm -f %s", p.target)
+               }
+               if !buildN {
+                       removeFile(p.target)
+               }
+       }
+
+       if cleanR {
+               for _, p1 := range p.imports {
+                       clean(p1)
+               }
+       }
+}
+
+// removeFile tries to remove file f, if error other than file doesn't exist
+// occurs, it will report the error.
+func removeFile(f string) {
+       err := os.Remove(f)
+       if err == nil || os.IsNotExist(err) {
+               return
+       }
+       // Windows does not allow deletion of a binary file while it is executing.
+       if toolIsWindows {
+               // Remove lingering ~ file from last attempt.
+               if _, err2 := os.Stat(f + "~"); err2 == nil {
+                       os.Remove(f + "~")
+               }
+               // Try to move it out of the way. If the move fails,
+               // which is likely, we'll try again the
+               // next time we do an install of this binary.
+               if err2 := os.Rename(f, f+"~"); err2 == nil {
+                       os.Remove(f + "~")
+                       return
+               }
+       }
+       errorf("go clean: %v", err)
+}
diff --git a/libgo/go/cmd/go/context.go b/libgo/go/cmd/go/context.go
new file mode 100644 (file)
index 0000000..68e5182
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2014 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"
+)
+
+type Context struct {
+       GOARCH        string   `json:",omitempty"` // target architecture
+       GOOS          string   `json:",omitempty"` // target operating system
+       GOROOT        string   `json:",omitempty"` // Go root
+       GOPATH        string   `json:",omitempty"` // Go path
+       CgoEnabled    bool     `json:",omitempty"` // whether cgo can be used
+       UseAllFiles   bool     `json:",omitempty"` // use files regardless of +build lines, file names
+       Compiler      string   `json:",omitempty"` // compiler to assume when computing target paths
+       BuildTags     []string `json:",omitempty"` // build constraints to match in +build lines
+       ReleaseTags   []string `json:",omitempty"` // releases the current release is compatible with
+       InstallSuffix string   `json:",omitempty"` // suffix to use in the name of the install dir
+}
+
+func newContext(c *build.Context) *Context {
+       return &Context{
+               GOARCH:        c.GOARCH,
+               GOOS:          c.GOOS,
+               GOROOT:        c.GOROOT,
+               CgoEnabled:    c.CgoEnabled,
+               UseAllFiles:   c.UseAllFiles,
+               Compiler:      c.Compiler,
+               BuildTags:     c.BuildTags,
+               ReleaseTags:   c.ReleaseTags,
+               InstallSuffix: c.InstallSuffix,
+       }
+}
diff --git a/libgo/go/cmd/go/discovery.go b/libgo/go/cmd/go/discovery.go
new file mode 100644 (file)
index 0000000..b9f4279
--- /dev/null
@@ -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.
+
+// +build !cmd_go_bootstrap
+
+// This code is compiled into the real 'go' binary, but it is not
+// compiled into the binary that is built during all.bash, so as
+// to avoid needing to build net (and thus use cgo) during the
+// bootstrap process.
+
+package main
+
+import (
+       "encoding/xml"
+       "fmt"
+       "io"
+       "strings"
+)
+
+// charsetReader returns a reader for the given charset. Currently
+// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful
+// error which is printed by go get, so the user can find why the package
+// wasn't downloaded if the encoding is not supported. Note that, in
+// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters
+// greater than 0x7f are not rejected).
+func charsetReader(charset string, input io.Reader) (io.Reader, error) {
+       switch strings.ToLower(charset) {
+       case "ascii":
+               return input, nil
+       default:
+               return nil, fmt.Errorf("can't decode XML document using charset %q", charset)
+       }
+}
+
+// parseMetaGoImports returns meta imports from the HTML in r.
+// Parsing ends at the end of the <head> section or the beginning of the <body>.
+func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) {
+       d := xml.NewDecoder(r)
+       d.CharsetReader = charsetReader
+       d.Strict = false
+       var t xml.Token
+       for {
+               t, err = d.Token()
+               if err != nil {
+                       if err == io.EOF {
+                               err = nil
+                       }
+                       return
+               }
+               if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") {
+                       return
+               }
+               if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") {
+                       return
+               }
+               e, ok := t.(xml.StartElement)
+               if !ok || !strings.EqualFold(e.Name.Local, "meta") {
+                       continue
+               }
+               if attrValue(e.Attr, "name") != "go-import" {
+                       continue
+               }
+               if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {
+                       imports = append(imports, metaImport{
+                               Prefix:   f[0],
+                               VCS:      f[1],
+                               RepoRoot: f[2],
+                       })
+               }
+       }
+}
+
+// attrValue returns the attribute value for the case-insensitive key
+// `name', or the empty string if nothing is found.
+func attrValue(attrs []xml.Attr, name string) string {
+       for _, a := range attrs {
+               if strings.EqualFold(a.Name.Local, name) {
+                       return a.Value
+               }
+       }
+       return ""
+}
diff --git a/libgo/go/cmd/go/doc.go b/libgo/go/cmd/go/doc.go
new file mode 100644 (file)
index 0000000..9840804
--- /dev/null
@@ -0,0 +1,990 @@
+// 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.
+
+// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh.
+// Edit the documentation in other files and rerun mkdoc.sh to generate this one.
+
+/*
+Go is a tool for managing Go source code.
+
+Usage:
+
+       go command [arguments]
+
+The commands are:
+
+    build       compile packages and dependencies
+    clean       remove object files
+    env         print Go environment information
+    fix         run go tool fix on packages
+    fmt         run gofmt on package sources
+    get         download and install packages and dependencies
+    install     compile and install packages and dependencies
+    list        list packages
+    run         compile and run Go program
+    test        test packages
+    tool        run specified go tool
+    version     print Go version
+    vet         run go tool vet on packages
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+
+    c           calling between Go and C
+    filetype    file types
+    gopath      GOPATH environment variable
+    importpath  import path syntax
+    packages    description of package lists
+    testflag    description of testing flags
+    testfunc    description of testing functions
+
+Use "go help [topic]" for more information about that topic.
+
+
+Compile packages and dependencies
+
+Usage:
+
+       go build [-o output] [-i] [build flags] [packages]
+
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+If the arguments are a list of .go files, build treats them as a list
+of source files specifying a single package.
+
+When the command line specifies a single main package,
+build writes the resulting executable to output.
+Otherwise build compiles the packages but discards the results,
+serving only as a check that the packages can be built.
+
+The -o flag specifies the output file name. If not specified, the
+output file name depends on the arguments and derives from the name
+of the package, such as p.a for package p, unless p is 'main'. If
+the package is main and file names are provided, the file name
+derives from the first file name mentioned, such as f1 for 'go build
+f1.go f2.go'; with no files provided ('go build'), the output file
+name is the base name of the containing directory.
+
+The -i flag installs the packages that are dependencies of the target.
+
+The build flags are shared by the build, clean, get, install, list, run,
+and test commands:
+
+       -a
+               force rebuilding of packages that are already up-to-date.
+       -n
+               print the commands but do not run them.
+       -p n
+               the number of builds that can be run in parallel.
+               The default is the number of CPUs available.
+       -race
+               enable data race detection.
+               Supported only on linux/amd64, darwin/amd64 and windows/amd64.
+       -v
+               print the names of packages as they are compiled.
+       -work
+               print the name of the temporary work directory and
+               do not delete it when exiting.
+       -x
+               print the commands.
+
+       -ccflags 'arg list'
+               arguments to pass on each 5c, 6c, or 8c compiler invocation.
+       -compiler name
+               name of compiler to use, as in runtime.Compiler (gccgo or gc).
+       -gccgoflags 'arg list'
+               arguments to pass on each gccgo compiler/linker invocation.
+       -gcflags 'arg list'
+               arguments to pass on each 5g, 6g, or 8g compiler invocation.
+       -installsuffix suffix
+               a suffix to use in the name of the package installation directory,
+               in order to keep output separate from default builds.
+               If using the -race flag, the install suffix is automatically set to race
+               or, if set explicitly, has _race appended to it.
+       -ldflags 'flag list'
+               arguments to pass on each 5l, 6l, or 8l linker invocation.
+       -tags 'tag list'
+               a list of build tags to consider satisfied during the build.
+               For more information about build tags, see the description of
+               build constraints in the documentation for the go/build package.
+
+The list flags accept a space-separated list of strings. To embed spaces
+in an element in the list, surround it with either single or double quotes.
+
+For more about specifying packages, see 'go help packages'.
+For more about where packages and binaries are installed,
+run 'go help gopath'.  For more about calling between Go and C/C++,
+run 'go help c'.
+
+See also: go install, go get, go clean.
+
+
+Remove object files
+
+Usage:
+
+       go clean [-i] [-r] [-n] [-x] [build flags] [packages]
+
+Clean removes object files from package source directories.
+The go command builds most objects in a temporary directory,
+so go clean is mainly concerned with object files left by other
+tools or by manual invocations of go build.
+
+Specifically, clean removes the following files from each of the
+source directories corresponding to the import paths:
+
+       _obj/            old object directory, left from Makefiles
+       _test/           old test directory, left from Makefiles
+       _testmain.go     old gotest file, left from Makefiles
+       test.out         old test log, left from Makefiles
+       build.out        old test log, left from Makefiles
+       *.[568ao]        object files, left from Makefiles
+
+       DIR(.exe)        from go build
+       DIR.test(.exe)   from go test -c
+       MAINFILE(.exe)   from go build MAINFILE.go
+       *.so             from SWIG
+
+In the list, DIR represents the final path element of the
+directory, and MAINFILE is the base name of any Go source
+file in the directory that is not included when building
+the package.
+
+The -i flag causes clean to remove the corresponding installed
+archive or binary (what 'go install' would create).
+
+The -n flag causes clean to print the remove commands it would execute,
+but not run them.
+
+The -r flag causes clean to be applied recursively to all the
+dependencies of the packages named by the import paths.
+
+The -x flag causes clean to print remove commands as it executes them.
+
+For more about build flags, see 'go help build'.
+
+For more about specifying packages, see 'go help packages'.
+
+
+Print Go environment information
+
+Usage:
+
+       go env [var ...]
+
+Env prints Go environment information.
+
+By default env prints information as a shell script
+(on Windows, a batch file).  If one or more variable
+names is given as arguments,  env prints the value of
+each named variable on its own line.
+
+
+Run go tool fix on packages
+
+Usage:
+
+       go fix [packages]
+
+Fix runs the Go fix command on the packages named by the import paths.
+
+For more about fix, see 'godoc fix'.
+For more about specifying packages, see 'go help packages'.
+
+To run fix with specific options, run 'go tool fix'.
+
+See also: go fmt, go vet.
+
+
+Run gofmt on package sources
+
+Usage:
+
+       go fmt [-n] [-x] [packages]
+
+Fmt runs the command 'gofmt -l -w' on the packages named
+by the import paths.  It prints the names of the files that are modified.
+
+For more about gofmt, see 'godoc gofmt'.
+For more about specifying packages, see 'go help packages'.
+
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go fix, go vet.
+
+
+Download and install packages and dependencies
+
+Usage:
+
+       go get [-d] [-fix] [-t] [-u] [build flags] [packages]
+
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+The -fix flag instructs get to run the fix tool on the downloaded packages
+before resolving dependencies or building the code.
+
+The -t flag instructs get to also download the packages required to build
+the tests for the specified packages.
+
+The -u flag instructs get to use the network to update the named packages
+and their dependencies.  By default, get uses the network to check out
+missing packages but does not use it to look for updates to existing packages.
+
+Get also accepts build flags to control the installation. See 'go help build'.
+
+When checking out or updating a package, get looks for a branch or tag
+that matches the locally installed version of Go. The most important
+rule is that if the local installation is running version "go1", get
+searches for a branch or tag named "go1". If no such version exists it
+retrieves the most recent version of the package.
+
+For more about specifying packages, see 'go help packages'.
+
+For more about how 'go get' finds source code to
+download, see 'go help importpath'.
+
+See also: go build, go install, go clean.
+
+
+Compile and install packages and dependencies
+
+Usage:
+
+       go install [build flags] [packages]
+
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+For more about the build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
+
+See also: go build, go get, go clean.
+
+
+List packages
+
+Usage:
+
+       go list [-e] [-f format] [-json] [build flags] [packages]
+
+List lists the packages named by the import paths, one per line.
+
+The default output shows the package import path:
+
+    code.google.com/p/google-api-go-client/books/v1
+    code.google.com/p/goauth2/oauth
+    code.google.com/p/sqlite
+
+The -f flag specifies an alternate format for the list, using the
+syntax of package template.  The default output is equivalent to -f
+'{{.ImportPath}}'. The struct being passed to the template is:
+
+    type Package struct {
+        Dir        string // directory containing package sources
+        ImportPath string // import path of package in dir
+        Name       string // package name
+        Doc        string // package documentation string
+        Target     string // install path
+        Goroot     bool   // is this package in the Go root?
+        Standard   bool   // is this package part of the standard Go library?
+        Stale      bool   // would 'go install' do anything for this package?
+        Root       string // Go root or Go path dir containing this package
+
+        // Source files
+        GoFiles  []string       // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+        CgoFiles []string       // .go sources files that import "C"
+        IgnoredGoFiles []string // .go sources ignored due to build constraints
+        CFiles   []string       // .c source files
+        CXXFiles []string       // .cc, .cxx and .cpp source files
+        MFiles   []string       // .m source files
+        HFiles   []string       // .h, .hh, .hpp and .hxx source files
+        SFiles   []string       // .s source files
+        SwigFiles []string      // .swig files
+        SwigCXXFiles []string   // .swigcxx files
+        SysoFiles []string      // .syso object files to add to archive
+
+        // Cgo directives
+        CgoCFLAGS    []string // cgo: flags for C compiler
+        CgoCPPFLAGS  []string // cgo: flags for C preprocessor
+        CgoCXXFLAGS  []string // cgo: flags for C++ compiler
+        CgoLDFLAGS   []string // cgo: flags for linker
+        CgoPkgConfig []string // cgo: pkg-config names
+
+        // Dependency information
+        Imports []string // import paths used by this package
+        Deps    []string // all (recursively) imported dependencies
+
+        // Error information
+        Incomplete bool            // this package or a dependency has an error
+        Error      *PackageError   // error loading package
+        DepsErrors []*PackageError // errors loading dependencies
+
+        TestGoFiles  []string // _test.go files in package
+        TestImports  []string // imports from TestGoFiles
+        XTestGoFiles []string // _test.go files outside package
+        XTestImports []string // imports from XTestGoFiles
+    }
+
+The template function "join" calls strings.Join.
+
+The template function "context" returns the build context, defined as:
+
+       type Context struct {
+               GOARCH        string   // target architecture
+               GOOS          string   // target operating system
+               GOROOT        string   // Go root
+               GOPATH        string   // Go path
+               CgoEnabled    bool     // whether cgo can be used
+               UseAllFiles   bool     // use files regardless of +build lines, file names
+               Compiler      string   // compiler to assume when computing target paths
+               BuildTags     []string // build constraints to match in +build lines
+               ReleaseTags   []string // releases the current release is compatible with
+               InstallSuffix string   // suffix to use in the name of the install dir
+       }
+
+For more information about the meaning of these fields see the documentation
+for the go/build package's Context type.
+
+The -json flag causes the package data to be printed in JSON format
+instead of using the template format.
+
+The -e flag changes the handling of erroneous packages, those that
+cannot be found or are malformed.  By default, the list command
+prints an error to standard error for each erroneous package and
+omits the packages from consideration during the usual printing.
+With the -e flag, the list command never prints errors to standard
+error and instead processes the erroneous packages with the usual
+printing.  Erroneous packages will have a non-empty ImportPath and
+a non-nil Error field; other information may or may not be missing
+(zeroed).
+
+For more about build flags, see 'go help build'.
+
+For more about specifying packages, see 'go help packages'.
+
+
+Compile and run Go program
+
+Usage:
+
+       go run [build flags] [-exec xprog] gofiles... [arguments...]
+
+Run compiles and runs the main package comprising the named Go source files.
+A Go source file is defined to be a file ending in a literal ".go" suffix.
+
+By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
+If the -exec flag is given, 'go run' invokes the binary using xprog: 'xprog a.out arguments...'.
+If the -exec flag is not given, GOOS or GOARCH is different from the system
+default, and a program named go_$GOOS_$GOARCH_exec can be found
+on the current search path, 'go run' invokes the binary using that program,
+for example 'go_nacl_386_exec a.out arguments...'. This allows execution of
+cross-compiled programs when a simulator or other execution method is
+available.
+
+For more about build flags, see 'go help build'.
+
+See also: go build.
+
+
+Test packages
+
+Usage:
+
+       go test [-c] [-i] [build and test flags] [packages] [flags for test binary]
+
+'Go test' automates testing the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+       ok   archive/tar   0.011s
+       FAIL archive/zip   0.022s
+       ok   compress/gzip 0.033s
+       ...
+
+followed by detailed output for each failed package.
+
+'Go test' recompiles each package along with any files with names matching
+the file pattern "*_test.go".
+Files whose names begin with "_" (including "_test.go") or "." are ignored.
+These additional files can contain test functions, benchmark functions, and
+example functions.  See 'go help testfunc' for more.
+Each listed package causes the execution of a separate test binary.
+
+Test files that declare a package with the suffix "_test" will be compiled as a
+separate package, and then linked and run with the main test binary.
+
+By default, go test needs no arguments.  It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+In addition to the build flags, the flags handled by 'go test' itself are:
+
+       -c  Compile the test binary to pkg.test but do not run it.
+           (Where pkg is the last element of the package's import path.)
+
+       -i
+           Install packages that are dependencies of the test.
+           Do not run the test.
+
+       -exec xprog
+           Run the test binary using xprog. The behavior is the same as
+           in 'go run'. See 'go help run' for details.
+
+The test binary also accepts flags that control execution of the test; these
+flags are also accessible by 'go test'.  See 'go help testflag' for details.
+
+If the test binary needs any other flags, they should be presented after the
+package names. The go tool treats as a flag the first argument that begins with
+a minus sign that it does not recognize itself; that argument and all subsequent
+arguments are passed as arguments to the test binary.
+
+For more about build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
+
+See also: go build, go vet.
+
+
+Run specified go tool
+
+Usage:
+
+       go tool [-n] command [args...]
+
+Tool runs the go tool command identified by the arguments.
+With no arguments it prints the list of known tools.
+
+The -n flag causes tool to print the command that would be
+executed but not execute it.
+
+For more about each tool command, see 'go tool command -h'.
+
+
+Print Go version
+
+Usage:
+
+       go version
+
+Version prints the Go version, as reported by runtime.Version.
+
+
+Run go tool vet on packages
+
+Usage:
+
+       go vet [-n] [-x] [packages]
+
+Vet runs the Go vet command on the packages named by the import paths.
+
+For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'.
+For more about specifying packages, see 'go help packages'.
+
+To run the vet tool with specific options, run 'go tool vet'.
+
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+See also: go fmt, go fix.
+
+
+Calling between Go and C
+
+There are two different ways to call between Go and C/C++ code.
+
+The first is the cgo tool, which is part of the Go distribution.  For
+information on how to use it see the cgo documentation (godoc cmd/cgo).
+
+The second is the SWIG program, which is a general tool for
+interfacing between languages.  For information on SWIG see
+http://swig.org/.  When running go build, any file with a .swig
+extension will be passed to SWIG.  Any file with a .swigcxx extension
+will be passed to SWIG with the -c++ option.
+
+When either cgo or SWIG is used, go build will pass any .c, .m, .s,
+or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++
+compiler.  The CC or CXX environment variables may be set to determine
+the C or C++ compiler, respectively, to use.
+
+
+File types
+
+The go command examines the contents of a restricted set of files
+in each directory. It identifies which files to examine based on
+the extension of the file name. These extensions are:
+
+       .go
+               Go source files.
+       .c, .h
+               C source files.
+               If the package uses cgo, these will be compiled with the
+               OS-native compiler (typically gcc); otherwise they will be
+               compiled with the Go-specific support compiler,
+               5c, 6c, or 8c, etc. as appropriate.
+       .cc, .cpp, .cxx, .hh, .hpp, .hxx
+               C++ source files. Only useful with cgo or SWIG, and always
+               compiled with the OS-native compiler.
+       .m
+               Objective-C source files. Only useful with cgo, and always
+               compiled with the OS-native compiler.
+       .s, .S
+               Assembler source files.
+               If the package uses cgo, these will be assembled with the
+               OS-native assembler (typically gcc (sic)); otherwise they
+               will be assembled with the Go-specific support assembler,
+               5a, 6a, or 8a, etc., as appropriate.
+       .swig, .swigcxx
+               SWIG definition files.
+       .syso
+               System object files.
+
+Files of each of these types except .syso may contain build
+constraints, but the go command stops scanning for build constraints
+at the first item in the file that is not a blank line or //-style
+line comment.
+
+
+GOPATH environment variable
+
+The Go path is used to resolve import statements.
+It is implemented by and documented in the go/build package.
+
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+
+GOPATH must be set to get, build and install packages outside the
+standard Go tree.
+
+Each directory listed in GOPATH must have a prescribed structure:
+
+The src/ directory holds source code.  The path below 'src'
+determines the import path or executable name.
+
+The pkg/ directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as "foo/bar" and
+has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
+
+The bin/ directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path.  That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.  If the GOBIN environment variable is
+set, commands are installed to the directory it names instead
+of DIR/bin.
+
+Here's an example directory layout:
+
+    GOPATH=/home/user/gocode
+
+    /home/user/gocode/
+        src/
+            foo/
+                bar/               (go code in package bar)
+                    x.go
+                quux/              (go code in package main)
+                    y.go
+        bin/
+            quux                   (installed command)
+        pkg/
+            linux_amd64/
+                foo/
+                    bar.a          (installed package object)
+
+Go searches each directory listed in GOPATH to find source code,
+but new packages are always downloaded into the first directory
+in the list.
+
+
+Import path syntax
+
+An import path (see 'go help packages') denotes a package
+stored in the local file system.  In general, an import path denotes
+either a standard package (such as "unicode/utf8") or a package
+found in one of the work spaces (see 'go help gopath').
+
+Relative import paths
+
+An import path beginning with ./ or ../ is called a relative path.
+The toolchain supports relative import paths as a shortcut in two ways.
+
+First, a relative path can be used as a shorthand on the command line.
+If you are working in the directory containing the code imported as
+"unicode" and want to run the tests for "unicode/utf8", you can type
+"go test ./utf8" instead of needing to specify the full path.
+Similarly, in the reverse situation, "go test .." will test "unicode" from
+the "unicode/utf8" directory. Relative patterns are also allowed, like
+"go test ./..." to test all subdirectories. See 'go help packages' for details
+on the pattern syntax.
+
+Second, if you are compiling a Go program not in a work space,
+you can use a relative path in an import statement in that program
+to refer to nearby code also not in a work space.
+This makes it easy to experiment with small multipackage programs
+outside of the usual work spaces, but such programs cannot be
+installed with "go install" (there is no work space in which to install them),
+so they are rebuilt from scratch each time they are built.
+To avoid ambiguity, Go programs cannot use relative import paths
+within a work space.
+
+Remote import paths
+
+Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+
+A few common code hosting sites have special syntax:
+
+       Bitbucket (Git, Mercurial)
+
+               import "bitbucket.org/user/project"
+               import "bitbucket.org/user/project/sub/directory"
+
+       GitHub (Git)
+
+               import "github.com/user/project"
+               import "github.com/user/project/sub/directory"
+
+       Google Code Project Hosting (Git, Mercurial, Subversion)
+
+               import "code.google.com/p/project"
+               import "code.google.com/p/project/sub/directory"
+
+               import "code.google.com/p/project.subrepository"
+               import "code.google.com/p/project.subrepository/sub/directory"
+
+       Launchpad (Bazaar)
+
+               import "launchpad.net/project"
+               import "launchpad.net/project/series"
+               import "launchpad.net/project/series/sub/directory"
+
+               import "launchpad.net/~user/project/branch"
+               import "launchpad.net/~user/project/branch/sub/directory"
+
+For code hosted on other servers, import paths may either be qualified
+with the version control type, or the go tool can dynamically fetch
+the import path over https/http and discover where the code resides
+from a <meta> tag in the HTML.
+
+To declare the code location, an import path of the form
+
+       repository.vcs/path
+
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository.  The supported version control systems are:
+
+       Bazaar      .bzr
+       Git         .git
+       Mercurial   .hg
+       Subversion  .svn
+
+For example,
+
+       import "example.org/user/foo.hg"
+
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+
+       import "example.org/repo.git/foo/bar"
+
+denotes the foo/bar directory of the Git repository at
+example.org/repo or repo.git.
+
+When a version control system supports multiple protocols,
+each is tried in turn when downloading.  For example, a Git
+download tries git://, then https://, then http://.
+
+If the import path is not a known code hosting site and also lacks a
+version control qualifier, the go tool attempts to fetch the import
+over https/http and looks for a <meta> tag in the document's HTML
+<head>.
+
+The meta tag has the form:
+
+       <meta name="go-import" content="import-prefix vcs repo-root">
+
+The import-prefix is the import path corresponding to the repository
+root. It must be a prefix or an exact match of the package being
+fetched with "go get". If it's not an exact match, another http
+request is made at the prefix to verify the <meta> tags match.
+
+The vcs is one of "git", "hg", "svn", etc,
+
+The repo-root is the root of the version control system
+containing a scheme and not containing a .vcs qualifier.
+
+For example,
+
+       import "example.org/pkg/foo"
+
+will result in the following request(s):
+
+       https://example.org/pkg/foo?go-get=1 (preferred)
+       http://example.org/pkg/foo?go-get=1  (fallback)
+
+If that page contains the meta tag
+
+       <meta name="go-import" content="example.org git https://code.org/r/p/exproj">
+
+the go tool will verify that https://example.org/?go-get=1 contains the
+same meta tag and then git clone https://code.org/r/p/exproj into
+GOPATH/src/example.org.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (see 'go help gopath').
+
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run 'go help install' for more.
+
+
+Description of package lists
+
+Many commands apply to a set of packages:
+
+       go action [packages]
+
+Usually, [packages] is a list of import paths.
+
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (see 'go help gopath').
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+There are three reserved names for paths that should not be used
+for packages to be built with the go tool:
+
+- "main" denotes the top-level package in a stand-alone executable.
+
+- "all" expands to all package directories found in all the GOPATH
+trees. For example, 'go list all' lists all the packages on the local
+system.
+
+- "std" is like all but expands to just the packages in the standard
+Go library.
+
+An import path is a pattern if it includes one or more "..." wildcards,
+each of which can match any string, including the empty string and
+strings containing slashes.  Such a pattern expands to all package
+directories found in the GOPATH trees with names matching the
+patterns.  As a special case, x/... matches x as well as x's subdirectories.
+For example, net/... expands to net and packages in its subdirectories.
+
+An import path can also name a package to be downloaded from
+a remote repository.  Run 'go help importpath' for details.
+
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you.  For example, paths used
+internally at Google all begin with 'google', and paths
+denoting remote repositories begin with the path to the code,
+such as 'code.google.com/p/project'.
+
+As a special case, if the package list is a list of .go files from a
+single directory, the command is applied to a single synthesized
+package made up of exactly those files, ignoring any build constraints
+in those files and ignoring any other files in the directory.
+
+File names that begin with "." or "_" are ignored by the go tool.
+
+
+Description of testing flags
+
+The 'go test' command takes both flags that apply to 'go test' itself
+and flags that apply to the resulting test binary.
+
+Several of the flags control profiling and write an execution profile
+suitable for "go tool pprof"; run "go tool pprof help" for more
+information.  The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+
+The following flags are recognized by the 'go test' command and
+control the execution of any test:
+
+       -bench regexp
+           Run benchmarks matching the regular expression.
+           By default, no benchmarks run. To run all benchmarks,
+           use '-bench .' or '-bench=.'.
+
+       -benchmem
+           Print memory allocation statistics for benchmarks.
+
+       -benchtime t
+           Run enough iterations of each benchmark to take t, specified
+           as a time.Duration (for example, -benchtime 1h30s).
+           The default is 1 second (1s).
+
+       -blockprofile block.out
+           Write a goroutine blocking profile to the specified file
+           when all tests are complete.
+
+       -blockprofilerate n
+           Control the detail provided in goroutine blocking profiles by
+           calling runtime.SetBlockProfileRate with n.
+           See 'godoc runtime SetBlockProfileRate'.
+           The profiler aims to sample, on average, one blocking event every
+           n nanoseconds the program spends blocked.  By default,
+           if -test.blockprofile is set without this flag, all blocking events
+           are recorded, equivalent to -test.blockprofilerate=1.
+
+       -cover
+           Enable coverage analysis.
+
+       -covermode set,count,atomic
+           Set the mode for coverage analysis for the package[s]
+           being tested. The default is "set" unless -race is enabled,
+           in which case it is "atomic".
+           The values:
+               set: bool: does this statement run?
+               count: int: how many times does this statement run?
+               atomic: int: count, but correct in multithreaded tests;
+                       significantly more expensive.
+           Sets -cover.
+
+       -coverpkg pkg1,pkg2,pkg3
+           Apply coverage analysis in each test to the given list of packages.
+           The default is for each test to analyze only the package being tested.
+           Packages are specified as import paths.
+           Sets -cover.
+
+       -coverprofile cover.out
+           Write a coverage profile to the specified file after all tests
+           have passed.
+           Sets -cover.
+
+       -cpu 1,2,4
+           Specify a list of GOMAXPROCS values for which the tests or
+           benchmarks should be executed.  The default is the current value
+           of GOMAXPROCS.
+
+       -cpuprofile cpu.out
+           Write a CPU profile to the specified file before exiting.
+
+       -memprofile mem.out
+           Write a memory profile to the specified file after all tests
+           have passed.
+
+       -memprofilerate n
+           Enable more precise (and expensive) memory profiles by setting
+           runtime.MemProfileRate.  See 'godoc runtime MemProfileRate'.
+           To profile all memory allocations, use -test.memprofilerate=1
+           and pass --alloc_space flag to the pprof tool.
+
+       -outputdir directory
+           Place output files from profiling in the specified directory,
+           by default the directory in which "go test" is running.
+
+       -parallel n
+           Allow parallel execution of test functions that call t.Parallel.
+           The value of this flag is the maximum number of tests to run
+           simultaneously; by default, it is set to the value of GOMAXPROCS.
+
+       -run regexp
+           Run only those tests and examples matching the regular
+           expression.
+
+       -short
+           Tell long-running tests to shorten their run time.
+           It is off by default but set during all.bash so that installing
+           the Go tree can run a sanity check but not spend time running
+           exhaustive tests.
+
+       -timeout t
+           If a test runs longer than t, panic.
+
+       -v
+           Verbose output: log all tests as they are run. Also print all
+           text from Log and Logf calls even if the test succeeds.
+
+The test binary, called pkg.test where pkg is the name of the
+directory containing the package sources, can be invoked directly
+after building it with 'go test -c'. When invoking the test binary
+directly, each of the standard flag names must be prefixed with 'test.',
+as in -test.run=TestMyFunc or -test.v.
+
+When running 'go test', flags not listed above are passed through
+unaltered. For instance, the command
+
+       go test -x -v -cpuprofile=prof.out -dir=testdata -update
+
+will compile the test binary and then run it as
+
+       pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
+
+The test flags that generate profiles (other than for coverage) also
+leave the test binary in pkg.test for use when analyzing the profiles.
+
+Flags not recognized by 'go test' must be placed after any specified packages.
+
+
+Description of testing functions
+
+The 'go test' command expects to find test, benchmark, and example functions
+in the "*_test.go" files corresponding to the package under test.
+
+A test function is one named TestXXX (where XXX is any alphanumeric string
+not starting with a lower case letter) and should have the signature,
+
+       func TestXXX(t *testing.T) { ... }
+
+A benchmark function is one named BenchmarkXXX and should have the signature,
+
+       func BenchmarkXXX(b *testing.B) { ... }
+
+An example function is similar to a test function but, instead of using
+*testing.T to report success or failure, prints output to os.Stdout.
+That output is compared against the function's "Output:" comment, which
+must be the last comment in the function body (see example below). An
+example with no such comment, or with no text after "Output:" is compiled
+but not executed.
+
+Godoc displays the body of ExampleXXX to demonstrate the use
+of the function, constant, or variable XXX.  An example of a method M with
+receiver type T or *T is named ExampleT_M.  There may be multiple examples
+for a given function, constant, or variable, distinguished by a trailing _xxx,
+where xxx is a suffix not beginning with an upper case letter.
+
+Here is an example of an example:
+
+       func ExamplePrintln() {
+               Println("The output of\nthis example.")
+               // Output: The output of
+               // this example.
+       }
+
+The entire test file is presented as the example when it contains a single
+example function, at least one other function, type, variable, or constant
+declaration, and no test or benchmark functions.
+
+See the documentation of the testing package for more information.
+
+
+*/
+package main
diff --git a/libgo/go/cmd/go/env.go b/libgo/go/cmd/go/env.go
new file mode 100644 (file)
index 0000000..26d37df
--- /dev/null
@@ -0,0 +1,112 @@
+// 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 main
+
+import (
+       "fmt"
+       "os"
+       "runtime"
+       "strings"
+)
+
+var cmdEnv = &Command{
+       Run:       runEnv,
+       UsageLine: "env [var ...]",
+       Short:     "print Go environment information",
+       Long: `
+Env prints Go environment information.
+
+By default env prints information as a shell script
+(on Windows, a batch file).  If one or more variable
+names is given as arguments,  env prints the value of
+each named variable on its own line.
+       `,
+}
+
+type envVar struct {
+       name, value string
+}
+
+func mkEnv() []envVar {
+       var b builder
+       b.init()
+
+       env := []envVar{
+               {"GOARCH", goarch},
+               {"GOBIN", gobin},
+               {"GOCHAR", archChar},
+               {"GOEXE", exeSuffix},
+               {"GOHOSTARCH", runtime.GOARCH},
+               {"GOHOSTOS", runtime.GOOS},
+               {"GOOS", goos},
+               {"GOPATH", os.Getenv("GOPATH")},
+               {"GORACE", os.Getenv("GORACE")},
+               {"GOROOT", goroot},
+               {"GOTOOLDIR", toolDir},
+
+               // disable escape codes in clang errors
+               {"TERM", "dumb"},
+       }
+
+       if goos != "plan9" {
+               cmd := b.gccCmd(".")
+               env = append(env, envVar{"CC", cmd[0]})
+               env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})
+               cmd = b.gxxCmd(".")
+               env = append(env, envVar{"CXX", cmd[0]})
+       }
+
+       if buildContext.CgoEnabled {
+               env = append(env, envVar{"CGO_ENABLED", "1"})
+       } else {
+               env = append(env, envVar{"CGO_ENABLED", "0"})
+       }
+
+       return env
+}
+
+func findEnv(env []envVar, name string) string {
+       for _, e := range env {
+               if e.name == name {
+                       return e.value
+               }
+       }
+       return ""
+}
+
+func runEnv(cmd *Command, args []string) {
+       env := mkEnv()
+       if len(args) > 0 {
+               for _, name := range args {
+                       fmt.Printf("%s\n", findEnv(env, name))
+               }
+               return
+       }
+
+       for _, e := range env {
+               if e.name != "TERM" {
+                       switch runtime.GOOS {
+                       default:
+                               fmt.Printf("%s=\"%s\"\n", e.name, e.value)
+                       case "plan9":
+                               if strings.IndexByte(e.value, '\x00') < 0 {
+                                       fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
+                               } else {
+                                       v := strings.Split(e.value, "\x00")
+                                       fmt.Printf("%s=(", e.name)
+                                       for x, s := range v {
+                                               if x > 0 {
+                                                       fmt.Printf(" ")
+                                               }
+                                               fmt.Printf("%s", s)
+                                       }
+                                       fmt.Printf(")\n")
+                               }
+                       case "windows":
+                               fmt.Printf("set %s=%s\n", e.name, e.value)
+                       }
+               }
+       }
+}
diff --git a/libgo/go/cmd/go/fix.go b/libgo/go/cmd/go/fix.go
new file mode 100644 (file)
index 0000000..8736cce
--- /dev/null
@@ -0,0 +1,30 @@
+// 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
+
+var cmdFix = &Command{
+       Run:       runFix,
+       UsageLine: "fix [packages]",
+       Short:     "run go tool fix on packages",
+       Long: `
+Fix runs the Go fix command on the packages named by the import paths.
+
+For more about fix, see 'godoc fix'.
+For more about specifying packages, see 'go help packages'.
+
+To run fix with specific options, run 'go tool fix'.
+
+See also: go fmt, go vet.
+       `,
+}
+
+func runFix(cmd *Command, args []string) {
+       for _, pkg := range packages(args) {
+               // Use pkg.gofiles instead of pkg.Dir so that
+               // the command only applies to this package,
+               // not to packages in subdirectories.
+               run(stringList(tool("fix"), relPaths(pkg.allgofiles)))
+       }
+}
diff --git a/libgo/go/cmd/go/fmt.go b/libgo/go/cmd/go/fmt.go
new file mode 100644 (file)
index 0000000..65dc3ca
--- /dev/null
@@ -0,0 +1,38 @@
+// 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
+
+func init() {
+       addBuildFlagsNX(cmdFmt)
+}
+
+var cmdFmt = &Command{
+       Run:       runFmt,
+       UsageLine: "fmt [-n] [-x] [packages]",
+       Short:     "run gofmt on package sources",
+       Long: `
+Fmt runs the command 'gofmt -l -w' on the packages named
+by the import paths.  It prints the names of the files that are modified.
+
+For more about gofmt, see 'godoc gofmt'.
+For more about specifying packages, see 'go help packages'.
+
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go fix, go vet.
+       `,
+}
+
+func runFmt(cmd *Command, args []string) {
+       for _, pkg := range packages(args) {
+               // Use pkg.gofiles instead of pkg.Dir so that
+               // the command only applies to this package,
+               // not to packages in subdirectories.
+               run(stringList("gofmt", "-l", "-w", relPaths(pkg.allgofiles)))
+       }
+}
diff --git a/libgo/go/cmd/go/get.go b/libgo/go/cmd/go/get.go
new file mode 100644 (file)
index 0000000..e708fcf
--- /dev/null
@@ -0,0 +1,429 @@
+// 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 (
+       "fmt"
+       "go/build"
+       "os"
+       "path/filepath"
+       "regexp"
+       "runtime"
+       "strconv"
+       "strings"
+)
+
+var cmdGet = &Command{
+       UsageLine: "get [-d] [-fix] [-t] [-u] [build flags] [packages]",
+       Short:     "download and install packages and dependencies",
+       Long: `
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+The -fix flag instructs get to run the fix tool on the downloaded packages
+before resolving dependencies or building the code.
+
+The -t flag instructs get to also download the packages required to build
+the tests for the specified packages.
+
+The -u flag instructs get to use the network to update the named packages
+and their dependencies.  By default, get uses the network to check out
+missing packages but does not use it to look for updates to existing packages.
+
+Get also accepts build flags to control the installation. See 'go help build'.
+
+When checking out or updating a package, get looks for a branch or tag
+that matches the locally installed version of Go. The most important
+rule is that if the local installation is running version "go1", get
+searches for a branch or tag named "go1". If no such version exists it
+retrieves the most recent version of the package.
+
+For more about specifying packages, see 'go help packages'.
+
+For more about how 'go get' finds source code to
+download, see 'go help importpath'.
+
+See also: go build, go install, go clean.
+       `,
+}
+
+var getD = cmdGet.Flag.Bool("d", false, "")
+var getT = cmdGet.Flag.Bool("t", false, "")
+var getU = cmdGet.Flag.Bool("u", false, "")
+var getFix = cmdGet.Flag.Bool("fix", false, "")
+
+func init() {
+       addBuildFlags(cmdGet)
+       cmdGet.Run = runGet // break init loop
+}
+
+func runGet(cmd *Command, args []string) {
+       // Phase 1.  Download/update.
+       var stk importStack
+       for _, arg := range downloadPaths(args) {
+               download(arg, &stk, *getT)
+       }
+       exitIfErrors()
+
+       // Phase 2. Rescan packages and re-evaluate args list.
+
+       // Code we downloaded and all code that depends on it
+       // needs to be evicted from the package cache so that
+       // the information will be recomputed.  Instead of keeping
+       // track of the reverse dependency information, evict
+       // everything.
+       for name := range packageCache {
+               delete(packageCache, name)
+       }
+
+       args = importPaths(args)
+
+       // Phase 3.  Install.
+       if *getD {
+               // Download only.
+               // Check delayed until now so that importPaths
+               // has a chance to print errors.
+               return
+       }
+
+       runInstall(cmd, args)
+}
+
+// downloadPaths prepares the list of paths to pass to download.
+// It expands ... patterns that can be expanded.  If there is no match
+// for a particular pattern, downloadPaths leaves it in the result list,
+// in the hope that we can figure out the repository from the
+// initial ...-free prefix.
+func downloadPaths(args []string) []string {
+       args = importPathsNoDotExpansion(args)
+       var out []string
+       for _, a := range args {
+               if strings.Contains(a, "...") {
+                       var expand []string
+                       // Use matchPackagesInFS to avoid printing
+                       // warnings.  They will be printed by the
+                       // eventual call to importPaths instead.
+                       if build.IsLocalImport(a) {
+                               expand = matchPackagesInFS(a)
+                       } else {
+                               expand = matchPackages(a)
+                       }
+                       if len(expand) > 0 {
+                               out = append(out, expand...)
+                               continue
+                       }
+               }
+               out = append(out, a)
+       }
+       return out
+}
+
+// downloadCache records the import paths we have already
+// considered during the download, to avoid duplicate work when
+// there is more than one dependency sequence leading to
+// a particular package.
+var downloadCache = map[string]bool{}
+
+// downloadRootCache records the version control repository
+// root directories we have already considered during the download.
+// For example, all the packages in the code.google.com/p/codesearch repo
+// share the same root (the directory for that path), and we only need
+// to run the hg commands to consider each repository once.
+var downloadRootCache = map[string]bool{}
+
+// download runs the download half of the get command
+// for the package named by the argument.
+func download(arg string, stk *importStack, getTestDeps bool) {
+       p := loadPackage(arg, stk)
+       if p.Error != nil && p.Error.hard {
+               errorf("%s", p.Error)
+               return
+       }
+
+       // There's nothing to do if this is a package in the standard library.
+       if p.Standard {
+               return
+       }
+
+       // Only process each package once.
+       if downloadCache[arg] {
+               return
+       }
+       downloadCache[arg] = true
+
+       pkgs := []*Package{p}
+       wildcardOkay := len(*stk) == 0
+       isWildcard := false
+
+       // Download if the package is missing, or update if we're using -u.
+       if p.Dir == "" || *getU {
+               // The actual download.
+               stk.push(p.ImportPath)
+               err := downloadPackage(p)
+               if err != nil {
+                       errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
+                       stk.pop()
+                       return
+               }
+
+               args := []string{arg}
+               // If the argument has a wildcard in it, re-evaluate the wildcard.
+               // We delay this until after reloadPackage so that the old entry
+               // for p has been replaced in the package cache.
+               if wildcardOkay && strings.Contains(arg, "...") {
+                       if build.IsLocalImport(arg) {
+                               args = matchPackagesInFS(arg)
+                       } else {
+                               args = matchPackages(arg)
+                       }
+                       isWildcard = true
+               }
+
+               // Clear all relevant package cache entries before
+               // doing any new loads.
+               for _, arg := range args {
+                       p := packageCache[arg]
+                       if p != nil {
+                               delete(packageCache, p.Dir)
+                               delete(packageCache, p.ImportPath)
+                       }
+               }
+
+               pkgs = pkgs[:0]
+               for _, arg := range args {
+                       stk.push(arg)
+                       p := loadPackage(arg, stk)
+                       stk.pop()
+                       if p.Error != nil {
+                               errorf("%s", p.Error)
+                               continue
+                       }
+                       pkgs = append(pkgs, p)
+               }
+       }
+
+       // Process package, which might now be multiple packages
+       // due to wildcard expansion.
+       for _, p := range pkgs {
+               if *getFix {
+                       run(stringList(tool("fix"), relPaths(p.allgofiles)))
+
+                       // The imports might have changed, so reload again.
+                       p = reloadPackage(arg, stk)
+                       if p.Error != nil {
+                               errorf("%s", p.Error)
+                               return
+                       }
+               }
+
+               if isWildcard {
+                       // Report both the real package and the
+                       // wildcard in any error message.
+                       stk.push(p.ImportPath)
+               }
+
+               // Process dependencies, now that we know what they are.
+               for _, dep := range p.deps {
+                       // Don't get test dependencies recursively.
+                       download(dep.ImportPath, stk, false)
+               }
+               if getTestDeps {
+                       // Process test dependencies when -t is specified.
+                       // (Don't get test dependencies for test dependencies.)
+                       for _, path := range p.TestImports {
+                               download(path, stk, false)
+                       }
+                       for _, path := range p.XTestImports {
+                               download(path, stk, false)
+                       }
+               }
+
+               if isWildcard {
+                       stk.pop()
+               }
+       }
+}
+
+// downloadPackage runs the create or download command
+// to make the first copy of or update a copy of the given package.
+func downloadPackage(p *Package) error {
+       var (
+               vcs            *vcsCmd
+               repo, rootPath string
+               err            error
+       )
+       if p.build.SrcRoot != "" {
+               // Directory exists.  Look for checkout along path to src.
+               vcs, rootPath, err = vcsForDir(p)
+               if err != nil {
+                       return err
+               }
+               repo = "<local>" // should be unused; make distinctive
+       } else {
+               // Analyze the import path to determine the version control system,
+               // repository, and the import path for the root of the repository.
+               rr, err := repoRootForImportPath(p.ImportPath)
+               if err != nil {
+                       return err
+               }
+               vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
+       }
+
+       if p.build.SrcRoot == "" {
+               // Package not found.  Put in first directory of $GOPATH.
+               list := filepath.SplitList(buildContext.GOPATH)
+               if len(list) == 0 {
+                       return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath")
+               }
+               // Guard against people setting GOPATH=$GOROOT.
+               if list[0] == goroot {
+                       return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath")
+               }
+               p.build.SrcRoot = filepath.Join(list[0], "src")
+               p.build.PkgRoot = filepath.Join(list[0], "pkg")
+       }
+       root := filepath.Join(p.build.SrcRoot, rootPath)
+       // If we've considered this repository already, don't do it again.
+       if downloadRootCache[root] {
+               return nil
+       }
+       downloadRootCache[root] = true
+
+       if buildV {
+               fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
+       }
+
+       // Check that this is an appropriate place for the repo to be checked out.
+       // The target directory must either not exist or have a repo checked out already.
+       meta := filepath.Join(root, "."+vcs.cmd)
+       st, err := os.Stat(meta)
+       if err == nil && !st.IsDir() {
+               return fmt.Errorf("%s exists but is not a directory", meta)
+       }
+       if err != nil {
+               // Metadata directory does not exist.  Prepare to checkout new copy.
+               // Some version control tools require the target directory not to exist.
+               // We require that too, just to avoid stepping on existing work.
+               if _, err := os.Stat(root); err == nil {
+                       return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
+               }
+               // Some version control tools require the parent of the target to exist.
+               parent, _ := filepath.Split(root)
+               if err = os.MkdirAll(parent, 0777); err != nil {
+                       return err
+               }
+               if err = vcs.create(root, repo); err != nil {
+                       return err
+               }
+       } else {
+               // Metadata directory does exist; download incremental updates.
+               if err = vcs.download(root); err != nil {
+                       return err
+               }
+       }
+
+       if buildN {
+               // Do not show tag sync in -n; it's noise more than anything,
+               // and since we're not running commands, no tag will be found.
+               // But avoid printing nothing.
+               fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
+               return nil
+       }
+
+       // Select and sync to appropriate version of the repository.
+       tags, err := vcs.tags(root)
+       if err != nil {
+               return err
+       }
+       vers := runtime.Version()
+       if i := strings.Index(vers, " "); i >= 0 {
+               vers = vers[:i]
+       }
+       if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil {
+               return err
+       }
+
+       return nil
+}
+
+// goTag matches go release tags such as go1 and go1.2.3.
+// The numbers involved must be small (at most 4 digits),
+// have no unnecessary leading zeros, and the version cannot
+// end in .0 - it is go1, not go1.0 or go1.0.0.
+var goTag = regexp.MustCompile(
+       `^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`,
+)
+
+// selectTag returns the closest matching tag for a given version.
+// Closest means the latest one that is not after the current release.
+// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
+// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
+// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
+//
+// NOTE(rsc): Eventually we will need to decide on some logic here.
+// For now, there is only "go1".  This matches the docs in go help get.
+func selectTag(goVersion string, tags []string) (match string) {
+       for _, t := range tags {
+               if t == "go1" {
+                       return "go1"
+               }
+       }
+       return ""
+
+       /*
+               if goTag.MatchString(goVersion) {
+                       v := goVersion
+                       for _, t := range tags {
+                               if !goTag.MatchString(t) {
+                                       continue
+                               }
+                               if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
+                                       match = t
+                               }
+                       }
+               }
+
+               return match
+       */
+}
+
+// cmpGoVersion returns -1, 0, +1 reporting whether
+// x < y, x == y, or x > y.
+func cmpGoVersion(x, y string) int {
+       // Malformed strings compare less than well-formed strings.
+       if !goTag.MatchString(x) {
+               return -1
+       }
+       if !goTag.MatchString(y) {
+               return +1
+       }
+
+       // Compare numbers in sequence.
+       xx := strings.Split(x[len("go"):], ".")
+       yy := strings.Split(y[len("go"):], ".")
+
+       for i := 0; i < len(xx) && i < len(yy); i++ {
+               // The Atoi are guaranteed to succeed
+               // because the versions match goTag.
+               xi, _ := strconv.Atoi(xx[i])
+               yi, _ := strconv.Atoi(yy[i])
+               if xi < yi {
+                       return -1
+               } else if xi > yi {
+                       return +1
+               }
+       }
+
+       if len(xx) < len(yy) {
+               return -1
+       }
+       if len(xx) > len(yy) {
+               return +1
+       }
+       return 0
+}
diff --git a/libgo/go/cmd/go/go11.go b/libgo/go/cmd/go/go11.go
new file mode 100644 (file)
index 0000000..8a434df
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+// +build go1.1
+
+package main
+
+// Test that go1.1 tag above is included in builds. main.go refers to this definition.
+const go11tag = true
diff --git a/libgo/go/cmd/go/help.go b/libgo/go/cmd/go/help.go
new file mode 100644 (file)
index 0000000..40da7e1
--- /dev/null
@@ -0,0 +1,337 @@
+// 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
+
+var helpC = &Command{
+       UsageLine: "c",
+       Short:     "calling between Go and C",
+       Long: `
+There are two different ways to call between Go and C/C++ code.
+
+The first is the cgo tool, which is part of the Go distribution.  For
+information on how to use it see the cgo documentation (godoc cmd/cgo).
+
+The second is the SWIG program, which is a general tool for
+interfacing between languages.  For information on SWIG see
+http://swig.org/.  When running go build, any file with a .swig
+extension will be passed to SWIG.  Any file with a .swigcxx extension
+will be passed to SWIG with the -c++ option.
+
+When either cgo or SWIG is used, go build will pass any .c, .m, .s,
+or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++
+compiler.  The CC or CXX environment variables may be set to determine
+the C or C++ compiler, respectively, to use.
+       `,
+}
+
+var helpPackages = &Command{
+       UsageLine: "packages",
+       Short:     "description of package lists",
+       Long: `
+Many commands apply to a set of packages:
+
+       go action [packages]
+
+Usually, [packages] is a list of import paths.
+
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (see 'go help gopath').
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+There are three reserved names for paths that should not be used
+for packages to be built with the go tool:
+
+- "main" denotes the top-level package in a stand-alone executable.
+
+- "all" expands to all package directories found in all the GOPATH
+trees. For example, 'go list all' lists all the packages on the local
+system.
+
+- "std" is like all but expands to just the packages in the standard
+Go library.
+
+An import path is a pattern if it includes one or more "..." wildcards,
+each of which can match any string, including the empty string and
+strings containing slashes.  Such a pattern expands to all package
+directories found in the GOPATH trees with names matching the
+patterns.  As a special case, x/... matches x as well as x's subdirectories.
+For example, net/... expands to net and packages in its subdirectories.
+
+An import path can also name a package to be downloaded from
+a remote repository.  Run 'go help importpath' for details.
+
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you.  For example, paths used
+internally at Google all begin with 'google', and paths
+denoting remote repositories begin with the path to the code,
+such as 'code.google.com/p/project'.
+
+As a special case, if the package list is a list of .go files from a
+single directory, the command is applied to a single synthesized
+package made up of exactly those files, ignoring any build constraints
+in those files and ignoring any other files in the directory.
+
+File names that begin with "." or "_" are ignored by the go tool.
+       `,
+}
+
+var helpImportPath = &Command{
+       UsageLine: "importpath",
+       Short:     "import path syntax",
+       Long: `
+
+An import path (see 'go help packages') denotes a package
+stored in the local file system.  In general, an import path denotes
+either a standard package (such as "unicode/utf8") or a package
+found in one of the work spaces (see 'go help gopath').
+
+Relative import paths
+
+An import path beginning with ./ or ../ is called a relative path.
+The toolchain supports relative import paths as a shortcut in two ways.
+
+First, a relative path can be used as a shorthand on the command line.
+If you are working in the directory containing the code imported as
+"unicode" and want to run the tests for "unicode/utf8", you can type
+"go test ./utf8" instead of needing to specify the full path.
+Similarly, in the reverse situation, "go test .." will test "unicode" from
+the "unicode/utf8" directory. Relative patterns are also allowed, like
+"go test ./..." to test all subdirectories. See 'go help packages' for details
+on the pattern syntax.
+
+Second, if you are compiling a Go program not in a work space,
+you can use a relative path in an import statement in that program
+to refer to nearby code also not in a work space.
+This makes it easy to experiment with small multipackage programs
+outside of the usual work spaces, but such programs cannot be
+installed with "go install" (there is no work space in which to install them),
+so they are rebuilt from scratch each time they are built.
+To avoid ambiguity, Go programs cannot use relative import paths
+within a work space.
+
+Remote import paths
+
+Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+
+A few common code hosting sites have special syntax:
+
+       Bitbucket (Git, Mercurial)
+
+               import "bitbucket.org/user/project"
+               import "bitbucket.org/user/project/sub/directory"
+
+       GitHub (Git)
+
+               import "github.com/user/project"
+               import "github.com/user/project/sub/directory"
+
+       Google Code Project Hosting (Git, Mercurial, Subversion)
+
+               import "code.google.com/p/project"
+               import "code.google.com/p/project/sub/directory"
+
+               import "code.google.com/p/project.subrepository"
+               import "code.google.com/p/project.subrepository/sub/directory"
+
+       Launchpad (Bazaar)
+
+               import "launchpad.net/project"
+               import "launchpad.net/project/series"
+               import "launchpad.net/project/series/sub/directory"
+
+               import "launchpad.net/~user/project/branch"
+               import "launchpad.net/~user/project/branch/sub/directory"
+
+For code hosted on other servers, import paths may either be qualified
+with the version control type, or the go tool can dynamically fetch
+the import path over https/http and discover where the code resides
+from a <meta> tag in the HTML.
+
+To declare the code location, an import path of the form
+
+       repository.vcs/path
+
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository.  The supported version control systems are:
+
+       Bazaar      .bzr
+       Git         .git
+       Mercurial   .hg
+       Subversion  .svn
+
+For example,
+
+       import "example.org/user/foo.hg"
+
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+
+       import "example.org/repo.git/foo/bar"
+
+denotes the foo/bar directory of the Git repository at
+example.org/repo or repo.git.
+
+When a version control system supports multiple protocols,
+each is tried in turn when downloading.  For example, a Git
+download tries git://, then https://, then http://.
+
+If the import path is not a known code hosting site and also lacks a
+version control qualifier, the go tool attempts to fetch the import
+over https/http and looks for a <meta> tag in the document's HTML
+<head>.
+
+The meta tag has the form:
+
+       <meta name="go-import" content="import-prefix vcs repo-root">
+
+The import-prefix is the import path corresponding to the repository
+root. It must be a prefix or an exact match of the package being
+fetched with "go get". If it's not an exact match, another http
+request is made at the prefix to verify the <meta> tags match.
+
+The vcs is one of "git", "hg", "svn", etc,
+
+The repo-root is the root of the version control system
+containing a scheme and not containing a .vcs qualifier.
+
+For example,
+
+       import "example.org/pkg/foo"
+
+will result in the following request(s):
+
+       https://example.org/pkg/foo?go-get=1 (preferred)
+       http://example.org/pkg/foo?go-get=1  (fallback)
+
+If that page contains the meta tag
+
+       <meta name="go-import" content="example.org git https://code.org/r/p/exproj">
+
+the go tool will verify that https://example.org/?go-get=1 contains the
+same meta tag and then git clone https://code.org/r/p/exproj into
+GOPATH/src/example.org.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (see 'go help gopath').
+
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run 'go help install' for more.
+       `,
+}
+
+var helpGopath = &Command{
+       UsageLine: "gopath",
+       Short:     "GOPATH environment variable",
+       Long: `
+The Go path is used to resolve import statements.
+It is implemented by and documented in the go/build package.
+
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+
+GOPATH must be set to get, build and install packages outside the
+standard Go tree.
+
+Each directory listed in GOPATH must have a prescribed structure:
+
+The src/ directory holds source code.  The path below 'src'
+determines the import path or executable name.
+
+The pkg/ directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as "foo/bar" and
+has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
+
+The bin/ directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path.  That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.  If the GOBIN environment variable is
+set, commands are installed to the directory it names instead
+of DIR/bin.
+
+Here's an example directory layout:
+
+    GOPATH=/home/user/gocode
+
+    /home/user/gocode/
+        src/
+            foo/
+                bar/               (go code in package bar)
+                    x.go
+                quux/              (go code in package main)
+                    y.go
+        bin/
+            quux                   (installed command)
+        pkg/
+            linux_amd64/
+                foo/
+                    bar.a          (installed package object)
+
+Go searches each directory listed in GOPATH to find source code,
+but new packages are always downloaded into the first directory
+in the list.
+       `,
+}
+
+var helpFileType = &Command{
+       UsageLine: "filetype",
+       Short:     "file types",
+       Long: `
+The go command examines the contents of a restricted set of files
+in each directory. It identifies which files to examine based on
+the extension of the file name. These extensions are:
+
+       .go
+               Go source files.
+       .c, .h
+               C source files.
+               If the package uses cgo, these will be compiled with the
+               OS-native compiler (typically gcc); otherwise they will be
+               compiled with the Go-specific support compiler,
+               5c, 6c, or 8c, etc. as appropriate.
+       .cc, .cpp, .cxx, .hh, .hpp, .hxx
+               C++ source files. Only useful with cgo or SWIG, and always
+               compiled with the OS-native compiler.
+       .m
+               Objective-C source files. Only useful with cgo, and always
+               compiled with the OS-native compiler.
+       .s, .S
+               Assembler source files.
+               If the package uses cgo, these will be assembled with the
+               OS-native assembler (typically gcc (sic)); otherwise they
+               will be assembled with the Go-specific support assembler,
+               5a, 6a, or 8a, etc., as appropriate.
+       .swig, .swigcxx
+               SWIG definition files.
+       .syso
+               System object files.
+
+Files of each of these types except .syso may contain build
+constraints, but the go command stops scanning for build constraints
+at the first item in the file that is not a blank line or //-style
+line comment.
+       `,
+}
diff --git a/libgo/go/cmd/go/http.go b/libgo/go/cmd/go/http.go
new file mode 100644 (file)
index 0000000..107b820
--- /dev/null
@@ -0,0 +1,87 @@
+// 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.
+
+// +build !cmd_go_bootstrap
+
+// This code is compiled into the real 'go' binary, but it is not
+// compiled into the binary that is built during all.bash, so as
+// to avoid needing to build net (and thus use cgo) during the
+// bootstrap process.
+
+package main
+
+import (
+       "fmt"
+       "io"
+       "io/ioutil"
+       "log"
+       "net/http"
+       "net/url"
+)
+
+// httpClient is the default HTTP client, but a variable so it can be
+// changed by tests, without modifying http.DefaultClient.
+var httpClient = http.DefaultClient
+
+// httpGET returns the data from an HTTP GET request for the given URL.
+func httpGET(url string) ([]byte, error) {
+       resp, err := httpClient.Get(url)
+       if err != nil {
+               return nil, err
+       }
+       defer resp.Body.Close()
+       if resp.StatusCode != 200 {
+               return nil, fmt.Errorf("%s: %s", url, resp.Status)
+       }
+       b, err := ioutil.ReadAll(resp.Body)
+       if err != nil {
+               return nil, fmt.Errorf("%s: %v", url, err)
+       }
+       return b, nil
+}
+
+// httpsOrHTTP returns the body of either the importPath's
+// https resource or, if unavailable, the http resource.
+func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err error) {
+       fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
+               u, err := url.Parse(scheme + "://" + importPath)
+               if err != nil {
+                       return "", nil, err
+               }
+               u.RawQuery = "go-get=1"
+               urlStr = u.String()
+               if buildV {
+                       log.Printf("Fetching %s", urlStr)
+               }
+               res, err = httpClient.Get(urlStr)
+               return
+       }
+       closeBody := func(res *http.Response) {
+               if res != nil {
+                       res.Body.Close()
+               }
+       }
+       urlStr, res, err := fetch("https")
+       if err != nil || res.StatusCode != 200 {
+               if buildV {
+                       if err != nil {
+                               log.Printf("https fetch failed.")
+                       } else {
+                               log.Printf("ignoring https fetch with status code %d", res.StatusCode)
+                       }
+               }
+               closeBody(res)
+               urlStr, res, err = fetch("http")
+       }
+       if err != nil {
+               closeBody(res)
+               return "", nil, err
+       }
+       // Note: accepting a non-200 OK here, so people can serve a
+       // meta import in their http 404 page.
+       if buildV {
+               log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode)
+       }
+       return urlStr, res.Body, nil
+}
diff --git a/libgo/go/cmd/go/list.go b/libgo/go/cmd/go/list.go
new file mode 100644 (file)
index 0000000..0ead435
--- /dev/null
@@ -0,0 +1,208 @@
+// 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 (
+       "bufio"
+       "encoding/json"
+       "io"
+       "os"
+       "strings"
+       "text/template"
+)
+
+var cmdList = &Command{
+       UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]",
+       Short:     "list packages",
+       Long: `
+List lists the packages named by the import paths, one per line.
+
+The default output shows the package import path:
+
+    code.google.com/p/google-api-go-client/books/v1
+    code.google.com/p/goauth2/oauth
+    code.google.com/p/sqlite
+
+The -f flag specifies an alternate format for the list, using the
+syntax of package template.  The default output is equivalent to -f
+'{{.ImportPath}}'. The struct being passed to the template is:
+
+    type Package struct {
+        Dir        string // directory containing package sources
+        ImportPath string // import path of package in dir
+        Name       string // package name
+        Doc        string // package documentation string
+        Target     string // install path
+        Goroot     bool   // is this package in the Go root?
+        Standard   bool   // is this package part of the standard Go library?
+        Stale      bool   // would 'go install' do anything for this package?
+        Root       string // Go root or Go path dir containing this package
+
+        // Source files
+        GoFiles  []string       // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+        CgoFiles []string       // .go sources files that import "C"
+        IgnoredGoFiles []string // .go sources ignored due to build constraints
+        CFiles   []string       // .c source files
+        CXXFiles []string       // .cc, .cxx and .cpp source files
+        MFiles   []string       // .m source files
+        HFiles   []string       // .h, .hh, .hpp and .hxx source files
+        SFiles   []string       // .s source files
+        SwigFiles []string      // .swig files
+        SwigCXXFiles []string   // .swigcxx files
+        SysoFiles []string      // .syso object files to add to archive
+
+        // Cgo directives
+        CgoCFLAGS    []string // cgo: flags for C compiler
+        CgoCPPFLAGS  []string // cgo: flags for C preprocessor
+        CgoCXXFLAGS  []string // cgo: flags for C++ compiler
+        CgoLDFLAGS   []string // cgo: flags for linker
+        CgoPkgConfig []string // cgo: pkg-config names
+
+        // Dependency information
+        Imports []string // import paths used by this package
+        Deps    []string // all (recursively) imported dependencies
+
+        // Error information
+        Incomplete bool            // this package or a dependency has an error
+        Error      *PackageError   // error loading package
+        DepsErrors []*PackageError // errors loading dependencies
+
+        TestGoFiles  []string // _test.go files in package
+        TestImports  []string // imports from TestGoFiles
+        XTestGoFiles []string // _test.go files outside package
+        XTestImports []string // imports from XTestGoFiles
+    }
+
+The template function "join" calls strings.Join.
+
+The template function "context" returns the build context, defined as:
+
+       type Context struct {
+               GOARCH        string   // target architecture
+               GOOS          string   // target operating system
+               GOROOT        string   // Go root
+               GOPATH        string   // Go path
+               CgoEnabled    bool     // whether cgo can be used
+               UseAllFiles   bool     // use files regardless of +build lines, file names
+               Compiler      string   // compiler to assume when computing target paths
+               BuildTags     []string // build constraints to match in +build lines
+               ReleaseTags   []string // releases the current release is compatible with
+               InstallSuffix string   // suffix to use in the name of the install dir
+       }
+
+For more information about the meaning of these fields see the documentation
+for the go/build package's Context type.
+
+The -json flag causes the package data to be printed in JSON format
+instead of using the template format.
+
+The -e flag changes the handling of erroneous packages, those that
+cannot be found or are malformed.  By default, the list command
+prints an error to standard error for each erroneous package and
+omits the packages from consideration during the usual printing.
+With the -e flag, the list command never prints errors to standard
+error and instead processes the erroneous packages with the usual
+printing.  Erroneous packages will have a non-empty ImportPath and
+a non-nil Error field; other information may or may not be missing
+(zeroed).
+
+For more about build flags, see 'go help build'.
+
+For more about specifying packages, see 'go help packages'.
+       `,
+}
+
+func init() {
+       cmdList.Run = runList // break init cycle
+       addBuildFlags(cmdList)
+}
+
+var listE = cmdList.Flag.Bool("e", false, "")
+var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
+var listJson = cmdList.Flag.Bool("json", false, "")
+var nl = []byte{'\n'}
+
+func runList(cmd *Command, args []string) {
+       out := newTrackingWriter(os.Stdout)
+       defer out.w.Flush()
+
+       var do func(*Package)
+       if *listJson {
+               do = func(p *Package) {
+                       b, err := json.MarshalIndent(p, "", "\t")
+                       if err != nil {
+                               out.Flush()
+                               fatalf("%s", err)
+                       }
+                       out.Write(b)
+                       out.Write(nl)
+               }
+       } else {
+               var cachedCtxt *Context
+               context := func() *Context {
+                       if cachedCtxt == nil {
+                               cachedCtxt = newContext(&buildContext)
+                       }
+                       return cachedCtxt
+               }
+               fm := template.FuncMap{
+                       "join":    strings.Join,
+                       "context": context,
+               }
+               tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
+               if err != nil {
+                       fatalf("%s", err)
+               }
+               do = func(p *Package) {
+                       if err := tmpl.Execute(out, p); err != nil {
+                               out.Flush()
+                               fatalf("%s", err)
+                       }
+                       if out.NeedNL() {
+                               out.Write(nl)
+                       }
+               }
+       }
+
+       load := packages
+       if *listE {
+               load = packagesAndErrors
+       }
+
+       for _, pkg := range load(args) {
+               do(pkg)
+       }
+}
+
+// TrackingWriter tracks the last byte written on every write so
+// we can avoid printing a newline if one was already written or
+// if there is no output at all.
+type TrackingWriter struct {
+       w    *bufio.Writer
+       last byte
+}
+
+func newTrackingWriter(w io.Writer) *TrackingWriter {
+       return &TrackingWriter{
+               w:    bufio.NewWriter(w),
+               last: '\n',
+       }
+}
+
+func (t *TrackingWriter) Write(p []byte) (n int, err error) {
+       n, err = t.w.Write(p)
+       if n > 0 {
+               t.last = p[n-1]
+       }
+       return
+}
+
+func (t *TrackingWriter) Flush() {
+       t.w.Flush()
+}
+
+func (t *TrackingWriter) NeedNL() bool {
+       return t.last != '\n'
+}
diff --git a/libgo/go/cmd/go/main.go b/libgo/go/cmd/go/main.go
new file mode 100644 (file)
index 0000000..5b1194a
--- /dev/null
@@ -0,0 +1,722 @@
+// 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 (
+       "bytes"
+       "flag"
+       "fmt"
+       "go/build"
+       "io"
+       "log"
+       "os"
+       "os/exec"
+       "path"
+       "path/filepath"
+       "regexp"
+       "runtime"
+       "strings"
+       "sync"
+       "text/template"
+       "unicode"
+       "unicode/utf8"
+)
+
+// A Command is an implementation of a go command
+// like go build or go fix.
+type Command struct {
+       // Run runs the command.
+       // The args are the arguments after the command name.
+       Run func(cmd *Command, args []string)
+
+       // UsageLine is the one-line usage message.
+       // The first word in the line is taken to be the command name.
+       UsageLine string
+
+       // Short is the short description shown in the 'go help' output.
+       Short string
+
+       // Long is the long message shown in the 'go help <this-command>' output.
+       Long string
+
+       // Flag is a set of flags specific to this command.
+       Flag flag.FlagSet
+
+       // CustomFlags indicates that the command will do its own
+       // flag parsing.
+       CustomFlags bool
+}
+
+// Name returns the command's name: the first word in the usage line.
+func (c *Command) Name() string {
+       name := c.UsageLine
+       i := strings.Index(name, " ")
+       if i >= 0 {
+               name = name[:i]
+       }
+       return name
+}
+
+func (c *Command) Usage() {
+       fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
+       fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
+       os.Exit(2)
+}
+
+// Runnable reports whether the command can be run; otherwise
+// it is a documentation pseudo-command such as importpath.
+func (c *Command) Runnable() bool {
+       return c.Run != nil
+}
+
+// Commands lists the available commands and help topics.
+// The order here is the order in which they are printed by 'go help'.
+var commands = []*Command{
+       cmdBuild,
+       cmdClean,
+       cmdEnv,
+       cmdFix,
+       cmdFmt,
+       cmdGet,
+       cmdInstall,
+       cmdList,
+       cmdRun,
+       cmdTest,
+       cmdTool,
+       cmdVersion,
+       cmdVet,
+
+       helpC,
+       helpFileType,
+       helpGopath,
+       helpImportPath,
+       helpPackages,
+       helpTestflag,
+       helpTestfunc,
+}
+
+var exitStatus = 0
+var exitMu sync.Mutex
+
+func setExitStatus(n int) {
+       exitMu.Lock()
+       if exitStatus < n {
+               exitStatus = n
+       }
+       exitMu.Unlock()
+}
+
+func main() {
+       _ = go11tag
+       flag.Usage = usage
+       flag.Parse()
+       log.SetFlags(0)
+
+       args := flag.Args()
+       if len(args) < 1 {
+               usage()
+       }
+
+       if args[0] == "help" {
+               help(args[1:])
+               return
+       }
+
+       // Diagnose common mistake: GOPATH==GOROOT.
+       // This setting is equivalent to not setting GOPATH at all,
+       // which is not what most people want when they do it.
+       if gopath := os.Getenv("GOPATH"); gopath == runtime.GOROOT() {
+               fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
+       } else {
+               for _, p := range filepath.SplitList(gopath) {
+                       // Note: using HasPrefix instead of Contains because a ~ can appear
+                       // in the middle of directory elements, such as /tmp/git-1.8.2~rc3
+                       // or C:\PROGRA~1. Only ~ as a path prefix has meaning to the shell.
+                       if strings.HasPrefix(p, "~") {
+                               fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p)
+                               os.Exit(2)
+                       }
+                       if build.IsLocalImport(p) {
+                               fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p)
+                               os.Exit(2)
+                       }
+               }
+       }
+
+       if fi, err := os.Stat(goroot); err != nil || !fi.IsDir() {
+               fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", goroot)
+               os.Exit(2)
+       }
+
+       for _, cmd := range commands {
+               if cmd.Name() == args[0] && cmd.Run != nil {
+                       cmd.Flag.Usage = func() { cmd.Usage() }
+                       if cmd.CustomFlags {
+                               args = args[1:]
+                       } else {
+                               cmd.Flag.Parse(args[1:])
+                               args = cmd.Flag.Args()
+                       }
+                       cmd.Run(cmd, args)
+                       exit()
+                       return
+               }
+       }
+
+       fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0])
+       setExitStatus(2)
+       exit()
+}
+
+var usageTemplate = `Go is a tool for managing Go source code.
+
+Usage:
+
+       go command [arguments]
+
+The commands are:
+{{range .}}{{if .Runnable}}
+    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+{{range .}}{{if not .Runnable}}
+    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [topic]" for more information about that topic.
+
+`
+
+var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+`
+
+var documentationTemplate = `// 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.
+
+// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh.
+// Edit the documentation in other files and rerun mkdoc.sh to generate this one.
+
+/*
+{{range .}}{{if .Short}}{{.Short | capitalize}}
+
+{{end}}{{if .Runnable}}Usage:
+
+       go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+
+
+{{end}}*/
+package main
+`
+
+// tmpl executes the given template text on data, writing the result to w.
+func tmpl(w io.Writer, text string, data interface{}) {
+       t := template.New("top")
+       t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
+       template.Must(t.Parse(text))
+       if err := t.Execute(w, data); err != nil {
+               panic(err)
+       }
+}
+
+func capitalize(s string) string {
+       if s == "" {
+               return s
+       }
+       r, n := utf8.DecodeRuneInString(s)
+       return string(unicode.ToTitle(r)) + s[n:]
+}
+
+func printUsage(w io.Writer) {
+       tmpl(w, usageTemplate, commands)
+}
+
+func usage() {
+       // special case "go test -h"
+       if len(os.Args) > 1 && os.Args[1] == "test" {
+               help([]string{"testflag"})
+               os.Exit(2)
+       }
+       printUsage(os.Stderr)
+       os.Exit(2)
+}
+
+// help implements the 'help' command.
+func help(args []string) {
+       if len(args) == 0 {
+               printUsage(os.Stdout)
+               // not exit 2: succeeded at 'go help'.
+               return
+       }
+       if len(args) != 1 {
+               fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
+               os.Exit(2) // failed at 'go help'
+       }
+
+       arg := args[0]
+
+       // 'go help documentation' generates doc.go.
+       if arg == "documentation" {
+               buf := new(bytes.Buffer)
+               printUsage(buf)
+               usage := &Command{Long: buf.String()}
+               tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))
+               return
+       }
+
+       for _, cmd := range commands {
+               if cmd.Name() == arg {
+                       tmpl(os.Stdout, helpTemplate, cmd)
+                       // not exit 2: succeeded at 'go help cmd'.
+                       return
+               }
+       }
+
+       fmt.Fprintf(os.Stderr, "Unknown help topic %#q.  Run 'go help'.\n", arg)
+       os.Exit(2) // failed at 'go help cmd'
+}
+
+// importPathsNoDotExpansion returns the import paths to use for the given
+// command line, but it does no ... expansion.
+func importPathsNoDotExpansion(args []string) []string {
+       if len(args) == 0 {
+               return []string{"."}
+       }
+       var out []string
+       for _, a := range args {
+               // Arguments are supposed to be import paths, but
+               // as a courtesy to Windows developers, rewrite \ to /
+               // in command-line arguments.  Handles .\... and so on.
+               if filepath.Separator == '\\' {
+                       a = strings.Replace(a, `\`, `/`, -1)
+               }
+
+               // Put argument in canonical form, but preserve leading ./.
+               if strings.HasPrefix(a, "./") {
+                       a = "./" + path.Clean(a)
+                       if a == "./." {
+                               a = "."
+                       }
+               } else {
+                       a = path.Clean(a)
+               }
+               if a == "all" || a == "std" {
+                       out = append(out, allPackages(a)...)
+                       continue
+               }
+               out = append(out, a)
+       }
+       return out
+}
+
+// importPaths returns the import paths to use for the given command line.
+func importPaths(args []string) []string {
+       args = importPathsNoDotExpansion(args)
+       var out []string
+       for _, a := range args {
+               if strings.Contains(a, "...") {
+                       if build.IsLocalImport(a) {
+                               out = append(out, allPackagesInFS(a)...)
+                       } else {
+                               out = append(out, allPackages(a)...)
+                       }
+                       continue
+               }
+               out = append(out, a)
+       }
+       return out
+}
+
+var atexitFuncs []func()
+
+func atexit(f func()) {
+       atexitFuncs = append(atexitFuncs, f)
+}
+
+func exit() {
+       for _, f := range atexitFuncs {
+               f()
+       }
+       os.Exit(exitStatus)
+}
+
+func fatalf(format string, args ...interface{}) {
+       errorf(format, args...)
+       exit()
+}
+
+func errorf(format string, args ...interface{}) {
+       log.Printf(format, args...)
+       setExitStatus(1)
+}
+
+var logf = log.Printf
+
+func exitIfErrors() {
+       if exitStatus != 0 {
+               exit()
+       }
+}
+
+func run(cmdargs ...interface{}) {
+       cmdline := stringList(cmdargs...)
+       if buildN || buildX {
+               fmt.Printf("%s\n", strings.Join(cmdline, " "))
+               if buildN {
+                       return
+               }
+       }
+
+       cmd := exec.Command(cmdline[0], cmdline[1:]...)
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+       if err := cmd.Run(); err != nil {
+               errorf("%v", err)
+       }
+}
+
+func runOut(dir string, cmdargs ...interface{}) []byte {
+       cmdline := stringList(cmdargs...)
+       cmd := exec.Command(cmdline[0], cmdline[1:]...)
+       cmd.Dir = dir
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               os.Stderr.Write(out)
+               errorf("%v", err)
+               out = nil
+       }
+       return out
+}
+
+// envForDir returns a copy of the environment
+// suitable for running in the given directory.
+// The environment is the current process's environment
+// but with an updated $PWD, so that an os.Getwd in the
+// child will be faster.
+func envForDir(dir string) []string {
+       env := os.Environ()
+       // Internally we only use rooted paths, so dir is rooted.
+       // Even if dir is not rooted, no harm done.
+       return mergeEnvLists([]string{"PWD=" + dir}, env)
+}
+
+// mergeEnvLists merges the two environment lists such that
+// variables with the same name in "in" replace those in "out".
+func mergeEnvLists(in, out []string) []string {
+NextVar:
+       for _, inkv := range in {
+               k := strings.SplitAfterN(inkv, "=", 2)[0]
+               for i, outkv := range out {
+                       if strings.HasPrefix(outkv, k) {
+                               out[i] = inkv
+                               continue NextVar
+                       }
+               }
+               out = append(out, inkv)
+       }
+       return out
+}
+
+// matchPattern(pattern)(name) reports whether
+// name matches pattern.  Pattern is a limited glob
+// pattern in which '...' means 'any string' and there
+// is no other special syntax.
+func matchPattern(pattern string) func(name string) bool {
+       re := regexp.QuoteMeta(pattern)
+       re = strings.Replace(re, `\.\.\.`, `.*`, -1)
+       // Special case: foo/... matches foo too.
+       if strings.HasSuffix(re, `/.*`) {
+               re = re[:len(re)-len(`/.*`)] + `(/.*)?`
+       }
+       reg := regexp.MustCompile(`^` + re + `$`)
+       return func(name string) bool {
+               return reg.MatchString(name)
+       }
+}
+
+// hasPathPrefix reports whether the path s begins with the
+// elements in prefix.
+func hasPathPrefix(s, prefix string) bool {
+       switch {
+       default:
+               return false
+       case len(s) == len(prefix):
+               return s == prefix
+       case len(s) > len(prefix):
+               if prefix != "" && prefix[len(prefix)-1] == '/' {
+                       return strings.HasPrefix(s, prefix)
+               }
+               return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
+       }
+}
+
+// treeCanMatchPattern(pattern)(name) reports whether
+// name or children of name can possibly match pattern.
+// Pattern is the same limited glob accepted by matchPattern.
+func treeCanMatchPattern(pattern string) func(name string) bool {
+       wildCard := false
+       if i := strings.Index(pattern, "..."); i >= 0 {
+               wildCard = true
+               pattern = pattern[:i]
+       }
+       return func(name string) bool {
+               return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
+                       wildCard && strings.HasPrefix(name, pattern)
+       }
+}
+
+// allPackages returns all the packages that can be found
+// under the $GOPATH directories and $GOROOT matching pattern.
+// The pattern is either "all" (all packages), "std" (standard packages)
+// or a path including "...".
+func allPackages(pattern string) []string {
+       pkgs := matchPackages(pattern)
+       if len(pkgs) == 0 {
+               fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+       }
+       return pkgs
+}
+
+func matchPackages(pattern string) []string {
+       match := func(string) bool { return true }
+       treeCanMatch := func(string) bool { return true }
+       if pattern != "all" && pattern != "std" {
+               match = matchPattern(pattern)
+               treeCanMatch = treeCanMatchPattern(pattern)
+       }
+
+       have := map[string]bool{
+               "builtin": true, // ignore pseudo-package that exists only for documentation
+       }
+       if !buildContext.CgoEnabled {
+               have["runtime/cgo"] = true // ignore during walk
+       }
+       var pkgs []string
+
+       // Commands
+       cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
+       filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
+               if err != nil || !fi.IsDir() || path == cmd {
+                       return nil
+               }
+               name := path[len(cmd):]
+               if !treeCanMatch(name) {
+                       return filepath.SkipDir
+               }
+               // Commands are all in cmd/, not in subdirectories.
+               if strings.Contains(name, string(filepath.Separator)) {
+                       return filepath.SkipDir
+               }
+
+               // We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
+               name = "cmd/" + name
+               if have[name] {
+                       return nil
+               }
+               have[name] = true
+               if !match(name) {
+                       return nil
+               }
+               _, err = buildContext.ImportDir(path, 0)
+               if err != nil {
+                       if _, noGo := err.(*build.NoGoError); !noGo {
+                               log.Print(err)
+                       }
+                       return nil
+               }
+               pkgs = append(pkgs, name)
+               return nil
+       })
+
+       for _, src := range buildContext.SrcDirs() {
+               if pattern == "std" && src != gorootSrcPkg {
+                       continue
+               }
+               src = filepath.Clean(src) + string(filepath.Separator)
+               filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
+                       if err != nil || !fi.IsDir() || path == src {
+                               return nil
+                       }
+
+                       // Avoid .foo, _foo, and testdata directory trees.
+                       _, elem := filepath.Split(path)
+                       if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+                               return filepath.SkipDir
+                       }
+
+                       name := filepath.ToSlash(path[len(src):])
+                       if pattern == "std" && strings.Contains(name, ".") {
+                               return filepath.SkipDir
+                       }
+                       if !treeCanMatch(name) {
+                               return filepath.SkipDir
+                       }
+                       if have[name] {
+                               return nil
+                       }
+                       have[name] = true
+                       if !match(name) {
+                               return nil
+                       }
+                       _, err = buildContext.ImportDir(path, 0)
+                       if err != nil {
+                               if _, noGo := err.(*build.NoGoError); noGo {
+                                       return nil
+                               }
+                       }
+                       pkgs = append(pkgs, name)
+                       return nil
+               })
+       }
+       return pkgs
+}
+
+// allPackagesInFS is like allPackages but is passed a pattern
+// beginning ./ or ../, meaning it should scan the tree rooted
+// at the given directory.  There are ... in the pattern too.
+func allPackagesInFS(pattern string) []string {
+       pkgs := matchPackagesInFS(pattern)
+       if len(pkgs) == 0 {
+               fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+       }
+       return pkgs
+}
+
+func matchPackagesInFS(pattern string) []string {
+       // Find directory to begin the scan.
+       // Could be smarter but this one optimization
+       // is enough for now, since ... is usually at the
+       // end of a path.
+       i := strings.Index(pattern, "...")
+       dir, _ := path.Split(pattern[:i])
+
+       // pattern begins with ./ or ../.
+       // path.Clean will discard the ./ but not the ../.
+       // We need to preserve the ./ for pattern matching
+       // and in the returned import paths.
+       prefix := ""
+       if strings.HasPrefix(pattern, "./") {
+               prefix = "./"
+       }
+       match := matchPattern(pattern)
+
+       var pkgs []string
+       filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
+               if err != nil || !fi.IsDir() {
+                       return nil
+               }
+               if path == dir {
+                       // filepath.Walk starts at dir and recurses. For the recursive case,
+                       // the path is the result of filepath.Join, which calls filepath.Clean.
+                       // The initial case is not Cleaned, though, so we do this explicitly.
+                       //
+                       // This converts a path like "./io/" to "io". Without this step, running
+                       // "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io
+                       // package, because prepending the prefix "./" to the unclean path would
+                       // result in "././io", and match("././io") returns false.
+                       path = filepath.Clean(path)
+               }
+
+               // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
+               _, elem := filepath.Split(path)
+               dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
+               if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
+                       return filepath.SkipDir
+               }
+
+               name := prefix + filepath.ToSlash(path)
+               if !match(name) {
+                       return nil
+               }
+               if _, err = build.ImportDir(path, 0); err != nil {
+                       if _, noGo := err.(*build.NoGoError); !noGo {
+                               log.Print(err)
+                       }
+                       return nil
+               }
+               pkgs = append(pkgs, name)
+               return nil
+       })
+       return pkgs
+}
+
+// stringList's arguments should be a sequence of string or []string values.
+// stringList flattens them into a single []string.
+func stringList(args ...interface{}) []string {
+       var x []string
+       for _, arg := range args {
+               switch arg := arg.(type) {
+               case []string:
+                       x = append(x, arg...)
+               case string:
+                       x = append(x, arg)
+               default:
+                       panic("stringList: invalid argument")
+               }
+       }
+       return x
+}
+
+// toFold returns a string with the property that
+//     strings.EqualFold(s, t) iff toFold(s) == toFold(t)
+// This lets us test a large set of strings for fold-equivalent
+// duplicates without making a quadratic number of calls
+// to EqualFold. Note that strings.ToUpper and strings.ToLower
+// have the desired property in some corner cases.
+func toFold(s string) string {
+       // Fast path: all ASCII, no upper case.
+       // Most paths look like this already.
+       for i := 0; i < len(s); i++ {
+               c := s[i]
+               if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
+                       goto Slow
+               }
+       }
+       return s
+
+Slow:
+       var buf bytes.Buffer
+       for _, r := range s {
+               // SimpleFold(x) cycles to the next equivalent rune > x
+               // or wraps around to smaller values. Iterate until it wraps,
+               // and we've found the minimum value.
+               for {
+                       r0 := r
+                       r = unicode.SimpleFold(r0)
+                       if r <= r0 {
+                               break
+                       }
+               }
+               // Exception to allow fast path above: A-Z => a-z
+               if 'A' <= r && r <= 'Z' {
+                       r += 'a' - 'A'
+               }
+               buf.WriteRune(r)
+       }
+       return buf.String()
+}
+
+// foldDup reports a pair of strings from the list that are
+// equal according to strings.EqualFold.
+// It returns "", "" if there are no such strings.
+func foldDup(list []string) (string, string) {
+       clash := map[string]string{}
+       for _, s := range list {
+               fold := toFold(s)
+               if t := clash[fold]; t != "" {
+                       if s > t {
+                               s, t = t, s
+                       }
+                       return s, t
+               }
+               clash[fold] = s
+       }
+       return "", ""
+}
diff --git a/libgo/go/cmd/go/match_test.go b/libgo/go/cmd/go/match_test.go
new file mode 100644 (file)
index 0000000..38b9b11
--- /dev/null
@@ -0,0 +1,88 @@
+// 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 main
+
+import "testing"
+
+var matchPatternTests = []stringPairTest{
+       {"...", "foo", true},
+       {"net", "net", true},
+       {"net", "net/http", false},
+       {"net/http", "net", false},
+       {"net/http", "net/http", true},
+       {"net...", "netchan", true},
+       {"net...", "net", true},
+       {"net...", "net/http", true},
+       {"net...", "not/http", false},
+       {"net/...", "netchan", false},
+       {"net/...", "net", true},
+       {"net/...", "net/http", true},
+       {"net/...", "not/http", false},
+}
+
+func TestMatchPattern(t *testing.T) {
+       testStringPairs(t, "matchPattern", matchPatternTests, func(pattern, name string) bool {
+               return matchPattern(pattern)(name)
+       })
+}
+
+var treeCanMatchPatternTests = []stringPairTest{
+       {"...", "foo", true},
+       {"net", "net", true},
+       {"net", "net/http", false},
+       {"net/http", "net", true},
+       {"net/http", "net/http", true},
+       {"net...", "netchan", true},
+       {"net...", "net", true},
+       {"net...", "net/http", true},
+       {"net...", "not/http", false},
+       {"net/...", "netchan", false},
+       {"net/...", "net", true},
+       {"net/...", "net/http", true},
+       {"net/...", "not/http", false},
+       {"abc.../def", "abcxyz", true},
+       {"abc.../def", "xyxabc", false},
+       {"x/y/z/...", "x", true},
+       {"x/y/z/...", "x/y", true},
+       {"x/y/z/...", "x/y/z", true},
+       {"x/y/z/...", "x/y/z/w", true},
+       {"x/y/z", "x", true},
+       {"x/y/z", "x/y", true},
+       {"x/y/z", "x/y/z", true},
+       {"x/y/z", "x/y/z/w", false},
+       {"x/.../y/z", "x/a/b/c", true},
+       {"x/.../y/z", "y/x/a/b/c", false},
+}
+
+func TestChildrenCanMatchPattern(t *testing.T) {
+       testStringPairs(t, "treeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool {
+               return treeCanMatchPattern(pattern)(name)
+       })
+}
+
+var hasPathPrefixTests = []stringPairTest{
+       {"abc", "a", false},
+       {"a/bc", "a", true},
+       {"a", "a", true},
+       {"a/bc", "a/", true},
+}
+
+func TestHasPathPrefix(t *testing.T) {
+       testStringPairs(t, "hasPathPrefix", hasPathPrefixTests, hasPathPrefix)
+}
+
+type stringPairTest struct {
+       in1 string
+       in2 string
+       out bool
+}
+
+func testStringPairs(t *testing.T, name string, tests []stringPairTest, f func(string, string) bool) {
+       for _, tt := range tests {
+               if out := f(tt.in1, tt.in2); out != tt.out {
+                       t.Errorf("%s(%q, %q) = %v, want %v", name, tt.in1, tt.in2, out, tt.out)
+               }
+       }
+}
diff --git a/libgo/go/cmd/go/mkdoc.sh b/libgo/go/cmd/go/mkdoc.sh
new file mode 100644 (file)
index 0000000..12fd7ba
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+# 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.
+
+go install # So the next line will produce updated documentation.
+go help documentation > doc.go
+gofmt -w doc.go
+
diff --git a/libgo/go/cmd/go/pkg.go b/libgo/go/cmd/go/pkg.go
new file mode 100644 (file)
index 0000000..b700ad5
--- /dev/null
@@ -0,0 +1,856 @@
+// 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 (
+       "bytes"
+       "errors"
+       "fmt"
+       "go/build"
+       "go/scanner"
+       "go/token"
+       "os"
+       pathpkg "path"
+       "path/filepath"
+       "sort"
+       "strings"
+       "time"
+       "unicode"
+)
+
+// A Package describes a single package found in a directory.
+type Package struct {
+       // Note: These fields are part of the go command's public API.
+       // See list.go.  It is okay to add fields, but not to change or
+       // remove existing ones.  Keep in sync with list.go
+       Dir         string `json:",omitempty"` // directory containing package sources
+       ImportPath  string `json:",omitempty"` // import path of package in dir
+       Name        string `json:",omitempty"` // package name
+       Doc         string `json:",omitempty"` // package documentation string
+       Target      string `json:",omitempty"` // install path
+       Goroot      bool   `json:",omitempty"` // is this package found in the Go root?
+       Standard    bool   `json:",omitempty"` // is this package part of the standard Go library?
+       Stale       bool   `json:",omitempty"` // would 'go install' do anything for this package?
+       Root        string `json:",omitempty"` // Go root or Go path dir containing this package
+       ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
+
+       // Source files
+       GoFiles        []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+       CgoFiles       []string `json:",omitempty"` // .go sources files that import "C"
+       IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints
+       CFiles         []string `json:",omitempty"` // .c source files
+       CXXFiles       []string `json:",omitempty"` // .cc, .cpp and .cxx source files
+       MFiles         []string `json:",omitempty"` // .m source files
+       HFiles         []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files
+       SFiles         []string `json:",omitempty"` // .s source files
+       SwigFiles      []string `json:",omitempty"` // .swig files
+       SwigCXXFiles   []string `json:",omitempty"` // .swigcxx files
+       SysoFiles      []string `json:",omitempty"` // .syso system object files added to package
+
+       // Cgo directives
+       CgoCFLAGS    []string `json:",omitempty"` // cgo: flags for C compiler
+       CgoCPPFLAGS  []string `json:",omitempty"` // cgo: flags for C preprocessor
+       CgoCXXFLAGS  []string `json:",omitempty"` // cgo: flags for C++ compiler
+       CgoLDFLAGS   []string `json:",omitempty"` // cgo: flags for linker
+       CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names
+
+       // Dependency information
+       Imports []string `json:",omitempty"` // import paths used by this package
+       Deps    []string `json:",omitempty"` // all (recursively) imported dependencies
+
+       // Error information
+       Incomplete bool            `json:",omitempty"` // was there an error loading this package or dependencies?
+       Error      *PackageError   `json:",omitempty"` // error loading this package (not dependencies)
+       DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
+
+       // Test information
+       TestGoFiles  []string `json:",omitempty"` // _test.go files in package
+       TestImports  []string `json:",omitempty"` // imports from TestGoFiles
+       XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
+       XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
+
+       // Unexported fields are not part of the public API.
+       build        *build.Package
+       pkgdir       string // overrides build.PkgDir
+       imports      []*Package
+       deps         []*Package
+       gofiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+       sfiles       []string
+       allgofiles   []string             // gofiles + IgnoredGoFiles, absolute paths
+       target       string               // installed file for this package (may be executable)
+       fake         bool                 // synthesized package
+       forceBuild   bool                 // this package must be rebuilt
+       forceLibrary bool                 // this package is a library (even if named "main")
+       cmdline      bool                 // defined by files listed on command line
+       local        bool                 // imported via local path (./ or ../)
+       localPrefix  string               // interpret ./ and ../ imports relative to this prefix
+       exeName      string               // desired name for temporary executable
+       coverMode    string               // preprocess Go source files with the coverage tool in this mode
+       coverVars    map[string]*CoverVar // variables created by coverage analysis
+       omitDWARF    bool                 // tell linker not to write DWARF information
+}
+
+// CoverVar holds the name of the generated coverage variables targeting the named file.
+type CoverVar struct {
+       File string // local file name
+       Var  string // name of count struct
+}
+
+func (p *Package) copyBuild(pp *build.Package) {
+       p.build = pp
+
+       p.Dir = pp.Dir
+       p.ImportPath = pp.ImportPath
+       p.Name = pp.Name
+       p.Doc = pp.Doc
+       p.Root = pp.Root
+       p.ConflictDir = pp.ConflictDir
+       // TODO? Target
+       p.Goroot = pp.Goroot
+       p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".")
+       p.GoFiles = pp.GoFiles
+       p.CgoFiles = pp.CgoFiles
+       p.IgnoredGoFiles = pp.IgnoredGoFiles
+       p.CFiles = pp.CFiles
+       p.CXXFiles = pp.CXXFiles
+       p.MFiles = pp.MFiles
+       p.HFiles = pp.HFiles
+       p.SFiles = pp.SFiles
+       p.SwigFiles = pp.SwigFiles
+       p.SwigCXXFiles = pp.SwigCXXFiles
+       p.SysoFiles = pp.SysoFiles
+       p.CgoCFLAGS = pp.CgoCFLAGS
+       p.CgoCPPFLAGS = pp.CgoCPPFLAGS
+       p.CgoCXXFLAGS = pp.CgoCXXFLAGS
+       p.CgoLDFLAGS = pp.CgoLDFLAGS
+       p.CgoPkgConfig = pp.CgoPkgConfig
+       p.Imports = pp.Imports
+       p.TestGoFiles = pp.TestGoFiles
+       p.TestImports = pp.TestImports
+       p.XTestGoFiles = pp.XTestGoFiles
+       p.XTestImports = pp.XTestImports
+}
+
+// A PackageError describes an error loading information about a package.
+type PackageError struct {
+       ImportStack   []string // shortest path from package named on command line to this one
+       Pos           string   // position of error
+       Err           string   // the error itself
+       isImportCycle bool     // the error is an import cycle
+       hard          bool     // whether the error is soft or hard; soft errors are ignored in some places
+}
+
+func (p *PackageError) Error() string {
+       // Import cycles deserve special treatment.
+       if p.isImportCycle {
+               return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports "))
+       }
+       if p.Pos != "" {
+               // Omit import stack.  The full path to the file where the error
+               // is the most important thing.
+               return p.Pos + ": " + p.Err
+       }
+       if len(p.ImportStack) == 0 {
+               return p.Err
+       }
+       return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err
+}
+
+// An importStack is a stack of import paths.
+type importStack []string
+
+func (s *importStack) push(p string) {
+       *s = append(*s, p)
+}
+
+func (s *importStack) pop() {
+       *s = (*s)[0 : len(*s)-1]
+}
+
+func (s *importStack) copy() []string {
+       return append([]string{}, *s...)
+}
+
+// shorterThan returns true if sp is shorter than t.
+// We use this to record the shortest import sequence
+// that leads to a particular package.
+func (sp *importStack) shorterThan(t []string) bool {
+       s := *sp
+       if len(s) != len(t) {
+               return len(s) < len(t)
+       }
+       // If they are the same length, settle ties using string ordering.
+       for i := range s {
+               if s[i] != t[i] {
+                       return s[i] < t[i]
+               }
+       }
+       return false // they are equal
+}
+
+// packageCache is a lookup cache for loadPackage,
+// so that if we look up a package multiple times
+// we return the same pointer each time.
+var packageCache = map[string]*Package{}
+
+// reloadPackage is like loadPackage but makes sure
+// not to use the package cache.
+func reloadPackage(arg string, stk *importStack) *Package {
+       p := packageCache[arg]
+       if p != nil {
+               delete(packageCache, p.Dir)
+               delete(packageCache, p.ImportPath)
+       }
+       return loadPackage(arg, stk)
+}
+
+// dirToImportPath returns the pseudo-import path we use for a package
+// outside the Go path.  It begins with _/ and then contains the full path
+// to the directory.  If the package lives in c:\home\gopher\my\pkg then
+// the pseudo-import path is _/c_/home/gopher/my/pkg.
+// Using a pseudo-import path like this makes the ./ imports no longer
+// a special case, so that all the code to deal with ordinary imports works
+// automatically.
+func dirToImportPath(dir string) string {
+       return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir)))
+}
+
+func makeImportValid(r rune) rune {
+       // Should match Go spec, compilers, and ../../pkg/go/parser/parser.go:/isValidImport.
+       const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
+       if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
+               return '_'
+       }
+       return r
+}
+
+// loadImport scans the directory named by path, which must be an import path,
+// but possibly a local import path (an absolute file system path or one beginning
+// with ./ or ../).  A local relative path is interpreted relative to srcDir.
+// It returns a *Package describing the package found in that directory.
+func loadImport(path string, srcDir string, stk *importStack, importPos []token.Position) *Package {
+       stk.push(path)
+       defer stk.pop()
+
+       // Determine canonical identifier for this package.
+       // For a local import the identifier is the pseudo-import path
+       // we create from the full directory to the package.
+       // Otherwise it is the usual import path.
+       importPath := path
+       isLocal := build.IsLocalImport(path)
+       if isLocal {
+               importPath = dirToImportPath(filepath.Join(srcDir, path))
+       }
+       if p := packageCache[importPath]; p != nil {
+               return reusePackage(p, stk)
+       }
+
+       p := new(Package)
+       p.local = isLocal
+       p.ImportPath = importPath
+       packageCache[importPath] = p
+
+       // Load package.
+       // Import always returns bp != nil, even if an error occurs,
+       // in order to return partial information.
+       //
+       // TODO: After Go 1, decide when to pass build.AllowBinary here.
+       // See issue 3268 for mistakes to avoid.
+       bp, err := buildContext.Import(path, srcDir, 0)
+       bp.ImportPath = importPath
+       if gobin != "" {
+               bp.BinDir = gobin
+       }
+       p.load(stk, bp, err)
+       if p.Error != nil && len(importPos) > 0 {
+               pos := importPos[0]
+               pos.Filename = shortPath(pos.Filename)
+               p.Error.Pos = pos.String()
+       }
+
+       return p
+}
+
+// reusePackage reuses package p to satisfy the import at the top
+// of the import stack stk.  If this use causes an import loop,
+// reusePackage updates p's error information to record the loop.
+func reusePackage(p *Package, stk *importStack) *Package {
+       // We use p.imports==nil to detect a package that
+       // is in the midst of its own loadPackage call
+       // (all the recursion below happens before p.imports gets set).
+       if p.imports == nil {
+               if p.Error == nil {
+                       p.Error = &PackageError{
+                               ImportStack:   stk.copy(),
+                               Err:           "import cycle not allowed",
+                               isImportCycle: true,
+                       }
+               }
+               p.Incomplete = true
+       }
+       // Don't rewrite the import stack in the error if we have an import cycle.
+       // If we do, we'll lose the path that describes the cycle.
+       if p.Error != nil && !p.Error.isImportCycle && stk.shorterThan(p.Error.ImportStack) {
+               p.Error.ImportStack = stk.copy()
+       }
+       return p
+}
+
+type targetDir int
+
+const (
+       toRoot targetDir = iota // to bin dir inside package root (default)
+       toTool                  // GOROOT/pkg/tool
+       toBin                   // GOROOT/bin
+)
+
+// goTools is a map of Go program import path to install target directory.
+var goTools = map[string]targetDir{
+       "cmd/addr2line":                        toTool,
+       "cmd/api":                              toTool,
+       "cmd/cgo":                              toTool,
+       "cmd/fix":                              toTool,
+       "cmd/link":                             toTool,
+       "cmd/nm":                               toTool,
+       "cmd/objdump":                          toTool,
+       "cmd/pack":                             toTool,
+       "cmd/yacc":                             toTool,
+       "code.google.com/p/go.tools/cmd/cover": toTool,
+       "code.google.com/p/go.tools/cmd/godoc": toBin,
+       "code.google.com/p/go.tools/cmd/vet":   toTool,
+}
+
+// expandScanner expands a scanner.List error into all the errors in the list.
+// The default Error method only shows the first error.
+func expandScanner(err error) error {
+       // Look for parser errors.
+       if err, ok := err.(scanner.ErrorList); ok {
+               // Prepare error with \n before each message.
+               // When printed in something like context: %v
+               // this will put the leading file positions each on
+               // its own line.  It will also show all the errors
+               // instead of just the first, as err.Error does.
+               var buf bytes.Buffer
+               for _, e := range err {
+                       e.Pos.Filename = shortPath(e.Pos.Filename)
+                       buf.WriteString("\n")
+                       buf.WriteString(e.Error())
+               }
+               return errors.New(buf.String())
+       }
+       return err
+}
+
+var raceExclude = map[string]bool{
+       "runtime/race": true,
+       "runtime/cgo":  true,
+       "cmd/cgo":      true,
+       "syscall":      true,
+       "errors":       true,
+}
+
+var cgoExclude = map[string]bool{
+       "runtime/cgo": true,
+}
+
+var cgoSyscallExclude = map[string]bool{
+       "runtime/cgo":  true,
+       "runtime/race": true,
+}
+
+// load populates p using information from bp, err, which should
+// be the result of calling build.Context.Import.
+func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package {
+       p.copyBuild(bp)
+
+       // The localPrefix is the path we interpret ./ imports relative to.
+       // Synthesized main packages sometimes override this.
+       p.localPrefix = dirToImportPath(p.Dir)
+
+       if err != nil {
+               p.Incomplete = true
+               err = expandScanner(err)
+               p.Error = &PackageError{
+                       ImportStack: stk.copy(),
+                       Err:         err.Error(),
+               }
+               return p
+       }
+
+       if p.Name == "main" {
+               _, elem := filepath.Split(p.Dir)
+               full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem
+               if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH {
+                       // Install cross-compiled binaries to subdirectories of bin.
+                       elem = full
+               }
+               if p.build.BinDir != gobin && goTools[p.ImportPath] == toBin {
+                       // Override BinDir.
+                       // This is from a subrepo but installs to $GOROOT/bin
+                       // by default anyway (like godoc).
+                       p.target = filepath.Join(gorootBin, elem)
+               } else if p.build.BinDir != "" {
+                       // Install to GOBIN or bin of GOPATH entry.
+                       p.target = filepath.Join(p.build.BinDir, elem)
+               }
+               if goTools[p.ImportPath] == toTool {
+                       // This is for 'go tool'.
+                       // Override all the usual logic and force it into the tool directory.
+                       p.target = filepath.Join(gorootPkg, "tool", full)
+               }
+               if p.target != "" && buildContext.GOOS == "windows" {
+                       p.target += ".exe"
+               }
+       } else if p.local {
+               // Local import turned into absolute path.
+               // No permanent install target.
+               p.target = ""
+       } else {
+               p.target = p.build.PkgObj
+       }
+
+       importPaths := p.Imports
+       // Packages that use cgo import runtime/cgo implicitly.
+       // Packages that use cgo also import syscall implicitly,
+       // to wrap errno.
+       // Exclude certain packages to avoid circular dependencies.
+       if len(p.CgoFiles) > 0 && (!p.Standard || !cgoExclude[p.ImportPath]) {
+               importPaths = append(importPaths, "runtime/cgo")
+       }
+       if len(p.CgoFiles) > 0 && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
+               importPaths = append(importPaths, "syscall")
+       }
+       // Everything depends on runtime, except runtime and unsafe.
+       if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
+               importPaths = append(importPaths, "runtime")
+               // When race detection enabled everything depends on runtime/race.
+               // Exclude certain packages to avoid circular dependencies.
+               if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
+                       importPaths = append(importPaths, "runtime/race")
+               }
+       }
+
+       // Build list of full paths to all Go files in the package,
+       // for use by commands like go fmt.
+       p.gofiles = stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
+       for i := range p.gofiles {
+               p.gofiles[i] = filepath.Join(p.Dir, p.gofiles[i])
+       }
+       sort.Strings(p.gofiles)
+
+       p.sfiles = stringList(p.SFiles)
+       for i := range p.sfiles {
+               p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i])
+       }
+       sort.Strings(p.sfiles)
+
+       p.allgofiles = stringList(p.IgnoredGoFiles)
+       for i := range p.allgofiles {
+               p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
+       }
+       p.allgofiles = append(p.allgofiles, p.gofiles...)
+       sort.Strings(p.allgofiles)
+
+       // Check for case-insensitive collision of input files.
+       // To avoid problems on case-insensitive files, we reject any package
+       // where two different input files have equal names under a case-insensitive
+       // comparison.
+       f1, f2 := foldDup(stringList(
+               p.GoFiles,
+               p.CgoFiles,
+               p.IgnoredGoFiles,
+               p.CFiles,
+               p.CXXFiles,
+               p.MFiles,
+               p.HFiles,
+               p.SFiles,
+               p.SysoFiles,
+               p.SwigFiles,
+               p.SwigCXXFiles,
+               p.TestGoFiles,
+               p.XTestGoFiles,
+       ))
+       if f1 != "" {
+               p.Error = &PackageError{
+                       ImportStack: stk.copy(),
+                       Err:         fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2),
+               }
+               return p
+       }
+
+       // Build list of imported packages and full dependency list.
+       imports := make([]*Package, 0, len(p.Imports))
+       deps := make(map[string]bool)
+       for i, path := range importPaths {
+               if path == "C" {
+                       continue
+               }
+               p1 := loadImport(path, p.Dir, stk, p.build.ImportPos[path])
+               if !reqPkgSrc && p1.Root == "" {
+                       continue
+               }
+               if p1.local {
+                       if !p.local && p.Error == nil {
+                               p.Error = &PackageError{
+                                       ImportStack: stk.copy(),
+                                       Err:         fmt.Sprintf("local import %q in non-local package", path),
+                               }
+                               pos := p.build.ImportPos[path]
+                               if len(pos) > 0 {
+                                       p.Error.Pos = pos[0].String()
+                               }
+                       }
+                       path = p1.ImportPath
+                       importPaths[i] = path
+               }
+               deps[path] = true
+               imports = append(imports, p1)
+               for _, dep := range p1.Deps {
+                       deps[dep] = true
+               }
+               if p1.Incomplete {
+                       p.Incomplete = true
+               }
+       }
+       p.imports = imports
+
+       p.Deps = make([]string, 0, len(deps))
+       for dep := range deps {
+               p.Deps = append(p.Deps, dep)
+       }
+       sort.Strings(p.Deps)
+       for _, dep := range p.Deps {
+               p1 := packageCache[dep]
+               if p1 == nil {
+                       panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
+               }
+               p.deps = append(p.deps, p1)
+               if p1.Error != nil {
+                       p.DepsErrors = append(p.DepsErrors, p1.Error)
+               }
+       }
+
+       // unsafe is a fake package.
+       if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
+               p.target = ""
+       }
+       p.Target = p.target
+
+       // In the absence of errors lower in the dependency tree,
+       // check for case-insensitive collisions of import paths.
+       if len(p.DepsErrors) == 0 {
+               dep1, dep2 := foldDup(p.Deps)
+               if dep1 != "" {
+                       p.Error = &PackageError{
+                               ImportStack: stk.copy(),
+                               Err:         fmt.Sprintf("case-insensitive import collision: %q and %q", dep1, dep2),
+                       }
+                       return p
+               }
+       }
+
+       return p
+}
+
+// usesSwig reports whether the package needs to run SWIG.
+func (p *Package) usesSwig() bool {
+       return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
+}
+
+// usesCgo reports whether the package needs to run cgo
+func (p *Package) usesCgo() bool {
+       return len(p.CgoFiles) > 0
+}
+
+// packageList returns the list of packages in the dag rooted at roots
+// as visited in a depth-first post-order traversal.
+func packageList(roots []*Package) []*Package {
+       seen := map[*Package]bool{}
+       all := []*Package{}
+       var walk func(*Package)
+       walk = func(p *Package) {
+               if seen[p] {
+                       return
+               }
+               seen[p] = true
+               for _, p1 := range p.imports {
+                       walk(p1)
+               }
+               all = append(all, p)
+       }
+       for _, root := range roots {
+               walk(root)
+       }
+       return all
+}
+
+// computeStale computes the Stale flag in the package dag that starts
+// at the named pkgs (command-line arguments).
+func computeStale(pkgs ...*Package) {
+       topRoot := map[string]bool{}
+       for _, p := range pkgs {
+               topRoot[p.Root] = true
+       }
+
+       for _, p := range packageList(pkgs) {
+               p.Stale = isStale(p, topRoot)
+       }
+}
+
+// isStale reports whether package p needs to be rebuilt.
+func isStale(p *Package, topRoot map[string]bool) bool {
+       if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
+               // fake, builtin package
+               return false
+       }
+       if p.Error != nil {
+               return true
+       }
+
+       // A package without Go sources means we only found
+       // the installed .a file.  Since we don't know how to rebuild
+       // it, it can't be stale, even if -a is set.  This enables binary-only
+       // distributions of Go packages, although such binaries are
+       // only useful with the specific version of the toolchain that
+       // created them.
+       if len(p.gofiles) == 0 && !p.usesSwig() {
+               return false
+       }
+
+       if buildA || p.target == "" || p.Stale {
+               return true
+       }
+
+       // Package is stale if completely unbuilt.
+       var built time.Time
+       if fi, err := os.Stat(p.target); err == nil {
+               built = fi.ModTime()
+       }
+       if built.IsZero() {
+               return true
+       }
+
+       olderThan := func(file string) bool {
+               fi, err := os.Stat(file)
+               return err != nil || fi.ModTime().After(built)
+       }
+
+       // Package is stale if a dependency is, or if a dependency is newer.
+       for _, p1 := range p.deps {
+               if p1.Stale || p1.target != "" && olderThan(p1.target) {
+                       return true
+               }
+       }
+
+       // As a courtesy to developers installing new versions of the compiler
+       // frequently, define that packages are stale if they are
+       // older than the compiler, and commands if they are older than
+       // the linker.  This heuristic will not work if the binaries are
+       // back-dated, as some binary distributions may do, but it does handle
+       // a very common case.
+       // See issue 3036.
+       // Assume code in $GOROOT is up to date, since it may not be writeable.
+       // See issue 4106.
+       if p.Root != goroot {
+               if olderThan(buildToolchain.compiler()) {
+                       return true
+               }
+               if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
+                       return true
+               }
+       }
+
+       // Have installed copy, probably built using current compilers,
+       // and built after its imported packages.  The only reason now
+       // that we'd have to rebuild it is if the sources were newer than
+       // the package.   If a package p is not in the same tree as any
+       // package named on the command-line, assume it is up-to-date
+       // no matter what the modification times on the source files indicate.
+       // This avoids rebuilding $GOROOT packages when people are
+       // working outside the Go root, and it effectively makes each tree
+       // listed in $GOPATH a separate compilation world.
+       // See issue 3149.
+       if p.Root != "" && !topRoot[p.Root] {
+               return false
+       }
+
+       srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
+       for _, src := range srcs {
+               if olderThan(filepath.Join(p.Dir, src)) {
+                       return true
+               }
+       }
+
+       return false
+}
+
+var cwd, _ = os.Getwd()
+
+var cmdCache = map[string]*Package{}
+
+// loadPackage is like loadImport but is used for command-line arguments,
+// not for paths found in import statements.  In addition to ordinary import paths,
+// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
+// in the Go command directory, as well as paths to those directories.
+func loadPackage(arg string, stk *importStack) *Package {
+       if build.IsLocalImport(arg) {
+               dir := arg
+               if !filepath.IsAbs(dir) {
+                       if abs, err := filepath.Abs(dir); err == nil {
+                               // interpret relative to current directory
+                               dir = abs
+                       }
+               }
+               if sub, ok := hasSubdir(gorootSrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") {
+                       arg = sub
+               }
+       }
+       if strings.HasPrefix(arg, "cmd/") {
+               if p := cmdCache[arg]; p != nil {
+                       return p
+               }
+               stk.push(arg)
+               defer stk.pop()
+
+               if strings.Contains(arg[4:], "/") {
+                       p := &Package{
+                               Error: &PackageError{
+                                       ImportStack: stk.copy(),
+                                       Err:         fmt.Sprintf("invalid import path: cmd/... is reserved for Go commands"),
+                                       hard:        true,
+                               },
+                       }
+                       return p
+               }
+
+               bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
+               bp.ImportPath = arg
+               bp.Goroot = true
+               bp.BinDir = gorootBin
+               if gobin != "" {
+                       bp.BinDir = gobin
+               }
+               bp.Root = goroot
+               bp.SrcRoot = gorootSrc
+               p := new(Package)
+               cmdCache[arg] = p
+               p.load(stk, bp, err)
+               if p.Error == nil && p.Name != "main" {
+                       p.Error = &PackageError{
+                               ImportStack: stk.copy(),
+                               Err:         fmt.Sprintf("expected package main but found package %s in %s", p.Name, p.Dir),
+                       }
+               }
+               return p
+       }
+
+       // Wasn't a command; must be a package.
+       // If it is a local import path but names a standard package,
+       // we treat it as if the user specified the standard package.
+       // This lets you run go test ./ioutil in package io and be
+       // referring to io/ioutil rather than a hypothetical import of
+       // "./ioutil".
+       if build.IsLocalImport(arg) {
+               bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+               if bp.ImportPath != "" && bp.ImportPath != "." {
+                       arg = bp.ImportPath
+               }
+       }
+
+       return loadImport(arg, cwd, stk, nil)
+}
+
+// packages returns the packages named by the
+// command line arguments 'args'.  If a named package
+// cannot be loaded at all (for example, if the directory does not exist),
+// then packages prints an error and does not include that
+// package in the results.  However, if errors occur trying
+// to load dependencies of a named package, the named
+// package is still returned, with p.Incomplete = true
+// and details in p.DepsErrors.
+func packages(args []string) []*Package {
+       var pkgs []*Package
+       for _, pkg := range packagesAndErrors(args) {
+               if pkg.Error != nil {
+                       errorf("can't load package: %s", pkg.Error)
+                       continue
+               }
+               pkgs = append(pkgs, pkg)
+       }
+       return pkgs
+}
+
+// packagesAndErrors is like 'packages' but returns a
+// *Package for every argument, even the ones that
+// cannot be loaded at all.
+// The packages that fail to load will have p.Error != nil.
+func packagesAndErrors(args []string) []*Package {
+       if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
+               return []*Package{goFilesPackage(args)}
+       }
+
+       args = importPaths(args)
+       var pkgs []*Package
+       var stk importStack
+       var set = make(map[string]bool)
+
+       for _, arg := range args {
+               if !set[arg] {
+                       pkgs = append(pkgs, loadPackage(arg, &stk))
+                       set[arg] = true
+               }
+       }
+       computeStale(pkgs...)
+
+       return pkgs
+}
+
+// packagesForBuild is like 'packages' but fails if any of
+// the packages or their dependencies have errors
+// (cannot be built).
+func packagesForBuild(args []string) []*Package {
+       pkgs := packagesAndErrors(args)
+       printed := map[*PackageError]bool{}
+       for _, pkg := range pkgs {
+               if pkg.Error != nil {
+                       errorf("can't load package: %s", pkg.Error)
+               }
+               for _, err := range pkg.DepsErrors {
+                       // Since these are errors in dependencies,
+                       // the same error might show up multiple times,
+                       // once in each package that depends on it.
+                       // Only print each once.
+                       if !printed[err] {
+                               printed[err] = true
+                               errorf("%s", err)
+                       }
+               }
+       }
+       exitIfErrors()
+       return pkgs
+}
+
+// hasSubdir reports whether dir is a subdirectory of
+// (possibly multiple levels below) root.
+// If so, it sets rel to the path fragment that must be
+// appended to root to reach dir.
+func hasSubdir(root, dir string) (rel string, ok bool) {
+       if p, err := filepath.EvalSymlinks(root); err == nil {
+               root = p
+       }
+       if p, err := filepath.EvalSymlinks(dir); err == nil {
+               dir = p
+       }
+       const sep = string(filepath.Separator)
+       root = filepath.Clean(root)
+       if !strings.HasSuffix(root, sep) {
+               root += sep
+       }
+       dir = filepath.Clean(dir)
+       if !strings.HasPrefix(dir, root) {
+               return "", false
+       }
+       return filepath.ToSlash(dir[len(root):]), true
+}
diff --git a/libgo/go/cmd/go/pkg_test.go b/libgo/go/cmd/go/pkg_test.go
new file mode 100644 (file)
index 0000000..06b9f0a
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright 2014 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 (
+       "reflect"
+       "strings"
+       "testing"
+)
+
+var foldDupTests = []struct {
+       list   []string
+       f1, f2 string
+}{
+       {stringList("math/rand", "math/big"), "", ""},
+       {stringList("math", "strings"), "", ""},
+       {stringList("strings"), "", ""},
+       {stringList("strings", "strings"), "strings", "strings"},
+       {stringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"},
+}
+
+func TestFoldDup(t *testing.T) {
+       for _, tt := range foldDupTests {
+               f1, f2 := foldDup(tt.list)
+               if f1 != tt.f1 || f2 != tt.f2 {
+                       t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2)
+               }
+       }
+}
+
+var parseMetaGoImportsTests = []struct {
+       in  string
+       out []metaImport
+}{
+       {
+               `<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">`,
+               []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+       },
+       {
+               `<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
+               <meta name="go-import" content="baz/quux git http://github.com/rsc/baz/quux">`,
+               []metaImport{
+                       {"foo/bar", "git", "https://github.com/rsc/foo/bar"},
+                       {"baz/quux", "git", "http://github.com/rsc/baz/quux"},
+               },
+       },
+       {
+               `<head>
+               <meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
+               </head>`,
+               []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+       },
+       {
+               `<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
+               <body>`,
+               []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+       },
+}
+
+func TestParseMetaGoImports(t *testing.T) {
+       for i, tt := range parseMetaGoImportsTests {
+               out, err := parseMetaGoImports(strings.NewReader(tt.in))
+               if err != nil {
+                       t.Errorf("test#%d: %v", i, err)
+                       continue
+               }
+               if !reflect.DeepEqual(out, tt.out) {
+                       t.Errorf("test#%d:\n\thave %q\n\twant %q", i, out, tt.out)
+               }
+       }
+}
diff --git a/libgo/go/cmd/go/run.go b/libgo/go/cmd/go/run.go
new file mode 100644 (file)
index 0000000..ef8aa95
--- /dev/null
@@ -0,0 +1,143 @@
+// 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 (
+       "fmt"
+       "os"
+       "os/exec"
+       "runtime"
+       "strings"
+)
+
+var execCmd []string // -exec flag, for run and test
+
+func findExecCmd() []string {
+       if execCmd != nil {
+               return execCmd
+       }
+       execCmd = []string{} // avoid work the second time
+       if goos == runtime.GOOS && goarch == runtime.GOARCH {
+               return execCmd
+       }
+       path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch))
+       if err == nil {
+               execCmd = []string{path}
+       }
+       return execCmd
+}
+
+var cmdRun = &Command{
+       UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
+       Short:     "compile and run Go program",
+       Long: `
+Run compiles and runs the main package comprising the named Go source files.
+A Go source file is defined to be a file ending in a literal ".go" suffix.
+
+By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
+If the -exec flag is given, 'go run' invokes the binary using xprog: 'xprog a.out arguments...'.
+If the -exec flag is not given, GOOS or GOARCH is different from the system
+default, and a program named go_$GOOS_$GOARCH_exec can be found
+on the current search path, 'go run' invokes the binary using that program,
+for example 'go_nacl_386_exec a.out arguments...'. This allows execution of
+cross-compiled programs when a simulator or other execution method is
+available.
+
+For more about build flags, see 'go help build'.
+
+See also: go build.
+       `,
+}
+
+func init() {
+       cmdRun.Run = runRun // break init loop
+
+       addBuildFlags(cmdRun)
+       cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "")
+}
+
+func printStderr(args ...interface{}) (int, error) {
+       return fmt.Fprint(os.Stderr, args...)
+}
+
+func runRun(cmd *Command, args []string) {
+       raceInit()
+       var b builder
+       b.init()
+       b.print = printStderr
+       i := 0
+       for i < len(args) && strings.HasSuffix(args[i], ".go") {
+               i++
+       }
+       files, cmdArgs := args[:i], args[i:]
+       if len(files) == 0 {
+               fatalf("go run: no go files listed")
+       }
+       for _, file := range files {
+               if strings.HasSuffix(file, "_test.go") {
+                       // goFilesPackage is going to assign this to TestGoFiles.
+                       // Reject since it won't be part of the build.
+                       fatalf("go run: cannot run *_test.go files (%s)", file)
+               }
+       }
+       p := goFilesPackage(files)
+       if p.Error != nil {
+               fatalf("%s", p.Error)
+       }
+       p.omitDWARF = true
+       for _, err := range p.DepsErrors {
+               errorf("%s", err)
+       }
+       exitIfErrors()
+       if p.Name != "main" {
+               fatalf("go run: cannot run non-main package")
+       }
+       p.target = "" // must build - not up to date
+       var src string
+       if len(p.GoFiles) > 0 {
+               src = p.GoFiles[0]
+       } else if len(p.CgoFiles) > 0 {
+               src = p.CgoFiles[0]
+       } else {
+               // this case could only happen if the provided source uses cgo
+               // while cgo is disabled.
+               hint := ""
+               if !buildContext.CgoEnabled {
+                       hint = " (cgo is disabled)"
+               }
+               fatalf("go run: no suitable source files%s", hint)
+       }
+       p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file
+       a1 := b.action(modeBuild, modeBuild, p)
+       a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
+       b.do(a)
+}
+
+// runProgram is the action for running a binary that has already
+// been compiled.  We ignore exit status.
+func (b *builder) runProgram(a *action) error {
+       cmdline := stringList(findExecCmd(), a.deps[0].target, a.args)
+       if buildN || buildX {
+               b.showcmd("", "%s", strings.Join(cmdline, " "))
+               if buildN {
+                       return nil
+               }
+       }
+
+       runStdin(cmdline)
+       return nil
+}
+
+// runStdin is like run, but connects Stdin.
+func runStdin(cmdline []string) {
+       cmd := exec.Command(cmdline[0], cmdline[1:]...)
+       cmd.Stdin = os.Stdin
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+       startSigHandlers()
+       if err := cmd.Run(); err != nil {
+               errorf("%v", err)
+       }
+}
diff --git a/libgo/go/cmd/go/script b/libgo/go/cmd/go/script
new file mode 100644 (file)
index 0000000..340a7e8
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+x() {
+       echo '--- ' "$@"
+       "$@"
+       echo '---'
+       echo
+}
+
+x go help
+x go help build
+x go help clean
+x go help install
+x go help fix
+x go help fmt
+x go help get
+x go help list
+x go help test
+x go help version
+x go help vet
+x go help gopath
+x go help importpath
+x go help remote
diff --git a/libgo/go/cmd/go/script.txt b/libgo/go/cmd/go/script.txt
new file mode 100644 (file)
index 0000000..a672146
--- /dev/null
@@ -0,0 +1,352 @@
+---  go help
+usage: go command [arguments]
+
+go manages Go source code.
+
+The commands are:
+
+    build       compile and install packages and dependencies
+    clean       remove intermediate objects
+    fix         run gofix on packages
+    fmt         run gofmt -w on packages
+    get         download and install packages and dependencies
+    install     install packages and dependencies
+    list        list packages
+    test        test packages
+    version     print Go version
+    vet         run govet on packages
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+
+    gopath      GOPATH environment variable
+    importpath  description of import paths
+    remote      remote import path syntax
+
+Use "go help [topic]" for more information about that topic.
+
+---
+
+---  go help build
+usage: go build [-n] [-v] [importpath...]
+
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+The -n flag prints the commands but does not run them.
+The -v flag prints the commands.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go install, go get, go clean.
+---
+
+---  go help clean
+usage: go clean [-nuke] [importpath...]
+
+Clean removes intermediate object files generated during
+the compilation of the packages named by the import paths,
+but by default it does not remove the installed package binaries.
+
+The -nuke flag causes clean to remove the installed package binaries too.
+
+TODO: Clean does not clean dependencies of the packages.
+
+For more about import paths, see 'go help importpath'.
+---
+
+---  go help install
+usage: go install [-n] [-v] [importpath...]
+
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+The -n flag prints the commands but does not run them.
+The -v flag prints the commands.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go get, go clean.
+---
+
+---  go help fix
+usage: go fix [importpath...]
+
+Fix runs the gofix command on the packages named by the import paths.
+
+For more about gofix, see 'godoc gofix'.
+For more about import paths, see 'go help importpath'.
+
+To run gofix with specific options, run gofix itself.
+
+See also: go fmt, go vet.
+---
+
+---  go help fmt
+usage: go fmt [importpath...]
+
+Fmt runs the command 'gofmt -w' on the packages named by the import paths.
+
+For more about gofmt, see 'godoc gofmt'.
+For more about import paths, see 'go help importpath'.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go fix, go vet.
+---
+
+---  go help get
+usage: go get [importpath...]
+
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+After downloading the code, 'go get' looks for a tag beginning
+with "go." that corresponds to the local Go version.
+For Go "release.r58" it looks for a tag named "go.r58".
+For "weekly.2011-06-03" it looks for "go.weekly.2011-06-03".
+If the specific "go.X" tag is not found, it uses the latest earlier
+version it can find.  Otherwise, it uses the default version for
+the version control system: HEAD for git, tip for Mercurial,
+and so on.
+
+TODO: Explain versions better.
+
+For more about import paths, see 'go help importpath'.
+
+For more about how 'go get' finds source code to
+download, see 'go help remote'.
+
+See also: go build, go install, go clean.
+---
+
+---  go help list
+usage: go list [-f format] [-json] [importpath...]
+
+List lists the packages named by the import paths.
+
+The default output shows the package name and file system location:
+
+    books /home/you/src/google-api-go-client.googlecode.com/hg/books/v1
+    oauth /home/you/src/goauth2.googlecode.com/hg/oauth
+    sqlite /home/you/src/gosqlite.googlecode.com/hg/sqlite
+
+The -f flag specifies an alternate format for the list,
+using the syntax of package template.  The default output
+is equivalent to -f '{{.Name}} {{.Dir}}'  The struct
+being passed to the template is:
+
+    type Package struct {
+        Name string         // package name
+        Doc string          // package documentation string
+        GoFiles []string    // names of Go source files in package
+        ImportPath string   // import path denoting package
+        Imports []string    // import paths used by this package
+        Deps []string       // all (recursively) imported dependencies
+        Dir string          // directory containing package sources
+        Version string      // version of installed package
+    }
+
+The -json flag causes the package data to be printed in JSON format.
+
+For more about import paths, see 'go help importpath'.
+---
+
+---  go help test
+usage: go test [importpath...]
+
+Test runs gotest to test the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+       test archive/tar
+       FAIL archive/zip
+       test compress/gzip
+       ...
+
+followed by gotest output for each failed package.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go compile, go vet.
+---
+
+---  go help version
+usage: go version
+
+Version prints the Go version, as reported by runtime.Version.
+---
+
+---  go help vet
+usage: go vet [importpath...]
+
+Vet runs the govet command on the packages named by the import paths.
+
+For more about govet, see 'godoc govet'.
+For more about import paths, see 'go help importpath'.
+
+To run govet with specific options, run govet itself.
+
+See also: go fmt, go fix.
+---
+
+---  go help gopath
+The GOPATH environment variable lists places to look for Go code.
+On Unix, the value is a colon-separated string.
+On Windows, the value is a semicolon-separated string.
+On Plan 9, the value is a list.
+
+GOPATH must be set to build and install packages outside the
+standard Go tree.
+
+Each directory listed in GOPATH must have a prescribed structure:
+
+The src/ directory holds source code.  The path below 'src'
+determines the import path or executable name.
+
+The pkg/ directory holds installed package objects.
+As in the Go tree, each target operating system and
+architecture pair has its own subdirectory of pkg
+(pkg/GOOS_GOARCH).
+
+If DIR is a directory listed in the GOPATH, a package with
+source in DIR/src/foo/bar can be imported as "foo/bar" and
+has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
+
+The bin/ directory holds compiled commands.
+Each command is named for its source directory, but only
+the final element, not the entire path.  That is, the
+command with source in DIR/src/foo/quux is installed into
+DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.
+
+Here's an example directory layout:
+
+    GOPATH=/home/user/gocode
+
+    /home/user/gocode/
+        src/
+            foo/
+                bar/               (go code in package bar)
+                    x.go
+                quux/              (go code in package main)
+                    y.go
+        bin/
+            quux                   (installed command)
+               pkg/
+                   linux_amd64/
+                       foo/
+                           bar.a          (installed package object)
+
+Go searches each directory listed in GOPATH to find source code,
+but new packages are always downloaded into the first directory 
+in the list.
+---
+
+---  go help importpath
+Many commands apply to a set of packages named by import paths:
+
+       go action [importpath...]
+
+An import path that is a rooted path or that begins with
+a . or .. element is interpreted as a file system path and
+denotes the package in that directory.
+
+Otherwise, the import path P denotes the package found in
+the directory DIR/src/P for some DIR listed in the GOPATH
+environment variable (see 'go help gopath'). 
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+The special import path "all" expands to all package directories
+found in all the GOPATH trees.  For example, 'go list all' 
+lists all the packages on the local system.
+
+An import path can also name a package to be downloaded from
+a remote repository.  Run 'go help remote' for details.
+
+Every package in a program must have a unique import path.
+By convention, this is arranged by starting each path with a
+unique prefix that belongs to you.  For example, paths used
+internally at Google all begin with 'google', and paths
+denoting remote repositories begin with the path to the code,
+such as 'project.googlecode.com/'.
+---
+
+---  go help remote
+An import path (see 'go help importpath') denotes a package
+stored in the local file system.  Certain import paths also
+describe how to obtain the source code for the package using
+a revision control system.
+
+A few common code hosting sites have special syntax:
+
+       BitBucket (Mercurial)
+
+               import "bitbucket.org/user/project"
+               import "bitbucket.org/user/project/sub/directory"
+
+       GitHub (Git)
+
+               import "github.com/user/project"
+               import "github.com/user/project/sub/directory"
+
+       Google Code Project Hosting (Git, Mercurial, Subversion)
+
+               import "project.googlecode.com/git"
+               import "project.googlecode.com/git/sub/directory"
+
+               import "project.googlecode.com/hg"
+               import "project.googlecode.com/hg/sub/directory"
+
+               import "project.googlecode.com/svn/trunk"
+               import "project.googlecode.com/svn/trunk/sub/directory"
+
+       Launchpad (Bazaar)
+
+               import "launchpad.net/project"
+               import "launchpad.net/project/series"
+               import "launchpad.net/project/series/sub/directory"
+
+               import "launchpad.net/~user/project/branch"
+               import "launchpad.net/~user/project/branch/sub/directory"
+
+For code hosted on other servers, an import path of the form
+
+       repository.vcs/path
+
+specifies the given repository, with or without the .vcs suffix,
+using the named version control system, and then the path inside
+that repository.  The supported version control systems are:
+
+       Bazaar      .bzr
+       Git         .git
+       Mercurial   .hg
+       Subversion  .svn
+
+For example,
+
+       import "example.org/user/foo.hg"
+
+denotes the root directory of the Mercurial repository at
+example.org/user/foo or foo.hg, and
+
+       import "example.org/repo.git/foo/bar"
+
+denotes the foo/bar directory of the Git repository at
+example.com/repo or repo.git.
+
+When a version control system supports multiple protocols,
+each is tried in turn when downloading.  For example, a Git
+download tries git://, then https://, then http://.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (see 'go help gopath').
+
+The go command attempts to download the version of the
+package appropriate for the Go release being used.
+Run 'go help install' for more.
+---
+
diff --git a/libgo/go/cmd/go/signal.go b/libgo/go/cmd/go/signal.go
new file mode 100644 (file)
index 0000000..e8ba0d3
--- /dev/null
@@ -0,0 +1,31 @@
+// 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 main
+
+import (
+       "os"
+       "os/signal"
+       "sync"
+)
+
+// interrupted is closed, if go process is interrupted.
+var interrupted = make(chan struct{})
+
+// processSignals setups signal handler.
+func processSignals() {
+       sig := make(chan os.Signal)
+       signal.Notify(sig, signalsToIgnore...)
+       go func() {
+               <-sig
+               close(interrupted)
+       }()
+}
+
+var onceProcessSignals sync.Once
+
+// startSigHandlers start signal handlers.
+func startSigHandlers() {
+       onceProcessSignals.Do(processSignals)
+}
diff --git a/libgo/go/cmd/go/signal_notunix.go b/libgo/go/cmd/go/signal_notunix.go
new file mode 100644 (file)
index 0000000..29aa9d8
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+// +build plan9 windows
+
+package main
+
+import (
+       "os"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt}
+
+// signalTrace is the signal to send to make a Go program
+// crash with a stack trace.
+var signalTrace os.Signal = nil
diff --git a/libgo/go/cmd/go/signal_unix.go b/libgo/go/cmd/go/signal_unix.go
new file mode 100644 (file)
index 0000000..e86cd46
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package main
+
+import (
+       "os"
+       "syscall"
+)
+
+var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT}
+
+// signalTrace is the signal to send to make a Go program
+// crash with a stack trace.
+var signalTrace os.Signal = syscall.SIGQUIT
diff --git a/libgo/go/cmd/go/tag_test.go b/libgo/go/cmd/go/tag_test.go
new file mode 100644 (file)
index 0000000..ffe218c
--- /dev/null
@@ -0,0 +1,100 @@
+// 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 "testing"
+
+var selectTagTestTags = []string{
+       "go.r58",
+       "go.r58.1",
+       "go.r59",
+       "go.r59.1",
+       "go.r61",
+       "go.r61.1",
+       "go.weekly.2010-01-02",
+       "go.weekly.2011-10-12",
+       "go.weekly.2011-10-12.1",
+       "go.weekly.2011-10-14",
+       "go.weekly.2011-11-01",
+       "go1",
+       "go1.0.1",
+       "go1.999",
+       "go1.9.2",
+       "go5",
+
+       // these should be ignored:
+       "release.r59",
+       "release.r59.1",
+       "release",
+       "weekly.2011-10-12",
+       "weekly.2011-10-12.1",
+       "weekly",
+       "foo",
+       "bar",
+       "go.f00",
+       "go!r60",
+       "go.1999-01-01",
+       "go.2x",
+       "go.20000000000000",
+       "go.2.",
+       "go.2.0",
+       "go2x",
+       "go20000000000000",
+       "go2.",
+       "go2.0",
+}
+
+var selectTagTests = []struct {
+       version  string
+       selected string
+}{
+       /*
+               {"release.r57", ""},
+               {"release.r58.2", "go.r58.1"},
+               {"release.r59", "go.r59"},
+               {"release.r59.1", "go.r59.1"},
+               {"release.r60", "go.r59.1"},
+               {"release.r60.1", "go.r59.1"},
+               {"release.r61", "go.r61"},
+               {"release.r66", "go.r61.1"},
+               {"weekly.2010-01-01", ""},
+               {"weekly.2010-01-02", "go.weekly.2010-01-02"},
+               {"weekly.2010-01-02.1", "go.weekly.2010-01-02"},
+               {"weekly.2010-01-03", "go.weekly.2010-01-02"},
+               {"weekly.2011-10-12", "go.weekly.2011-10-12"},
+               {"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"},
+               {"weekly.2011-10-13", "go.weekly.2011-10-12.1"},
+               {"weekly.2011-10-14", "go.weekly.2011-10-14"},
+               {"weekly.2011-10-14.1", "go.weekly.2011-10-14"},
+               {"weekly.2011-11-01", "go.weekly.2011-11-01"},
+               {"weekly.2014-01-01", "go.weekly.2011-11-01"},
+               {"weekly.3000-01-01", "go.weekly.2011-11-01"},
+               {"go1", "go1"},
+               {"go1.1", "go1.0.1"},
+               {"go1.998", "go1.9.2"},
+               {"go1.1000", "go1.999"},
+               {"go6", "go5"},
+
+               // faulty versions:
+               {"release.f00", ""},
+               {"weekly.1999-01-01", ""},
+               {"junk", ""},
+               {"", ""},
+               {"go2x", ""},
+               {"go200000000000", ""},
+               {"go2.", ""},
+               {"go2.0", ""},
+       */
+       {"anything", "go1"},
+}
+
+func TestSelectTag(t *testing.T) {
+       for _, c := range selectTagTests {
+               selected := selectTag(c.version, selectTagTestTags)
+               if selected != c.selected {
+                       t.Errorf("selectTag(%q) = %q, want %q", c.version, selected, c.selected)
+               }
+       }
+}
diff --git a/libgo/go/cmd/go/test.bash b/libgo/go/cmd/go/test.bash
new file mode 100644 (file)
index 0000000..0060ce2
--- /dev/null
@@ -0,0 +1,820 @@
+#!/bin/bash
+# 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.
+
+set -e
+go build -o testgo
+go() {
+       echo TEST ERROR: ran go, not testgo: go "$@" >&2
+       exit 2
+}
+
+started=false
+TEST() {
+       if $started; then
+               stop
+       fi
+       echo TEST: "$@"
+       started=true
+       ok=true
+}
+stop() {
+       if ! $started; then
+               echo TEST ERROR: stop missing start >&2
+               exit 2
+       fi
+       started=false
+       if $ok; then
+               echo PASS
+       else
+               echo FAIL
+               allok=false
+       fi
+}
+
+ok=true
+allok=true
+
+unset GOBIN
+unset GOPATH
+unset GOROOT
+
+TEST 'file:line in error messages'
+# Test that error messages have file:line information at beginning of
+# the line. Also test issue 4917: that the error is on stderr.
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+fn=$d/err.go
+echo "package main" > $fn
+echo 'import "bar"' >> $fn
+./testgo run $fn 2>$d/err.out || true
+if ! grep -q "^$fn:" $d/err.out; then
+       echo "missing file:line in error message"
+       cat $d/err.out
+       ok=false
+fi
+rm -r $d
+
+# Test local (./) imports.
+testlocal() {
+       local="$1"
+       TEST local imports $2 '(easy)'
+       ./testgo build -o hello "testdata/$local/easy.go"
+       ./hello >hello.out
+       if ! grep -q '^easysub\.Hello' hello.out; then
+               echo "testdata/$local/easy.go did not generate expected output"
+               cat hello.out
+               ok=false
+       fi
+       
+       TEST local imports $2 '(easysub)'
+       ./testgo build -o hello "testdata/$local/easysub/main.go"
+       ./hello >hello.out
+       if ! grep -q '^easysub\.Hello' hello.out; then
+               echo "testdata/$local/easysub/main.go did not generate expected output"
+               cat hello.out
+               ok=false
+       fi
+       
+       TEST local imports $2 '(hard)'
+       ./testgo build -o hello "testdata/$local/hard.go"
+       ./hello >hello.out
+       if ! grep -q '^sub\.Hello' hello.out || ! grep -q '^subsub\.Hello' hello.out ; then
+               echo "testdata/$local/hard.go did not generate expected output"
+               cat hello.out
+               ok=false
+       fi
+       
+       rm -f hello.out hello
+       
+       # Test that go install x.go fails.
+       TEST local imports $2 '(go install should fail)'
+       if ./testgo install "testdata/$local/easy.go" >/dev/null 2>&1; then
+               echo "go install testdata/$local/easy.go succeeded"
+               ok=false
+       fi
+}
+
+# Test local imports
+testlocal local ''
+
+# Test local imports again, with bad characters in the directory name.
+bad='#$%:, &()*;<=>?\^{}'
+rm -rf "testdata/$bad"
+cp -R testdata/local "testdata/$bad"
+testlocal "$bad" 'with bad characters in path'
+rm -rf "testdata/$bad"
+
+TEST error message for syntax error in test go file says FAIL
+export GOPATH=$(pwd)/testdata
+if ./testgo test syntaxerror 2>testdata/err; then
+       echo 'go test syntaxerror succeeded'
+       ok=false
+elif ! grep FAIL testdata/err >/dev/null; then
+       echo 'go test did not say FAIL:'
+       cat testdata/err
+       ok=false
+fi
+rm -f ./testdata/err
+unset GOPATH
+
+TEST wildcards do not look in useless directories
+export GOPATH=$(pwd)/testdata
+if ./testgo list ... >testdata/err 2>&1; then
+       echo "go list ... succeeded"
+       ok=false
+elif ! grep badpkg testdata/err >/dev/null; then
+       echo "go list ... failure does not mention badpkg"
+       cat testdata/err
+       ok=false
+elif ! ./testgo list m... >testdata/err 2>&1; then
+       echo "go list m... failed"
+       ok=false
+fi
+rm -rf ./testdata/err
+unset GOPATH
+
+# Test tests with relative imports.
+TEST relative imports '(go test)'
+if ! ./testgo test ./testdata/testimport; then
+       echo "go test ./testdata/testimport failed"
+       ok=false
+fi
+
+# Test installation with relative imports.
+TEST relative imports '(go test -i)'
+if ! ./testgo test -i ./testdata/testimport; then
+    echo "go test -i ./testdata/testimport failed"
+    ok=false
+fi
+
+# Test tests with relative imports in packages synthesized
+# from Go files named on the command line.
+TEST relative imports in command-line package
+if ! ./testgo test ./testdata/testimport/*.go; then
+       echo "go test ./testdata/testimport/*.go failed"
+       ok=false
+fi
+
+TEST version control error message includes correct directory
+export GOPATH=$(pwd)/testdata/shadow/root1
+if ./testgo get -u foo 2>testdata/err; then
+       echo "go get -u foo succeeded unexpectedly"
+       ok=false
+elif ! grep testdata/shadow/root1/src/foo testdata/err >/dev/null; then
+       echo "go get -u error does not mention shadow/root1/src/foo:"
+       cat testdata/err
+       ok=false
+fi
+unset GOPATH
+
+TEST go install fails with no buildable files
+export GOPATH=$(pwd)/testdata
+export CGO_ENABLED=0
+if ./testgo install cgotest 2>testdata/err; then
+       echo "go install cgotest succeeded unexpectedly"
+elif ! grep 'no buildable Go source files' testdata/err >/dev/null; then
+       echo "go install cgotest did not report 'no buildable Go source files'"
+       cat testdata/err
+       ok=false
+fi
+unset CGO_ENABLED
+unset GOPATH
+
+# Test that without $GOBIN set, binaries get installed
+# into the GOPATH bin directory.
+TEST install into GOPATH
+rm -rf testdata/bin
+if ! GOPATH=$(pwd)/testdata ./testgo install go-cmd-test; then
+       echo "go install go-cmd-test failed"
+       ok=false
+elif ! test -x testdata/bin/go-cmd-test; then
+       echo "go install go-cmd-test did not write to testdata/bin/go-cmd-test"
+       ok=false
+fi
+
+TEST package main_test imports archive not binary
+export GOBIN=$(pwd)/testdata/bin
+mkdir -p $GOBIN
+export GOPATH=$(pwd)/testdata
+touch ./testdata/src/main_test/m.go
+if ! ./testgo test main_test; then
+       echo "go test main_test failed without install"
+       ok=false
+elif ! ./testgo install main_test; then
+       echo "go test main_test failed"
+       ok=false
+elif [ "$(./testgo list -f '{{.Stale}}' main_test)" != false ]; then
+       echo "after go install, main listed as stale"
+       ok=false
+elif ! ./testgo test main_test; then
+       echo "go test main_test failed after install"
+       ok=false
+fi
+rm -rf $GOBIN
+unset GOBIN
+
+# And with $GOBIN set, binaries get installed to $GOBIN.
+TEST install into GOBIN
+if ! GOBIN=$(pwd)/testdata/bin1 GOPATH=$(pwd)/testdata ./testgo install go-cmd-test; then
+       echo "go install go-cmd-test failed"
+       ok=false
+elif ! test -x testdata/bin1/go-cmd-test; then
+       echo "go install go-cmd-test did not write to testdata/bin1/go-cmd-test"
+       ok=false
+fi
+
+# Without $GOBIN set, installing a program outside $GOPATH should fail
+# (there is nowhere to install it).
+TEST install without destination fails
+if ./testgo install testdata/src/go-cmd-test/helloworld.go 2>testdata/err; then
+       echo "go install testdata/src/go-cmd-test/helloworld.go should have failed, did not"
+       ok=false
+elif ! grep 'no install location for .go files listed on command line' testdata/err; then
+       echo "wrong error:"
+       cat testdata/err
+       ok=false
+fi
+rm -f testdata/err
+
+# With $GOBIN set, should install there.
+TEST install to GOBIN '(command-line package)'
+if ! GOBIN=$(pwd)/testdata/bin1 ./testgo install testdata/src/go-cmd-test/helloworld.go; then
+       echo "go install testdata/src/go-cmd-test/helloworld.go failed"
+       ok=false
+elif ! test -x testdata/bin1/helloworld; then
+       echo "go install testdata/src/go-cmd-test/helloworld.go did not write testdata/bin1/helloworld"
+       ok=false
+fi
+
+TEST godoc installs into GOBIN
+d=$(mktemp -d -t testgoXXX)
+export GOPATH=$d
+mkdir $d/gobin
+GOBIN=$d/gobin ./testgo get code.google.com/p/go.tools/cmd/godoc
+if [ ! -x $d/gobin/godoc ]; then
+       echo did not install godoc to '$GOBIN'
+       GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc
+       ok=false
+fi
+
+TEST godoc installs into GOROOT
+GOROOT=$(./testgo env GOROOT)
+rm -f $GOROOT/bin/godoc
+./testgo install code.google.com/p/go.tools/cmd/godoc
+if [ ! -x $GOROOT/bin/godoc ]; then
+       echo did not install godoc to '$GOROOT/bin'
+       ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc
+       ok=false
+fi
+
+TEST cmd/fix installs into tool
+GOOS=$(./testgo env GOOS)
+GOARCH=$(./testgo env GOARCH)
+rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix
+./testgo install cmd/fix
+if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then
+       echo 'did not install cmd/fix to $GOROOT/pkg/tool'
+       GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix
+       ok=false
+fi
+rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix
+GOBIN=$d/gobin ./testgo install cmd/fix
+if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then
+       echo 'did not install cmd/fix to $GOROOT/pkg/tool with $GOBIN set'
+       GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix
+       ok=false
+fi
+
+TEST gopath program installs into GOBIN
+mkdir $d/src/progname
+echo 'package main; func main() {}' >$d/src/progname/p.go
+GOBIN=$d/gobin ./testgo install progname
+if [ ! -x $d/gobin/progname ]; then
+       echo 'did not install progname to $GOBIN/progname'
+       ./testgo list -f 'Target: {{.Target}}' cmd/api
+       ok=false
+fi
+rm -f $d/gobin/progname $d/bin/progname
+
+TEST gopath program installs into GOPATH/bin
+./testgo install progname
+if [ ! -x $d/bin/progname ]; then
+       echo 'did not install progname to $GOPATH/bin/progname'
+       ./testgo list -f 'Target: {{.Target}}' progname
+       ok=false
+fi
+
+unset GOPATH
+rm -rf $d
+
+# Reject relative paths in GOPATH.
+TEST reject relative paths in GOPATH '(command-line package)'
+if GOPATH=. ./testgo build testdata/src/go-cmd-test/helloworld.go; then
+    echo 'GOPATH="." go build should have failed, did not'
+    ok=false
+fi
+
+TEST reject relative paths in GOPATH 
+if GOPATH=:$(pwd)/testdata:. ./testgo build go-cmd-test; then
+    echo 'GOPATH=":$(pwd)/testdata:." go build should have failed, did not'
+    ok=false
+fi
+
+# issue 4104
+TEST go test with package listed multiple times
+if [ $(./testgo test fmt fmt fmt fmt fmt | wc -l) -ne 1 ] ; then
+    echo 'go test fmt fmt fmt fmt fmt tested the same package multiple times'
+    ok=false
+fi
+
+# ensure that output of 'go list' is consistent between runs
+TEST go list is consistent
+./testgo list std > test_std.list
+if ! ./testgo list std | cmp -s test_std.list - ; then
+       echo "go list std ordering is inconsistent"
+       ok=false
+fi
+rm -f test_std.list
+
+# issue 4096. Validate the output of unsuccessful go install foo/quxx 
+TEST unsuccessful go install should mention missing package
+if [ $(./testgo install 'foo/quxx' 2>&1 | grep -c 'cannot find package "foo/quxx" in any of') -ne 1 ] ; then
+       echo 'go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of'
+       ok=false
+fi 
+# test GOROOT search failure is reported
+TEST GOROOT search failure reporting
+if [ $(./testgo install 'foo/quxx' 2>&1 | egrep -c 'foo/quxx \(from \$GOROOT\)$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: .*foo/quxx (from $GOROOT)'
+        ok=false
+fi
+# test multiple GOPATH entries are reported separately
+TEST multiple GOPATH entries reported separately
+if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/./src/foo/quxx') -ne 2 ] ; then
+        echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx'
+        ok=false
+fi
+# test (from $GOPATH) annotation is reported for the first GOPATH entry
+TEST mention GOPATH in first GOPATH entry
+if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/a/src/foo/quxx \(from \$GOPATH\)$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)'
+        ok=false
+fi
+# but not on the second
+TEST but not the second entry
+if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/b/src/foo/quxx$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: .*testdata/b/src/foo/quxx'
+        ok=false
+fi
+# test missing GOPATH is reported
+TEST missing GOPATH is reported
+if [ $(GOPATH= ./testgo install 'foo/quxx' 2>&1 | egrep -c '\(\$GOPATH not set\)$') -ne 1 ] ; then
+        echo 'go install foo/quxx expected error: ($GOPATH not set)'
+        ok=false
+fi
+
+# issue 4186. go get cannot be used to download packages to $GOROOT
+# Test that without GOPATH set, go get should fail
+TEST without GOPATH, go get fails
+d=$(mktemp -d -t testgoXXX)
+mkdir -p $d/src/pkg
+if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then 
+       echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
+       ok=false
+fi     
+rm -rf $d
+
+# Test that with GOPATH=$GOROOT, go get should fail
+TEST with GOPATH=GOROOT, go get fails
+d=$(mktemp -d -t testgoXXX)
+mkdir -p $d/src/pkg
+if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
+        echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
+        ok=false
+fi
+rm -rf $d
+
+TEST ldflags arguments with spaces '(issue 3941)'
+d=$(mktemp -d -t testgoXXX)
+cat >$d/main.go<<EOF
+package main
+var extern string
+func main() {
+       println(extern)
+}
+EOF
+./testgo run -ldflags '-X main.extern "hello world"' $d/main.go 2>hello.out
+if ! grep -q '^hello world' hello.out; then
+       echo "ldflags -X main.extern 'hello world' failed. Output:"
+       cat hello.out
+       ok=false
+fi
+rm -rf $d hello.out
+
+TEST go test -cpuprofile leaves binary behind
+./testgo test -cpuprofile strings.prof strings || ok=false
+if [ ! -x strings.test ]; then
+       echo "go test -cpuprofile did not create strings.test"
+       ok=false
+fi
+rm -f strings.prof strings.test
+
+TEST symlinks do not confuse go list '(issue 4568)'
+old=$(pwd)
+tmp=$(cd /tmp && pwd -P)
+d=$(TMPDIR=$tmp mktemp -d -t testgoXXX)
+mkdir -p $d/src
+(
+       ln -s $d $d/src/dir1
+       cd $d/src
+       echo package p >dir1/p.go
+       export GOPATH=$d
+       if [ "$($old/testgo list -f '{{.Root}}' dir1)" != "$d" ]; then
+               echo Confused by symlinks.
+               echo "Package in current directory $(pwd) should have Root $d"
+               env|grep WD
+               $old/testgo list -json . dir1
+               touch $d/failed
+       fi              
+)
+if [ -f $d/failed ]; then
+       ok=false
+fi
+rm -rf $d
+
+TEST 'install with tags (issue 4515)'
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+mkdir -p $d/src/example/a $d/src/example/b $d/bin
+cat >$d/src/example/a/main.go <<EOF
+package main
+func main() {}
+EOF
+cat >$d/src/example/b/main.go <<EOF
+// +build mytag
+
+package main
+func main() {}
+EOF
+GOPATH=$d ./testgo install -tags mytag example/a example/b || ok=false
+if [ ! -x $d/bin/a -o ! -x $d/bin/b ]; then
+       echo go install example/a example/b did not install binaries
+       ok=false
+fi
+rm -f $d/bin/*
+GOPATH=$d ./testgo install -tags mytag example/... || ok=false
+if [ ! -x $d/bin/a -o ! -x $d/bin/b ]; then
+       echo go install example/... did not install binaries
+       ok=false
+fi
+rm -f $d/bin/*go
+export GOPATH=$d
+if [ "$(./testgo list -tags mytag example/b...)" != "example/b" ]; then
+       echo go list example/b did not find example/b
+       ok=false
+fi
+unset GOPATH
+rm -rf $d
+
+TEST case collisions '(issue 4773)'
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+export GOPATH=$d
+mkdir -p $d/src/example/{a/pkg,a/Pkg,b}
+cat >$d/src/example/a/a.go <<EOF
+package p
+import (
+       _ "example/a/pkg"
+       _ "example/a/Pkg"
+)
+EOF
+cat >$d/src/example/a/pkg/pkg.go <<EOF
+package pkg
+EOF
+cat >$d/src/example/a/Pkg/pkg.go <<EOF
+package pkg
+EOF
+if ./testgo list example/a 2>$d/out; then
+       echo go list example/a should have failed, did not.
+       ok=false
+elif ! grep "case-insensitive import collision" $d/out >/dev/null; then
+       echo go list example/a did not report import collision.
+       ok=false
+fi
+cat >$d/src/example/b/file.go <<EOF
+package b
+EOF
+cat >$d/src/example/b/FILE.go <<EOF
+package b
+EOF
+if [ $(ls $d/src/example/b | wc -l) = 2 ]; then
+       # case-sensitive file system, let directory read find both files
+       args="example/b"
+else
+       # case-insensitive file system, list files explicitly on command line.
+       args="$d/src/example/b/file.go $d/src/example/b/FILE.go"
+fi
+if ./testgo list $args 2>$d/out; then
+       echo go list example/b should have failed, did not.
+       ok=false
+elif ! grep "case-insensitive file name collision" $d/out >/dev/null; then
+       echo go list example/b did not report file name collision.
+       ok=false
+fi
+
+TEST go get cover
+./testgo get code.google.com/p/go.tools/cmd/cover || ok=false
+
+unset GOPATH
+rm -rf $d
+
+TEST shadowing logic
+export GOPATH=$(pwd)/testdata/shadow/root1:$(pwd)/testdata/shadow/root2
+
+# The math in root1 is not "math" because the standard math is.
+cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/math)
+if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/pkg/math)" ]; then
+       echo shadowed math is not shadowed: "$cdir"
+       ok=false
+fi
+
+# The foo in root1 is "foo".
+cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/foo)
+if [ "$cdir" != "(foo) ()" ]; then
+       echo unshadowed foo is shadowed: "$cdir"
+       ok=false
+fi
+
+# The foo in root2 is not "foo" because the foo in root1 got there first.
+cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root2/src/foo)
+if [ "$cdir" != "(_$(pwd)/testdata/shadow/root2/src/foo) ($(pwd)/testdata/shadow/root1/src/foo)" ]; then
+       echo shadowed foo is not shadowed: "$cdir"
+       ok=false
+fi
+
+# The error for go install should mention the conflicting directory.
+err=$(! ./testgo install ./testdata/shadow/root2/src/foo 2>&1)
+if [ "$err" != "go install: no install location for $(pwd)/testdata/shadow/root2/src/foo: hidden by $(pwd)/testdata/shadow/root1/src/foo" ]; then
+       echo wrong shadowed install error: "$err"
+       ok=false
+fi
+
+# Only succeeds if source order is preserved.
+TEST source file name order preserved
+./testgo test testdata/example[12]_test.go || ok=false
+
+# Check that coverage analysis works at all.
+# Don't worry about the exact numbers but require not 0.0%.
+checkcoverage() {
+       if grep '[^0-9]0\.0%' testdata/cover.txt >/dev/null; then
+               echo 'some coverage results are 0.0%'
+               ok=false
+       fi
+       cat testdata/cover.txt
+       rm -f testdata/cover.txt
+}
+       
+TEST coverage runs
+./testgo test -short -coverpkg=strings strings regexp >testdata/cover.txt 2>&1 || ok=false
+./testgo test -short -cover strings math regexp >>testdata/cover.txt 2>&1 || ok=false
+checkcoverage
+
+# Check that coverage analysis uses set mode.
+TEST coverage uses set mode
+if ./testgo test -short -cover encoding/binary -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then
+       if ! grep -q 'mode: set' testdata/cover.out; then
+               ok=false
+       fi
+       checkcoverage
+else
+       ok=false
+fi
+rm -f testdata/cover.out testdata/cover.txt
+
+TEST coverage uses atomic mode for -race.
+if ./testgo test -short -race -cover encoding/binary -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then
+       if ! grep -q 'mode: atomic' testdata/cover.out; then
+               ok=false
+       fi
+       checkcoverage
+else
+       ok=false
+fi
+rm -f testdata/cover.out
+
+TEST coverage uses actual setting to override even for -race.
+if ./testgo test -short -race -cover encoding/binary -covermode=count -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then
+       if ! grep -q 'mode: count' testdata/cover.out; then
+               ok=false
+       fi
+       checkcoverage
+else
+       ok=false
+fi
+rm -f testdata/cover.out
+
+TEST coverage with cgo
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+./testgo test -short -cover ./testdata/cgocover >testdata/cover.txt 2>&1 || ok=false
+checkcoverage
+
+TEST cgo depends on syscall
+rm -rf $GOROOT/pkg/*_race
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+export GOPATH=$d
+mkdir -p $d/src/foo
+echo '
+package foo
+//#include <stdio.h>
+import "C"
+' >$d/src/foo/foo.go
+./testgo build -race foo || ok=false
+rm -rf $d
+unset GOPATH
+
+TEST cgo shows full path names
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+export GOPATH=$d
+mkdir -p $d/src/x/y/dirname
+echo '
+package foo
+import "C"
+func f() {
+' >$d/src/x/y/dirname/foo.go
+if ./testgo build x/y/dirname >$d/err 2>&1; then
+       echo build succeeded unexpectedly.
+       ok=false
+elif ! grep x/y/dirname $d/err >/dev/null; then
+       echo error did not use full path.
+       cat $d/err
+       ok=false
+fi
+rm -rf $d
+unset GOPATH
+
+TEST 'cgo handles -Wl,$ORIGIN'
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+export GOPATH=$d
+mkdir -p $d/src/origin
+echo '
+package origin
+// #cgo !darwin LDFLAGS: -Wl,-rpath -Wl,$ORIGIN
+// void f(void) {}
+import "C"
+
+func f() { C.f() }
+' >$d/src/origin/origin.go
+if ! ./testgo build origin; then
+       echo build failed
+       ok=false
+fi
+rm -rf $d
+unset GOPATH
+
+TEST 'Issue 6480: "go test -c -test.bench=XXX fmt" should not hang'
+if ! ./testgo test -c -test.bench=XXX fmt; then
+       echo build test failed
+       ok=false
+fi
+rm -f fmt.test
+
+TEST 'Issue 7573: cmd/cgo: undefined reference when linking a C-library using gccgo'
+d=$(mktemp -d -t testgoXXX)
+export GOPATH=$d
+mkdir -p $d/src/cgoref
+ldflags="-L alibpath -lalib"
+echo "
+package main
+// #cgo LDFLAGS: $ldflags
+// void f(void) {}
+import \"C\"
+
+func main() { C.f() }
+" >$d/src/cgoref/cgoref.go
+go_cmds="$(./testgo build -n -compiler gccgo cgoref 2>&1 1>/dev/null)"
+ldflags_count="$(echo "$go_cmds" | egrep -c "^gccgo.*$(echo $ldflags | sed -e 's/-/\\-/g')" || true)"
+if [ "$ldflags_count" -lt 1 ]; then
+       echo "No Go-inline "#cgo LDFLAGS:" (\"$ldflags\") passed to gccgo linking stage."
+       ok=false
+fi
+rm -rf $d
+unset ldflags_count
+unset go_cmds
+unset ldflags
+unset GOPATH
+
+TEST list template can use context function
+if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then 
+       echo unable to use context in list template
+       ok=false
+fi
+
+TEST 'Issue 7108: cmd/go: "go test" should fail if package does not build'
+export GOPATH=$(pwd)/testdata
+if ./testgo test notest >/dev/null 2>&1; then
+       echo 'go test notest succeeded, but should fail'
+       ok=false
+fi
+unset GOPATH
+
+TEST 'Issue 6844: cmd/go: go test -a foo does not rebuild regexp'
+if ! ./testgo test -x -a -c testdata/dep_test.go 2>deplist; then
+       echo "go test -x -a -c testdata/dep_test.go failed"
+       ok=false
+elif ! grep -q regexp deplist; then
+       echo "go test -x -a -c testdata/dep_test.go did not rebuild regexp"
+       ok=false
+fi
+rm -f deplist
+rm -f deps.test
+
+TEST list template can use context function
+if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then 
+       echo unable to use context in list template
+       ok=false
+fi
+
+TEST build -i installs dependencies
+d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
+export GOPATH=$d
+mkdir -p $d/src/x/y/foo $d/src/x/y/bar
+echo '
+package foo
+func F() {}
+' >$d/src/x/y/foo/foo.go
+echo '
+package bar
+import "x/y/foo"
+func F() { foo.F() }
+' >$d/src/x/y/bar/bar.go
+if ! ./testgo build -v -i x/y/bar &> $d/err; then
+       echo build -i failed
+       cat $d/err
+       ok=false
+elif ! grep x/y/foo $d/err >/dev/null; then
+       echo first build -i did not build x/y/foo
+       cat $d/err
+       ok=false
+fi
+if ! ./testgo build -v -i x/y/bar &> $d/err; then
+       echo second build -i failed
+       cat $d/err
+       ok=false
+elif grep x/y/foo $d/err >/dev/null; then
+       echo second build -i built x/y/foo
+       cat $d/err
+       ok=false
+fi
+rm -rf $d
+unset GOPATH
+
+TEST 'go build in test-only directory fails with a good error'
+if ./testgo build ./testdata/testonly 2>testdata/err.out; then
+       echo "go build ./testdata/testonly succeeded, should have failed"
+       ok=false
+elif ! grep 'no buildable Go' testdata/err.out >/dev/null; then
+       echo "go build ./testdata/testonly produced unexpected error:"
+       cat testdata/err.out
+       ok=false
+fi
+rm -f testdata/err.out
+
+TEST 'go test detects test-only import cycles'
+export GOPATH=$(pwd)/testdata
+if ./testgo test -c testcycle/p3 2>testdata/err.out; then
+       echo "go test testcycle/p3 succeeded, should have failed"
+       ok=false
+elif ! grep 'import cycle not allowed in test' testdata/err.out >/dev/null; then
+       echo "go test testcycle/p3 produced unexpected error:"
+       cat testdata/err.out
+       ok=false
+fi
+rm -f testdata/err.out
+unset GOPATH
+
+TEST 'go test foo_test.go works'
+if ! ./testgo test testdata/standalone_test.go; then
+       echo "go test testdata/standalone_test.go failed"
+       ok=false
+fi
+
+TEST 'go test xtestonly works'
+export GOPATH=$(pwd)/testdata
+./testgo clean -i xtestonly
+if ! ./testgo test xtestonly >/dev/null; then
+       echo "go test xtestonly failed"
+       ok=false
+fi
+unset GOPATH
+
+
+# clean up
+if $started; then stop; fi
+rm -rf testdata/bin testdata/bin1
+rm -f testgo
+
+if $allok; then
+       echo PASS
+else
+       echo FAIL
+       exit 1
+fi
diff --git a/libgo/go/cmd/go/test.go b/libgo/go/cmd/go/test.go
new file mode 100644 (file)
index 0000000..f7ae9c0
--- /dev/null
@@ -0,0 +1,1308 @@
+// 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 (
+       "bytes"
+       "fmt"
+       "go/ast"
+       "go/build"
+       "go/doc"
+       "go/parser"
+       "go/token"
+       "log"
+       "os"
+       "os/exec"
+       "path"
+       "path/filepath"
+       "regexp"
+       "runtime"
+       "sort"
+       "strings"
+       "text/template"
+       "time"
+       "unicode"
+       "unicode/utf8"
+)
+
+// Break init loop.
+func init() {
+       cmdTest.Run = runTest
+}
+
+var cmdTest = &Command{
+       CustomFlags: true,
+       UsageLine:   "test [-c] [-i] [build and test flags] [packages] [flags for test binary]",
+       Short:       "test packages",
+       Long: `
+'Go test' automates testing the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+       ok   archive/tar   0.011s
+       FAIL archive/zip   0.022s
+       ok   compress/gzip 0.033s
+       ...
+
+followed by detailed output for each failed package.
+
+'Go test' recompiles each package along with any files with names matching
+the file pattern "*_test.go". 
+Files whose names begin with "_" (including "_test.go") or "." are ignored.
+These additional files can contain test functions, benchmark functions, and
+example functions.  See 'go help testfunc' for more.
+Each listed package causes the execution of a separate test binary.
+
+Test files that declare a package with the suffix "_test" will be compiled as a
+separate package, and then linked and run with the main test binary.
+
+By default, go test needs no arguments.  It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+In addition to the build flags, the flags handled by 'go test' itself are:
+
+       -c  Compile the test binary to pkg.test but do not run it.
+           (Where pkg is the last element of the package's import path.)
+
+       -i
+           Install packages that are dependencies of the test.
+           Do not run the test.
+
+       -exec xprog
+           Run the test binary using xprog. The behavior is the same as
+           in 'go run'. See 'go help run' for details.
+
+The test binary also accepts flags that control execution of the test; these
+flags are also accessible by 'go test'.  See 'go help testflag' for details.
+
+If the test binary needs any other flags, they should be presented after the
+package names. The go tool treats as a flag the first argument that begins with
+a minus sign that it does not recognize itself; that argument and all subsequent
+arguments are passed as arguments to the test binary.
+
+For more about build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
+
+See also: go build, go vet.
+`,
+}
+
+var helpTestflag = &Command{
+       UsageLine: "testflag",
+       Short:     "description of testing flags",
+       Long: `
+The 'go test' command takes both flags that apply to 'go test' itself
+and flags that apply to the resulting test binary.
+
+Several of the flags control profiling and write an execution profile
+suitable for "go tool pprof"; run "go tool pprof help" for more
+information.  The --alloc_space, --alloc_objects, and --show_bytes
+options of pprof control how the information is presented.
+
+The following flags are recognized by the 'go test' command and
+control the execution of any test:
+
+       -bench regexp
+           Run benchmarks matching the regular expression.
+           By default, no benchmarks run. To run all benchmarks,
+           use '-bench .' or '-bench=.'.
+
+       -benchmem
+           Print memory allocation statistics for benchmarks.
+
+       -benchtime t
+           Run enough iterations of each benchmark to take t, specified
+           as a time.Duration (for example, -benchtime 1h30s).
+           The default is 1 second (1s).
+
+       -blockprofile block.out
+           Write a goroutine blocking profile to the specified file
+           when all tests are complete.
+
+       -blockprofilerate n
+           Control the detail provided in goroutine blocking profiles by
+           calling runtime.SetBlockProfileRate with n.
+           See 'godoc runtime SetBlockProfileRate'.
+           The profiler aims to sample, on average, one blocking event every
+           n nanoseconds the program spends blocked.  By default,
+           if -test.blockprofile is set without this flag, all blocking events
+           are recorded, equivalent to -test.blockprofilerate=1.
+
+       -cover
+           Enable coverage analysis.
+
+       -covermode set,count,atomic
+           Set the mode for coverage analysis for the package[s]
+           being tested. The default is "set" unless -race is enabled,
+           in which case it is "atomic".
+           The values:
+               set: bool: does this statement run?
+               count: int: how many times does this statement run?
+               atomic: int: count, but correct in multithreaded tests;
+                       significantly more expensive.
+           Sets -cover.
+
+       -coverpkg pkg1,pkg2,pkg3
+           Apply coverage analysis in each test to the given list of packages.
+           The default is for each test to analyze only the package being tested.
+           Packages are specified as import paths.
+           Sets -cover.
+
+       -coverprofile cover.out
+           Write a coverage profile to the specified file after all tests
+           have passed.
+           Sets -cover.
+
+       -cpu 1,2,4
+           Specify a list of GOMAXPROCS values for which the tests or
+           benchmarks should be executed.  The default is the current value
+           of GOMAXPROCS.
+
+       -cpuprofile cpu.out
+           Write a CPU profile to the specified file before exiting.
+
+       -memprofile mem.out
+           Write a memory profile to the specified file after all tests
+           have passed.
+
+       -memprofilerate n
+           Enable more precise (and expensive) memory profiles by setting
+           runtime.MemProfileRate.  See 'godoc runtime MemProfileRate'.
+           To profile all memory allocations, use -test.memprofilerate=1
+           and pass --alloc_space flag to the pprof tool.
+
+       -outputdir directory
+           Place output files from profiling in the specified directory,
+           by default the directory in which "go test" is running.
+
+       -parallel n
+           Allow parallel execution of test functions that call t.Parallel.
+           The value of this flag is the maximum number of tests to run
+           simultaneously; by default, it is set to the value of GOMAXPROCS.
+
+       -run regexp
+           Run only those tests and examples matching the regular
+           expression.
+
+       -short
+           Tell long-running tests to shorten their run time.
+           It is off by default but set during all.bash so that installing
+           the Go tree can run a sanity check but not spend time running
+           exhaustive tests.
+
+       -timeout t
+           If a test runs longer than t, panic.
+
+       -v
+           Verbose output: log all tests as they are run. Also print all
+           text from Log and Logf calls even if the test succeeds.
+
+The test binary, called pkg.test where pkg is the name of the
+directory containing the package sources, can be invoked directly
+after building it with 'go test -c'. When invoking the test binary
+directly, each of the standard flag names must be prefixed with 'test.',
+as in -test.run=TestMyFunc or -test.v.
+
+When running 'go test', flags not listed above are passed through
+unaltered. For instance, the command
+
+       go test -x -v -cpuprofile=prof.out -dir=testdata -update
+
+will compile the test binary and then run it as
+
+       pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
+
+The test flags that generate profiles (other than for coverage) also
+leave the test binary in pkg.test for use when analyzing the profiles.
+
+Flags not recognized by 'go test' must be placed after any specified packages.
+`,
+}
+
+var helpTestfunc = &Command{
+       UsageLine: "testfunc",
+       Short:     "description of testing functions",
+       Long: `
+The 'go test' command expects to find test, benchmark, and example functions
+in the "*_test.go" files corresponding to the package under test.
+
+A test function is one named TestXXX (where XXX is any alphanumeric string
+not starting with a lower case letter) and should have the signature,
+
+       func TestXXX(t *testing.T) { ... }
+
+A benchmark function is one named BenchmarkXXX and should have the signature,
+
+       func BenchmarkXXX(b *testing.B) { ... }
+
+An example function is similar to a test function but, instead of using
+*testing.T to report success or failure, prints output to os.Stdout.
+That output is compared against the function's "Output:" comment, which
+must be the last comment in the function body (see example below). An
+example with no such comment, or with no text after "Output:" is compiled
+but not executed.
+
+Godoc displays the body of ExampleXXX to demonstrate the use
+of the function, constant, or variable XXX.  An example of a method M with
+receiver type T or *T is named ExampleT_M.  There may be multiple examples
+for a given function, constant, or variable, distinguished by a trailing _xxx,
+where xxx is a suffix not beginning with an upper case letter.
+
+Here is an example of an example:
+
+       func ExamplePrintln() {
+               Println("The output of\nthis example.")
+               // Output: The output of
+               // this example.
+       }
+
+The entire test file is presented as the example when it contains a single
+example function, at least one other function, type, variable, or constant
+declaration, and no test or benchmark functions.
+
+See the documentation of the testing package for more information.
+`,
+}
+
+var (
+       testC            bool       // -c flag
+       testCover        bool       // -cover flag
+       testCoverMode    string     // -covermode flag
+       testCoverPaths   []string   // -coverpkg flag
+       testCoverPkgs    []*Package // -coverpkg flag
+       testProfile      bool       // some profiling flag
+       testNeedBinary   bool       // profile needs to keep binary around
+       testV            bool       // -v flag
+       testFiles        []string   // -file flag(s)  TODO: not respected
+       testTimeout      string     // -timeout flag
+       testArgs         []string
+       testBench        bool
+       testStreamOutput bool // show output as it is generated
+       testShowPass     bool // show passing output
+
+       testKillTimeout = 10 * time.Minute
+)
+
+var testMainDeps = map[string]bool{
+       // Dependencies for testmain.
+       "testing": true,
+       "regexp":  true,
+}
+
+func runTest(cmd *Command, args []string) {
+       var pkgArgs []string
+       pkgArgs, testArgs = testFlags(args)
+
+       findExecCmd() // initialize cached result
+
+       raceInit()
+       pkgs := packagesForBuild(pkgArgs)
+       if len(pkgs) == 0 {
+               fatalf("no packages to test")
+       }
+
+       if testC && len(pkgs) != 1 {
+               fatalf("cannot use -c flag with multiple packages")
+       }
+       if testProfile && len(pkgs) != 1 {
+               fatalf("cannot use test profile flag with multiple packages")
+       }
+
+       // If a test timeout was given and is parseable, set our kill timeout
+       // to that timeout plus one minute.  This is a backup alarm in case
+       // the test wedges with a goroutine spinning and its background
+       // timer does not get a chance to fire.
+       if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 {
+               testKillTimeout = dt + 1*time.Minute
+       }
+
+       // show passing test output (after buffering) with -v flag.
+       // must buffer because tests are running in parallel, and
+       // otherwise the output will get mixed.
+       testShowPass = testV
+
+       // stream test output (no buffering) when no package has
+       // been given on the command line (implicit current directory)
+       // or when benchmarking.
+       // Also stream if we're showing output anyway with a
+       // single package under test.  In that case, streaming the
+       // output produces the same result as not streaming,
+       // just more immediately.
+       testStreamOutput = len(pkgArgs) == 0 || testBench ||
+               (len(pkgs) <= 1 && testShowPass)
+
+       var b builder
+       b.init()
+
+       if buildI {
+               buildV = testV
+
+               deps := make(map[string]bool)
+               for dep := range testMainDeps {
+                       deps[dep] = true
+               }
+
+               for _, p := range pkgs {
+                       // Dependencies for each test.
+                       for _, path := range p.Imports {
+                               deps[path] = true
+                       }
+                       for _, path := range p.TestImports {
+                               deps[path] = true
+                       }
+                       for _, path := range p.XTestImports {
+                               deps[path] = true
+                       }
+               }
+
+               // translate C to runtime/cgo
+               if deps["C"] {
+                       delete(deps, "C")
+                       deps["runtime/cgo"] = true
+                       if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH {
+                               deps["cmd/cgo"] = true
+                       }
+               }
+               // Ignore pseudo-packages.
+               delete(deps, "unsafe")
+
+               all := []string{}
+               if reqPkgSrc {
+                       for path := range deps {
+                               if !build.IsLocalImport(path) {
+                                       all = append(all, path)
+                               }
+                       }
+               }
+               sort.Strings(all)
+
+               a := &action{}
+               for _, p := range packagesForBuild(all) {
+                       a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
+               }
+               b.do(a)
+               if !testC || a.failed {
+                       return
+               }
+               b.init()
+       }
+
+       var builds, runs, prints []*action
+
+       if testCoverPaths != nil {
+               // Load packages that were asked about for coverage.
+               // packagesForBuild exits if the packages cannot be loaded.
+               testCoverPkgs = packagesForBuild(testCoverPaths)
+
+               // Warn about -coverpkg arguments that are not actually used.
+               used := make(map[string]bool)
+               for _, p := range pkgs {
+                       used[p.ImportPath] = true
+                       for _, dep := range p.Deps {
+                               used[dep] = true
+                       }
+               }
+               for _, p := range testCoverPkgs {
+                       if !used[p.ImportPath] {
+                               log.Printf("warning: no packages being tested depend on %s", p.ImportPath)
+                       }
+               }
+
+               // Mark all the coverage packages for rebuilding with coverage.
+               for _, p := range testCoverPkgs {
+                       p.Stale = true // rebuild
+                       p.fake = true  // do not warn about rebuild
+                       p.coverMode = testCoverMode
+                       var coverFiles []string
+                       coverFiles = append(coverFiles, p.GoFiles...)
+                       coverFiles = append(coverFiles, p.CgoFiles...)
+                       coverFiles = append(coverFiles, p.TestGoFiles...)
+                       p.coverVars = declareCoverVars(p.ImportPath, coverFiles...)
+               }
+       }
+
+       // Prepare build + run + print actions for all packages being tested.
+       for _, p := range pkgs {
+               buildTest, runTest, printTest, err := b.test(p)
+               if err != nil {
+                       str := err.Error()
+                       if strings.HasPrefix(str, "\n") {
+                               str = str[1:]
+                       }
+                       failed := fmt.Sprintf("FAIL\t%s [setup failed]\n", p.ImportPath)
+
+                       if p.ImportPath != "" {
+                               errorf("# %s\n%s\n%s", p.ImportPath, str, failed)
+                       } else {
+                               errorf("%s\n%s", str, failed)
+                       }
+                       continue
+               }
+               builds = append(builds, buildTest)
+               runs = append(runs, runTest)
+               prints = append(prints, printTest)
+       }
+
+       // Ultimately the goal is to print the output.
+       root := &action{deps: prints}
+
+       // Force the printing of results to happen in order,
+       // one at a time.
+       for i, a := range prints {
+               if i > 0 {
+                       a.deps = append(a.deps, prints[i-1])
+               }
+       }
+
+       // Force benchmarks to run in serial.
+       if !testC && testBench {
+               // The first run must wait for all builds.
+               // Later runs must wait for the previous run's print.
+               for i, run := range runs {
+                       if i == 0 {
+                               run.deps = append(run.deps, builds...)
+                       } else {
+                               run.deps = append(run.deps, prints[i-1])
+                       }
+               }
+       }
+
+       // If we are building any out-of-date packages other
+       // than those under test, warn.
+       okBuild := map[*Package]bool{}
+       for _, p := range pkgs {
+               okBuild[p] = true
+       }
+       warned := false
+       for _, a := range actionList(root) {
+               if a.p == nil || okBuild[a.p] {
+                       continue
+               }
+               okBuild[a.p] = true // warn at most once
+
+               // Don't warn about packages being rebuilt because of
+               // things like coverage analysis.
+               for _, p1 := range a.p.imports {
+                       if p1.fake {
+                               a.p.fake = true
+                       }
+               }
+
+               if a.f != nil && !okBuild[a.p] && !a.p.fake && !a.p.local {
+                       if !warned {
+                               fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n")
+                               warned = true
+                       }
+                       fmt.Fprintf(os.Stderr, "\t%s\n", a.p.ImportPath)
+               }
+       }
+       if warned {
+               args := strings.Join(pkgArgs, " ")
+               if args != "" {
+                       args = " " + args
+               }
+               extraOpts := ""
+               if buildRace {
+                       extraOpts = "-race "
+               }
+               fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\n\n", extraOpts, args)
+       }
+
+       b.do(root)
+}
+
+func contains(x []string, s string) bool {
+       for _, t := range x {
+               if t == s {
+                       return true
+               }
+       }
+       return false
+}
+
+func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
+       if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
+               build := b.action(modeBuild, modeBuild, p)
+               run := &action{p: p, deps: []*action{build}}
+               print := &action{f: (*builder).notest, p: p, deps: []*action{run}}
+               return build, run, print, nil
+       }
+
+       // Build Package structs describing:
+       //      ptest - package + test files
+       //      pxtest - package of external test files
+       //      pmain - pkg.test binary
+       var ptest, pxtest, pmain *Package
+
+       var imports, ximports []*Package
+       var stk importStack
+       stk.push(p.ImportPath + " (test)")
+       for _, path := range p.TestImports {
+               p1 := loadImport(path, p.Dir, &stk, p.build.TestImportPos[path])
+               if !reqPkgSrc && p1.Root == "" {
+                       continue
+               }
+               if p1.Error != nil {
+                       return nil, nil, nil, p1.Error
+               }
+               if contains(p1.Deps, p.ImportPath) {
+                       // Same error that loadPackage returns (via reusePackage) in pkg.go.
+                       // Can't change that code, because that code is only for loading the
+                       // non-test copy of a package.
+                       err := &PackageError{
+                               ImportStack:   testImportStack(stk[0], p1, p.ImportPath),
+                               Err:           "import cycle not allowed in test",
+                               isImportCycle: true,
+                       }
+                       return nil, nil, nil, err
+               }
+               imports = append(imports, p1)
+       }
+       stk.pop()
+       stk.push(p.ImportPath + "_test")
+       pxtestNeedsPtest := false
+       for _, path := range p.XTestImports {
+               if path == p.ImportPath {
+                       pxtestNeedsPtest = true
+                       continue
+               }
+               p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path])
+               if !reqPkgSrc && p1.Root == "" {
+                       continue
+               }
+               if p1.Error != nil {
+                       return nil, nil, nil, p1.Error
+               }
+               ximports = append(ximports, p1)
+       }
+       stk.pop()
+
+       // Use last element of import path, not package name.
+       // They differ when package name is "main".
+       // But if the import path is "command-line-arguments",
+       // like it is during 'go run', use the package name.
+       var elem string
+       if p.ImportPath == "command-line-arguments" {
+               elem = p.Name
+       } else {
+               _, elem = path.Split(p.ImportPath)
+       }
+       testBinary := elem + ".test"
+
+       // The ptest package needs to be importable under the
+       // same import path that p has, but we cannot put it in
+       // the usual place in the temporary tree, because then
+       // other tests will see it as the real package.
+       // Instead we make a _test directory under the import path
+       // and then repeat the import path there.  We tell the
+       // compiler and linker to look in that _test directory first.
+       //
+       // That is, if the package under test is unicode/utf8,
+       // then the normal place to write the package archive is
+       // $WORK/unicode/utf8.a, but we write the test package archive to
+       // $WORK/unicode/utf8/_test/unicode/utf8.a.
+       // We write the external test package archive to
+       // $WORK/unicode/utf8/_test/unicode/utf8_test.a.
+       testDir := filepath.Join(b.work, filepath.FromSlash(p.ImportPath+"/_test"))
+       ptestObj := buildToolchain.pkgpath(testDir, p)
+
+       // Create the directory for the .a files.
+       ptestDir, _ := filepath.Split(ptestObj)
+       if err := b.mkdir(ptestDir); err != nil {
+               return nil, nil, nil, err
+       }
+
+       // Should we apply coverage analysis locally,
+       // only for this package and only for this test?
+       // Yes, if -cover is on but -coverpkg has not specified
+       // a list of packages for global coverage.
+       localCover := testCover && testCoverPaths == nil
+
+       // Test package.
+       if len(p.TestGoFiles) > 0 || localCover || p.Name == "main" {
+               ptest = new(Package)
+               *ptest = *p
+               ptest.GoFiles = nil
+               ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
+               ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
+               ptest.target = ""
+               ptest.Imports = stringList(p.Imports, p.TestImports)
+               ptest.imports = append(append([]*Package{}, p.imports...), imports...)
+               ptest.pkgdir = testDir
+               ptest.fake = true
+               ptest.forceLibrary = true
+               ptest.Stale = true
+               ptest.build = new(build.Package)
+               *ptest.build = *p.build
+               m := map[string][]token.Position{}
+               for k, v := range p.build.ImportPos {
+                       m[k] = append(m[k], v...)
+               }
+               for k, v := range p.build.TestImportPos {
+                       m[k] = append(m[k], v...)
+               }
+               ptest.build.ImportPos = m
+
+               if localCover {
+                       ptest.coverMode = testCoverMode
+                       var coverFiles []string
+                       coverFiles = append(coverFiles, ptest.GoFiles...)
+                       coverFiles = append(coverFiles, ptest.CgoFiles...)
+                       ptest.coverVars = declareCoverVars(ptest.ImportPath, coverFiles...)
+               }
+       } else {
+               ptest = p
+       }
+
+       // External test package.
+       if len(p.XTestGoFiles) > 0 {
+               pxtest = &Package{
+                       Name:        p.Name + "_test",
+                       ImportPath:  p.ImportPath + "_test",
+                       localPrefix: p.localPrefix,
+                       Root:        p.Root,
+                       Dir:         p.Dir,
+                       GoFiles:     p.XTestGoFiles,
+                       Imports:     p.XTestImports,
+                       build: &build.Package{
+                               ImportPos: p.build.XTestImportPos,
+                       },
+                       imports: ximports,
+                       pkgdir:  testDir,
+                       fake:    true,
+                       Stale:   true,
+               }
+               if pxtestNeedsPtest {
+                       pxtest.imports = append(pxtest.imports, ptest)
+               }
+       }
+
+       // Action for building pkg.test.
+       pmain = &Package{
+               Name:       "main",
+               Dir:        testDir,
+               GoFiles:    []string{"_testmain.go"},
+               ImportPath: "testmain",
+               Root:       p.Root,
+               build:      &build.Package{Name: "main"},
+               pkgdir:     testDir,
+               fake:       true,
+               Stale:      true,
+               omitDWARF:  !testC && !testNeedBinary,
+       }
+
+       // The generated main also imports testing and regexp.
+       stk.push("testmain")
+       for dep := range testMainDeps {
+               if dep == ptest.ImportPath {
+                       pmain.imports = append(pmain.imports, ptest)
+               } else {
+                       p1 := loadImport(dep, "", &stk, nil)
+                       if !reqPkgSrc && p1.Root == "" {
+                               continue
+                       }
+                       if p1.Error != nil {
+                               return nil, nil, nil, p1.Error
+                       }
+                       pmain.imports = append(pmain.imports, p1)
+               }
+       }
+
+       if testCoverPkgs != nil {
+               // Add imports, but avoid duplicates.
+               seen := map[*Package]bool{p: true, ptest: true}
+               for _, p1 := range pmain.imports {
+                       seen[p1] = true
+               }
+               for _, p1 := range testCoverPkgs {
+                       if !seen[p1] {
+                               seen[p1] = true
+                               pmain.imports = append(pmain.imports, p1)
+                       }
+               }
+       }
+
+       // Do initial scan for metadata needed for writing _testmain.go
+       // Use that metadata to update the list of imports for package main.
+       // The list of imports is used by recompileForTest and by the loop
+       // afterward that gathers t.Cover information.
+       t, err := loadTestFuncs(ptest)
+       if err != nil {
+               return nil, nil, nil, err
+       }
+       if t.NeedTest || ptest.coverMode != "" {
+               pmain.imports = append(pmain.imports, ptest)
+       }
+       if t.NeedXtest {
+               pmain.imports = append(pmain.imports, pxtest)
+       }
+
+       if ptest != p && localCover {
+               // We have made modifications to the package p being tested
+               // and are rebuilding p (as ptest), writing it to the testDir tree.
+               // Arrange to rebuild, writing to that same tree, all packages q
+               // such that the test depends on q, and q depends on p.
+               // This makes sure that q sees the modifications to p.
+               // Strictly speaking, the rebuild is only necessary if the
+               // modifications to p change its export metadata, but
+               // determining that is a bit tricky, so we rebuild always.
+               //
+               // This will cause extra compilation, so for now we only do it
+               // when testCover is set. The conditions are more general, though,
+               // and we may find that we need to do it always in the future.
+               recompileForTest(pmain, p, ptest, testDir)
+       }
+
+       for _, cp := range pmain.imports {
+               if len(cp.coverVars) > 0 {
+                       t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars})
+               }
+       }
+
+       // writeTestmain writes _testmain.go. This must happen after recompileForTest,
+       // because recompileForTest modifies XXX.
+       if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), t); err != nil {
+               return nil, nil, nil, err
+       }
+
+       computeStale(pmain)
+
+       if ptest != p {
+               a := b.action(modeBuild, modeBuild, ptest)
+               a.objdir = testDir + string(filepath.Separator) + "_obj_test" + string(filepath.Separator)
+               a.objpkg = ptestObj
+               a.target = ptestObj
+               a.link = false
+       }
+
+       if pxtest != nil {
+               a := b.action(modeBuild, modeBuild, pxtest)
+               a.objdir = testDir + string(filepath.Separator) + "_obj_xtest" + string(filepath.Separator)
+               a.objpkg = buildToolchain.pkgpath(testDir, pxtest)
+               a.target = a.objpkg
+       }
+
+       a := b.action(modeBuild, modeBuild, pmain)
+       a.objdir = testDir + string(filepath.Separator)
+       a.objpkg = filepath.Join(testDir, "main.a")
+       a.target = filepath.Join(testDir, testBinary) + exeSuffix
+       pmainAction := a
+
+       if testC || testNeedBinary {
+               // -c or profiling flag: create action to copy binary to ./test.out.
+               runAction = &action{
+                       f:      (*builder).install,
+                       deps:   []*action{pmainAction},
+                       p:      pmain,
+                       target: filepath.Join(cwd, testBinary+exeSuffix),
+               }
+               pmainAction = runAction // in case we are running the test
+       }
+       if testC {
+               printAction = &action{p: p, deps: []*action{runAction}} // nop
+       } else {
+               // run test
+               runAction = &action{
+                       f:          (*builder).runTest,
+                       deps:       []*action{pmainAction},
+                       p:          p,
+                       ignoreFail: true,
+               }
+               cleanAction := &action{
+                       f:    (*builder).cleanTest,
+                       deps: []*action{runAction},
+                       p:    p,
+               }
+               printAction = &action{
+                       f:    (*builder).printTest,
+                       deps: []*action{cleanAction},
+                       p:    p,
+               }
+       }
+
+       return pmainAction, runAction, printAction, nil
+}
+
+func testImportStack(top string, p *Package, target string) []string {
+       stk := []string{top, p.ImportPath}
+Search:
+       for p.ImportPath != target {
+               for _, p1 := range p.imports {
+                       if p1.ImportPath == target || contains(p1.Deps, target) {
+                               stk = append(stk, p1.ImportPath)
+                               p = p1
+                               continue Search
+                       }
+               }
+               // Can't happen, but in case it does...
+               stk = append(stk, "<lost path to cycle>")
+               break
+       }
+       return stk
+}
+
+func recompileForTest(pmain, preal, ptest *Package, testDir string) {
+       // The "test copy" of preal is ptest.
+       // For each package that depends on preal, make a "test copy"
+       // that depends on ptest. And so on, up the dependency tree.
+       testCopy := map[*Package]*Package{preal: ptest}
+       for _, p := range packageList([]*Package{pmain}) {
+               // Copy on write.
+               didSplit := false
+               split := func() {
+                       if didSplit {
+                               return
+                       }
+                       didSplit = true
+                       if p.pkgdir != testDir {
+                               p1 := new(Package)
+                               testCopy[p] = p1
+                               *p1 = *p
+                               p1.imports = make([]*Package, len(p.imports))
+                               copy(p1.imports, p.imports)
+                               p = p1
+                               p.pkgdir = testDir
+                               p.target = ""
+                               p.fake = true
+                               p.Stale = true
+                       }
+               }
+
+               // Update p.deps and p.imports to use at test copies.
+               for i, dep := range p.deps {
+                       if p1 := testCopy[dep]; p1 != nil && p1 != dep {
+                               split()
+                               p.deps[i] = p1
+                       }
+               }
+               for i, imp := range p.imports {
+                       if p1 := testCopy[imp]; p1 != nil && p1 != imp {
+                               split()
+                               p.imports[i] = p1
+                       }
+               }
+       }
+}
+
+var coverIndex = 0
+
+// isTestFile reports whether the source file is a set of tests and should therefore
+// be excluded from coverage analysis.
+func isTestFile(file string) bool {
+       // We don't cover tests, only the code they test.
+       return strings.HasSuffix(file, "_test.go")
+}
+
+// declareCoverVars attaches the required cover variables names
+// to the files, to be used when annotating the files.
+func declareCoverVars(importPath string, files ...string) map[string]*CoverVar {
+       coverVars := make(map[string]*CoverVar)
+       for _, file := range files {
+               if isTestFile(file) {
+                       continue
+               }
+               coverVars[file] = &CoverVar{
+                       File: filepath.Join(importPath, file),
+                       Var:  fmt.Sprintf("GoCover_%d", coverIndex),
+               }
+               coverIndex++
+       }
+       return coverVars
+}
+
+// runTest is the action for running a test binary.
+func (b *builder) runTest(a *action) error {
+       args := stringList(findExecCmd(), a.deps[0].target, testArgs)
+       a.testOutput = new(bytes.Buffer)
+
+       if buildN || buildX {
+               b.showcmd("", "%s", strings.Join(args, " "))
+               if buildN {
+                       return nil
+               }
+       }
+
+       if a.failed {
+               // We were unable to build the binary.
+               a.failed = false
+               fmt.Fprintf(a.testOutput, "FAIL\t%s [build failed]\n", a.p.ImportPath)
+               setExitStatus(1)
+               return nil
+       }
+
+       cmd := exec.Command(args[0], args[1:]...)
+       cmd.Dir = a.p.Dir
+       cmd.Env = envForDir(cmd.Dir)
+       var buf bytes.Buffer
+       if testStreamOutput {
+               cmd.Stdout = os.Stdout
+               cmd.Stderr = os.Stderr
+       } else {
+               cmd.Stdout = &buf
+               cmd.Stderr = &buf
+       }
+
+       // If there are any local SWIG dependencies, we want to load
+       // the shared library from the build directory.
+       if a.p.usesSwig() {
+               env := cmd.Env
+               found := false
+               prefix := "LD_LIBRARY_PATH="
+               for i, v := range env {
+                       if strings.HasPrefix(v, prefix) {
+                               env[i] = v + ":."
+                               found = true
+                               break
+                       }
+               }
+               if !found {
+                       env = append(env, "LD_LIBRARY_PATH=.")
+               }
+               cmd.Env = env
+       }
+
+       t0 := time.Now()
+       err := cmd.Start()
+
+       // This is a last-ditch deadline to detect and
+       // stop wedged test binaries, to keep the builders
+       // running.
+       if err == nil {
+               tick := time.NewTimer(testKillTimeout)
+               startSigHandlers()
+               done := make(chan error)
+               go func() {
+                       done <- cmd.Wait()
+               }()
+       Outer:
+               select {
+               case err = <-done:
+                       // ok
+               case <-tick.C:
+                       if signalTrace != nil {
+                               // Send a quit signal in the hope that the program will print
+                               // a stack trace and exit. Give it five seconds before resorting
+                               // to Kill.
+                               cmd.Process.Signal(signalTrace)
+                               select {
+                               case err = <-done:
+                                       fmt.Fprintf(&buf, "*** Test killed with %v: ran too long (%v).\n", signalTrace, testKillTimeout)
+                                       break Outer
+                               case <-time.After(5 * time.Second):
+                               }
+                       }
+                       cmd.Process.Kill()
+                       err = <-done
+                       fmt.Fprintf(&buf, "*** Test killed: ran too long (%v).\n", testKillTimeout)
+               }
+               tick.Stop()
+       }
+       out := buf.Bytes()
+       t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
+       if err == nil {
+               if testShowPass {
+                       a.testOutput.Write(out)
+               }
+               fmt.Fprintf(a.testOutput, "ok  \t%s\t%s%s\n", a.p.ImportPath, t, coveragePercentage(out))
+               return nil
+       }
+
+       setExitStatus(1)
+       if len(out) > 0 {
+               a.testOutput.Write(out)
+               // assume printing the test binary's exit status is superfluous
+       } else {
+               fmt.Fprintf(a.testOutput, "%s\n", err)
+       }
+       fmt.Fprintf(a.testOutput, "FAIL\t%s\t%s\n", a.p.ImportPath, t)
+
+       return nil
+}
+
+// coveragePercentage returns the coverage results (if enabled) for the
+// test. It uncovers the data by scanning the output from the test run.
+func coveragePercentage(out []byte) string {
+       if !testCover {
+               return ""
+       }
+       // The string looks like
+       //      test coverage for encoding/binary: 79.9% of statements
+       // Extract the piece from the percentage to the end of the line.
+       re := regexp.MustCompile(`coverage: (.*)\n`)
+       matches := re.FindSubmatch(out)
+       if matches == nil {
+               // Probably running "go test -cover" not "go test -cover fmt".
+               // The coverage output will appear in the output directly.
+               return ""
+       }
+       return fmt.Sprintf("\tcoverage: %s", matches[1])
+}
+
+// cleanTest is the action for cleaning up after a test.
+func (b *builder) cleanTest(a *action) error {
+       if buildWork {
+               return nil
+       }
+       run := a.deps[0]
+       testDir := filepath.Join(b.work, filepath.FromSlash(run.p.ImportPath+"/_test"))
+       os.RemoveAll(testDir)
+       return nil
+}
+
+// printTest is the action for printing a test result.
+func (b *builder) printTest(a *action) error {
+       clean := a.deps[0]
+       run := clean.deps[0]
+       os.Stdout.Write(run.testOutput.Bytes())
+       run.testOutput = nil
+       return nil
+}
+
+// notest is the action for testing a package with no test files.
+func (b *builder) notest(a *action) error {
+       fmt.Printf("?   \t%s\t[no test files]\n", a.p.ImportPath)
+       return nil
+}
+
+// isTest tells whether name looks like a test (or benchmark, according to prefix).
+// It is a Test (say) if there is a character after Test that is not a lower-case letter.
+// We don't want TesticularCancer.
+func isTest(name, prefix string) bool {
+       if !strings.HasPrefix(name, prefix) {
+               return false
+       }
+       if len(name) == len(prefix) { // "Test" is ok
+               return true
+       }
+       rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+       return !unicode.IsLower(rune)
+}
+
+type coverInfo struct {
+       Package *Package
+       Vars    map[string]*CoverVar
+}
+
+// loadTestFuncs returns the testFuncs describing the tests that will be run.
+func loadTestFuncs(ptest *Package) (*testFuncs, error) {
+       t := &testFuncs{
+               Package: ptest,
+       }
+       for _, file := range ptest.TestGoFiles {
+               if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.NeedTest); err != nil {
+                       return nil, err
+               }
+       }
+       for _, file := range ptest.XTestGoFiles {
+               if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.NeedXtest); err != nil {
+                       return nil, err
+               }
+       }
+       return t, nil
+}
+
+// writeTestmain writes the _testmain.go file for t to the file named out.
+func writeTestmain(out string, t *testFuncs) error {
+       f, err := os.Create(out)
+       if err != nil {
+               return err
+       }
+       defer f.Close()
+
+       if err := testmainTmpl.Execute(f, t); err != nil {
+               return err
+       }
+
+       return nil
+}
+
+type testFuncs struct {
+       Tests      []testFunc
+       Benchmarks []testFunc
+       Examples   []testFunc
+       Package    *Package
+       NeedTest   bool
+       NeedXtest  bool
+       Cover      []coverInfo
+}
+
+func (t *testFuncs) CoverMode() string {
+       return testCoverMode
+}
+
+func (t *testFuncs) CoverEnabled() bool {
+       return testCover
+}
+
+// Covered returns a string describing which packages are being tested for coverage.
+// If the covered package is the same as the tested package, it returns the empty string.
+// Otherwise it is a comma-separated human-readable list of packages beginning with
+// " in", ready for use in the coverage message.
+func (t *testFuncs) Covered() string {
+       if testCoverPaths == nil {
+               return ""
+       }
+       return " in " + strings.Join(testCoverPaths, ", ")
+}
+
+// Tested returns the name of the package being tested.
+func (t *testFuncs) Tested() string {
+       return t.Package.Name
+}
+
+type testFunc struct {
+       Package string // imported package name (_test or _xtest)
+       Name    string // function name
+       Output  string // output, for examples
+}
+
+var testFileSet = token.NewFileSet()
+
+func (t *testFuncs) load(filename, pkg string, seen *bool) error {
+       f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
+       if err != nil {
+               return expandScanner(err)
+       }
+       for _, d := range f.Decls {
+               n, ok := d.(*ast.FuncDecl)
+               if !ok {
+                       continue
+               }
+               if n.Recv != nil {
+                       continue
+               }
+               name := n.Name.String()
+               switch {
+               case isTest(name, "Test"):
+                       t.Tests = append(t.Tests, testFunc{pkg, name, ""})
+                       *seen = true
+               case isTest(name, "Benchmark"):
+                       t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""})
+                       *seen = true
+               }
+       }
+       ex := doc.Examples(f)
+       sort.Sort(byOrder(ex))
+       for _, e := range ex {
+               if e.Output == "" && !e.EmptyOutput {
+                       // Don't run examples with no output.
+                       continue
+               }
+               t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output})
+               *seen = true
+       }
+       return nil
+}
+
+type byOrder []*doc.Example
+
+func (x byOrder) Len() int           { return len(x) }
+func (x byOrder) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x byOrder) Less(i, j int) bool { return x[i].Order < x[j].Order }
+
+var testmainTmpl = template.Must(template.New("main").Parse(`
+package main
+
+import (
+       "regexp"
+       "testing"
+
+{{if .NeedTest}}
+       _test {{.Package.ImportPath | printf "%q"}}
+{{end}}
+{{if .NeedXtest}}
+       _xtest {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
+{{end}}
+{{range $i, $p := .Cover}}
+       _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
+{{end}}
+)
+
+var tests = []testing.InternalTest{
+{{range .Tests}}
+       {"{{.Name}}", {{.Package}}.{{.Name}}},
+{{end}}
+}
+
+var benchmarks = []testing.InternalBenchmark{
+{{range .Benchmarks}}
+       {"{{.Name}}", {{.Package}}.{{.Name}}},
+{{end}}
+}
+
+var examples = []testing.InternalExample{
+{{range .Examples}}
+       {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}},
+{{end}}
+}
+
+var matchPat string
+var matchRe *regexp.Regexp
+
+func matchString(pat, str string) (result bool, err error) {
+       if matchRe == nil || matchPat != pat {
+               matchPat = pat
+               matchRe, err = regexp.Compile(matchPat)
+               if err != nil {
+                       return
+               }
+       }
+       return matchRe.MatchString(str), nil
+}
+
+{{if .CoverEnabled}}
+
+// Only updated by init functions, so no need for atomicity.
+var (
+       coverCounters = make(map[string][]uint32)
+       coverBlocks = make(map[string][]testing.CoverBlock)
+)
+
+func init() {
+       {{range $i, $p := .Cover}}
+       {{range $file, $cover := $p.Vars}}
+       coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:])
+       {{end}}
+       {{end}}
+}
+
+func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) {
+       if 3*len(counter) != len(pos) || len(counter) != len(numStmts) {
+               panic("coverage: mismatched sizes")
+       }
+       if coverCounters[fileName] != nil {
+               // Already registered.
+               return
+       }
+       coverCounters[fileName] = counter
+       block := make([]testing.CoverBlock, len(counter))
+       for i := range counter {
+               block[i] = testing.CoverBlock{
+                       Line0: pos[3*i+0],
+                       Col0: uint16(pos[3*i+2]),
+                       Line1: pos[3*i+1],
+                       Col1: uint16(pos[3*i+2]>>16),
+                       Stmts: numStmts[i],
+               }
+       }
+       coverBlocks[fileName] = block
+}
+{{end}}
+
+func main() {
+{{if .CoverEnabled}}
+       testing.RegisterCover(testing.Cover{
+               Mode: {{printf "%q" .CoverMode}},
+               Counters: coverCounters,
+               Blocks: coverBlocks,
+               CoveredPackages: {{printf "%q" .Covered}},
+       })
+{{end}}
+       testing.Main(matchString, tests, benchmarks, examples)
+}
+
+`))
diff --git a/libgo/go/cmd/go/testdata/cgocover/p.go b/libgo/go/cmd/go/testdata/cgocover/p.go
new file mode 100644 (file)
index 0000000..a6a3891
--- /dev/null
@@ -0,0 +1,19 @@
+package p
+
+/*
+void
+f(void)
+{
+}
+*/
+import "C"
+
+var b bool
+
+func F() {
+       if b {
+               for {
+               }
+       }
+       C.f()
+}
diff --git a/libgo/go/cmd/go/testdata/cgocover/p_test.go b/libgo/go/cmd/go/testdata/cgocover/p_test.go
new file mode 100644 (file)
index 0000000..a8f057e
--- /dev/null
@@ -0,0 +1,7 @@
+package p
+
+import "testing"
+
+func TestF(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/dep_test.go b/libgo/go/cmd/go/testdata/dep_test.go
new file mode 100644 (file)
index 0000000..0c53ac4
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2014 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 deps
+
+import _ "testing"
diff --git a/libgo/go/cmd/go/testdata/example1_test.go b/libgo/go/cmd/go/testdata/example1_test.go
new file mode 100644 (file)
index 0000000..ec7092e
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2013 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.
+
+// Make sure that go test runs Example_Z before Example_A, preserving source order.
+
+package p
+
+import "fmt"
+
+var n int
+
+func Example_Z() {
+       n++
+       fmt.Println(n)
+       // Output: 1
+}
+
+func Example_A() {
+       n++
+       fmt.Println(n)
+       // Output: 2
+}
diff --git a/libgo/go/cmd/go/testdata/example2_test.go b/libgo/go/cmd/go/testdata/example2_test.go
new file mode 100644 (file)
index 0000000..1e0e80b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2013 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.
+
+// Make sure that go test runs Example_Y before Example_B, preserving source order.
+
+package p
+
+import "fmt"
+
+func Example_Y() {
+       n++
+       fmt.Println(n)
+       // Output: 3
+}
+
+func Example_B() {
+       n++
+       fmt.Println(n)
+       // Output: 4
+}
diff --git a/libgo/go/cmd/go/testdata/local/easy.go b/libgo/go/cmd/go/testdata/local/easy.go
new file mode 100644 (file)
index 0000000..4eeb517
--- /dev/null
@@ -0,0 +1,7 @@
+package main
+
+import "./easysub"
+
+func main() {
+       easysub.Hello()
+}
diff --git a/libgo/go/cmd/go/testdata/local/easysub/easysub.go b/libgo/go/cmd/go/testdata/local/easysub/easysub.go
new file mode 100644 (file)
index 0000000..07040da
--- /dev/null
@@ -0,0 +1,7 @@
+package easysub
+
+import "fmt"
+
+func Hello() {
+       fmt.Println("easysub.Hello")
+}
diff --git a/libgo/go/cmd/go/testdata/local/easysub/main.go b/libgo/go/cmd/go/testdata/local/easysub/main.go
new file mode 100644 (file)
index 0000000..6c30b52
--- /dev/null
@@ -0,0 +1,9 @@
+// +build ignore
+
+package main
+
+import "."
+
+func main() {
+       easysub.Hello()
+}
diff --git a/libgo/go/cmd/go/testdata/local/hard.go b/libgo/go/cmd/go/testdata/local/hard.go
new file mode 100644 (file)
index 0000000..2ffac3f
--- /dev/null
@@ -0,0 +1,7 @@
+package main
+
+import "./sub"
+
+func main() {
+       sub.Hello()
+}
diff --git a/libgo/go/cmd/go/testdata/local/sub/sub.go b/libgo/go/cmd/go/testdata/local/sub/sub.go
new file mode 100644 (file)
index 0000000..d5dbf6d
--- /dev/null
@@ -0,0 +1,12 @@
+package sub
+
+import (
+       "fmt"
+
+       subsub "./sub"
+)
+
+func Hello() {
+       fmt.Println("sub.Hello")
+       subsub.Hello()
+}
diff --git a/libgo/go/cmd/go/testdata/local/sub/sub/subsub.go b/libgo/go/cmd/go/testdata/local/sub/sub/subsub.go
new file mode 100644 (file)
index 0000000..4cc7223
--- /dev/null
@@ -0,0 +1,7 @@
+package subsub
+
+import "fmt"
+
+func Hello() {
+       fmt.Println("subsub.Hello")
+}
diff --git a/libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go b/libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go
new file mode 100644 (file)
index 0000000..f52652b
--- /dev/null
@@ -0,0 +1 @@
+package foo
diff --git a/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go b/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go
new file mode 100644 (file)
index 0000000..c91c24e
--- /dev/null
@@ -0,0 +1 @@
+package math
diff --git a/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go b/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go
new file mode 100644 (file)
index 0000000..f52652b
--- /dev/null
@@ -0,0 +1 @@
+package foo
diff --git a/libgo/go/cmd/go/testdata/src/badpkg/x.go b/libgo/go/cmd/go/testdata/src/badpkg/x.go
new file mode 100644 (file)
index 0000000..dda35e8
--- /dev/null
@@ -0,0 +1 @@
+pkg badpkg
diff --git a/libgo/go/cmd/go/testdata/src/cgotest/m.go b/libgo/go/cmd/go/testdata/src/cgotest/m.go
new file mode 100644 (file)
index 0000000..4d68307
--- /dev/null
@@ -0,0 +1,5 @@
+package cgotest
+
+import "C"
+
+var _ C.int
diff --git a/libgo/go/cmd/go/testdata/src/go-cmd-test/helloworld.go b/libgo/go/cmd/go/testdata/src/go-cmd-test/helloworld.go
new file mode 100644 (file)
index 0000000..002a5c7
--- /dev/null
@@ -0,0 +1,5 @@
+package main
+
+func main() {
+       println("hello world")
+}
diff --git a/libgo/go/cmd/go/testdata/src/main_test/m.go b/libgo/go/cmd/go/testdata/src/main_test/m.go
new file mode 100644 (file)
index 0000000..c682f03
--- /dev/null
@@ -0,0 +1,4 @@
+package main
+
+func F()    {}
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/src/main_test/m_test.go b/libgo/go/cmd/go/testdata/src/main_test/m_test.go
new file mode 100644 (file)
index 0000000..f865b77
--- /dev/null
@@ -0,0 +1,10 @@
+package main_test
+
+import (
+       . "main_test"
+       "testing"
+)
+
+func Test1(t *testing.T) {
+       F()
+}
diff --git a/libgo/go/cmd/go/testdata/src/notest/hello.go b/libgo/go/cmd/go/testdata/src/notest/hello.go
new file mode 100644 (file)
index 0000000..7c42c32
--- /dev/null
@@ -0,0 +1,6 @@
+package notest
+
+func hello() {
+       println("hello world")
+}
+Hello world
diff --git a/libgo/go/cmd/go/testdata/src/syntaxerror/x.go b/libgo/go/cmd/go/testdata/src/syntaxerror/x.go
new file mode 100644 (file)
index 0000000..c89cd18
--- /dev/null
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go b/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go
new file mode 100644 (file)
index 0000000..2460743
--- /dev/null
@@ -0,0 +1,4 @@
+package p
+
+func f() (x.y, z int) {
+}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go
new file mode 100644 (file)
index 0000000..65ab76d
--- /dev/null
@@ -0,0 +1,7 @@
+package p1
+
+import _ "testcycle/p2"
+
+func init() {
+       println("p1 init")
+}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go
new file mode 100644 (file)
index 0000000..75abb13
--- /dev/null
@@ -0,0 +1,6 @@
+package p1
+
+import "testing"
+
+func Test(t *testing.T) {
+}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go b/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go
new file mode 100644 (file)
index 0000000..7e26cdf
--- /dev/null
@@ -0,0 +1,7 @@
+package p2
+
+import _ "testcycle/p3"
+
+func init() {
+       println("p2 init")
+}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go
new file mode 100644 (file)
index 0000000..bb0a2f4
--- /dev/null
@@ -0,0 +1,5 @@
+package p3
+
+func init() {
+       println("p3 init")
+}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go
new file mode 100644 (file)
index 0000000..9b4b075
--- /dev/null
@@ -0,0 +1,10 @@
+package p3
+
+import (
+       "testing"
+
+       _ "testcycle/p1"
+)
+
+func Test(t *testing.T) {
+}
diff --git a/libgo/go/cmd/go/testdata/src/xtestonly/f.go b/libgo/go/cmd/go/testdata/src/xtestonly/f.go
new file mode 100644 (file)
index 0000000..dac039e
--- /dev/null
@@ -0,0 +1,3 @@
+package xtestonly
+
+func F() int { return 42 }
diff --git a/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go b/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go
new file mode 100644 (file)
index 0000000..01f6e83
--- /dev/null
@@ -0,0 +1,12 @@
+package xtestonly_test
+
+import (
+       "testing"
+       "xtestonly"
+)
+
+func TestF(t *testing.T) {
+       if x := xtestonly.F(); x != 42 {
+               t.Errorf("f.F() = %d, want 42", x)
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/standalone_test.go b/libgo/go/cmd/go/testdata/standalone_test.go
new file mode 100644 (file)
index 0000000..59cf918
--- /dev/null
@@ -0,0 +1,6 @@
+package standalone_test
+
+import "testing"
+
+func Test(t *testing.T) {
+}
diff --git a/libgo/go/cmd/go/testdata/testimport/p.go b/libgo/go/cmd/go/testdata/testimport/p.go
new file mode 100644 (file)
index 0000000..f94d2cd
--- /dev/null
@@ -0,0 +1,3 @@
+package p
+
+func F() int { return 1 }
diff --git a/libgo/go/cmd/go/testdata/testimport/p1/p1.go b/libgo/go/cmd/go/testdata/testimport/p1/p1.go
new file mode 100644 (file)
index 0000000..fd31527
--- /dev/null
@@ -0,0 +1,3 @@
+package p1
+
+func F() int { return 1 }
diff --git a/libgo/go/cmd/go/testdata/testimport/p2/p2.go b/libgo/go/cmd/go/testdata/testimport/p2/p2.go
new file mode 100644 (file)
index 0000000..d488886
--- /dev/null
@@ -0,0 +1,3 @@
+package p2
+
+func F() int { return 1 }
diff --git a/libgo/go/cmd/go/testdata/testimport/p_test.go b/libgo/go/cmd/go/testdata/testimport/p_test.go
new file mode 100644 (file)
index 0000000..a3fb4a9
--- /dev/null
@@ -0,0 +1,13 @@
+package p
+
+import (
+       "./p1"
+
+       "testing"
+)
+
+func TestF(t *testing.T) {
+       if F() != p1.F() {
+               t.Fatal(F())
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/testimport/x_test.go b/libgo/go/cmd/go/testdata/testimport/x_test.go
new file mode 100644 (file)
index 0000000..b253e3f
--- /dev/null
@@ -0,0 +1,15 @@
+package p_test
+
+import (
+       . "../testimport"
+
+       "./p2"
+
+       "testing"
+)
+
+func TestF1(t *testing.T) {
+       if F() != p2.F() {
+               t.Fatal(F())
+       }
+}
diff --git a/libgo/go/cmd/go/testdata/testonly/p_test.go b/libgo/go/cmd/go/testdata/testonly/p_test.go
new file mode 100644 (file)
index 0000000..c89cd18
--- /dev/null
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testflag.go b/libgo/go/cmd/go/testflag.go
new file mode 100644 (file)
index 0000000..73f311e
--- /dev/null
@@ -0,0 +1,318 @@
+// 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 (
+       "fmt"
+       "os"
+       "strconv"
+       "strings"
+)
+
+// The flag handling part of go test is large and distracting.
+// We can't use the flag package because some of the flags from
+// our command line are for us, and some are for 6.out, and
+// some are for both.
+
+var usageMessage = `Usage of go test:
+  -c=false: compile but do not run the test binary
+  -file=file_test.go: specify file to use for tests;
+      use multiple times for multiple files
+  -p=n: build and test up to n packages in parallel
+  -x=false: print command lines as they are executed
+
+  // These flags can be passed with or without a "test." prefix: -v or -test.v.
+  -bench="": passes -test.bench to test
+  -benchmem=false: print memory allocation statistics for benchmarks
+  -benchtime=1s: passes -test.benchtime to test
+  -cover=false: enable coverage analysis
+  -covermode="set": specifies mode for coverage analysis
+  -coverpkg="": comma-separated list of packages for coverage analysis
+  -coverprofile="": passes -test.coverprofile to test if -cover
+  -cpu="": passes -test.cpu to test
+  -cpuprofile="": passes -test.cpuprofile to test
+  -memprofile="": passes -test.memprofile to test
+  -memprofilerate=0: passes -test.memprofilerate to test
+  -blockprofile="": pases -test.blockprofile to test
+  -blockprofilerate=0: passes -test.blockprofilerate to test
+  -outputdir=$PWD: passes -test.outputdir to test
+  -parallel=0: passes -test.parallel to test
+  -run="": passes -test.run to test
+  -short=false: passes -test.short to test
+  -timeout=0: passes -test.timeout to test
+  -v=false: passes -test.v to test
+`
+
+// usage prints a usage message and exits.
+func testUsage() {
+       fmt.Fprint(os.Stderr, usageMessage)
+       setExitStatus(2)
+       exit()
+}
+
+// testFlagSpec defines a flag we know about.
+type testFlagSpec struct {
+       name       string
+       boolVar    *bool
+       passToTest bool // pass to Test
+       multiOK    bool // OK to have multiple instances
+       present    bool // flag has been seen
+}
+
+// testFlagDefn is the set of flags we process.
+var testFlagDefn = []*testFlagSpec{
+       // local.
+       {name: "c", boolVar: &testC},
+       {name: "file", multiOK: true},
+       {name: "cover", boolVar: &testCover},
+       {name: "coverpkg"},
+
+       // build flags.
+       {name: "a", boolVar: &buildA},
+       {name: "n", boolVar: &buildN},
+       {name: "p"},
+       {name: "x", boolVar: &buildX},
+       {name: "i", boolVar: &buildI},
+       {name: "work", boolVar: &buildWork},
+       {name: "ccflags"},
+       {name: "gcflags"},
+       {name: "exec"},
+       {name: "ldflags"},
+       {name: "gccgoflags"},
+       {name: "tags"},
+       {name: "compiler"},
+       {name: "race", boolVar: &buildRace},
+       {name: "installsuffix"},
+
+       // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
+       {name: "bench", passToTest: true},
+       {name: "benchmem", boolVar: new(bool), passToTest: true},
+       {name: "benchtime", passToTest: true},
+       {name: "covermode"},
+       {name: "coverprofile", passToTest: true},
+       {name: "cpu", passToTest: true},
+       {name: "cpuprofile", passToTest: true},
+       {name: "memprofile", passToTest: true},
+       {name: "memprofilerate", passToTest: true},
+       {name: "blockprofile", passToTest: true},
+       {name: "blockprofilerate", passToTest: true},
+       {name: "outputdir", passToTest: true},
+       {name: "parallel", passToTest: true},
+       {name: "run", passToTest: true},
+       {name: "short", boolVar: new(bool), passToTest: true},
+       {name: "timeout", passToTest: true},
+       {name: "v", boolVar: &testV, passToTest: true},
+}
+
+// testFlags processes the command line, grabbing -x and -c, rewriting known flags
+// to have "test" before them, and reading the command line for the 6.out.
+// Unfortunately for us, we need to do our own flag processing because go test
+// grabs some flags but otherwise its command line is just a holding place for
+// pkg.test's arguments.
+// We allow known flags both before and after the package name list,
+// to allow both
+//     go test fmt -custom-flag-for-fmt-test
+//     go test -x math
+func testFlags(args []string) (packageNames, passToTest []string) {
+       inPkg := false
+       outputDir := ""
+       for i := 0; i < len(args); i++ {
+               if !strings.HasPrefix(args[i], "-") {
+                       if !inPkg && packageNames == nil {
+                               // First package name we've seen.
+                               inPkg = true
+                       }
+                       if inPkg {
+                               packageNames = append(packageNames, args[i])
+                               continue
+                       }
+               }
+
+               if inPkg {
+                       // Found an argument beginning with "-"; end of package list.
+                       inPkg = false
+               }
+
+               f, value, extraWord := testFlag(args, i)
+               if f == nil {
+                       // This is a flag we do not know; we must assume
+                       // that any args we see after this might be flag
+                       // arguments, not package names.
+                       inPkg = false
+                       if packageNames == nil {
+                               // make non-nil: we have seen the empty package list
+                               packageNames = []string{}
+                       }
+                       passToTest = append(passToTest, args[i])
+                       continue
+               }
+               var err error
+               switch f.name {
+               // bool flags.
+               case "a", "c", "i", "n", "x", "v", "race", "cover", "work":
+                       setBoolFlag(f.boolVar, value)
+               case "p":
+                       setIntFlag(&buildP, value)
+               case "exec":
+                       execCmd, err = splitQuotedFields(value)
+                       if err != nil {
+                               fatalf("invalid flag argument for -%s: %v", f.name, err)
+                       }
+               case "ccflags":
+                       buildCcflags, err = splitQuotedFields(value)
+                       if err != nil {
+                               fatalf("invalid flag argument for -%s: %v", f.name, err)
+                       }
+               case "gcflags":
+                       buildGcflags, err = splitQuotedFields(value)
+                       if err != nil {
+                               fatalf("invalid flag argument for -%s: %v", f.name, err)
+                       }
+               case "ldflags":
+                       buildLdflags, err = splitQuotedFields(value)
+                       if err != nil {
+                               fatalf("invalid flag argument for -%s: %v", f.name, err)
+                       }
+               case "gccgoflags":
+                       buildGccgoflags, err = splitQuotedFields(value)
+                       if err != nil {
+                               fatalf("invalid flag argument for -%s: %v", f.name, err)
+                       }
+               case "tags":
+                       buildContext.BuildTags = strings.Fields(value)
+               case "compiler":
+                       buildCompiler{}.Set(value)
+               case "file":
+                       testFiles = append(testFiles, value)
+               case "bench":
+                       // record that we saw the flag; don't care about the value
+                       testBench = true
+               case "timeout":
+                       testTimeout = value
+               case "blockprofile", "cpuprofile", "memprofile":
+                       testProfile = true
+                       testNeedBinary = true
+               case "coverpkg":
+                       testCover = true
+                       if value == "" {
+                               testCoverPaths = nil
+                       } else {
+                               testCoverPaths = strings.Split(value, ",")
+                       }
+               case "coverprofile":
+                       testCover = true
+                       testProfile = true
+               case "covermode":
+                       switch value {
+                       case "set", "count", "atomic":
+                               testCoverMode = value
+                       default:
+                               fatalf("invalid flag argument for -cover: %q", value)
+                       }
+                       testCover = true
+               case "outputdir":
+                       outputDir = value
+               }
+               if extraWord {
+                       i++
+               }
+               if f.passToTest {
+                       passToTest = append(passToTest, "-test."+f.name+"="+value)
+               }
+       }
+
+       if testCoverMode == "" {
+               testCoverMode = "set"
+               if buildRace {
+                       // Default coverage mode is atomic when -race is set.
+                       testCoverMode = "atomic"
+               }
+       }
+
+       // Tell the test what directory we're running in, so it can write the profiles there.
+       if testProfile && outputDir == "" {
+               dir, err := os.Getwd()
+               if err != nil {
+                       fatalf("error from os.Getwd: %s", err)
+               }
+               passToTest = append(passToTest, "-test.outputdir", dir)
+       }
+       return
+}
+
+// testFlag sees if argument i is a known flag and returns its definition, value, and whether it consumed an extra word.
+func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool) {
+       arg := args[i]
+       if strings.HasPrefix(arg, "--") { // reduce two minuses to one
+               arg = arg[1:]
+       }
+       switch arg {
+       case "-?", "-h", "-help":
+               usage()
+       }
+       if arg == "" || arg[0] != '-' {
+               return
+       }
+       name := arg[1:]
+       // If there's already "test.", drop it for now.
+       name = strings.TrimPrefix(name, "test.")
+       equals := strings.Index(name, "=")
+       if equals >= 0 {
+               value = name[equals+1:]
+               name = name[:equals]
+       }
+       for _, f = range testFlagDefn {
+               if name == f.name {
+                       // Booleans are special because they have modes -x, -x=true, -x=false.
+                       if f.boolVar != nil {
+                               if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag
+                                       value = "true"
+                               } else {
+                                       // verify it parses
+                                       setBoolFlag(new(bool), value)
+                               }
+                       } else { // Non-booleans must have a value.
+                               extra = equals < 0
+                               if extra {
+                                       if i+1 >= len(args) {
+                                               testSyntaxError("missing argument for flag " + f.name)
+                                       }
+                                       value = args[i+1]
+                               }
+                       }
+                       if f.present && !f.multiOK {
+                               testSyntaxError(f.name + " flag may be set only once")
+                       }
+                       f.present = true
+                       return
+               }
+       }
+       f = nil
+       return
+}
+
+// setBoolFlag sets the addressed boolean to the value.
+func setBoolFlag(flag *bool, value string) {
+       x, err := strconv.ParseBool(value)
+       if err != nil {
+               testSyntaxError("illegal bool flag value " + value)
+       }
+       *flag = x
+}
+
+// setIntFlag sets the addressed integer to the value.
+func setIntFlag(flag *int, value string) {
+       x, err := strconv.Atoi(value)
+       if err != nil {
+               testSyntaxError("illegal int flag value " + value)
+       }
+       *flag = x
+}
+
+func testSyntaxError(msg string) {
+       fmt.Fprintf(os.Stderr, "go test: %s\n", msg)
+       fmt.Fprintf(os.Stderr, `run "go help test" or "go help testflag" for more information`+"\n")
+       os.Exit(2)
+}
diff --git a/libgo/go/cmd/go/tool.go b/libgo/go/cmd/go/tool.go
new file mode 100644 (file)
index 0000000..6d26f7a
--- /dev/null
@@ -0,0 +1,156 @@
+// 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 (
+       "fmt"
+       "go/build"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "sort"
+       "strings"
+)
+
+var cmdTool = &Command{
+       Run:       runTool,
+       UsageLine: "tool [-n] command [args...]",
+       Short:     "run specified go tool",
+       Long: `
+Tool runs the go tool command identified by the arguments.
+With no arguments it prints the list of known tools.
+
+The -n flag causes tool to print the command that would be
+executed but not execute it.
+
+For more about each tool command, see 'go tool command -h'.
+`,
+}
+
+var (
+       toolGOOS      = runtime.GOOS
+       toolGOARCH    = runtime.GOARCH
+       toolIsWindows = toolGOOS == "windows"
+       toolDir       = build.ToolDir
+
+       toolN bool
+)
+
+func init() {
+       cmdTool.Flag.BoolVar(&toolN, "n", false, "")
+}
+
+const toolWindowsExtension = ".exe"
+
+func tool(toolName string) string {
+       toolPath := filepath.Join(toolDir, toolName)
+       if toolIsWindows && toolName != "pprof" {
+               toolPath += toolWindowsExtension
+       }
+       // Give a nice message if there is no tool with that name.
+       if _, err := os.Stat(toolPath); err != nil {
+               if isInGoToolsRepo(toolName) {
+                       fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get code.google.com/p/go.tools/cmd/%s\n", toolName, toolName)
+               } else {
+                       fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
+               }
+               setExitStatus(3)
+               exit()
+       }
+       return toolPath
+}
+
+func isInGoToolsRepo(toolName string) bool {
+       switch toolName {
+       case "cover", "vet":
+               return true
+       }
+       return false
+}
+
+func runTool(cmd *Command, args []string) {
+       if len(args) == 0 {
+               listTools()
+               return
+       }
+       toolName := args[0]
+       // The tool name must be lower-case letters, numbers or underscores.
+       for _, c := range toolName {
+               switch {
+               case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
+               default:
+                       fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
+                       setExitStatus(2)
+                       return
+               }
+       }
+       toolPath := tool(toolName)
+       if toolPath == "" {
+               return
+       }
+       if toolIsWindows && toolName == "pprof" {
+               args = append([]string{"perl", toolPath}, args[1:]...)
+               var err error
+               toolPath, err = exec.LookPath("perl")
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
+                       setExitStatus(3)
+                       return
+               }
+       }
+       if toolN {
+               fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
+               return
+       }
+       toolCmd := &exec.Cmd{
+               Path:   toolPath,
+               Args:   args,
+               Stdin:  os.Stdin,
+               Stdout: os.Stdout,
+               Stderr: os.Stderr,
+       }
+       err := toolCmd.Run()
+       if err != nil {
+               // Only print about the exit status if the command
+               // didn't even run (not an ExitError) or it didn't exit cleanly
+               // or we're printing command lines too (-x mode).
+               // Assume if command exited cleanly (even with non-zero status)
+               // it printed any messages it wanted to print.
+               if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
+                       fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
+               }
+               setExitStatus(1)
+               return
+       }
+}
+
+// listTools prints a list of the available tools in the tools directory.
+func listTools() {
+       f, err := os.Open(toolDir)
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
+               setExitStatus(2)
+               return
+       }
+       defer f.Close()
+       names, err := f.Readdirnames(-1)
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
+               setExitStatus(2)
+               return
+       }
+
+       sort.Strings(names)
+       for _, name := range names {
+               // Unify presentation by going to lower case.
+               name = strings.ToLower(name)
+               // If it's windows, don't show the .exe suffix.
+               if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
+                       name = name[:len(name)-len(toolWindowsExtension)]
+               }
+               fmt.Println(name)
+       }
+}
diff --git a/libgo/go/cmd/go/vcs.go b/libgo/go/cmd/go/vcs.go
new file mode 100644 (file)
index 0000000..8f0bae0
--- /dev/null
@@ -0,0 +1,728 @@
+// 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 main
+
+import (
+       "bytes"
+       "encoding/json"
+       "errors"
+       "fmt"
+       "log"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "regexp"
+       "strings"
+)
+
+// A vcsCmd describes how to use a version control system
+// like Mercurial, Git, or Subversion.
+type vcsCmd struct {
+       name string
+       cmd  string // name of binary to invoke command
+
+       createCmd   string // command to download a fresh copy of a repository
+       downloadCmd string // command to download updates into an existing repository
+
+       tagCmd         []tagCmd // commands to list tags
+       tagLookupCmd   []tagCmd // commands to lookup tags before running tagSyncCmd
+       tagSyncCmd     string   // command to sync to specific tag
+       tagSyncDefault string   // command to sync to default tag
+
+       scheme  []string
+       pingCmd string
+}
+
+// A tagCmd describes a command to list available tags
+// that can be passed to tagSyncCmd.
+type tagCmd struct {
+       cmd     string // command to list tags
+       pattern string // regexp to extract tags from list
+}
+
+// vcsList lists the known version control systems
+var vcsList = []*vcsCmd{
+       vcsHg,
+       vcsGit,
+       vcsSvn,
+       vcsBzr,
+}
+
+// vcsByCmd returns the version control system for the given
+// command name (hg, git, svn, bzr).
+func vcsByCmd(cmd string) *vcsCmd {
+       for _, vcs := range vcsList {
+               if vcs.cmd == cmd {
+                       return vcs
+               }
+       }
+       return nil
+}
+
+// vcsHg describes how to use Mercurial.
+var vcsHg = &vcsCmd{
+       name: "Mercurial",
+       cmd:  "hg",
+
+       createCmd:   "clone -U {repo} {dir}",
+       downloadCmd: "pull",
+
+       // We allow both tag and branch names as 'tags'
+       // for selecting a version.  This lets people have
+       // a go.release.r60 branch and a go1 branch
+       // and make changes in both, without constantly
+       // editing .hgtags.
+       tagCmd: []tagCmd{
+               {"tags", `^(\S+)`},
+               {"branches", `^(\S+)`},
+       },
+       tagSyncCmd:     "update -r {tag}",
+       tagSyncDefault: "update default",
+
+       scheme:  []string{"https", "http", "ssh"},
+       pingCmd: "identify {scheme}://{repo}",
+}
+
+// vcsGit describes how to use Git.
+var vcsGit = &vcsCmd{
+       name: "Git",
+       cmd:  "git",
+
+       createCmd:   "clone {repo} {dir}",
+       downloadCmd: "pull --ff-only",
+
+       tagCmd: []tagCmd{
+               // tags/xxx matches a git tag named xxx
+               // origin/xxx matches a git branch named xxx on the default remote repository
+               {"show-ref", `(?:tags|origin)/(\S+)$`},
+       },
+       tagLookupCmd: []tagCmd{
+               {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
+       },
+       tagSyncCmd:     "checkout {tag}",
+       tagSyncDefault: "checkout master",
+
+       scheme:  []string{"git", "https", "http", "git+ssh"},
+       pingCmd: "ls-remote {scheme}://{repo}",
+}
+
+// vcsBzr describes how to use Bazaar.
+var vcsBzr = &vcsCmd{
+       name: "Bazaar",
+       cmd:  "bzr",
+
+       createCmd: "branch {repo} {dir}",
+
+       // Without --overwrite bzr will not pull tags that changed.
+       // Replace by --overwrite-tags after http://pad.lv/681792 goes in.
+       downloadCmd: "pull --overwrite",
+
+       tagCmd:         []tagCmd{{"tags", `^(\S+)`}},
+       tagSyncCmd:     "update -r {tag}",
+       tagSyncDefault: "update -r revno:-1",
+
+       scheme:  []string{"https", "http", "bzr", "bzr+ssh"},
+       pingCmd: "info {scheme}://{repo}",
+}
+
+// vcsSvn describes how to use Subversion.
+var vcsSvn = &vcsCmd{
+       name: "Subversion",
+       cmd:  "svn",
+
+       createCmd:   "checkout {repo} {dir}",
+       downloadCmd: "update",
+
+       // There is no tag command in subversion.
+       // The branch information is all in the path names.
+
+       scheme:  []string{"https", "http", "svn", "svn+ssh"},
+       pingCmd: "info {scheme}://{repo}",
+}
+
+func (v *vcsCmd) String() string {
+       return v.name
+}
+
+// run runs the command line cmd in the given directory.
+// keyval is a list of key, value pairs.  run expands
+// instances of {key} in cmd into value, but only after
+// splitting cmd into individual arguments.
+// If an error occurs, run prints the command line and the
+// command's combined stdout+stderr to standard error.
+// Otherwise run discards the command's output.
+func (v *vcsCmd) run(dir string, cmd string, keyval ...string) error {
+       _, err := v.run1(dir, cmd, keyval, true)
+       return err
+}
+
+// runVerboseOnly is like run but only generates error output to standard error in verbose mode.
+func (v *vcsCmd) runVerboseOnly(dir string, cmd string, keyval ...string) error {
+       _, err := v.run1(dir, cmd, keyval, false)
+       return err
+}
+
+// runOutput is like run but returns the output of the command.
+func (v *vcsCmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) {
+       return v.run1(dir, cmd, keyval, true)
+}
+
+// run1 is the generalized implementation of run and runOutput.
+func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) {
+       m := make(map[string]string)
+       for i := 0; i < len(keyval); i += 2 {
+               m[keyval[i]] = keyval[i+1]
+       }
+       args := strings.Fields(cmdline)
+       for i, arg := range args {
+               args[i] = expand(m, arg)
+       }
+
+       _, err := exec.LookPath(v.cmd)
+       if err != nil {
+               fmt.Fprintf(os.Stderr,
+                       "go: missing %s command. See http://golang.org/s/gogetcmd\n",
+                       v.name)
+               return nil, err
+       }
+
+       cmd := exec.Command(v.cmd, args...)
+       cmd.Dir = dir
+       cmd.Env = envForDir(cmd.Dir)
+       if buildX {
+               fmt.Printf("cd %s\n", dir)
+               fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
+       }
+       var buf bytes.Buffer
+       cmd.Stdout = &buf
+       cmd.Stderr = &buf
+       err = cmd.Run()
+       out := buf.Bytes()
+       if err != nil {
+               if verbose || buildV {
+                       fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
+                       os.Stderr.Write(out)
+               }
+               return nil, err
+       }
+       return out, nil
+}
+
+// ping pings to determine scheme to use.
+func (v *vcsCmd) ping(scheme, repo string) error {
+       return v.runVerboseOnly(".", v.pingCmd, "scheme", scheme, "repo", repo)
+}
+
+// create creates a new copy of repo in dir.
+// The parent of dir must exist; dir must not.
+func (v *vcsCmd) create(dir, repo string) error {
+       return v.run(".", v.createCmd, "dir", dir, "repo", repo)
+}
+
+// download downloads any new changes for the repo in dir.
+func (v *vcsCmd) download(dir string) error {
+       if err := v.fixDetachedHead(dir); err != nil {
+               return err
+       }
+       return v.run(dir, v.downloadCmd)
+}
+
+// fixDetachedHead switches a Git repository in dir from a detached head to the master branch.
+// Go versions before 1.2 downloaded Git repositories in an unfortunate way
+// that resulted in the working tree state being on a detached head.
+// That meant the repository was not usable for normal Git operations.
+// Go 1.2 fixed that, but we can't pull into a detached head, so if this is
+// a Git repository we check for being on a detached head and switch to the
+// real branch, almost always called "master".
+// TODO(dsymonds): Consider removing this for Go 1.3.
+func (v *vcsCmd) fixDetachedHead(dir string) error {
+       if v != vcsGit {
+               return nil
+       }
+
+       // "git symbolic-ref HEAD" succeeds iff we are not on a detached head.
+       if err := v.runVerboseOnly(dir, "symbolic-ref HEAD"); err == nil {
+               // not on a detached head
+               return nil
+       }
+       if buildV {
+               log.Printf("%s on detached head; repairing", dir)
+       }
+       return v.run(dir, "checkout master")
+}
+
+// tags returns the list of available tags for the repo in dir.
+func (v *vcsCmd) tags(dir string) ([]string, error) {
+       var tags []string
+       for _, tc := range v.tagCmd {
+               out, err := v.runOutput(dir, tc.cmd)
+               if err != nil {
+                       return nil, err
+               }
+               re := regexp.MustCompile(`(?m-s)` + tc.pattern)
+               for _, m := range re.FindAllStringSubmatch(string(out), -1) {
+                       tags = append(tags, m[1])
+               }
+       }
+       return tags, nil
+}
+
+// tagSync syncs the repo in dir to the named tag,
+// which either is a tag returned by tags or is v.tagDefault.
+func (v *vcsCmd) tagSync(dir, tag string) error {
+       if v.tagSyncCmd == "" {
+               return nil
+       }
+       if tag != "" {
+               for _, tc := range v.tagLookupCmd {
+                       out, err := v.runOutput(dir, tc.cmd, "tag", tag)
+                       if err != nil {
+                               return err
+                       }
+                       re := regexp.MustCompile(`(?m-s)` + tc.pattern)
+                       m := re.FindStringSubmatch(string(out))
+                       if len(m) > 1 {
+                               tag = m[1]
+                               break
+                       }
+               }
+       }
+       if tag == "" && v.tagSyncDefault != "" {
+               return v.run(dir, v.tagSyncDefault)
+       }
+       return v.run(dir, v.tagSyncCmd, "tag", tag)
+}
+
+// A vcsPath describes how to convert an import path into a
+// version control system and repository name.
+type vcsPath struct {
+       prefix string                              // prefix this description applies to
+       re     string                              // pattern for import path
+       repo   string                              // repository to use (expand with match of re)
+       vcs    string                              // version control system to use (expand with match of re)
+       check  func(match map[string]string) error // additional checks
+       ping   bool                                // ping for scheme to use to download repo
+
+       regexp *regexp.Regexp // cached compiled form of re
+}
+
+// vcsForDir inspects dir and its parents to determine the
+// version control system and code repository to use.
+// On return, root is the import path
+// corresponding to the root of the repository
+// (thus root is a prefix of importPath).
+func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) {
+       // Clean and double-check that dir is in (a subdirectory of) srcRoot.
+       dir := filepath.Clean(p.Dir)
+       srcRoot := filepath.Clean(p.build.SrcRoot)
+       if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
+               return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
+       }
+
+       origDir := dir
+       for len(dir) > len(srcRoot) {
+               for _, vcs := range vcsList {
+                       if fi, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil && fi.IsDir() {
+                               return vcs, dir[len(srcRoot)+1:], nil
+                       }
+               }
+
+               // Move to parent.
+               ndir := filepath.Dir(dir)
+               if len(ndir) >= len(dir) {
+                       // Shouldn't happen, but just in case, stop.
+                       break
+               }
+               dir = ndir
+       }
+
+       return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir)
+}
+
+// repoRoot represents a version control system, a repo, and a root of
+// where to put it on disk.
+type repoRoot struct {
+       vcs *vcsCmd
+
+       // repo is the repository URL, including scheme
+       repo string
+
+       // root is the import path corresponding to the root of the
+       // repository
+       root string
+}
+
+var httpPrefixRE = regexp.MustCompile(`^https?:`)
+
+// repoRootForImportPath analyzes importPath to determine the
+// version control system, and code repository to use.
+func repoRootForImportPath(importPath string) (*repoRoot, error) {
+       rr, err := repoRootForImportPathStatic(importPath, "")
+       if err == errUnknownSite {
+               rr, err = repoRootForImportDynamic(importPath)
+
+               // repoRootForImportDynamic returns error detail
+               // that is irrelevant if the user didn't intend to use a
+               // dynamic import in the first place.
+               // Squelch it.
+               if err != nil {
+                       if buildV {
+                               log.Printf("import %q: %v", importPath, err)
+                       }
+                       err = fmt.Errorf("unrecognized import path %q", importPath)
+               }
+       }
+
+       if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.root, "...") {
+               // Do not allow wildcards in the repo root.
+               rr = nil
+               err = fmt.Errorf("cannot expand ... in %q", importPath)
+       }
+       return rr, err
+}
+
+var errUnknownSite = errors.New("dynamic lookup required to find mapping")
+
+// repoRootForImportPathStatic attempts to map importPath to a
+// repoRoot using the commonly-used VCS hosting sites in vcsPaths
+// (github.com/user/dir), or from a fully-qualified importPath already
+// containing its VCS type (foo.com/repo.git/dir)
+//
+// If scheme is non-empty, that scheme is forced.
+func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
+       // A common error is to use https://packagepath because that's what
+       // hg and git require. Diagnose this helpfully.
+       if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil {
+               // The importPath has been cleaned, so has only one slash. The pattern
+               // ignores the slashes; the error message puts them back on the RHS at least.
+               return nil, fmt.Errorf("%q not allowed in import path", importPath[loc[0]:loc[1]]+"//")
+       }
+       for _, srv := range vcsPaths {
+               if !strings.HasPrefix(importPath, srv.prefix) {
+                       continue
+               }
+               m := srv.regexp.FindStringSubmatch(importPath)
+               if m == nil {
+                       if srv.prefix != "" {
+                               return nil, fmt.Errorf("invalid %s import path %q", srv.prefix, importPath)
+                       }
+                       continue
+               }
+
+               // Build map of named subexpression matches for expand.
+               match := map[string]string{
+                       "prefix": srv.prefix,
+                       "import": importPath,
+               }
+               for i, name := range srv.regexp.SubexpNames() {
+                       if name != "" && match[name] == "" {
+                               match[name] = m[i]
+                       }
+               }
+               if srv.vcs != "" {
+                       match["vcs"] = expand(match, srv.vcs)
+               }
+               if srv.repo != "" {
+                       match["repo"] = expand(match, srv.repo)
+               }
+               if srv.check != nil {
+                       if err := srv.check(match); err != nil {
+                               return nil, err
+                       }
+               }
+               vcs := vcsByCmd(match["vcs"])
+               if vcs == nil {
+                       return nil, fmt.Errorf("unknown version control system %q", match["vcs"])
+               }
+               if srv.ping {
+                       if scheme != "" {
+                               match["repo"] = scheme + "://" + match["repo"]
+                       } else {
+                               for _, scheme := range vcs.scheme {
+                                       if vcs.ping(scheme, match["repo"]) == nil {
+                                               match["repo"] = scheme + "://" + match["repo"]
+                                               break
+                                       }
+                               }
+                       }
+               }
+               rr := &repoRoot{
+                       vcs:  vcs,
+                       repo: match["repo"],
+                       root: match["root"],
+               }
+               return rr, nil
+       }
+       return nil, errUnknownSite
+}
+
+// repoRootForImportDynamic finds a *repoRoot for a custom domain that's not
+// statically known by repoRootForImportPathStatic.
+//
+// This handles "vanity import paths" like "name.tld/pkg/foo".
+func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
+       slash := strings.Index(importPath, "/")
+       if slash < 0 {
+               return nil, errors.New("import path doesn't contain a slash")
+       }
+       host := importPath[:slash]
+       if !strings.Contains(host, ".") {
+               return nil, errors.New("import path doesn't contain a hostname")
+       }
+       urlStr, body, err := httpsOrHTTP(importPath)
+       if err != nil {
+               return nil, fmt.Errorf("http/https fetch: %v", err)
+       }
+       defer body.Close()
+       imports, err := parseMetaGoImports(body)
+       if err != nil {
+               return nil, fmt.Errorf("parsing %s: %v", importPath, err)
+       }
+       metaImport, err := matchGoImport(imports, importPath)
+       if err != nil {
+               if err != errNoMatch {
+                       return nil, fmt.Errorf("parse %s: %v", urlStr, err)
+               }
+               return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr)
+       }
+       if buildV {
+               log.Printf("get %q: found meta tag %#v at %s", importPath, metaImport, urlStr)
+       }
+       // If the import was "uni.edu/bob/project", which said the
+       // prefix was "uni.edu" and the RepoRoot was "evilroot.com",
+       // make sure we don't trust Bob and check out evilroot.com to
+       // "uni.edu" yet (possibly overwriting/preempting another
+       // non-evil student).  Instead, first verify the root and see
+       // if it matches Bob's claim.
+       if metaImport.Prefix != importPath {
+               if buildV {
+                       log.Printf("get %q: verifying non-authoritative meta tag", importPath)
+               }
+               urlStr0 := urlStr
+               urlStr, body, err = httpsOrHTTP(metaImport.Prefix)
+               if err != nil {
+                       return nil, fmt.Errorf("fetch %s: %v", urlStr, err)
+               }
+               imports, err := parseMetaGoImports(body)
+               if err != nil {
+                       return nil, fmt.Errorf("parsing %s: %v", importPath, err)
+               }
+               if len(imports) == 0 {
+                       return nil, fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
+               }
+               metaImport2, err := matchGoImport(imports, importPath)
+               if err != nil || metaImport != metaImport2 {
+                       return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, metaImport.Prefix)
+               }
+       }
+
+       if !strings.Contains(metaImport.RepoRoot, "://") {
+               return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, metaImport.RepoRoot)
+       }
+       rr := &repoRoot{
+               vcs:  vcsByCmd(metaImport.VCS),
+               repo: metaImport.RepoRoot,
+               root: metaImport.Prefix,
+       }
+       if rr.vcs == nil {
+               return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, metaImport.VCS)
+       }
+       return rr, nil
+}
+
+// metaImport represents the parsed <meta name="go-import"
+// content="prefix vcs reporoot" /> tags from HTML files.
+type metaImport struct {
+       Prefix, VCS, RepoRoot string
+}
+
+// errNoMatch is returned from matchGoImport when there's no applicable match.
+var errNoMatch = errors.New("no import match")
+
+// matchGoImport returns the metaImport from imports matching importPath.
+// An error is returned if there are multiple matches.
+// errNoMatch is returned if none match.
+func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) {
+       match := -1
+       for i, im := range imports {
+               if !strings.HasPrefix(importPath, im.Prefix) {
+                       continue
+               }
+               if match != -1 {
+                       err = fmt.Errorf("multiple meta tags match import path %q", importPath)
+                       return
+               }
+               match = i
+       }
+       if match == -1 {
+               err = errNoMatch
+               return
+       }
+       return imports[match], nil
+}
+
+// expand rewrites s to replace {k} with match[k] for each key k in match.
+func expand(match map[string]string, s string) string {
+       for k, v := range match {
+               s = strings.Replace(s, "{"+k+"}", v, -1)
+       }
+       return s
+}
+
+// vcsPaths lists the known vcs paths.
+var vcsPaths = []*vcsPath{
+       // Google Code - new syntax
+       {
+               prefix: "code.google.com/",
+               re:     `^(?P<root>code\.google\.com/p/(?P<project>[a-z0-9\-]+)(\.(?P<subrepo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
+               repo:   "https://{root}",
+               check:  googleCodeVCS,
+       },
+
+       // Google Code - old syntax
+       {
+               re:    `^(?P<project>[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P<path>/.*)?$`,
+               check: oldGoogleCode,
+       },
+
+       // Github
+       {
+               prefix: "github.com/",
+               re:     `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
+               vcs:    "git",
+               repo:   "https://{root}",
+               check:  noVCSSuffix,
+       },
+
+       // Bitbucket
+       {
+               prefix: "bitbucket.org/",
+               re:     `^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+               repo:   "https://{root}",
+               check:  bitbucketVCS,
+       },
+
+       // Launchpad
+       {
+               prefix: "launchpad.net/",
+               re:     `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+               vcs:    "bzr",
+               repo:   "https://{root}",
+               check:  launchpadVCS,
+       },
+
+       // General syntax for any server.
+       {
+               re:   `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
+               ping: true,
+       },
+}
+
+func init() {
+       // fill in cached regexps.
+       // Doing this eagerly discovers invalid regexp syntax
+       // without having to run a command that needs that regexp.
+       for _, srv := range vcsPaths {
+               srv.regexp = regexp.MustCompile(srv.re)
+       }
+}
+
+// noVCSSuffix checks that the repository name does not
+// end in .foo for any version control system foo.
+// The usual culprit is ".git".
+func noVCSSuffix(match map[string]string) error {
+       repo := match["repo"]
+       for _, vcs := range vcsList {
+               if strings.HasSuffix(repo, "."+vcs.cmd) {
+                       return fmt.Errorf("invalid version control suffix in %s path", match["prefix"])
+               }
+       }
+       return nil
+}
+
+var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
+
+// googleCodeVCS determines the version control system for
+// a code.google.com repository, by scraping the project's
+// /source/checkout page.
+func googleCodeVCS(match map[string]string) error {
+       if err := noVCSSuffix(match); err != nil {
+               return err
+       }
+       data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}"))
+       if err != nil {
+               return err
+       }
+
+       if m := googleCheckout.FindSubmatch(data); m != nil {
+               if vcs := vcsByCmd(string(m[1])); vcs != nil {
+                       // Subversion requires the old URLs.
+                       // TODO: Test.
+                       if vcs == vcsSvn {
+                               if match["subrepo"] != "" {
+                                       return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects")
+                               }
+                               match["repo"] = expand(match, "https://{project}.googlecode.com/svn")
+                       }
+                       match["vcs"] = vcs.cmd
+                       return nil
+               }
+       }
+
+       return fmt.Errorf("unable to detect version control system for code.google.com/ path")
+}
+
+// oldGoogleCode is invoked for old-style foo.googlecode.com paths.
+// It prints an error giving the equivalent new path.
+func oldGoogleCode(match map[string]string) error {
+       return fmt.Errorf("invalid Google Code import path: use %s instead",
+               expand(match, "code.google.com/p/{project}{path}"))
+}
+
+// bitbucketVCS determines the version control system for a
+// Bitbucket repository, by using the Bitbucket API.
+func bitbucketVCS(match map[string]string) error {
+       if err := noVCSSuffix(match); err != nil {
+               return err
+       }
+
+       var resp struct {
+               SCM string `json:"scm"`
+       }
+       url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}")
+       data, err := httpGET(url)
+       if err != nil {
+               return err
+       }
+       if err := json.Unmarshal(data, &resp); err != nil {
+               return fmt.Errorf("decoding %s: %v", url, err)
+       }
+
+       if vcsByCmd(resp.SCM) != nil {
+               match["vcs"] = resp.SCM
+               if resp.SCM == "git" {
+                       match["repo"] += ".git"
+               }
+               return nil
+       }
+
+       return fmt.Errorf("unable to detect version control system for bitbucket.org/ path")
+}
+
+// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case,
+// "foo" could be a series name registered in Launchpad with its own branch,
+// and it could also be the name of a directory within the main project
+// branch one level up.
+func launchpadVCS(match map[string]string) error {
+       if match["project"] == "" || match["series"] == "" {
+               return nil
+       }
+       _, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format"))
+       if err != nil {
+               match["root"] = expand(match, "launchpad.net/{project}")
+               match["repo"] = expand(match, "https://{root}")
+       }
+       return nil
+}
diff --git a/libgo/go/cmd/go/version.go b/libgo/go/cmd/go/version.go
new file mode 100644 (file)
index 0000000..a41f4a7
--- /dev/null
@@ -0,0 +1,25 @@
+// 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 (
+       "fmt"
+       "runtime"
+)
+
+var cmdVersion = &Command{
+       Run:       runVersion,
+       UsageLine: "version",
+       Short:     "print Go version",
+       Long:      `Version prints the Go version, as reported by runtime.Version.`,
+}
+
+func runVersion(cmd *Command, args []string) {
+       if len(args) != 0 {
+               cmd.Usage()
+       }
+
+       fmt.Printf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
+}
diff --git a/libgo/go/cmd/go/vet.go b/libgo/go/cmd/go/vet.go
new file mode 100644 (file)
index 0000000..ffb4318
--- /dev/null
@@ -0,0 +1,37 @@
+// 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
+
+func init() {
+       addBuildFlagsNX(cmdVet)
+}
+
+var cmdVet = &Command{
+       Run:       runVet,
+       UsageLine: "vet [-n] [-x] [packages]",
+       Short:     "run go tool vet on packages",
+       Long: `
+Vet runs the Go vet command on the packages named by the import paths.
+
+For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'.
+For more about specifying packages, see 'go help packages'.
+
+To run the vet tool with specific options, run 'go tool vet'.
+
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+See also: go fmt, go fix.
+       `,
+}
+
+func runVet(cmd *Command, args []string) {
+       for _, pkg := range packages(args) {
+               // Use pkg.gofiles instead of pkg.Dir so that
+               // the command only applies to this package,
+               // not to packages in subdirectories.
+               run(tool("vet"), relPaths(stringList(pkg.gofiles, pkg.sfiles)))
+       }
+}
diff --git a/libgo/go/cmd/gofmt/doc.go b/libgo/go/cmd/gofmt/doc.go
new file mode 100644 (file)
index 0000000..8f73ef5
--- /dev/null
@@ -0,0 +1,93 @@
+// 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.
+
+/*
+Gofmt formats Go programs.
+It uses tabs (width = 8) for indentation and blanks for alignment.
+
+Without an explicit path, it processes the standard input.  Given a file,
+it operates on that file; given a directory, it operates on all .go files in
+that directory, recursively.  (Files starting with a period are ignored.)
+By default, gofmt prints the reformatted sources to standard output.
+
+Usage:
+       gofmt [flags] [path ...]
+
+The flags are:
+       -d
+               Do not print reformatted sources to standard output.
+               If a file's formatting is different than gofmt's, print diffs
+               to standard output.
+       -e
+               Print all (including spurious) errors.
+       -l
+               Do not print reformatted sources to standard output.
+               If a file's formatting is different from gofmt's, print its name
+               to standard output.
+       -r rule
+               Apply the rewrite rule to the source before reformatting.
+       -s
+               Try to simplify code (after applying the rewrite rule, if any).
+       -w
+               Do not print reformatted sources to standard output.
+               If a file's formatting is different from gofmt's, overwrite it
+               with gofmt's version.
+
+Debugging support:
+       -cpuprofile filename
+               Write cpu profile to the specified file.
+
+
+The rewrite rule specified with the -r flag must be a string of the form:
+
+       pattern -> replacement
+
+Both pattern and replacement must be valid Go expressions.
+In the pattern, single-character lowercase identifiers serve as
+wildcards matching arbitrary sub-expressions; those expressions
+will be substituted for the same identifiers in the replacement.
+
+When gofmt reads from standard input, it accepts either a full Go program
+or a program fragment.  A program fragment must be a syntactically
+valid declaration list, statement list, or expression.  When formatting
+such a fragment, gofmt preserves leading indentation as well as leading
+and trailing spaces, so that individual sections of a Go program can be
+formatted by piping them through gofmt.
+
+Examples
+
+To check files for unnecessary parentheses:
+
+       gofmt -r '(a) -> a' -l *.go
+
+To remove the parentheses:
+
+       gofmt -r '(a) -> a' -w *.go
+
+To convert the package tree from explicit slice upper bounds to implicit ones:
+
+       gofmt -r 'α[β:len(α)] -> Î±[β:]' -w $GOROOT/src/pkg
+
+The simplify command
+
+When invoked with -s gofmt will make the following source transformations where possible.
+
+       An array, slice, or map composite literal of the form:
+               []T{T{}, T{}}
+       will be simplified to:
+               []T{{}, {}}
+
+       A slice expression of the form:
+               s[a:len(s)]
+       will be simplified to:
+               s[a:]
+
+       A range of the form:
+               for x, _ = range v {...}
+       will be simplified to:
+               for x = range v {...}
+*/
+package main
+
+// BUG(rsc): The implementation of -r is a bit slow.
diff --git a/libgo/go/cmd/gofmt/gofmt.go b/libgo/go/cmd/gofmt/gofmt.go
new file mode 100644 (file)
index 0000000..576cae5
--- /dev/null
@@ -0,0 +1,344 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "bytes"
+       "flag"
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "go/printer"
+       "go/scanner"
+       "go/token"
+       "io"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime/pprof"
+       "strings"
+)
+
+var (
+       // main operation modes
+       list        = flag.Bool("l", false, "list files whose formatting differs from gofmt's")
+       write       = flag.Bool("w", false, "write result to (source) file instead of stdout")
+       rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')")
+       simplifyAST = flag.Bool("s", false, "simplify code")
+       doDiff      = flag.Bool("d", false, "display diffs instead of rewriting files")
+       allErrors   = flag.Bool("e", false, "report all errors (not just the first 10 on different lines)")
+
+       // debugging
+       cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
+)
+
+const (
+       tabWidth    = 8
+       printerMode = printer.UseSpaces | printer.TabIndent
+)
+
+var (
+       fileSet    = token.NewFileSet() // per process FileSet
+       exitCode   = 0
+       rewrite    func(*ast.File) *ast.File
+       parserMode parser.Mode
+)
+
+func report(err error) {
+       scanner.PrintError(os.Stderr, err)
+       exitCode = 2
+}
+
+func usage() {
+       fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n")
+       flag.PrintDefaults()
+       os.Exit(2)
+}
+
+func initParserMode() {
+       parserMode = parser.ParseComments
+       if *allErrors {
+               parserMode |= parser.AllErrors
+       }
+}
+
+func isGoFile(f os.FileInfo) bool {
+       // ignore non-Go files
+       name := f.Name()
+       return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
+}
+
+// If in == nil, the source is the contents of the file with the given filename.
+func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error {
+       if in == nil {
+               f, err := os.Open(filename)
+               if err != nil {
+                       return err
+               }
+               defer f.Close()
+               in = f
+       }
+
+       src, err := ioutil.ReadAll(in)
+       if err != nil {
+               return err
+       }
+
+       file, adjust, err := parse(fileSet, filename, src, stdin)
+       if err != nil {
+               return err
+       }
+
+       if rewrite != nil {
+               if adjust == nil {
+                       file = rewrite(file)
+               } else {
+                       fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n")
+               }
+       }
+
+       ast.SortImports(fileSet, file)
+
+       if *simplifyAST {
+               simplify(file)
+       }
+
+       var buf bytes.Buffer
+       err = (&printer.Config{Mode: printerMode, Tabwidth: tabWidth}).Fprint(&buf, fileSet, file)
+       if err != nil {
+               return err
+       }
+       res := buf.Bytes()
+       if adjust != nil {
+               res = adjust(src, res)
+       }
+
+       if !bytes.Equal(src, res) {
+               // formatting has changed
+               if *list {
+                       fmt.Fprintln(out, filename)
+               }
+               if *write {
+                       err = ioutil.WriteFile(filename, res, 0)
+                       if err != nil {
+                               return err
+                       }
+               }
+               if *doDiff {
+                       data, err := diff(src, res)
+                       if err != nil {
+                               return fmt.Errorf("computing diff: %s", err)
+                       }
+                       fmt.Printf("diff %s gofmt/%s\n", filename, filename)
+                       out.Write(data)
+               }
+       }
+
+       if !*list && !*write && !*doDiff {
+               _, err = out.Write(res)
+       }
+
+       return err
+}
+
+func visitFile(path string, f os.FileInfo, err error) error {
+       if err == nil && isGoFile(f) {
+               err = processFile(path, nil, os.Stdout, false)
+       }
+       if err != nil {
+               report(err)
+       }
+       return nil
+}
+
+func walkDir(path string) {
+       filepath.Walk(path, visitFile)
+}
+
+func main() {
+       // call gofmtMain in a separate function
+       // so that it can use defer and have them
+       // run before the exit.
+       gofmtMain()
+       os.Exit(exitCode)
+}
+
+func gofmtMain() {
+       flag.Usage = usage
+       flag.Parse()
+
+       if *cpuprofile != "" {
+               f, err := os.Create(*cpuprofile)
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err)
+                       exitCode = 2
+                       return
+               }
+               defer f.Close()
+               pprof.StartCPUProfile(f)
+               defer pprof.StopCPUProfile()
+       }
+
+       initParserMode()
+       initRewrite()
+
+       if flag.NArg() == 0 {
+               if err := processFile("<standard input>", os.Stdin, os.Stdout, true); err != nil {
+                       report(err)
+               }
+               return
+       }
+
+       for i := 0; i < flag.NArg(); i++ {
+               path := flag.Arg(i)
+               switch dir, err := os.Stat(path); {
+               case err != nil:
+                       report(err)
+               case dir.IsDir():
+                       walkDir(path)
+               default:
+                       if err := processFile(path, nil, os.Stdout, false); err != nil {
+                               report(err)
+                       }
+               }
+       }
+}
+
+func diff(b1, b2 []byte) (data []byte, err error) {
+       f1, err := ioutil.TempFile("", "gofmt")
+       if err != nil {
+               return
+       }
+       defer os.Remove(f1.Name())
+       defer f1.Close()
+
+       f2, err := ioutil.TempFile("", "gofmt")
+       if err != nil {
+               return
+       }
+       defer os.Remove(f2.Name())
+       defer f2.Close()
+
+       f1.Write(b1)
+       f2.Write(b2)
+
+       data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
+       if len(data) > 0 {
+               // diff exits with a non-zero status when the files don't match.
+               // Ignore that failure as long as we get output.
+               err = nil
+       }
+       return
+
+}
+
+// parse parses src, which was read from filename,
+// as a Go source file or statement list.
+func parse(fset *token.FileSet, filename string, src []byte, stdin bool) (*ast.File, func(orig, src []byte) []byte, error) {
+       // Try as whole source file.
+       file, err := parser.ParseFile(fset, filename, src, parserMode)
+       if err == nil {
+               return file, nil, nil
+       }
+       // If the error is that the source file didn't begin with a
+       // package line and this is standard input, fall through to
+       // try as a source fragment.  Stop and return on any other error.
+       if !stdin || !strings.Contains(err.Error(), "expected 'package'") {
+               return nil, nil, err
+       }
+
+       // If this is a declaration list, make it a source file
+       // by inserting a package clause.
+       // Insert using a ;, not a newline, so that the line numbers
+       // in psrc match the ones in src.
+       psrc := append([]byte("package p;"), src...)
+       file, err = parser.ParseFile(fset, filename, psrc, parserMode)
+       if err == nil {
+               adjust := func(orig, src []byte) []byte {
+                       // Remove the package clause.
+                       // Gofmt has turned the ; into a \n.
+                       src = src[len("package p\n"):]
+                       return matchSpace(orig, src)
+               }
+               return file, adjust, nil
+       }
+       // If the error is that the source file didn't begin with a
+       // declaration, fall through to try as a statement list.
+       // Stop and return on any other error.
+       if !strings.Contains(err.Error(), "expected declaration") {
+               return nil, nil, err
+       }
+
+       // If this is a statement list, make it a source file
+       // by inserting a package clause and turning the list
+       // into a function body.  This handles expressions too.
+       // Insert using a ;, not a newline, so that the line numbers
+       // in fsrc match the ones in src.
+       fsrc := append(append([]byte("package p; func _() {"), src...), '}')
+       file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
+       if err == nil {
+               adjust := func(orig, src []byte) []byte {
+                       // Remove the wrapping.
+                       // Gofmt has turned the ; into a \n\n.
+                       src = src[len("package p\n\nfunc _() {"):]
+                       src = src[:len(src)-len("}\n")]
+                       // Gofmt has also indented the function body one level.
+                       // Remove that indent.
+                       src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1)
+                       return matchSpace(orig, src)
+               }
+               return file, adjust, nil
+       }
+
+       // Failed, and out of options.
+       return nil, nil, err
+}
+
+func cutSpace(b []byte) (before, middle, after []byte) {
+       i := 0
+       for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') {
+               i++
+       }
+       j := len(b)
+       for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') {
+               j--
+       }
+       if i <= j {
+               return b[:i], b[i:j], b[j:]
+       }
+       return nil, nil, b[j:]
+}
+
+// matchSpace reformats src to use the same space context as orig.
+// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src.
+// 2) matchSpace copies the indentation of the first non-blank line in orig
+//    to every non-blank line in src.
+// 3) matchSpace copies the trailing space from orig and uses it in place
+//   of src's trailing space.
+func matchSpace(orig []byte, src []byte) []byte {
+       before, _, after := cutSpace(orig)
+       i := bytes.LastIndex(before, []byte{'\n'})
+       before, indent := before[:i+1], before[i+1:]
+
+       _, src, _ = cutSpace(src)
+
+       var b bytes.Buffer
+       b.Write(before)
+       for len(src) > 0 {
+               line := src
+               if i := bytes.IndexByte(line, '\n'); i >= 0 {
+                       line, src = line[:i+1], line[i+1:]
+               } else {
+                       src = nil
+               }
+               if len(line) > 0 && line[0] != '\n' { // not blank
+                       b.Write(indent)
+               }
+               b.Write(line)
+       }
+       b.Write(after)
+       return b.Bytes()
+}
diff --git a/libgo/go/cmd/gofmt/gofmt_test.go b/libgo/go/cmd/gofmt/gofmt_test.go
new file mode 100644 (file)
index 0000000..b9335b8
--- /dev/null
@@ -0,0 +1,134 @@
+// 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 (
+       "bytes"
+       "io/ioutil"
+       "path/filepath"
+       "strings"
+       "testing"
+)
+
+func runTest(t *testing.T, in, out, flags string) {
+       // process flags
+       *simplifyAST = false
+       *rewriteRule = ""
+       stdin := false
+       for _, flag := range strings.Split(flags, " ") {
+               elts := strings.SplitN(flag, "=", 2)
+               name := elts[0]
+               value := ""
+               if len(elts) == 2 {
+                       value = elts[1]
+               }
+               switch name {
+               case "":
+                       // no flags
+               case "-r":
+                       *rewriteRule = value
+               case "-s":
+                       *simplifyAST = true
+               case "-stdin":
+                       // fake flag - pretend input is from stdin
+                       stdin = true
+               default:
+                       t.Errorf("unrecognized flag name: %s", name)
+               }
+       }
+
+       initParserMode()
+       initRewrite()
+
+       var buf bytes.Buffer
+       err := processFile(in, nil, &buf, stdin)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       expected, err := ioutil.ReadFile(out)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       if got := buf.Bytes(); !bytes.Equal(got, expected) {
+               t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
+               d, err := diff(expected, got)
+               if err == nil {
+                       t.Errorf("%s", d)
+               }
+               if err := ioutil.WriteFile(in+".gofmt", got, 0666); err != nil {
+                       t.Error(err)
+               }
+       }
+}
+
+var tests = []struct {
+       in, flags string
+}{
+       {"gofmt.go", ""},
+       {"gofmt_test.go", ""},
+       {"testdata/composites.input", "-s"},
+       {"testdata/slices1.input", "-s"},
+       {"testdata/slices2.input", "-s"},
+       {"testdata/old.input", ""},
+       {"testdata/rewrite1.input", "-r=Foo->Bar"},
+       {"testdata/rewrite2.input", "-r=int->bool"},
+       {"testdata/rewrite3.input", "-r=x->x"},
+       {"testdata/rewrite4.input", "-r=(x)->x"},
+       {"testdata/rewrite5.input", "-r=x+x->2*x"},
+       {"testdata/rewrite6.input", "-r=fun(x)->Fun(x)"},
+       {"testdata/rewrite7.input", "-r=fun(x...)->Fun(x)"},
+       {"testdata/rewrite8.input", "-r=interface{}->int"},
+       {"testdata/stdin*.input", "-stdin"},
+       {"testdata/comments.input", ""},
+       {"testdata/import.input", ""},
+       {"testdata/crlf.input", ""},       // test case for issue 3961; see also TestCRLF
+       {"testdata/typeswitch.input", ""}, // test case for issue 4470
+}
+
+func TestRewrite(t *testing.T) {
+       for _, test := range tests {
+               match, err := filepath.Glob(test.in)
+               if err != nil {
+                       t.Error(err)
+                       continue
+               }
+               for _, in := range match {
+                       out := in
+                       if strings.HasSuffix(in, ".input") {
+                               out = in[:len(in)-len(".input")] + ".golden"
+                       }
+                       runTest(t, in, out, test.flags)
+                       if in != out {
+                               // Check idempotence.
+                               runTest(t, out, out, test.flags)
+                       }
+               }
+       }
+}
+
+func TestCRLF(t *testing.T) {
+       const input = "testdata/crlf.input"   // must contain CR/LF's
+       const golden = "testdata/crlf.golden" // must not contain any CR's
+
+       data, err := ioutil.ReadFile(input)
+       if err != nil {
+               t.Error(err)
+       }
+       if bytes.Index(data, []byte("\r\n")) < 0 {
+               t.Errorf("%s contains no CR/LF's", input)
+       }
+
+       data, err = ioutil.ReadFile(golden)
+       if err != nil {
+               t.Error(err)
+       }
+       if bytes.Index(data, []byte("\r")) >= 0 {
+               t.Errorf("%s contains CR's", golden)
+       }
+}
diff --git a/libgo/go/cmd/gofmt/long_test.go b/libgo/go/cmd/gofmt/long_test.go
new file mode 100644 (file)
index 0000000..108278b
--- /dev/null
@@ -0,0 +1,159 @@
+// 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.
+
+// This test applies gofmt to all Go files under -root.
+// To test specific files provide a list of comma-separated
+// filenames via the -files flag: go test -files=gofmt.go .
+
+package main
+
+import (
+       "bytes"
+       "flag"
+       "fmt"
+       "go/ast"
+       "go/printer"
+       "go/token"
+       "io"
+       "os"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "testing"
+)
+
+var (
+       root    = flag.String("root", runtime.GOROOT(), "test root directory")
+       files   = flag.String("files", "", "comma-separated list of files to test")
+       ngo     = flag.Int("n", runtime.NumCPU(), "number of goroutines used")
+       verbose = flag.Bool("verbose", false, "verbose mode")
+       nfiles  int // number of files processed
+)
+
+func gofmt(fset *token.FileSet, filename string, src *bytes.Buffer) error {
+       f, _, err := parse(fset, filename, src.Bytes(), false)
+       if err != nil {
+               return err
+       }
+       ast.SortImports(fset, f)
+       src.Reset()
+       return (&printer.Config{Mode: printerMode, Tabwidth: tabWidth}).Fprint(src, fset, f)
+}
+
+func testFile(t *testing.T, b1, b2 *bytes.Buffer, filename string) {
+       // open file
+       f, err := os.Open(filename)
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       // read file
+       b1.Reset()
+       _, err = io.Copy(b1, f)
+       f.Close()
+       if err != nil {
+               t.Error(err)
+               return
+       }
+
+       // exclude files w/ syntax errors (typically test cases)
+       fset := token.NewFileSet()
+       if _, _, err = parse(fset, filename, b1.Bytes(), false); err != nil {
+               if *verbose {
+                       fmt.Fprintf(os.Stderr, "ignoring %s\n", err)
+               }
+               return
+       }
+
+       // gofmt file
+       if err = gofmt(fset, filename, b1); err != nil {
+               t.Errorf("1st gofmt failed: %v", err)
+               return
+       }
+
+       // make a copy of the result
+       b2.Reset()
+       b2.Write(b1.Bytes())
+
+       // gofmt result again
+       if err = gofmt(fset, filename, b2); err != nil {
+               t.Errorf("2nd gofmt failed: %v", err)
+               return
+       }
+
+       // the first and 2nd result should be identical
+       if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
+               t.Errorf("gofmt %s not idempotent", filename)
+       }
+}
+
+func testFiles(t *testing.T, filenames <-chan string, done chan<- int) {
+       b1 := new(bytes.Buffer)
+       b2 := new(bytes.Buffer)
+       for filename := range filenames {
+               testFile(t, b1, b2, filename)
+       }
+       done <- 0
+}
+
+func genFilenames(t *testing.T, filenames chan<- string) {
+       defer close(filenames)
+
+       handleFile := func(filename string, fi os.FileInfo, err error) error {
+               if err != nil {
+                       t.Error(err)
+                       return nil
+               }
+               if isGoFile(fi) {
+                       filenames <- filename
+                       nfiles++
+               }
+               return nil
+       }
+
+       // test Go files provided via -files, if any
+       if *files != "" {
+               for _, filename := range strings.Split(*files, ",") {
+                       fi, err := os.Stat(filename)
+                       handleFile(filename, fi, err)
+               }
+               return // ignore files under -root
+       }
+
+       // otherwise, test all Go files under *root
+       filepath.Walk(*root, handleFile)
+}
+
+func TestAll(t *testing.T) {
+       if testing.Short() {
+               return
+       }
+
+       if *ngo < 1 {
+               *ngo = 1 // make sure test is run
+       }
+       if *verbose {
+               fmt.Printf("running test using %d goroutines\n", *ngo)
+       }
+
+       // generate filenames
+       filenames := make(chan string, 32)
+       go genFilenames(t, filenames)
+
+       // launch test goroutines
+       done := make(chan int)
+       for i := 0; i < *ngo; i++ {
+               go testFiles(t, filenames, done)
+       }
+
+       // wait for all test goroutines to complete
+       for i := 0; i < *ngo; i++ {
+               <-done
+       }
+
+       if *verbose {
+               fmt.Printf("processed %d files\n", nfiles)
+       }
+}
diff --git a/libgo/go/cmd/gofmt/rewrite.go b/libgo/go/cmd/gofmt/rewrite.go
new file mode 100644 (file)
index 0000000..fb6c6fc
--- /dev/null
@@ -0,0 +1,306 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "go/token"
+       "os"
+       "reflect"
+       "strings"
+       "unicode"
+       "unicode/utf8"
+)
+
+func initRewrite() {
+       if *rewriteRule == "" {
+               rewrite = nil // disable any previous rewrite
+               return
+       }
+       f := strings.Split(*rewriteRule, "->")
+       if len(f) != 2 {
+               fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n")
+               os.Exit(2)
+       }
+       pattern := parseExpr(f[0], "pattern")
+       replace := parseExpr(f[1], "replacement")
+       rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) }
+}
+
+// parseExpr parses s as an expression.
+// It might make sense to expand this to allow statement patterns,
+// but there are problems with preserving formatting and also
+// with what a wildcard for a statement looks like.
+func parseExpr(s, what string) ast.Expr {
+       x, err := parser.ParseExpr(s)
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err)
+               os.Exit(2)
+       }
+       return x
+}
+
+// Keep this function for debugging.
+/*
+func dump(msg string, val reflect.Value) {
+       fmt.Printf("%s:\n", msg)
+       ast.Print(fileSet, val.Interface())
+       fmt.Println()
+}
+*/
+
+// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
+func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
+       cmap := ast.NewCommentMap(fileSet, p, p.Comments)
+       m := make(map[string]reflect.Value)
+       pat := reflect.ValueOf(pattern)
+       repl := reflect.ValueOf(replace)
+
+       var rewriteVal func(val reflect.Value) reflect.Value
+       rewriteVal = func(val reflect.Value) reflect.Value {
+               // don't bother if val is invalid to start with
+               if !val.IsValid() {
+                       return reflect.Value{}
+               }
+               for k := range m {
+                       delete(m, k)
+               }
+               val = apply(rewriteVal, val)
+               if match(m, pat, val) {
+                       val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
+               }
+               return val
+       }
+
+       r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File)
+       r.Comments = cmap.Filter(r).Comments() // recreate comments list
+       return r
+}
+
+// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y.
+func set(x, y reflect.Value) {
+       // don't bother if x cannot be set or y is invalid
+       if !x.CanSet() || !y.IsValid() {
+               return
+       }
+       defer func() {
+               if x := recover(); x != nil {
+                       if s, ok := x.(string); ok &&
+                               (strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
+                               // x cannot be set to y - ignore this rewrite
+                               return
+                       }
+                       panic(x)
+               }
+       }()
+       x.Set(y)
+}
+
+// Values/types for special cases.
+var (
+       objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
+       scopePtrNil  = reflect.ValueOf((*ast.Scope)(nil))
+
+       identType     = reflect.TypeOf((*ast.Ident)(nil))
+       objectPtrType = reflect.TypeOf((*ast.Object)(nil))
+       positionType  = reflect.TypeOf(token.NoPos)
+       callExprType  = reflect.TypeOf((*ast.CallExpr)(nil))
+       scopePtrType  = reflect.TypeOf((*ast.Scope)(nil))
+)
+
+// apply replaces each AST field x in val with f(x), returning val.
+// To avoid extra conversions, f operates on the reflect.Value form.
+func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
+       if !val.IsValid() {
+               return reflect.Value{}
+       }
+
+       // *ast.Objects introduce cycles and are likely incorrect after
+       // rewrite; don't follow them but replace with nil instead
+       if val.Type() == objectPtrType {
+               return objectPtrNil
+       }
+
+       // similarly for scopes: they are likely incorrect after a rewrite;
+       // replace them with nil
+       if val.Type() == scopePtrType {
+               return scopePtrNil
+       }
+
+       switch v := reflect.Indirect(val); v.Kind() {
+       case reflect.Slice:
+               for i := 0; i < v.Len(); i++ {
+                       e := v.Index(i)
+                       set(e, f(e))
+               }
+       case reflect.Struct:
+               for i := 0; i < v.NumField(); i++ {
+                       e := v.Field(i)
+                       set(e, f(e))
+               }
+       case reflect.Interface:
+               e := v.Elem()
+               set(v, f(e))
+       }
+       return val
+}
+
+func isWildcard(s string) bool {
+       rune, size := utf8.DecodeRuneInString(s)
+       return size == len(s) && unicode.IsLower(rune)
+}
+
+// match returns true if pattern matches val,
+// recording wildcard submatches in m.
+// If m == nil, match checks whether pattern == val.
+func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
+       // Wildcard matches any expression.  If it appears multiple
+       // times in the pattern, it must match the same expression
+       // each time.
+       if m != nil && pattern.IsValid() && pattern.Type() == identType {
+               name := pattern.Interface().(*ast.Ident).Name
+               if isWildcard(name) && val.IsValid() {
+                       // wildcards only match valid (non-nil) expressions.
+                       if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() {
+                               if old, ok := m[name]; ok {
+                                       return match(nil, old, val)
+                               }
+                               m[name] = val
+                               return true
+                       }
+               }
+       }
+
+       // Otherwise, pattern and val must match recursively.
+       if !pattern.IsValid() || !val.IsValid() {
+               return !pattern.IsValid() && !val.IsValid()
+       }
+       if pattern.Type() != val.Type() {
+               return false
+       }
+
+       // Special cases.
+       switch pattern.Type() {
+       case identType:
+               // For identifiers, only the names need to match
+               // (and none of the other *ast.Object information).
+               // This is a common case, handle it all here instead
+               // of recursing down any further via reflection.
+               p := pattern.Interface().(*ast.Ident)
+               v := val.Interface().(*ast.Ident)
+               return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
+       case objectPtrType, positionType:
+               // object pointers and token positions always match
+               return true
+       case callExprType:
+               // For calls, the Ellipsis fields (token.Position) must
+               // match since that is how f(x) and f(x...) are different.
+               // Check them here but fall through for the remaining fields.
+               p := pattern.Interface().(*ast.CallExpr)
+               v := val.Interface().(*ast.CallExpr)
+               if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {
+                       return false
+               }
+       }
+
+       p := reflect.Indirect(pattern)
+       v := reflect.Indirect(val)
+       if !p.IsValid() || !v.IsValid() {
+               return !p.IsValid() && !v.IsValid()
+       }
+
+       switch p.Kind() {
+       case reflect.Slice:
+               if p.Len() != v.Len() {
+                       return false
+               }
+               for i := 0; i < p.Len(); i++ {
+                       if !match(m, p.Index(i), v.Index(i)) {
+                               return false
+                       }
+               }
+               return true
+
+       case reflect.Struct:
+               if p.NumField() != v.NumField() {
+                       return false
+               }
+               for i := 0; i < p.NumField(); i++ {
+                       if !match(m, p.Field(i), v.Field(i)) {
+                               return false
+                       }
+               }
+               return true
+
+       case reflect.Interface:
+               return match(m, p.Elem(), v.Elem())
+       }
+
+       // Handle token integers, etc.
+       return p.Interface() == v.Interface()
+}
+
+// subst returns a copy of pattern with values from m substituted in place
+// of wildcards and pos used as the position of tokens from the pattern.
+// if m == nil, subst returns a copy of pattern and doesn't change the line
+// number information.
+func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value {
+       if !pattern.IsValid() {
+               return reflect.Value{}
+       }
+
+       // Wildcard gets replaced with map value.
+       if m != nil && pattern.Type() == identType {
+               name := pattern.Interface().(*ast.Ident).Name
+               if isWildcard(name) {
+                       if old, ok := m[name]; ok {
+                               return subst(nil, old, reflect.Value{})
+                       }
+               }
+       }
+
+       if pos.IsValid() && pattern.Type() == positionType {
+               // use new position only if old position was valid in the first place
+               if old := pattern.Interface().(token.Pos); !old.IsValid() {
+                       return pattern
+               }
+               return pos
+       }
+
+       // Otherwise copy.
+       switch p := pattern; p.Kind() {
+       case reflect.Slice:
+               v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
+               for i := 0; i < p.Len(); i++ {
+                       v.Index(i).Set(subst(m, p.Index(i), pos))
+               }
+               return v
+
+       case reflect.Struct:
+               v := reflect.New(p.Type()).Elem()
+               for i := 0; i < p.NumField(); i++ {
+                       v.Field(i).Set(subst(m, p.Field(i), pos))
+               }
+               return v
+
+       case reflect.Ptr:
+               v := reflect.New(p.Type()).Elem()
+               if elem := p.Elem(); elem.IsValid() {
+                       v.Set(subst(m, elem, pos).Addr())
+               }
+               return v
+
+       case reflect.Interface:
+               v := reflect.New(p.Type()).Elem()
+               if elem := p.Elem(); elem.IsValid() {
+                       v.Set(subst(m, elem, pos))
+               }
+               return v
+       }
+
+       return pattern
+}
diff --git a/libgo/go/cmd/gofmt/simplify.go b/libgo/go/cmd/gofmt/simplify.go
new file mode 100644 (file)
index 0000000..45d000d
--- /dev/null
@@ -0,0 +1,121 @@
+// Copyright 2010 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/ast"
+       "go/token"
+       "reflect"
+)
+
+type simplifier struct {
+       hasDotImport bool // package file contains: import . "some/import/path"
+}
+
+func (s *simplifier) Visit(node ast.Node) ast.Visitor {
+       switch n := node.(type) {
+       case *ast.CompositeLit:
+               // array, slice, and map composite literals may be simplified
+               outer := n
+               var eltType ast.Expr
+               switch typ := outer.Type.(type) {
+               case *ast.ArrayType:
+                       eltType = typ.Elt
+               case *ast.MapType:
+                       eltType = typ.Value
+               }
+
+               if eltType != nil {
+                       typ := reflect.ValueOf(eltType)
+                       for i, x := range outer.Elts {
+                               px := &outer.Elts[i]
+                               // look at value of indexed/named elements
+                               if t, ok := x.(*ast.KeyValueExpr); ok {
+                                       x = t.Value
+                                       px = &t.Value
+                               }
+                               ast.Walk(s, x) // simplify x
+                               // if the element is a composite literal and its literal type
+                               // matches the outer literal's element type exactly, the inner
+                               // literal type may be omitted
+                               if inner, ok := x.(*ast.CompositeLit); ok {
+                                       if match(nil, typ, reflect.ValueOf(inner.Type)) {
+                                               inner.Type = nil
+                                       }
+                               }
+                               // if the outer literal's element type is a pointer type *T
+                               // and the element is & of a composite literal of type T,
+                               // the inner &T may be omitted.
+                               if ptr, ok := eltType.(*ast.StarExpr); ok {
+                                       if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND {
+                                               if inner, ok := addr.X.(*ast.CompositeLit); ok {
+                                                       if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) {
+                                                               inner.Type = nil // drop T
+                                                               *px = inner      // drop &
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       // node was simplified - stop walk (there are no subnodes to simplify)
+                       return nil
+               }
+
+       case *ast.SliceExpr:
+               // a slice expression of the form: s[a:len(s)]
+               // can be simplified to: s[a:]
+               // if s is "simple enough" (for now we only accept identifiers)
+               if s.hasDotImport {
+                       // if dot imports are present, we cannot be certain that an
+                       // unresolved "len" identifier refers to the predefined len()
+                       break
+               }
+               if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil {
+                       // the array/slice object is a single, resolved identifier
+                       if call, _ := n.High.(*ast.CallExpr); call != nil && len(call.Args) == 1 && !call.Ellipsis.IsValid() {
+                               // the high expression is a function call with a single argument
+                               if fun, _ := call.Fun.(*ast.Ident); fun != nil && fun.Name == "len" && fun.Obj == nil {
+                                       // the function called is "len" and it is not locally defined; and
+                                       // because we don't have dot imports, it must be the predefined len()
+                                       if arg, _ := call.Args[0].(*ast.Ident); arg != nil && arg.Obj == s.Obj {
+                                               // the len argument is the array/slice object
+                                               n.High = nil
+                                       }
+                               }
+                       }
+               }
+               // Note: We could also simplify slice expressions of the form s[0:b] to s[:b]
+               //       but we leave them as is since sometimes we want to be very explicit
+               //       about the lower bound.
+               // An example where the 0 helps:
+               //       x, y, z := b[0:2], b[2:4], b[4:6]
+               // An example where it does not:
+               //       x, y := b[:n], b[n:]
+
+       case *ast.RangeStmt:
+               // a range of the form: for x, _ = range v {...}
+               // can be simplified to: for x = range v {...}
+               if ident, _ := n.Value.(*ast.Ident); ident != nil && ident.Name == "_" {
+                       n.Value = nil
+               }
+       }
+
+       return s
+}
+
+func simplify(f *ast.File) {
+       var s simplifier
+
+       // determine if f contains dot imports
+       for _, imp := range f.Imports {
+               if imp.Name != nil && imp.Name.Name == "." {
+                       s.hasDotImport = true
+                       break
+               }
+       }
+
+       ast.Walk(&s, f)
+}
diff --git a/libgo/go/cmd/gofmt/testdata/comments.golden b/libgo/go/cmd/gofmt/testdata/comments.golden
new file mode 100644 (file)
index 0000000..ad6bcaf
--- /dev/null
@@ -0,0 +1,9 @@
+package main
+
+func main() {}
+
+// comment here
+
+func f() {}
+
+//line foo.go:1
diff --git a/libgo/go/cmd/gofmt/testdata/comments.input b/libgo/go/cmd/gofmt/testdata/comments.input
new file mode 100644 (file)
index 0000000..ad6bcaf
--- /dev/null
@@ -0,0 +1,9 @@
+package main
+
+func main() {}
+
+// comment here
+
+func f() {}
+
+//line foo.go:1
diff --git a/libgo/go/cmd/gofmt/testdata/composites.golden b/libgo/go/cmd/gofmt/testdata/composites.golden
new file mode 100644 (file)
index 0000000..b2825e7
--- /dev/null
@@ -0,0 +1,202 @@
+package P
+
+type T struct {
+       x, y int
+}
+
+var _ = [42]T{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = [...]T{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = []T{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = []T{
+       {},
+       10: {1, 2},
+       20: {3, 4},
+}
+
+var _ = []struct {
+       x, y int
+}{
+       {},
+       10: {1, 2},
+       20: {3, 4},
+}
+
+var _ = []interface{}{
+       T{},
+       10: T{1, 2},
+       20: T{3, 4},
+}
+
+var _ = [][]int{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = [][]int{
+       ([]int{}),
+       ([]int{1, 2}),
+       {3, 4},
+}
+
+var _ = [][][]int{
+       {},
+       {
+               {},
+               {0, 1, 2, 3},
+               {4, 5},
+       },
+}
+
+var _ = map[string]T{
+       "foo": {},
+       "bar": {1, 2},
+       "bal": {3, 4},
+}
+
+var _ = map[string]struct {
+       x, y int
+}{
+       "foo": {},
+       "bar": {1, 2},
+       "bal": {3, 4},
+}
+
+var _ = map[string]interface{}{
+       "foo": T{},
+       "bar": T{1, 2},
+       "bal": T{3, 4},
+}
+
+var _ = map[string][]int{
+       "foo": {},
+       "bar": {1, 2},
+       "bal": {3, 4},
+}
+
+var _ = map[string][]int{
+       "foo": ([]int{}),
+       "bar": ([]int{1, 2}),
+       "bal": {3, 4},
+}
+
+// from exp/4s/data.go
+var pieces4 = []Piece{
+       {0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+       {1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+       {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+       {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+}
+
+var _ = [42]*T{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = [...]*T{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = []*T{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = []*T{
+       {},
+       10: {1, 2},
+       20: {3, 4},
+}
+
+var _ = []*struct {
+       x, y int
+}{
+       {},
+       10: {1, 2},
+       20: {3, 4},
+}
+
+var _ = []interface{}{
+       &T{},
+       10: &T{1, 2},
+       20: &T{3, 4},
+}
+
+var _ = []*[]int{
+       {},
+       {1, 2},
+       {3, 4},
+}
+
+var _ = []*[]int{
+       (&[]int{}),
+       (&[]int{1, 2}),
+       {3, 4},
+}
+
+var _ = []*[]*[]int{
+       {},
+       {
+               {},
+               {0, 1, 2, 3},
+               {4, 5},
+       },
+}
+
+var _ = map[string]*T{
+       "foo": {},
+       "bar": {1, 2},
+       "bal": {3, 4},
+}
+
+var _ = map[string]*struct {
+       x, y int
+}{
+       "foo": {},
+       "bar": {1, 2},
+       "bal": {3, 4},
+}
+
+var _ = map[string]interface{}{
+       "foo": &T{},
+       "bar": &T{1, 2},
+       "bal": &T{3, 4},
+}
+
+var _ = map[string]*[]int{
+       "foo": {},
+       "bar": {1, 2},
+       "bal": {3, 4},
+}
+
+var _ = map[string]*[]int{
+       "foo": (&[]int{}),
+       "bar": (&[]int{1, 2}),
+       "bal": {3, 4},
+}
+
+var pieces4 = []*Piece{
+       {0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+       {1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+       {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil},
+       {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil},
+}
diff --git a/libgo/go/cmd/gofmt/testdata/composites.input b/libgo/go/cmd/gofmt/testdata/composites.input
new file mode 100644 (file)
index 0000000..7210daf
--- /dev/null
@@ -0,0 +1,202 @@
+package P
+
+type T struct {
+       x, y int
+}
+
+var _ = [42]T{
+       T{},
+       T{1, 2},
+       T{3, 4},
+}
+
+var _ = [...]T{
+       T{},
+       T{1, 2},
+       T{3, 4},
+}
+
+var _ = []T{
+       T{},
+       T{1, 2},
+       T{3, 4},
+}
+
+var _ = []T{
+       T{},
+       10: T{1, 2},
+       20: T{3, 4},
+}
+
+var _ = []struct {
+       x, y int
+}{
+       struct{ x, y int }{},
+       10: struct{ x, y int }{1, 2},
+       20: struct{ x, y int }{3, 4},
+}
+
+var _ = []interface{}{
+       T{},
+       10: T{1, 2},
+       20: T{3, 4},
+}
+
+var _ = [][]int{
+       []int{},
+       []int{1, 2},
+       []int{3, 4},
+}
+
+var _ = [][]int{
+       ([]int{}),
+       ([]int{1, 2}),
+       []int{3, 4},
+}
+
+var _ = [][][]int{
+       [][]int{},
+       [][]int{
+               []int{},
+               []int{0, 1, 2, 3},
+               []int{4, 5},
+       },
+}
+
+var _ = map[string]T{
+       "foo": T{},
+       "bar": T{1, 2},
+       "bal": T{3, 4},
+}
+
+var _ = map[string]struct {
+       x, y int
+}{
+       "foo": struct{ x, y int }{},
+       "bar": struct{ x, y int }{1, 2},
+       "bal": struct{ x, y int }{3, 4},
+}
+
+var _ = map[string]interface{}{
+       "foo": T{},
+       "bar": T{1, 2},
+       "bal": T{3, 4},
+}
+
+var _ = map[string][]int{
+       "foo": []int{},
+       "bar": []int{1, 2},
+       "bal": []int{3, 4},
+}
+
+var _ = map[string][]int{
+       "foo": ([]int{}),
+       "bar": ([]int{1, 2}),
+       "bal": []int{3, 4},
+}
+
+// from exp/4s/data.go
+var pieces4 = []Piece{
+       Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+       Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+       Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+       Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+}
+
+var _ = [42]*T{
+       &T{},
+       &T{1, 2},
+       &T{3, 4},
+}
+
+var _ = [...]*T{
+       &T{},
+       &T{1, 2},
+       &T{3, 4},
+}
+
+var _ = []*T{
+       &T{},
+       &T{1, 2},
+       &T{3, 4},
+}
+
+var _ = []*T{
+       &T{},
+       10: &T{1, 2},
+       20: &T{3, 4},
+}
+
+var _ = []*struct {
+       x, y int
+}{
+       &struct{ x, y int }{},
+       10: &struct{ x, y int }{1, 2},
+       20: &struct{ x, y int }{3, 4},
+}
+
+var _ = []interface{}{
+       &T{},
+       10: &T{1, 2},
+       20: &T{3, 4},
+}
+
+var _ = []*[]int{
+       &[]int{},
+       &[]int{1, 2},
+       &[]int{3, 4},
+}
+
+var _ = []*[]int{
+       (&[]int{}),
+       (&[]int{1, 2}),
+       &[]int{3, 4},
+}
+
+var _ = []*[]*[]int{
+       &[]*[]int{},
+       &[]*[]int{
+               &[]int{},
+               &[]int{0, 1, 2, 3},
+               &[]int{4, 5},
+       },
+}
+
+var _ = map[string]*T{
+       "foo": &T{},
+       "bar": &T{1, 2},
+       "bal": &T{3, 4},
+}
+
+var _ = map[string]*struct {
+       x, y int
+}{
+       "foo": &struct{ x, y int }{},
+       "bar": &struct{ x, y int }{1, 2},
+       "bal": &struct{ x, y int }{3, 4},
+}
+
+var _ = map[string]interface{}{
+       "foo": &T{},
+       "bar": &T{1, 2},
+       "bal": &T{3, 4},
+}
+
+var _ = map[string]*[]int{
+       "foo": &[]int{},
+       "bar": &[]int{1, 2},
+       "bal": &[]int{3, 4},
+}
+
+var _ = map[string]*[]int{
+       "foo": (&[]int{}),
+       "bar": (&[]int{1, 2}),
+       "bal": &[]int{3, 4},
+}
+
+var pieces4 = []*Piece{
+       &Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+       &Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+       &Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil},
+       &Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil},
+}
diff --git a/libgo/go/cmd/gofmt/testdata/crlf.golden b/libgo/go/cmd/gofmt/testdata/crlf.golden
new file mode 100644 (file)
index 0000000..57679f7
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+       Source containing CR/LF line endings.
+       The gofmt'ed output must only have LF
+       line endings.
+*/
+package main
+
+func main() {
+       // line comment
+       println("hello, world!") // another line comment
+       println()
+}
diff --git a/libgo/go/cmd/gofmt/testdata/crlf.input b/libgo/go/cmd/gofmt/testdata/crlf.input
new file mode 100644 (file)
index 0000000..61a1aa0
--- /dev/null
@@ -0,0 +1,12 @@
+/*\r
+       Source containing CR/LF line endings.\r
+       The gofmt'ed output must only have LF\r
+       line endings.\r
+*/\r
+package main\r
+\r
+func main() {\r
+       // line comment\r
+       println("hello, world!") // another line comment\r
+       println()\r
+}\r
diff --git a/libgo/go/cmd/gofmt/testdata/import.golden b/libgo/go/cmd/gofmt/testdata/import.golden
new file mode 100644 (file)
index 0000000..51d7be7
--- /dev/null
@@ -0,0 +1,126 @@
+package main
+
+import (
+       "errors"
+       "fmt"
+       "io"
+       "log"
+       "math"
+)
+
+import (
+       "fmt"
+
+       "math"
+
+       "log"
+
+       "errors"
+
+       "io"
+)
+
+import (
+       "errors"
+       "fmt"
+       "io"
+       "log"
+       "math"
+
+       "fmt"
+
+       "math"
+
+       "log"
+
+       "errors"
+
+       "io"
+)
+
+import (
+       // a block with comments
+       "errors"
+       "fmt" // for Printf
+       "io"  // for Reader
+       "log" // for Fatal
+       "math"
+)
+
+import (
+       "fmt" // for Printf
+
+       "math"
+
+       "log" // for Fatal
+
+       "errors"
+
+       "io" // for Reader
+)
+
+import (
+       // for Printf
+       "fmt"
+
+       "math"
+
+       // for Fatal
+       "log"
+
+       "errors"
+
+       // for Reader
+       "io"
+)
+
+import (
+       "errors"
+       "fmt" // for Printf
+       "io"  // for Reader
+       "log" // for Fatal
+       "math"
+
+       "fmt" // for Printf
+
+       "math"
+
+       "log" // for Fatal
+
+       "errors"
+
+       "io" // for Reader
+)
+
+import (
+       "fmt" // for Printf
+
+       "errors"
+       "io"  // for Reader
+       "log" // for Fatal
+       "math"
+
+       "errors"
+       "fmt" // for Printf
+       "io"  // for Reader
+       "log" // for Fatal
+       "math"
+)
+
+// Test deduping and extended sorting
+import (
+       a "A" // aA
+       b "A" // bA1
+       b "A" // bA2
+       "B"   // B
+       . "B" // .B
+       _ "B" // _b
+       "C"
+       a "D" // aD
+)
+
+import (
+       "dedup_by_group"
+
+       "dedup_by_group"
+)
diff --git a/libgo/go/cmd/gofmt/testdata/import.input b/libgo/go/cmd/gofmt/testdata/import.input
new file mode 100644 (file)
index 0000000..9a4b09d
--- /dev/null
@@ -0,0 +1,131 @@
+package main
+
+import (
+       "fmt"
+       "math"
+       "log"
+       "errors"
+       "io"
+)
+
+import (
+       "fmt"
+
+       "math"
+
+       "log"
+
+       "errors"
+
+       "io"
+)
+
+import (
+       "fmt"
+       "math"
+       "log"
+       "errors"
+       "io"
+
+       "fmt"
+
+       "math"
+
+       "log"
+
+       "errors"
+
+       "io"
+)
+
+import (
+       // a block with comments
+       "fmt" // for Printf
+       "math"
+       "log" // for Fatal
+       "errors"
+       "io" // for Reader
+)
+
+import (
+       "fmt" // for Printf
+
+       "math"
+
+       "log" // for Fatal
+
+       "errors"
+
+       "io" // for Reader
+)
+
+import (
+       // for Printf
+       "fmt"
+
+       "math"
+
+       // for Fatal
+       "log"
+
+       "errors"
+
+       // for Reader
+       "io"
+)
+
+import (
+       "fmt" // for Printf
+       "math"
+       "log" // for Fatal
+       "errors"
+       "io" // for Reader
+
+       "fmt" // for Printf
+
+       "math"
+
+       "log" // for Fatal
+
+       "errors"
+
+       "io" // for Reader
+)
+
+import (
+       "fmt" // for Printf
+
+       "math"
+       "log" // for Fatal
+       "errors"
+       "io" // for Reader
+
+       "fmt" // for Printf
+       "math"
+       "log" // for Fatal
+       "errors"
+       "io" // for Reader
+)
+
+// Test deduping and extended sorting
+import (
+       "B" // B
+       a "A" // aA
+       b "A" // bA2
+       b "A" // bA1
+       . "B" // .B
+       . "B"
+       "C"
+       "C"
+       "C"
+       a "D" // aD
+       "B"
+       _ "B" // _b
+)
+
+import (
+       "dedup_by_group"
+       "dedup_by_group"
+
+       "dedup_by_group"
+)
diff --git a/libgo/go/cmd/gofmt/testdata/old.golden b/libgo/go/cmd/gofmt/testdata/old.golden
new file mode 100644 (file)
index 0000000..95a0b72
--- /dev/null
@@ -0,0 +1,9 @@
+package P
+
+func f() {
+       if x {
+               y
+       } else {
+               z
+       }
+}
diff --git a/libgo/go/cmd/gofmt/testdata/old.input b/libgo/go/cmd/gofmt/testdata/old.input
new file mode 100644 (file)
index 0000000..e24eed2
--- /dev/null
@@ -0,0 +1,8 @@
+package P
+
+func f() {
+       if x {
+               y
+       } else
+               z
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite1.golden b/libgo/go/cmd/gofmt/testdata/rewrite1.golden
new file mode 100644 (file)
index 0000000..d9beb37
--- /dev/null
@@ -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
+
+type Bar int
+
+func main() {
+       var a Bar
+       println(a)
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite1.input b/libgo/go/cmd/gofmt/testdata/rewrite1.input
new file mode 100644 (file)
index 0000000..bdb8943
--- /dev/null
@@ -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
+
+type Foo int
+
+func main() {
+       var a Foo
+       println(a)
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite2.golden b/libgo/go/cmd/gofmt/testdata/rewrite2.golden
new file mode 100644 (file)
index 0000000..64c67ff
--- /dev/null
@@ -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.
+
+package p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []bool {}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite2.input b/libgo/go/cmd/gofmt/testdata/rewrite2.input
new file mode 100644 (file)
index 0000000..2117144
--- /dev/null
@@ -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.
+
+package p
+
+// Slices have nil Len values in the corresponding ast.ArrayType
+// node and reflect.NewValue(slice.Len) is an invalid reflect.Value.
+// The rewriter must not crash in that case. Was issue 1696.
+func f() []int {}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite3.golden b/libgo/go/cmd/gofmt/testdata/rewrite3.golden
new file mode 100644 (file)
index 0000000..0d16d16
--- /dev/null
@@ -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
+
+// Field tags are *ast.BasicLit nodes that are nil when the tag is
+// absent. These nil nodes must not be mistaken for expressions,
+// the rewriter should not try to dereference them. Was issue 2410.
+type Foo struct {
+       Field int
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite3.input b/libgo/go/cmd/gofmt/testdata/rewrite3.input
new file mode 100644 (file)
index 0000000..0d16d16
--- /dev/null
@@ -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
+
+// Field tags are *ast.BasicLit nodes that are nil when the tag is
+// absent. These nil nodes must not be mistaken for expressions,
+// the rewriter should not try to dereference them. Was issue 2410.
+type Foo struct {
+       Field int
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite4.golden b/libgo/go/cmd/gofmt/testdata/rewrite4.golden
new file mode 100644 (file)
index 0000000..8dfc81a
--- /dev/null
@@ -0,0 +1,74 @@
+// 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.
+
+// Rewriting of parenthesized expressions (x) -> x
+// must not drop parentheses if that would lead to
+// wrong association of the operands.
+// Was issue 1847.
+
+package main
+
+// From example 1 of issue 1847.
+func _() {
+       var t = (&T{1000}).Id()
+}
+
+// From example 2 of issue 1847.
+func _() {
+       fmt.Println((*xpp).a)
+}
+
+// Some more test cases.
+func _() {
+       _ = (-x).f
+       _ = (*x).f
+       _ = (&x).f
+       _ = (!x).f
+       _ = -x.f
+       _ = *x.f
+       _ = &x.f
+       _ = !x.f
+       (-x).f()
+       (*x).f()
+       (&x).f()
+       (!x).f()
+       _ = -x.f()
+       _ = *x.f()
+       _ = &x.f()
+       _ = !x.f()
+
+       _ = (-x).f
+       _ = (*x).f
+       _ = (&x).f
+       _ = (!x).f
+       _ = -x.f
+       _ = *x.f
+       _ = &x.f
+       _ = !x.f
+       (-x).f()
+       (*x).f()
+       (&x).f()
+       (!x).f()
+       _ = -x.f()
+       _ = *x.f()
+       _ = &x.f()
+       _ = !x.f()
+
+       _ = -x.f
+       _ = *x.f
+       _ = &x.f
+       _ = !x.f
+       _ = -x.f
+       _ = *x.f
+       _ = &x.f
+       _ = !x.f
+       _ = -x.f()
+       _ = *x.f()
+       _ = &x.f()
+       _ = !x.f()
+       _ = -x.f()
+       _ = *x.f()
+       _ = &x.f()
+       _ = !x.f()
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite4.input b/libgo/go/cmd/gofmt/testdata/rewrite4.input
new file mode 100644 (file)
index 0000000..164cc04
--- /dev/null
@@ -0,0 +1,74 @@
+// 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.
+
+// Rewriting of parenthesized expressions (x) -> x
+// must not drop parentheses if that would lead to
+// wrong association of the operands.
+// Was issue 1847.
+
+package main
+
+// From example 1 of issue 1847.
+func _() {
+       var t = (&T{1000}).Id()
+}
+
+// From example 2 of issue 1847.
+func _() {
+       fmt.Println((*xpp).a)
+}
+
+// Some more test cases.
+func _() {
+       _ = (-x).f
+       _ = (*x).f
+       _ = (&x).f
+       _ = (!x).f
+       _ = (-x.f)
+       _ = (*x.f)
+       _ = (&x.f)
+       _ = (!x.f)
+       (-x).f()
+       (*x).f()
+       (&x).f()
+       (!x).f()
+       _ = (-x.f())
+       _ = (*x.f())
+       _ = (&x.f())
+       _ = (!x.f())
+
+       _ = ((-x)).f
+       _ = ((*x)).f
+       _ = ((&x)).f
+       _ = ((!x)).f
+       _ = ((-x.f))
+       _ = ((*x.f))
+       _ = ((&x.f))
+       _ = ((!x.f))
+       ((-x)).f()
+       ((*x)).f()
+       ((&x)).f()
+       ((!x)).f()
+       _ = ((-x.f()))
+       _ = ((*x.f()))
+       _ = ((&x.f()))
+       _ = ((!x.f()))
+
+       _ = -(x).f
+       _ = *(x).f
+       _ = &(x).f
+       _ = !(x).f
+       _ = -x.f
+       _ = *x.f
+       _ = &x.f
+       _ = !x.f
+       _ = -(x).f()
+       _ = *(x).f()
+       _ = &(x).f()
+       _ = !(x).f()
+       _ = -x.f()
+       _ = *x.f()
+       _ = &x.f()
+       _ = !x.f()
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite5.golden b/libgo/go/cmd/gofmt/testdata/rewrite5.golden
new file mode 100644 (file)
index 0000000..5a448a6
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+// Rewriting of expressions containing nodes with associated comments to
+// expressions without those nodes must also eliminate the associated
+// comments.
+
+package p
+
+func f(x int) int {
+       _ = 2 * x // this comment remains in the rewrite
+       _ = 2 * x
+       return 2 * x
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite5.input b/libgo/go/cmd/gofmt/testdata/rewrite5.input
new file mode 100644 (file)
index 0000000..0d759e6
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+// Rewriting of expressions containing nodes with associated comments to
+// expressions without those nodes must also eliminate the associated
+// comments.
+
+package p
+
+func f(x int) int {
+       _ = x + x // this comment remains in the rewrite
+       _ = x /* this comment must not be in the rewrite */ + x
+       return x /* this comment must not be in the rewrite */ + x
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite6.golden b/libgo/go/cmd/gofmt/testdata/rewrite6.golden
new file mode 100644 (file)
index 0000000..e565dbd
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+       Fun(x)    // -r='fun(x)->Fun(x)' should rewrite this to Fun(x)
+       fun(x...) // -r='fun(x)->Fun(x)' should not rewrite this
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite6.input b/libgo/go/cmd/gofmt/testdata/rewrite6.input
new file mode 100644 (file)
index 0000000..8c088b3
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+       fun(x)    // -r='fun(x)->Fun(x)' should rewrite this to Fun(x)
+       fun(x...) // -r='fun(x)->Fun(x)' should not rewrite this
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite7.golden b/libgo/go/cmd/gofmt/testdata/rewrite7.golden
new file mode 100644 (file)
index 0000000..29babad
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+       fun(x) // -r='fun(x...)->Fun(x)' should not rewrite this
+       Fun(x) // -r='fun(x...)->Fun(x)' should rewrite this to Fun(x)
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite7.input b/libgo/go/cmd/gofmt/testdata/rewrite7.input
new file mode 100644 (file)
index 0000000..073e2a3
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2013 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.
+
+// Rewriting of calls must take the ... (ellipsis)
+// attribute for the last argument into account.
+
+package p
+
+func fun(x []int) {}
+
+func g(x []int) {
+       fun(x)    // -r='fun(x...)->Fun(x)' should not rewrite this
+       fun(x...) // -r='fun(x...)->Fun(x)' should rewrite this to Fun(x)
+}
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite8.golden b/libgo/go/cmd/gofmt/testdata/rewrite8.golden
new file mode 100644 (file)
index 0000000..cfc452b
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+// Check that literal type expression rewrites are accepted.
+// Was issue 4406.
+
+package p
+
+type T int
diff --git a/libgo/go/cmd/gofmt/testdata/rewrite8.input b/libgo/go/cmd/gofmt/testdata/rewrite8.input
new file mode 100644 (file)
index 0000000..235efa9
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2013 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.
+
+// Check that literal type expression rewrites are accepted.
+// Was issue 4406.
+
+package p
+
+type T interface{}
diff --git a/libgo/go/cmd/gofmt/testdata/slices1.golden b/libgo/go/cmd/gofmt/testdata/slices1.golden
new file mode 100644 (file)
index 0000000..61e074f
--- /dev/null
@@ -0,0 +1,58 @@
+// Test cases for slice expression simplification.
+package p
+
+var (
+       a [10]byte
+       b [20]float32
+       s []int
+       t struct {
+               s []byte
+       }
+
+       _ = a[0:]
+       _ = a[1:10]
+       _ = a[2:]
+       _ = a[3:(len(a))]
+       _ = a[len(a) : len(a)-1]
+       _ = a[0:len(b)]
+
+       _ = a[:]
+       _ = a[:10]
+       _ = a[:]
+       _ = a[:(len(a))]
+       _ = a[:len(a)-1]
+       _ = a[:len(b)]
+
+       _ = s[0:]
+       _ = s[1:10]
+       _ = s[2:]
+       _ = s[3:(len(s))]
+       _ = s[len(a) : len(s)-1]
+       _ = s[0:len(b)]
+
+       _ = s[:]
+       _ = s[:10]
+       _ = s[:]
+       _ = s[:(len(s))]
+       _ = s[:len(s)-1]
+       _ = s[:len(b)]
+
+       _ = t.s[0:]
+       _ = t.s[1:10]
+       _ = t.s[2:len(t.s)]
+       _ = t.s[3:(len(t.s))]
+       _ = t.s[len(a) : len(t.s)-1]
+       _ = t.s[0:len(b)]
+
+       _ = t.s[:]
+       _ = t.s[:10]
+       _ = t.s[:len(t.s)]
+       _ = t.s[:(len(t.s))]
+       _ = t.s[:len(t.s)-1]
+       _ = t.s[:len(b)]
+)
+
+func _() {
+       s := s[0:]
+       _ = s
+}
diff --git a/libgo/go/cmd/gofmt/testdata/slices1.input b/libgo/go/cmd/gofmt/testdata/slices1.input
new file mode 100644 (file)
index 0000000..4d2cbff
--- /dev/null
@@ -0,0 +1,58 @@
+// Test cases for slice expression simplification.
+package p
+
+var (
+       a [10]byte
+       b [20]float32
+       s []int
+       t struct {
+               s []byte
+       }
+
+       _ = a[0:]
+       _ = a[1:10]
+       _ = a[2:len(a)]
+       _ = a[3:(len(a))]
+       _ = a[len(a) : len(a)-1]
+       _ = a[0:len(b)]
+
+       _ = a[:]
+       _ = a[:10]
+       _ = a[:len(a)]
+       _ = a[:(len(a))]
+       _ = a[:len(a)-1]
+       _ = a[:len(b)]
+
+       _ = s[0:]
+       _ = s[1:10]
+       _ = s[2:len(s)]
+       _ = s[3:(len(s))]
+       _ = s[len(a) : len(s)-1]
+       _ = s[0:len(b)]
+
+       _ = s[:]
+       _ = s[:10]
+       _ = s[:len(s)]
+       _ = s[:(len(s))]
+       _ = s[:len(s)-1]
+       _ = s[:len(b)]
+
+       _ = t.s[0:]
+       _ = t.s[1:10]
+       _ = t.s[2:len(t.s)]
+       _ = t.s[3:(len(t.s))]
+       _ = t.s[len(a) : len(t.s)-1]
+       _ = t.s[0:len(b)]
+
+       _ = t.s[:]
+       _ = t.s[:10]
+       _ = t.s[:len(t.s)]
+       _ = t.s[:(len(t.s))]
+       _ = t.s[:len(t.s)-1]
+       _ = t.s[:len(b)]
+)
+
+func _() {
+       s := s[0:len(s)]
+       _ = s
+}
diff --git a/libgo/go/cmd/gofmt/testdata/slices2.golden b/libgo/go/cmd/gofmt/testdata/slices2.golden
new file mode 100644 (file)
index 0000000..433788e
--- /dev/null
@@ -0,0 +1,61 @@
+// Test cases for slice expression simplification.
+// Because of a dot import, these slices must remain untouched.
+package p
+
+import . "math"
+
+var (
+       a [10]byte
+       b [20]float32
+       s []int
+       t struct {
+               s []byte
+       }
+
+       _ = a[0:]
+       _ = a[1:10]
+       _ = a[2:len(a)]
+       _ = a[3:(len(a))]
+       _ = a[len(a) : len(a)-1]
+       _ = a[0:len(b)]
+
+       _ = a[:]
+       _ = a[:10]
+       _ = a[:len(a)]
+       _ = a[:(len(a))]
+       _ = a[:len(a)-1]
+       _ = a[:len(b)]
+
+       _ = s[0:]
+       _ = s[1:10]
+       _ = s[2:len(s)]
+       _ = s[3:(len(s))]
+       _ = s[len(a) : len(s)-1]
+       _ = s[0:len(b)]
+
+       _ = s[:]
+       _ = s[:10]
+       _ = s[:len(s)]
+       _ = s[:(len(s))]
+       _ = s[:len(s)-1]
+       _ = s[:len(b)]
+
+       _ = t.s[0:]
+       _ = t.s[1:10]
+       _ = t.s[2:len(t.s)]
+       _ = t.s[3:(len(t.s))]
+       _ = t.s[len(a) : len(t.s)-1]
+       _ = t.s[0:len(b)]
+
+       _ = t.s[:]
+       _ = t.s[:10]
+       _ = t.s[:len(t.s)]
+       _ = t.s[:(len(t.s))]
+       _ = t.s[:len(t.s)-1]
+       _ = t.s[:len(b)]
+)
+
+func _() {
+       s := s[0:len(s)]
+       _ = s
+}
diff --git a/libgo/go/cmd/gofmt/testdata/slices2.input b/libgo/go/cmd/gofmt/testdata/slices2.input
new file mode 100644 (file)
index 0000000..433788e
--- /dev/null
@@ -0,0 +1,61 @@
+// Test cases for slice expression simplification.
+// Because of a dot import, these slices must remain untouched.
+package p
+
+import . "math"
+
+var (
+       a [10]byte
+       b [20]float32
+       s []int
+       t struct {
+               s []byte
+       }
+
+       _ = a[0:]
+       _ = a[1:10]
+       _ = a[2:len(a)]
+       _ = a[3:(len(a))]
+       _ = a[len(a) : len(a)-1]
+       _ = a[0:len(b)]
+
+       _ = a[:]
+       _ = a[:10]
+       _ = a[:len(a)]
+       _ = a[:(len(a))]
+       _ = a[:len(a)-1]
+       _ = a[:len(b)]
+
+       _ = s[0:]
+       _ = s[1:10]
+       _ = s[2:len(s)]
+       _ = s[3:(len(s))]
+       _ = s[len(a) : len(s)-1]
+       _ = s[0:len(b)]
+
+       _ = s[:]
+       _ = s[:10]
+       _ = s[:len(s)]
+       _ = s[:(len(s))]
+       _ = s[:len(s)-1]
+       _ = s[:len(b)]
+
+       _ = t.s[0:]
+       _ = t.s[1:10]
+       _ = t.s[2:len(t.s)]
+       _ = t.s[3:(len(t.s))]
+       _ = t.s[len(a) : len(t.s)-1]
+       _ = t.s[0:len(b)]
+
+       _ = t.s[:]
+       _ = t.s[:10]
+       _ = t.s[:len(t.s)]
+       _ = t.s[:(len(t.s))]
+       _ = t.s[:len(t.s)-1]
+       _ = t.s[:len(b)]
+)
+
+func _() {
+       s := s[0:len(s)]
+       _ = s
+}
diff --git a/libgo/go/cmd/gofmt/testdata/stdin1.golden b/libgo/go/cmd/gofmt/testdata/stdin1.golden
new file mode 100644 (file)
index 0000000..ff8b0b7
--- /dev/null
@@ -0,0 +1,3 @@
+       if x {
+               y
+       }
diff --git a/libgo/go/cmd/gofmt/testdata/stdin1.golden.gofmt b/libgo/go/cmd/gofmt/testdata/stdin1.golden.gofmt
new file mode 100644 (file)
index 0000000..1f88887
--- /dev/null
@@ -0,0 +1,3 @@
+       if x {
+       y
+}
diff --git a/libgo/go/cmd/gofmt/testdata/stdin1.input b/libgo/go/cmd/gofmt/testdata/stdin1.input
new file mode 100644 (file)
index 0000000..ff8b0b7
--- /dev/null
@@ -0,0 +1,3 @@
+       if x {
+               y
+       }
diff --git a/libgo/go/cmd/gofmt/testdata/stdin1.input.gofmt b/libgo/go/cmd/gofmt/testdata/stdin1.input.gofmt
new file mode 100644 (file)
index 0000000..1f88887
--- /dev/null
@@ -0,0 +1,3 @@
+       if x {
+       y
+}
diff --git a/libgo/go/cmd/gofmt/testdata/stdin2.golden b/libgo/go/cmd/gofmt/testdata/stdin2.golden
new file mode 100644 (file)
index 0000000..7eb1b54
--- /dev/null
@@ -0,0 +1,11 @@
+
+
+var x int
+
+func f() {
+       y := z
+       /* this is a comment */
+       // this is a comment too
+}
+
+
diff --git a/libgo/go/cmd/gofmt/testdata/stdin2.golden.gofmt b/libgo/go/cmd/gofmt/testdata/stdin2.golden.gofmt
new file mode 100644 (file)
index 0000000..85e8003
--- /dev/null
@@ -0,0 +1,10 @@
+
+
+
+var x int
+
+func f() {
+       y := z
+}
+
+
diff --git a/libgo/go/cmd/gofmt/testdata/stdin2.input b/libgo/go/cmd/gofmt/testdata/stdin2.input
new file mode 100644 (file)
index 0000000..99defd2
--- /dev/null
@@ -0,0 +1,11 @@
+
+
+var x int
+
+
+func f() { y := z
+       /* this is a comment */
+       // this is a comment too
+}
+
+
diff --git a/libgo/go/cmd/gofmt/testdata/stdin2.input.gofmt b/libgo/go/cmd/gofmt/testdata/stdin2.input.gofmt
new file mode 100644 (file)
index 0000000..7eb1b54
--- /dev/null
@@ -0,0 +1,11 @@
+
+
+var x int
+
+func f() {
+       y := z
+       /* this is a comment */
+       // this is a comment too
+}
+
+
diff --git a/libgo/go/cmd/gofmt/testdata/stdin3.golden b/libgo/go/cmd/gofmt/testdata/stdin3.golden
new file mode 100644 (file)
index 0000000..1bf2f5a
--- /dev/null
@@ -0,0 +1,6 @@
+
+               /* note: no newline at end of file */
+               for i := 0; i < 10; i++ {
+                       s += i
+               }
+       
\ No newline at end of file
diff --git a/libgo/go/cmd/gofmt/testdata/stdin3.golden.gofmt b/libgo/go/cmd/gofmt/testdata/stdin3.golden.gofmt
new file mode 100644 (file)
index 0000000..b4d1d46
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+               /* note: no newline at end of file */
+               for i := 0; i < 10; i++ {
+                       s += i
+               }
+       
\ No newline at end of file
diff --git a/libgo/go/cmd/gofmt/testdata/stdin3.input b/libgo/go/cmd/gofmt/testdata/stdin3.input
new file mode 100644 (file)
index 0000000..d963bd0
--- /dev/null
@@ -0,0 +1,4 @@
+
+               /* note: no newline at end of file */
+               for i := 0; i < 10; i++ { s += i }
+       
\ No newline at end of file
diff --git a/libgo/go/cmd/gofmt/testdata/stdin3.input.gofmt b/libgo/go/cmd/gofmt/testdata/stdin3.input.gofmt
new file mode 100644 (file)
index 0000000..b4d1d46
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+               /* note: no newline at end of file */
+               for i := 0; i < 10; i++ {
+                       s += i
+               }
+       
\ No newline at end of file
diff --git a/libgo/go/cmd/gofmt/testdata/stdin4.golden b/libgo/go/cmd/gofmt/testdata/stdin4.golden
new file mode 100644 (file)
index 0000000..5f73435
--- /dev/null
@@ -0,0 +1,3 @@
+       // comment
+
+       i := 0
diff --git a/libgo/go/cmd/gofmt/testdata/stdin4.golden.gofmt b/libgo/go/cmd/gofmt/testdata/stdin4.golden.gofmt
new file mode 100644 (file)
index 0000000..5f73435
--- /dev/null
@@ -0,0 +1,3 @@
+       // comment
+
+       i := 0
diff --git a/libgo/go/cmd/gofmt/testdata/stdin4.input b/libgo/go/cmd/gofmt/testdata/stdin4.input
new file mode 100644 (file)
index 0000000..f02a54f
--- /dev/null
@@ -0,0 +1,3 @@
+       // comment
+       
+       i := 0
diff --git a/libgo/go/cmd/gofmt/testdata/stdin4.input.gofmt b/libgo/go/cmd/gofmt/testdata/stdin4.input.gofmt
new file mode 100644 (file)
index 0000000..5f73435
--- /dev/null
@@ -0,0 +1,3 @@
+       // comment
+
+       i := 0
diff --git a/libgo/go/cmd/gofmt/testdata/typeswitch.golden b/libgo/go/cmd/gofmt/testdata/typeswitch.golden
new file mode 100644 (file)
index 0000000..2b1905e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+       Parenthesized type switch expressions originally
+       accepted by gofmt must continue to be rewritten
+       into the correct unparenthesized form.
+
+       Only type-switches that didn't declare a variable
+       in the type switch type assertion and which
+       contained only "expression-like" (named) types in their
+       cases were permitted to have their type assertion parenthesized
+       by go/parser (due to a weak predicate in the parser). All others
+       were rejected always, either with a syntax error in the
+       type switch header or in the case.
+
+       See also issue 4470.
+*/
+package p
+
+func f() {
+       var x interface{}
+       switch x.(type) { // should remain the same
+       }
+       switch x.(type) { // should become: switch x.(type) {
+       }
+
+       switch x.(type) { // should remain the same
+       case int:
+       }
+       switch x.(type) { // should become: switch x.(type) {
+       case int:
+       }
+
+       switch x.(type) { // should remain the same
+       case []int:
+       }
+
+       // Parenthesized (x.(type)) in type switches containing cases
+       // with unnamed (literal) types were never permitted by gofmt;
+       // thus there won't be any code in the wild using this style if
+       // the code was gofmt-ed.
+       /*
+               switch (x.(type)) {
+               case []int:
+               }
+       */
+
+       switch t := x.(type) { // should remain the same
+       default:
+               _ = t
+       }
+
+       // Parenthesized (x.(type)) in type switches declaring a variable
+       // were never permitted by gofmt; thus there won't be any code in
+       // the wild using this style if the code was gofmt-ed.
+       /*
+               switch t := (x.(type)) {
+               default:
+                       _ = t
+               }
+       */
+}
diff --git a/libgo/go/cmd/gofmt/testdata/typeswitch.input b/libgo/go/cmd/gofmt/testdata/typeswitch.input
new file mode 100644 (file)
index 0000000..8f8cba9
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+       Parenthesized type switch expressions originally
+       accepted by gofmt must continue to be rewritten
+       into the correct unparenthesized form.
+
+       Only type-switches that didn't declare a variable
+       in the type switch type assertion and which
+       contained only "expression-like" (named) types in their
+       cases were permitted to have their type assertion parenthesized
+       by go/parser (due to a weak predicate in the parser). All others
+       were rejected always, either with a syntax error in the
+       type switch header or in the case.
+
+       See also issue 4470.
+*/
+package p
+
+func f() {
+       var x interface{}
+       switch x.(type) { // should remain the same
+       }
+       switch (x.(type)) { // should become: switch x.(type) {
+       }
+
+       switch x.(type) { // should remain the same
+       case int:
+       }
+       switch (x.(type)) { // should become: switch x.(type) {
+       case int:
+       }
+
+       switch x.(type) { // should remain the same
+       case []int:
+       }
+
+       // Parenthesized (x.(type)) in type switches containing cases
+       // with unnamed (literal) types were never permitted by gofmt;
+       // thus there won't be any code in the wild using this style if
+       // the code was gofmt-ed.
+       /*
+       switch (x.(type)) {
+       case []int:
+       }
+       */
+
+       switch t := x.(type) { // should remain the same
+       default:
+               _ = t
+       }
+
+       // Parenthesized (x.(type)) in type switches declaring a variable
+       // were never permitted by gofmt; thus there won't be any code in
+       // the wild using this style if the code was gofmt-ed.
+       /*
+       switch t := (x.(type)) {
+       default:
+               _ = t
+       }
+       */
+}
index 1032c93c7e278f95517b04979129742878a3e2a5..5fe7dcb6b2f8e5dfc50384e5b930ee37df9ac963 100644 (file)
@@ -268,6 +268,8 @@ var cgoEnabled = map[string]bool{
        "linux/386":       true,
        "linux/amd64":     true,
        "linux/arm":       true,
+       "linux/ppc64":     true,
+       "linux/ppc64le":   true,
        "linux/s390":      true,
        "linux/s390x":     true,
        "netbsd/386":      true,
@@ -1196,8 +1198,15 @@ func init() {
        }
 }
 
-// ToolDir is the directory containing build tools.
-var ToolDir = filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
+func getToolDir() string {
+       if runtime.Compiler == "gccgo" {
+               return runtime.GCCGOTOOLDIR
+       } else {
+               return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
+       }
+}
+
+var ToolDir = getToolDir()
 
 // IsLocalImport reports whether the import path is
 // a local import path, like ".", "..", "./foo", or "../foo".
@@ -1218,6 +1227,8 @@ func ArchChar(goarch string) (string, error) {
                return "5", nil
        case "arm64":
                return "7", nil
+       case "ppc64", "ppc64le":
+               return "9", nil
        }
        return "", errors.New("unsupported GOARCH " + goarch)
 }
index 333d4fd000f4de9944a99e12e96a7cee9669ca86..393984c7d577f818821a2bc30869d7d362a3fe4b 100644 (file)
@@ -201,5 +201,8 @@ func Version() string {
 const GOOS string = theGoos
 
 // GOARCH is the running program's architecture target:
-// 386, amd64, arm or arm64.
+// 386, amd64, arm, arm64, ppc64, ppc64le.
 const GOARCH string = theGoarch
+
+// GCCGOTOOLDIR is the Tool Dir for the gccgo build
+const GCCGOTOOLDIR string = theGccgoToolDir
index e579ac7c41b9539240dca95df42ad7f08f3fd7b0..fb0d1afe82ff938df946f08e2ae0ca978c8f8061 100755 (executable)
@@ -163,6 +163,36 @@ done
   done
 done
 
+cmdlist="cgo go gofmt"
+for c in $cmdlist; do
+  (cd ${NEWDIR}/src/cmd/$c && find . -name '*.go' -print) | while read f; do
+    oldfile=${OLDDIR}/src/cmd/$c/$f
+    newfile=${NEWDIR}/src/cmd/$c/$f
+    libgofile=go/cmd/$c/$f
+    merge $f ${oldfile} ${newfile} ${libgofile}
+  done
+
+  (cd ${NEWDIR}/src/cmd/$c && find . -name testdata -print) | while read d; do
+    oldtd=${OLDDIR}/src/cmd/$c/$d
+    newtd=${NEWDIR}/src/cmd/$c/$d
+    libgotd=go/cmd/$c/$d
+    if ! test -d ${oldtd}; then
+      continue
+    fi
+    (cd ${oldtd} && hg status -A .) | while read f; do
+      if test "`basename $f`" = ".hgignore"; then
+        continue
+      fi
+      f=`echo $f | sed -e 's/^..//'`
+      name=$d/$f
+      oldfile=${oldtd}/$f
+      newfile=${newtd}/$f
+      libgofile=${libgotd}/$f
+      merge ${name} ${oldfile} ${newfile} ${libgofile}
+    done
+  done
+done
+
 runtime="chan.goc chan.h cpuprof.goc env_posix.c heapdump.c lock_futex.c lfstack.goc lock_sema.c mcache.c mcentral.c mfixalloc.c mgc0.c mgc0.h mheap.c msize.c netpoll.goc netpoll_epoll.c netpoll_kqueue.c netpoll_stub.c panic.c print.c proc.c race.h rdebug.goc runtime.c runtime.h signal_unix.c signal_unix.h malloc.h malloc.goc mprof.goc parfor.c runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
 for f in $runtime; do
   merge_c $f $f