Skip to content

Commit b590856

Browse files
authored
Merge pull request #6 from luoliwoshang/llcppsigfetch/include
llcppsigfetch:abs include path & system header & config mode 's include flags
2 parents a687144 + c00cd21 commit b590856

File tree

8 files changed

+208
-105
lines changed

8 files changed

+208
-105
lines changed

_xtool/llcppsigfetch/llcppsigfetch.go

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ import (
2020
"fmt"
2121
"io"
2222
"os"
23-
"path/filepath"
2423
"strconv"
2524
"strings"
2625

27-
"github.com/goplus/llgo/c"
28-
"github.com/goplus/llgo/c/cjson"
2926
"github.com/goplus/llcppg/_xtool/llcppsigfetch/parse"
3027
"github.com/goplus/llcppg/_xtool/llcppsymg/args"
3128
"github.com/goplus/llcppg/_xtool/llcppsymg/clangutils"
3229
"github.com/goplus/llcppg/_xtool/llcppsymg/config"
30+
"github.com/goplus/llcppg/_xtool/llcppsymg/config/cfgparse"
31+
"github.com/goplus/llgo/c"
32+
"github.com/goplus/llgo/c/cjson"
3333
)
3434

3535
func main() {
@@ -150,8 +150,7 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool, verbose boo
150150
os.Exit(1)
151151
}
152152

153-
//todo(zzy): reuse the llcppsymg's cflags parse
154-
cflag := ParseCFlags(conf.CFlags)
153+
cflag := cfgparse.ParseCFlags(conf.CFlags)
155154
files, notFounds, err := cflag.GenHeaderFilePaths(conf.Include)
156155
check(err)
157156

@@ -162,7 +161,16 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool, verbose boo
162161
}
163162
}
164163

165-
context := parse.NewContext(conf.Cplusplus)
164+
// Generate include directory flags (-I flags)
165+
incFlags := make([]string, 0, len(cflag.Paths))
166+
for _, path := range cflag.Paths {
167+
incFlags = append(incFlags, "-I"+path)
168+
}
169+
170+
context := parse.NewContext(&parse.ContextConfig{
171+
Conf: conf.Config,
172+
IncFlags: incFlags,
173+
})
166174
err = context.ProcessFiles(files)
167175
check(err)
168176

@@ -208,48 +216,6 @@ func outputResult(result *c.Char, outputToFile bool) {
208216
}
209217
}
210218

