summaryrefslogtreecommitdiff
path: root/src/cmd/cgo/out.go
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-02-29 11:23:13 +0100
committerOndřej Surý <ondrej@sury.org>2012-02-29 11:23:13 +0100
commitb6d7097a0d6072199f2cd74d67404890697cf78a (patch)
treea2193c528a79fd5606507568859ee5067c6b86e4 /src/cmd/cgo/out.go
parent4cecda6c347bd6902b960c6a35a967add7070b0d (diff)
downloadgolang-b6d7097a0d6072199f2cd74d67404890697cf78a.tar.gz
Imported Upstream version 2012.02.22upstream-weekly/2012.02.22
Diffstat (limited to 'src/cmd/cgo/out.go')
-rw-r--r--src/cmd/cgo/out.go83
1 files changed, 58 insertions, 25 deletions
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);
}
`