diff --git a/c/clang/_demo/castdump/astdump.go b/c/clang/_demo/castdump/astdump.go deleted file mode 100644 index 401c8a9b9..000000000 --- a/c/clang/_demo/castdump/astdump.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/goplus/llgo/c" - "github.com/goplus/llgo/c/clang" -) - -func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult { - depth := *(*c.Uint)(clientData) - printAST(cursor, depth+1) - return clang.ChildVisit_Continue -} - -func printAST(cursor clang.Cursor, depth c.Uint) { - cursorKind := cursor.Kind.String() - - cursorSpelling := cursor.String() - - for i := c.Uint(0); i < depth; i++ { - c.Fputs(c.Str(" "), c.Stdout) - } - - c.Printf(c.Str("%s: %s\n"), cursorKind.CStr(), cursorSpelling.CStr()) - - cursorKind.Dispose() - cursorSpelling.Dispose() - - clang.VisitChildren(cursor, visit, c.Pointer(&depth)) -} - -func main() { - if c.Argc != 2 { - fmt.Fprintln(os.Stderr, "Usage: castdump ") - return - } - sourceFile := *c.Advance(c.Argv, 1) - - index := clang.CreateIndex(0, 0) - - unit := index.ParseTranslationUnit( - sourceFile, - nil, 0, - nil, 0, - clang.TranslationUnit_None, - ) - - if unit == nil { - println("Unable to parse translation unit. Quitting.") - c.Exit(1) - } - - cursor := unit.Cursor() - - printAST(cursor, 0) - - unit.Dispose() - index.Dispose() -} diff --git a/chore/_xtool/castdump/castdump.go b/chore/_xtool/castdump/castdump.go new file mode 100644 index 000000000..79f82274d --- /dev/null +++ b/chore/_xtool/castdump/castdump.go @@ -0,0 +1,166 @@ +package main + +import ( + "fmt" + "os" + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/clang" +) + +type Data struct { + Depth c.Uint + Unit *clang.TranslationUnit +} + +func accessToString(spec clang.CXXAccessSpecifier) string { + switch spec { + case clang.CXXInvalidAccessSpecifier: + return "invalid" + case clang.CXXPublic: + return "public" + case clang.CXXProtected: + return "protected" + case clang.CXXPrivate: + return "private" + default: + return "unkown" + } +} + +func visit(cursor, parent clang.Cursor, ClientData c.Pointer) clang.ChildVisitResult { + data := (*Data)(ClientData) + printAST(cursor, data) + return clang.ChildVisit_Continue +} + +func printLocation(cursor clang.Cursor) { + loc := cursor.Location() + var file clang.File + var line, column c.Uint + + loc.SpellingLocation(&file, &line, &column, nil) + filename := file.FileName() + defer filename.Dispose() + + c.Printf(c.Str("(Loc:%s:%d:%d)\n"), filename.CStr(), line, column) +} + +func printAccess(cursor clang.Cursor) { + kind := cursor.Kind.String() + spell := cursor.String() + defer kind.Dispose() + defer spell.Dispose() + + c.Printf(c.Str("%s: %s %s\n"), kind.CStr(), spell.CStr(), c.AllocaCStr(accessToString(cursor.CXXAccessSpecifier()))) +} + +func printMacro(cursor clang.Cursor, unit *clang.TranslationUnit) { + kind := cursor.Kind.String() + defer kind.Dispose() + + c.Printf(c.Str("%s: "), kind.CStr()) + ran := cursor.Extent() + var numTokens c.Uint + var tokens *clang.Token + unit.Tokenize(ran, &tokens, &numTokens) + tokensSlice := unsafe.Slice(tokens, int(numTokens)) + for _, tok := range tokensSlice { + tokStr := unit.Token(tok) + c.Printf(c.Str("%s "), tokStr.CStr()) + tokStr.Dispose() + } + c.Printf(c.Str("\n")) +} + +func printFunc(cursor clang.Cursor) { + kind := cursor.Kind.String() + spell := cursor.String() + symbol := cursor.Mangling() + defer symbol.Dispose() + defer kind.Dispose() + defer spell.Dispose() + + c.Printf(c.Str("%s: %s (Symbol: %s)"), kind.CStr(), spell.CStr(), symbol.CStr()) +} + +func printDefault(cursor clang.Cursor) { + kind := cursor.Kind.String() + spell := cursor.String() + defer kind.Dispose() + defer spell.Dispose() + + if cursor.Type().Kind != clang.TypeInvalid { + typeSpell := cursor.Type().String() + c.Printf(c.Str("%s: %s (Type: %s)"), kind.CStr(), spell.CStr(), typeSpell.CStr()) + typeSpell.Dispose() + } else { + c.Printf(c.Str("%s: %s"), kind.CStr(), spell.CStr()) + } +} + +func printAST(cursor clang.Cursor, data *Data) { + kind := cursor.Kind.String() + spell := cursor.String() + + for i := c.Uint(0); i < data.Depth; i++ { + c.Fputs(c.Str(" "), c.Stdout) + } + + switch cursor.Kind { + case clang.CursorCXXAccessSpecifier: + printAccess(cursor) + case clang.CursorMacroDefinition: + printMacro(cursor, data.Unit) + case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor: + printFunc(cursor) + default: + printDefault(cursor) + } + + printLocation(cursor) + + data.Depth++ + clang.VisitChildren(cursor, visit, c.Pointer(data)) + data.Depth-- + + kind.Dispose() + spell.Dispose() +} + +func main() { + if c.Argc != 2 { + fmt.Fprintln(os.Stderr, "Usage: castdump ") + return + } + + args := make([]*c.Char, 3) + args[0] = c.Str("-x") + args[1] = c.Str("c++") + args[2] = c.Str("-std=c++11") + + sourceFile := *c.Advance(c.Argv, 1) + index := clang.CreateIndex(0, 0) + unit := index.ParseTranslationUnit( + sourceFile, + unsafe.SliceData(args), 3, + nil, 0, + clang.DetailedPreprocessingRecord, + ) + defer index.Dispose() + defer unit.Dispose() + + if unit == nil { + println("Unable to parse translation unit. Quitting.") + c.Exit(1) + } + + cursor := unit.Cursor() + + Data := &Data{ + Depth: 0, + Unit: unit, + } + printAST(cursor, Data) +}