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