Repository: Konstantin8105/c4go
Pull request #282 (2019-02-25 12:32:45)

CSTD and unistd


Patch:
diff --git a/.travis.yml b/.travis.yml
index c600546..eb66abc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,6 +57,9 @@ before_install:
 
   # code style
   - go get -u -v github.com/Konstantin8105/cs
+  
+  # for tests
+  - go get -u -v golang.org/x/sys/unix
 
   # install gometalinter
   # - go get -u github.com/alecthomas/gometalinter
diff --git a/README.md b/README.md
index 32b5604..ced67fb 100644
--- a/README.md
+++ b/README.md
@@ -131,9 +131,9 @@ func main() {
             signal.h	       0/3	           0%
             stdarg.h	       4/4	         100%
             stddef.h	       2/6	        33.3%
-             stdio.h	     33/46	        71.7%
+             stdio.h	     35/46	        76.1%
             stdlib.h	     33/47	        70.2%
-            string.h	     14/24	        58.3%
+            string.h	     16/24	        66.7%
               time.h	      7/15	        46.7%
              wchar.h	      3/68	        4.41%
             wctype.h	      0/22	           0%
diff --git a/noarch/fcntl.go b/noarch/fcntl.go
index 973a727..329e4a7 100644
--- a/noarch/fcntl.go
+++ b/noarch/fcntl.go
@@ -4,14 +4,13 @@ import "golang.org/x/sys/unix"
 
 type Flock = unix.Flock_t
 
-func OpenM(pathname []byte, flags int, mode int) int {
-	fd, err := unix.Open(CStringToString(pathname), flags, uint32(mode))
+func Open(pathname []byte, flags int, mode ...int) int {
+	if len(mode) == 0 {
+		mode = append(mode, 644)
+	}
+	fd, err := unix.Open(CStringToString(pathname), flags, uint32(mode[0]))
 	if err != nil {
 		return -1
 	}
 	return fd
 }
-
-func Open(pathname []byte, flags int) int {
-	return OpenM(pathname, flags, 644)
-}
diff --git a/noarch/stdio.go b/noarch/stdio.go
index 8d1af6b..0d7cc8e 100644
--- a/noarch/stdio.go
+++ b/noarch/stdio.go
@@ -697,6 +697,13 @@ func Scanf(format []byte, args ...interface{}) int {
 	return n
 }
 
+func Sscanf(str []byte, format []byte, args ...interface{}) int {
+	realArgs := prepareArgsForScanf(args)
+	n, _ := fmt.Sscanf(CStringToString(str), CStringToString(format), realArgs...)
+	finalizeArgsForScanf(realArgs, args)
+	return n
+}
+
 // Putchar handles putchar().
 //
 // Writes a character to the standard output (stdout).
@@ -807,3 +814,25 @@ func Vsnprintf(buffer []byte, n int, format []byte, varList ...interface{}) int
 	n = len(result)
 	return n
 }
+
+func Perror(msg []byte) {
+	m := CStringToString(msg)
+	fmt.Fprintf(os.Stderr, "%s: No such file or directory\n", m)
+}
+
+func Getline(line [][]byte, len []uint, f *File) SsizeT {
+	counter := 0
+	for {
+		buf := make([]byte, 1)
+		_, err := f.OsFile.Read(buf)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			break
+		}
+		line[0] = append(line[0], buf...)
+		counter++
+	}
+	return SsizeT(counter)
+}
diff --git a/noarch/string.go b/noarch/string.go
index b7b084f..84097fc 100644
--- a/noarch/string.go
+++ b/noarch/string.go
@@ -148,11 +148,13 @@ func Memset(ptr []byte, value byte, num uint32) []byte {
 }
 
 // Memmove move block of memory
