Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(444)

Side by Side Diff: src/cmd/cgo/godefs.go

Issue 5367043: code review 5367043: godefs: delete, replaced by cgo -godefs (Closed)
Patch Set: diff -r 9870fbad1533 https://go.googlecode.com/hg Created 13 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5
6 package main
7
8 import (
9 "bytes"
10 "fmt"
11 "go/ast"
12 "go/printer"
13 "go/token"
14 "os"
15 "strings"
16 )
17
18 // godefs returns the output for -godefs mode.
19 func (p *Package) godefs(f *File, srcfile string) string {
20 var buf bytes.Buffer
21
22 fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n")
23 fmt.Fprintf(&buf, "// %s\n", strings.Join(os.Args, " "))
24 fmt.Fprintf(&buf, "\n")
25
26 override := make(map[string]string)
27
28 // Allow source file to specify override mappings.
29 // For example, the socket data structures refer
30 // to in_addr and in_addr6 structs but we want to be
31 // able to treat them as byte arrays, so the godefs
32 // inputs in package syscall say
33 //
34 // // +godefs map struct_in_addr [4]byte
35 // // +godefs map struct_in_addr6 [16]byte
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 comm ent: %s\n", c.Text)
47 continue
48 }
49 override["_Ctype_"+strings.TrimSpace(s[:i])] = strings.T rimSpace(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 // Otherwise, if the source file says type T C.whatever,
59 // use "T" as the mangling of C.whatever,
60 // except in the definition (handled at end of function).
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 // Extend overrides using typedefs:
80 // If we know that C.xxx should format as T
81 // and xxx is a typedef for yyy, make C.yyy format as T.
82 for typ, def := range typedef {
83 if new := override[typ]; new != "" {
84 if id, ok := def.(*ast.Ident); ok {
85 override[id.Name] = new
86 }
87 }
88 }
89
90 // Apply overrides.
91 for old, new := range override {
92 if id := goIdent[old]; id != nil {
93 id.Name = new
94 }
95 }
96
97 // Any names still using the _C syntax are not going to compile,
98 // although in general we don't know whether they all made it
99 // into the file, so we can't warn here.
100 //
101 // The most common case is union types, which begin with
102 // _Ctype_union and for which typedef[name] is a Go byte
103 // array of the appropriate size (such as [4]byte).
104 // Substitute those union types with byte arrays.
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 printer.Fprint(&buf, fset, f.AST)
114
115 return buf.String()
116 }
117
118 // cdefs returns the output for -cdefs mode.
119 // The easiest way to do this is to translate the godefs Go to C.
120 func (p *Package) cdefs(f *File, srcfile string) string {
r 2011/11/09 21:27:41 i'd still like to see the c stuff separated from t
121 godefsOutput := p.godefs(f, srcfile)
122
123 lines := strings.Split(godefsOutput, "\n")
124 lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"
125
126 for i, line := range lines {
127 lines[i] = strings.TrimSpace(line)
128 }
129
130 var out bytes.Buffer
131 printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, f ormat, args...) }
132
133 didTypedef := false
134 for i := 0; i < len(lines); i++ {
135 line := lines[i]
136
137 // Delete
138 // package x
139 if strings.HasPrefix(line, "package ") {
140 continue
141 }
142
143 // Convert
144 // const (
145 // A = 1
146 // B = 2
147 // )
148 //
149 // to
150 //
151 // enum {
152 // A = 1,
153 // B = 2,
154 // };
155 if line == "const (" {
156 printf("enum {\n")
157 for i++; i < len(lines) && lines[i] != ")"; i++ {
158 line = lines[i]
159 if line != "" {
160 printf("\t%s,", line)
161 }
162 printf("\n")
163 }
164 printf("};\n")
165 continue
166 }
167
168 // Convert
169 // const A = 1
170 // to
171 // enum { A = 1 };
172 if strings.HasPrefix(line, "const ") {
173 printf("enum { %s };\n", line[len("const "):])
174 continue
175 }
176
177 // On first type definition, typedef all the structs
178 // in case there are dependencies between them.
179 if !didTypedef && strings.HasPrefix(line, "type ") {
180 didTypedef = true
181 for _, line := range lines {
182 line = strings.TrimSpace(line)
183 if strings.HasPrefix(line, "type ") && strings.H asSuffix(line, " struct {") {
184 s := line[len("type ") : len(line)-len(" struct {")]
185 printf("typedef struct %s %s;\n", s, s)
186 }
187 }
188 printf("\n")
189 printf("#pragma pack on\n")
190 printf("\n")
191 }
192
193 // Convert
194 // type T struct {
195 // X int64
196 // Y *int32
197 // Z [4]byte
198 // }
199 //
200 // to
201 //
202 // struct T {
203 // int64 X;
204 // int32 *Y;
205 // byte Z[4];
206 // }
207 if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
208 s := line[len("type ") : len(line)-len(" struct {")]
209 printf("struct %s {\n", s)
210 for i++; i < len(lines) && lines[i] != "}"; i++ {
211 line := lines[i]
212 if line != "" {
213 f := strings.Fields(line)
214 if len(f) != 2 {
215 fmt.Fprintf(os.Stderr, "cgo: can not parse struct field: %s\n", line)
216 nerrors++
217 continue
218 }
219 printf("\t%s;", cdecl(f[0], f[1]))
220 }
221 printf("\n")
222 }
223 printf("};\n")
224 continue
225 }
226
227 // Convert
228 // type T int
229 // to
230 // typedef int T;
231 if strings.HasPrefix(line, "type ") {
232 f := strings.Fields(line[len("type "):])
233 if len(f) != 2 {
234 fmt.Fprintf(os.Stderr, "cgo: cannot parse type d efinition: %s\n", line)
235 nerrors++
236 continue
237 }
238 printf("typedef\t%s;\n", cdecl(f[0], f[1]))
239 continue
240 }
241
242 printf("%s\n", line)
243 }
244
245 if didTypedef {
246 printf("\n")
247 printf("#pragma pack off\n")
248 }
249
250 return out.String()
251 }
252
253 // cdecl returns the C declaration for the given Go name and type.
254 // It only handles the specific cases necessary for converting godefs output.
255 func cdecl(name, typ string) string {
256 // X *[0]byte -> X *void
257 if strings.HasPrefix(typ, "*[0]") {
258 typ = "*void"
259 }
260 // X *byte -> *X byte
261 if strings.HasPrefix(typ, "*") {
262 name = "*" + name
263 typ = typ[1:]
264 }
265 // X [4]byte -> X[4] byte
266 if strings.HasPrefix(typ, "[") {
267 i := strings.Index(typ, "]") + 1
268 name = name + typ[:i]
269 typ = typ[i:]
270 }
271 // X T -> T X
272 return typ + "\t" + name
273 }
274
275 var gofmtBuf bytes.Buffer
276
277 // gofmt returns the gofmt-formatted string for an AST node.
278 func gofmt(n interface{}) string {
279 gofmtBuf.Reset()
280 err := printer.Fprint(&gofmtBuf, fset, n)
281 if err != nil {
282 return "<" + err.Error() + ">"
283 }
284 return gofmtBuf.String()
285 }
OLDNEW
« src/cmd/cgo/gcc.go ('K') | « src/cmd/cgo/gcc.go ('k') | src/cmd/cgo/main.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b