Repository: Konstantin8105/c4go
Pull request #267 (2019-02-09 17:17:07)

New C header:wchar

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

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

```diff
@@           Coverage Diff            @@
##           master   #267      +/-   ##
========================================
+ Coverage   86.96%    87%   +0.03%     
========================================
  Files         176    177       +1     
  Lines        9676   9712      +36     
========================================
+ Hits         8415   8450      +35     
- Misses        871    872       +1     
  Partials      390    390
```


| [Impacted Files](https://codecov.io/gh/Konstantin8105/c4go/pull/267?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [program/definition\_function.go](https://codecov.io/gh/Konstantin8105/c4go/pull/267/diff?src=pr&el=tree#diff-cHJvZ3JhbS9kZWZpbml0aW9uX2Z1bmN0aW9uLmdv) | `89.53% <ø> (ø)` | :arrow_up: |
| [ast/string\_literal.go](https://codecov.io/gh/Konstantin8105/c4go/pull/267/diff?src=pr&el=tree#diff-YXN0L3N0cmluZ19saXRlcmFsLmdv) | `100% <100%> (ø)` | :arrow_up: |
| [noarch/wchar.go](https://codecov.io/gh/Konstantin8105/c4go/pull/267/diff?src=pr&el=tree#diff-bm9hcmNoL3djaGFyLmdv) | `76.92% <76.92%> (ø)` | |
| [transpiler/literals.go](https://codecov.io/gh/Konstantin8105/c4go/pull/267/diff?src=pr&el=tree#diff-dHJhbnNwaWxlci9saXRlcmFscy5nbw==) | `81.81% <78.57%> (+1.11%)` | :arrow_up: |
| [types/cast.go](https://codecov.io/gh/Konstantin8105/c4go/pull/267/diff?src=pr&el=tree#diff-dHlwZXMvY2FzdC5nbw==) | `71.74% <0%> (+2.23%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Konstantin8105/c4go/pull/267?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/267?src=pr&el=footer). Last update [be59c13...3f859cf](https://codecov.io/gh/Konstantin8105/c4go/pull/267?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index c9746a4..bab696d 100644
--- a/README.md
+++ b/README.md
@@ -135,7 +135,7 @@ func main() {
             stdlib.h	     33/47	        70.2%
             string.h	     12/24	          50%
               time.h	      7/15	        46.7%
-             wchar.h	      0/68	           0%
+             wchar.h	      3/68	        4.41%
             wctype.h	      0/22	           0%
 ```
 
diff --git a/ast/string_literal.go b/ast/string_literal.go
index 5b0d105..effea99 100644
--- a/ast/string_literal.go
+++ b/ast/string_literal.go
@@ -6,13 +6,14 @@ type StringLiteral struct {
 	Pos        Position
 	Type       string
 	Value      string
+	Runes      bool
 	IsLvalue   bool
 	ChildNodes []Node
 }
 
 func parseStringLiteral(line string) *StringLiteral {
 	groups := groupsFromRegex(
-		`<(?P<position>.*)> '(?P<type>.*)' lvalue (?P<value>".*")`,
+		`<(?P<position>.*)> '(?P<type>.*)' lvalue (?P<runes>L)?(?P<value>".*")`,
 		line,
 	)
 
@@ -22,6 +23,7 @@ func parseStringLiteral(line string) *StringLiteral {
 		Type:       groups["type"],
 		Value:      unquote(groups["value"]),
 		IsLvalue:   true,
+		Runes:      groups["runes"] != "",
 		ChildNodes: []Node{},
 	}
 }
diff --git a/noarch/wchar.go b/noarch/wchar.go
new file mode 100644
index 0000000..1d3fc64
--- /dev/null
+++ b/noarch/wchar.go
@@ -0,0 +1,50 @@
+package noarch
+
+import (
+	"strings"
+)
+
+type WcharT = rune
+
+func Wcscmp(w1, w2 []WcharT) int {
+	var len1, len2 int
+	for len1 = range w1 {
+		if rune(w1[len1]) == '\x00' {
+			break
+		}
+	}
+	for len2 = range w2 {
+		if rune(w2[len2]) == '\x00' {
+			break
+		}
+	}
+	if len1 > len2 {
+		return -1
+	}
+	if len1 < len2 {
+		return 1
+	}
+	for i := range w1 {
+		if i == len1 {
+			break
+		}
+		if r := strings.Compare(string(w1[i]), string(w2[i])); r != 0 {
+			return r
+		}
+	}
+	return 0
+}
+
+func Wcscpy(w1, w2 []WcharT) []WcharT {
+	for i, c := range w2 {
+		w1[i] = WcharT(rune(c))
+		if rune(w2[i]) == '\x00' {
+			break
+		}
+	}
+	return w2
+}
+
+func Wcslen(w []WcharT) int {
+	return len(w)
+}
diff --git a/program/definition_function.go b/program/definition_function.go
index 81ef181..236c259 100644
--- a/program/definition_function.go
+++ b/program/definition_function.go
@@ -233,6 +233,12 @@ var builtInFunctionDefinitions = map[string][]string{
 		"int vsprintf(char*, const char *, ...) -> noarch.Vsprintf",
 		"int vsnprintf(char*, int, const char *, ...) -> noarch.Vsnprintf",
 	},
+	"wchar.h": {
+		// wchar.h
+		"wchar_t * wcscpy(wchar_t*, const wchar_t*) -> noarch.Wcscpy",
+		"int wcscmp(const wchar_t*, const wchar_t*) -> noarch.Wcscmp",
+		"size_t wcslen(const wchar_t*) -> noarch.Wcslen",
+	},
 	"string.h": {
 		// string.h
 		"char* strcat(char *, const char *) -> noarch.Strcat",
diff --git a/program/definition_type.go b/program/definition_type.go
index da8d361..7ea9347 100644
--- a/program/definition_type.go
+++ b/program/definition_type.go
@@ -40,6 +40,7 @@ var DefinitionType = map[string]string{
 	"_Bool":                  "int",
 	"size_t":                 "uint",
 	"ptrdiff_t":              "github.com/Konstantin8105/c4go/noarch.PtrdiffT",
+	"wchar_t":                "github.com/Konstantin8105/c4go/noarch.WcharT",
 
 	// void*
 	"void*":  "interface{}",
diff --git a/transpiler/literals.go b/transpiler/literals.go
index fdd8943..60422c1 100644
--- a/transpiler/literals.go
+++ b/transpiler/literals.go
@@ -60,8 +60,10 @@ func transpileStringLiteral(p *program.Program, n *ast.StringLiteral, arrayToArr
 	// Example:
 	// StringLiteral 0x280b918 <col:29> 'char [30]' lvalue "%0"
 	baseType := types.GetBaseType(n.Type)
-	if baseType != "char" {
-		err = fmt.Errorf("Type is not `char` : %v", n.Type)
+	if baseType != "char" &&
+		!strings.Contains(baseType, "int") &&
+		!strings.Contains(baseType, "wchar_t") {
+		err = fmt.Errorf("Type is not valid : %v", n.Type)
 		p.AddMessage(p.GenerateWarningMessage(err, n))
 		return
 	}
@@ -72,15 +74,23 @@ func transpileStringLiteral(p *program.Program, n *ast.StringLiteral, arrayToArr
 			expr = util.NewCallExpr("[]byte",
 				util.NewStringLit(strconv.Quote(n.Value+"\x00")))
 			exprType = "const char *"
+			err = nil // ignore error
 			return
 		}
 		buf := bytes.NewBufferString(n.Value + "\x00")
 		if buf.Len() < s {
 			buf.Write(make([]byte, s-buf.Len()))
 		}
-		expr = util.NewCallExpr("[]byte",
-			util.NewStringLit(strconv.Quote(buf.String())))
-		exprType = "const char *"
+		switch {
+		case strings.Contains(baseType, "int"), strings.Contains(baseType, "wchar_t"):
+			expr = util.NewCallExpr("[]rune",
+				util.NewStringLit(strconv.Quote(buf.String())))
+			exprType = "const wchar_t *"
+		default:
+			expr = util.NewCallExpr("[]byte",
+				util.NewStringLit(strconv.Quote(buf.String())))
+			exprType = "const char *"
+		}
 		return
 	}
 	// Example:


Test patch:
diff --git a/ast/string_literal_test.go b/ast/string_literal_test.go
index d0f7340..755215f 100644
--- a/ast/string_literal_test.go
+++ b/ast/string_literal_test.go
@@ -27,9 +27,19 @@ func TestStringLiteral(t *testing.T) {
 			Pos:        NewPositionFromString("col:14"),
 			Type:       "char [14]",
 			IsLvalue:   true,
+			Runes:      false,
 			Value:      "x\vx\x00xxx\axx\tx\n",
 			ChildNodes: []Node{},
 		},
+		`0x3ed1658 <col:16> 'int [16]' lvalue L"copy successful"`: &StringLiteral{
+			Addr:       0x3ed1658,
+			Pos:        NewPositionFromString("col:16"),
+			Type:       "int [16]",
+			IsLvalue:   true,
+			Runes:      true,
+			Value:      "copy successful",
+			ChildNodes: []Node{},
+		},
 	}
 
 	runNodeTests(t, nodes)
diff --git a/tests/if.c b/tests/if.c
index 29fed43..2b32f7c 100644
--- a/tests/if.c
+++ b/tests/if.c
@@ -8,7 +8,7 @@ int d(int v)
 
 int main()
 {
-    plan(22);
+    plan(23);
 
     int x = 1;
 
@@ -161,5 +161,12 @@ int main()
 	(void)(esc) ;
 	(void)(esct);
 
+	int *y = NULL;
+	if ((y = (int*)calloc(1,sizeof(int))) != NULL){
+		pass("y");
+	} else {
+        fail("y");
+	}
+
     done_testing();
 }
diff --git a/tests/tests.h b/tests/tests.h
index 38af708..655ba85 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -1,6 +1,7 @@
 #include <string.h> // strlen()
-#include <math.h> // signbit()
-#include <stdio.h> // printf()
+#include <math.h>   // signbit()
+#include <stdio.h>  // printf()
+#include <wchar.h>  // wcscmp()
 
 // When comparing floating-point numbers this is how many significant bits will
 // be used to calculate the epsilon.
@@ -190,6 +191,18 @@ static int last_test_was_ok = 1;
             strlen(#actual), #expected, strlen(#expected), actual) \
     }
 
+// Compare two C wchars
+#define is_wchareq(actual, expected)                               \
+    if (wcscmp(actual, expected) == 0)                             \
+    {                                                              \
+        pass("%s == %s", #actual, #expected)                       \
+    }                                                              \
+    else                                                           \
+    {                                                              \
+        fail("%s (%d b) == %s (%d b) # got \"%s\"", #actual,       \
+            strlen(#actual), #expected, strlen(#expected), actual) \
+    }
+
 // Check that a floating-point value is Not A Number. Passing a value that is
 // not floating point may lead to undefined behaviour.
 #define is_nan(actual)                              \
diff --git a/tests/wchar.c b/tests/wchar.c
new file mode 100644
index 0000000..0b2a46d
--- /dev/null
+++ b/tests/wchar.c
@@ -0,0 +1,31 @@
+#include "tests.h"
+#include <wchar.h>
+
+int main() {
+	plan(5);
+
+	{
+		diag("wcscmp");
+		wchar_t wsKey[] = L"jilia";
+		if (wcscmp(wsKey,L"jilia") == 0){
+			pass("0k - equal");
+		}
+		if (wcscmp(wsKey,L"jiiia") != 0){
+			pass("0k - not equal");
+		}
+	}
+
+	{
+		diag("wcscpy");
+		wchar_t wcs1[]=L"Sample string";
+		wchar_t wcs2[40];
+		wchar_t wcs3[40];
+		wcscpy (wcs2,wcs1);
+		wcscpy (wcs3,L"copy successful");
+		is_wchareq(wcs1,L"Sample string");
+		is_wchareq(wcs2,L"Sample string");
+		is_wchareq(wcs3,L"copy successful");
+	}
+
+	done_testing();
+}