summaryrefslogtreecommitdiff
path: root/src/cmd/cgo
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/cgo')
-rw-r--r--src/cmd/cgo/Makefile16
-rw-r--r--src/cmd/cgo/ast.go15
-rw-r--r--src/cmd/cgo/doc.go11
-rw-r--r--src/cmd/cgo/gcc.go100
-rw-r--r--src/cmd/cgo/godefs.go4
-rw-r--r--src/cmd/cgo/main.go15
-rw-r--r--src/cmd/cgo/out.go83
-rw-r--r--src/cmd/cgo/util.go14
8 files changed, 166 insertions, 92 deletions
diff --git a/src/cmd/cgo/Makefile b/src/cmd/cgo/Makefile
deleted file mode 100644
index a3f034f7c..000000000
--- a/src/cmd/cgo/Makefile
+++ /dev/null
@@ -1,16 +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.
-
-include ../../Make.inc
-
-TARG=cgo
-GOFILES=\
- ast.go\
- gcc.go\
- godefs.go\
- main.go\
- out.go\
- util.go\
-
-include ../../Make.cmd
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
index da6ae4176..381e606ef 100644
--- a/src/cmd/cgo/ast.go
+++ b/src/cmd/cgo/ast.go
@@ -147,6 +147,9 @@ func (f *File) saveRef(x interface{}, context string) {
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")
@@ -232,7 +235,11 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
// These are ordered and grouped to match ../../pkg/go/ast/ast.go
case *ast.Field:
- f.walk(&n.Type, "type", visit)
+ 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)
@@ -289,9 +296,9 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
case *ast.StructType:
f.walk(n.Fields, "field", visit)
case *ast.FuncType:
- f.walk(n.Params, "field", visit)
+ f.walk(n.Params, "param", visit)
if n.Results != nil {
- f.walk(n.Results, "field", visit)
+ f.walk(n.Results, "param", visit)
}
case *ast.InterfaceType:
f.walk(n.Methods, "field", visit)
@@ -379,7 +386,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
f.walk(n.Specs, "spec", visit)
case *ast.FuncDecl:
if n.Recv != nil {
- f.walk(n.Recv, "field", visit)
+ f.walk(n.Recv, "param", visit)
}
f.walk(n.Type, "type", visit)
if n.Body != nil {
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index 6282c0bbf..83f1ba46c 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -6,7 +6,7 @@
Cgo enables the creation of Go packages that call C code.
-Usage: cgo [compiler options] file.go
+Usage: go tool cgo [compiler options] file.go
The compiler options are passed through uninterpreted when
invoking gcc to compile the C parts of the package.
@@ -16,8 +16,8 @@ the pseudo-package "C" and then refers 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 is used as a header when compiling the C parts of
-the package. For example:
+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>
@@ -57,6 +57,8 @@ 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.
+Go structs cannot embed fields with C types.
+
Any C function that returns a value may be called in a multiple
assignment context to retrieve both the return value and the
C errno variable as an error. For example:
@@ -100,7 +102,8 @@ 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 _cgo_export.h generated header. Functions with multiple
+found in _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.
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 155eb0440..98a847e6f 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -524,6 +524,10 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
for i, n := range names {
nameToIndex[n] = i
}
+ nameToRef := make(map[*Name]*Ref)
+ for _, ref := range f.Ref {
+ nameToRef[ref.Name] = ref
+ }
r := d.Reader()
for {
e, err := r.Next()
@@ -597,12 +601,16 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
if types[i] == nil {
continue
}
+ pos := token.NoPos
+ if ref, ok := nameToRef[n]; ok {
+ pos = ref.Pos()
+ }
f, fok := types[i].(*dwarf.FuncType)
if n.Kind != "type" && fok {
n.Kind = "func"
- n.FuncType = conv.FuncType(f)
+ n.FuncType = conv.FuncType(f, pos)
} else {
- n.Type = conv.Type(types[i])
+ n.Type = conv.Type(types[i], pos)
if enums[i] != 0 && n.Type.EnumValues != nil {
k := fmt.Sprintf("__cgo_enum__%d", i)
n.Kind = "const"
@@ -701,7 +709,7 @@ func (p *Package) rewriteRef(f *File) {
// Substitute definition for mangled type name.
if id, ok := expr.(*ast.Ident); ok {
if t := typedef[id.Name]; t != nil {
- expr = t
+ expr = t.Go
}
if id.Name == r.Name.Mangle && r.Name.Const != "" {
expr = ast.NewIdent(r.Name.Const)
@@ -886,7 +894,7 @@ type typeConv struct {
}
var tagGen int
-var typedef = make(map[string]ast.Expr)
+var typedef = make(map[string]*Type)
var goIdent = make(map[string]*ast.Ident)
func (c *typeConv) Init(ptrSize int64) {
@@ -972,10 +980,10 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
// Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field.
-func (c *typeConv) Type(dtype dwarf.Type) *Type {
+func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
if t, ok := c.m[dtype]; ok {
if t.Go == nil {
- fatalf("type conversion loop at %s", dtype)
+ fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
}
return t
}
@@ -998,11 +1006,11 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
switch dt := dtype.(type) {
default:
- fatalf("unexpected type: %s", dtype)
+ fatalf("%s: unexpected type: %s", lineno(pos), dtype)
case *dwarf.AddrType:
if t.Size != c.ptrSize {
- fatalf("unexpected: %d-byte address type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
}
t.Go = c.uintptr
t.Align = t.Size
@@ -1017,7 +1025,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
Len: c.intExpr(dt.Count),
}
t.Go = gt // publish before recursive call
- sub := c.Type(dt.Type)
+ sub := c.Type(dt.Type, pos)
t.Align = sub.Align
gt.Elt = sub.Go
t.C.Set("typeof(%s[%d])", sub.C, dt.Count)
@@ -1028,7 +1036,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.CharType:
if t.Size != 1 {
- fatalf("unexpected: %d-byte char type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
}
t.Go = c.int8
t.Align = 1
@@ -1048,7 +1056,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
}
switch t.Size + int64(signed) {
default:
- fatalf("unexpected: %d-byte enum type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
case 1:
t.Go = c.uint8
case 2:
@@ -1070,7 +1078,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.FloatType:
switch t.Size {
default:
- fatalf("unexpected: %d-byte float type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
case 4:
t.Go = c.float32
case 8:
@@ -1083,7 +1091,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.ComplexType:
switch t.Size {
default:
- fatalf("unexpected: %d-byte complex type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
case 8:
t.Go = c.complex64
case 16:
@@ -1101,11 +1109,11 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.IntType:
if dt.BitSize > 0 {
- fatalf("unexpected: %d-bit int type - %s", dt.BitSize, dtype)
+ fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
}
switch t.Size {
default:
- fatalf("unexpected: %d-byte int type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
case 1:
t.Go = c.int8
case 2:
@@ -1131,13 +1139,13 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
gt := &ast.StarExpr{}
t.Go = gt // publish before recursive call
- sub := c.Type(dt.Type)
+ sub := c.Type(dt.Type, pos)
gt.X = sub.Go
t.C.Set("%s*", sub.C)
case *dwarf.QualType:
// Ignore qualifier.
- t = c.Type(dt.Type)
+ t = c.Type(dt.Type, pos)
c.m[dtype] = t
return t
@@ -1156,17 +1164,23 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
goIdent[name.Name] = name
switch dt.Kind {
case "union", "class":
- typedef[name.Name] = c.Opaque(t.Size)
+ t.Go = c.Opaque(t.Size)
if t.C.Empty() {
t.C.Set("typeof(unsigned char[%d])", t.Size)
}
+ typedef[name.Name] = t
case "struct":
- g, csyntax, align := c.Struct(dt)
+ g, csyntax, align := c.Struct(dt, pos)
if t.C.Empty() {
t.C.Set(csyntax)
}
t.Align = align
- typedef[name.Name] = g
+ tt := *t
+ if tag != "" {
+ tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
+ }
+ tt.Go = g
+ typedef[name.Name] = &tt
}
case *dwarf.TypedefType:
@@ -1191,11 +1205,13 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
name := c.Ident("_Ctype_" + dt.Name)
goIdent[name.Name] = name
t.Go = name // publish before recursive call
- sub := c.Type(dt.Type)
+ sub := c.Type(dt.Type, pos)
t.Size = sub.Size
t.Align = sub.Align
if _, ok := typedef[name.Name]; !ok {
- typedef[name.Name] = sub.Go
+ tt := *t
+ tt.Go = sub.Go
+ typedef[name.Name] = &tt
}
if *godefs || *cdefs {
t.Go = sub.Go
@@ -1203,18 +1219,18 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.UcharType:
if t.Size != 1 {
- fatalf("unexpected: %d-byte uchar type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
}
t.Go = c.uint8
t.Align = 1
case *dwarf.UintType:
if dt.BitSize > 0 {
- fatalf("unexpected: %d-bit uint type - %s", dt.BitSize, dtype)
+ fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
}
switch t.Size {
default:
- fatalf("unexpected: %d-byte uint type - %s", t.Size, dtype)
+ fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
case 1:
t.Go = c.uint8
case 2:
@@ -1242,7 +1258,8 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
}
s = strings.Join(strings.Split(s, " "), "") // strip spaces
name := c.Ident("_Ctype_" + s)
- typedef[name.Name] = t.Go
+ tt := *t
+ typedef[name.Name] = &tt
if !*godefs && !*cdefs {
t.Go = name
}
@@ -1250,7 +1267,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
}
if t.C.Empty() {
- fatalf("internal error: did not create C name for %s", dtype)
+ fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
}
return t
@@ -1258,8 +1275,8 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
// FuncArg returns a Go type with the same memory layout as
// dtype when used as the type of a C function argument.
-func (c *typeConv) FuncArg(dtype dwarf.Type) *Type {
- t := c.Type(dtype)
+func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
+ t := c.Type(dtype, pos)
switch dt := dtype.(type) {
case *dwarf.ArrayType:
// Arrays are passed implicitly as pointers in C.
@@ -1280,9 +1297,18 @@ func (c *typeConv) FuncArg(dtype dwarf.Type) *Type {
if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
// Unless the typedef happens to point to void* since
// Go has special rules around using unsafe.Pointer.
- if _, void := base(ptr.Type).(*dwarf.VoidType); !void {
- return c.Type(ptr)
+ if _, void := base(ptr.Type).(*dwarf.VoidType); void {
+ break
+ }
+
+ t = c.Type(ptr, pos)
+ if t == nil {
+ return nil
}
+
+ // Remember the C spelling, in case the struct
+ // has __attribute__((unavailable)) on it. See issue 2888.
+ t.Typedef = dt.Name
}
}
return t
@@ -1290,7 +1316,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type) *Type {
// FuncType returns the Go type analogous to dtype.
// There is no guarantee about matching memory layout.
-func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType {
+func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
p := make([]*Type, len(dtype.ParamType))
gp := make([]*ast.Field, len(dtype.ParamType))
for i, f := range dtype.ParamType {
@@ -1303,13 +1329,13 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType {
p, gp = nil, nil
break
}
- p[i] = c.FuncArg(f)
+ p[i] = c.FuncArg(f, pos)
gp[i] = &ast.Field{Type: p[i].Go}
}
var r *Type
var gr []*ast.Field
if _, ok := dtype.ReturnType.(*dwarf.VoidType); !ok && dtype.ReturnType != nil {
- r = c.Type(dtype.ReturnType)
+ r = c.Type(dtype.ReturnType, pos)
gr = []*ast.Field{{Type: r.Go}}
}
return &FuncType{
@@ -1352,7 +1378,7 @@ func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
}
// Struct conversion: return Go and (6g) C syntax for type.
-func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax string, align int64) {
+func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
var buf bytes.Buffer
buf.WriteString("struct {")
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
@@ -1394,7 +1420,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
fld = c.pad(fld, f.ByteOffset-off)
off = f.ByteOffset
}
- t := c.Type(f.Type)
+ t := c.Type(f.Type, pos)
tgo := t.Go
size := t.Size
@@ -1435,7 +1461,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
off = dt.ByteSize
}
if off != dt.ByteSize {
- fatalf("struct size calculation error")
+ fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
}
buf.WriteString("}")
csyntax = buf.String()
diff --git a/src/cmd/cgo/godefs.go b/src/cmd/cgo/godefs.go
index 683872927..fec70a334 100644
--- a/src/cmd/cgo/godefs.go
+++ b/src/cmd/cgo/godefs.go
@@ -80,7 +80,7 @@ func (p *Package) godefs(f *File, srcfile string) string {
// 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.(*ast.Ident); ok {
+ if id, ok := def.Go.(*ast.Ident); ok {
override[id.Name] = new
}
}
@@ -109,7 +109,7 @@ func (p *Package) godefs(f *File, srcfile string) string {
}
}
- printer.Fprint(&buf, fset, f.AST)
+ conf.Fprint(&buf, fset, f.AST)
return buf.String()
}
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index f58291237..a8be7be7d 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -15,6 +15,7 @@ import (
"flag"
"fmt"
"go/ast"
+ "go/printer"
"go/token"
"io"
"os"
@@ -38,6 +39,7 @@ type Package struct {
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.
@@ -97,6 +99,7 @@ type Type struct {
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.
@@ -158,6 +161,13 @@ func main() {
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()
@@ -304,6 +314,9 @@ func (p *Package) Record(f *File) {
}
}
- p.ExpFunc = append(p.ExpFunc, f.ExpFunc...)
+ if f.ExpFunc != nil {
+ p.ExpFunc = append(p.ExpFunc, f.ExpFunc...)
+ p.Preamble += "\n" + f.Preamble
+ }
p.Decl = append(p.Decl, f.AST.Decls...)
}
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 3e25b2099..4dc0f8454 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -17,6 +17,8 @@ import (
"strings"
)
+var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
+
// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Package) writeDefs() {
@@ -57,7 +59,7 @@ func (p *Package) writeDefs() {
for name, def := range typedef {
fmt.Fprintf(fgo2, "type %s ", name)
- printer.Fprint(fgo2, fset, def)
+ conf.Fprint(fgo2, fset, def.Go)
fmt.Fprintf(fgo2, "\n\n")
}
fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
@@ -87,7 +89,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fc, "\n")
fmt.Fprintf(fgo2, "var %s ", n.Mangle)
- printer.Fprint(fgo2, fset, &ast.StarExpr{X: n.Type.Go})
+ conf.Fprint(fgo2, fset, &ast.StarExpr{X: n.Type.Go})
fmt.Fprintf(fgo2, "\n")
}
fmt.Fprintf(fc, "\n")
@@ -194,7 +196,11 @@ func (p *Package) structType(n *Name) (string, int64) {
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
off += pad
}
- fmt.Fprintf(&buf, "\t\t%s p%d;\n", t.C, i)
+ c := t.Typedef
+ if c == "" {
+ c = t.C.String()
+ }
+ fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
off += t.Size
}
if off%p.PtrSize != 0 {
@@ -255,23 +261,46 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
Name: ast.NewIdent(n.Mangle),
Type: gtype,
}
- printer.Fprint(fgo2, fset, d)
+
if *gccgo {
- fmt.Fprintf(fgo2, " __asm__(\"%s\")\n", n.C)
- } else {
- fmt.Fprintf(fgo2, "\n")
+ // Gccgo style hooks.
+ // we hook directly into C. gccgo goes not support cgocall yet.
+ if !n.AddError {
+ fmt.Fprintf(fgo2, "//extern %s\n", n.C)
+ conf.Fprint(fgo2, fset, d)
+ fmt.Fprint(fgo2, "\n")
+ } else {
+ // write a small wrapper to retrieve errno.
+ cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
+ paramnames := []string(nil)
+ for i, param := range d.Type.Params.List {
+ paramName := fmt.Sprintf("p%d", i)
+ param.Names = []*ast.Ident{ast.NewIdent(paramName)}
+ paramnames = append(paramnames, paramName)
+ }
+ conf.Fprint(fgo2, fset, d)
+ fmt.Fprintf(fgo2, "{\n")
+ fmt.Fprintf(fgo2, "\tr := %s(%s)\n", cname, strings.Join(paramnames, ", "))
+ fmt.Fprintf(fgo2, "\treturn r, syscall.GetErrno()\n")
+ fmt.Fprintf(fgo2, "}\n")
+ // declare the C function.
+ fmt.Fprintf(fgo2, "//extern %s\n", n.C)
+ d.Name = ast.NewIdent(cname)
+ l := d.Type.Results.List
+ d.Type.Results.List = l[:len(l)-1]
+ conf.Fprint(fgo2, fset, d)
+ fmt.Fprint(fgo2, "\n")
+ }
+ return
}
+ conf.Fprint(fgo2, fset, d)
+ fmt.Fprint(fgo2, "\n")
if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
// The builtins are already defined in the C prolog.
return
}
- // gccgo does not require a wrapper unless an error must be returned.
- if *gccgo && !n.AddError {
- return
- }
-
var argSize int64
_, argSize = p.structType(n)
@@ -327,8 +356,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
- fmt.Fprintf(fgo1, "//line %s:1\n", srcfile)
- printer.Fprint(fgo1, fset, f.AST)
+ conf.Fprint(fgo1, fset, f.AST)
// While we process the vars and funcs, also write 6c and gcc output.
// Gcc output starts with the preamble.
@@ -354,6 +382,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
}
p.Written[name] = true
+ if *gccgo {
+ // we don't use wrappers with gccgo.
+ return
+ }
+
ctype, _ := p.structType(n)
// Gcc wrapper unpacks the C argument struct
@@ -399,6 +432,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
fgcch := creat(*objDir + "_cgo_export.h")
fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
+ fmt.Fprintf(fgcch, "%s\n", p.Preamble)
fmt.Fprintf(fgcch, "%s\n", gccExportHeaderProlog)
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
@@ -542,11 +576,11 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
// a Go wrapper function.
if fn.Recv != nil {
fmt.Fprintf(fgo2, "func %s(recv ", goname)
- printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
+ conf.Fprint(fgo2, fset, fn.Recv.List[0].Type)
forFieldList(fntype.Params,
func(i int, atype ast.Expr) {
fmt.Fprintf(fgo2, ", p%d ", i)
- printer.Fprint(fgo2, fset, atype)
+ conf.Fprint(fgo2, fset, atype)
})
fmt.Fprintf(fgo2, ")")
if gccResult != "void" {
@@ -556,7 +590,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
if i > 0 {
fmt.Fprint(fgo2, ", ")
}
- printer.Fprint(fgo2, fset, atype)
+ conf.Fprint(fgo2, fset, atype)
})
fmt.Fprint(fgo2, ")")
}
@@ -664,10 +698,8 @@ func (p *Package) cgoType(e ast.Expr) *Type {
}
}
}
- for name, def := range typedef {
- if name == t.Name {
- return p.cgoType(def)
- }
+ if def := typedef[t.Name]; def != nil {
+ return def
}
if t.Name == "uintptr" {
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")}
@@ -692,7 +724,7 @@ func (p *Package) cgoType(e ast.Expr) *Type {
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
}
}
- error_(e.Pos(), "unrecognized Go type %T", e)
+ error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
return &Type{Size: 4, Align: 4, C: c("int")}
}
@@ -782,11 +814,12 @@ struct __go_string __go_byte_array_to_string(const void* p, int len);
struct __go_open_array __go_string_to_byte_array (struct __go_string str);
const char *CString(struct __go_string s) {
- return strndup(s.__data, s.__length);
+ return strndup((const char*)s.__data, s.__length);
}
struct __go_string GoString(char *p) {
- return __go_byte_array_to_string(p, strlen(p));
+ int len = (p != NULL) ? strlen(p) : 0;
+ return __go_byte_array_to_string(p, len);
}
struct __go_string GoStringN(char *p, int n) {
@@ -794,7 +827,7 @@ struct __go_string GoStringN(char *p, int n) {
}
Slice GoBytes(char *p, int n) {
- struct __go_string s = { p, n };
+ struct __go_string s = { (const unsigned char *)p, n };
return __go_string_to_byte_array(s);
}
`
diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go
index 8a778418d..cd7cde2b6 100644
--- a/src/cmd/cgo/util.go
+++ b/src/cmd/cgo/util.go
@@ -56,17 +56,25 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
<-c
<-c
- w, err := p.Wait(0)
+ state, err := p.Wait()
if err != nil {
fatalf("%s", err)
}
- ok = w.Exited() && w.ExitStatus() == 0
+ ok = state.Success()
return
}
+func lineno(pos token.Pos) string {
+ return fset.Position(pos).String()
+}
+
// Die with an error message.
func fatalf(msg string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, msg+"\n", args...)
+ // 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)
}