llcppsigfech:basic struct
llcppsigfetch:basic parse converter llcppsigfetch:converter top decl llcppg:converter test
This commit is contained in:
@@ -16,6 +16,65 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsymg/config"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// TODO(xsw): implement llcppsigfetch tool
|
cfgFile := "llcppg.cfg"
|
||||||
|
if len(os.Args) > 1 {
|
||||||
|
cfgFile = os.Args[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
var err error
|
||||||
|
if cfgFile == "-" {
|
||||||
|
data, err = io.ReadAll(os.Stdin)
|
||||||
|
} else {
|
||||||
|
data, err = os.ReadFile(cfgFile)
|
||||||
|
}
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
conf, err := config.GetConf(data)
|
||||||
|
check(err)
|
||||||
|
defer conf.Delete()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "Failed to parse config file:", cfgFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
files := getHeaderFiles(conf.CFlags, conf.Include)
|
||||||
|
|
||||||
|
context := parse.NewContext()
|
||||||
|
err = context.ProcessFiles(files)
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
outputInfo(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(err error) {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHeaderFiles(cflags string, files []string) []string {
|
||||||
|
prefix := cflags
|
||||||
|
prefix = strings.TrimPrefix(prefix, "-I")
|
||||||
|
var paths []string
|
||||||
|
for _, f := range files {
|
||||||
|
paths = append(paths, filepath.Join(prefix, f))
|
||||||
|
}
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
|
func outputInfo(context *parse.Context) {
|
||||||
|
// TODO(zzy):
|
||||||
}
|
}
|
||||||
|
|||||||
98
chore/_xtool/llcppsigfetch/parse/cvt.go
Normal file
98
chore/_xtool/llcppsigfetch/parse/cvt.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package parse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/c/clang"
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Converter struct {
|
||||||
|
files map[string]*ast.File
|
||||||
|
typeMap map[clang.Type]*ast.Expr
|
||||||
|
declMap map[clang.Cursor]*ast.Decl
|
||||||
|
curLoc ast.Location
|
||||||
|
index *clang.Index
|
||||||
|
unit *clang.TranslationUnit
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConverter(filepath string) (*Converter, error) {
|
||||||
|
args := []*c.Char{
|
||||||
|
c.Str("-x"),
|
||||||
|
c.Str("c++"),
|
||||||
|
c.Str("-std=c++11"),
|
||||||
|
}
|
||||||
|
index := clang.CreateIndex(0, 0)
|
||||||
|
unit := index.ParseTranslationUnit(
|
||||||
|
c.AllocaCStr(filepath),
|
||||||
|
unsafe.SliceData(args), 3,
|
||||||
|
nil, 0,
|
||||||
|
clang.DetailedPreprocessingRecord,
|
||||||
|
)
|
||||||
|
if unit == nil {
|
||||||
|
return nil, errors.New("failed to parse translation unit")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Converter{
|
||||||
|
typeMap: make(map[clang.Type]*ast.Expr),
|
||||||
|
declMap: make(map[clang.Cursor]*ast.Decl),
|
||||||
|
files: make(map[string]*ast.File),
|
||||||
|
index: index,
|
||||||
|
unit: unit,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) Dispose() {
|
||||||
|
ct.index.Dispose()
|
||||||
|
ct.unit.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// visit top decls (struct,class,function,enum & marco,include)
|
||||||
|
func visit(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult {
|
||||||
|
ct := (*Converter)(clientData)
|
||||||
|
switch cursor.Kind {
|
||||||
|
case clang.CursorInclusionDirective:
|
||||||
|
fmt.Println("todo: Process include")
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
case clang.CursorMacroDefinition:
|
||||||
|
fmt.Println("todo: Process macro")
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
case clang.CursorEnumDecl:
|
||||||
|
fmt.Println("todo: Process enum")
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
case clang.CursorClassDecl:
|
||||||
|
ct.ProcessClass(cursor)
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
case clang.CursorStructDecl:
|
||||||
|
fmt.Println("todo: Process struct")
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
case clang.CursorFunctionDecl:
|
||||||
|
ct.ProcessFunc(cursor)
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
default:
|
||||||
|
// non-top-level decl, continue recursion
|
||||||
|
return clang.ChildVisit_Recurse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessFunc(cursor clang.Cursor) {
|
||||||
|
println("todo: Process func")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) ProcessClass(cursor clang.Cursor) {
|
||||||
|
println("todo: Process class")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) Convert() (map[string]*ast.File, error) {
|
||||||
|
cursor := ct.unit.Cursor()
|
||||||
|
// visit top decls (struct,class,function & marco,include)
|
||||||
|
clang.VisitChildren(cursor, visit, c.Pointer(ct))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ct *Converter) UpdateLocation(loc ast.Location) {
|
||||||
|
ct.curLoc = loc
|
||||||
|
}
|
||||||
24
chore/_xtool/llcppsigfetch/parse/cvt_test/cvt.go
Normal file
24
chore/_xtool/llcppsigfetch/parse/cvt_test/cvt.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if c.Argc != 2 {
|
||||||
|
fmt.Fprintln(os.Stderr, "Usage: cvt <headerFile>")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sourceFile := *c.Advance(c.Argv, 1)
|
||||||
|
c.Printf(c.Str("sourceFile: %s\n"), sourceFile)
|
||||||
|
converter, err := parse.NewConverter(c.GoString(sourceFile))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer converter.Dispose()
|
||||||
|
converter.Convert()
|
||||||
|
}
|
||||||
60
chore/_xtool/llcppsigfetch/parse/parse.go
Normal file
60
chore/_xtool/llcppsigfetch/parse/parse.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package parse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/chore/llcppg/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Context struct {
|
||||||
|
Files map[string]*ast.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContext() *Context {
|
||||||
|
return &Context{
|
||||||
|
Files: make(map[string]*ast.File),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessFiles processes the given files and adds them to the context
|
||||||
|
func (p *Context) ProcessFiles(files []string) error {
|
||||||
|
for _, file := range files {
|
||||||
|
if err := p.processFile(file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse file and add it to the context,avoid duplicate parsing
|
||||||
|
func (p *Context) processFile(path string) error {
|
||||||
|
if _, exists := p.Files[path]; exists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
parsedfiles, err := p.parseFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("failed to parse file: " + path)
|
||||||
|
}
|
||||||
|
|
||||||
|
for path, file := range parsedfiles {
|
||||||
|
if _, exist := p.Files[path]; !exist {
|
||||||
|
p.Files[path] = file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Context) parseFile(path string) (map[string]*ast.File, error) {
|
||||||
|
converter, err := NewConverter(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to create converter " + path)
|
||||||
|
}
|
||||||
|
defer converter.Dispose()
|
||||||
|
|
||||||
|
files, err := converter.Convert()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user