-func Memmove(ptr []byte, source []byte, num uint32) []byte {
+func Memmove(ptr, source interface{}, num uint32) interface{} {
+	p1 := ptr.([]byte)
+	p2 := source.([]byte)
 	for i := int(num); i >= 0; i-- {
-		ptr[i] = source[i]
+		p1[i] = p2[i]
 	}
-	return ptr
+	return p1
 }
 
 // Memcmp - compare two buffers
@@ -191,3 +193,11 @@ func Strrchr(source []byte, c int) []byte {
 	}
 	return source
 }
+
+func Strdup(s []byte) []byte {
+	return s
+}
+
+func Strerror(e int) []byte {
+	return []byte("strerror")
+}
diff --git a/noarch/unistd.go b/noarch/unistd.go
index 661e8fa..2cf2fd6 100644
--- a/noarch/unistd.go
+++ b/noarch/unistd.go
@@ -1,3 +1,46 @@
 package noarch
 
+import (
+	"fmt"
+	"os"
+
+	"golang.org/x/sys/unix"
+)
+
+func Isatty(fd int) int {
+	_, err := unix.IoctlGetTermios(fd, unix.TCGETS)
+	// TODO need test
+	if err != nil {
+		return 0
+	}
+	return 1
+}
+
+func Pipe(p []int) int {
+	err := unix.Pipe(p)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "%v", err)
+		return -1
+	}
+	return 0
+}
+
+func Read(fd int, p []byte, num int) SsizeT {
+	n, err := unix.Read(fd, p)
+	_ = num
+	if err != nil {
+		return SsizeT(-1)
+	}
+	return SsizeT(n)
+}
+
+func Write(fd int, p []byte, num uint) SsizeT {
+	n, err := unix.Write(fd, p)
+	_ = num
+	if err != nil {
+		return SsizeT(-1)
+	}
+	return SsizeT(n)
+}
+
 type SsizeT int32