211-
// todo(zzy): reuse the llcppsymg's cflags parse https://github.com/goplus/llgo/pull/788
212-
type CFlags struct {
213-
Paths []string // Include Path
214-
}
215-
216-
func ParseCFlags(cflags string) *CFlags {
217-
parts := strings.Fields(cflags)
218-
cf := &CFlags{}
219-
for _, part := range parts {
220-
if strings.HasPrefix(part, "-I") {
221-
cf.Paths = append(cf.Paths, part[2:])
222-
}
223-
}
224-
return cf
225-
}
226-
227-
func (cf *CFlags) GenHeaderFilePaths(files []string) ([]string, []string, error) {
228-
var foundPaths []string
229-
var notFound []string
230-
231-
for _, file := range files {
232-
var found bool
233-
for _, path := range cf.Paths {
234-
fullPath := filepath.Join(path, file)
235-
if _, err := os.Stat(fullPath); err == nil {
236-
foundPaths = append(foundPaths, fullPath)
237-
found = true
238-
break
239-
}
240-
}
241-
if !found {
242-
notFound = append(notFound, file)
243-
}
244-
}
245-
246-
if len(foundPaths) == 0 {
247-
return nil, notFound, fmt.Errorf("failed to find any header files")
248-
}
249-
250-
return foundPaths, notFound, nil
251-
}
252-
253219
func outputInfo(context *parse.Context, outputToFile bool) {
254220
info := context.Output()
255221
str := info.Print()

_xtool/llcppsigfetch/parse/cvt.go

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,19 @@ import (
77
"strings"
88
"unsafe"
99

10-
"github.com/goplus/llgo/c"
11-
"github.com/goplus/llgo/c/cjson"
12-
"github.com/goplus/llgo/c/clang"
1310
"github.com/goplus/llcppg/_xtool/llcppsymg/clangutils"
1411
"github.com/goplus/llcppg/ast"
1512
"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"
1616
)
1717

1818
type FileEntry struct {
19-
Path string
20-
Doc *ast.File
19+
Path string
20+
IncPath string
21+
IsSys bool
22+
Doc *ast.File
2123
}
2224

2325
type Converter struct {
@@ -58,11 +60,14 @@ func NewConverter(config *clangutils.Config) (*Converter, error) {
5860
return nil, err
5961
}
6062

63+
files := initFileEntries(unit)
64+
6165
return &Converter{
62-
Files: make([]*FileEntry, 0),
66+
Files: files,
6367
index: index,
6468
unit: unit,
6569
}, nil
70+
6671
}
6772

6873
func (ct *Converter) Dispose() {
@@ -71,6 +76,26 @@ func (ct *Converter) Dispose() {
7176
ct.unit.Dispose()
7277
}
7378

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+
7499
func (ct *Converter) GetTokens(cursor clang.Cursor) []*ast.Token {
75100
ran := cursor.Extent()
76101
var numTokens c.Uint
@@ -121,42 +146,40 @@ func (ct *Converter) logln(args ...interface{}) {
121146
}
122147
}
123148

124-
func (ct *Converter) UpdateLoc(cursor clang.Cursor) {
149+
func (ct *Converter) GetCurFile(cursor clang.Cursor) *ast.File {
125150
loc := cursor.Location()
126151
var file clang.File
127152
loc.SpellingLocation(&file, nil, nil, nil)
128-
129153
filePath := toStr(file.FileName())
130-
131154
if filePath == "" {
132155
//todo(zzy): For some built-in macros, there is no file.
133156
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 == "" {
141157
ct.logln("GetCurFile: NO FILE")
142158
return nil
143159
}
160+
ct.curLoc = ast.Location{File: filePath}
161+
144162
// todo(zzy): more efficient
145163
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)
148166
return ct.Files[i].Doc
149167
}
150168
}
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
155176
}
156177

157178
func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
158179
base := ast.DeclBase{
159-
Loc: &ct.curLoc,
180+
Loc: &ast.Location{
181+
File: ct.curLoc.File,
182+
},
160183
Parent: ct.BuildScopingExpr(cursor.SemanticParent()),
161184
}
162185
commentGroup, isDoc := ct.ParseCommentGroup(cursor)
@@ -206,9 +229,7 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
206229
ct.incIndent()
207230
defer ct.decIndent()
208231

209-
ct.UpdateLoc(cursor)
210-
211-
curFile := ct.GetCurFile()
232+
curFile := ct.GetCurFile(cursor)
212233

213234
name := toStr(cursor.String())
214235
ct.logf("visitTop: Cursor: %s\n", name)
@@ -219,7 +240,11 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
219240

220241
switch cursor.Kind {
221242
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+
}
223248
curFile.Includes = append(curFile.Includes, include)
224249
ct.logln("visitTop: ProcessInclude END ", include.Path)
225250
case clang.CursorMacroDefinition:
@@ -276,27 +301,18 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
276301
curFile.Decls = append(curFile.Decls, typedefDecl)
277302
ct.logln("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name)
278303
case clang.CursorNamespace:
279-
VisitChildren(cursor, ct.visitTop)
304+
clangutils.VisitChildren(cursor, ct.visitTop)
280305
}
281306
return clang.ChildVisit_Continue
282307
}
283308

