libgo: Add sources for go, cgo, and gofmt commands.

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
This commit is contained in:
Ian Lance Taylor 2015-01-06 23:26:02 +00:00
parent efcdb22fe3
commit 7d7d64c1ae
135 changed files with 18991 additions and 3 deletions

View 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) $@

View 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) $@

460
libgo/go/cmd/cgo/ast.go Normal file
View File

@ -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)
}
}
}

748
libgo/go/cmd/cgo/doc.go Normal file
View File

@ -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.
*/

1728
libgo/go/cmd/cgo/gcc.go Normal file

File diff suppressed because it is too large Load Diff

294
libgo/go/cmd/cgo/godefs.go Normal file
View File

@ -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()
}

360
libgo/go/cmd/cgo/main.go Normal file
View File

@ -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...)
}

1299
libgo/go/cmd/cgo/out.go Normal file

File diff suppressed because it is too large Load Diff

84
libgo/go/cmd/cgo/util.go Normal file
View File

@ -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
}

View File

@ -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")
}

2594
libgo/go/cmd/go/build.go Normal file

File diff suppressed because it is too large Load Diff

248
libgo/go/cmd/go/clean.go Normal file
View File

@ -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)
}

View File

@ -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,
}
}

View File

@ -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 ""
}

990
libgo/go/cmd/go/doc.go Normal file
View File

@ -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

112
libgo/go/cmd/go/env.go Normal file
View File

@ -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)
}
}
}
}

30
libgo/go/cmd/go/fix.go Normal file
View File

@ -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)))
}
}

38
libgo/go/cmd/go/fmt.go Normal file
View File

@ -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)))
}
}

429
libgo/go/cmd/go/get.go Normal file
View File

@ -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
}

10
libgo/go/cmd/go/go11.go Normal file
View File

@ -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

337
libgo/go/cmd/go/help.go Normal file
View File

