...
Source file
src/cmd/cgo/godefs.go
Documentation: cmd/cgo
1
2
3
4
5 package main
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/printer"
11 "go/token"
12 "os"
13 "path/filepath"
14 "strings"
15 )
16
17
18 func (p *Package) godefs(f *File, args []string) string {
19 var buf strings.Builder
20
21 fmt.Fprintf(&buf, "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n")
22 fmt.Fprintf(&buf, "// %s %s\n", filepath.Base(args[0]), strings.Join(args[1:], " "))
23 fmt.Fprintf(&buf, "\n")
24
25 override := make(map[string]string)
26
27
28
29
30
31
32
33
34
35
36 for _, g := range f.Comments {
37 for _, c := range g.List {
38 i := strings.Index(c.Text, "+godefs map")
39 if i < 0 {
40 continue
41 }
42 s := strings.TrimSpace(c.Text[i+len("+godefs map"):])
43 i = strings.Index(s, " ")
44 if i < 0 {
45 fmt.Fprintf(os.Stderr, "invalid +godefs map comment: %s\n", c.Text)
46 continue
47 }
48 override["_Ctype_"+strings.TrimSpace(s[:i])] = strings.TrimSpace(s[i:])
49 }
50 }
51 for _, n := range f.Name {
52 if s := override[n.Go]; s != "" {
53 override[n.Mangle] = s
54 }
55 }
56
57
58
59
60 refName := make(map[*ast.Expr]*Name)
61 for _, r := range f.Ref {
62 refName[r.Expr] = r.Name
63 }
64 for _, d := range f.AST.Decls {
65 d, ok := d.(*ast.GenDecl)
66 if !ok || d.Tok != token.TYPE {
67 continue
68 }
69 for _, s := range d.Specs {
70 s := s.(*ast.TypeSpec)
71 n := refName[&s.Type]
72 if n != nil && n.Mangle != "" {
73 override[n.Mangle] = s.Name.Name
74 }
75 }
76 }
77
78
79
80
81 for typ, def := range typedef {
82 if new := override[typ]; new != "" {
83 if id, ok := def.Go.(*ast.Ident); ok {
84 override[id.Name] = new
85 }
86 }
87 }
88
89
90 for old, new := range override {
91 if id := goIdent[old]; id != nil {
92 id.Name = new
93 }
94 }
95
96
97
98
99
100
101
102
103
104 for name, id := range goIdent {
105 if id.Name == name && strings.Contains(name, "_Ctype_union") {
106 if def := typedef[name]; def != nil {
107 id.Name = gofmt(def)
108 }
109 }
110 }
111
112 conf.Fprint(&buf, fset, f.AST)
113
114 return buf.String()
115 }
116
117 var gofmtBuf strings.Builder
118
119
120 func gofmt(n interface{}) string {
121 gofmtBuf.Reset()
122 err := printer.Fprint(&gofmtBuf, fset, n)
123 if err != nil {
124 return "<" + err.Error() + ">"
125 }
126 return gofmtBuf.String()
127 }
128
View as plain text