diff --git a/program/definition_function.go b/program/definition_function.go
index dbc6136..15198d1 100644
--- a/program/definition_function.go
+++ b/program/definition_function.go
@@ -232,6 +232,9 @@ var builtInFunctionDefinitions = map[string][]string{
 		"int snprintf(char*, int, const char *, ...) -> noarch.Snprintf",
 		"int vsprintf(char*, const char *, ...) -> noarch.Vsprintf",
 		"int vsnprintf(char*, int, const char *, ...) -> noarch.Vsnprintf",
+		"void perror( const char *) -> noarch.Perror",
+		"ssize_t getline(char **, size_t *, FILE *) -> noarch.Getline",
+		"int sscanf( const char *, const char *, ...) -> noarch.Sscanf",
 	},
 	"wchar.h": {
 		// wchar.h
@@ -262,6 +265,8 @@ var builtInFunctionDefinitions = map[string][]string{
 		"int memcmp(const char *, const char *, unsigned int) -> noarch.Memcmp",
 		"void * memcpy(void *, const void *, size_t) -> noarch.Memcpy",
 		"const char * strrchr( const char *, int) -> noarch.Strrchr",
+		"char * strdup(const char *) -> noarch.Strdup",
+		"char * strerror(int ) -> noarch.Strerror",
 	},
 	"stdlib.h": {
 		// stdlib.h
@@ -325,8 +330,15 @@ var builtInFunctionDefinitions = map[string][]string{
 		"int gettimeofday(struct timeval *, struct timezone *) -> noarch.Gettimeofday",
 	},
 	"fcntl.h": {
-		"int open(const char *, int , mode_t ) -> noarch.OpenM",
-		"int open(const char *, int ) -> noarch.Open",
+		"int open(const char *, int , ...) -> noarch.Open",
+	},
+	"unistd.h": {
+		"int pipe(int *) -> noarch.Pipe",
+		"void exit(int) -> golang.org/x/sys/unix.Exit",
+		"ssize_t write(int, const void *, size_t) -> noarch.Write",
+		"ssize_t read(int, void *, size_t) -> noarch.Read",
+		"int close(int) -> golang.org/x/sys/unix.CloseOnExec",
+		"int isatty(int) -> noarch.Isatty",
 	},
 }
 
diff --git a/transpiler/unary.go b/transpiler/unary.go
index 9d24103..e8cdcc0 100644
--- a/transpiler/unary.go
+++ b/transpiler/unary.go
@@ -232,9 +232,13 @@ func transpileUnaryOperatorNot(n *ast.UnaryOperator, p *program.Program) (
 
 // tranpileUnaryOperatorAmpersant - operator ampersant &
 // Example of AST:
-// `-ImplicitCastExpr 0x2d0fe38 <col:9, col:10> 'int *' <BitCast>
-//   `-UnaryOperator 0x2d0fe18 <col:9, col:10> 'int (*)[5]' prefix '&'
-//     `-DeclRefExpr 0x2d0fdc0 <col:10> 'int [5]' lvalue Var 0x2d0fb20 'arr' 'int [5]'
+//
+// UnaryOperator 'int (*)[5]' prefix '&'
+// `-DeclRefExpr 'int [5]' lvalue Var 0x2d0fb20 'arr' 'int [5]'
+//
+// UnaryOperator 'char **' prefix '&'
+// `-DeclRefExpr 'char *' lvalue Var 0x39b95f0 'line' 'char *'
+//
 func transpileUnaryOperatorAmpersant(n *ast.UnaryOperator, p *program.Program) (
 	expr goast.Expr, eType string, preStmts []goast.Stmt, postStmts []goast.Stmt, err error) {
 	defer func() {
diff --git a/types/cast.go b/types/cast.go
index 959938b..27f7ab3 100644
--- a/types/cast.go
+++ b/types/cast.go
@@ -337,6 +337,8 @@ func CastExpr(p *program.Program, expr goast.Expr, cFromType, cToType string) (
 
 		// Known aliases
 		"__uint16_t", "size_t",
+
+		"noarch.SsizeT",
 	}
 	for _, v := range types {
 		if fromType == v && toType == "bool" {


Test patch:
diff --git a/tests/array.c b/tests/array.c
index 6f61f3a..65279a5 100644
--- a/tests/array.c
+++ b/tests/array.c
@@ -401,7 +401,7 @@ void test_parg_struct()
 
 int main()
 {
-    plan(169);
+    plan(171);
 
     test_parg_struct();
     START_TEST(struct_init);
@@ -899,6 +899,18 @@ int main()
 		(*pnt2)++;
 		is_streq(*pnt2,"llo");
 	}
+	{
+		diag("pnt of value : size_t");
+		size_t len = 42;
+		size_t * l = &len;
+		is_eq(*l,len);
+	}
+	{
+		diag("pnt of value : ssize_t");
+		ssize_t len = 42;
+		ssize_t * l = &len;
+		is_eq(*l,len);
+	}
 
     done_testing();
 }
diff --git a/tests/if.c b/tests/if.c
index 36dae25..550044c 100644
--- a/tests/if.c
+++ b/tests/if.c
@@ -8,7 +8,7 @@ int d(int v)
 
 int main()
 {
-    plan(24);
+    plan(25);
 
     int x = 1;
 
@@ -176,5 +176,13 @@ int main()
         fail("y2");
 	}
 
+	{
+		diag("ssize_t to bool");
+		ssize_t len = 1;
+		if (len) {
+			pass("ok");
+		}
+	}
+
     done_testing();
 }
diff --git a/tests/stdio.c b/tests/stdio.c
index 8a4ff17..648ad0b 100644
--- a/tests/stdio.c
+++ b/tests/stdio.c
@@ -12,7 +12,8 @@
     test_##t();
 
 // size of that file
-int filesize = 11394;
+int filesize = 32;
+char *test_file = "tests/stdio.txt";
 
 void test_putchar()
 {
@@ -334,7 +335,7 @@ void test_ftell()
     FILE* pFile;
     long size;
 
-    pFile = fopen("tests/stdio.c", "r");
+    pFile = fopen(test_file, "r");
     is_not_null(pFile);
 
     fseek(pFile, 0, SEEK_END); // non-portable
@@ -446,7 +447,7 @@ void test_feof()
 {
     FILE* pFile;
     int n = 0;
-    pFile = fopen("tests/stdio.c", "r");
+    pFile = fopen(test_file, "r");
     is_not_null(pFile);
 
     while (fgetc(pFile) != EOF) {
@@ -534,9 +535,38 @@ void test_eof()
     }
 }
 
+void test_perror()
+{
+	perror("test perror");
+}
+
+void test_getline()
+{
+    FILE* pFile;
+    pFile = fopen(test_file, "r");
+    is_not_null(pFile);
+
+	size_t len;
+	char *line = NULL;
+	char **pnt = &line;
+	size_t *l = &len;
+	is_true(getline(pnt,l,pFile) == filesize);
+}
+
+void test_sscanf()
+{
+	char sentence []="Rudolph is 12 years old";
+	char temp[50];
+	char str [20];
+	int i;
+	sscanf (sentence,"%s %s %d",str,temp,&i);
+	is_eq(i,12);
+	is_streq(str,"Rudolph");
+}
+
 int main()
 {
-    plan(61);
+    plan(65);
 
     START_TEST(putchar)
     START_TEST(puts)
@@ -570,6 +600,11 @@ int main()
     START_TEST(vsprintf)
     START_TEST(vsnprintf)
     START_TEST(eof)
+	START_TEST(getline)
+	START_TEST(sscanf)
+
+	// that test must be last test
+	START_TEST(perror)
 
     done_testing();
 }
diff --git a/tests/stdio.txt b/tests/stdio.txt
new file mode 100644
index 0000000..10c9a9e
--- /dev/null
+++ b/tests/stdio.txt
@@ -0,0 +1,1 @@
+Test file for testing <stdio.h>
diff --git a/tests/string.c b/tests/string.c
index c5d8048..dd8a826 100644
--- a/tests/string.c
+++ b/tests/string.c
@@ -3,7 +3,7 @@
 
 int main()
 {
-    plan(41);
+    plan(43);
 
     diag("TODO: __builtin_object_size");
     // https://github.com/Konstantin8105/c4go/issues/359
@@ -177,6 +177,17 @@ int main()
 		pch=strrchr(str,'s');
 		is_eq(pch-str+1,18);
 	}
+	{
+		diag("strdup");
+		const char *s1 = "String";
+		char *s2 = strdup(s1);
+		is_streq(s1,s2);
+		is_true(s1 != s2);
+	}
+	{
+		diag("strerror");
+		strerror(0);
+	}
 
     done_testing();
 }
diff --git a/tests/unistd.c b/tests/unistd.c
new file mode 100644
index 0000000..9a1e8ad
--- /dev/null
+++ b/tests/unistd.c
@@ -0,0 +1,33 @@
+#include <unistd.h> 
+#include "tests.h"
+
+#define MSGSIZE 16 
+char* msg1 = "hello, world #1"; 
+char* msg2 = "hello, world #2"; 
+char* msg3 = "hello, world #3"; 
+  
+int main() 
+{ 
+    plan(3);
+
+    char inbuf[MSGSIZE]; 
+    int p[2]; 
+  
+    if (pipe(p) < 0) 
+        exit(1); 
+  
+    write(p[1], msg1, MSGSIZE); 
+    write(p[1], msg2, MSGSIZE); 
+    write(p[1], msg3, MSGSIZE); 
+
+    read(p[0], inbuf, MSGSIZE); 
+	is_streq(inbuf, msg1);
+
+    read(p[0], inbuf, MSGSIZE); 
+	is_streq(inbuf, msg2);
+
+    read(p[0], inbuf, MSGSIZE); 
+	is_streq(inbuf, msg3);
+
+    done_testing();
+}