-
Notifications
You must be signed in to change notification settings - Fork 5
/
file.go
122 lines (99 loc) · 2.37 KB
/
file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package gen
import (
"bytes"
"os"
"path/filepath"
"text/template"
"golang.org/x/tools/imports"
)
// File represents a generation file.
type File struct {
Name string
IncludeFiles IncludeFiles
Functions []interface{}
Enums []*Enum
Structs []*Struct
}
// NewFile creates a new blank file.
func NewFile(name string) *File {
return &File{
Name: name,
IncludeFiles: NewIncludeFiles(),
}
}
var templateGenerateFile = template.Must(template.New("go-clang-generate-file").Parse(`package clang
{{range $h, $dunno := $.IncludeFiles}}// #include "{{$h}}"
{{end}}// #include "go-clang.h"
import "C"
{{range $i, $f := $.Functions}}
{{$f}}
{{end}}
{{range $i, $e := $.Enums}}
{{$e.Comment}}
type {{$e.Name}} {{$e.UnderlyingType}}
const (
{{range $i, $ei := .Items}} {{if $ei.Comment}}{{$ei.Comment}}
{{end}}{{$ei.Name}}{{if eq $i 0}} {{$e.Name}}{{end}} = C.{{$ei.CName}}
{{end}}
)
{{range $i, $m := $e.Methods}}
{{$m}}
{{end}}
{{end}}
{{range $i, $s := $.Structs}}
{{$s.Comment}}
type {{$s.Name}} struct {
c {{if $s.IsPointerComposition}}*{{end}}C.{{if not $s.CNameIsTypeDef}}struct_{{end}}{{$s.CName}}
}
{{range $i, $m := $s.Methods}}
{{$m}}
{{end}}
{{end}}
`))
// Generate generates file.
func (f *File) Generate() error {
for _, e := range f.Enums {
f.IncludeFiles.unifyIncludeFiles(e.IncludeFiles)
for _, fu := range e.Methods {
switch fu := fu.(type) {
case *Function:
f.IncludeFiles.unifyIncludeFiles(fu.IncludeFiles)
}
}
}
for _, s := range f.Structs {
f.IncludeFiles.unifyIncludeFiles(s.IncludeFiles)
for _, fu := range s.Methods {
switch fu := fu.(type) {
case *Function:
f.IncludeFiles.unifyIncludeFiles(fu.IncludeFiles)
}
}
}
for _, fn := range f.Functions {
switch fu := fn.(type) {
case *Function:
f.IncludeFiles.unifyIncludeFiles(fu.IncludeFiles)
}
}
var b bytes.Buffer
if err := templateGenerateFile.Execute(&b, f); err != nil {
return err
}
cwd, err := os.Getwd()
if err != nil {
return err
}
filename := filepath.Join(cwd, "clang", f.Name+"_gen.go")
bo := b.Bytes()
bo = bytes.ReplaceAll(bo, []byte(`#include "./clang/`), []byte(`#include "./`))
out, err := imports.Process(filename, bo, nil)
if err != nil {
// Write the file anyway so we can look at the problem
if err := os.WriteFile(filename, bo, 0600); err != nil {
return err
}
return err
}
return os.WriteFile(filename, out, 0600)
}