Merge pull request #780 from luoliwoshang/llcppsymg/language
llcppsymg:parse c / c++ & output func proto
This commit is contained in:
@@ -4,17 +4,22 @@ 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 SymbolInfo struct {
|
||||
GoName string
|
||||
ProtoName string
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
namespaceName string
|
||||
className string
|
||||
prefixes []string
|
||||
symbolMap map[string]string
|
||||
symbolMap map[string]*SymbolInfo
|
||||
currentFile string
|
||||
nameCounts map[string]int
|
||||
}
|
||||
@@ -22,7 +27,7 @@ type Context struct {
|
||||
func newContext(prefixes []string) *Context {
|
||||
return &Context{
|
||||
prefixes: prefixes,
|
||||
symbolMap: make(map[string]string),
|
||||
symbolMap: make(map[string]*SymbolInfo),
|
||||
nameCounts: make(map[string]int),
|
||||
}
|
||||
}
|
||||
@@ -48,9 +53,35 @@ func (c *Context) removePrefix(str string) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func (c *Context) genGoName(name string) string {
|
||||
class := c.removePrefix(c.className)
|
||||
func toTitle(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToUpper(s[:1]) + strings.ToLower(s[1:])
|
||||
}
|
||||
|
||||
func toCamel(originName string) string {
|
||||
if originName == "" {
|
||||
return ""
|
||||
}
|
||||
subs := strings.Split(string(originName), "_")
|
||||
name := ""
|
||||
for _, sub := range subs {
|
||||
name += toTitle(sub)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// 1. remove prefix from config
|
||||
// 2. convert to camel case
|
||||
func (c *Context) toGoName(name string) string {
|
||||
name = c.removePrefix(name)
|
||||
return toCamel(name)
|
||||
}
|
||||
|
||||
func (c *Context) genGoName(name string) string {
|
||||
class := c.toGoName(c.className)
|
||||
name = c.toGoName(name)
|
||||
|
||||
var baseName string
|
||||
if class == "" {
|
||||
@@ -73,6 +104,22 @@ func (c *Context) genMethodName(class, name string) string {
|
||||
return prefix + name
|
||||
}
|
||||
|
||||
func (p *Context) genProtoName(cursor clang.Cursor) string {
|
||||
displayName := cursor.DisplayName()
|
||||
defer displayName.Dispose()
|
||||
|
||||
scopingParts := clangutils.BuildScopingParts(cursor.SemanticParent())
|
||||
|
||||
var builder strings.Builder
|
||||
for _, part := range scopingParts {
|
||||
builder.WriteString(part)
|
||||
builder.WriteString("::")
|
||||
}
|
||||
|
||||
builder.WriteString(c.GoString(displayName.CStr()))
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
func (c *Context) addSuffix(name string) string {
|
||||
c.nameCounts[name]++
|
||||
count := c.nameCounts[name]
|
||||
@@ -96,8 +143,10 @@ func collectFuncInfo(cursor clang.Cursor) {
|
||||
defer symbol.Dispose()
|
||||
defer cursorStr.Dispose()
|
||||
|
||||
goName := context.genGoName(name)
|
||||
context.symbolMap[symbolName] = goName
|
||||
context.symbolMap[symbolName] = &SymbolInfo{
|
||||
GoName: context.genGoName(name),
|
||||
ProtoName: context.genProtoName(cursor),
|
||||
}
|
||||
}
|
||||
|
||||
func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult {
|
||||
@@ -141,35 +190,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]*SymbolInfo, error) {
|
||||
context = newContext(prefixes)
|
||||
|
||||
index := clang.CreateIndex(0, 0)
|
||||
for _, filename := range filepaths {
|
||||
unit := index.ParseTranslationUnit(
|
||||
c.AllocaCStr(filename),
|
||||
unsafe.SliceData(args), 3,
|
||||
nil, 0,
|
||||
clang.TranslationUnit_None,
|
||||
)
|
||||
|
||||
if unit == nil {
|
||||
_, unit, err := clangutils.CreateTranslationUnit(&clangutils.Config{
|
||||
File: filename,
|
||||
Temp: false,
|
||||
IsCpp: isCpp,
|
||||
Index: index,
|
||||
})
|
||||
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()
|
||||
|
||||
return context.symbolMap, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user