diff options
Diffstat (limited to 'src/cmd/cgo/main.go')
-rw-r--r-- | src/cmd/cgo/main.go | 268 |
1 files changed, 0 insertions, 268 deletions
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go deleted file mode 100644 index be9c2bc4f..000000000 --- a/src/cmd/cgo/main.go +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// 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/token" - "io" - "os" - "path/filepath" - "reflect" - "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 - GccOptions []string - CgoFlags map[string]string // #cgo flags (CFLAGS, LDFLAGS) - Written map[string]bool - Name map[string]*Name // accumulated Name from Files - Typedef map[string]ast.Expr // accumulated Typedef from Files - ExpFunc []*ExpFunc // accumulated ExpFunc from Files - Decl []ast.Decl - GoFiles []string // list of Go files - GccFiles []string // list of gcc output files -} - -// A File collects information about a single Go input file. -type File struct { - AST *ast.File // parsed AST - 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 - Typedef map[string]ast.Expr // translations of all necessary types from C -} - -// 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", "func", "not-type" - Type *Type // the type of xxx - FuncType *FuncType - AddError bool - Const string // constant definition -} - -// 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 -} - -// 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, -} - -var cPrefix string - -var fset = token.NewFileSet() - -var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file") - -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 Make.pkg 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 - } - - 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() - } - - // Copy it to a new slice so it can grow. - gccOptions := make([]string, i) - copy(gccOptions, args[0:i]) - - goFiles := args[i:] - - arch := os.Getenv("GOARCH") - if arch == "" { - fatalf("$GOARCH is not set") - } - ptrSize := ptrSizeMap[arch] - if ptrSize == 0 { - fatalf("unknown $GOARCH %q", arch) - } - - // Clear locale variables so gcc emits English errors [sic]. - os.Setenv("LANG", "en_US.UTF-8") - os.Setenv("LC_ALL", "C") - os.Setenv("LC_CTYPE", "C") - - p := &Package{ - PtrSize: ptrSize, - GccOptions: gccOptions, - CgoFlags: make(map[string]string), - Written: make(map[string]bool), - } - - // 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()[0:6]) - - fs := make([]*File, len(goFiles)) - for i, input := range goFiles { - // Parse flags for all files before translating due to CFLAGS. - f := new(File) - f.ReadGo(input) - p.ParseFlags(f, input) - fs[i] = f - } - - // make sure that _obj directory exists, so that we can write - // all the output files there. - os.Mkdir("_obj", 0777) - - 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.writeOutput(f, input) - - p.Record(f) - } - - p.writeDefs() - if nerrors > 0 { - os.Exit(2) - } -} - -// 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", k) - } - } - } - - p.ExpFunc = append(p.ExpFunc, f.ExpFunc...) - p.Decl = append(p.Decl, f.AST.Decls...) -} |