@@ -7,17 +7,19 @@ import (
7
7
"strings"
8
8
"unsafe"
9
9
10
- "github.com/goplus/llgo/c"
11
- "github.com/goplus/llgo/c/cjson"
12
- "github.com/goplus/llgo/c/clang"
13
10
"github.com/goplus/llcppg/_xtool/llcppsymg/clangutils"
14
11
"github.com/goplus/llcppg/ast"
15
12
"github.com/goplus/llcppg/token"
13
+ "github.com/goplus/llgo/c"
14
+ "github.com/goplus/llgo/c/cjson"
15
+ "github.com/goplus/llgo/c/clang"
16
16
)
17
17
18
18
type FileEntry struct {
19
- Path string
20
- Doc * ast.File
19
+ Path string
20
+ IncPath string
21
+ IsSys bool
22
+ Doc * ast.File
21
23
}
22
24
23
25
type Converter struct {
@@ -58,11 +60,14 @@ func NewConverter(config *clangutils.Config) (*Converter, error) {
58
60
return nil , err
59
61
}
60
62
63
+ files := initFileEntries (unit )
64
+
61
65
return & Converter {
62
- Files : make ([] * FileEntry , 0 ) ,
66
+ Files : files ,
63
67
index : index ,
64
68
unit : unit ,
65
69
}, nil
70
+
66
71
}
67
72
68
73
func (ct * Converter ) Dispose () {
@@ -71,6 +76,26 @@ func (ct *Converter) Dispose() {
71
76
ct .unit .Dispose ()
72
77
}
73
78
79
+ func initFileEntries (unit * clang.TranslationUnit ) []* FileEntry {
80
+ files := make ([]* FileEntry , 0 )
81
+ clangutils .GetInclusions (unit , func (inced clang.File , incins []clang.SourceLocation ) {
82
+ loc := unit .GetLocation (inced , 1 , 1 )
83
+ incedFile := toStr (inced .FileName ())
84
+ var incPath string
85
+ if len (incins ) > 0 {
86
+ cur := unit .GetCursor (& incins [0 ])
87
+ incPath = toStr (cur .String ())
88
+ }
89
+ files = append (files , & FileEntry {
90
+ Path : incedFile ,
91
+ IncPath : incPath ,
92
+ IsSys : loc .IsInSystemHeader () != 0 ,
93
+ Doc : & ast.File {},
94
+ })
95
+ })
96
+ return files
97
+ }
98
+
74
99
func (ct * Converter ) GetTokens (cursor clang.Cursor ) []* ast.Token {
75
100
ran := cursor .Extent ()
76
101
var numTokens c.Uint
@@ -121,42 +146,40 @@ func (ct *Converter) logln(args ...interface{}) {
121
146
}
122
147
}
123
148
124
- func (ct * Converter ) UpdateLoc (cursor clang.Cursor ) {
149
+ func (ct * Converter ) GetCurFile (cursor clang.Cursor ) * ast. File {
125
150
loc := cursor .Location ()
126
151
var file clang.File
127
152
loc .SpellingLocation (& file , nil , nil , nil )
128
-
129
153
filePath := toStr (file .FileName ())
130
-
131
154
if filePath == "" {
132
155
//todo(zzy): For some built-in macros, there is no file.
133
156
ct .curLoc = ast.Location {File : "" }
134
- return
135
- }
136
- ct .curLoc = ast.Location {File : filePath }
137
- }
138
-
139
- func (ct * Converter ) GetCurFile () * ast.File {
140
- if ct .curLoc .File == "" {
141
157
ct .logln ("GetCurFile: NO FILE" )
142
158
return nil
143
159
}
160
+ ct .curLoc = ast.Location {File : filePath }
161
+
144
162
// todo(zzy): more efficient
145
163
for i , entry := range ct .Files {
146
- if entry .Path == ct . curLoc . File {
147
- ct .logln ("GetCurFile: found" , ct . curLoc . File )
164
+ if entry .Path == filePath {
165
+ ct .logln ("GetCurFile: found" , filePath )
148
166
return ct .Files [i ].Doc
149
167
}
150
168
}
151
- ct .logln ("GetCurFile: Create New ast.File" , ct .curLoc .File )
152
- newDoc := & ast.File {}
153
- ct .Files = append (ct .Files , & FileEntry {Path : ct .curLoc .File , Doc : newDoc })
154
- return newDoc
169
+ ct .logln ("GetCurFile: Create New ast.File" , filePath )
170
+ entry := & FileEntry {Path : filePath , Doc : & ast.File {}, IsSys : false }
171
+ if loc .IsInSystemHeader () != 0 {
172
+ entry .IsSys = true
173
+ }
174
+ ct .Files = append (ct .Files , entry )
175
+ return entry .Doc
155
176
}
156
177
157
178
func (ct * Converter ) CreateDeclBase (cursor clang.Cursor ) ast.DeclBase {
158
179
base := ast.DeclBase {
159
- Loc : & ct .curLoc ,
180
+ Loc : & ast.Location {
181
+ File : ct .curLoc .File ,
182
+ },
160
183
Parent : ct .BuildScopingExpr (cursor .SemanticParent ()),
161
184
}
162
185
commentGroup , isDoc := ct .ParseCommentGroup (cursor )
@@ -206,9 +229,7 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
206
229
ct .incIndent ()
207
230
defer ct .decIndent ()
208
231
209
- ct .UpdateLoc (cursor )
210
-
211
- curFile := ct .GetCurFile ()
232
+ curFile := ct .GetCurFile (cursor )
212
233
213
234
name := toStr (cursor .String ())
214
235
ct .logf ("visitTop: Cursor: %s\n " , name )
@@ -219,7 +240,11 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
219
240
220
241
switch cursor .Kind {
221
242
case clang .CursorInclusionDirective :
222
- include := ct .ProcessInclude (cursor )
243
+ include , err := ct .ProcessInclude (cursor )
244
+ if err != nil {
245
+ ct .logln (err )
246
+ return clang .ChildVisit_Continue
247
+ }
223
248
curFile .Includes = append (curFile .Includes , include )
224
249
ct .logln ("visitTop: ProcessInclude END " , include .Path )
225
250
case clang .CursorMacroDefinition :
@@ -276,27 +301,18 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
276
301
curFile .Decls = append (curFile .Decls , typedefDecl )
277
302
ct .logln ("visitTop: ProcessTypeDefDecl END" , typedefDecl .Name .Name )
278
303
case clang .CursorNamespace :
279
- VisitChildren (cursor , ct .visitTop )
304
+ clangutils . VisitChildren (cursor , ct .visitTop )
280
305
}
281
306
return clang .ChildVisit_Continue
282
307
}
283
308
284
309
func (ct * Converter ) Convert () ([]* FileEntry , error ) {
285
310
cursor := ct .unit .Cursor ()
286
311
// visit top decls (struct,class,function & macro,include)
287
- VisitChildren (cursor , ct .visitTop )
312
+ clangutils . VisitChildren (cursor , ct .visitTop )
288
313
return ct .Files , nil
289
314
}
290
315
291
- type Visitor func (cursor , parent clang.Cursor ) clang.ChildVisitResult
292
-
293
- func VisitChildren (cursor clang.Cursor , fn Visitor ) c.Uint {
294
- return clang .VisitChildren (cursor , func (cursor , parent clang.Cursor , clientData unsafe.Pointer ) clang.ChildVisitResult {
295
- cfn := * (* Visitor )(clientData )
296
- return cfn (cursor , parent )
297
- }, unsafe .Pointer (& fn ))
298
- }
299
-
300
316
func (ct * Converter ) ProcessType (t clang.Type ) ast.Expr {
301
317
ct .incIndent ()
302
318
defer ct .decIndent ()
@@ -521,7 +537,7 @@ func (ct *Converter) ProcessMethodAttributes(cursor clang.Cursor, fn *ast.FuncDe
521
537
func (ct * Converter ) ProcessEnumType (cursor clang.Cursor ) * ast.EnumType {
522
538
items := make ([]* ast.EnumItem , 0 )
523
539
524
- VisitChildren (cursor , func (cursor , parent clang.Cursor ) clang.ChildVisitResult {
540
+ clangutils . VisitChildren (cursor , func (cursor , parent clang.Cursor ) clang.ChildVisitResult {
525
541
if cursor .Kind == clang .CursorEnumConstantDecl {
526
542
name := cursor .String ()
527
543
defer name .Dispose ()
@@ -578,9 +594,14 @@ func (ct *Converter) ProcessMacro(cursor clang.Cursor) *ast.Macro {
578
594
return macro
579
595
}
580
596
581
- func (ct * Converter ) ProcessInclude (cursor clang.Cursor ) * ast.Include {
597
+ func (ct * Converter ) ProcessInclude (cursor clang.Cursor ) ( * ast.Include , error ) {
582
598
name := toStr (cursor .String ())
583
- return & ast.Include {Path : name }
599
+ includedFile := cursor .IncludedFile ()
600
+ includedPath := toStr (includedFile .FileName ())
601
+ if includedPath == "" {
602
+ return nil , fmt .Errorf ("%s: failed to get included file" , name )
603
+ }
604
+ return & ast.Include {Path : includedPath }, nil
584
605
}
585
606
586
607
func (ct * Converter ) createBaseField (cursor clang.Cursor ) * ast.Field {
@@ -619,7 +640,7 @@ func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList {
619
640
620
641
params := & ast.FieldList {}
621
642
ct .logln ("ProcessFieldList: VisitChildren" )
622
- VisitChildren (cursor , func (subcsr , parent clang.Cursor ) clang.ChildVisitResult {
643
+ clangutils . VisitChildren (cursor , func (subcsr , parent clang.Cursor ) clang.ChildVisitResult {
623
644
switch subcsr .Kind {
624
645
case clang .CursorParmDecl , clang .CursorFieldDecl :
625
646
// In C language, parameter lists do not have similar parameter grouping in Go.
@@ -665,7 +686,7 @@ func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList {
665
686
// Note:Public Method is considered
666
687
func (ct * Converter ) ProcessMethods (cursor clang.Cursor ) []* ast.FuncDecl {
667
688
methods := make ([]* ast.FuncDecl , 0 )
668
- VisitChildren (cursor , func (subcsr , parent clang.Cursor ) clang.ChildVisitResult {
689
+ clangutils . VisitChildren (cursor , func (subcsr , parent clang.Cursor ) clang.ChildVisitResult {
669
690
if isMethod (subcsr ) && subcsr .CXXAccessSpecifier () == clang .CXXPublic {
670
691
method := ct .ProcessFuncDecl (subcsr )
671
692
if method != nil {
@@ -950,8 +971,7 @@ func isRangeChildOf(childRange, parentRange clang.SourceRange) bool {
950
971
}
951
972
952
973
func getOffset (location clang.SourceLocation ) c.Uint {
953
- var offset c.Uint
954
- location .SpellingLocation (nil , nil , nil , & offset )
974
+ _ , _ , _ , offset := clangutils .GetLocation (location )
955
975
return offset
956
976
}
957
977
0 commit comments