c/clang/symg:merge llcppinfofetch to llcppsymg

This commit is contained in:
luoliwoshang
2024-07-29 17:57:38 +08:00
parent 01d0338851
commit 84ca145663
2 changed files with 46 additions and 73 deletions

View File

@@ -31,6 +31,7 @@ import (
"github.com/goplus/llgo/c" "github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/cjson" "github.com/goplus/llgo/c/cjson"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
"github.com/goplus/llgo/chore/llcppg/types" "github.com/goplus/llgo/chore/llcppg/types"
"github.com/goplus/llgo/cpp/llvm" "github.com/goplus/llgo/cpp/llvm"
) )
@@ -58,10 +59,11 @@ func main() {
check(err) check(err)
files, err := parseHeaderFile(config) filepaths := generateHeaderFilePath(config.CFlags, config.Include)
astInfos, err := parse.ParseHeaderFile(filepaths)
check(err) check(err)
symbolInfo := getCommonSymbols(symbols, files, config.TrimPrefixes) symbolInfo := getCommonSymbols(symbols, astInfos, config.TrimPrefixes)
jsonData, err := json.MarshalIndent(symbolInfo, "", " ") jsonData, err := json.MarshalIndent(symbolInfo, "", " ")
check(err) check(err)
@@ -91,7 +93,7 @@ func getConf(data []byte) (config types.Config, err error) {
conf := cjson.ParseBytes(data) conf := cjson.ParseBytes(data)
defer conf.Delete() defer conf.Delete()
if conf == nil { if conf == nil {
return config, errors.New("failed to execute nm command") return config, errors.New("failed to parse config")
} }
config.Name = c.GoString(conf.GetItem("name").GetStringValue()) config.Name = c.GoString(conf.GetItem("name").GetStringValue())
config.CFlags = c.GoString(conf.GetItem("cflags").GetStringValue()) config.CFlags = c.GoString(conf.GetItem("cflags").GetStringValue())
@@ -179,26 +181,6 @@ func decodeSymbolName(symbolName string) (string, error) {
return decodedName, nil return decodedName, nil
} }
func parseHeaderFile(config types.Config) ([]types.ASTInformation, error) {
files := generateHeaderFilePath(config.CFlags, config.Include)
fmt.Println(files)
headerFileCmd := exec.Command("llcppinfofetch", files...)
fmt.Println("Executing command:", headerFileCmd.String())
headerFileOutput, err := headerFileCmd.Output()
if err != nil {
return nil, errors.New("failed to execute header file command")
}
fmt.Println("headerFileOutput:", string(headerFileOutput), len(headerFileOutput))
t := make([]types.ASTInformation, 0)
err = json.Unmarshal(headerFileOutput, &t)
if err != nil {
return nil, err
}
return t, nil
}
func generateHeaderFilePath(cflags string, files []string) []string { func generateHeaderFilePath(cflags string, files []string) []string {
prefixPath := cflags prefixPath := cflags
prefixPath = strings.TrimPrefix(prefixPath, "-I") prefixPath = strings.TrimPrefix(prefixPath, "-I")

View File

@@ -1,23 +1,20 @@
package main package parse
import ( import (
"fmt" "errors"
"os"
"strconv" "strconv"
"unsafe" "unsafe"
"github.com/goplus/llgo/chore/llcppg/types"
"github.com/goplus/llgo/c" "github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/cjson"
"github.com/goplus/llgo/c/clang" "github.com/goplus/llgo/c/clang"
"github.com/goplus/llgo/chore/llcppg/types"
) )
type Context struct { type Context struct {
namespaceName string namespaceName string
className string className string
astInfo []types.ASTInformation astInfo []types.ASTInformation
currentFile *c.Char currentFile string
} }
func newContext() *Context { func newContext() *Context {
@@ -34,7 +31,7 @@ func (c *Context) setClassName(name string) {
c.className = name c.className = name
} }
func (c *Context) setCurrentFile(filename *c.Char) { func (c *Context) setCurrentFile(filename string) {
c.currentFile = filename c.currentFile = filename
} }
@@ -109,37 +106,50 @@ func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitRe
loc.SpellingLocation(&file, &line, &column, nil) loc.SpellingLocation(&file, &line, &column, nil)
filename := file.FileName() filename := file.FileName()
if c.Strcmp(filename.CStr(), context.currentFile) == 0 { if c.Strcmp(filename.CStr(), c.AllocaCStr(context.currentFile)) == 0 {
info := collectFuncInfo(cursor) info := collectFuncInfo(cursor)
info.Location = c.GoString(filename.CStr()) + ":" + strconv.Itoa(int(line)) + ":" + strconv.Itoa(int(column)) info.Location = c.GoString(filename.CStr()) + ":" + strconv.Itoa(int(line)) + ":" + strconv.Itoa(int(column))
context.astInfo = append(context.astInfo, info) context.astInfo = append(context.astInfo, info)
} }
defer filename.Dispose() defer filename.Dispose()
} }
return clang.ChildVisit_Continue return clang.ChildVisit_Continue
} }
func parse(filenames []*c.Char) []types.ASTInformation { // func main() {
// if c.Argc < 2 {
// fmt.Fprintln(os.Stderr, "Usage: <C++ header file1> [<C++ header file2> ...]\n")
// return
// } else {
// filenames := make([]*c.Char, c.Argc-1)
// for i := 1; i < int(c.Argc); i++ {
// filenames[i-1] = c.Index(c.Argv, c.Int(i))
// }
// printJson(parse(filenames))
// }
// }
func ParseHeaderFile(filepaths []string) ([]types.ASTInformation, error) {
index := clang.CreateIndex(0, 0) index := clang.CreateIndex(0, 0)
args := make([]*c.Char, 3) args := make([]*c.Char, 3)
args[0] = c.Str("-x") args[0] = c.Str("-x")
args[1] = c.Str("c++") args[1] = c.Str("c++")
args[2] = c.Str("-std=c++11") args[2] = c.Str("-std=c++11")
context = newContext()
for _, filename := range filenames { for _, filename := range filepaths {
unit := index.ParseTranslationUnit( unit := index.ParseTranslationUnit(
filename, c.AllocaCStr(filename),
unsafe.SliceData(args), 3, unsafe.SliceData(args), 3,
nil, 0, nil, 0,
clang.TranslationUnit_None, clang.TranslationUnit_None,
) )
if unit == nil { if unit == nil {
fmt.Printf("Unable to parse translation unit for file: %s. Skipping.\n", c.GoString(filename)) return nil, errors.New("Unable to parse translation unit for file " + filename)
continue
} }
cursor := unit.Cursor() cursor := unit.Cursor()
@@ -152,42 +162,23 @@ func parse(filenames []*c.Char) []types.ASTInformation {
index.Dispose() index.Dispose()
return context.astInfo return context.astInfo, nil
}
func printJson(infos []types.ASTInformation) {
root := cjson.Array()
for _, info := range infos { // files := generateHeaderFilePath(config.CFlags, config.Include)
item := cjson.Object() // fmt.Println(files)
item.SetItem(c.Str("namespace"), cjson.String(c.AllocaCStr(info.Namespace))) // headerFileCmd := exec.Command("llcppinfofetch", files...)
item.SetItem(c.Str("class"), cjson.String(c.AllocaCStr(info.Class)))
item.SetItem(c.Str("name"), cjson.String(c.AllocaCStr(info.Name)))
item.SetItem(c.Str("returnType"), cjson.String(c.AllocaCStr(info.ReturnType)))
item.SetItem(c.Str("location"), cjson.String(c.AllocaCStr(info.Location)))
item.SetItem(c.Str("symbol"), cjson.String(c.AllocaCStr(info.Symbol)))
params := cjson.Array() // fmt.Println("Executing command:", headerFileCmd.String())
for _, param := range info.Parameters {
paramObj := cjson.Object()
paramObj.SetItem(c.Str("name"), cjson.String(c.AllocaCStr(param.Name)))
paramObj.SetItem(c.Str("type"), cjson.String(c.AllocaCStr(param.Type)))
params.AddItem(paramObj)
}
item.SetItem(c.Str("parameters"), params)
root.AddItem(item) // headerFileOutput, err := headerFileCmd.Output()
} // if err != nil {
c.Printf(c.Str("%s\n"), root.Print()) // return nil, errors.New("failed to execute header file command")
} // }
func main() { // fmt.Println("headerFileOutput:", string(headerFileOutput), len(headerFileOutput))
if c.Argc < 2 { // t := make([]types.ASTInformation, 0)
fmt.Fprintln(os.Stderr, "Usage: <C++ header file1> [<C++ header file2> ...]\n") // err = json.Unmarshal(headerFileOutput, &t)
return // if err != nil {
} else { // return nil, err
filenames := make([]*c.Char, c.Argc-1) // }
for i := 1; i < int(c.Argc); i++ { // return t, nil
filenames[i-1] = c.Index(c.Argv, c.Int(i))
}
printJson(parse(filenames))
}
} }