284309
func (ct *Converter) Convert() ([]*FileEntry, error) {
285310
cursor := ct.unit.Cursor()
286311
// visit top decls (struct,class,function & macro,include)
287-
VisitChildren(cursor, ct.visitTop)
312+
clangutils.VisitChildren(cursor, ct.visitTop)
288313
return ct.Files, nil
289314
}
290315

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-
300316
func (ct *Converter) ProcessType(t clang.Type) ast.Expr {
301317
ct.incIndent()
302318
defer ct.decIndent()
@@ -521,7 +537,7 @@ func (ct *Converter) ProcessMethodAttributes(cursor clang.Cursor, fn *ast.FuncDe
521537
func (ct *Converter) ProcessEnumType(cursor clang.Cursor) *ast.EnumType {
522538
items := make([]*ast.EnumItem, 0)
523539

524-
VisitChildren(cursor, func(cursor, parent clang.Cursor) clang.ChildVisitResult {
540+
clangutils.VisitChildren(cursor, func(cursor, parent clang.Cursor) clang.ChildVisitResult {
525541
if cursor.Kind == clang.CursorEnumConstantDecl {
526542
name := cursor.String()
527543
defer name.Dispose()
@@ -578,9 +594,14 @@ func (ct *Converter) ProcessMacro(cursor clang.Cursor) *ast.Macro {
578594
return macro
579595
}
580596

581-
func (ct *Converter) ProcessInclude(cursor clang.Cursor) *ast.Include {
597+
func (ct *Converter) ProcessInclude(cursor clang.Cursor) (*ast.Include, error) {
582598
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
584605
}
585606

586607
func (ct *Converter) createBaseField(cursor clang.Cursor) *ast.Field {
@@ -619,7 +640,7 @@ func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList {
619640

620641
params := &ast.FieldList{}
621642
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 {
623644
switch subcsr.Kind {
624645
case clang.CursorParmDecl, clang.CursorFieldDecl:
625646
// 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 {
665686
// Note:Public Method is considered
666687
func (ct *Converter) ProcessMethods(cursor clang.Cursor) []*ast.FuncDecl {
667688
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 {
669690
if isMethod(subcsr) && subcsr.CXXAccessSpecifier() == clang.CXXPublic {
670691
method := ct.ProcessFuncDecl(subcsr)
671692
if method != nil {
@@ -950,8 +971,7 @@ func isRangeChildOf(childRange, parentRange clang.SourceRange) bool {
950971
}
951972

952973
func getOffset(location clang.SourceLocation) c.Uint {
953-
var offset c.Uint
954-
location.SpellingLocation(nil, nil, nil, &offset)
974+
_, _, _, offset := clangutils.GetLocation(location)
955975
return offset
956976
}
957977

_xtool/llcppsigfetch/parse/cvt_test/cvt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func GetType(option *GetTypeOptions) (clang.Type, *clang.Index, *clang.Translati
7979
}
8080
cursor := unit.Cursor()
8181
var typ clang.Type
82-
parse.VisitChildren(cursor, func(child, parent clang.Cursor) clang.ChildVisitResult {
82+
clangutils.VisitChildren(cursor, func(child, parent clang.Cursor) clang.ChildVisitResult {
8383
if child.Kind == clang.CursorVarDecl && (option.ExpectTypeKind == clang.TypeInvalid || option.ExpectTypeKind == child.Type().Kind) {
8484
typ = child.Type()
8585
return clang.ChildVisit_Break

_xtool/llcppsigfetch/parse/cvt_test/preprocess_test/llgo.expect

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
#stdout
2+
=== TestSystemHeader ===
3+
stdio.h is absolute path
4+
include files are all system headers
5+
=== TestInclusionMap ===
6+
sys/types.h include path found
27
TestDefine Case 1:
38
{
49
"temp.h": {
@@ -110,10 +115,7 @@ TestInclude Case 1:
110115
"temp.h": {
111116
"_Type": "File",
112117
"decls": [],
113-
"includes": [{
114-
"_Type": "Include",
115-
"Path": "foo.h"
116-
}],
118+
"includes": [],
117119
"macros": []
118120
}
119121
}
@@ -169,7 +171,7 @@ TestMacroExpansionOtherFile:
169171
}],
170172
"includes": [{
171173
"_Type": "Include",
172-
"Path": "def.h"
174+
"Path": "./testdata/macroexpan/def.h"
173175
}],
174176
"macros": []
175177
},

0 commit comments

Comments
 (0)