From 3f39c576b7d2fcbef4394e189edf7b00e9b99a2f Mon Sep 17 00:00:00 2001 From: konstantin8105 Date: Wed, 21 Jun 2017 00:37:17 +0300 Subject: [PATCH 01/16] Clarify preprocess error --- .gitignore | 4 ++++ main.go | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1b8b17bb5..c77cb1453 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ /c2go /.vscode *.coverprofile + +# Vim backups +*.go~ +*.go.swp diff --git a/main.go b/main.go index b70d58261..93d374fcf 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( + "bytes" "flag" "fmt" "io/ioutil" @@ -150,8 +151,20 @@ func Start(args ProgramArgs) { Check("", err) // 2. Preprocess - pp, err := exec.Command("clang", "-E", args.inputFile).Output() - Check("preprocess failed: ", err) + var pp []byte + { + cmd := exec.Command("clang", "-E", args.inputFile) + var out bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + err = cmd.Run() + if err != nil { + fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) + Check("preprocess failed: ", err) + } + pp = []byte(out.String()) + } pp_file_path := path.Join(os.TempDir(), "pp.c") err = ioutil.WriteFile(pp_file_path, pp, 0644) From d5676d9a3623132fb17b368ee91a178a4c8c7479 Mon Sep 17 00:00:00 2001 From: konstantin8105 Date: Wed, 21 Jun 2017 01:48:43 +0300 Subject: [PATCH 02/16] Fix metalinter error. Fix #170 --- main.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 93d374fcf..20b8183a6 100644 --- a/main.go +++ b/main.go @@ -26,6 +26,7 @@ import ( // See https://github.com/elliotchance/c2go/wiki/Release-Process const Version = "0.13.3" +// ProgramArgs - argument of program type ProgramArgs struct { verbose bool ast bool @@ -106,6 +107,7 @@ func buildTree(nodes []treeNode, depth int) []ast.Node { return results } +// ToJSON - tree convert to JSON func ToJSON(tree []interface{}) []map[string]interface{} { r := make([]map[string]interface{}, len(tree)) @@ -135,12 +137,14 @@ func ToJSON(tree []interface{}) []map[string]interface{} { return r } +// Check - checking error. Panic-nonfree function func Check(prefix string, e error) { if e != nil { panic(prefix + e.Error()) } } +// Start - base function func Start(args ProgramArgs) { if os.Getenv("GOPATH") == "" { panic("The $GOPATH must be set.") @@ -166,21 +170,21 @@ func Start(args ProgramArgs) { pp = []byte(out.String()) } - pp_file_path := path.Join(os.TempDir(), "pp.c") - err = ioutil.WriteFile(pp_file_path, pp, 0644) + ppFilePath := path.Join(os.TempDir(), "pp.c") + err = ioutil.WriteFile(ppFilePath, pp, 0644) Check("writing to /tmp/pp.c failed: ", err) // 3. Generate JSON from AST - ast_pp, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", pp_file_path).Output() + astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output() if err != nil { // If clang fails it still prints out the AST, so we have to run it // again to get the real error. - errBody, _ := exec.Command("clang", pp_file_path).CombinedOutput() + errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput() panic("clang failed: " + err.Error() + ":\n\n" + string(errBody)) } - lines := readAST(ast_pp) + lines := readAST(astPP) if args.ast { for _, l := range lines { fmt.Println(l) @@ -252,7 +256,8 @@ func main() { switch os.Args[1] { case "ast": - astCommand.Parse(os.Args[2:]) + err := astCommand.Parse(os.Args[2:]) + Check("Ast command cannot parse", err) if *astHelpFlag || astCommand.NArg() == 0 { fmt.Fprintf(os.Stderr, "Usage: %s ast file.c\n", os.Args[0]) @@ -265,7 +270,8 @@ func main() { Start(args) case "transpile": - transpileCommand.Parse(os.Args[2:]) + err := transpileCommand.Parse(os.Args[2:]) + Check("Transpile command cannot parse", err) if *transpileHelpFlag || transpileCommand.NArg() == 0 { fmt.Fprintf(os.Stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file.c\n", os.Args[0]) From 34083baa83c17ace5d9432abf2a57453c9e2ff6c Mon Sep 17 00:00:00 2001 From: konstantin8105 Date: Wed, 21 Jun 2017 02:40:10 +0300 Subject: [PATCH 03/16] Add test --- analyze/analyze.go | 208 ++++++++++++++++++++++++++++++++++++ analyze/analyze_test.go | 53 ++++++++++ main.go | 226 +++------------------------------------- 3 files changed, 276 insertions(+), 211 deletions(-) create mode 100644 analyze/analyze.go create mode 100644 analyze/analyze_test.go diff --git a/analyze/analyze.go b/analyze/analyze.go new file mode 100644 index 000000000..22bb1ba07 --- /dev/null +++ b/analyze/analyze.go @@ -0,0 +1,208 @@ +package analyze + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "path/filepath" + "reflect" + "regexp" + "strings" + + "github.com/elliotchance/c2go/ast" + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/transpiler" +) + +// ProgramArgs - argument of program +type ProgramArgs struct { + Verbose bool + Ast bool + InputFile string + OutputFile string + PackageName string +} + +func readAST(data []byte) []string { + uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{}) + return strings.Split(string(uncolored), "\n") +} + +type treeNode struct { + indent int + node ast.Node +} + +func convertLinesToNodes(lines []string) []treeNode { + nodes := []treeNode{} + for _, line := range lines { + if strings.TrimSpace(line) == "" { + continue + } + + // It is tempting to discard null AST nodes, but these may + // have semantic importance: for example, they represent omitted + // for-loop conditions, as in for(;;). + line = strings.Replace(line, "<<>>", "NullStmt", 1) + + indentAndType := regexp.MustCompile("^([|\\- `]*)(\\w+)").FindStringSubmatch(line) + if len(indentAndType) == 0 { + panic(fmt.Sprintf("Cannot understand line '%s'", line)) + } + + offset := len(indentAndType[1]) + node := ast.Parse(line[offset:]) + + indentLevel := len(indentAndType[1]) / 2 + nodes = append(nodes, treeNode{indentLevel, node}) + } + + return nodes +} + +// buildTree convert an array of nodes, each prefixed with a depth into a tree. +func buildTree(nodes []treeNode, depth int) []ast.Node { + if len(nodes) == 0 { + return []ast.Node{} + } + + // Split the list into sections, treat each section as a a tree with its own root. + sections := [][]treeNode{} + for _, node := range nodes { + if node.indent == depth { + sections = append(sections, []treeNode{node}) + } else { + sections[len(sections)-1] = append(sections[len(sections)-1], node) + } + } + + results := []ast.Node{} + for _, section := range sections { + slice := []treeNode{} + for _, n := range section { + if n.indent > depth { + slice = append(slice, n) + } + } + + children := buildTree(slice, depth+1) + for _, child := range children { + section[0].node.AddChild(child) + } + results = append(results, section[0].node) + } + + return results +} + +// ToJSON - tree convert to JSON +func ToJSON(tree []interface{}) []map[string]interface{} { + r := make([]map[string]interface{}, len(tree)) + + for j, n := range tree { + rn := reflect.ValueOf(n).Elem() + r[j] = make(map[string]interface{}) + r[j]["node"] = rn.Type().Name() + + for i := 0; i < rn.NumField(); i++ { + name := strings.ToLower(rn.Type().Field(i).Name) + value := rn.Field(i).Interface() + + if name == "children" { + v := value.([]interface{}) + + if len(v) == 0 { + continue + } + + value = ToJSON(v) + } + + r[j][name] = value + } + } + + return r +} + +// Start - base function +func Start(args ProgramArgs) error { + if os.Getenv("GOPATH") == "" { + panic("The $GOPATH must be set.") + } + + // 1. Compile it first (checking for errors) + _, err := os.Stat(args.InputFile) + if err != nil { + return fmt.Errorf("Input file is not found") + } + + // 2. Preprocess + var pp []byte + { + cmd := exec.Command("clang", "-E", args.InputFile) + var out bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + err = cmd.Run() + if err != nil { + return fmt.Errorf("preprocess failed: %v\nStdErr = %v", err, stderr.String()) + } + pp = []byte(out.String()) + } + + ppFilePath := path.Join(os.TempDir(), "pp.c") + err = ioutil.WriteFile(ppFilePath, pp, 0644) + if err != nil { + return fmt.Errorf("writing to /tmp/pp.c failed: %v", err) + } + + // 3. Generate JSON from AST + astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output() + if err != nil { + // If clang fails it still prints out the AST, so we have to run it + // again to get the real error. + errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput() + + panic("clang failed: " + err.Error() + ":\n\n" + string(errBody)) + } + + lines := readAST(astPP) + if args.Ast { + for _, l := range lines { + fmt.Println(l) + } + fmt.Println() + } + + nodes := convertLinesToNodes(lines) + tree := buildTree(nodes, 0) + + p := program.NewProgram() + p.Verbose = args.Verbose + + err = transpiler.TranspileAST(args.InputFile, args.PackageName, p, tree[0].(ast.Node)) + if err != nil { + panic(err) + } + + outputFilePath := args.OutputFile + + if outputFilePath == "" { + cleanFileName := filepath.Clean(filepath.Base(args.InputFile)) + extension := filepath.Ext(args.InputFile) + + outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go" + } + + err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0755) + if err != nil { + return fmt.Errorf("writing C output file failed: %v", err) + } + + return nil +} diff --git a/analyze/analyze_test.go b/analyze/analyze_test.go new file mode 100644 index 000000000..77fd5ae15 --- /dev/null +++ b/analyze/analyze_test.go @@ -0,0 +1,53 @@ +package analyze_test + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/Konstantin8105/c2go/analyze" +) + +func TestStartPreprocess(t *testing.T) { + // temp dir + tempDir := os.TempDir() + + // create temp file with garantee + // wrong file body + tempFile, err := New(tempDir, "c2go", "preprocess.c") + if err != nil { + t.Errorf("Cannot create temp file for execute test") + } + + fmt.Fprintf(tempFile, "#include \nint main(void){\nwrong\n}") + + err = tempFile.Close() + if err != nil { + t.Errorf("Cannot close the temp file") + } + + fmt.Println("tempDir = ", tempDir) + fmt.Println("tempFile = ", tempFile) + + var args analyze.ProgramArgs + args.InputFile = tempFile.Name() + + err = analyze.Start(args) + fmt.Println("err = ", err) + if err == nil { + t.Errorf("Cannot test preprocess of application") + } +} + +// New returns an unused filename for output files. +func New(dir, prefix, suffix string) (*os.File, error) { + for index := 1; index < 10000; index++ { + path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix)) + if _, err := os.Stat(path); err != nil { + return os.Create(path) + } + } + // Give up + return nil, fmt.Errorf("could not create file of the form %s%03d%s", prefix, 1, suffix) +} diff --git a/main.go b/main.go index 20b8183a6..57dcac2f7 100644 --- a/main.go +++ b/main.go @@ -2,21 +2,11 @@ package main import ( - "bytes" "flag" "fmt" - "io/ioutil" "os" - "os/exec" - "path" - "path/filepath" - "reflect" - "regexp" - "strings" - "github.com/elliotchance/c2go/ast" - "github.com/elliotchance/c2go/program" - "github.com/elliotchance/c2go/transpiler" + "github.com/Konstantin8105/c2go/analyze" ) // Version can be requested through the command line with: @@ -26,196 +16,6 @@ import ( // See https://github.com/elliotchance/c2go/wiki/Release-Process const Version = "0.13.3" -// ProgramArgs - argument of program -type ProgramArgs struct { - verbose bool - ast bool - inputFile string - outputFile string - packageName string -} - -func readAST(data []byte) []string { - uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{}) - return strings.Split(string(uncolored), "\n") -} - -type treeNode struct { - indent int - node ast.Node -} - -func convertLinesToNodes(lines []string) []treeNode { - nodes := []treeNode{} - for _, line := range lines { - if strings.TrimSpace(line) == "" { - continue - } - - // It is tempting to discard null AST nodes, but these may - // have semantic importance: for example, they represent omitted - // for-loop conditions, as in for(;;). - line = strings.Replace(line, "<<>>", "NullStmt", 1) - - indentAndType := regexp.MustCompile("^([|\\- `]*)(\\w+)").FindStringSubmatch(line) - if len(indentAndType) == 0 { - panic(fmt.Sprintf("Cannot understand line '%s'", line)) - } - - offset := len(indentAndType[1]) - node := ast.Parse(line[offset:]) - - indentLevel := len(indentAndType[1]) / 2 - nodes = append(nodes, treeNode{indentLevel, node}) - } - - return nodes -} - -// buildTree convert an array of nodes, each prefixed with a depth into a tree. -func buildTree(nodes []treeNode, depth int) []ast.Node { - if len(nodes) == 0 { - return []ast.Node{} - } - - // Split the list into sections, treat each section as a a tree with its own root. - sections := [][]treeNode{} - for _, node := range nodes { - if node.indent == depth { - sections = append(sections, []treeNode{node}) - } else { - sections[len(sections)-1] = append(sections[len(sections)-1], node) - } - } - - results := []ast.Node{} - for _, section := range sections { - slice := []treeNode{} - for _, n := range section { - if n.indent > depth { - slice = append(slice, n) - } - } - - children := buildTree(slice, depth+1) - for _, child := range children { - section[0].node.AddChild(child) - } - results = append(results, section[0].node) - } - - return results -} - -// ToJSON - tree convert to JSON -func ToJSON(tree []interface{}) []map[string]interface{} { - r := make([]map[string]interface{}, len(tree)) - - for j, n := range tree { - rn := reflect.ValueOf(n).Elem() - r[j] = make(map[string]interface{}) - r[j]["node"] = rn.Type().Name() - - for i := 0; i < rn.NumField(); i++ { - name := strings.ToLower(rn.Type().Field(i).Name) - value := rn.Field(i).Interface() - - if name == "children" { - v := value.([]interface{}) - - if len(v) == 0 { - continue - } - - value = ToJSON(v) - } - - r[j][name] = value - } - } - - return r -} - -// Check - checking error. Panic-nonfree function -func Check(prefix string, e error) { - if e != nil { - panic(prefix + e.Error()) - } -} - -// Start - base function -func Start(args ProgramArgs) { - if os.Getenv("GOPATH") == "" { - panic("The $GOPATH must be set.") - } - - // 1. Compile it first (checking for errors) - _, err := os.Stat(args.inputFile) - Check("", err) - - // 2. Preprocess - var pp []byte - { - cmd := exec.Command("clang", "-E", args.inputFile) - var out bytes.Buffer - var stderr bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &stderr - err = cmd.Run() - if err != nil { - fmt.Println(fmt.Sprint(err) + ": " + stderr.String()) - Check("preprocess failed: ", err) - } - pp = []byte(out.String()) - } - - ppFilePath := path.Join(os.TempDir(), "pp.c") - err = ioutil.WriteFile(ppFilePath, pp, 0644) - Check("writing to /tmp/pp.c failed: ", err) - - // 3. Generate JSON from AST - astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output() - if err != nil { - // If clang fails it still prints out the AST, so we have to run it - // again to get the real error. - errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput() - - panic("clang failed: " + err.Error() + ":\n\n" + string(errBody)) - } - - lines := readAST(astPP) - if args.ast { - for _, l := range lines { - fmt.Println(l) - } - fmt.Println() - } - - nodes := convertLinesToNodes(lines) - tree := buildTree(nodes, 0) - - p := program.NewProgram() - p.Verbose = args.verbose - - err = transpiler.TranspileAST(args.inputFile, args.packageName, p, tree[0].(ast.Node)) - if err != nil { - panic(err) - } - - outputFilePath := args.outputFile - - if outputFilePath == "" { - cleanFileName := filepath.Clean(filepath.Base(args.inputFile)) - extension := filepath.Ext(args.inputFile) - - outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go" - } - - err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0755) - Check("writing C output file failed: ", err) -} - func main() { var ( versionFlag = flag.Bool("v", false, "print the version and exit") @@ -252,12 +52,12 @@ func main() { os.Exit(1) } - args := ProgramArgs{verbose: *verboseFlag, ast: false} + args := analyze.ProgramArgs{Verbose: *verboseFlag, Ast: false} switch os.Args[1] { case "ast": err := astCommand.Parse(os.Args[2:]) - Check("Ast command cannot parse", err) + analyze.Check("Ast command cannot parse", err) if *astHelpFlag || astCommand.NArg() == 0 { fmt.Fprintf(os.Stderr, "Usage: %s ast file.c\n", os.Args[0]) @@ -265,13 +65,15 @@ func main() { os.Exit(1) } - args.ast = true - args.inputFile = astCommand.Arg(0) + args.Ast = true + args.InputFile = astCommand.Arg(0) - Start(args) + if err = analyze.Start(args); err != nil { + fmt.Printf("Error: %v", err) + } case "transpile": err := transpileCommand.Parse(os.Args[2:]) - Check("Transpile command cannot parse", err) + analyze.Check("Transpile command cannot parse", err) if *transpileHelpFlag || transpileCommand.NArg() == 0 { fmt.Fprintf(os.Stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file.c\n", os.Args[0]) @@ -279,11 +81,13 @@ func main() { os.Exit(1) } - args.inputFile = transpileCommand.Arg(0) - args.outputFile = *outputFlag - args.packageName = *packageFlag + args.InputFile = transpileCommand.Arg(0) + args.OutputFile = *outputFlag + args.PackageName = *packageFlag - Start(args) + if err = analyze.Start(args); err != nil { + fmt.Printf("Error: %v", err) + } default: flag.Usage() os.Exit(1) From e8a3d746b9679e6bc7eefd2d5b566b49110a4aab Mon Sep 17 00:00:00 2001 From: konstantin8105 Date: Wed, 21 Jun 2017 02:52:31 +0300 Subject: [PATCH 04/16] remote temp file in test --- analyze/analyze_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/analyze/analyze_test.go b/analyze/analyze_test.go index 77fd5ae15..378caabbe 100644 --- a/analyze/analyze_test.go +++ b/analyze/analyze_test.go @@ -19,6 +19,9 @@ func TestStartPreprocess(t *testing.T) { if err != nil { t.Errorf("Cannot create temp file for execute test") } + defer func() { + _ = os.Remove(tempFile.Name()) + }() fmt.Fprintf(tempFile, "#include \nint main(void){\nwrong\n}") From d05fe44e8aedc6c275a27d4c9700470016a89270 Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Wed, 21 Jun 2017 17:10:51 +0300 Subject: [PATCH 05/16] remove analyze.Check function from mian function --- .gitignore | 1 + main.go | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c77cb1453..d226169f9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ # Vim backups *.go~ *.go.swp +*.un~ diff --git a/main.go b/main.go index 57dcac2f7..f58658654 100644 --- a/main.go +++ b/main.go @@ -57,7 +57,10 @@ func main() { switch os.Args[1] { case "ast": err := astCommand.Parse(os.Args[2:]) - analyze.Check("Ast command cannot parse", err) + if err != nil { + fmt.Printf("Ast command cannot parse: %v", err) + return + } if *astHelpFlag || astCommand.NArg() == 0 { fmt.Fprintf(os.Stderr, "Usage: %s ast file.c\n", os.Args[0]) @@ -73,7 +76,10 @@ func main() { } case "transpile": err := transpileCommand.Parse(os.Args[2:]) - analyze.Check("Transpile command cannot parse", err) + if err != nil { + fmt.Printf("Transpile command cannot parse: %v", err) + return + } if *transpileHelpFlag || transpileCommand.NArg() == 0 { fmt.Fprintf(os.Stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file.c\n", os.Args[0]) From 6bd3509dc36e413dcb4cad2df1fd8366754e16b2 Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Wed, 21 Jun 2017 17:51:01 +0300 Subject: [PATCH 06/16] modify mail_test for build --- main_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main_test.go b/main_test.go index ffd24cf21..fb0427475 100644 --- a/main_test.go +++ b/main_test.go @@ -15,6 +15,7 @@ import ( "regexp" + "github.com/Konstantin8105/c2go/analyze" "github.com/elliotchance/c2go/util" ) @@ -82,14 +83,14 @@ func TestIntegrationScripts(t *testing.T) { err = cmd.Run() cProgram.isZero = err == nil - programArgs := ProgramArgs{ + programArgs := analyze.ProgramArgs{ inputFile: file, outputFile: "build/main.go", packageName: "main", } // Compile Go - Start(programArgs) + analyze.Start(programArgs) buildErr, err := exec.Command("go", "build", "-o", goPath, "build/main.go").CombinedOutput() if err != nil { From 12f12c87e4cf450f87b0853c95d14a58bbe66cf8 Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Wed, 21 Jun 2017 18:01:10 +0300 Subject: [PATCH 07/16] modify mail_test for build --- main_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main_test.go b/main_test.go index fb0427475..e29120e8d 100644 --- a/main_test.go +++ b/main_test.go @@ -84,9 +84,9 @@ func TestIntegrationScripts(t *testing.T) { cProgram.isZero = err == nil programArgs := analyze.ProgramArgs{ - inputFile: file, - outputFile: "build/main.go", - packageName: "main", + InputFile: file, + OutputFile: "build/main.go", + PackageName: "main", } // Compile Go From 9c9b225963127d5bc75e3e0eafdf9ae7c7c6f0ff Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Wed, 21 Jun 2017 18:06:00 +0300 Subject: [PATCH 08/16] add change from return to os.Exit --- main.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index f58658654..5286d12cf 100644 --- a/main.go +++ b/main.go @@ -59,7 +59,7 @@ func main() { err := astCommand.Parse(os.Args[2:]) if err != nil { fmt.Printf("Ast command cannot parse: %v", err) - return + os.Exit(1) } if *astHelpFlag || astCommand.NArg() == 0 { @@ -73,12 +73,13 @@ func main() { if err = analyze.Start(args); err != nil { fmt.Printf("Error: %v", err) + os.Exit(1) } case "transpile": err := transpileCommand.Parse(os.Args[2:]) if err != nil { fmt.Printf("Transpile command cannot parse: %v", err) - return + os.Exit(1) } if *transpileHelpFlag || transpileCommand.NArg() == 0 { @@ -93,6 +94,7 @@ func main() { if err = analyze.Start(args); err != nil { fmt.Printf("Error: %v", err) + os.Exit(1) } default: flag.Usage() From b20766404d29c7be6b12732e2795607938984483 Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Wed, 21 Jun 2017 18:20:25 +0300 Subject: [PATCH 09/16] remove debug information from test --- analyze/analyze_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/analyze/analyze_test.go b/analyze/analyze_test.go index 378caabbe..795b1b254 100644 --- a/analyze/analyze_test.go +++ b/analyze/analyze_test.go @@ -30,14 +30,10 @@ func TestStartPreprocess(t *testing.T) { t.Errorf("Cannot close the temp file") } - fmt.Println("tempDir = ", tempDir) - fmt.Println("tempFile = ", tempFile) - var args analyze.ProgramArgs args.InputFile = tempFile.Name() err = analyze.Start(args) - fmt.Println("err = ", err) if err == nil { t.Errorf("Cannot test preprocess of application") } From d3bb1e05e4e0ccea3eb4eddf94d4e9ed72dbd4de Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Wed, 21 Jun 2017 19:17:44 +0300 Subject: [PATCH 10/16] change links for imports --- analyze/analyze_test.go | 2 +- main.go | 2 +- main_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/analyze/analyze_test.go b/analyze/analyze_test.go index 795b1b254..aee7101ca 100644 --- a/analyze/analyze_test.go +++ b/analyze/analyze_test.go @@ -6,7 +6,7 @@ import ( "path/filepath" "testing" - "github.com/Konstantin8105/c2go/analyze" + "github.com/elliotchance/c2go/analyze" ) func TestStartPreprocess(t *testing.T) { diff --git a/main.go b/main.go index 5286d12cf..ede3d53b8 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,7 @@ import ( "fmt" "os" - "github.com/Konstantin8105/c2go/analyze" + "github.com/elliotchance/c2go/analyze" ) // Version can be requested through the command line with: diff --git a/main_test.go b/main_test.go index e29120e8d..b2c27e281 100644 --- a/main_test.go +++ b/main_test.go @@ -15,7 +15,7 @@ import ( "regexp" - "github.com/Konstantin8105/c2go/analyze" + "github.com/elliotchance/c2go/analyze" "github.com/elliotchance/c2go/util" ) From a13eeb875669f4e007d2825a0462fabf877d5e45 Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Wed, 21 Jun 2017 20:20:50 +0300 Subject: [PATCH 11/16] Remove analyze folder --- analyze/analyze.go | 208 -------------------------------------- analyze/analyze_test.go | 52 ---------- main.go | 217 ++++++++++++++++++++++++++++++++++++++-- main_test.go | 53 ++++++++-- 4 files changed, 255 insertions(+), 275 deletions(-) delete mode 100644 analyze/analyze.go delete mode 100644 analyze/analyze_test.go diff --git a/analyze/analyze.go b/analyze/analyze.go deleted file mode 100644 index 22bb1ba07..000000000 --- a/analyze/analyze.go +++ /dev/null @@ -1,208 +0,0 @@ -package analyze - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "reflect" - "regexp" - "strings" - - "github.com/elliotchance/c2go/ast" - "github.com/elliotchance/c2go/program" - "github.com/elliotchance/c2go/transpiler" -) - -// ProgramArgs - argument of program -type ProgramArgs struct { - Verbose bool - Ast bool - InputFile string - OutputFile string - PackageName string -} - -func readAST(data []byte) []string { - uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{}) - return strings.Split(string(uncolored), "\n") -} - -type treeNode struct { - indent int - node ast.Node -} - -func convertLinesToNodes(lines []string) []treeNode { - nodes := []treeNode{} - for _, line := range lines { - if strings.TrimSpace(line) == "" { - continue - } - - // It is tempting to discard null AST nodes, but these may - // have semantic importance: for example, they represent omitted - // for-loop conditions, as in for(;;). - line = strings.Replace(line, "<<>>", "NullStmt", 1) - - indentAndType := regexp.MustCompile("^([|\\- `]*)(\\w+)").FindStringSubmatch(line) - if len(indentAndType) == 0 { - panic(fmt.Sprintf("Cannot understand line '%s'", line)) - } - - offset := len(indentAndType[1]) - node := ast.Parse(line[offset:]) - - indentLevel := len(indentAndType[1]) / 2 - nodes = append(nodes, treeNode{indentLevel, node}) - } - - return nodes -} - -// buildTree convert an array of nodes, each prefixed with a depth into a tree. -func buildTree(nodes []treeNode, depth int) []ast.Node { - if len(nodes) == 0 { - return []ast.Node{} - } - - // Split the list into sections, treat each section as a a tree with its own root. - sections := [][]treeNode{} - for _, node := range nodes { - if node.indent == depth { - sections = append(sections, []treeNode{node}) - } else { - sections[len(sections)-1] = append(sections[len(sections)-1], node) - } - } - - results := []ast.Node{} - for _, section := range sections { - slice := []treeNode{} - for _, n := range section { - if n.indent > depth { - slice = append(slice, n) - } - } - - children := buildTree(slice, depth+1) - for _, child := range children { - section[0].node.AddChild(child) - } - results = append(results, section[0].node) - } - - return results -} - -// ToJSON - tree convert to JSON -func ToJSON(tree []interface{}) []map[string]interface{} { - r := make([]map[string]interface{}, len(tree)) - - for j, n := range tree { - rn := reflect.ValueOf(n).Elem() - r[j] = make(map[string]interface{}) - r[j]["node"] = rn.Type().Name() - - for i := 0; i < rn.NumField(); i++ { - name := strings.ToLower(rn.Type().Field(i).Name) - value := rn.Field(i).Interface() - - if name == "children" { - v := value.([]interface{}) - - if len(v) == 0 { - continue - } - - value = ToJSON(v) - } - - r[j][name] = value - } - } - - return r -} - -// Start - base function -func Start(args ProgramArgs) error { - if os.Getenv("GOPATH") == "" { - panic("The $GOPATH must be set.") - } - - // 1. Compile it first (checking for errors) - _, err := os.Stat(args.InputFile) - if err != nil { - return fmt.Errorf("Input file is not found") - } - - // 2. Preprocess - var pp []byte - { - cmd := exec.Command("clang", "-E", args.InputFile) - var out bytes.Buffer - var stderr bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &stderr - err = cmd.Run() - if err != nil { - return fmt.Errorf("preprocess failed: %v\nStdErr = %v", err, stderr.String()) - } - pp = []byte(out.String()) - } - - ppFilePath := path.Join(os.TempDir(), "pp.c") - err = ioutil.WriteFile(ppFilePath, pp, 0644) - if err != nil { - return fmt.Errorf("writing to /tmp/pp.c failed: %v", err) - } - - // 3. Generate JSON from AST - astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output() - if err != nil { - // If clang fails it still prints out the AST, so we have to run it - // again to get the real error. - errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput() - - panic("clang failed: " + err.Error() + ":\n\n" + string(errBody)) - } - - lines := readAST(astPP) - if args.Ast { - for _, l := range lines { - fmt.Println(l) - } - fmt.Println() - } - - nodes := convertLinesToNodes(lines) - tree := buildTree(nodes, 0) - - p := program.NewProgram() - p.Verbose = args.Verbose - - err = transpiler.TranspileAST(args.InputFile, args.PackageName, p, tree[0].(ast.Node)) - if err != nil { - panic(err) - } - - outputFilePath := args.OutputFile - - if outputFilePath == "" { - cleanFileName := filepath.Clean(filepath.Base(args.InputFile)) - extension := filepath.Ext(args.InputFile) - - outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go" - } - - err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0755) - if err != nil { - return fmt.Errorf("writing C output file failed: %v", err) - } - - return nil -} diff --git a/analyze/analyze_test.go b/analyze/analyze_test.go deleted file mode 100644 index aee7101ca..000000000 --- a/analyze/analyze_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package analyze_test - -import ( - "fmt" - "os" - "path/filepath" - "testing" - - "github.com/elliotchance/c2go/analyze" -) - -func TestStartPreprocess(t *testing.T) { - // temp dir - tempDir := os.TempDir() - - // create temp file with garantee - // wrong file body - tempFile, err := New(tempDir, "c2go", "preprocess.c") - if err != nil { - t.Errorf("Cannot create temp file for execute test") - } - defer func() { - _ = os.Remove(tempFile.Name()) - }() - - fmt.Fprintf(tempFile, "#include \nint main(void){\nwrong\n}") - - err = tempFile.Close() - if err != nil { - t.Errorf("Cannot close the temp file") - } - - var args analyze.ProgramArgs - args.InputFile = tempFile.Name() - - err = analyze.Start(args) - if err == nil { - t.Errorf("Cannot test preprocess of application") - } -} - -// New returns an unused filename for output files. -func New(dir, prefix, suffix string) (*os.File, error) { - for index := 1; index < 10000; index++ { - path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix)) - if _, err := os.Stat(path); err != nil { - return os.Create(path) - } - } - // Give up - return nil, fmt.Errorf("could not create file of the form %s%03d%s", prefix, 1, suffix) -} diff --git a/main.go b/main.go index ede3d53b8..ca2395ba4 100644 --- a/main.go +++ b/main.go @@ -2,11 +2,21 @@ package main import ( + "bytes" "flag" "fmt" + "io/ioutil" "os" + "os/exec" + "path" + "path/filepath" + "reflect" + "regexp" + "strings" - "github.com/elliotchance/c2go/analyze" + "github.com/elliotchance/c2go/ast" + "github.com/elliotchance/c2go/program" + "github.com/elliotchance/c2go/transpiler" ) // Version can be requested through the command line with: @@ -16,6 +26,195 @@ import ( // See https://github.com/elliotchance/c2go/wiki/Release-Process const Version = "0.13.3" +// ProgramArgs - arguments of program +type ProgramArgs struct { + verbose bool + ast bool + inputFile string + outputFile string + packageName string +} + +func readAST(data []byte) []string { + uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{}) + return strings.Split(string(uncolored), "\n") +} + +type treeNode struct { + indent int + node ast.Node +} + +func convertLinesToNodes(lines []string) []treeNode { + nodes := []treeNode{} + for _, line := range lines { + if strings.TrimSpace(line) == "" { + continue + } + + // It is tempting to discard null AST nodes, but these may + // have semantic importance: for example, they represent omitted + // for-loop conditions, as in for(;;). + line = strings.Replace(line, "<<>>", "NullStmt", 1) + + indentAndType := regexp.MustCompile("^([|\\- `]*)(\\w+)").FindStringSubmatch(line) + if len(indentAndType) == 0 { + panic(fmt.Sprintf("Cannot understand line '%s'", line)) + } + + offset := len(indentAndType[1]) + node := ast.Parse(line[offset:]) + + indentLevel := len(indentAndType[1]) / 2 + nodes = append(nodes, treeNode{indentLevel, node}) + } + + return nodes +} + +// buildTree convert an array of nodes, each prefixed with a depth into a tree. +func buildTree(nodes []treeNode, depth int) []ast.Node { + if len(nodes) == 0 { + return []ast.Node{} + } + + // Split the list into sections, treat each section as a a tree with its own root. + sections := [][]treeNode{} + for _, node := range nodes { + if node.indent == depth { + sections = append(sections, []treeNode{node}) + } else { + sections[len(sections)-1] = append(sections[len(sections)-1], node) + } + } + + results := []ast.Node{} + for _, section := range sections { + slice := []treeNode{} + for _, n := range section { + if n.indent > depth { + slice = append(slice, n) + } + } + + children := buildTree(slice, depth+1) + for _, child := range children { + section[0].node.AddChild(child) + } + results = append(results, section[0].node) + } + + return results +} + +// ToJSON - tree convert to JSON +func ToJSON(tree []interface{}) []map[string]interface{} { + r := make([]map[string]interface{}, len(tree)) + + for j, n := range tree { + rn := reflect.ValueOf(n).Elem() + r[j] = make(map[string]interface{}) + r[j]["node"] = rn.Type().Name() + + for i := 0; i < rn.NumField(); i++ { + name := strings.ToLower(rn.Type().Field(i).Name) + value := rn.Field(i).Interface() + + if name == "children" { + v := value.([]interface{}) + + if len(v) == 0 { + continue + } + + value = ToJSON(v) + } + + r[j][name] = value + } + } + + return r +} + +// Start - base function +func Start(args ProgramArgs) error { + if os.Getenv("GOPATH") == "" { + panic("The $GOPATH must be set.") + } + + // 1. Compile it first (checking for errors) + _, err := os.Stat(args.inputFile) + if err != nil { + return fmt.Errorf("Input file is not found") + } + + // 2. Preprocess + var pp []byte + { + cmd := exec.Command("clang", "-E", args.inputFile) + var out bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + err = cmd.Run() + if err != nil { + return fmt.Errorf("preprocess failed: %v\nStdErr = %v", err, stderr.String()) + } + pp = []byte(out.String()) + } + + ppFilePath := path.Join(os.TempDir(), "pp.c") + err = ioutil.WriteFile(ppFilePath, pp, 0644) + if err != nil { + return fmt.Errorf("writing to /tmp/pp.c failed: %v", err) + } + + // 3. Generate JSON from AST + astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output() + if err != nil { + // If clang fails it still prints out the AST, so we have to run it + // again to get the real error. + errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput() + + panic("clang failed: " + err.Error() + ":\n\n" + string(errBody)) + } + + lines := readAST(astPP) + if args.ast { + for _, l := range lines { + fmt.Println(l) + } + fmt.Println() + } + + nodes := convertLinesToNodes(lines) + tree := buildTree(nodes, 0) + + p := program.NewProgram() + p.Verbose = args.verbose + + err = transpiler.TranspileAST(args.inputFile, args.packageName, p, tree[0].(ast.Node)) + if err != nil { + panic(err) + } + + outputFilePath := args.outputFile + + if outputFilePath == "" { + cleanFileName := filepath.Clean(filepath.Base(args.inputFile)) + extension := filepath.Ext(args.inputFile) + + outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go" + } + + err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0755) + if err != nil { + return fmt.Errorf("writing C output file failed: %v", err) + } + + return nil +} func main() { var ( versionFlag = flag.Bool("v", false, "print the version and exit") @@ -52,7 +251,7 @@ func main() { os.Exit(1) } - args := analyze.ProgramArgs{Verbose: *verboseFlag, Ast: false} + args := ProgramArgs{verbose: *verboseFlag, ast: false} switch os.Args[1] { case "ast": @@ -68,10 +267,10 @@ func main() { os.Exit(1) } - args.Ast = true - args.InputFile = astCommand.Arg(0) + args.ast = true + args.inputFile = astCommand.Arg(0) - if err = analyze.Start(args); err != nil { + if err = Start(args); err != nil { fmt.Printf("Error: %v", err) os.Exit(1) } @@ -88,11 +287,11 @@ func main() { os.Exit(1) } - args.InputFile = transpileCommand.Arg(0) - args.OutputFile = *outputFlag - args.PackageName = *packageFlag + args.inputFile = transpileCommand.Arg(0) + args.outputFile = *outputFlag + args.packageName = *packageFlag - if err = analyze.Start(args); err != nil { + if err = Start(args); err != nil { fmt.Printf("Error: %v", err) os.Exit(1) } diff --git a/main_test.go b/main_test.go index b2c27e281..e64167b01 100644 --- a/main_test.go +++ b/main_test.go @@ -15,7 +15,6 @@ import ( "regexp" - "github.com/elliotchance/c2go/analyze" "github.com/elliotchance/c2go/util" ) @@ -83,14 +82,14 @@ func TestIntegrationScripts(t *testing.T) { err = cmd.Run() cProgram.isZero = err == nil - programArgs := analyze.ProgramArgs{ - InputFile: file, - OutputFile: "build/main.go", - PackageName: "main", + programArgs := ProgramArgs{ + inputFile: file, + outputFile: "build/main.go", + packageName: "main", } // Compile Go - analyze.Start(programArgs) + Start(programArgs) buildErr, err := exec.Command("go", "build", "-o", goPath, "build/main.go").CombinedOutput() if err != nil { @@ -154,3 +153,45 @@ func TestIntegrationScripts(t *testing.T) { fmt.Printf("TAP: # Total tests: %d\n", totalTapTests) } } + +func TestStartPreprocess(t *testing.T) { + // temp dir + tempDir := os.TempDir() + + // create temp file with garantee + // wrong file body + tempFile, err := New(tempDir, "c2go", "preprocess.c") + if err != nil { + t.Errorf("Cannot create temp file for execute test") + } + defer func() { + _ = os.Remove(tempFile.Name()) + }() + + fmt.Fprintf(tempFile, "#include \nint main(void){\nwrong\n}") + + err = tempFile.Close() + if err != nil { + t.Errorf("Cannot close the temp file") + } + + var args ProgramArgs + args.inputFile = tempFile.Name() + + err = Start(args) + if err == nil { + t.Errorf("Cannot test preprocess of application") + } +} + +// New returns an unused filename for output files. +func New(dir, prefix, suffix string) (*os.File, error) { + for index := 1; index < 10000; index++ { + path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix)) + if _, err := os.Stat(path); err != nil { + return os.Create(path) + } + } + // Give up + return nil, fmt.Errorf("could not create file of the form %s%03d%s", prefix, 1, suffix) +} From cca8b9bac0d370432d5e21de3efd939629bf1afd Mon Sep 17 00:00:00 2001 From: konstantin8105 Date: Wed, 21 Jun 2017 23:15:41 +0300 Subject: [PATCH 12/16] Add test for GOPATH. Fix #159. Fix #168 --- main.go | 15 ++++++++++++++- main_test.go | 35 ++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index ca2395ba4..23fe5a513 100644 --- a/main.go +++ b/main.go @@ -140,7 +140,7 @@ func ToJSON(tree []interface{}) []map[string]interface{} { // Start - base function func Start(args ProgramArgs) error { if os.Getenv("GOPATH") == "" { - panic("The $GOPATH must be set.") + return fmt.Errorf("The $GOPATH must be set") } // 1. Compile it first (checking for errors) @@ -159,6 +159,7 @@ func Start(args ProgramArgs) error { cmd.Stderr = &stderr err = cmd.Run() if err != nil { + // TODO: try to find broken include headers return fmt.Errorf("preprocess failed: %v\nStdErr = %v", err, stderr.String()) } pp = []byte(out.String()) @@ -215,6 +216,18 @@ func Start(args ProgramArgs) error { return nil } + +// NewTempFile - returns temp file +func NewTempFile(dir, prefix, suffix string) (*os.File, error) { + for index := 1; index < 10000; index++ { + path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix)) + if _, err := os.Stat(path); err != nil { + return os.Create(path) + } + } + return nil, fmt.Errorf("could not create file of the form %s%03d%s", prefix, 1, suffix) +} + func main() { var ( versionFlag = flag.Bool("v", false, "print the version and exit") diff --git a/main_test.go b/main_test.go index e64167b01..d5ab7984e 100644 --- a/main_test.go +++ b/main_test.go @@ -160,7 +160,7 @@ func TestStartPreprocess(t *testing.T) { // create temp file with garantee // wrong file body - tempFile, err := New(tempDir, "c2go", "preprocess.c") + tempFile, err := NewTempFile(tempDir, "c2go", "preprocess.c") if err != nil { t.Errorf("Cannot create temp file for execute test") } @@ -184,14 +184,31 @@ func TestStartPreprocess(t *testing.T) { } } -// New returns an unused filename for output files. -func New(dir, prefix, suffix string) (*os.File, error) { - for index := 1; index < 10000; index++ { - path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix)) - if _, err := os.Stat(path); err != nil { - return os.Create(path) +func TestGoPath(t *testing.T) { + gopath := "GOPATH" + + existEnv := os.Getenv(gopath) + if existEnv == "" { + t.Errorf("Please create value $GOPATH of the environment variable") + } + + // reset value of env.var. + err := os.Setenv(gopath, "") + if err != nil { + t.Errorf("Cannot set value of the environment variable") + } + + // return env.var. + defer func() { + err = os.Setenv(gopath, existEnv) + if err != nil { + t.Errorf("Please create value $GOPATH of the environment variable") } + }() + + // testing + err = Start(*(new(ProgramArgs))) + if err == nil { + t.Errorf("We have to check $GOPATH") } - // Give up - return nil, fmt.Errorf("could not create file of the form %s%03d%s", prefix, 1, suffix) } From 1f91d8283df40bb115bb6e25740eee256006dc62 Mon Sep 17 00:00:00 2001 From: konstantin8105 Date: Wed, 21 Jun 2017 23:17:10 +0300 Subject: [PATCH 13/16] Remove TODO --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index 23fe5a513..53b0f8da6 100644 --- a/main.go +++ b/main.go @@ -159,7 +159,6 @@ func Start(args ProgramArgs) error { cmd.Stderr = &stderr err = cmd.Run() if err != nil { - // TODO: try to find broken include headers return fmt.Errorf("preprocess failed: %v\nStdErr = %v", err, stderr.String()) } pp = []byte(out.String()) From 24a2550a24b3298b1f0338d7494de8a09529da29 Mon Sep 17 00:00:00 2001 From: konstantin8105 Date: Wed, 21 Jun 2017 23:23:55 +0300 Subject: [PATCH 14/16] add myself to LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index d26aa18a6..c28ba9a87 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Elliot Chance +Copyright (c) 2017 Elliot Chance, Izyumov Konstantin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 331db044f9f6a1748e79b5131eadf321e0393548 Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Thu, 22 Jun 2017 14:02:28 +0300 Subject: [PATCH 15/16] Changes in according to review comments --- .gitignore | 7 +------ LICENSE | 2 +- main.go | 25 ++++++++++--------------- main_test.go | 33 +++++++++++++++++---------------- 4 files changed, 29 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index d226169f9..0d5e453a6 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,4 @@ /coverage.txt /c2go /.vscode -*.coverprofile - -# Vim backups -*.go~ -*.go.swp -*.un~ +*.coverprofile \ No newline at end of file diff --git a/LICENSE b/LICENSE index c28ba9a87..d26aa18a6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Elliot Chance, Izyumov Konstantin +Copyright (c) 2017 Elliot Chance Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/main.go b/main.go index 53b0f8da6..7cedc0a1c 100644 --- a/main.go +++ b/main.go @@ -216,15 +216,15 @@ func Start(args ProgramArgs) error { return nil } -// NewTempFile - returns temp file -func NewTempFile(dir, prefix, suffix string) (*os.File, error) { +// newTempFile - returns temp file +func newTempFile(dir, prefix, suffix string) (*os.File, error) { for index := 1; index < 10000; index++ { path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix)) if _, err := os.Stat(path); err != nil { return os.Create(path) } } - return nil, fmt.Errorf("could not create file of the form %s%03d%s", prefix, 1, suffix) + return nil, fmt.Errorf("could not create file: %s%03d%s", prefix, 1, suffix) } func main() { @@ -269,7 +269,7 @@ func main() { case "ast": err := astCommand.Parse(os.Args[2:]) if err != nil { - fmt.Printf("Ast command cannot parse: %v", err) + fmt.Printf("ast command cannot parse: %v", err) os.Exit(1) } @@ -281,15 +281,10 @@ func main() { args.ast = true args.inputFile = astCommand.Arg(0) - - if err = Start(args); err != nil { - fmt.Printf("Error: %v", err) - os.Exit(1) - } case "transpile": err := transpileCommand.Parse(os.Args[2:]) if err != nil { - fmt.Printf("Transpile command cannot parse: %v", err) + fmt.Printf("transpile command cannot parse: %v", err) os.Exit(1) } @@ -302,13 +297,13 @@ func main() { args.inputFile = transpileCommand.Arg(0) args.outputFile = *outputFlag args.packageName = *packageFlag - - if err = Start(args); err != nil { - fmt.Printf("Error: %v", err) - os.Exit(1) - } default: flag.Usage() os.Exit(1) } + + if err := Start(args); err != nil { + fmt.Printf("Error: %v", err) + os.Exit(1) + } } diff --git a/main_test.go b/main_test.go index d5ab7984e..b787bac02 100644 --- a/main_test.go +++ b/main_test.go @@ -89,7 +89,10 @@ func TestIntegrationScripts(t *testing.T) { } // Compile Go - Start(programArgs) + err = Start(programArgs) + if err != nil { + t.Fatalf("error: %s\n%s", err, out) + } buildErr, err := exec.Command("go", "build", "-o", goPath, "build/main.go").CombinedOutput() if err != nil { @@ -160,15 +163,13 @@ func TestStartPreprocess(t *testing.T) { // create temp file with garantee // wrong file body - tempFile, err := NewTempFile(tempDir, "c2go", "preprocess.c") + tempFile, err := newTempFile(tempDir, "c2go", "preprocess.c") if err != nil { t.Errorf("Cannot create temp file for execute test") } - defer func() { - _ = os.Remove(tempFile.Name()) - }() + defer os.Remove(tempFile.Name()) - fmt.Fprintf(tempFile, "#include \nint main(void){\nwrong\n}") + fmt.Fprintf(tempFile, "#include \nint main(void){\nwrong();\n}") err = tempFile.Close() if err != nil { @@ -189,26 +190,26 @@ func TestGoPath(t *testing.T) { existEnv := os.Getenv(gopath) if existEnv == "" { - t.Errorf("Please create value $GOPATH of the environment variable") - } - - // reset value of env.var. - err := os.Setenv(gopath, "") - if err != nil { - t.Errorf("Cannot set value of the environment variable") + t.Errorf("$GOPATH is not set") } // return env.var. defer func() { err = os.Setenv(gopath, existEnv) if err != nil { - t.Errorf("Please create value $GOPATH of the environment variable") + t.Errorf("Cannot restore the value of $GOPATH") } }() + // reset value of env.var. + err := os.Setenv(gopath, "") + if err != nil { + t.Errorf("Cannot set value of $GOPATH") + } + // testing - err = Start(*(new(ProgramArgs))) + err = Start(&ProgramArgs{}) if err == nil { - t.Errorf("We have to check $GOPATH") + t.Errorf(err.Error()) } } From 0e5375f0feff44e50de62dff40fa8f6bd723f49d Mon Sep 17 00:00:00 2001 From: Konstantin8105 Date: Thu, 22 Jun 2017 14:15:12 +0300 Subject: [PATCH 16/16] code review --- main_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main_test.go b/main_test.go index b787bac02..ae77ae060 100644 --- a/main_test.go +++ b/main_test.go @@ -195,7 +195,7 @@ func TestGoPath(t *testing.T) { // return env.var. defer func() { - err = os.Setenv(gopath, existEnv) + err := os.Setenv(gopath, existEnv) if err != nil { t.Errorf("Cannot restore the value of $GOPATH") } @@ -208,7 +208,7 @@ func TestGoPath(t *testing.T) { } // testing - err = Start(&ProgramArgs{}) + err = Start(ProgramArgs{}) if err == nil { t.Errorf(err.Error()) }