diff --git a/chore/_xtool/llcppsymg/clangutils/clangutils.go b/chore/_xtool/llcppsymg/clangutils/clangutils.go new file mode 100644 index 00000000..c03281dd --- /dev/null +++ b/chore/_xtool/llcppsymg/clangutils/clangutils.go @@ -0,0 +1,72 @@ +package clangutils + +import ( + "errors" + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/clang" +) + +type Config struct { + File string + Temp bool + Args []string + IsCpp bool + Index *clang.Index +} + +func CreateTranslationUnit(config *Config) (*clang.Index, *clang.TranslationUnit, error) { + // default use the c/c++ standard of clang; c:gnu17 c++:gnu++17 + // https://clang.llvm.org/docs/CommandGuide/clang.html + defaultArgs := []string{"-x", "c"} + if config.IsCpp { + defaultArgs = []string{"-x", "c++"} + } + allArgs := append(defaultArgs, config.Args...) + + cArgs := make([]*c.Char, len(allArgs)) + for i, arg := range allArgs { + cArgs[i] = c.AllocaCStr(arg) + } + + var index *clang.Index + if config.Index != nil { + index = config.Index + } else { + index = clang.CreateIndex(0, 0) + } + + var unit *clang.TranslationUnit + + if config.Temp { + content := c.AllocaCStr(config.File) + tempFile := &clang.UnsavedFile{ + Filename: c.Str("temp.h"), + Contents: content, + Length: c.Ulong(c.Strlen(content)), + } + + unit = index.ParseTranslationUnit( + tempFile.Filename, + unsafe.SliceData(cArgs), c.Int(len(cArgs)), + tempFile, 1, + clang.DetailedPreprocessingRecord, + ) + + } else { + cFile := c.AllocaCStr(config.File) + unit = index.ParseTranslationUnit( + cFile, + unsafe.SliceData(cArgs), c.Int(len(cArgs)), + nil, 0, + clang.DetailedPreprocessingRecord, + ) + } + + if unit == nil { + return nil, nil, errors.New("failed to parse translation unit") + } + + return index, unit, nil +} diff --git a/chore/_xtool/llcppsymg/parse/parse.go b/chore/_xtool/llcppsymg/parse/parse.go index f3e852eb..408e8419 100644 --- a/chore/_xtool/llcppsymg/parse/parse.go +++ b/chore/_xtool/llcppsymg/parse/parse.go @@ -4,10 +4,10 @@ import ( "errors" "strconv" "strings" - "unsafe" "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/clang" + "github.com/goplus/llgo/chore/_xtool/llcppsymg/clangutils" ) type Context struct { @@ -133,35 +133,25 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe return clang.ChildVisit_Continue } -func ParseHeaderFile(filepaths []string, prefixes []string) (map[string]string, error) { - index := clang.CreateIndex(0, 0) - args := make([]*c.Char, 3) - args[0] = c.Str("-x") - args[1] = c.Str("c++") - args[2] = c.Str("-std=c++11") +func ParseHeaderFile(filepaths []string, prefixes []string, isCpp bool) (map[string]string, error) { + context = newContext(prefixes) for _, filename := range filepaths { - unit := index.ParseTranslationUnit( - c.AllocaCStr(filename), - unsafe.SliceData(args), 3, - nil, 0, - clang.TranslationUnit_None, - ) - - if unit == nil { + index, unit, err := clangutils.CreateTranslationUnit(&clangutils.Config{ + File: filename, + Temp: false, + IsCpp: isCpp, + }) + if err != nil { return nil, errors.New("Unable to parse translation unit for file " + filename) } cursor := unit.Cursor() context.setCurrentFile(filename) - clang.VisitChildren(cursor, visit, nil) - unit.Dispose() + index.Dispose() } - - index.Dispose() - return context.symbolMap, nil }