Repository: Konstantin8105/c4go
Pull request #310 (2019-03-11 21:11:46)

iteration by array 2D

codecov[bot]: # [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/310?src=pr&el=h1) Report
> Merging [#310](https://codecov.io/gh/Konstantin8105/c4go/pull/310?src=pr&el=desc) into [master](https://codecov.io/gh/Konstantin8105/c4go/commit/9a8c233cf6d029268b0aece2dad05918625afe89?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/Konstantin8105/c4go/pull/310/graphs/tree.svg?width=650&token=esH2rHXlZ2&height=150&src=pr)](https://codecov.io/gh/Konstantin8105/c4go/pull/310?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #310      +/-   ##
==========================================
+ Coverage   86.58%   86.59%   +0.01%     
==========================================
  Files         184      184              
  Lines       10437    10447      +10     
==========================================
+ Hits         9037     9047      +10     
  Misses        982      982              
  Partials      418      418
```


| [Impacted Files](https://codecov.io/gh/Konstantin8105/c4go/pull/310?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [transpiler/variables.go](https://codecov.io/gh/Konstantin8105/c4go/pull/310/diff?src=pr&el=tree#diff-dHJhbnNwaWxlci92YXJpYWJsZXMuZ28=) | `84.86% <ø> (ø)` | :arrow_up: |
| [transpiler/binary.go](https://codecov.io/gh/Konstantin8105/c4go/pull/310/diff?src=pr&el=tree#diff-dHJhbnNwaWxlci9iaW5hcnkuZ28=) | `72.31% <ø> (ø)` | :arrow_up: |
| [transpiler/scope.go](https://codecov.io/gh/Konstantin8105/c4go/pull/310/diff?src=pr&el=tree#diff-dHJhbnNwaWxlci9zY29wZS5nbw==) | `89.65% <100%> (+1.9%)` | :arrow_up: |
| [util/goast.go](https://codecov.io/gh/Konstantin8105/c4go/pull/310/diff?src=pr&el=tree#diff-dXRpbC9nb2FzdC5nbw==) | `92.42% <100%> (+0.02%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/310?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/310?src=pr&el=footer). Last update [9a8c233...7a1af1f](https://codecov.io/gh/Konstantin8105/c4go/pull/310?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/transpiler/binary.go b/transpiler/binary.go
index bc81bcb..268c603 100644
--- a/transpiler/binary.go
+++ b/transpiler/binary.go
@@ -79,13 +79,13 @@ func transpileBinaryOperator(n *ast.BinaryOperator, p *program.Program, exprIsSt
 	}()
 
 	// Char overflow
-	// BinaryOperator 0x2b74458 <line:506:7, col:18> 'int' '!='
-	// |-ImplicitCastExpr 0x2b74440 <col:7, col:10> 'int' <IntegralCast>
-	// | `-ImplicitCastExpr 0x2b74428 <col:7, col:10> 'char' <LValueToRValue>
+	// BinaryOperator  'int' '!='
+	// |-ImplicitCastExpr 'int' <IntegralCast>
+	// | `-ImplicitCastExpr 'char' <LValueToRValue>
 	// |   `-...
-	// `-ParenExpr 0x2b74408 <col:15, col:18> 'int'
-	//   `-UnaryOperator 0x2b743e8 <col:16, col:17> 'int' prefix '-'
-	//     `-IntegerLiteral 0x2b743c8 <col:17> 'int' 1
+	// `-ParenExpr 'int'
+	//   `-UnaryOperator 'int' prefix '-'
+	//     `-IntegerLiteral 'int' 1
 	if n.Operator == "!=" {
 		var leftOk bool
 		if l0, ok := n.ChildNodes[0].(*ast.ImplicitCastExpr); ok && l0.Type == "int" {
diff --git a/transpiler/scope.go b/transpiler/scope.go
index 6f1a0a5..de036d1 100644
--- a/transpiler/scope.go
+++ b/transpiler/scope.go
@@ -31,6 +31,14 @@ func transpileCompoundStmt(n *ast.CompoundStmt, p *program.Program) (
 			}
 		}
 
+		// add '_ = '
+		var addPrefix bool
+		if impl, ok := x.(*ast.ImplicitCastExpr); ok && len(impl.Children()) == 1 {
+			if _, ok := impl.Children()[0].(*ast.ArraySubscriptExpr); ok {
+				addPrefix = true
+			}
+		}
+
 		var result []goast.Stmt
 		switch {
 		case isVaList:
@@ -49,6 +57,7 @@ func transpileCompoundStmt(n *ast.CompoundStmt, p *program.Program) (
 					},
 				},
 			}
+
 		default:
 			// Other cases
 			if parent, ok := x.(*ast.ParenExpr); ok {
@@ -58,6 +67,14 @@ func transpileCompoundStmt(n *ast.CompoundStmt, p *program.Program) (
 			if err != nil {
 				return nil, nil, nil, err
 			}
+			if addPrefix && len(result) == 1 {
+				// goast.Print(token.NewFileSet(), result[0])
+				result[0] = &goast.AssignStmt{
+					Lhs: []goast.Expr{goast.NewIdent("_")},
+					Tok: token.ASSIGN,
+					Rhs: []goast.Expr{result[0].(*goast.ExprStmt).X},
+				}
+			}
 		}
 
 		if result != nil {
diff --git a/transpiler/variables.go b/transpiler/variables.go
index 85791cc..2b26306 100644
--- a/transpiler/variables.go
+++ b/transpiler/variables.go
@@ -330,6 +330,12 @@ func transpileArraySubscriptExpr(n *ast.ArraySubscriptExpr, p *program.Program)
 	}
 	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)
 
+	//	index, err = types.CastExpr(p, index, indexType, "int")
+	//	if err != nil {
+	//		return nil, "", nil, nil, err
+	//	}
+	//	index = util.NewCallExpr("int", index)
+
 	return &goast.IndexExpr{
 		X:     expression,
 		Index: index,
diff --git a/util/goast.go b/util/goast.go
index 730986e..4ed462f 100644
--- a/util/goast.go
+++ b/util/goast.go
@@ -304,20 +304,40 @@ func ConvertFunctionNameFromCtoGo(name string) string {
 
 // GetUintptr - return uintptr. Example : uintptr(unsafe.Pointer(&expr))
 func GetUintptr(expr goast.Expr) goast.Expr {
-	return &goast.CallExpr{
-		Fun: goast.NewIdent("uintptr"),
-		Args: []goast.Expr{
-			&goast.CallExpr{
-				Fun: goast.NewIdent("unsafe.Pointer"),
-				Args: []goast.Expr{
-					&goast.UnaryExpr{
-						Op: token.AND,
-						X:  expr,
-					},
-				},
-			},
-		},
+
+	if _, ok := expr.(*goast.SelectorExpr); ok {
+		expr = &goast.IndexExpr{
+			X:     expr,
+			Index: goast.NewIdent("0"),
+		}
 	}
+
+	if sl, ok := expr.(*goast.SliceExpr); ok {
+		if c, ok := sl.X.(*goast.CallExpr); ok {
+			if fin, ok := c.Fun.(*goast.Ident); ok && strings.Contains(fin.Name, "100000") {
+				if len(c.Args) == 1 {
+					if cc, ok := c.Args[0].(*goast.CallExpr); ok {
+						if fin, ok := cc.Fun.(*goast.Ident); ok && strings.Contains(fin.Name, "unsafe.Pointer") {
+							if len(cc.Args) == 1 {
+								if un, ok := cc.Args[0].(*goast.UnaryExpr); ok && un.Op == token.AND {
+									expr = un.X
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return NewCallExpr("uintptr",
+		NewCallExpr("unsafe.Pointer",
+			&goast.UnaryExpr{
+				Op: token.AND,
+				X:  expr,
+			},
+		),
+	)
 }
 
 // GetUintptrForSlice - return uintptr for slice
@@ -342,10 +362,7 @@ func GetUintptrForSlice(expr goast.Expr, sizeof int) (goast.Expr, string) {
 					},
 					Lparen: 1,
 					Args: []goast.Expr{&goast.CallExpr{
-						Fun: &goast.SelectorExpr{
-							X:   goast.NewIdent("unsafe"),
-							Sel: goast.NewIdent("Pointer"),
-						},
+						Fun:    goast.NewIdent("unsafe.Pointer"),
 						Lparen: 1,
 						Args: []goast.Expr{&goast.UnaryExpr{
 							Op: token.AND,
@@ -378,17 +395,13 @@ func CreateSliceFromReference(goType string, expr goast.Expr) goast.Expr {
 	//     p.AddImport("unsafe")
 	//
 	return &goast.SliceExpr{
-		X: NewCallExpr(
-			fmt.Sprintf("(*[100000000]%s)", goType),
-			&goast.CallExpr{
-				Fun: goast.NewIdent("unsafe.Pointer"),
-				Args: []goast.Expr{
-					&goast.UnaryExpr{
-						X:  expr,
-						Op: token.AND,
-					},
-				},
-			}),
+		X: NewCallExpr(fmt.Sprintf("(*[100000000]%s)", goType),
+			NewCallExpr("unsafe.Pointer",
+				&goast.UnaryExpr{
+					X:  expr,
+					Op: token.AND,
+				}),
+		),
 	}
 }
 


Test patch:
diff --git a/main_test.go b/main_test.go
index a4820d8..3f7c92b 100644
--- a/main_test.go
+++ b/main_test.go
@@ -17,6 +17,7 @@ import (
 	"path/filepath"
 	"strconv"
 	"strings"
+	"sync"
 	"syscall"
 	"testing"
 
@@ -96,17 +97,42 @@ func TestIntegrationScripts(t *testing.T) {
 				clangFlags = append(clangFlags, "-Itests/bind/bind.h")
 			}
 
+			var wg sync.WaitGroup
+			wg.Add(len(progs))
+			errProgs := make([]error, len(progs))
+
 			for i := 0; i < len(progs); i++ {
-				out, err := progs[i](file, subFolder, stdin, clangFlags, args)
-				if err != nil {
-					t.Fatalf("Error for function %d : %v", i, err)
-					return
+				go func(i int) {
+					defer func() {
+						wg.Done()
+					}()
+					var out string
+					out, errProgs[i] = progs[i](file, subFolder, stdin, clangFlags, args)
+					if errProgs[i] != nil {
+						errProgs[i] = fmt.Errorf("Error for function %d : %v", i, errProgs[i])
+						return
+					}
+					if out == "" {
+						errProgs[i] = fmt.Errorf("Result is empty for function %d: %v", i, errProgs[i])
+						return
+					}
+					results[i] = out
+				}(i)
+			}
+			wg.Wait()
+			{
+				fail := false
+				for i := range errProgs {
+					if errProgs[i] != nil {
+						fail = true
+					}
 				}
-				if out == "" {
-					t.Fatalf("Result is empty for function %d: %v", i, err)
-					return
+				if fail {
+					for i := range errProgs {
+						t.Errorf("%d: %v", i, errProgs[i])
+					}
+					t.Fail()
 				}
-				results[i] = out
 			}
 
 			var (
diff --git a/tests/array.c b/tests/array.c
index b6af6f8..7e53448 100644
--- a/tests/array.c
+++ b/tests/array.c
@@ -431,9 +431,110 @@ void test_function_array()
 	is_eq(y , 52);
 }
 
+void test_string_array()
+{
+	{
+		diag("point 0");
+		struct line_t{
+			struct line_t *last;
+			struct line_t *next;
+			int pos;
+		};
+		struct line_t l1;
+		l1.last = NULL;
+		l1.next = NULL;
+		struct line_t l2;
+		l2.last = &l1;
+		l2.next = NULL;
+		is_true(l2.last == &l1);
+	}
+	{
+		diag("point 1");
+		char ch_arr[3][10] = { "spike", "tom", "jerry" };
+		printf("%s\n",(*(ch_arr + 0) + 0) );
+		printf("%s\n",(*(ch_arr + 0) + 1) );
+		printf("%s\n",(*(ch_arr + 1) + 2) );
+	}
+// TODO
+// {
+// 	diag("point 2");
+// 	// see https://stackoverflow.com/questions/6812242/defining-and-iterating-through-array-of-strings-in-c
+// 	char *numbers[] = {"One", "Two", "Three", ""}, **n;
+// 	n = numbers;
+// 	while (*n != "") {
+// 	  printf ("%s\n",  *n++);
+// 	}
+// }
+	{
+		diag("point 3");
+		// see https://stackoverflow.com/questions/6812242/defining-and-iterating-through-array-of-strings-in-c
+		static const char* strings[]={"asdf","asdfasdf",0};
+		const char** ptr = strings;
+		while(*ptr != 0)
+		{
+			printf("%s \n", *ptr);
+			++ptr;
+		}
+	}
+	{
+		diag("point 4");
+		// see https://codereview.stackexchange.com/questions/71119/printing-the-contents-of-a-string-array-using-pointers
+		char *names[] = { "John", "Mona", "Lisa", "Frank" };
+		for (int i = 0; i < 4; ++i) {
+		    char *pos = names[i];
+		    while (*pos != '\0') {
+		        printf("%c", *(pos++));
+		    }
+		    printf("\n");
+		}
+	}
+	{
+		diag("point 5");
+		const char *names[] = { "John", "Mona", "Lisa", "Frank", NULL };
+		for (int i=0; names[i]; ++i) {
+		    const char *ch = names[i]; 
+		    while(*ch) {
+		        putchar(*ch++);
+		    }
+		    putchar('\n');
+		}
+	}
+	{
+		diag("point 6");
+		const char *names[] = { "John", "Mona", "Lisa", "Frank", NULL };
+		for(const char** pNames = names; *pNames; pNames++) {
+			const char *pName = *pNames;
+			while (*pName) {
+			    putchar(*pName++);
+			}
+			putchar('\n');
+		}
+	}
+	{
+		diag("point 7");
+		char *names[] = { "John", "Mona", "Lisa", "Frank" };
+		int elements = sizeof (names) / sizeof (names[0]);
+		for (int i = 0; i < elements; i++) {
+		    char *p = names[i];
+		    while (*p)
+		        putchar(*p++);
+		    putchar('\n');
+		}
+	}
+	{
+		diag("point 8");
+		int array[] = {5, 2, 9, 7, 15};
+		int i = 0;
+		array[i]++; printf("%d %d\n", i, array[i]);
+		array[i]++; printf("%d %d\n", i, array[i]);
+		array[i++]; printf("%d %d\n", i, array[i]);
+		array[i++]; printf("%d %d\n", i, array[i]);
+	}
+}
+
 int main()
 {
-    plan(173);
+    plan(174);
 
     test_parg_struct();
     START_TEST(struct_init);
@@ -944,6 +1045,7 @@ int main()
         ssize_t* l = &len;
         is_eq(*l, len);
     }
+	START_TEST(string_array);
 
     done_testing();
 }