diff options
Diffstat (limited to 'src/cmd/cgo')
-rw-r--r-- | src/cmd/cgo/Makefile | 16 | ||||
-rw-r--r-- | src/cmd/cgo/ast.go | 15 | ||||
-rw-r--r-- | src/cmd/cgo/doc.go | 11 | ||||
-rw-r--r-- | src/cmd/cgo/gcc.go | 100 | ||||
-rw-r--r-- | src/cmd/cgo/godefs.go | 4 | ||||
-rw-r--r-- | src/cmd/cgo/main.go | 15 | ||||
-rw-r--r-- | src/cmd/cgo/out.go | 83 | ||||
-rw-r--r-- | src/cmd/cgo/util.go | 14 |
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) } |