@ -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.
`,
}

87
libgo/go/cmd/go/http.go Normal file
View File

@ -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
}

208
libgo/go/cmd/go/list.go Normal file
View File

@ -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'
}

722
libgo/go/cmd/go/main.go Normal file
View File

@ -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 "", ""
}

View File

@ -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)
}
}
}

9
libgo/go/cmd/go/mkdoc.sh Normal file
View File

@ -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

856
libgo/go/cmd/go/pkg.go Normal file
View File

@ -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
}

View File

@ -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)
}
}
}

143
libgo/go/cmd/go/run.go Normal file
View File

@ -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)
}
}

23
libgo/go/cmd/go/script Normal file
View File

@ -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

352
libgo/go/cmd/go/script.txt Normal file
View File

@ -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.
---

31
libgo/go/cmd/go/signal.go Normal file
View File

@ -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)
}

View File

@ -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

View File

@ -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

100
libgo/go/cmd/go/tag_test.go Normal file
View File

@ -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)
}
}
}

820
libgo/go/cmd/go/test.bash Normal file
View File

@ -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

1308
libgo/go/cmd/go/test.go Normal file

File diff suppressed because it is too large Load Diff

19
libgo/go/cmd/go/testdata/cgocover/p.go vendored Normal file
View File

@ -0,0 +1,19 @@
package p
/*
void
f(void)
{
}
*/
import "C"
var b bool
func F() {
if b {
for {
}
}
C.f()
}

View File

@ -0,0 +1,7 @@
package p
import "testing"
func TestF(t *testing.T) {
F()
}

7
libgo/go/cmd/go/testdata/dep_test.go vendored Normal file
View File

@ -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"

View File

@ -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
}

View File

@ -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
}

View File

@ -0,0 +1,7 @@
package main
import "./easysub"
func main() {
easysub.Hello()
}

View File

@ -0,0 +1,7 @@
package easysub
import "fmt"
func Hello() {
fmt.Println("easysub.Hello")
}

View File

@ -0,0 +1,9 @@
// +build ignore
package main
import "."
func main() {
easysub.Hello()
}

View File

@ -0,0 +1,7 @@
package main
import "./sub"
func main() {
sub.Hello()
}

View File

@ -0,0 +1,12 @@
package sub
import (
"fmt"
subsub "./sub"
)
func Hello() {
fmt.Println("sub.Hello")
subsub.Hello()
}

View File

@ -0,0 +1,7 @@
package subsub
import "fmt"
func Hello() {
fmt.Println("subsub.Hello")
}

View File

@ -0,0 +1 @@
package foo

View File

@ -0,0 +1 @@
package math

View File

@ -0,0 +1 @@
package foo

View File

@ -0,0 +1 @@
pkg badpkg

View File

@ -0,0 +1,5 @@
package cgotest
import "C"
var _ C.int

View File

@ -0,0 +1,5 @@
package main
func main() {
println("hello world")
}

View File

@ -0,0 +1,4 @@
package main
func F() {}
func main() {}

View File

@ -0,0 +1,10 @@
package main_test
import (
. "main_test"
"testing"
)
func Test1(t *testing.T) {
F()
}

View File

@ -0,0 +1,6 @@
package notest
func hello() {
println("hello world")
}
Hello world

View File

@ -0,0 +1 @@
package p

View File

@ -0,0 +1,4 @@
package p
func f() (x.y, z int) {
}

View File

@ -0,0 +1,7 @@
package p1
import _ "testcycle/p2"
func init() {
println("p1 init")
}

View File

@ -0,0 +1,6 @@
package p1
import "testing"
func Test(t *testing.T) {
}

View File

@ -0,0 +1,7 @@
package p2
import _ "testcycle/p3"
func init() {
println("p2 init")
}

View File

@ -0,0 +1,5 @@
package p3
func init() {
println("p3 init")
}

View File

@ -0,0 +1,10 @@
package p3
import (
"testing"
_ "testcycle/p1"
)
func Test(t *testing.T) {
}

View File

@ -0,0 +1,3 @@
package xtestonly
func F() int { return 42 }

View File

@ -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)
}
}

View File

@ -0,0 +1,6 @@
package standalone_test
import "testing"
func Test(t *testing.T) {
}

View File

@ -0,0 +1,3 @@
package p
func F() int { return 1 }

View File

@ -0,0 +1,3 @@
package p1
func F() int { return 1 }

View File

@ -0,0 +1,3 @@
package p2
func F() int { return 1 }

View File

@ -0,0 +1,13 @@
package p
import (
"./p1"
"testing"
)
func TestF(t *testing.T) {
if F() != p1.F() {
t.Fatal(F())
}
}

View File

@ -0,0 +1,15 @@
package p_test
import (
. "../testimport"
"./p2"
"testing"
)
func TestF1(t *testing.T) {
if F() != p2.F() {
t.Fatal(F())
}
}

View File

@ -0,0 +1 @@
package p

318
libgo/go/cmd/go/testflag.go Normal file
View File

@ -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)
}

156
libgo/go/cmd/go/tool.go Normal file
View File

@ -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)
}
}

728
libgo/go/cmd/go/vcs.go Normal file
View File

@ -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
}

View File

@ -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)
}

37
libgo/go/cmd/go/vet.go Normal file
View File

@ -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)))
}
}

93
libgo/go/cmd/gofmt/doc.go Normal file
View File

@ -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.

344
libgo/go/cmd/gofmt/gofmt.go Normal file
View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -0,0 +1,9 @@
package main
func main() {}
// comment here
func f() {}
//line foo.go:1

View File

@ -0,0 +1,9 @@
package main
func main() {}
// comment here
func f() {}
//line foo.go:1

View File

@ -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},
}

View File

@ -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},
}

12
libgo/go/cmd/gofmt/testdata/crlf.golden vendored Normal file
View File

@ -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()
}

12
libgo/go/cmd/gofmt/testdata/crlf.input vendored Normal file
View File

@ -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()
}

View File

@ -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"
)

131
libgo/go/cmd/gofmt/testdata/import.input vendored Normal file
View File

@ -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"
)

View File

@ -0,0 +1,9 @@
package P
func f() {
if x {
y
} else {
z
}
}

8
libgo/go/cmd/gofmt/testdata/old.input vendored Normal file
View File

@ -0,0 +1,8 @@
package P
func f() {
if x {
y
} else
z
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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 {}

View File

@ -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 {}

View File

@ -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
}

View File

@ -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
}

Some files were not shown because too many files have changed in this diff Show More