From 01bf7c8c388c0cb90f3bee5746884435b285667f Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Fri, 18 Oct 2024 23:35:52 +0800 Subject: [PATCH 01/13] llcppsymg & llcppsigfetch parse args --- .../llcppsymg/_cmptest/args_test/args.go | 63 +++++++++++++++++++ .../llcppsymg/_cmptest/args_test/llgo.expect | 54 ++++++++++++++++ chore/_xtool/llcppsymg/args/args.go | 51 +++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 chore/_xtool/llcppsymg/_cmptest/args_test/args.go create mode 100644 chore/_xtool/llcppsymg/_cmptest/args_test/llgo.expect create mode 100644 chore/_xtool/llcppsymg/args/args.go diff --git a/chore/_xtool/llcppsymg/_cmptest/args_test/args.go b/chore/_xtool/llcppsymg/_cmptest/args_test/args.go new file mode 100644 index 00000000..76dcf7a7 --- /dev/null +++ b/chore/_xtool/llcppsymg/_cmptest/args_test/args.go @@ -0,0 +1,63 @@ +package main + +import ( + "fmt" + + "github.com/goplus/llgo/chore/_xtool/llcppsymg/args" +) + +func main() { + TestParseArgs() +} + +func TestParseArgs() { + fmt.Println("=== Test ParseArgs ===") + + swflags := map[string]bool{ + "--extract": true, + } + + testCases := []struct { + name string + input []string + }{ + { + name: "Basic flags", + input: []string{"-h", "-v", "-"}, + }, + { + name: "Config file", + input: []string{"lua.llcppg.cfg"}, + }, + { + name: "Extract with multiple args", + input: []string{"--extract", "file1.h", "file2.h", "-v"}, + }, + { + name: "Non-skippable flags", + input: []string{"--extract", "file1.h", "file2.h", "-out=true", "-cpp=true", "-v"}, + }, + { + name: "Mixed flags", + input: []string{"-v", "--extract", "file.h", "-out=true", "config.json"}, + }, + { + name: "Empty input", + input: []string{}, + }, + } + + for _, tc := range testCases { + fmt.Printf("Test case: %s\n", tc.name) + fmt.Printf("Input: %v\n", tc.input) + + result, filteredArgs := args.ParseArgs(tc.input, swflags) + + fmt.Printf("Help: %v\n", result.Help) + fmt.Printf("Verbose: %v\n", result.Verbose) + fmt.Printf("UseStdin: %v\n", result.UseStdin) + fmt.Printf("CfgFile: %s\n", result.CfgFile) + fmt.Printf("FilteredArgs: %v\n", filteredArgs) + fmt.Println() + } +} diff --git a/chore/_xtool/llcppsymg/_cmptest/args_test/llgo.expect b/chore/_xtool/llcppsymg/_cmptest/args_test/llgo.expect new file mode 100644 index 00000000..2f1e9416 --- /dev/null +++ b/chore/_xtool/llcppsymg/_cmptest/args_test/llgo.expect @@ -0,0 +1,54 @@ +#stdout +=== Test ParseArgs === +Test case: Basic flags +Input: [-h -v -] +Help: true +Verbose: true +UseStdin: true +CfgFile: llcppg.cfg +FilteredArgs: [] + +Test case: Config file +Input: [lua.llcppg.cfg] +Help: false +Verbose: false +UseStdin: false +CfgFile: lua.llcppg.cfg +FilteredArgs: [] + +Test case: Extract with multiple args +Input: [--extract file1.h file2.h -v] +Help: false +Verbose: true +UseStdin: false +CfgFile: llcppg.cfg +FilteredArgs: [--extract file1.h file2.h] + +Test case: Non-skippable flags +Input: [--extract file1.h file2.h -out=true -cpp=true -v] +Help: false +Verbose: true +UseStdin: false +CfgFile: llcppg.cfg +FilteredArgs: [--extract file1.h file2.h -out=true -cpp=true] + +Test case: Mixed flags +Input: [-v --extract file.h -out=true config.json] +Help: false +Verbose: true +UseStdin: false +CfgFile: config.json +FilteredArgs: [--extract file.h -out=true] + +Test case: Empty input +Input: [] +Help: false +Verbose: false +UseStdin: false +CfgFile: llcppg.cfg +FilteredArgs: [] + + +#stderr + +#exit 0 diff --git a/chore/_xtool/llcppsymg/args/args.go b/chore/_xtool/llcppsymg/args/args.go new file mode 100644 index 00000000..76d1eaa1 --- /dev/null +++ b/chore/_xtool/llcppsymg/args/args.go @@ -0,0 +1,51 @@ +package args + +import "strings" + +type Args struct { + Help bool + Verbose bool + UseStdin bool + CfgFile string +} + +func ParseArgs(args []string, swflags map[string]bool) (*Args, []string) { + result := &Args{} + filteredArgs := []string{} + for i := 0; i < len(args); i++ { + arg := args[i] + if strings.HasPrefix(arg, "-") { + switch arg { + case "-h", "--help": + result.Help = true + continue + case "-v": + result.Verbose = true + continue + case "-": + result.UseStdin = true + continue + default: + if hasArg, ok := swflags[arg]; ok { + if hasArg { + filteredArgs = append(filteredArgs, arg) + for i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") { + filteredArgs = append(filteredArgs, args[i+1]) + i++ + } + continue + } + } + filteredArgs = append(filteredArgs, arg) + } + } else if result.CfgFile == "" { + result.CfgFile = arg + } else { + filteredArgs = append(filteredArgs, arg) + } + } + if result.CfgFile == "" { + result.CfgFile = "llcppg.cfg" + } + return result, filteredArgs +} From ee335de22245b4e49954ef3f01892b6713b40ff7 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Sun, 29 Sep 2024 16:18:17 +0800 Subject: [PATCH 02/13] llcppsigfetch:use stdin --- chore/_xtool/llcppsigfetch/llcppsigfetch.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/llcppsigfetch.go b/chore/_xtool/llcppsigfetch/llcppsigfetch.go index dfbea922..42a2a41d 100644 --- a/chore/_xtool/llcppsigfetch/llcppsigfetch.go +++ b/chore/_xtool/llcppsigfetch/llcppsigfetch.go @@ -33,22 +33,26 @@ import ( func main() { cfgFile := "" + useStdin := false outputToFile := false for i := 1; i < len(os.Args); i++ { arg := os.Args[i] - if arg == "--extract" { + switch { + case arg == "--extract": runExtract() return - } else if arg == "--help" || arg == "-h" { + case arg == "--help" || arg == "-h": printUsage() return - } else if strings.HasPrefix(arg, "-out=") { + case strings.HasPrefix(arg, "-out="): outputToFile = parseBoolArg(arg, "out", false) - } else if cfgFile == "" && !strings.HasPrefix(arg, "-") { + case cfgFile == "" && !strings.HasPrefix(arg, "-"): cfgFile = arg + case arg == "-": + useStdin = true } } - runFromConfig(cfgFile, outputToFile) + runFromConfig(cfgFile, useStdin, outputToFile) } func printUsage() { @@ -79,14 +83,14 @@ func printUsage() { fmt.Println("Note: The two usage modes are mutually exclusive. Use either [] OR --extract, not both.") } -func runFromConfig(cfgFile string, outputToFile bool) { +func runFromConfig(cfgFile string, useStdin bool, outputToFile bool) { if cfgFile == "" { cfgFile = "llcppg.cfg" } var data []byte var err error - if cfgFile == "-" { + if useStdin { data, err = io.ReadAll(os.Stdin) } else { data, err = os.ReadFile(cfgFile) From 82275d49a6d89113b4cb25c7fa5c633bd98706dc Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Sun, 29 Sep 2024 16:22:12 +0800 Subject: [PATCH 03/13] llcppg:pipe writer close --- chore/llcppg/llcppg.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chore/llcppg/llcppg.go b/chore/llcppg/llcppg.go index e0e9745d..aba5b9d9 100644 --- a/chore/llcppg/llcppg.go +++ b/chore/llcppg/llcppg.go @@ -36,13 +36,14 @@ func llcppsymg(conf []byte) error { return cmd.Run() } -func llcppsigfetch(conf []byte, out io.Writer) { +func llcppsigfetch(conf []byte, out *io.PipeWriter) { cmd := exec.Command("llcppsigfetch", "-") cmd.Stdin = bytes.NewReader(conf) cmd.Stdout = out cmd.Stderr = os.Stderr err := cmd.Run() check(err) + out.Close() } func gogensig(in io.Reader) error { From a30bdcbb50d305f2da7e00e3d34b33350fb6de8f Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Wed, 9 Oct 2024 19:55:13 +0800 Subject: [PATCH 04/13] gogensig:unsigned & signed char --- .../cvt_test/decl_test/union_test/llgo.expect | 4 +- .../cvt_test/decl_test/union_test/union.go | 2 +- .../parse/cvt_test/type_test/llgo.expect | 37 +++++++++--------- .../parse/cvt_test/type_test/type.go | 38 ++++++++++++++++--- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/llgo.expect index 7be1d152..7263896d 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/llgo.expect @@ -180,8 +180,8 @@ TestUnionDecl Case 3: "_Type": "Field", "Type": { "_Type": "BuiltinType", - "Kind": 2, - "Flags": 1 + "Kind": 6, + "Flags": 0 }, "Doc": null, "Comment": null, diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/union.go b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/union.go index 5e8c18b5..c963feb8 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/union.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/union_test/union.go @@ -20,7 +20,7 @@ func TestUnionDecl() { int i; float f; union { - char c; + int c; short s; } inner; };`, diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/llgo.expect index d7e93459..cad17f83 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/llgo.expect @@ -1,4 +1,5 @@ #stdout +Char's flags is signed or unsigned Void:flags:0 kind:0 Bool:flags:0 kind:1 Char_S:flags:1 kind:2 @@ -26,16 +27,16 @@ Complex:flags:0 kind:11 Complex:flags:16 kind:11 Complex:flags:20 kind:11 Unknown:flags:0 kind:0 -Type: char *: +Type: int *: { "_Type": "PointerType", "X": { "_Type": "BuiltinType", - "Kind": 2, - "Flags": 1 + "Kind": 6, + "Flags": 0 } } -Type: char ***: +Type: int ***: { "_Type": "PointerType", "X": { @@ -44,29 +45,29 @@ Type: char ***: "_Type": "PointerType", "X": { "_Type": "BuiltinType", - "Kind": 2, - "Flags": 1 + "Kind": 6, + "Flags": 0 } } } } -Type: char[]: +Type: int[]: { "_Type": "ArrayType", "Elt": { "_Type": "BuiltinType", - "Kind": 2, - "Flags": 1 + "Kind": 6, + "Flags": 0 }, "Len": null } -Type: char[10]: +Type: int[10]: { "_Type": "ArrayType", "Elt": { "_Type": "BuiltinType", - "Kind": 2, - "Flags": 1 + "Kind": 6, + "Flags": 0 }, "Len": { "_Type": "BasicLit", @@ -74,15 +75,15 @@ Type: char[10]: "Value": "10" } } -Type: char[3][4]: +Type: int[3][4]: { "_Type": "ArrayType", "Elt": { "_Type": "ArrayType", "Elt": { "_Type": "BuiltinType", - "Kind": 2, - "Flags": 1 + "Kind": 6, + "Flags": 0 }, "Len": { "_Type": "BasicLit", @@ -303,7 +304,7 @@ Type: class a::b::c: }, "Tag": 3 } -Type: int (*)(int, char): +Type: int (*)(int, int): { "_Type": "PointerType", "X": { @@ -326,8 +327,8 @@ Type: int (*)(int, char): "_Type": "Field", "Type": { "_Type": "BuiltinType", - "Kind": 2, - "Flags": 1 + "Kind": 6, + "Flags": 0 }, "Doc": null, "Comment": null, diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/type.go b/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/type.go index 03a5771f..76fef62f 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/type.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/type_test/type.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "os" "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/cjson" @@ -12,6 +13,7 @@ import ( ) func main() { + TestChar() TestBuiltinType() TestNonBuiltinTypes() } @@ -64,14 +66,38 @@ func TestBuiltinType() { } } +// Char's Default Type in macos is signed char & in linux is unsigned char +// So we only confirm the char's kind is char & flags is unsigned or signed +func TestChar() { + typ, index, transunit := test.GetType(&test.GetTypeOptions{ + TypeCode: "char", + IsCpp: false, + }) + converter := &parse.Converter{} + expr := converter.ProcessType(typ) + if btType, ok := expr.(*ast.BuiltinType); ok { + if btType.Kind == ast.Char { + if btType.Flags == ast.Signed || btType.Flags == ast.Unsigned { + fmt.Println("Char's flags is signed or unsigned") + } else { + fmt.Fprintf(os.Stderr, "Char's flags is not signed or unsigned") + } + } + } else { + fmt.Fprintf(os.Stderr, "Char's expr is not a builtin type") + } + index.Dispose() + transunit.Dispose() +} + func TestNonBuiltinTypes() { tests := []string{ - "char*", - "char***", + "int*", + "int***", - "char[]", - "char[10]", - "char[3][4]", + "int[]", + "int[10]", + "int[3][4]", "int&", "int&&", @@ -122,7 +148,7 @@ func TestNonBuiltinTypes() { } class a::b::c`, - `int (*p)(int, char);`, + `int (*p)(int, int);`, } for _, t := range tests { From b6b889bff66e2ae759a935a7cda064c55c479765 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Thu, 10 Oct 2024 14:43:54 +0800 Subject: [PATCH 05/13] llcppsigfetch:remove leading underscores --- chore/_xtool/llcppsigfetch/parse/cvt.go | 4 +--- .../cvt_test/decl_test/class_test/llgo.expect | 24 +++++++++---------- .../decl_test/comment_test/llgo.expect | 20 ++++++++-------- .../cvt_test/decl_test/func_test/llgo.expect | 10 ++++---- .../cvt_test/decl_test/scope_test/llgo.expect | 10 ++++---- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 0cf35879..fbeba192 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -414,9 +414,7 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl { funcType.Params = params mangledNameStr := c.GoString(mangledName.CStr()) - if len(mangledNameStr) >= 1 && mangledNameStr[0] == '_' { - mangledNameStr = mangledNameStr[1:] - } + mangledNameStr = strings.TrimLeft(mangledNameStr, "_") funcDecl := &ast.FuncDecl{ DeclBase: ct.CreateDeclBase(cursor), diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect index c75368df..65f75cd7 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect @@ -128,7 +128,7 @@ TestClassDecl Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN1A3fooEid", + "MangledName": "ZN1A3fooEid", "Type": { "_Type": "FuncType", "Params": { @@ -225,7 +225,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "A" }, - "MangledName": "_ZN1AC1Ev", + "MangledName": "ZN1AC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -261,7 +261,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "A" }, - "MangledName": "_ZN1AC1Ev", + "MangledName": "ZN1AC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -297,7 +297,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "~A" }, - "MangledName": "_ZN1AD1Ev", + "MangledName": "ZN1AD1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -333,7 +333,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN1A3fooEv", + "MangledName": "ZN1A3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -400,7 +400,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "Base" }, - "MangledName": "_ZN4BaseC1Ev", + "MangledName": "ZN4BaseC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -436,7 +436,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "~Base" }, - "MangledName": "_ZN4BaseD1Ev", + "MangledName": "ZN4BaseD1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -472,7 +472,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN4Base3fooEv", + "MangledName": "ZN4Base3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -529,7 +529,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "Derived" }, - "MangledName": "_ZN7DerivedC1Ev", + "MangledName": "ZN7DerivedC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -565,7 +565,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "~Derived" }, - "MangledName": "_ZN7DerivedD1Ev", + "MangledName": "ZN7DerivedD1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -601,7 +601,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN7Derived3fooEv", + "MangledName": "ZN7Derived3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -680,7 +680,7 @@ TestClassDecl Case 5: "_Type": "Ident", "Name": "bar" }, - "MangledName": "_ZN1A3Foo3barEv", + "MangledName": "ZN1A3Foo3barEv", "Type": { "_Type": "FuncType", "Params": { diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect index 6c769412..13076294 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect @@ -15,7 +15,7 @@ TestDoc Case 1: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -58,7 +58,7 @@ TestDoc Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -107,7 +107,7 @@ TestDoc Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -156,7 +156,7 @@ TestDoc Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -205,7 +205,7 @@ TestDoc Case 5: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -257,7 +257,7 @@ TestDoc Case 6: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -309,7 +309,7 @@ TestDoc Case 7: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -361,7 +361,7 @@ TestDoc Case 8: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -419,7 +419,7 @@ TestDoc Case 9: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -707,7 +707,7 @@ TestDoc Case 11: "_Type": "Ident", "Name": "Foo" }, - "MangledName": "_ZN3Doc3FooEv", + "MangledName": "ZN3Doc3FooEv", "Type": { "_Type": "FuncType", "Params": { diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect index 383660fb..e573491a 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect @@ -15,7 +15,7 @@ TestFuncDecl Case 1: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -58,7 +58,7 @@ TestFuncDecl Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3fooi", + "MangledName": "Z3fooi", "Type": { "_Type": "FuncType", "Params": { @@ -116,7 +116,7 @@ TestFuncDecl Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3fooiz", + "MangledName": "Z3fooiz", "Type": { "_Type": "FuncType", "Params": { @@ -184,7 +184,7 @@ TestFuncDecl Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3fooid", + "MangledName": "Z3fooid", "Type": { "_Type": "FuncType", "Params": { @@ -260,7 +260,7 @@ TestFuncDecl Case 5: "_Type": "Ident", "Name": "add" }, - "MangledName": "_ZL3addii", + "MangledName": "ZL3addii", "Type": { "_Type": "FuncType", "Params": { diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect index 66093d7f..e903e0f8 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect @@ -15,7 +15,7 @@ TestScope Case 1: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_Z3foov", + "MangledName": "Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -61,7 +61,7 @@ TestScope Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN1a3fooEv", + "MangledName": "ZN1a3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -114,7 +114,7 @@ TestScope Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN1a1b3fooEv", + "MangledName": "ZN1a1b3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -179,7 +179,7 @@ TestScope Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN1a3fooEv", + "MangledName": "ZN1a3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -256,7 +256,7 @@ TestScope Case 5: "_Type": "Ident", "Name": "foo" }, - "MangledName": "_ZN1a1b3fooEv", + "MangledName": "ZN1a1b3fooEv", "Type": { "_Type": "FuncType", "Params": { From 8840968e0758f61debd6c765e3b5ae34ac392a6b Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 21 Oct 2024 17:43:01 +0800 Subject: [PATCH 06/13] llcppsigfetch:refine args parse --- chore/_xtool/llcppsigfetch/llcppsigfetch.go | 102 +++++++++----------- 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/llcppsigfetch.go b/chore/_xtool/llcppsigfetch/llcppsigfetch.go index 42a2a41d..0c35c638 100644 --- a/chore/_xtool/llcppsigfetch/llcppsigfetch.go +++ b/chore/_xtool/llcppsigfetch/llcppsigfetch.go @@ -27,32 +27,58 @@ import ( "github.com/goplus/llgo/c" "github.com/goplus/llgo/c/cjson" "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse" + "github.com/goplus/llgo/chore/_xtool/llcppsymg/args" "github.com/goplus/llgo/chore/_xtool/llcppsymg/clangutils" "github.com/goplus/llgo/chore/_xtool/llcppsymg/config" ) func main() { - cfgFile := "" - useStdin := false - outputToFile := false - for i := 1; i < len(os.Args); i++ { - arg := os.Args[i] + ags, remainArgs := args.ParseArgs(os.Args[1:], map[string]bool{ + "--extract": true, + }) + + if ags.Help { + printUsage() + return + } + extract := false + out := false + + var extractFile string + isTemp := false + isCpp := true + otherArgs := []string{} + + for i := 0; i < len(remainArgs); i++ { + arg := remainArgs[i] switch { case arg == "--extract": - runExtract() - return - case arg == "--help" || arg == "-h": - printUsage() - return + extract = true + if i+1 < len(remainArgs) && !strings.HasPrefix(remainArgs[i+1], "-") { + extractFile = remainArgs[i+1] + i++ + } else { + fmt.Println("Error: --extract requires a valid file argument") + printUsage() + os.Exit(1) + } case strings.HasPrefix(arg, "-out="): - outputToFile = parseBoolArg(arg, "out", false) - case cfgFile == "" && !strings.HasPrefix(arg, "-"): - cfgFile = arg - case arg == "-": - useStdin = true + out = parseBoolArg(arg, "out", false) + case strings.HasPrefix(arg, "-temp="): + isTemp = parseBoolArg(arg, "temp", false) + case strings.HasPrefix(arg, "-cpp="): + isCpp = parseBoolArg(arg, "cpp", true) + default: + otherArgs = append(otherArgs, arg) } } - runFromConfig(cfgFile, useStdin, outputToFile) + + if extract { + runExtract(extractFile, isTemp, isCpp, out, otherArgs) + } else { + runFromConfig(ags.CfgFile, ags.UseStdin, out) + } + } func printUsage() { @@ -84,10 +110,6 @@ func printUsage() { } func runFromConfig(cfgFile string, useStdin bool, outputToFile bool) { - if cfgFile == "" { - cfgFile = "llcppg.cfg" - } - var data []byte var err error if useStdin { @@ -114,48 +136,20 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool) { outputInfo(context, outputToFile) } -func runExtract() { - if len(os.Args) < 3 { - fmt.Println("Error: Insufficient arguments for --extract") - printUsage() - os.Exit(1) - } - +func runExtract(file string, isTemp bool, isCpp bool, outToFile bool, otherArgs []string) { cfg := &clangutils.Config{ - File: os.Args[2], - Args: []string{}, - IsCpp: true, - Temp: false, + File: file, + Args: otherArgs, + IsCpp: isCpp, + Temp: isTemp, } - - outputToFile := false - for i := 3; i < len(os.Args); i++ { - arg := os.Args[i] - switch { - case strings.HasPrefix(arg, "-temp="): - cfg.Temp = parseBoolArg(arg, "temp", false) - os.Args = append(os.Args[:i], os.Args[i+1:]...) - i-- - case strings.HasPrefix(arg, "-cpp="): - cfg.IsCpp = parseBoolArg(arg, "cpp", true) - os.Args = append(os.Args[:i], os.Args[i+1:]...) - i-- - case strings.HasPrefix(arg, "-out="): - outputToFile = parseBoolArg(arg, "out", false) - os.Args = append(os.Args[:i], os.Args[i+1:]...) - i-- - default: - cfg.Args = append(cfg.Args, arg) - } - } - converter, err := parse.NewConverter(cfg) check(err) _, err = converter.Convert() check(err) result := converter.MarshalOutputASTFiles() cstr := result.Print() - outputResult(cstr, outputToFile) + outputResult(cstr, outToFile) cjson.FreeCStr(cstr) result.Delete() converter.Dispose() From 72d176b77adc6b98a5f30f8f55ed382aa1c52f35 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Mon, 21 Oct 2024 20:51:08 +0800 Subject: [PATCH 07/13] llcppsigfetch:-v --- chore/_xtool/llcppsigfetch/llcppsigfetch.go | 93 +++++++++++++++--- chore/_xtool/llcppsigfetch/parse/cvt.go | 101 +++++++++++++++++++- chore/_xtool/llcppsigfetch/parse/parse.go | 28 ++++++ 3 files changed, 205 insertions(+), 17 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/llcppsigfetch.go b/chore/_xtool/llcppsigfetch/llcppsigfetch.go index 0c35c638..847d6e27 100644 --- a/chore/_xtool/llcppsigfetch/llcppsigfetch.go +++ b/chore/_xtool/llcppsigfetch/llcppsigfetch.go @@ -19,6 +19,7 @@ package main import ( "fmt" "io" + "log" "os" "path/filepath" "strconv" @@ -41,6 +42,10 @@ func main() { printUsage() return } + if ags.Verbose { + log.SetFlags(0) + parse.SetDebug(parse.DbgFlagAll) + } extract := false out := false @@ -74,9 +79,21 @@ func main() { } if extract { - runExtract(extractFile, isTemp, isCpp, out, otherArgs) + if ags.Verbose { + log.Println("runExtract: extractFile:", extractFile) + log.Println("isTemp:", isTemp) + log.Println("isCpp:", isCpp) + log.Println("out:", out) + log.Println("otherArgs:", otherArgs) + } + runExtract(extractFile, isTemp, isCpp, out, otherArgs, ags.Verbose) } else { - runFromConfig(ags.CfgFile, ags.UseStdin, out) + if ags.Verbose { + log.Println("runFromConfig: config file:", ags.CfgFile) + log.Println("use stdin:", ags.UseStdin) + log.Println("output to file:", out) + } + runFromConfig(ags.CfgFile, ags.UseStdin, out, ags.Verbose) } } @@ -109,7 +126,7 @@ func printUsage() { fmt.Println("Note: The two usage modes are mutually exclusive. Use either [] OR --extract, not both.") } -func runFromConfig(cfgFile string, useStdin bool, outputToFile bool) { +func runFromConfig(cfgFile string, useStdin bool, outputToFile bool, verbose bool) { var data []byte var err error if useStdin { @@ -117,6 +134,13 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool) { } else { data, err = os.ReadFile(cfgFile) } + if verbose { + if useStdin { + log.Println("runFromConfig: read from stdin") + } else { + log.Println("runFromConfig: read from file", cfgFile) + } + } check(err) conf, err := config.GetConf(data) @@ -124,10 +148,21 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool) { defer conf.Delete() if err != nil { - fmt.Fprintln(os.Stderr, "Failed to parse config file:", cfgFile) + log.Println("Failed to parse config file:", cfgFile) + os.Exit(1) } - files := getHeaderFiles(conf.CFlags, conf.Include) + //todo(zzy): reuse the llcppsymg's cflags parse + cflag := ParseCFlags(conf.CFlags) + files, notFounds, err := cflag.GenHeaderFilePaths(conf.Include) + check(err) + + if verbose { + log.Println("runFromConfig: header file paths", files) + if len(notFounds) > 0 { + log.Println("runFromConfig: not found header files", notFounds) + } + } context := parse.NewContext(conf.Cplusplus) err = context.ProcessFiles(files) @@ -136,7 +171,7 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool) { outputInfo(context, outputToFile) } -func runExtract(file string, isTemp bool, isCpp bool, outToFile bool, otherArgs []string) { +func runExtract(file string, isTemp bool, isCpp bool, outToFile bool, otherArgs []string, verbose bool) { cfg := &clangutils.Config{ File: file, Args: otherArgs, @@ -175,14 +210,46 @@ func outputResult(result *c.Char, outputToFile bool) { } } -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)) +// todo(zzy): reuse the llcppsymg's cflags parse https://github.com/goplus/llgo/pull/788 +type CFlags struct { + Paths []string // Include Path +} + +func ParseCFlags(cflags string) *CFlags { + parts := strings.Fields(cflags) + cf := &CFlags{} + for _, part := range parts { + if strings.HasPrefix(part, "-I") { + cf.Paths = append(cf.Paths, part[2:]) + } } - return paths + return cf +} + +func (cf *CFlags) GenHeaderFilePaths(files []string) ([]string, []string, error) { + var foundPaths []string + var notFound []string + + for _, file := range files { + var found bool + for _, path := range cf.Paths { + fullPath := filepath.Join(path, file) + if _, err := os.Stat(fullPath); err == nil { + foundPaths = append(foundPaths, fullPath) + found = true + break + } + } + if !found { + notFound = append(notFound, file) + } + } + + if len(foundPaths) == 0 { + return nil, notFound, fmt.Errorf("failed to find any header files") + } + + return foundPaths, notFound, nil } func outputInfo(context *parse.Context, outputToFile bool) { diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index fbeba192..836d4949 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -2,6 +2,7 @@ package parse import ( "fmt" + "log" "os" "strings" "unsafe" @@ -64,6 +65,13 @@ type Config struct { } func NewConverter(config *clangutils.Config) (*Converter, error) { + if debugParse { + log.Println("NewConverter: config") + log.Println("config.File", config.File) + log.Println("config.Args", config.Args) + log.Println("config.IsCpp", config.IsCpp) + log.Println("config.Temp", config.Temp) + } index, unit, err := clangutils.CreateTranslationUnit(config) if err != nil { return nil, err @@ -79,7 +87,13 @@ func NewConverter(config *clangutils.Config) (*Converter, error) { } func (ct *Converter) Dispose() { + if debugParse { + log.Println("Dispose: ct.index") + } ct.index.Dispose() + if debugParse { + log.Println("Dispose: ct.unit") + } ct.unit.Dispose() } @@ -123,14 +137,23 @@ func (ct *Converter) UpdateLoc(cursor clang.Cursor) { func (ct *Converter) GetCurFile() *ast.File { if ct.curLoc.File == "" { + if debugParse { + log.Println("GetCurFile: NO FILE") + } return nil } // todo(zzy): more efficient for i, entry := range ct.Files { if entry.Path == ct.curLoc.File { + if debugParse { + log.Println("GetCurFile: found", ct.curLoc.File) + } return ct.Files[i].Doc } } + if debugParse { + log.Println("GetCurFile: Create New ast.File", ct.curLoc.File) + } newDoc := &ast.File{} ct.Files = append(ct.Files, &FileEntry{Path: ct.curLoc.File, Doc: newDoc}) return newDoc @@ -219,6 +242,13 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul ct.UpdateLoc(cursor) curFile := ct.GetCurFile() + + if debugParse { + name := cursor.String() + defer name.Dispose() + log.Println("visitTop: Cursor:", c.GoString(name.CStr())) + } + if curFile == nil { return clang.ChildVisit_Continue } @@ -227,27 +257,69 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul case clang.CursorInclusionDirective: include := ct.ProcessInclude(cursor) curFile.Includes = append(curFile.Includes, include) + if debugParse { + log.Println("visitTop: ProcessInclude END ", include.Path) + } case clang.CursorMacroDefinition: macro := ct.ProcessMacro(cursor) curFile.Macros = append(curFile.Macros, macro) + if debugParse { + log.Println("visitTop: ProcessMacro END ", macro.Name, "Tokens Length:", len(macro.Tokens)) + } case clang.CursorEnumDecl: enum := ct.ProcessEnumDecl(cursor) curFile.Decls = append(curFile.Decls, enum) + if debugParse { + name := "anonymous" + if enum.Name != nil { + name = enum.Name.Name + } + log.Println("visitTop: ProcessEnumDecl END", name) + } case clang.CursorClassDecl: classDecl := ct.ProcessClassDecl(cursor) curFile.Decls = append(curFile.Decls, classDecl) + if debugParse { + name := "anonymous" + if classDecl.Name != nil { + name = classDecl.Name.Name + } + log.Println("visitTop: ProcessClassDecl END", name) + } case clang.CursorStructDecl: structDecl := ct.ProcessStructDecl(cursor) curFile.Decls = append(curFile.Decls, structDecl) + if debugParse { + name := "anonymous" + if structDecl.Name != nil { + name = structDecl.Name.Name + } + log.Println("visitTop: ProcessStructDecl END", name) + } case clang.CursorUnionDecl: unionDecl := ct.ProcessUnionDecl(cursor) curFile.Decls = append(curFile.Decls, unionDecl) + if debugParse { + name := "anonymous" + if unionDecl.Name != nil { + name = unionDecl.Name.Name + } + log.Println("visitTop: ProcessUnionDecl END", name) + } case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor: // Handle functions and class methods (including out-of-class method) // Example: void MyClass::myMethod() { ... } out-of-class method - curFile.Decls = append(curFile.Decls, ct.ProcessFuncDecl(cursor)) + funcDecl := ct.ProcessFuncDecl(cursor) + curFile.Decls = append(curFile.Decls, funcDecl) + if debugParse { + log.Println("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline) + } case clang.CursorTypedefDecl: - curFile.Decls = append(curFile.Decls, ct.ProcessTypeDefDecl(cursor)) + typedefDecl := ct.ProcessTypeDefDecl(cursor) + curFile.Decls = append(curFile.Decls, typedefDecl) + if debugParse { + log.Println("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name) + } case clang.CursorNamespace: VisitChildren(cursor, ct.visitTop) } @@ -352,12 +424,17 @@ func (ct *Converter) ProcessTypeDefDecl(cursor clang.Cursor) *ast.TypedefDecl { } ct.SetTypeDecl(cursor, decl) + return decl } func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr { underlyingTyp := cursor.TypedefDeclUnderlyingType() + if underlyingTyp.Kind != clang.TypeElaborated { + if debugParse { + log.Println("ProcessUnderlyingType: not elaborated") + } return ct.ProcessType(underlyingTyp) } @@ -370,6 +447,9 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr { // In this case, libclang incorrectly reports an anonymous struct as a named struct sourceCode := ct.GetTokens(referTypeCursor) if isAnonymousStructure(sourceCode) { + if debugParse { + log.Println("ProcessUnderlyingType: is anonymous structure") + } ct.SetAnonyType(referTypeCursor) typ, isValidType := ct.GetTypeDecl(referTypeCursor) if isValidType { @@ -377,9 +457,15 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr { // according to a normal anonymous decl switch declType := typ.(type) { case *ast.EnumTypeDecl: + if debugParse { + log.Println("ProcessUnderlyingType: is actually anonymous enum,remove name") + } declType.Name = nil case *ast.TypeDecl: if declType.Type.Tag != ast.Class { + if debugParse { + log.Println("ProcessUnderlyingType: is actually anonymous struct,remove name") + } declType.Name = nil } else { // Unreachable: There should be no anonymous classes in this context @@ -405,11 +491,17 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl { // function type will only collect return type // ProcessType can't get the field names,will collect in follows + if debugParse { + log.Println("ProcessFuncDecl: Get Base FuncType") + } funcType, ok := ct.ProcessType(cursor.Type()).(*ast.FuncType) if !ok { fmt.Println("failed to process function type") return nil } + if debugParse { + log.Println("ProcessFuncDecl: ProcessFieldList") + } params := ct.ProcessFieldList(cursor) funcType.Params = params @@ -428,6 +520,9 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl { } if isMethod(cursor) { + if debugParse { + log.Println("ProcessFuncDecl: is method, ProcessMethodAttributes") + } ct.ProcessMethodAttributes(cursor, funcDecl) } else { if cursor.StorageClass() == clang.SCStatic { @@ -436,7 +531,6 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl { } ct.SetTypeDecl(cursor, funcDecl) - return funcDecl } @@ -675,7 +769,6 @@ func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl { Type: typ, } ct.SetTypeDecl(cursor, decl) - return decl } diff --git a/chore/_xtool/llcppsigfetch/parse/parse.go b/chore/_xtool/llcppsigfetch/parse/parse.go index a267d4fc..f76480cd 100644 --- a/chore/_xtool/llcppsigfetch/parse/parse.go +++ b/chore/_xtool/llcppsigfetch/parse/parse.go @@ -2,11 +2,27 @@ package parse import ( "errors" + "log" "github.com/goplus/llgo/c/cjson" "github.com/goplus/llgo/chore/_xtool/llcppsymg/clangutils" ) +type dbgFlags = int + +const ( + DbgParse dbgFlags = 1 << iota + DbgFlagAll = DbgParse +) + +var ( + debugParse bool +) + +func SetDebug(dbgFlags dbgFlags) { + debugParse = (dbgFlags & DbgParse) != 0 +} + type Context struct { Files []*FileEntry IsCpp bool @@ -25,6 +41,9 @@ func (p *Context) Output() *cjson.JSON { // ProcessFiles processes the given files and adds them to the context func (p *Context) ProcessFiles(files []string) error { + if debugParse { + log.Println("ProcessFiles: files", files, "isCpp", p.IsCpp) + } for _, file := range files { if err := p.processFile(file); err != nil { return err @@ -35,8 +54,14 @@ func (p *Context) ProcessFiles(files []string) error { // parse file and add it to the context,avoid duplicate parsing func (p *Context) processFile(path string) error { + if debugParse { + log.Println("processFile: path", path) + } for _, entry := range p.Files { if entry.Path == path { + if debugParse { + log.Println("processFile: already parsed", path) + } return nil } } @@ -50,6 +75,9 @@ func (p *Context) processFile(path string) error { } func (p *Context) parseFile(path string) ([]*FileEntry, error) { + if debugParse { + log.Println("parseFile: path", path) + } converter, err := NewConverter(&clangutils.Config{ File: path, Temp: false, From 3877dcf83a3158dfc4d14936ba1b34a95596bff0 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 22 Oct 2024 15:21:49 +0800 Subject: [PATCH 08/13] llcppsigfetch:refine log out --- chore/_xtool/llcppsigfetch/parse/cvt.go | 359 ++++++++++++++---------- 1 file changed, 216 insertions(+), 143 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 836d4949..47592bae 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -48,6 +48,7 @@ type Converter struct { // Example: // typedef struct { int x; } MyStruct; anonyTypeMap map[string]bool // cursorUsr + indent int // for verbose debug } var tagMap = map[string]ast.Tag{ @@ -72,6 +73,7 @@ func NewConverter(config *clangutils.Config) (*Converter, error) { log.Println("config.IsCpp", config.IsCpp) log.Println("config.Temp", config.Temp) } + index, unit, err := clangutils.CreateTranslationUnit(config) if err != nil { return nil, err @@ -87,13 +89,8 @@ func NewConverter(config *clangutils.Config) (*Converter, error) { } func (ct *Converter) Dispose() { - if debugParse { - log.Println("Dispose: ct.index") - } + ct.logln("Dispose") ct.index.Dispose() - if debugParse { - log.Println("Dispose: ct.unit") - } ct.unit.Dispose() } @@ -118,74 +115,87 @@ func (ct *Converter) GetTokens(cursor clang.Cursor) []*ast.Token { return result } +func (ct *Converter) logBase() string { + return strings.Repeat(" ", ct.indent) +} +func (ct *Converter) incIndent() { + ct.indent++ +} + +func (ct *Converter) decIndent() { + if ct.indent > 0 { + ct.indent-- + } +} + +func (ct *Converter) logf(format string, args ...interface{}) { + if debugParse { + log.Printf(ct.logBase()+format, args...) + } +} +func (ct *Converter) logln(args ...interface{}) { + if debugParse { + if len(args) > 0 { + firstArg := fmt.Sprintf("%s%v", ct.logBase(), args[0]) + log.Println(append([]interface{}{firstArg}, args[1:]...)...) + } else { + log.Println(ct.logBase()) + } + } +} + func (ct *Converter) UpdateLoc(cursor clang.Cursor) { loc := cursor.Location() var file clang.File loc.SpellingLocation(&file, nil, nil, nil) - filename := file.FileName() - defer filename.Dispose() - if filename.CStr() == nil { + filePath := toStr(file.FileName()) + + if filePath == "" { //todo(zzy): For some built-in macros, there is no file. ct.curLoc = ast.Location{File: ""} return } - - filePath := c.GoString(filename.CStr()) ct.curLoc = ast.Location{File: filePath} } func (ct *Converter) GetCurFile() *ast.File { if ct.curLoc.File == "" { - if debugParse { - log.Println("GetCurFile: NO FILE") - } + ct.logln("GetCurFile: NO FILE") return nil } // todo(zzy): more efficient for i, entry := range ct.Files { if entry.Path == ct.curLoc.File { - if debugParse { - log.Println("GetCurFile: found", ct.curLoc.File) - } + ct.logln("GetCurFile: found", ct.curLoc.File) return ct.Files[i].Doc } } - if debugParse { - log.Println("GetCurFile: Create New ast.File", ct.curLoc.File) - } + ct.logln("GetCurFile: Create New ast.File", ct.curLoc.File) newDoc := &ast.File{} ct.Files = append(ct.Files, &FileEntry{Path: ct.curLoc.File, Doc: newDoc}) return newDoc } func (ct *Converter) SetAnonyType(cursor clang.Cursor) { - usr := cursor.USR() - usrStr := c.GoString(usr.CStr()) - defer usr.Dispose() - ct.anonyTypeMap[usrStr] = true + usr := toStr(cursor.USR()) + ct.anonyTypeMap[usr] = true } func (ct *Converter) GetAnonyType(cursor clang.Cursor) (bool, bool) { - usr := cursor.USR() - usrStr := c.GoString(usr.CStr()) - defer usr.Dispose() - isAnony, ok := ct.anonyTypeMap[usrStr] + usr := toStr(cursor.USR()) + isAnony, ok := ct.anonyTypeMap[usr] return isAnony, ok } func (ct *Converter) SetTypeDecl(cursor clang.Cursor, decl ast.Decl) { - usr := cursor.USR() - usrStr := c.GoString(usr.CStr()) - ct.typeDecls[usrStr] = decl - usr.Dispose() + usr := toStr(cursor.USR()) + ct.typeDecls[usr] = decl } func (ct *Converter) GetTypeDecl(cursor clang.Cursor) (ast.Decl, bool) { - usr := cursor.USR() - usrStr := c.GoString(usr.CStr()) - decl, ok := ct.typeDecls[usrStr] - usr.Dispose() + usr := toStr(cursor.USR()) + decl, ok := ct.typeDecls[usr] return decl, ok } @@ -213,14 +223,13 @@ func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase { // Note: In cases where both documentation comments and line comments conceptually exist, // only the line comment will be preserved. func (ct *Converter) ParseCommentGroup(cursor clang.Cursor) (comentGroup *ast.CommentGroup, isDoc bool) { - rawComment := cursor.RawCommentText() - defer rawComment.Dispose() + rawComment := toStr(cursor.RawCommentText()) commentGroup := &ast.CommentGroup{} - if rawComment.CStr() != nil { + if rawComment != "" { commentRange := cursor.CommentRange() cursorRange := cursor.Extent() isDoc := getOffset(commentRange.RangeStart()) < getOffset(cursorRange.RangeStart()) - commentGroup = ct.ParseComment(c.GoString(rawComment.CStr())) + commentGroup = ct.ParseComment(rawComment) if len(commentGroup.List) > 0 { return commentGroup, isDoc } @@ -239,15 +248,15 @@ func (ct *Converter) ParseComment(rawComment string) *ast.CommentGroup { // visit top decls (struct,class,function,enum & macro,include) func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResult { + ct.incIndent() + defer ct.decIndent() + ct.UpdateLoc(cursor) curFile := ct.GetCurFile() - if debugParse { - name := cursor.String() - defer name.Dispose() - log.Println("visitTop: Cursor:", c.GoString(name.CStr())) - } + name := toStr(cursor.String()) + ct.logf("visitTop: Cursor: %s\n", name) if curFile == nil { return clang.ChildVisit_Continue @@ -257,69 +266,57 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul case clang.CursorInclusionDirective: include := ct.ProcessInclude(cursor) curFile.Includes = append(curFile.Includes, include) - if debugParse { - log.Println("visitTop: ProcessInclude END ", include.Path) - } + ct.logln("visitTop: ProcessInclude END ", include.Path) case clang.CursorMacroDefinition: macro := ct.ProcessMacro(cursor) curFile.Macros = append(curFile.Macros, macro) - if debugParse { - log.Println("visitTop: ProcessMacro END ", macro.Name, "Tokens Length:", len(macro.Tokens)) - } + ct.logln("visitTop: ProcessMacro END ", macro.Name, "Tokens Length:", len(macro.Tokens)) case clang.CursorEnumDecl: enum := ct.ProcessEnumDecl(cursor) curFile.Decls = append(curFile.Decls, enum) - if debugParse { - name := "anonymous" - if enum.Name != nil { - name = enum.Name.Name - } - log.Println("visitTop: ProcessEnumDecl END", name) + + ct.logf("visitTop: ProcessEnumDecl END") + if enum.Name != nil { + ct.logln(enum.Name.Name) + } else { + ct.logln("ANONY") } + case clang.CursorClassDecl: classDecl := ct.ProcessClassDecl(cursor) curFile.Decls = append(curFile.Decls, classDecl) - if debugParse { - name := "anonymous" - if classDecl.Name != nil { - name = classDecl.Name.Name - } - log.Println("visitTop: ProcessClassDecl END", name) - } + // class havent anonymous situation + ct.logln("visitTop: ProcessClassDecl END", classDecl.Name.Name) case clang.CursorStructDecl: structDecl := ct.ProcessStructDecl(cursor) curFile.Decls = append(curFile.Decls, structDecl) - if debugParse { - name := "anonymous" - if structDecl.Name != nil { - name = structDecl.Name.Name - } - log.Println("visitTop: ProcessStructDecl END", name) + + ct.logf("visitTop: ProcessStructDecl END") + if structDecl.Name != nil { + ct.logln(structDecl.Name.Name) + } else { + ct.logln("ANONY") } case clang.CursorUnionDecl: unionDecl := ct.ProcessUnionDecl(cursor) curFile.Decls = append(curFile.Decls, unionDecl) - if debugParse { - name := "anonymous" - if unionDecl.Name != nil { - name = unionDecl.Name.Name - } - log.Println("visitTop: ProcessUnionDecl END", name) + + ct.logf("visitTop: ProcessUnionDecl END") + if unionDecl.Name != nil { + ct.logln(unionDecl.Name.Name) + } else { + ct.logln("ANONY") } case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor: // Handle functions and class methods (including out-of-class method) // Example: void MyClass::myMethod() { ... } out-of-class method funcDecl := ct.ProcessFuncDecl(cursor) curFile.Decls = append(curFile.Decls, funcDecl) - if debugParse { - log.Println("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline) - } + ct.logln("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline) case clang.CursorTypedefDecl: typedefDecl := ct.ProcessTypeDefDecl(cursor) curFile.Decls = append(curFile.Decls, typedefDecl) - if debugParse { - log.Println("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name) - } + ct.logln("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name) case clang.CursorNamespace: VisitChildren(cursor, ct.visitTop) } @@ -343,6 +340,12 @@ func VisitChildren(cursor clang.Cursor, fn Visitor) c.Uint { } func (ct *Converter) ProcessType(t clang.Type) ast.Expr { + ct.incIndent() + defer ct.decIndent() + + typeName, typeKind := getTypeDesc(t) + ct.logln("ProcessType: TypeName:", typeName, "TypeKind:", typeKind) + if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin { return ct.ProcessBuiltinType(t) } @@ -354,14 +357,22 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr { var expr ast.Expr switch t.Kind { case clang.TypePointer: + name, kind := getTypeDesc(t.PointeeType()) + ct.logln("ProcessType: PointerType Pointee TypeName:", name, "TypeKind:", kind) expr = &ast.PointerType{X: ct.ProcessType(t.PointeeType())} case clang.TypeLValueReference: + name, kind := getTypeDesc(t.NonReferenceType()) + ct.logln("ProcessType: LvalueRefType NonReference TypeName:", name, "TypeKind:", kind) expr = &ast.LvalueRefType{X: ct.ProcessType(t.NonReferenceType())} case clang.TypeRValueReference: + name, kind := getTypeDesc(t.NonReferenceType()) + ct.logln("ProcessType: RvalueRefType NonReference TypeName:", name, "TypeKind:", kind) expr = &ast.RvalueRefType{X: ct.ProcessType(t.NonReferenceType())} case clang.TypeFunctionProto, clang.TypeFunctionNoProto: // treating TypeFunctionNoProto as a general function without parameters // function type will only collect return type, params will be collected in ProcessFuncDecl + name, kind := getTypeDesc(t) + ct.logln("ProcessType: FunctionType TypeName:", name, "TypeKind:", kind) expr = ct.ProcessFunctionType(t) case clang.TypeConstantArray, clang.TypeIncompleteArray, clang.TypeVariableArray, clang.TypeDependentSizedArray: if t.Kind == clang.TypeConstantArray { @@ -378,6 +389,9 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr { Elt: ct.ProcessType(t.ArrayElementType()), } } + default: + name, kind := getTypeDesc(t) + ct.logln("ProcessType: Unknown Type TypeName:", name, "TypeKind:", kind) } return expr } @@ -386,11 +400,19 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr { // This is because we cannot reverse-lookup the corresponding declaration node from a function type. // Note: For function declarations, parameter names are collected in the ProcessFuncDecl method. func (ct *Converter) ProcessFunctionType(t clang.Type) *ast.FuncType { + ct.incIndent() + defer ct.decIndent() + typeName, typeKind := getTypeDesc(t) + ct.logln("ProcessFunctionType: TypeName:", typeName, "TypeKind:", typeKind) // Note: Attempting to get the type declaration for a function type will result in CursorNoDeclFound // cursor := t.TypeDeclaration() // This would return CursorNoDeclFound + resType := t.ResultType() - ret := ct.ProcessType(t.ResultType()) + name, kind := getTypeDesc(resType) + ct.logln("ProcessFunctionType: ResultType TypeName:", name, "TypeKind:", kind) + + ret := ct.ProcessType(resType) params := &ast.FieldList{} numArgs := t.NumArgTypes() for i := 0; i < int(numArgs); i++ { @@ -412,14 +434,16 @@ func (ct *Converter) ProcessFunctionType(t clang.Type) *ast.FuncType { } func (ct *Converter) ProcessTypeDefDecl(cursor clang.Cursor) *ast.TypedefDecl { - name := cursor.String() - defer name.Dispose() + ct.incIndent() + defer ct.decIndent() + name, kind := getCursorDesc(cursor) + ct.logln("ProcessTypeDefDecl: CursorName:", name, "CursorKind:", kind) typ := ct.ProcessUnderlyingType(cursor) decl := &ast.TypedefDecl{ DeclBase: ct.CreateDeclBase(cursor), - Name: &ast.Ident{Name: c.GoString(name.CStr())}, + Name: &ast.Ident{Name: name}, Type: typ, } @@ -432,9 +456,7 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr { underlyingTyp := cursor.TypedefDeclUnderlyingType() if underlyingTyp.Kind != clang.TypeElaborated { - if debugParse { - log.Println("ProcessUnderlyingType: not elaborated") - } + ct.logln("ProcessUnderlyingType: not elaborated") return ct.ProcessType(underlyingTyp) } @@ -447,9 +469,7 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr { // In this case, libclang incorrectly reports an anonymous struct as a named struct sourceCode := ct.GetTokens(referTypeCursor) if isAnonymousStructure(sourceCode) { - if debugParse { - log.Println("ProcessUnderlyingType: is anonymous structure") - } + ct.logln("ProcessUnderlyingType: is anonymous structure") ct.SetAnonyType(referTypeCursor) typ, isValidType := ct.GetTypeDecl(referTypeCursor) if isValidType { @@ -457,15 +477,11 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr { // according to a normal anonymous decl switch declType := typ.(type) { case *ast.EnumTypeDecl: - if debugParse { - log.Println("ProcessUnderlyingType: is actually anonymous enum,remove name") - } + ct.logln("ProcessUnderlyingType: is actually anonymous enum,remove name") declType.Name = nil case *ast.TypeDecl: if declType.Type.Tag != ast.Class { - if debugParse { - log.Println("ProcessUnderlyingType: is actually anonymous struct,remove name") - } + ct.logln("ProcessUnderlyingType: is actually anonymous struct,remove name") declType.Name = nil } else { // Unreachable: There should be no anonymous classes in this context @@ -484,35 +500,30 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr { // converts functions, methods, constructors, destructors (including out-of-class decl) to ast.FuncDecl nodes. func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl { - name := cursor.String() - mangledName := cursor.Mangling() - defer name.Dispose() - defer mangledName.Dispose() + ct.incIndent() + defer ct.decIndent() + name, kind := getCursorDesc(cursor) + mangledName := toStr(cursor.Mangling()) + ct.logln("ProcessFuncDecl: CursorName:", name, "CursorKind:", kind) // function type will only collect return type // ProcessType can't get the field names,will collect in follows - if debugParse { - log.Println("ProcessFuncDecl: Get Base FuncType") - } funcType, ok := ct.ProcessType(cursor.Type()).(*ast.FuncType) if !ok { - fmt.Println("failed to process function type") + ct.logln("ProcessFuncDecl: failed to process function type") return nil } - if debugParse { - log.Println("ProcessFuncDecl: ProcessFieldList") - } + ct.logln("ProcessFuncDecl: ProcessFieldList") params := ct.ProcessFieldList(cursor) funcType.Params = params - mangledNameStr := c.GoString(mangledName.CStr()) - mangledNameStr = strings.TrimLeft(mangledNameStr, "_") + mangledName = strings.TrimLeft(mangledName, "_") funcDecl := &ast.FuncDecl{ DeclBase: ct.CreateDeclBase(cursor), - Name: &ast.Ident{Name: c.GoString(name.CStr())}, + Name: &ast.Ident{Name: name}, Type: funcType, - MangledName: mangledNameStr, + MangledName: mangledName, } if cursor.IsFunctionInlined() != 0 { @@ -520,9 +531,7 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl { } if isMethod(cursor) { - if debugParse { - log.Println("ProcessFuncDecl: is method, ProcessMethodAttributes") - } + ct.logln("ProcessFuncDecl: is method, ProcessMethodAttributes") ct.ProcessMethodAttributes(cursor, funcDecl) } else { if cursor.StorageClass() == clang.SCStatic { @@ -599,12 +608,11 @@ func (ct *Converter) ProcessEnumType(cursor clang.Cursor) *ast.EnumType { } func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl { - name := cursor.String() - defer name.Dispose() + name := toStr(cursor.String()) decl := &ast.EnumTypeDecl{ DeclBase: ct.CreateDeclBase(cursor), - Name: &ast.Ident{Name: c.GoString(name.CStr())}, + Name: &ast.Ident{Name: name}, Type: ct.ProcessEnumType(cursor), } ct.SetTypeDecl(cursor, decl) @@ -613,20 +621,18 @@ func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl { // current only collect macro which defined in file func (ct *Converter) ProcessMacro(cursor clang.Cursor) *ast.Macro { - name := cursor.String() - defer name.Dispose() + name := toStr(cursor.String()) macro := &ast.Macro{ - Name: c.GoString(name.CStr()), + Name: name, Tokens: ct.GetTokens(cursor), } return macro } func (ct *Converter) ProcessInclude(cursor clang.Cursor) *ast.Include { - name := cursor.String() - defer name.Dispose() - return &ast.Include{Path: c.GoString(name.CStr())} + name := toStr(cursor.String()) + return &ast.Include{Path: name} } // todo(zzy): after https://github.com/goplus/llgo/issues/804 has be resolved @@ -637,11 +643,19 @@ type visitFieldContext struct { } func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field { + p.converter.incIndent() + defer p.converter.decIndent() + + fieldName := toStr(cursor.String()) + + typ := cursor.Type() + typeName, typeKind := getTypeDesc(typ) + + p.converter.logf("createBaseField: ProcessType %s TypeKind: %s", typeName, typeKind) + field := &ast.Field{ - Type: p.converter.ProcessType(cursor.Type()), + Type: p.converter.ProcessType(typ), } - fieldName := cursor.String() - defer fieldName.Dispose() commentGroup, isDoc := p.converter.ParseCommentGroup(cursor) if commentGroup != nil { @@ -651,8 +665,8 @@ func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field { field.Comment = commentGroup } } - if name := fieldName.CStr(); name != nil { - field.Names = []*ast.Ident{{Name: c.GoString(name)}} + if fieldName != "" { + field.Names = []*ast.Ident{{Name: fieldName}} } return field } @@ -668,6 +682,12 @@ func visitFieldList(cursor, parent clang.Cursor, clientData unsafe.Pointer) clan // struct A { // int a, b; // }; + if cursor.Kind == clang.CursorFieldDecl { + ctx.converter.logln("visitFieldList: CursorFieldDecl") + } else { + ctx.converter.logln("visitFieldList: CursorParmDecl") + } + field := ctx.createBaseField(cursor) if cursor.Kind == clang.CursorFieldDecl { field.Access = ast.AccessSpecifier(cursor.CXXAccessSpecifier()) @@ -690,11 +710,15 @@ func visitFieldList(cursor, parent clang.Cursor, clientData unsafe.Pointer) clan // For Record Type(struct,union ...) & Func 's FieldList func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList { + ct.incIndent() + defer ct.decIndent() + params := &ast.FieldList{} ctx := &visitFieldContext{ params: params, converter: ct, } + ct.logln("ProcessFieldList: VisitChildren") clang.VisitChildren(cursor, visitFieldList, c.Pointer(ctx)) if (cursor.Kind == clang.CursorFunctionDecl || isMethod(cursor)) && cursor.IsVariadic() != 0 { params.List = append(params.List, &ast.Field{ @@ -732,12 +756,18 @@ func (ct *Converter) ProcessMethods(cursor clang.Cursor) []*ast.FuncDecl { } func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl { + ct.incIndent() + defer ct.decIndent() + cursorName, cursorKind := getCursorDesc(cursor) + ct.logln("ProcessRecordDecl: CursorName:", cursorName, "CursorKind:", cursorKind) + anony := cursor.IsAnonymousRecordDecl() var name *ast.Ident if anony == 0 { - cursorName := cursor.String() - defer cursorName.Dispose() - name = &ast.Ident{Name: c.GoString(cursorName.CStr())} + name = &ast.Ident{Name: cursorName} + ct.logln("ProcessRecordDecl: has name", cursorName) + } else { + ct.logln("ProcessRecordDecl: is anonymous") } decl := &ast.TypeDecl{ @@ -759,6 +789,9 @@ func (ct *Converter) ProcessUnionDecl(cursor clang.Cursor) *ast.TypeDecl { } func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl { + cursorName, cursorKind := getCursorDesc(cursor) + ct.logln("ProcessClassDecl: CursorName:", cursorName, "CursorKind:", cursorKind) + // Pushing class scope before processing its type and popping after base := ct.CreateDeclBase(cursor) typ := ct.ProcessRecordType(cursor) @@ -768,15 +801,31 @@ func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl { Name: &ast.Ident{Name: c.GoString(cursor.String().CStr())}, Type: typ, } + ct.SetTypeDecl(cursor, decl) return decl } func (ct *Converter) ProcessRecordType(cursor clang.Cursor) *ast.RecordType { + ct.incIndent() + defer ct.decIndent() + + cursorName, cursorKind := getCursorDesc(cursor) + ct.logln("ProcessRecordType: CursorName:", cursorName, "CursorKind:", cursorKind) + + tag := toTag(cursor.Kind) + ct.logln("ProcessRecordType: toTag", tag) + + ct.logln("ProcessRecordType: ProcessFieldList") + fields := ct.ProcessFieldList(cursor) + + ct.logln("ProcessRecordType: ProcessMethods") + methods := ct.ProcessMethods(cursor) + return &ast.RecordType{ - Tag: toTag(cursor.Kind), - Fields: ct.ProcessFieldList(cursor), - Methods: ct.ProcessMethods(cursor), + Tag: tag, + Fields: fields, + Methods: methods, } } @@ -790,8 +839,10 @@ func (ct *Converter) ProcessRecordType(cursor clang.Cursor) *ast.RecordType { // - Examples: struct { int x; int y; }, union { int a; float b; } // - Handling: Retrieve their corresponding concrete types func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr { - name := t.String() - defer name.Dispose() + ct.incIndent() + defer ct.decIndent() + typeName, typeKind := getTypeDesc(t) + ct.logln("ProcessElaboratedType: TypeName:", typeName, "TypeKind:", typeKind) decl := t.TypeDeclaration() isAnony, ok := ct.GetAnonyType(decl) @@ -804,8 +855,6 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr { return ct.ProcessRecordType(decl) } - typeName := c.GoString(name.CStr()) - // for elaborated type, it could have a tag description // like struct A, union B, class C, enum D parts := strings.SplitN(typeName, " ", 2) @@ -822,6 +871,11 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr { } func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType { + ct.incIndent() + defer ct.decIndent() + typeName, typeKind := getTypeDesc(t) + ct.logln("ProcessBuiltinType: TypeName:", typeName, "TypeKind:", typeKind) + kind := ast.Void var flags ast.TypeFlag @@ -874,9 +928,8 @@ func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType { // float complfex flag is not set default: // like IBM128,NullPtr,Accum - kindStr := t.Kind.String() - defer kindStr.Dispose() - fmt.Fprintln(os.Stderr, "todo: unknown builtin type:", c.GoString(kindStr.CStr())) + kindStr := toStr(t.Kind.String()) + fmt.Fprintln(os.Stderr, "todo: unknown builtin type:", kindStr) } if IsExplicitSigned(t) { @@ -983,3 +1036,23 @@ func isAnonymousStructure(sourceCode []*ast.Token) bool { sourceCode[1].Token == token.PUNCT && sourceCode[1].Lit == "{" } + +func toStr(clangStr clang.String) (str string) { + defer clangStr.Dispose() + if clangStr.CStr() != nil { + str = c.GoString(clangStr.CStr()) + } + return +} + +func getTypeDesc(t clang.Type) (name string, kind string) { + name = toStr(t.String()) + kind = toStr(t.Kind.String()) + return +} + +func getCursorDesc(cursor clang.Cursor) (name string, kind string) { + name = toStr(cursor.String()) + kind = toStr(cursor.Kind.String()) + return +} From a608c51e36676ce2b92110a774c935cef2756cab Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 22 Oct 2024 17:28:53 +0800 Subject: [PATCH 09/13] llcppsigfetch:fix fopen's return type nil --- chore/_xtool/llcppsigfetch/parse/cvt.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 47592bae..54a577e2 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -354,6 +354,10 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr { return ct.ProcessElaboratedType(t) } + if t.Kind == clang.TypeTypedef { + return ct.ProcessTypeDefType(t) + } + var expr ast.Expr switch t.Kind { case clang.TypePointer: @@ -437,7 +441,7 @@ func (ct *Converter) ProcessTypeDefDecl(cursor clang.Cursor) *ast.TypedefDecl { ct.incIndent() defer ct.decIndent() name, kind := getCursorDesc(cursor) - ct.logln("ProcessTypeDefDecl: CursorName:", name, "CursorKind:", kind) + ct.logln("ProcessTypeDefDecl: CursorName:", name, "CursorKind:", kind, "CursorTypeKind:", toStr(cursor.Type().Kind.String())) typ := ct.ProcessUnderlyingType(cursor) @@ -870,6 +874,16 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr { return ct.BuildScopingExpr(decl) } +func (ct *Converter) ProcessTypeDefType(t clang.Type) ast.Expr { + cursor := t.TypeDeclaration() + ct.logln("ProcessTypeDefType: Typedef TypeDeclaration", toStr(cursor.String()), toStr(t.String())) + if name := toStr(cursor.String()); name != "" { + return &ast.Ident{Name: name} + } + ct.logln("ProcessTypeDefType: typedef type have no name") + return nil +} + func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType { ct.incIndent() defer ct.decIndent() From 91ebf88c977c16713a611aea37d7daf28f55ae98 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Wed, 23 Oct 2024 15:13:14 +0800 Subject: [PATCH 10/13] llcppsigfetch:use fmt to log because linux nil defer of log --- chore/_xtool/llcppsigfetch/llcppsigfetch.go | 36 ++++++++++----------- chore/_xtool/llcppsigfetch/parse/cvt.go | 17 +++++----- chore/_xtool/llcppsigfetch/parse/parse.go | 11 ++++--- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/llcppsigfetch.go b/chore/_xtool/llcppsigfetch/llcppsigfetch.go index 847d6e27..e04de549 100644 --- a/chore/_xtool/llcppsigfetch/llcppsigfetch.go +++ b/chore/_xtool/llcppsigfetch/llcppsigfetch.go @@ -19,7 +19,6 @@ package main import ( "fmt" "io" - "log" "os" "path/filepath" "strconv" @@ -43,7 +42,6 @@ func main() { return } if ags.Verbose { - log.SetFlags(0) parse.SetDebug(parse.DbgFlagAll) } extract := false @@ -63,7 +61,7 @@ func main() { extractFile = remainArgs[i+1] i++ } else { - fmt.Println("Error: --extract requires a valid file argument") + fmt.Fprintln(os.Stderr, "Error: --extract requires a valid file argument") printUsage() os.Exit(1) } @@ -80,18 +78,18 @@ func main() { if extract { if ags.Verbose { - log.Println("runExtract: extractFile:", extractFile) - log.Println("isTemp:", isTemp) - log.Println("isCpp:", isCpp) - log.Println("out:", out) - log.Println("otherArgs:", otherArgs) + fmt.Fprintln(os.Stderr, "runExtract: extractFile:", extractFile) + fmt.Fprintln(os.Stderr, "isTemp:", isTemp) + fmt.Fprintln(os.Stderr, "isCpp:", isCpp) + fmt.Fprintln(os.Stderr, "out:", out) + fmt.Fprintln(os.Stderr, "otherArgs:", otherArgs) } runExtract(extractFile, isTemp, isCpp, out, otherArgs, ags.Verbose) } else { if ags.Verbose { - log.Println("runFromConfig: config file:", ags.CfgFile) - log.Println("use stdin:", ags.UseStdin) - log.Println("output to file:", out) + fmt.Fprintln(os.Stderr, "runFromConfig: config file:", ags.CfgFile) + fmt.Fprintln(os.Stderr, "use stdin:", ags.UseStdin) + fmt.Fprintln(os.Stderr, "output to file:", out) } runFromConfig(ags.CfgFile, ags.UseStdin, out, ags.Verbose) } @@ -136,9 +134,9 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool, verbose boo } if verbose { if useStdin { - log.Println("runFromConfig: read from stdin") + fmt.Fprintln(os.Stderr, "runFromConfig: read from stdin") } else { - log.Println("runFromConfig: read from file", cfgFile) + fmt.Fprintln(os.Stderr, "runFromConfig: read from file", cfgFile) } } check(err) @@ -148,7 +146,7 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool, verbose boo defer conf.Delete() if err != nil { - log.Println("Failed to parse config file:", cfgFile) + fmt.Fprintln(os.Stderr, "Failed to parse config file:", cfgFile) os.Exit(1) } @@ -158,9 +156,9 @@ func runFromConfig(cfgFile string, useStdin bool, outputToFile bool, verbose boo check(err) if verbose { - log.Println("runFromConfig: header file paths", files) + fmt.Fprintln(os.Stderr, "runFromConfig: header file paths", files) if len(notFounds) > 0 { - log.Println("runFromConfig: not found header files", notFounds) + fmt.Fprintln(os.Stderr, "runFromConfig: not found header files", notFounds) } } @@ -204,7 +202,7 @@ func outputResult(result *c.Char, outputToFile bool) { fmt.Fprintf(os.Stderr, "Error writing to output file: %v\n", err) os.Exit(1) } - fmt.Printf("Results saved to %s\n", outputFile) + fmt.Fprintf(os.Stderr, "Results saved to %s\n", outputFile) } else { c.Printf(result) } @@ -263,12 +261,12 @@ func outputInfo(context *parse.Context, outputToFile bool) { func parseBoolArg(arg, name string, defaultValue bool) bool { parts := strings.SplitN(arg, "=", 2) if len(parts) != 2 { - fmt.Printf("Warning: Invalid -%s= argument, defaulting to %v\n", name, defaultValue) + fmt.Fprintf(os.Stderr, "Warning: Invalid -%s= argument, defaulting to %v\n", name, defaultValue) return defaultValue } value, err := strconv.ParseBool(parts[1]) if err != nil { - fmt.Printf("Warning: Invalid -%s= value '%s', defaulting to %v\n", name, parts[1], defaultValue) + fmt.Fprintf(os.Stderr, "Warning: Invalid -%s= value '%s', defaulting to %v\n", name, parts[1], defaultValue) return defaultValue } return value diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 54a577e2..a982fe83 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -2,7 +2,6 @@ package parse import ( "fmt" - "log" "os" "strings" "unsafe" @@ -67,11 +66,11 @@ type Config struct { func NewConverter(config *clangutils.Config) (*Converter, error) { if debugParse { - log.Println("NewConverter: config") - log.Println("config.File", config.File) - log.Println("config.Args", config.Args) - log.Println("config.IsCpp", config.IsCpp) - log.Println("config.Temp", config.Temp) + fmt.Fprintln(os.Stderr, "NewConverter: config") + fmt.Fprintln(os.Stderr, "config.File", config.File) + fmt.Fprintln(os.Stderr, "config.Args", config.Args) + fmt.Fprintln(os.Stderr, "config.IsCpp", config.IsCpp) + fmt.Fprintln(os.Stderr, "config.Temp", config.Temp) } index, unit, err := clangutils.CreateTranslationUnit(config) @@ -130,16 +129,16 @@ func (ct *Converter) decIndent() { func (ct *Converter) logf(format string, args ...interface{}) { if debugParse { - log.Printf(ct.logBase()+format, args...) + fmt.Fprintf(os.Stderr, ct.logBase()+format, args...) } } func (ct *Converter) logln(args ...interface{}) { if debugParse { if len(args) > 0 { firstArg := fmt.Sprintf("%s%v", ct.logBase(), args[0]) - log.Println(append([]interface{}{firstArg}, args[1:]...)...) + fmt.Fprintln(os.Stderr, append([]interface{}{firstArg}, args[1:]...)...) } else { - log.Println(ct.logBase()) + fmt.Fprintln(os.Stderr, ct.logBase()) } } } diff --git a/chore/_xtool/llcppsigfetch/parse/parse.go b/chore/_xtool/llcppsigfetch/parse/parse.go index f76480cd..ab4755f0 100644 --- a/chore/_xtool/llcppsigfetch/parse/parse.go +++ b/chore/_xtool/llcppsigfetch/parse/parse.go @@ -2,7 +2,8 @@ package parse import ( "errors" - "log" + "fmt" + "os" "github.com/goplus/llgo/c/cjson" "github.com/goplus/llgo/chore/_xtool/llcppsymg/clangutils" @@ -42,7 +43,7 @@ func (p *Context) Output() *cjson.JSON { // ProcessFiles processes the given files and adds them to the context func (p *Context) ProcessFiles(files []string) error { if debugParse { - log.Println("ProcessFiles: files", files, "isCpp", p.IsCpp) + fmt.Fprintln(os.Stderr, "ProcessFiles: files", files, "isCpp", p.IsCpp) } for _, file := range files { if err := p.processFile(file); err != nil { @@ -55,12 +56,12 @@ func (p *Context) ProcessFiles(files []string) error { // parse file and add it to the context,avoid duplicate parsing func (p *Context) processFile(path string) error { if debugParse { - log.Println("processFile: path", path) + fmt.Fprintln(os.Stderr, "processFile: path", path) } for _, entry := range p.Files { if entry.Path == path { if debugParse { - log.Println("processFile: already parsed", path) + fmt.Fprintln(os.Stderr, "processFile: already parsed", path) } return nil } @@ -76,7 +77,7 @@ func (p *Context) processFile(path string) error { func (p *Context) parseFile(path string) ([]*FileEntry, error) { if debugParse { - log.Println("parseFile: path", path) + fmt.Fprintln(os.Stderr, "parseFile: path", path) } converter, err := NewConverter(&clangutils.Config{ File: path, From 4f5ebb279d66cd7109cc4e853c1a1fceba7e4ec3 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Wed, 23 Oct 2024 16:02:39 +0800 Subject: [PATCH 11/13] llcppsigfetch:refine field collection --- chore/_xtool/llcppsigfetch/parse/cvt.go | 126 ++++++++++-------------- 1 file changed, 50 insertions(+), 76 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index a982fe83..8ad9b658 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -638,29 +638,22 @@ func (ct *Converter) ProcessInclude(cursor clang.Cursor) *ast.Include { return &ast.Include{Path: name} } -// todo(zzy): after https://github.com/goplus/llgo/issues/804 has be resolved -// Change the following code to use the closure -type visitFieldContext struct { - params *ast.FieldList - converter *Converter -} - -func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field { - p.converter.incIndent() - defer p.converter.decIndent() +func (ct *Converter) createBaseField(cursor clang.Cursor) *ast.Field { + ct.incIndent() + defer ct.decIndent() fieldName := toStr(cursor.String()) typ := cursor.Type() typeName, typeKind := getTypeDesc(typ) - p.converter.logf("createBaseField: ProcessType %s TypeKind: %s", typeName, typeKind) + ct.logf("createBaseField: ProcessType %s TypeKind: %s", typeName, typeKind) field := &ast.Field{ - Type: p.converter.ProcessType(typ), + Type: ct.ProcessType(typ), } - commentGroup, isDoc := p.converter.ParseCommentGroup(cursor) + commentGroup, isDoc := ct.ParseCommentGroup(cursor) if commentGroup != nil { if isDoc { field.Doc = commentGroup @@ -673,43 +666,6 @@ func (p *visitFieldContext) createBaseField(cursor clang.Cursor) *ast.Field { } return field } -func visitFieldList(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult { - ctx := (*visitFieldContext)(clientData) - - switch cursor.Kind { - case clang.CursorParmDecl, clang.CursorFieldDecl: - // In C language, parameter lists do not have similar parameter grouping in Go. - // func foo(a, b int) - - // For follows struct, it will also parse to two FieldDecl - // struct A { - // int a, b; - // }; - if cursor.Kind == clang.CursorFieldDecl { - ctx.converter.logln("visitFieldList: CursorFieldDecl") - } else { - ctx.converter.logln("visitFieldList: CursorParmDecl") - } - - field := ctx.createBaseField(cursor) - if cursor.Kind == clang.CursorFieldDecl { - field.Access = ast.AccessSpecifier(cursor.CXXAccessSpecifier()) - } - - ctx.params.List = append(ctx.params.List, field) - - case clang.CursorVarDecl: - if cursor.StorageClass() == clang.SCStatic { - // static member variable - field := ctx.createBaseField(cursor) - field.Access = ast.AccessSpecifier(cursor.CXXAccessSpecifier()) - field.IsStatic = true - ctx.params.List = append(ctx.params.List, field) - } - } - - return clang.ChildVisit_Continue -} // For Record Type(struct,union ...) & Func 's FieldList func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList { @@ -717,12 +673,42 @@ func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList { defer ct.decIndent() params := &ast.FieldList{} - ctx := &visitFieldContext{ - params: params, - converter: ct, - } ct.logln("ProcessFieldList: VisitChildren") - clang.VisitChildren(cursor, visitFieldList, c.Pointer(ctx)) + VisitChildren(cursor, func(subcsr, parent clang.Cursor) clang.ChildVisitResult { + switch subcsr.Kind { + case clang.CursorParmDecl, clang.CursorFieldDecl: + // In C language, parameter lists do not have similar parameter grouping in Go. + // func foo(a, b int) + + // For follows struct, it will also parse to two FieldDecl + // struct A { + // int a, b; + // }; + if subcsr.Kind == clang.CursorFieldDecl { + ct.logln("ProcessFieldList: CursorFieldDecl") + } else { + ct.logln("ProcessFieldList: CursorParmDecl") + } + + field := ct.createBaseField(subcsr) + if subcsr.Kind == clang.CursorFieldDecl { + field.Access = ast.AccessSpecifier(subcsr.CXXAccessSpecifier()) + } + + params.List = append(params.List, field) + + case clang.CursorVarDecl: + if subcsr.StorageClass() == clang.SCStatic { + // static member variable + field := ct.createBaseField(subcsr) + field.Access = ast.AccessSpecifier(subcsr.CXXAccessSpecifier()) + field.IsStatic = true + params.List = append(params.List, field) + } + } + return clang.ChildVisit_Continue + }) + if (cursor.Kind == clang.CursorFunctionDecl || isMethod(cursor)) && cursor.IsVariadic() != 0 { params.List = append(params.List, &ast.Field{ Type: &ast.Variadic{}, @@ -731,30 +717,18 @@ func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList { return params } -type visitMethodsContext struct { - methods *[]*ast.FuncDecl - converter *Converter -} - -func visitMethods(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult { - ctx := (*visitMethodsContext)(clientData) - if isMethod(cursor) && cursor.CXXAccessSpecifier() == clang.CXXPublic { - method := ctx.converter.ProcessFuncDecl(cursor) - if method != nil { - *ctx.methods = append(*ctx.methods, method) - } - } - return clang.ChildVisit_Continue -} - // Note:Public Method is considered func (ct *Converter) ProcessMethods(cursor clang.Cursor) []*ast.FuncDecl { methods := make([]*ast.FuncDecl, 0) - ctx := &visitMethodsContext{ - methods: &methods, - converter: ct, - } - clang.VisitChildren(cursor, visitMethods, c.Pointer(ctx)) + VisitChildren(cursor, func(subcsr, parent clang.Cursor) clang.ChildVisitResult { + if isMethod(subcsr) && subcsr.CXXAccessSpecifier() == clang.CXXPublic { + method := ct.ProcessFuncDecl(subcsr) + if method != nil { + methods = append(methods, method) + } + } + return clang.ChildVisit_Continue + }) return methods } From 05777019c8d9f13285b854f6ff7bb48ebf7dc781 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Thu, 24 Oct 2024 17:46:33 +0800 Subject: [PATCH 12/13] llcppsigfetch:anony enum --- chore/_xtool/llcppsigfetch/parse/cvt.go | 29 ++++---- .../cvt_test/decl_test/enum_test/enum.go | 5 ++ .../cvt_test/decl_test/enum_test/llgo.expect | 66 +++++++++++++++++-- 3 files changed, 84 insertions(+), 16 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 8ad9b658..1c26389f 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -611,13 +611,22 @@ func (ct *Converter) ProcessEnumType(cursor clang.Cursor) *ast.EnumType { } func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl { - name := toStr(cursor.String()) + cursorName, cursorKind := getCursorDesc(cursor) + ct.logln("ProcessEnumDecl: CursorName:", cursorName, "CursorKind:", cursorKind) decl := &ast.EnumTypeDecl{ DeclBase: ct.CreateDeclBase(cursor), - Name: &ast.Ident{Name: name}, Type: ct.ProcessEnumType(cursor), } + + anony := cursor.IsAnonymous() + if anony == 0 { + decl.Name = &ast.Ident{Name: cursorName} + ct.logln("ProcessEnumDecl: has name", cursorName) + } else { + ct.logln("ProcessRecordDecl: is anonymous") + } + ct.SetTypeDecl(cursor, decl) return decl } @@ -738,22 +747,20 @@ func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl { cursorName, cursorKind := getCursorDesc(cursor) ct.logln("ProcessRecordDecl: CursorName:", cursorName, "CursorKind:", cursorKind) + decl := &ast.TypeDecl{ + DeclBase: ct.CreateDeclBase(cursor), + Type: ct.ProcessRecordType(cursor), + } + anony := cursor.IsAnonymousRecordDecl() - var name *ast.Ident if anony == 0 { - name = &ast.Ident{Name: cursorName} + decl.Name = &ast.Ident{Name: cursorName} ct.logln("ProcessRecordDecl: has name", cursorName) } else { ct.logln("ProcessRecordDecl: is anonymous") } - decl := &ast.TypeDecl{ - DeclBase: ct.CreateDeclBase(cursor), - Name: name, - Type: ct.ProcessRecordType(cursor), - } ct.SetTypeDecl(cursor, decl) - return decl } @@ -775,7 +782,7 @@ func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl { decl := &ast.TypeDecl{ DeclBase: base, - Name: &ast.Ident{Name: c.GoString(cursor.String().CStr())}, + Name: &ast.Ident{Name: cursorName}, Type: typ, } diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/enum.go b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/enum.go index 8ed4cba7..31e3be96 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/enum.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/enum.go @@ -8,6 +8,11 @@ func main() { func TestEnumDecl() { testCases := []string{ + `enum { + a, + b, + c, + };`, `enum Foo { a, b, diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/llgo.expect index b82d9957..23f9c577 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/enum_test/llgo.expect @@ -11,10 +11,7 @@ TestEnumDecl Case 1: }, "Doc": null, "Parent": null, - "Name": { - "_Type": "Ident", - "Name": "Foo" - }, + "Name": null, "Type": { "_Type": "EnumType", "Items": [{ @@ -59,6 +56,65 @@ TestEnumDecl Case 1: } TestEnumDecl Case 2: +{ + "temp.h": { + "_Type": "File", + "decls": [{ + "_Type": "EnumTypeDecl", + "Loc": { + "_Type": "Location", + "File": "temp.h" + }, + "Doc": null, + "Parent": null, + "Name": { + "_Type": "Ident", + "Name": "Foo" + }, + "Type": { + "_Type": "EnumType", + "Items": [{ + "_Type": "EnumItem", + "Name": { + "_Type": "Ident", + "Name": "a" + }, + "Value": { + "_Type": "BasicLit", + "Kind": 0, + "Value": "0" + } + }, { + "_Type": "EnumItem", + "Name": { + "_Type": "Ident", + "Name": "b" + }, + "Value": { + "_Type": "BasicLit", + "Kind": 0, + "Value": "1" + } + }, { + "_Type": "EnumItem", + "Name": { + "_Type": "Ident", + "Name": "c" + }, + "Value": { + "_Type": "BasicLit", + "Kind": 0, + "Value": "2" + } + }] + } + }], + "includes": [], + "macros": [] + } +} + +TestEnumDecl Case 3: { "temp.h": { "_Type": "File", @@ -117,7 +173,7 @@ TestEnumDecl Case 2: } } -TestEnumDecl Case 3: +TestEnumDecl Case 4: { "temp.h": { "_Type": "File", From a7727adca2e31892adddddfe742631f35a7fea28 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Sat, 26 Oct 2024 13:09:30 +0800 Subject: [PATCH 13/13] llcppsigfetch:remove one leading underscore only in mac --- chore/_xtool/llcppsigfetch/parse/cvt.go | 6 ++++- .../cvt_test/decl_test/class_test/llgo.expect | 24 +++++++++---------- .../decl_test/comment_test/llgo.expect | 20 ++++++++-------- .../cvt_test/decl_test/func_test/llgo.expect | 10 ++++---- .../cvt_test/decl_test/scope_test/llgo.expect | 10 ++++---- 5 files changed, 37 insertions(+), 33 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 1c26389f..069e2a71 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -3,6 +3,7 @@ package parse import ( "fmt" "os" + "runtime" "strings" "unsafe" @@ -520,7 +521,10 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl { params := ct.ProcessFieldList(cursor) funcType.Params = params - mangledName = strings.TrimLeft(mangledName, "_") + // Linux has one less leading underscore than macOS, so remove one leading underscore on macOS + if runtime.GOOS == "darwin" { + mangledName = strings.TrimPrefix(mangledName, "_") + } funcDecl := &ast.FuncDecl{ DeclBase: ct.CreateDeclBase(cursor), diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect index 65f75cd7..c75368df 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/class_test/llgo.expect @@ -128,7 +128,7 @@ TestClassDecl Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN1A3fooEid", + "MangledName": "_ZN1A3fooEid", "Type": { "_Type": "FuncType", "Params": { @@ -225,7 +225,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "A" }, - "MangledName": "ZN1AC1Ev", + "MangledName": "_ZN1AC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -261,7 +261,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "A" }, - "MangledName": "ZN1AC1Ev", + "MangledName": "_ZN1AC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -297,7 +297,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "~A" }, - "MangledName": "ZN1AD1Ev", + "MangledName": "_ZN1AD1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -333,7 +333,7 @@ TestClassDecl Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN1A3fooEv", + "MangledName": "_ZN1A3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -400,7 +400,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "Base" }, - "MangledName": "ZN4BaseC1Ev", + "MangledName": "_ZN4BaseC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -436,7 +436,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "~Base" }, - "MangledName": "ZN4BaseD1Ev", + "MangledName": "_ZN4BaseD1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -472,7 +472,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN4Base3fooEv", + "MangledName": "_ZN4Base3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -529,7 +529,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "Derived" }, - "MangledName": "ZN7DerivedC1Ev", + "MangledName": "_ZN7DerivedC1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -565,7 +565,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "~Derived" }, - "MangledName": "ZN7DerivedD1Ev", + "MangledName": "_ZN7DerivedD1Ev", "Type": { "_Type": "FuncType", "Params": { @@ -601,7 +601,7 @@ TestClassDecl Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN7Derived3fooEv", + "MangledName": "_ZN7Derived3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -680,7 +680,7 @@ TestClassDecl Case 5: "_Type": "Ident", "Name": "bar" }, - "MangledName": "ZN1A3Foo3barEv", + "MangledName": "_ZN1A3Foo3barEv", "Type": { "_Type": "FuncType", "Params": { diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect index 13076294..6c769412 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/comment_test/llgo.expect @@ -15,7 +15,7 @@ TestDoc Case 1: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -58,7 +58,7 @@ TestDoc Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -107,7 +107,7 @@ TestDoc Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -156,7 +156,7 @@ TestDoc Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -205,7 +205,7 @@ TestDoc Case 5: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -257,7 +257,7 @@ TestDoc Case 6: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -309,7 +309,7 @@ TestDoc Case 7: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -361,7 +361,7 @@ TestDoc Case 8: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -419,7 +419,7 @@ TestDoc Case 9: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -707,7 +707,7 @@ TestDoc Case 11: "_Type": "Ident", "Name": "Foo" }, - "MangledName": "ZN3Doc3FooEv", + "MangledName": "_ZN3Doc3FooEv", "Type": { "_Type": "FuncType", "Params": { diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect index e573491a..383660fb 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/func_test/llgo.expect @@ -15,7 +15,7 @@ TestFuncDecl Case 1: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -58,7 +58,7 @@ TestFuncDecl Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3fooi", + "MangledName": "_Z3fooi", "Type": { "_Type": "FuncType", "Params": { @@ -116,7 +116,7 @@ TestFuncDecl Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3fooiz", + "MangledName": "_Z3fooiz", "Type": { "_Type": "FuncType", "Params": { @@ -184,7 +184,7 @@ TestFuncDecl Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3fooid", + "MangledName": "_Z3fooid", "Type": { "_Type": "FuncType", "Params": { @@ -260,7 +260,7 @@ TestFuncDecl Case 5: "_Type": "Ident", "Name": "add" }, - "MangledName": "ZL3addii", + "MangledName": "_ZL3addii", "Type": { "_Type": "FuncType", "Params": { diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect index e903e0f8..66093d7f 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/scope_test/llgo.expect @@ -15,7 +15,7 @@ TestScope Case 1: "_Type": "Ident", "Name": "foo" }, - "MangledName": "Z3foov", + "MangledName": "_Z3foov", "Type": { "_Type": "FuncType", "Params": { @@ -61,7 +61,7 @@ TestScope Case 2: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN1a3fooEv", + "MangledName": "_ZN1a3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -114,7 +114,7 @@ TestScope Case 3: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN1a1b3fooEv", + "MangledName": "_ZN1a1b3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -179,7 +179,7 @@ TestScope Case 4: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN1a3fooEv", + "MangledName": "_ZN1a3fooEv", "Type": { "_Type": "FuncType", "Params": { @@ -256,7 +256,7 @@ TestScope Case 5: "_Type": "Ident", "Name": "foo" }, - "MangledName": "ZN1a1b3fooEv", + "MangledName": "_ZN1a1b3fooEv", "Type": { "_Type": "FuncType", "Params": {