summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2019-07-11 17:27:00 +0800
committerruki <[email protected]>2019-07-11 17:27:00 +0800
commit5df725a007759b9821ac624e870b558ae0340853 (patch)
tree4a2fba76a420dcc801c0c699bc9fe5f4eecbed05 /core/src
parent4bc4a680ec5b6769955f655aa0bc0c0da56cbe80 (diff)
parent45a4253be8540240758a69eb8c0c103a3edde057 (diff)
Merge branch 'utf8' into dev
Diffstat (limited to 'core/src')
-rw-r--r--core/src/demo/xmake.c4
-rw-r--r--core/src/demo/xmake.lua6
-rwxr-xr-xcore/src/tbox/inc/linux/tbox.config.h69
-rwxr-xr-xcore/src/tbox/inc/macosx/tbox.config.h69
-rwxr-xr-xcore/src/tbox/inc/windows/tbox.config.h61
-rw-r--r--core/src/tbox/makefile5
m---------core/src/tbox/tbox0
-rw-r--r--core/src/tbox/xmake.lua4
-rw-r--r--core/src/xmake/io/file.h146
-rw-r--r--core/src/xmake/io/file___len.c56
-rw-r--r--core/src/xmake/io/file___tostring.c (renamed from core/src/xmake/io/isatty.c)42
-rw-r--r--core/src/xmake/io/file_close___gc.c123
-rw-r--r--core/src/xmake/io/file_flush.c86
-rw-r--r--core/src/xmake/io/file_isatty.c49
-rw-r--r--core/src/xmake/io/file_path.c55
-rw-r--r--core/src/xmake/io/file_read.c554
-rw-r--r--core/src/xmake/io/file_seek.c81
-rw-r--r--core/src/xmake/io/file_write.c147
-rw-r--r--core/src/xmake/io/open.c320
-rw-r--r--core/src/xmake/io/std.c138
-rw-r--r--core/src/xmake/machine.c98
-rw-r--r--core/src/xmake/makefile12
-rw-r--r--core/src/xmake/os/find.c2
-rw-r--r--core/src/xmake/sandbox/interactive.c100
-rw-r--r--core/src/xmake/string/convert.c27
-rw-r--r--core/src/xmake/winos/ansi.c169
-rw-r--r--core/src/xmake/winos/ansi.h29
-rw-r--r--core/src/xmake/winos/registry_query.c4
-rw-r--r--core/src/xmake/xmake.lua11
29 files changed, 2290 insertions, 177 deletions
diff --git a/core/src/demo/xmake.c b/core/src/demo/xmake.c
index 9c2d489d1..f7c8e6cc5 100644
--- a/core/src/demo/xmake.c
+++ b/core/src/demo/xmake.c
@@ -1,6 +1,6 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
- */
+ */
#include "xmake/xmake.h"
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -12,7 +12,7 @@ tb_int_t main(tb_int_t argc, tb_char_t** argv)
tb_int_t ok = -1;
// init xmake
- if (xm_init())
+ if (xm_init())
{
// init machine
xm_machine_ref_t machine = xm_machine_init();
diff --git a/core/src/demo/xmake.lua b/core/src/demo/xmake.lua
index 4aceb3340..edd6adfdd 100644
--- a/core/src/demo/xmake.lua
+++ b/core/src/demo/xmake.lua
@@ -4,7 +4,7 @@ target("demo")
-- add deps
add_deps("xmake")
- -- make as a binary
+ -- make as a binary
set_kind("binary")
-- set basename of target file
@@ -28,8 +28,8 @@ target("demo")
end
-- add links
- if is_plat("windows") then
- add_links("ws2_32", "advapi32")
+ if is_plat("windows") then
+ add_links("ws2_32", "advapi32", "shell32")
elseif is_plat("android") then
add_links("m", "c")
elseif is_plat("macosx") then
diff --git a/core/src/tbox/inc/linux/tbox.config.h b/core/src/tbox/inc/linux/tbox.config.h
index ccc0cabe0..1b2590f12 100755
--- a/core/src/tbox/inc/linux/tbox.config.h
+++ b/core/src/tbox/inc/linux/tbox.config.h
@@ -2,47 +2,84 @@
#define TB_CONFIG_H
// version
-#define TB_CONFIG_VERSION "1.6.2"
+#define TB_CONFIG_VERSION "1.6.3"
#define TB_CONFIG_VERSION_MAJOR 1
#define TB_CONFIG_VERSION_MINOR 6
-#define TB_CONFIG_VERSION_ALTER 2
-#define TB_CONFIG_VERSION_BUILD 201705202359
+#define TB_CONFIG_VERSION_ALTER 3
+#define TB_CONFIG_VERSION_BUILD 201907051345
// defines
#define TB_CONFIG_OS_LINUX 1
#define _GNU_SOURCE 1
#define _REENTRANT 1
#define TB_CONFIG_SMALL 1
+/* #undef TB_CONFIG_MICRO_ENABLE */
+/* #undef TB_CONFIG_TYPE_HAVE_WCHAR */
#define TB_CONFIG_TYPE_HAVE_FLOAT 1
+#define TB_CONFIG_FORCE_UTF8 1
+
+// keywords
+#define TB_CONFIG_KEYWORD_HAVE__thread 1
+#define TB_CONFIG_KEYWORD_HAVE_Thread_local 1
+
+// modules
+/* #undef TB_CONFIG_MODULE_HAVE_XML */
+/* #undef TB_CONFIG_MODULE_HAVE_ZIP */
#define TB_CONFIG_MODULE_HAVE_HASH 1
+/* #undef TB_CONFIG_MODULE_HAVE_REGEX */
+/* #undef TB_CONFIG_MODULE_HAVE_OBJECT */
+#define TB_CONFIG_MODULE_HAVE_CHARSET 1
+/* #undef TB_CONFIG_MODULE_HAVE_DATABASE */
+/* #undef TB_CONFIG_MODULE_HAVE_COROUTINE */
+
+// packages
+/* #undef TB_CONFIG_PACKAGE_HAVE_ZLIB */
+/* #undef TB_CONFIG_PACKAGE_HAVE_MYSQL */
+/* #undef TB_CONFIG_PACKAGE_HAVE_SQLITE3 */
+/* #undef TB_CONFIG_PACKAGE_HAVE_OPENSSL */
+/* #undef TB_CONFIG_PACKAGE_HAVE_POLARSSL */
+/* #undef TB_CONFIG_PACKAGE_HAVE_MBEDTLS */
+/* #undef TB_CONFIG_PACKAGE_HAVE_PCRE2 */
+/* #undef TB_CONFIG_PACKAGE_HAVE_PCRE */
+
+// libc functions
#define TB_CONFIG_LIBC_HAVE_MEMCPY 1
#define TB_CONFIG_LIBC_HAVE_MEMSET 1
#define TB_CONFIG_LIBC_HAVE_MEMMOVE 1
#define TB_CONFIG_LIBC_HAVE_MEMCMP 1
+#define TB_CONFIG_LIBC_HAVE_MEMMEM 1
#define TB_CONFIG_LIBC_HAVE_STRCAT 1
#define TB_CONFIG_LIBC_HAVE_STRNCAT 1
#define TB_CONFIG_LIBC_HAVE_STRCPY 1
#define TB_CONFIG_LIBC_HAVE_STRNCPY 1
+/* #undef TB_CONFIG_LIBC_HAVE_STRLCPY */
#define TB_CONFIG_LIBC_HAVE_STRLEN 1
#define TB_CONFIG_LIBC_HAVE_STRNLEN 1
#define TB_CONFIG_LIBC_HAVE_STRSTR 1
+#define TB_CONFIG_LIBC_HAVE_STRCHR 1
+#define TB_CONFIG_LIBC_HAVE_STRRCHR 1
+#define TB_CONFIG_LIBC_HAVE_STRCASESTR 1
#define TB_CONFIG_LIBC_HAVE_STRCMP 1
#define TB_CONFIG_LIBC_HAVE_STRCASECMP 1
#define TB_CONFIG_LIBC_HAVE_STRNCMP 1
#define TB_CONFIG_LIBC_HAVE_STRNCASECMP 1
+
#define TB_CONFIG_LIBC_HAVE_WCSCAT 1
#define TB_CONFIG_LIBC_HAVE_WCSNCAT 1
#define TB_CONFIG_LIBC_HAVE_WCSCPY 1
#define TB_CONFIG_LIBC_HAVE_WCSNCPY 1
+/* #undef TB_CONFIG_LIBC_HAVE_WCSLCPY */
#define TB_CONFIG_LIBC_HAVE_WCSLEN 1
#define TB_CONFIG_LIBC_HAVE_WCSNLEN 1
#define TB_CONFIG_LIBC_HAVE_WCSSTR 1
+/* #undef TB_CONFIG_LIBC_HAVE_WCSCASESTR */
#define TB_CONFIG_LIBC_HAVE_WCSCMP 1
#define TB_CONFIG_LIBC_HAVE_WCSCASECMP 1
#define TB_CONFIG_LIBC_HAVE_WCSNCMP 1
#define TB_CONFIG_LIBC_HAVE_WCSNCASECMP 1
#define TB_CONFIG_LIBC_HAVE_WCSTOMBS 1
#define TB_CONFIG_LIBC_HAVE_MBSTOWCS 1
+
#define TB_CONFIG_LIBC_HAVE_GMTIME 1
#define TB_CONFIG_LIBC_HAVE_MKTIME 1
#define TB_CONFIG_LIBC_HAVE_LOCALTIME 1
@@ -53,9 +90,19 @@
#define TB_CONFIG_LIBC_HAVE_KILL 1
#define TB_CONFIG_LIBC_HAVE_BACKTRACE 1
#define TB_CONFIG_LIBC_HAVE_SETLOCALE 1
+#define TB_CONFIG_LIBC_HAVE_FPUTC 1
+#define TB_CONFIG_LIBC_HAVE_FGETC 1
+#define TB_CONFIG_LIBC_HAVE_UNGETC 1
#define TB_CONFIG_LIBC_HAVE_FPUTS 1
+#define TB_CONFIG_LIBC_HAVE_FGETS 1
+#define TB_CONFIG_LIBC_HAVE_FREAD 1
+#define TB_CONFIG_LIBC_HAVE_FWRITE 1
#define TB_CONFIG_LIBC_HAVE_SRANDOM 1
#define TB_CONFIG_LIBC_HAVE_RANDOM 1
+
+// libm functions
+#define TB_CONFIG_LIBM_HAVE_SINCOS 1
+#define TB_CONFIG_LIBM_HAVE_SINCOSF 1
#define TB_CONFIG_LIBM_HAVE_LOG2 1
#define TB_CONFIG_LIBM_HAVE_LOG2F 1
#define TB_CONFIG_LIBM_HAVE_SQRT 1
@@ -80,6 +127,8 @@
#define TB_CONFIG_LIBM_HAVE_SINF 1
#define TB_CONFIG_LIBM_HAVE_EXP 1
#define TB_CONFIG_LIBM_HAVE_EXPF 1
+
+// posix functions
#define TB_CONFIG_POSIX_HAVE_POLL 1
#define TB_CONFIG_POSIX_HAVE_SELECT 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1
@@ -88,28 +137,36 @@
#define TB_CONFIG_POSIX_HAVE_PTHREAD_GETSPECIFIC 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_CREATE 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_DELETE 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_SETAFFINITY_NP 1
#define TB_CONFIG_POSIX_HAVE_SOCKET 1
+#define TB_CONFIG_POSIX_HAVE_POLL 1
#define TB_CONFIG_POSIX_HAVE_OPENDIR 1
#define TB_CONFIG_POSIX_HAVE_DLOPEN 1
#define TB_CONFIG_POSIX_HAVE_OPEN 1
+#define TB_CONFIG_POSIX_HAVE_STAT64 1
#define TB_CONFIG_POSIX_HAVE_GETHOSTNAME 1
#define TB_CONFIG_POSIX_HAVE_GETIFADDRS 1
#define TB_CONFIG_POSIX_HAVE_SEM_INIT 1
#define TB_CONFIG_POSIX_HAVE_GETPAGESIZE 1
#define TB_CONFIG_POSIX_HAVE_SYSCONF 1
#define TB_CONFIG_POSIX_HAVE_SCHED_YIELD 1
+#define TB_CONFIG_POSIX_HAVE_SCHED_SETAFFINITY 1
#define TB_CONFIG_POSIX_HAVE_REGCOMP 1
#define TB_CONFIG_POSIX_HAVE_REGEXEC 1
#define TB_CONFIG_POSIX_HAVE_READV 1
#define TB_CONFIG_POSIX_HAVE_WRITEV 1
#define TB_CONFIG_POSIX_HAVE_PREADV 1
#define TB_CONFIG_POSIX_HAVE_PWRITEV 1
+#define TB_CONFIG_POSIX_HAVE_PREAD64 1
+#define TB_CONFIG_POSIX_HAVE_PWRITE64 1
#define TB_CONFIG_POSIX_HAVE_FDATASYNC 1
+/* #undef TB_CONFIG_POSIX_HAVE_COPYFILE */
#define TB_CONFIG_POSIX_HAVE_SENDFILE 1
#define TB_CONFIG_POSIX_HAVE_EPOLL_CREATE 1
#define TB_CONFIG_POSIX_HAVE_EPOLL_WAIT 1
#define TB_CONFIG_POSIX_HAVE_POSIX_SPAWNP 1
#define TB_CONFIG_POSIX_HAVE_EXECVP 1
+#define TB_CONFIG_POSIX_HAVE_EXECVPE 1
#define TB_CONFIG_POSIX_HAVE_FORK 1
#define TB_CONFIG_POSIX_HAVE_VFORK 1
#define TB_CONFIG_POSIX_HAVE_WAITPID 1
@@ -119,6 +176,12 @@
#define TB_CONFIG_POSIX_HAVE_GETNAMEINFO 1
#define TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME 1
#define TB_CONFIG_POSIX_HAVE_GETHOSTBYADDR 1
+
+// systemv functions
#define TB_CONFIG_SYSTEMV_HAVE_SEMGET 1
+#define TB_CONFIG_SYSTEMV_HAVE_SEMTIMEDOP 1
+
+// valgrind functions
+/* #undef TB_CONFIG_SYSTEMV_HAVE_VALGRIND_STACK_REGISTER */
#endif
diff --git a/core/src/tbox/inc/macosx/tbox.config.h b/core/src/tbox/inc/macosx/tbox.config.h
index 0fa89b373..5bfbea9cc 100755
--- a/core/src/tbox/inc/macosx/tbox.config.h
+++ b/core/src/tbox/inc/macosx/tbox.config.h
@@ -2,19 +2,47 @@
#define TB_CONFIG_H
// version
-#define TB_CONFIG_VERSION "1.6.2"
+#define TB_CONFIG_VERSION "1.6.3"
#define TB_CONFIG_VERSION_MAJOR 1
#define TB_CONFIG_VERSION_MINOR 6
-#define TB_CONFIG_VERSION_ALTER 2
-#define TB_CONFIG_VERSION_BUILD 201705202248
+#define TB_CONFIG_VERSION_ALTER 3
+#define TB_CONFIG_VERSION_BUILD 201907052137
// defines
#define TB_CONFIG_OS_MACOSX 1
#define _GNU_SOURCE 1
#define _REENTRANT 1
#define TB_CONFIG_SMALL 1
+/* #undef TB_CONFIG_MICRO_ENABLE */
+/* #undef TB_CONFIG_TYPE_HAVE_WCHAR */
#define TB_CONFIG_TYPE_HAVE_FLOAT 1
+#define TB_CONFIG_FORCE_UTF8 1
+
+// keywords
+#define TB_CONFIG_KEYWORD_HAVE__thread 1
+#define TB_CONFIG_KEYWORD_HAVE_Thread_local 1
+
+// modules
+/* #undef TB_CONFIG_MODULE_HAVE_XML */
+/* #undef TB_CONFIG_MODULE_HAVE_ZIP */
#define TB_CONFIG_MODULE_HAVE_HASH 1
+/* #undef TB_CONFIG_MODULE_HAVE_REGEX */
+/* #undef TB_CONFIG_MODULE_HAVE_OBJECT */
+#define TB_CONFIG_MODULE_HAVE_CHARSET 1
+/* #undef TB_CONFIG_MODULE_HAVE_DATABASE */
+/* #undef TB_CONFIG_MODULE_HAVE_COROUTINE */
+
+// packages
+/* #undef TB_CONFIG_PACKAGE_HAVE_ZLIB */
+/* #undef TB_CONFIG_PACKAGE_HAVE_MYSQL */
+/* #undef TB_CONFIG_PACKAGE_HAVE_SQLITE3 */
+/* #undef TB_CONFIG_PACKAGE_HAVE_OPENSSL */
+/* #undef TB_CONFIG_PACKAGE_HAVE_POLARSSL */
+/* #undef TB_CONFIG_PACKAGE_HAVE_MBEDTLS */
+/* #undef TB_CONFIG_PACKAGE_HAVE_PCRE2 */
+/* #undef TB_CONFIG_PACKAGE_HAVE_PCRE */
+
+// libc functions
#define TB_CONFIG_LIBC_HAVE_MEMCPY 1
#define TB_CONFIG_LIBC_HAVE_MEMSET 1
#define TB_CONFIG_LIBC_HAVE_MEMMOVE 1
@@ -28,11 +56,14 @@
#define TB_CONFIG_LIBC_HAVE_STRLEN 1
#define TB_CONFIG_LIBC_HAVE_STRNLEN 1
#define TB_CONFIG_LIBC_HAVE_STRSTR 1
+#define TB_CONFIG_LIBC_HAVE_STRCHR 1
+#define TB_CONFIG_LIBC_HAVE_STRRCHR 1
#define TB_CONFIG_LIBC_HAVE_STRCASESTR 1
#define TB_CONFIG_LIBC_HAVE_STRCMP 1
#define TB_CONFIG_LIBC_HAVE_STRCASECMP 1
#define TB_CONFIG_LIBC_HAVE_STRNCMP 1
#define TB_CONFIG_LIBC_HAVE_STRNCASECMP 1
+
#define TB_CONFIG_LIBC_HAVE_WCSCAT 1
#define TB_CONFIG_LIBC_HAVE_WCSNCAT 1
#define TB_CONFIG_LIBC_HAVE_WCSCPY 1
@@ -41,12 +72,14 @@
#define TB_CONFIG_LIBC_HAVE_WCSLEN 1
#define TB_CONFIG_LIBC_HAVE_WCSNLEN 1
#define TB_CONFIG_LIBC_HAVE_WCSSTR 1
+/* #undef TB_CONFIG_LIBC_HAVE_WCSCASESTR */
#define TB_CONFIG_LIBC_HAVE_WCSCMP 1
#define TB_CONFIG_LIBC_HAVE_WCSCASECMP 1
#define TB_CONFIG_LIBC_HAVE_WCSNCMP 1
#define TB_CONFIG_LIBC_HAVE_WCSNCASECMP 1
#define TB_CONFIG_LIBC_HAVE_WCSTOMBS 1
#define TB_CONFIG_LIBC_HAVE_MBSTOWCS 1
+
#define TB_CONFIG_LIBC_HAVE_GMTIME 1
#define TB_CONFIG_LIBC_HAVE_MKTIME 1
#define TB_CONFIG_LIBC_HAVE_LOCALTIME 1
@@ -57,9 +90,19 @@
#define TB_CONFIG_LIBC_HAVE_KILL 1
#define TB_CONFIG_LIBC_HAVE_BACKTRACE 1
#define TB_CONFIG_LIBC_HAVE_SETLOCALE 1
+#define TB_CONFIG_LIBC_HAVE_FPUTC 1
+#define TB_CONFIG_LIBC_HAVE_FGETC 1
+#define TB_CONFIG_LIBC_HAVE_UNGETC 1
#define TB_CONFIG_LIBC_HAVE_FPUTS 1
+#define TB_CONFIG_LIBC_HAVE_FGETS 1
+#define TB_CONFIG_LIBC_HAVE_FREAD 1
+#define TB_CONFIG_LIBC_HAVE_FWRITE 1
#define TB_CONFIG_LIBC_HAVE_SRANDOM 1
#define TB_CONFIG_LIBC_HAVE_RANDOM 1
+
+// libm functions
+/* #undef TB_CONFIG_LIBM_HAVE_SINCOS */
+/* #undef TB_CONFIG_LIBM_HAVE_SINCOSF */
#define TB_CONFIG_LIBM_HAVE_LOG2 1
#define TB_CONFIG_LIBM_HAVE_LOG2F 1
#define TB_CONFIG_LIBM_HAVE_SQRT 1
@@ -84,6 +127,8 @@
#define TB_CONFIG_LIBM_HAVE_SINF 1
#define TB_CONFIG_LIBM_HAVE_EXP 1
#define TB_CONFIG_LIBM_HAVE_EXPF 1
+
+// posix functions
#define TB_CONFIG_POSIX_HAVE_POLL 1
#define TB_CONFIG_POSIX_HAVE_SELECT 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1
@@ -92,7 +137,9 @@
#define TB_CONFIG_POSIX_HAVE_PTHREAD_GETSPECIFIC 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_CREATE 1
#define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_DELETE 1
+/* #undef TB_CONFIG_POSIX_HAVE_PTHREAD_SETAFFINITY_NP */
#define TB_CONFIG_POSIX_HAVE_SOCKET 1
+#define TB_CONFIG_POSIX_HAVE_POLL 1
#define TB_CONFIG_POSIX_HAVE_OPENDIR 1
#define TB_CONFIG_POSIX_HAVE_DLOPEN 1
#define TB_CONFIG_POSIX_HAVE_OPEN 1
@@ -103,13 +150,23 @@
#define TB_CONFIG_POSIX_HAVE_GETPAGESIZE 1
#define TB_CONFIG_POSIX_HAVE_SYSCONF 1
#define TB_CONFIG_POSIX_HAVE_SCHED_YIELD 1
+/* #undef TB_CONFIG_POSIX_HAVE_SCHED_SETAFFINITY */
#define TB_CONFIG_POSIX_HAVE_REGCOMP 1
#define TB_CONFIG_POSIX_HAVE_REGEXEC 1
#define TB_CONFIG_POSIX_HAVE_READV 1
#define TB_CONFIG_POSIX_HAVE_WRITEV 1
+/* #undef TB_CONFIG_POSIX_HAVE_PREADV */
+/* #undef TB_CONFIG_POSIX_HAVE_PWRITEV */
+/* #undef TB_CONFIG_POSIX_HAVE_PREAD64 */
+/* #undef TB_CONFIG_POSIX_HAVE_PWRITE64 */
+/* #undef TB_CONFIG_POSIX_HAVE_FDATASYNC */
#define TB_CONFIG_POSIX_HAVE_COPYFILE 1
+/* #undef TB_CONFIG_POSIX_HAVE_SENDFILE */
+/* #undef TB_CONFIG_POSIX_HAVE_EPOLL_CREATE */
+/* #undef TB_CONFIG_POSIX_HAVE_EPOLL_WAIT */
#define TB_CONFIG_POSIX_HAVE_POSIX_SPAWNP 1
#define TB_CONFIG_POSIX_HAVE_EXECVP 1
+/* #undef TB_CONFIG_POSIX_HAVE_EXECVPE */
#define TB_CONFIG_POSIX_HAVE_FORK 1
#define TB_CONFIG_POSIX_HAVE_VFORK 1
#define TB_CONFIG_POSIX_HAVE_WAITPID 1
@@ -119,6 +176,12 @@
#define TB_CONFIG_POSIX_HAVE_GETNAMEINFO 1
#define TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME 1
#define TB_CONFIG_POSIX_HAVE_GETHOSTBYADDR 1
+
+// systemv functions
#define TB_CONFIG_SYSTEMV_HAVE_SEMGET 1
+/* #undef TB_CONFIG_SYSTEMV_HAVE_SEMTIMEDOP */
+
+// valgrind functions
+/* #undef TB_CONFIG_SYSTEMV_HAVE_VALGRIND_STACK_REGISTER */
#endif
diff --git a/core/src/tbox/inc/windows/tbox.config.h b/core/src/tbox/inc/windows/tbox.config.h
deleted file mode 100755
index 4cc30f8d8..000000000
--- a/core/src/tbox/inc/windows/tbox.config.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef TB_CONFIG_H
-#define TB_CONFIG_H
-
-// version
-#define TB_CONFIG_VERSION "1.6.2"
-#define TB_CONFIG_VERSION_MAJOR 1
-#define TB_CONFIG_VERSION_MINOR 6
-#define TB_CONFIG_VERSION_ALTER 2
-#define TB_CONFIG_VERSION_BUILD 201707201725
-
-// defines
-#define TB_CONFIG_OS_WINDOWS 1
-#define _GNU_SOURCE 1
-#define _REENTRANT 1
-#define TB_CONFIG_SMALL 1
-#define TB_CONFIG_TYPE_HAVE_FLOAT 1
-#define TB_CONFIG_MODULE_HAVE_HASH 1
-#define TB_CONFIG_LIBC_HAVE_MEMCPY 1
-#define TB_CONFIG_LIBC_HAVE_MEMSET 1
-#define TB_CONFIG_LIBC_HAVE_MEMMOVE 1
-#define TB_CONFIG_LIBC_HAVE_MEMCMP 1
-#define TB_CONFIG_LIBC_HAVE_STRCAT 1
-#define TB_CONFIG_LIBC_HAVE_STRNCAT 1
-#define TB_CONFIG_LIBC_HAVE_STRCPY 1
-#define TB_CONFIG_LIBC_HAVE_STRNCPY 1
-#define TB_CONFIG_LIBC_HAVE_STRLEN 1
-#define TB_CONFIG_LIBC_HAVE_STRNLEN 1
-#define TB_CONFIG_LIBC_HAVE_STRSTR 1
-#define TB_CONFIG_LIBC_HAVE_STRCMP 1
-#define TB_CONFIG_LIBC_HAVE_STRNCMP 1
-#define TB_CONFIG_LIBC_HAVE_WCSCAT 1
-#define TB_CONFIG_LIBC_HAVE_WCSNCAT 1
-#define TB_CONFIG_LIBC_HAVE_WCSCPY 1
-#define TB_CONFIG_LIBC_HAVE_WCSNCPY 1
-#define TB_CONFIG_LIBC_HAVE_WCSLEN 1
-#define TB_CONFIG_LIBC_HAVE_WCSNLEN 1
-#define TB_CONFIG_LIBC_HAVE_WCSSTR 1
-#define TB_CONFIG_LIBC_HAVE_WCSCMP 1
-#define TB_CONFIG_LIBC_HAVE_WCSNCMP 1
-#define TB_CONFIG_LIBC_HAVE_WCSTOMBS 1
-#define TB_CONFIG_LIBC_HAVE_MBSTOWCS 1
-#define TB_CONFIG_LIBC_HAVE_GMTIME 1
-#define TB_CONFIG_LIBC_HAVE_MKTIME 1
-#define TB_CONFIG_LIBC_HAVE_LOCALTIME 1
-#define TB_CONFIG_LIBC_HAVE_SIGNAL 1
-#define TB_CONFIG_LIBC_HAVE_SETJMP 1
-#define TB_CONFIG_LIBC_HAVE_SETLOCALE 1
-#define TB_CONFIG_LIBC_HAVE_FPUTS 1
-#define TB_CONFIG_LIBM_HAVE_SQRT 1
-#define TB_CONFIG_LIBM_HAVE_ACOS 1
-#define TB_CONFIG_LIBM_HAVE_ASIN 1
-#define TB_CONFIG_LIBM_HAVE_POW 1
-#define TB_CONFIG_LIBM_HAVE_FMOD 1
-#define TB_CONFIG_LIBM_HAVE_TAN 1
-#define TB_CONFIG_LIBM_HAVE_ATAN 1
-#define TB_CONFIG_LIBM_HAVE_ATAN2 1
-#define TB_CONFIG_LIBM_HAVE_COS 1
-#define TB_CONFIG_LIBM_HAVE_SIN 1
-#define TB_CONFIG_LIBM_HAVE_EXP 1
-
-#endif
diff --git a/core/src/tbox/makefile b/core/src/tbox/makefile
index 11038c4e4..51dc1ae1c 100644
--- a/core/src/tbox/makefile
+++ b/core/src/tbox/makefile
@@ -47,6 +47,7 @@ tbox_C_FILES += \
tbox/src/tbox/libc/string/memset \
tbox/src/tbox/libc/string/strcat \
tbox/src/tbox/libc/string/strchr \
+ tbox/src/tbox/libc/string/strnchr \
tbox/src/tbox/libc/string/strcmp \
tbox/src/tbox/libc/string/strcpy \
tbox/src/tbox/libc/string/strdup \
@@ -128,6 +129,7 @@ tbox_C_FILES += \
tbox/src/tbox/stream/filter \
tbox/src/tbox/stream/impl/filter/cache \
tbox/src/tbox/stream/impl/filter/chunked \
+ tbox/src/tbox/stream/impl/filter/charset \
tbox/src/tbox/stream/impl/stream/data \
tbox/src/tbox/stream/impl/stream/file \
tbox/src/tbox/stream/impl/stream/filter \
@@ -199,6 +201,7 @@ tbox_C_FILES += \
tbox/src/tbox/container/stack \
tbox/src/tbox/container/vector \
tbox/src/tbox/libm/impl/libm \
+ tbox/src/tbox/libm/exp \
tbox/src/tbox/libm/ilog2i \
tbox/src/tbox/libm/isqrti \
tbox/src/tbox/libm/idivi8 \
@@ -220,6 +223,7 @@ tbox_C_FILES += \
tbox/src/tbox/platform/path \
tbox/src/tbox/platform/poller \
tbox/src/tbox/platform/print \
+ tbox/src/tbox/platform/stdfile \
tbox/src/tbox/platform/process \
tbox/src/tbox/platform/processor \
tbox/src/tbox/platform/sched \
@@ -230,6 +234,7 @@ tbox_C_FILES += \
tbox/src/tbox/platform/thread_local \
tbox/src/tbox/platform/time \
tbox/src/tbox/platform/timer \
+ tbox/src/tbox/platform/impl/charset \
tbox/src/tbox/platform/impl/sockdata \
tbox/src/tbox/platform/impl/dns \
tbox/src/tbox/platform/impl/platform \
diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox
-Subproject ad025d12b7dfc9a993da2c7a75bd1e9cd70bd57
+Subproject 32e03f155426a393c3d5fce302366a9ec52d423
diff --git a/core/src/tbox/xmake.lua b/core/src/tbox/xmake.lua
index 563fd12d5..3469900ec 100644
--- a/core/src/tbox/xmake.lua
+++ b/core/src/tbox/xmake.lua
@@ -1,7 +1,7 @@
includes("tbox")
--- enable hash, charset modules
-for _, name in ipairs({"hash", "charset"}) do
+-- enable hash, charset, utf8 modules
+for _, name in ipairs({ "hash", "charset", "force-utf8" }) do
option(name)
set_default(true)
after_check(function (option)
diff --git a/core/src/xmake/io/file.h b/core/src/xmake/io/file.h
new file mode 100644
index 000000000..900ef00b6
--- /dev/null
+++ b/core/src/xmake/io/file.h
@@ -0,0 +1,146 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file.h
+ *
+ */
+#ifndef XM_IO_FILE_H
+#define XM_IO_FILE_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+#define xm_io_file_is_file(file) ((file)->type == XM_IO_FILE_TYPE_FILE)
+#define xm_io_file_is_std(file) ((file)->type != XM_IO_FILE_TYPE_FILE)
+
+#define xm_io_file_is_closed_file(file) (xm_io_file_is_file(file) && !((file)->file_ref))
+#define xm_io_file_is_closed_std(file) (xm_io_file_is_std(file) && !((file)->std_ref))
+
+#define xm_io_file_is_tty(file) (!!((file)->type & XM_IO_FILE_FLAG_TTY))
+#define xm_io_file_is_closed(file) (xm_io_file_is_closed_file(file) || xm_io_file_is_closed_std(file))
+
+#define xm_io_file_udata "XM_IO_FILE*"
+
+#define xm_io_file_return_success() \
+ do \
+ { \
+ return 1; \
+ } while (0)
+
+#define xm_io_file_return_error(lua, file, reason) \
+ do \
+ { \
+ lua_pushnil(lua); \
+ lua_pushfstring(lua, "error: %s (%s)", reason, file->name); \
+ return 2; \
+ } while (0)
+
+#define xm_io_file_return_error_closed(lua) \
+ do \
+ { \
+ lua_pushnil(lua); \
+ lua_pushliteral(lua, "error: file has been closed"); \
+ return 2; \
+ } while (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+typedef enum __xm_io_file_type_e
+{
+ XM_IO_FILE_TYPE_FILE = 0 //!< disk file
+
+, XM_IO_FILE_TYPE_STDIN = 1
+, XM_IO_FILE_TYPE_STDOUT = 2
+, XM_IO_FILE_TYPE_STDERR = 3
+
+, XM_IO_FILE_FLAG_TTY = 0x10 //!< mark tty std stream
+
+} xm_io_file_type_e;
+
+/* use negetive numbers for this enum, its a extension for tb_charset_type_e
+ * before adding new values, make sure they have not conflicts with values in tb_charset_type_e
+ */
+typedef enum __xm_io_file_encoding_e
+{
+ XM_IO_FILE_ENCODING_UNKNOWN = -1
+, XM_IO_FILE_ENCODING_BINARY = -2
+
+} xm_io_file_encoding_e;
+
+typedef struct __xm_io_file
+{
+ union
+ {
+ /* the normal file for XM_IO_FILE_TYPE_FILE
+ *
+ * direct: file_ref -> stream -> file
+ * transcode: file_ref -> fstream -> stream -> file
+ */
+ tb_stream_ref_t file_ref;
+
+ // the standard io file
+ tb_stdfile_ref_t std_ref;
+ };
+
+ tb_stream_ref_t stream; // the file stream for XM_IO_FILE_TYPE_FILE
+ tb_stream_ref_t fstream; // the file charset stream filter
+ tb_size_t mode; // tb_file_mode_t
+ tb_size_t type; // xm_io_file_type_e
+ tb_size_t encoding; // value of xm_io_file_encoding_e or tb_charset_type_e
+ tb_char_t name[64];
+ tb_char_t const* path;
+ tb_buffer_t rcache; // the read line cache buffer
+ tb_buffer_t wcache; // the write line cache buffer
+} xm_io_file;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+static __tb_inline__ xm_io_file* xm_io_newfile(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, tb_null);
+
+ // new file
+ xm_io_file* file = (xm_io_file*)lua_newuserdata(lua, sizeof(xm_io_file));
+ tb_assert_and_check_return_val(file, tb_null);
+
+ // init file
+ luaL_getmetatable(lua, xm_io_file_udata);
+ lua_setmetatable(lua, -2);
+ tb_memset(file, 0, sizeof(xm_io_file));
+ return file;
+}
+
+static __tb_inline__ xm_io_file* xm_io_getfile(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, tb_null);
+
+ // get file
+ xm_io_file* file = (xm_io_file*)luaL_checkudata(lua, 1, xm_io_file_udata);
+ tb_assert(file);
+ return file;
+}
+
+#endif
diff --git a/core/src/xmake/io/file___len.c b/core/src/xmake/io/file___len.c
new file mode 100644
index 000000000..449df7d3c
--- /dev/null
+++ b/core/src/xmake/io/file___len.c
@@ -0,0 +1,56 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file___len.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file___len"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/* get file length, #file
+ */
+tb_int_t xm_io_file___len(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ xm_io_file* file = xm_io_getfile(lua);
+ if (xm_io_file_is_closed(file))
+ xm_io_file_return_error_closed(lua);
+ else if (xm_io_file_is_file(file))
+ {
+ // get size from raw file stream, because we cannot get size from fstream
+ tb_assert(file->stream);
+ lua_pushnumber(lua, (lua_Number)tb_stream_size(file->stream));
+ xm_io_file_return_success();
+ }
+ else xm_io_file_return_error(lua, file, "getting file size for this file is invalid");
+}
diff --git a/core/src/xmake/io/isatty.c b/core/src/xmake/io/file___tostring.c
index d4dd7b57d..8290d358a 100644
--- a/core/src/xmake/io/isatty.c
+++ b/core/src/xmake/io/file___tostring.c
@@ -11,57 +11,41 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *
+ *
* Copyright (C) 2015 - 2019, TBOOX Open Source Group.
*
- * @author ruki
- * @file isatty.c
+ * @author OpportunityLiu
+ * @file file___tostring.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
-#define TB_TRACE_MODULE_NAME "isatty"
-#define TB_TRACE_MODULE_DEBUG (0)
+#define TB_TRACE_MODULE_NAME "file___tostring"
+#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
+#include "file.h"
#include "prefix.h"
-#ifdef TB_CONFIG_OS_WINDOWS
-# include <io.h>
-#else
-# include <unistd.h>
-#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
-/* stdout: io.isatty()
- * stderr: io.isatty(io.stderr)
- * stdin: io.isatty(io.stdin)
+/*
+ * tostring(file)
*/
-tb_int_t xm_io_isatty(lua_State* lua)
+tb_int_t xm_io_file___tostring(lua_State* lua)
{
// check
tb_assert_and_check_return_val(lua, 0);
- // get file pointer
- FILE** fp = (FILE**)luaL_checkudata(lua, 1, LUA_FILEHANDLE);
-
- // no arguments? default: stdout
- tb_int_t answer = 1;
-#ifdef TB_CONFIG_OS_WINDOWS
- if (fp) answer = _isatty(_fileno(*fp));
-#else
- if (fp) answer = isatty(fileno(*fp));
-#endif
-
- // return answer
- lua_pushboolean(lua, answer);
-
- // ok
+ // get file name as string
+ xm_io_file* file = xm_io_getfile(lua);
+ lua_pushstring(lua, file->name);
return 1;
}
+
diff --git a/core/src/xmake/io/file_close___gc.c b/core/src/xmake/io/file_close___gc.c
new file mode 100644
index 000000000..3ff136f6a
--- /dev/null
+++ b/core/src/xmake/io/file_close___gc.c
@@ -0,0 +1,123 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file_close___gc.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file_close___gc"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+static tb_int_t xm_io_file_close_impl(lua_State* lua, tb_bool_t allow_closed_file)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ xm_io_file* file = xm_io_getfile(lua);
+ if (xm_io_file_is_closed(file))
+ {
+ if (allow_closed_file)
+ {
+ lua_pushboolean(lua, tb_true);
+ xm_io_file_return_success();
+ }
+ else xm_io_file_return_error_closed(lua);
+ }
+ if (xm_io_file_is_file(file))
+ {
+ // check
+ tb_assert(file->file_ref);
+
+#ifdef TB_CONFIG_OS_WINDOWS
+ // write cached data first
+ tb_byte_t const* odata = tb_buffer_data(&file->wcache);
+ tb_size_t osize = tb_buffer_size(&file->wcache);
+ if (odata && osize)
+ {
+ if (!tb_stream_bwrit(file->file_ref, odata, osize)) return tb_false;
+ tb_buffer_clear(&file->wcache);
+ }
+#endif
+
+ // close file
+ if (!tb_stream_clos(file->file_ref))
+ xm_io_file_return_error(lua, file, "failed to close file");
+ file->file_ref = tb_null;
+
+ // exit fstream
+ if (file->fstream) tb_stream_exit(file->fstream);
+ file->fstream = tb_null;
+
+ // exit stream
+ if (file->stream) tb_stream_exit(file->stream);
+ file->stream = tb_null;
+
+ // exit the line cache buffer
+ tb_buffer_exit(&file->rcache);
+ tb_buffer_exit(&file->wcache);
+
+ // free file path
+ if (file->path)
+ {
+ tb_free(file->path);
+ file->path = tb_null;
+ }
+
+ // mark this file as closed
+ tb_strlcpy(file->name, "file: (closed file)", tb_arrayn(file->name));
+ lua_pushboolean(lua, tb_true);
+ xm_io_file_return_success();
+ }
+ else
+ {
+ lua_pushboolean(lua, tb_true);
+ xm_io_file_return_success();
+ }
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*
+ * file:close()
+ */
+tb_int_t xm_io_file_close(lua_State* lua)
+{
+ return xm_io_file_close_impl(lua, tb_false);
+}
+
+/*
+ * file:close()
+ */
+tb_int_t xm_io_file___gc(lua_State* lua)
+{
+ return xm_io_file_close_impl(lua, tb_true);
+}
diff --git a/core/src/xmake/io/file_flush.c b/core/src/xmake/io/file_flush.c
new file mode 100644
index 000000000..ccab16310
--- /dev/null
+++ b/core/src/xmake/io/file_flush.c
@@ -0,0 +1,86 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file_flush.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file_flush"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+static tb_bool_t xm_io_std_flush_impl(xm_io_file* file)
+{
+ tb_assert_and_check_return_val(xm_io_file_is_std(file) && !xm_io_file_is_closed(file), tb_false);
+ return (file->std_ref != tb_stdfile_input())? tb_stdfile_flush(file->std_ref) : tb_false;
+}
+
+static tb_bool_t xm_io_file_flush_impl(xm_io_file* file)
+{
+ // check
+ tb_assert_and_check_return_val(xm_io_file_is_file(file) && !xm_io_file_is_closed(file), tb_false);
+
+#ifdef TB_CONFIG_OS_WINDOWS
+ // write cached data first
+ tb_byte_t const* odata = tb_buffer_data(&file->wcache);
+ tb_size_t osize = tb_buffer_size(&file->wcache);
+ if (odata && osize)
+ {
+ if (!tb_stream_bwrit(file->file_ref, odata, osize)) return tb_false;
+ tb_buffer_clear(&file->wcache);
+ }
+#endif
+ return tb_stream_sync(file->file_ref, tb_false);
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*
+ * file:flush()
+ */
+tb_int_t xm_io_file_flush(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // file has been closed?
+ xm_io_file* file = xm_io_getfile(lua);
+ if (xm_io_file_is_closed(file))
+ xm_io_file_return_error_closed(lua);
+
+ // flush file
+ tb_bool_t ok = xm_io_file_is_file(file) ? xm_io_file_flush_impl(file) : xm_io_std_flush_impl(file);
+ if (ok)
+ {
+ lua_pushboolean(lua, tb_true);
+ xm_io_file_return_success();
+ }
+ else xm_io_file_return_error(lua, file, "failed to flush file");
+}
diff --git a/core/src/xmake/io/file_isatty.c b/core/src/xmake/io/file_isatty.c
new file mode 100644
index 000000000..e09ea9b13
--- /dev/null
+++ b/core/src/xmake/io/file_isatty.c
@@ -0,0 +1,49 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file_isatty.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file_isatty"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/* file:isatty()
+ */
+tb_int_t xm_io_file_isatty(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // is tty?
+ xm_io_file* file = xm_io_getfile(lua);
+ lua_pushboolean(lua, xm_io_file_is_tty(file));
+ return 1;
+}
diff --git a/core/src/xmake/io/file_path.c b/core/src/xmake/io/file_path.c
new file mode 100644
index 000000000..92ecfa3c5
--- /dev/null
+++ b/core/src/xmake/io/file_path.c
@@ -0,0 +1,55 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file_path.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file_path"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/* file:path()
+ */
+tb_int_t xm_io_file_path(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // this file has been closed?
+ xm_io_file* file = xm_io_getfile(lua);
+ if (xm_io_file_is_closed(file))
+ xm_io_file_return_error_closed(lua);
+ else
+ {
+ // return file path
+ lua_pushstring(lua, file->path);
+ return 1;
+ }
+}
diff --git a/core/src/xmake/io/file_read.c b/core/src/xmake/io/file_read.c
new file mode 100644
index 000000000..7cfae3a93
--- /dev/null
+++ b/core/src/xmake/io/file_read.c
@@ -0,0 +1,554 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file_read.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file_read"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#include "file.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+typedef enum __xm_pushline_state_e
+{
+ PL_EOF,
+ PL_FIN,
+ PL_CONL,
+ PL_FAIL,
+
+} xm_pushline_state_e;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+static tb_long_t xm_io_file_buffer_readline(tb_stream_ref_t stream, tb_buffer_ref_t line)
+{
+ // check
+ tb_assert_and_check_return_val(stream && line, -1);
+
+ // read line and reserve crlf
+ tb_bool_t eof = tb_false;
+ tb_hize_t offset = 0;
+ tb_byte_t* data = tb_null;
+ tb_hong_t size = tb_stream_size(stream);
+ while (size < 0 || (offset = tb_stream_offset(stream)) < size)
+ {
+ tb_long_t real = tb_stream_peek(stream, &data, TB_STREAM_BLOCK_MAXN);
+ if (real > 0)
+ {
+ tb_char_t const* e = tb_strnchr((tb_char_t const*)data, real, '\n');
+ if (e)
+ {
+ tb_size_t n = (tb_byte_t const*)e + 1 - data;
+ if (!tb_stream_skip(stream, n)) return -1;
+ tb_buffer_memncat(line, data, n);
+ break;
+ }
+ else
+ {
+ if (!tb_stream_skip(stream, real)) return -1;
+ tb_buffer_memncat(line, data, real);
+ }
+ }
+ else if (!real)
+ {
+ real = tb_stream_wait(stream, TB_STREAM_WAIT_READ, -1);
+ if (real <= 0)
+ {
+ eof = tb_true;
+ break;
+ }
+ }
+ else
+ {
+ eof = tb_true;
+ break;
+ }
+ }
+
+ // ok?
+ tb_size_t linesize = tb_buffer_size(line);
+ if (linesize) return linesize;
+ else return (eof || tb_stream_beof(stream))? -1 : 0;
+}
+static tb_int_t xm_io_file_buffer_pushline(tb_buffer_ref_t buf, xm_io_file* file, tb_char_t const* continuation, tb_bool_t keep_crlf)
+{
+ // check
+ tb_assert(buf && file && continuation && xm_io_file_is_file(file) && !xm_io_file_is_closed(file));
+
+ // is binary?
+ tb_bool_t is_binary = file->encoding == XM_IO_FILE_ENCODING_BINARY;
+ if (is_binary)
+ {
+ continuation = "";
+ keep_crlf = tb_true;
+ }
+
+ // clear line buffer
+ tb_buffer_clear(&file->rcache);
+
+ // read line data
+ tb_long_t size = xm_io_file_buffer_readline(file->file_ref, &file->rcache);
+
+ // translate line data
+ tb_int_t result = PL_FAIL;
+ tb_char_t* data = tb_null;
+ tb_size_t conlen = tb_strlen(continuation);
+ do
+ {
+ // eof?
+ if (size < 0)
+ {
+ result = PL_EOF;
+ break;
+ }
+
+ // patch two '\0'
+ tb_buffer_memncat(&file->rcache, (tb_byte_t const*)"\0\0", 2);
+
+ // get line data
+ data = (tb_char_t*)tb_buffer_data(&file->rcache);
+ tb_assert_and_check_break(data);
+
+ // no lf found
+ if (size > 0 && data[size - 1] != '\n')
+ result = PL_FIN;
+ else if (size > 1)
+ {
+ // crlf? => lf
+ if (!is_binary && data[size - 2] == '\r')
+ {
+ data[size - 2] = '\n';
+ size--;
+ }
+
+ // has continuation?
+ tb_bool_t has_conline = conlen && size >= conlen + 1 && tb_strncmp(continuation, (tb_char_t const*)(data + size - conlen - 1), conlen) == 0;
+
+ // do not keep crlf, strip the last lf
+ if (!keep_crlf && !has_conline) size--;
+
+ // strip it if has continuation?
+ if (has_conline) size -= conlen + 1;
+ data[size] = '\0';
+
+ result = has_conline ? PL_CONL : PL_FIN;
+ }
+ else
+ {
+ // a single '\n'
+ if (!keep_crlf) size = 0;
+ result = PL_FIN;
+ }
+
+ } while (0);
+
+ // push line data
+ if (data && size > 0 && (result == PL_FIN || result == PL_CONL))
+ tb_buffer_memncat(buf, (tb_byte_t const*)data, size);
+
+ // return result
+ return result;
+}
+static tb_int_t xm_io_file_read_all_directly(lua_State* lua, xm_io_file* file)
+{
+ // check
+ tb_assert(lua && file && xm_io_file_is_file(file) && !xm_io_file_is_closed(file));
+
+ // init buffer
+ tb_buffer_t buf;
+ if (!tb_buffer_init(&buf))
+ xm_io_file_return_error(lua, file, "init buffer failed!");
+
+ // read all
+ tb_byte_t data[TB_STREAM_BLOCK_MAXN];
+ tb_stream_ref_t stream = file->file_ref;
+ while (!tb_stream_beof(stream))
+ {
+ tb_long_t real = tb_stream_read(stream, data, sizeof(data));
+ if (real > 0)
+ tb_buffer_memncat(&buf, data, real);
+ else if (!real)
+ {
+ real = tb_stream_wait(stream, TB_STREAM_WAIT_READ, -1);
+ tb_check_break(real > 0);
+ }
+ else break;
+ }
+
+ if (tb_buffer_size(&buf))
+ lua_pushlstring(lua, (tb_char_t const*)tb_buffer_data(&buf), tb_buffer_size(&buf));
+ else lua_pushliteral(lua, "");
+ tb_buffer_exit(&buf);
+ return 1;
+}
+static tb_int_t xm_io_file_read_all(lua_State* lua, xm_io_file* file, tb_char_t const* continuation)
+{
+ // check
+ tb_assert(lua && file && continuation && xm_io_file_is_file(file) && !xm_io_file_is_closed(file));
+
+ // is binary? read all directly
+ tb_bool_t is_binary = file->encoding == XM_IO_FILE_ENCODING_BINARY;
+ if (is_binary)
+ return xm_io_file_read_all_directly(lua, file);
+
+ // init buffer
+ tb_buffer_t buf;
+ if (!tb_buffer_init(&buf))
+ xm_io_file_return_error(lua, file, "init buffer failed!");
+
+ // read all
+ tb_bool_t has_content = tb_false;
+ while (1)
+ {
+ switch (xm_io_file_buffer_pushline(&buf, file, continuation, tb_true))
+ {
+ case PL_EOF:
+ if (!has_content) lua_pushliteral(lua, "");
+ else lua_pushlstring(lua, (tb_char_t const*)tb_buffer_data(&buf), tb_buffer_size(&buf));
+ tb_buffer_exit(&buf);
+ return 1;
+ case PL_FIN:
+ case PL_CONL:
+ has_content = tb_true;
+ continue;
+ case PL_FAIL:
+ default:
+ tb_buffer_exit(&buf);
+ xm_io_file_return_error(lua, file, "failed to read all");
+ break;
+ }
+ }
+}
+
+static tb_int_t xm_io_file_read_line(lua_State* lua, xm_io_file* file, tb_char_t const* continuation, tb_bool_t keep_crlf)
+{
+ // check
+ tb_assert(lua && file && continuation && xm_io_file_is_file(file) && !xm_io_file_is_closed(file));
+
+ // init buffer
+ tb_buffer_t buf;
+ if (!tb_buffer_init(&buf))
+ xm_io_file_return_error(lua, file, "init buffer failed!");
+
+ // read line
+ tb_bool_t has_content = tb_false;
+ while (1)
+ {
+ switch (xm_io_file_buffer_pushline(&buf, file, continuation, keep_crlf))
+ {
+ case PL_EOF:
+ if (!has_content) lua_pushnil(lua);
+ else lua_pushlstring(lua, (tb_char_t const*)tb_buffer_data(&buf), tb_buffer_size(&buf));
+ tb_buffer_exit(&buf);
+ return 1;
+ case PL_FIN:
+ lua_pushlstring(lua, (tb_char_t const*)tb_buffer_data(&buf), tb_buffer_size(&buf));
+ tb_buffer_exit(&buf);
+ return 1;
+ case PL_CONL:
+ has_content = tb_true;
+ continue;
+ case PL_FAIL:
+ default:
+ tb_buffer_exit(&buf);
+ xm_io_file_return_error(lua, file, "failed to readline");
+ break;
+ }
+ }
+}
+
+static tb_int_t xm_io_file_read_n(lua_State* lua, xm_io_file* file, tb_char_t const* continuation, tb_long_t n)
+{
+ // check
+ tb_assert(lua && file && continuation && xm_io_file_is_file(file) && !xm_io_file_is_closed(file));
+
+ // check continuation
+ if (*continuation != '\0')
+ xm_io_file_return_error(lua, file, "continuation is not supported for read number of bytes");
+
+ // check encoding
+ if (file->encoding != XM_IO_FILE_ENCODING_BINARY)
+ xm_io_file_return_error(lua, file, "read number of bytes only allows binary file, reopen with 'rb' and try again");
+
+ tb_bool_t ok = tb_false;
+ if (n == 0)
+ {
+ tb_byte_t* data = tb_null;
+ if (tb_stream_need(file->file_ref, &data, 1))
+ {
+ lua_pushliteral(lua, "");
+ ok = tb_true;
+ }
+ }
+ else
+ {
+ tb_byte_t* bufptr = tb_buffer_resize(&file->rcache, n + 1);
+ if (bufptr)
+ {
+ if (tb_stream_bread(file->file_ref, bufptr, n))
+ {
+ lua_pushlstring(lua, (tb_char_t const*)bufptr, n);
+ ok = tb_true;
+ }
+ }
+ }
+ if (!ok) lua_pushnil(lua);
+ return 1;
+}
+
+static tb_size_t xm_io_file_std_buffer_pushline(tb_buffer_ref_t buf, xm_io_file* file, tb_char_t const* continuation, tb_bool_t keep_crlf)
+{
+ // check
+ tb_assert(buf && file && continuation && xm_io_file_is_std(file) && !xm_io_file_is_closed(file));
+
+ // get input buffer
+ tb_char_t strbuf[8192];
+ tb_size_t buflen = 0;
+ tb_size_t result = PL_FAIL;
+ if (tb_stdfile_gets(file->std_ref, strbuf, tb_arrayn(strbuf) - 1))
+ buflen = tb_strlen(strbuf);
+ else return PL_EOF;
+
+ tb_size_t conlen = tb_strlen(continuation);
+ if (buflen > 0 && strbuf[buflen - 1] != '\n')
+ {
+ // end of file, no lf found
+ result = PL_FIN;
+ }
+ else if (buflen > 1)
+ {
+ // crlf? => lf
+ if (strbuf[buflen - 2] == '\r')
+ {
+ strbuf[buflen - 2] = '\n';
+ buflen--;
+ }
+
+ // has continuation?
+ tb_bool_t has_conline = conlen && buflen >= conlen + 1 && tb_strncmp(continuation, (strbuf + buflen - conlen - 1), conlen) == 0;
+
+ // do not keep crlf, strip the last lf
+ if (!keep_crlf && !has_conline) buflen--;
+
+ // strip it if has continuation?
+ if (has_conline) buflen -= conlen + 1;
+ strbuf[buflen] = '\0';
+
+ result = has_conline? PL_CONL : PL_FIN;
+ }
+ else
+ {
+ // a single '\n'
+ if (!keep_crlf) buflen = 0;
+ result = PL_FIN;
+ }
+
+ if (result == PL_FIN || result == PL_CONL)
+ tb_buffer_memncat(buf, (tb_byte_t const*)strbuf, buflen);
+ return result;
+}
+
+static tb_int_t xm_io_file_std_read_line(lua_State* lua, xm_io_file* file, tb_char_t const* continuation, tb_bool_t keep_crlf)
+{
+ // check
+ tb_assert(lua && file && continuation && xm_io_file_is_std(file) && !xm_io_file_is_closed(file));
+
+ // init buffer
+ tb_buffer_t buf;
+ if (!tb_buffer_init(&buf))
+ xm_io_file_return_error(lua, file, "init buffer failed!");
+
+ // read line
+ tb_bool_t has_content = tb_false;
+ while (1)
+ {
+ switch (xm_io_file_std_buffer_pushline(&buf, file, continuation, keep_crlf))
+ {
+ case PL_EOF:
+ if (!has_content) lua_pushnil(lua);
+ else lua_pushlstring(lua, (tb_char_t const*)tb_buffer_data(&buf), tb_buffer_size(&buf));
+ tb_buffer_exit(&buf);
+ return 1;
+ case PL_FIN:
+ lua_pushlstring(lua, (tb_char_t const*)tb_buffer_data(&buf), tb_buffer_size(&buf));
+ tb_buffer_exit(&buf);
+ return 1;
+ case PL_CONL:
+ has_content = tb_true;
+ continue;
+ case PL_FAIL:
+ default:
+ tb_buffer_exit(&buf);
+ xm_io_file_return_error(lua, file, "failed to readline");
+ break;
+ }
+ }
+}
+
+static tb_int_t xm_io_file_std_read_all(lua_State* lua, xm_io_file* file, tb_char_t const* continuation)
+{
+ // check
+ tb_assert(lua && file && continuation && xm_io_file_is_std(file) && !xm_io_file_is_closed(file));
+
+ // init buffer
+ tb_buffer_t buf;
+ if (!tb_buffer_init(&buf))
+ xm_io_file_return_error(lua, file, "init buffer failed!");
+
+ // read all
+ tb_bool_t has_content = tb_false;
+ while (1)
+ {
+ switch (xm_io_file_std_buffer_pushline(&buf, file, continuation, tb_true))
+ {
+ case PL_EOF:
+ if (!has_content) lua_pushliteral(lua, "");
+ else lua_pushlstring(lua, (tb_char_t const*)tb_buffer_data(&buf), tb_buffer_size(&buf));
+ tb_buffer_exit(&buf);
+ return 1;
+ case PL_FIN:
+ case PL_CONL:
+ has_content = tb_true;
+ continue;
+ case PL_FAIL:
+ default:
+ tb_buffer_exit(&buf);
+ xm_io_file_return_error(lua, file, "failed to readline");
+ break;
+ }
+ }
+}
+
+static tb_int_t xm_io_file_std_read_n(lua_State* lua, xm_io_file* file, tb_char_t const* continuation, tb_long_t n)
+{
+ // check
+ tb_assert(lua && file && continuation && xm_io_file_is_std(file) && !xm_io_file_is_closed(file));
+
+ // check continuation
+ if (*continuation != '\0')
+ xm_io_file_return_error(lua, file, "continuation is not supported for std streams");
+
+ // io.read(0)
+ if (n == 0)
+ {
+ tb_char_t ch;
+ if (!tb_stdfile_peek(file->std_ref, &ch))
+ lua_pushnil(lua);
+ else
+ lua_pushliteral(lua, "");
+ return 1;
+ }
+
+ // get line buffer
+ tb_byte_t* buf_ptr = tb_buffer_resize(&file->rcache, (tb_size_t)n);
+ tb_assert(buf_ptr);
+
+ // io.read(n)
+ if (tb_stdfile_read(file->std_ref, buf_ptr, (tb_size_t)n))
+ lua_pushlstring(lua, (tb_char_t const*)buf_ptr, (size_t)n);
+ else lua_pushnil(lua);
+ return 1;
+}
+
+static tb_int_t xm_io_file_std_read_num(lua_State* lua, xm_io_file* file, tb_char_t const* continuation)
+{
+ // check
+ tb_assert(lua && file && continuation && xm_io_file_is_std(file) && !xm_io_file_is_closed(file));
+
+ // check continuation
+ if (*continuation != '\0')
+ xm_io_file_return_error(lua, file, "continuation is not supported for std streams");
+
+ // read number
+ tb_char_t strbuf[512];
+ if (tb_stdfile_gets(file->std_ref, strbuf, tb_arrayn(strbuf)))
+ lua_pushnumber(lua, tb_s10tod(strbuf)); // TODO check invalid float number string and push nil
+ else lua_pushnil(lua);
+ return 1;
+}
+
+/*
+ * file:read([mode, [continuation]])
+ * file:read("all", "\\")
+ * file:read("L")
+ * file:read(10)
+ */
+tb_int_t xm_io_file_read(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // get file and arguments
+ xm_io_file* file = xm_io_getfile(lua);
+ tb_char_t const* mode = luaL_optstring(lua, 2, "l");
+ tb_char_t const* continuation = luaL_optstring(lua, 3, "");
+ tb_assert_and_check_return_val(mode && continuation, 0);
+
+ tb_long_t count = -1;
+ if (lua_isnumber(lua, 2))
+ {
+ count = (tb_long_t)lua_tointeger(lua, 2);
+ if (count < 0) xm_io_file_return_error(lua, file, "invalid read size, must be positive nubmber or 0");
+ }
+ else if (*mode == '*')
+ mode++;
+
+ if (xm_io_file_is_file(file))
+ {
+ // this file has been closed?
+ if (xm_io_file_is_closed_file(file))
+ xm_io_file_return_error_closed(lua);
+
+ if (count >= 0) return xm_io_file_read_n(lua, file, continuation, count);
+ switch (*mode)
+ {
+ case 'a': return xm_io_file_read_all(lua, file, continuation);
+ case 'L': return xm_io_file_read_line(lua, file, continuation, tb_true);
+ case 'n': xm_io_file_return_error(lua, file, "read number is not implemented");
+ case 'l': return xm_io_file_read_line(lua, file, continuation, tb_false);
+ default:
+ xm_io_file_return_error(lua, file, "unknonwn read mode");
+ return 0;
+ }
+ }
+ else
+ {
+ if (count >= 0) return xm_io_file_std_read_n(lua, file, continuation, count);
+ switch (*mode)
+ {
+ case 'a': return xm_io_file_std_read_all(lua, file, continuation);
+ case 'L': return xm_io_file_std_read_line(lua, file, continuation, tb_true);
+ case 'n': return xm_io_file_std_read_num(lua, file, continuation);
+ case 'l': return xm_io_file_std_read_line(lua, file, continuation, tb_false);
+ default:
+ xm_io_file_return_error(lua, file, "unknonwn read mode");
+ return 0;
+ }
+ }
+}
diff --git a/core/src/xmake/io/file_seek.c b/core/src/xmake/io/file_seek.c
new file mode 100644
index 000000000..37588fe4f
--- /dev/null
+++ b/core/src/xmake/io/file_seek.c
@@ -0,0 +1,81 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file_seek.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file_seek"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/*
+ * file:seek([whence [, offset]])
+ */
+tb_int_t xm_io_file_seek(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ xm_io_file* file = xm_io_getfile(lua);
+ tb_char_t const* whence = luaL_optstring(lua, 2, "cur");
+ tb_hong_t offset = (tb_hong_t)luaL_optnumber(lua, 3, 0);
+ tb_assert_and_check_return_val(file && whence, 0);
+
+ if (xm_io_file_is_file(file))
+ {
+ if (xm_io_file_is_closed_file(file))
+ xm_io_file_return_error_closed(lua);
+
+ switch (*whence)
+ {
+ case 's': // "set"
+ break;
+ case 'e': // "end"
+ {
+ tb_hong_t size = tb_stream_size(file->file_ref);
+ if (size > 0 && size + offset <= size)
+ offset = size + offset;
+ else xm_io_file_return_error(lua, file, "seek failed, invalid offset!");
+ }
+ break;
+ default: // "cur"
+ offset = tb_stream_offset(file->file_ref) + offset;
+ break;
+ }
+
+ if (tb_stream_seek(file->file_ref, offset))
+ {
+ lua_pushnumber(lua, (lua_Number)offset);
+ xm_io_file_return_success();
+ }
+ else xm_io_file_return_error(lua, file, "seek failed!");
+ }
+ else xm_io_file_return_error(lua, file, "seek is not supported on this file");
+}
diff --git a/core/src/xmake/io/file_write.c b/core/src/xmake/io/file_write.c
new file mode 100644
index 000000000..553b91996
--- /dev/null
+++ b/core/src/xmake/io/file_write.c
@@ -0,0 +1,147 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file file_write.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "file_write"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#include "file.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+static tb_void_t xm_io_file_write_file_directly(xm_io_file* file, tb_char_t const* data, tb_size_t size)
+{
+ // check
+ tb_assert(file && data && xm_io_file_is_file(file) && !xm_io_file_is_closed(file));
+
+ // write data to file
+ tb_stream_bwrit(file->file_ref, (tb_byte_t const*)data, size);
+}
+static tb_void_t xm_io_file_write_file_transcrlf(xm_io_file* file, tb_char_t const* data, tb_size_t size)
+{
+ // check
+ tb_assert(file && data && xm_io_file_is_file(file) && !xm_io_file_is_closed(file));
+
+#ifdef TB_CONFIG_OS_WINDOWS
+
+ // write cached data first
+ tb_byte_t const* odata = tb_buffer_data(&file->wcache);
+ tb_size_t osize = tb_buffer_size(&file->wcache);
+ if (odata && osize)
+ {
+ if (!tb_stream_bwrit(file->file_ref, odata, osize)) return ;
+ tb_buffer_clear(&file->wcache);
+ }
+
+ // write data by lines
+ tb_char_t const* p = (tb_char_t const*)data;
+ tb_char_t const* e = p + size;
+ tb_char_t const* lf = tb_null;
+ while (p < e)
+ {
+ lf = tb_strnchr(p, e - p, '\n');
+ if (lf)
+ {
+ if (lf > p && lf[-1] == '\r')
+ {
+ if (!tb_stream_bwrit(file->file_ref, (tb_byte_t const*)p, lf + 1 - p)) break;
+ }
+ else
+ {
+ if (lf > p && !tb_stream_bwrit(file->file_ref, (tb_byte_t const*)p, lf - p)) break;
+ if (!tb_stream_bwrit(file->file_ref, (tb_byte_t const*)"\r\n", 2)) break;
+ }
+
+ // next line
+ p = lf + 1;
+ }
+ else
+ {
+ // cache the left data
+ tb_buffer_memncat(&file->wcache, (tb_byte_t const*)p, e - p);
+ p = e;
+ break;
+ }
+ }
+#else
+ return xm_io_file_write_file_directly(file, data, size);
+#endif
+}
+static tb_void_t xm_io_file_write_std(xm_io_file* file, tb_char_t const* data, tb_size_t size)
+{
+ // check
+ tb_assert(file && data && xm_io_file_is_std(file) && !xm_io_file_is_closed(file));
+
+ // check type
+ tb_size_t type = (file->type & ~XM_IO_FILE_FLAG_TTY);
+ tb_check_return(type != XM_IO_FILE_TYPE_STDIN);
+
+ // write data to stdout/stderr
+ tb_stdfile_writ(file->std_ref, (tb_byte_t const*)data, size);
+}
+
+/*
+ * file:write(...)
+ */
+tb_int_t xm_io_file_write(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // get file
+ xm_io_file* file = xm_io_getfile(lua);
+ tb_int_t narg = lua_gettop(lua);
+
+ // this file has been closed?
+ if (xm_io_file_is_closed(file))
+ xm_io_file_return_error_closed(lua);
+
+ if (narg > 1)
+ {
+ tb_bool_t is_binary = file->encoding == XM_IO_FILE_ENCODING_BINARY;
+ for (tb_int_t i = 2; i <= narg; i++)
+ {
+ // get data
+ size_t datasize = 0;
+ tb_char_t const* data = luaL_checklstring(lua, i, &datasize);
+ tb_check_continue(datasize);
+ tb_assert_and_check_break(data);
+
+ // write data to std or file
+ if (xm_io_file_is_std(file))
+ xm_io_file_write_std(file, data, (tb_size_t)datasize);
+ else if (is_binary)
+ xm_io_file_write_file_directly(file, data, (tb_size_t)datasize);
+ else
+ xm_io_file_write_file_transcrlf(file, data, (tb_size_t)datasize);
+ }
+ }
+
+ lua_settop(lua, 1);
+ xm_io_file_return_success();
+}
diff --git a/core/src/xmake/io/open.c b/core/src/xmake/io/open.c
new file mode 100644
index 000000000..1507e9235
--- /dev/null
+++ b/core/src/xmake/io/open.c
@@ -0,0 +1,320 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file open.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "open"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+// num of bytes read to guess encoding
+#define CHECK_SIZE (1024)
+
+// is utf-8 tail character
+#define IS_UTF8_TAIL(c) (c >= 0x80 && c < 0xc0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+static tb_size_t xm_io_file_detect_charset(tb_byte_t const** data_ptr, tb_long_t size)
+{
+ // check
+ tb_assert(data_ptr && *data_ptr);
+
+ tb_byte_t const* data = *data_ptr;
+ tb_size_t charset = XM_IO_FILE_ENCODING_BINARY;
+ do
+ {
+ if (size >= 3 && data[0] == 239 && data[1] == 187 && data[2] == 191) // utf-8 with bom
+ {
+ charset = TB_CHARSET_TYPE_UTF8;
+ data += 3; // skip bom
+ break;
+ }
+ if (size >= 2)
+ {
+ if (data[0] == 254 && data[1] == 255) // utf16be
+ {
+ charset = TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_BE;
+ data += 2; // skip bom
+ break;
+ }
+ else if (data[0] == 255 && data[1] == 254) // utf16le
+ {
+ charset = TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_LE;
+ data += 2; // skip bom
+ break;
+ }
+ }
+
+ tb_sint16_t utf16be_conf = 0;
+ tb_sint16_t utf16le_conf = 0;
+ tb_sint16_t utf8_conf = 0;
+ tb_sint16_t ascii_conf = 0;
+ tb_sint16_t zero_count = 0;
+ for (tb_long_t i = 0; i < (size - 4) && i < CHECK_SIZE; i++)
+ {
+ if (data[i] == 0) zero_count++;
+
+ if (data[i] < 0x80)
+ ascii_conf++;
+ else
+ ascii_conf = TB_MINS16;
+
+ if (i % 2 == 0)
+ {
+ if (data[i] == 0) utf16be_conf++;
+ if (data[i + 1] == 0) utf16le_conf++;
+ }
+
+ if (IS_UTF8_TAIL(data[i]))
+ ;
+ else if (data[i] < 0x80)
+ utf8_conf++;
+ else if (data[i] >= 0xc0 && data[i] < 0xe0 && IS_UTF8_TAIL(data[i + 1]))
+ utf8_conf++;
+ else if (data[i] >= 0xe0 && data[i] < 0xf0 && IS_UTF8_TAIL(data[i + 1]) && IS_UTF8_TAIL(data[i + 2]))
+ utf8_conf++;
+ else if (data[i] >= 0xf0 && data[i] < 0xf8 && IS_UTF8_TAIL(data[i + 1]) && IS_UTF8_TAIL(data[i + 2]) && IS_UTF8_TAIL(data[i + 3]))
+ utf8_conf++;
+ else
+ utf8_conf = TB_MINS16;
+ }
+
+ if (ascii_conf > 0 && zero_count <= 1)
+ {
+ charset = TB_CHARSET_TYPE_UTF8;
+ break;
+ }
+ if (utf8_conf > 0 && zero_count <= 1)
+ {
+ charset = TB_CHARSET_TYPE_UTF8;
+ break;
+ }
+ if (utf16be_conf > 0 && utf16be_conf > utf16le_conf)
+ {
+ charset = TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_BE;
+ break;
+ }
+ if (utf16le_conf > 0 && utf16le_conf >= utf16be_conf)
+ {
+ charset = TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_LE;
+ break;
+ }
+ if (utf8_conf > 0)
+ {
+ charset = TB_CHARSET_TYPE_UTF8;
+ break;
+ }
+
+#ifdef TB_CONFIG_OS_WINDOWS
+ charset = TB_CHARSET_TYPE_ANSI;
+#endif
+
+ } while (0);
+
+ *data_ptr = data;
+ return charset;
+}
+static tb_size_t xm_io_file_detect_encoding(tb_stream_ref_t stream, tb_long_t* pbomoff)
+{
+ // check
+ tb_assert_and_check_return_val(stream && pbomoff, XM_IO_FILE_ENCODING_BINARY);
+
+ // detect encoding
+ tb_byte_t* data = tb_null;
+ tb_size_t encoding = XM_IO_FILE_ENCODING_BINARY;
+ tb_long_t size = tb_stream_peek(stream, &data, CHECK_SIZE);
+ if (size > 0)
+ {
+ tb_byte_t const* p = data;
+ encoding = xm_io_file_detect_charset(&p, size);
+ *pbomoff = p - data;
+ }
+ return encoding;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/*
+ * io.open(path, modestr)
+ */
+tb_int_t xm_io_open(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // get file path and mode
+ tb_char_t const* path = luaL_checkstring(lua, 1);
+ tb_char_t const* modestr = luaL_optstring(lua, 2, "r");
+ tb_assert_and_check_return_val(path && modestr, 0);
+
+ // get file mode value
+ tb_size_t mode = TB_FILE_MODE_RW;
+ switch (modestr[0])
+ {
+ case 'w': mode |= TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC; break;
+ case 'a': mode |= TB_FILE_MODE_APPEND | TB_FILE_MODE_CREAT; break;
+ default: break;
+ }
+
+ // get file encoding
+ tb_long_t bomoff = 0;
+ tb_stream_ref_t stream = tb_null;
+ tb_bool_t update = !!tb_strchr(modestr, '+');
+ tb_size_t encoding = XM_IO_FILE_ENCODING_UNKNOWN;
+ if (modestr[1] == 'b' || (update && modestr[2] == 'b'))
+ encoding = XM_IO_FILE_ENCODING_BINARY;
+ else if (tb_strstr(modestr, "utf8") || tb_strstr(modestr, "utf-8"))
+ encoding = TB_CHARSET_TYPE_UTF8;
+ else if (tb_strstr(modestr, "utf16le") || tb_strstr(modestr, "utf-16le"))
+ encoding = TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_LE;
+ else if (tb_strstr(modestr, "utf16be") || tb_strstr(modestr, "utf-16be"))
+ encoding = TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_BE;
+ else if (tb_strstr(modestr, "utf16") || tb_strstr(modestr, "utf-16"))
+ encoding = TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_NE;
+ else if (modestr[0] == 'w' || modestr[0] == 'a') // set to utf-8 if not specified for the writing mode
+ encoding = TB_CHARSET_TYPE_UTF8;
+ else if (modestr[0] == 'r') // detect encoding if not specified for the reading mode
+ {
+ stream = tb_stream_init_from_file(path, mode);
+ if (stream && tb_stream_open(stream))
+ encoding = xm_io_file_detect_encoding(stream, &bomoff);
+ else
+ {
+ if (stream) tb_stream_exit(stream);
+ lua_pushnil(lua);
+ lua_pushliteral(lua, "file not found!");
+ return 2;
+ }
+ }
+ else
+ {
+ lua_pushnil(lua);
+ lua_pushliteral(lua, "invalid open mode!");
+ return 2;
+ }
+ tb_assert_and_check_return_val(encoding != XM_IO_FILE_ENCODING_UNKNOWN, 0);
+
+ // open file
+ tb_bool_t open_ok = tb_false;
+ tb_stream_ref_t file_ref = tb_null;
+ tb_stream_ref_t fstream = tb_null;
+ do
+ {
+ // init stream from file
+ stream = stream? stream : tb_stream_init_from_file(path, mode);
+ tb_assert_and_check_break(stream);
+
+ // is transcode?
+ tb_bool_t is_transcode = encoding != TB_CHARSET_TYPE_UTF8 && encoding != XM_IO_FILE_ENCODING_BINARY;
+ if (is_transcode)
+ {
+ if (modestr[0] == 'r')
+ fstream = tb_stream_init_filter_from_charset(stream, encoding, TB_CHARSET_TYPE_UTF8);
+ else
+ fstream = tb_stream_init_filter_from_charset(stream, TB_CHARSET_TYPE_UTF8, encoding);
+ tb_assert_and_check_break(fstream);
+
+ // use fstream as file
+ file_ref = fstream;
+ }
+ else file_ref = stream;
+
+ // open file stream
+ if (!tb_stream_open(file_ref)) break;
+
+ // skip bom characters if exists
+ if (bomoff > 0 && !tb_stream_seek(stream, bomoff)) break;
+
+ // ok
+ open_ok = tb_true;
+
+ } while (0);
+
+ // open failed?
+ if (!open_ok)
+ {
+ // exit stream
+ if (stream) tb_stream_exit(stream);
+ stream = tb_null;
+
+ // exit charset stream filter
+ if (fstream) tb_stream_exit(fstream);
+ fstream = tb_null;
+
+ // return errors
+ lua_pushnil(lua);
+ lua_pushliteral(lua, "failed to open file.");
+ return 2;
+ }
+
+ // get absolute file path
+ tb_char_t full[TB_PATH_MAXN] = {0};
+ path = tb_path_absolute(path, full, TB_PATH_MAXN);
+ tb_assert_and_check_return_val(path, 0);
+
+ // new file
+ xm_io_file* xm_file = xm_io_newfile(lua);
+ xm_file->file_ref = file_ref;
+ xm_file->stream = stream;
+ xm_file->fstream = fstream;
+ xm_file->mode = mode;
+ xm_file->type = XM_IO_FILE_TYPE_FILE;
+ xm_file->encoding = encoding;
+
+ // init the read/write line cache buffer
+ tb_buffer_init(&xm_file->rcache);
+ tb_buffer_init(&xm_file->wcache);
+
+ // save file path
+ tb_size_t pathlen = tb_strlen(path);
+ xm_file->path = tb_malloc_cstr(pathlen + 1);
+ if (xm_file->path)
+ {
+ tb_strncpy((tb_char_t*)xm_file->path, path, pathlen);
+ ((tb_char_t*)xm_file->path)[pathlen] = '\0';
+ }
+
+ // save file name
+ tb_size_t name_maxn = tb_arrayn(xm_file->name);
+ tb_strlcpy(xm_file->name, "file: ", name_maxn);
+ if (pathlen < name_maxn - tb_arrayn("file: "))
+ tb_strcat(xm_file->name, path);
+ else
+ {
+ tb_strcat(xm_file->name, "...");
+ tb_strcat(xm_file->name, path + (pathlen - name_maxn + tb_arrayn("file: ") + tb_arrayn("...")));
+ }
+ return 1;
+}
diff --git a/core/src/xmake/io/std.c b/core/src/xmake/io/std.c
new file mode 100644
index 000000000..4ee446d85
--- /dev/null
+++ b/core/src/xmake/io/std.c
@@ -0,0 +1,138 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file std.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "io_std"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "file.h"
+#include "prefix.h"
+#include <stdio.h>
+#ifdef TB_CONFIG_OS_WINDOWS
+# include <io.h>
+#else
+# include <unistd.h>
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+static tb_size_t xm_io_std_isatty(tb_size_t type)
+{
+ tb_bool_t answer = tb_false;
+#ifdef TB_CONFIG_OS_WINDOWS
+ DWORD mode;
+ HANDLE console_handle;
+ switch (type)
+ {
+ case XM_IO_FILE_TYPE_STDIN: console_handle = GetStdHandle(STD_INPUT_HANDLE); break;
+ case XM_IO_FILE_TYPE_STDOUT: console_handle = GetStdHandle(STD_OUTPUT_HANDLE); break;
+ case XM_IO_FILE_TYPE_STDERR: console_handle = GetStdHandle(STD_ERROR_HANDLE); break;
+ }
+ answer = GetConsoleMode(console_handle, &mode);
+#else
+ switch (type)
+ {
+ case XM_IO_FILE_TYPE_STDIN: answer = isatty(fileno(stdin)); break;
+ case XM_IO_FILE_TYPE_STDOUT: answer = isatty(fileno(stdout)); break;
+ case XM_IO_FILE_TYPE_STDERR: answer = isatty(fileno(stderr)); break;
+ }
+#endif
+
+ if (answer) type |= XM_IO_FILE_FLAG_TTY;
+ return type;
+}
+
+static tb_void_t xm_io_std_init(lua_State* lua, tb_size_t type)
+{
+ // check
+ tb_assert_and_check_return(lua);
+
+ tb_char_t const* name = tb_null;
+ tb_char_t const* path = tb_null;
+ tb_stdfile_ref_t fp = tb_null;
+ switch (type)
+ {
+ case XM_IO_FILE_TYPE_STDIN:
+ name = "stdin";
+ fp = tb_stdfile_input();
+ break;
+ case XM_IO_FILE_TYPE_STDOUT:
+ name = "stdout";
+ fp = tb_stdfile_output();
+ break;
+ case XM_IO_FILE_TYPE_STDERR:
+ name = "stderr";
+ fp = tb_stdfile_error();
+ break;
+ }
+#ifdef TB_CONFIG_OS_WINDOWS
+ path = "CON"; // console device
+#else
+ switch (type)
+ {
+ case XM_IO_FILE_TYPE_STDIN: path = "/dev/stdin"; break;
+ case XM_IO_FILE_TYPE_STDOUT: path = "/dev/stdout"; break;
+ case XM_IO_FILE_TYPE_STDERR: path = "/dev/stderr"; break;
+ }
+#endif
+ tb_assert_and_check_return(name && path && fp);
+
+ // new file
+ xm_io_file* file = xm_io_newfile(lua);
+ tb_assert_and_check_return(file);
+ lua_setfield(lua, -2, name);
+
+ // init file
+ file->encoding = TB_CHARSET_TYPE_UTF8;
+ file->type = xm_io_std_isatty(type);
+ file->path = path;
+ file->std_ref = fp;
+ file->stream = tb_null;
+ file->fstream = tb_null;
+
+ // init name
+ tb_char_t const* info = xm_io_file_is_tty(file) ? "" : " redirected";
+ tb_snprintf(file->name, tb_arrayn(file->name), "file: (%s%s)", name, info);
+
+ // init the line cache buffer
+ tb_buffer_init(&file->rcache);
+ tb_buffer_init(&file->wcache);
+}
+
+tb_int_t xm_io_std(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // init io.stdin, io.stdout and io.stderr
+ lua_getglobal(lua, "io");
+ xm_io_std_init(lua, XM_IO_FILE_TYPE_STDIN);
+ xm_io_std_init(lua, XM_IO_FILE_TYPE_STDOUT);
+ xm_io_std_init(lua, XM_IO_FILE_TYPE_STDERR);
+ lua_pop(lua, 1);
+ return 0;
+}
diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c
index 2ca2227c5..77661a445 100644
--- a/core/src/xmake/machine.c
+++ b/core/src/xmake/machine.c
@@ -31,6 +31,8 @@
#include "xmake.h"
#if defined(TB_CONFIG_OS_WINDOWS)
# include <windows.h>
+# include <io.h>
+# include <fcntl.h>
#elif defined(TB_CONFIG_OS_MACOSX)
# include <mach-o/dyld.h>
#elif defined(TB_CONFIG_OS_LINUX)
@@ -53,6 +55,8 @@ typedef struct __xm_machine_t
* declaration
*/
+// the global functions
+
// the os functions
tb_int_t xm_os_argv(lua_State* lua);
tb_int_t xm_os_find(lua_State* lua);
@@ -88,7 +92,20 @@ tb_int_t xm_os_getown(lua_State* lua);
#endif
// the io functions
-tb_int_t xm_io_isatty(lua_State* lua);
+tb_int_t xm_io_std(lua_State* lua);
+tb_int_t xm_io_open(lua_State* lua);
+
+// the file functions
+tb_int_t xm_io_file_read(lua_State* lua);
+tb_int_t xm_io_file_seek(lua_State* lua);
+tb_int_t xm_io_file_write(lua_State* lua);
+tb_int_t xm_io_file_flush(lua_State* lua);
+tb_int_t xm_io_file_close(lua_State* lua);
+tb_int_t xm_io_file_isatty(lua_State* lua);
+tb_int_t xm_io_file_path(lua_State* lua);
+tb_int_t xm_io_file___len(lua_State* lua);
+tb_int_t xm_io_file___tostring(lua_State* lua);
+tb_int_t xm_io_file___gc(lua_State* lua);
// the path functions
tb_int_t xm_path_relative(lua_State* lua);
@@ -102,6 +119,11 @@ tb_int_t xm_hash_sha256(lua_State* lua);
// the windows functions
#ifdef TB_CONFIG_OS_WINDOWS
+tb_int_t xm_winos_cp_info(lua_State* lua);
+tb_int_t xm_winos_console_cp(lua_State* lua);
+tb_int_t xm_winos_console_output_cp(lua_State* lua);
+tb_int_t xm_winos_ansi_cp(lua_State* lua);
+tb_int_t xm_winos_oem_cp(lua_State* lua);
tb_int_t xm_winos_logical_drives(lua_State* lua);
tb_int_t xm_winos_registry_query(lua_State* lua);
#endif
@@ -186,19 +208,40 @@ static luaL_Reg const g_os_functions[] =
#ifdef TB_CONFIG_OS_WINDOWS
static luaL_Reg const g_winos_functions[] =
{
- { "logical_drives", xm_winos_logical_drives }
-, { "registry_query", xm_winos_registry_query }
-, { tb_null, tb_null }
+ { "cp_info", xm_winos_cp_info }
+, { "console_cp", xm_winos_console_cp }
+, { "console_output_cp", xm_winos_console_output_cp }
+, { "oem_cp", xm_winos_oem_cp }
+, { "ansi_cp", xm_winos_ansi_cp }
+, { "logical_drives", xm_winos_logical_drives }
+, { "registry_query", xm_winos_registry_query }
+, { tb_null, tb_null }
};
#endif
// the io functions
static luaL_Reg const g_io_functions[] =
{
- { "isatty", xm_io_isatty }
+ { "open", xm_io_open }
, { tb_null, tb_null }
};
+// the file functions
+static luaL_Reg const g_io_file_functions[] =
+{
+ { "read", xm_io_file_read }
+, { "seek", xm_io_file_seek }
+, { "write", xm_io_file_write }
+, { "flush", xm_io_file_flush }
+, { "isatty", xm_io_file_isatty }
+, { "path", xm_io_file_path }
+, { "close", xm_io_file_close }
+, { "__gc", xm_io_file___gc }
+, { "__len", xm_io_file___len }
+, { "__tostring", xm_io_file___tostring }
+, { tb_null, tb_null }
+};
+
// the path functions
static luaL_Reg const g_path_functions[] =
{
@@ -274,15 +317,25 @@ static tb_bool_t xm_machine_save_arguments(xm_machine_t* machine, tb_int_t argc,
// check
tb_assert_and_check_return_val(machine && machine->lua && argc >= 1 && argv, tb_false);
+#ifdef TB_CONFIG_OS_WINDOWS
+ tb_wchar_t **argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
+#endif
+
// put a new table into the stack
- lua_newtable(machine->lua);
+ lua_createtable(machine->lua, argc, 0);
// save all arguments to the new table
tb_int_t i = 0;
for (i = 1; i < argc; i++)
{
+#ifdef TB_CONFIG_OS_WINDOWS
+ tb_char_t argvbuf[4096] = {0};
+ tb_wcstombs(argvbuf, argvw[i], tb_arrayn(argvbuf));
// table_new[table.getn(table_new) + 1] = argv[i]
+ lua_pushstring(machine->lua, argvbuf);
+#else
lua_pushstring(machine->lua, argv[i]);
+#endif
lua_rawseti(machine->lua, -2, (int)lua_objlen(machine->lua, -2) + 1);
}
@@ -303,10 +356,13 @@ static tb_size_t xm_machine_get_program_file(xm_machine_t* machine, tb_char_t* p
{
#if defined(TB_CONFIG_OS_WINDOWS)
// get the executale file path as program directory
- tb_size_t size = (tb_size_t)GetModuleFileName(tb_null, path, (DWORD)maxn);
- tb_assert_and_check_break(size < maxn);
-
+ tb_wchar_t buf[TB_PATH_MAXN] = {0};
+ tb_size_t size = (tb_size_t)GetModuleFileNameW(tb_null, buf, (DWORD)TB_PATH_MAXN);
+ tb_assert_and_check_break(size < TB_PATH_MAXN);
// end
+ buf[size] = L'\0';
+ size = tb_wcstombs(path, buf, maxn);
+ tb_assert_and_check_break(size < maxn);
path[size] = '\0';
// ok
@@ -520,6 +576,26 @@ xm_machine_ref_t xm_machine_init()
// bind io functions
luaL_register(machine->lua, "io", g_io_functions);
+ // bind file functions
+ // stack: {metatable}
+ luaL_newmetatable(machine->lua, "XM_IO_FILE*");
+ // stack: {metatable}, {metatable}
+ lua_pushvalue(machine->lua, -1);
+ // stack: {metatable, __index = {metatable}}
+ lua_setfield(machine->lua, -2, "__index");
+ // stack: {metatable}, {io}
+ lua_getglobal(machine->lua, "io");
+ // stack: {metatable}, {io}, {metatable}
+ lua_pushvalue(machine->lua, -2);
+ // stack: {metatable}, {io, file = {metatable}}
+ lua_setfield(machine->lua, -2, "file");
+ // stack: {metatable}
+ lua_pop(machine->lua, 1);
+ // stack:
+ luaL_register(machine->lua, NULL, g_io_file_functions);
+ // add stdin,stdout,stderr to io
+ xm_io_std(machine->lua);
+
// bind path functions
luaL_register(machine->lua, "path", g_path_functions);
@@ -643,6 +719,10 @@ tb_int_t xm_machine_main(xm_machine_ref_t self, tb_int_t argc, tb_char_t** argv)
xm_machine_t* machine = (xm_machine_t*)self;
tb_assert_and_check_return_val(machine && machine->lua, -1);
+#ifdef TB_CONFIG_OS_WINDOWS
+ if (_isatty(_fileno(stdin))) _setmode(_fileno(stdin), _O_U16TEXT);
+#endif
+
// save main arguments to the global variable: _ARGV
if (!xm_machine_save_arguments(machine, argc, argv)) return -1;
diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile
index b51504cee..f35becda6 100644
--- a/core/src/xmake/makefile
+++ b/core/src/xmake/makefile
@@ -44,7 +44,17 @@ xmake_C_FILES += \
os/uid \
os/gid \
os/getown \
- io/isatty \
+ io/file___len \
+ io/file___tostring \
+ io/file_close___gc \
+ io/file_flush \
+ io/file_isatty \
+ io/file_path \
+ io/file_read \
+ io/file_seek \
+ io/file_write \
+ io/open \
+ io/std \
path/relative \
path/absolute \
path/translate \
diff --git a/core/src/xmake/os/find.c b/core/src/xmake/os/find.c
index 198e0a5bf..3a1271048 100644
--- a/core/src/xmake/os/find.c
+++ b/core/src/xmake/os/find.c
@@ -90,7 +90,7 @@ static tb_bool_t xm_os_find_walk(tb_char_t const* path, tb_file_info_t const* in
tb_assert_and_check_return_val(rootdir && rootlen, tb_false);
// check
- tb_assert(!tb_strcmp(path, rootdir));
+ tb_assert(!tb_strncmp(path, rootdir, rootlen));
tb_assert(rootlen + 1 <= tb_strlen(path));
// skip the rootdir if not "."
diff --git a/core/src/xmake/sandbox/interactive.c b/core/src/xmake/sandbox/interactive.c
index 6fc643520..95d01a19c 100644
--- a/core/src/xmake/sandbox/interactive.c
+++ b/core/src/xmake/sandbox/interactive.c
@@ -29,17 +29,19 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
-#define TB_TRACE_MODULE_NAME "sandbox.interactive"
-#define TB_TRACE_MODULE_DEBUG (0)
+#define TB_TRACE_MODULE_NAME "sandbox.interactive"
+#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
+#include "../winos/ansi.h"
#ifdef XM_CONFIG_API_HAVE_READLINE
-# include <stdio.h> // on some OS (like centos) required
-# include <readline/readline.h>
# include <readline/history.h>
+# include <readline/readline.h>
+# include <stdlib.h>
+# include <stdio.h> // on some OS (like centos) required
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -47,10 +49,13 @@
*/
// interactive prompt
-#define LUA_PROMPT "> "
+#define LUA_PROMPT "> "
// continuation prompt
-#define LUA_PROMPT2 ">> "
+#define LUA_PROMPT2 ">> "
+
+// buffer size for prompt
+#define LUA_PROMPT_BUFSIZE 4096
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
@@ -59,7 +64,7 @@
// report results
static tb_void_t xm_sandbox_report(lua_State *lua)
{
- if (!lua_isnil(lua, -1))
+ if (!lua_isnil(lua, -1))
{
// get message
tb_char_t const* msg = lua_tostring(lua, -1);
@@ -77,14 +82,14 @@ static tb_void_t xm_sandbox_report(lua_State *lua)
// the traceback function
static tb_int_t xm_sandbox_traceback(lua_State *lua)
{
- if (!lua_isstring(lua, 1))
+ if (!lua_isstring(lua, 1))
{
// non-string error object? try metamethod.
if (lua_isnoneornil(lua, 1) || !luaL_callmeta(lua, 1, "__tostring") || !lua_isstring(lua, -1))
- return 1; // return non-string error object.
-
+ return 1; // return non-string error object.
+
// replace object by result of __tostring metamethod.
- lua_remove(lua, 1);
+ lua_remove(lua, 1);
}
// return backtrace
@@ -92,8 +97,8 @@ static tb_int_t xm_sandbox_traceback(lua_State *lua)
return 1;
}
-// execute codes
-static tb_int_t xm_sandbox_docall(lua_State *lua, tb_int_t narg, tb_int_t clear)
+// execute codes
+static tb_int_t xm_sandbox_docall(lua_State* lua, tb_int_t narg, tb_int_t clear)
{
/* get error function index
*
@@ -105,19 +110,19 @@ static tb_int_t xm_sandbox_docall(lua_State *lua, tb_int_t narg, tb_int_t clear)
lua_pushcfunction(lua, xm_sandbox_traceback);
// put it under chunk and args
- lua_insert(lua, errfunc);
+ lua_insert(lua, errfunc);
/* execute it
*
- * stack: errfunc arg1 scriptfunc -> ...
- * after: errfunc arg1 [results] -> ...
+ * stack: errfunc arg1 scriptfunc -> ...
+ * after: errfunc arg1 [results] -> ...
*/
- tb_int_t status = lua_pcall(lua, narg, (clear? 0 : LUA_MULTRET), errfunc);
+ tb_int_t status = lua_pcall(lua, narg, (clear ? 0 : LUA_MULTRET), errfunc);
// remove traceback function
- lua_remove(lua, errfunc);
+ lua_remove(lua, errfunc);
- // force a complete garbage collection in case of errors
+ // force a complete garbage collection in case of errors
if (status != 0) lua_gc(lua, LUA_GCCOLLECT, 0);
// ok?
@@ -128,12 +133,12 @@ static tb_int_t xm_sandbox_docall(lua_State *lua, tb_int_t narg, tb_int_t clear)
static tb_int_t xm_sandbox_incomplete(lua_State *lua, tb_int_t status)
{
// syntax error?
- if (status == LUA_ERRSYNTAX)
+ if (status == LUA_ERRSYNTAX)
{
- size_t lmsg;
+ size_t lmsg;
tb_char_t const* msg = lua_tolstring(lua, -1, &lmsg);
- tb_char_t const* tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
- if (tb_strstr(msg, LUA_QL("<eof>")) == tp)
+ tb_char_t const* tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
+ if (tb_strstr(msg, LUA_QL("<eof>")) == tp)
{
lua_pop(lua, 1);
return 1;
@@ -156,35 +161,34 @@ static tb_size_t xm_sandbox_readline(tb_char_t* data, tb_size_t maxn, tb_char_t
tb_size_t size = tb_strlcpy(data, line, maxn);
// free line
- tb_free(line);
+ free((void*)line);
// truncated?
- if (size >= maxn)
- return 0;
+ if (size >= maxn) return 0;
// ok
return size;
}
#else
-
+
// print prompt
tb_printf(prompt);
tb_print_sync();
// get input buffer
- if (fgets(data, (tb_int_t)maxn, stdin))
+ if (tb_stdfile_gets(tb_stdfile_input(), data, maxn))
return tb_strlen(data);
#endif
-
+
// no more input
return 0;
}
// read and push input line
-static tb_int_t xm_sandbox_pushline(lua_State *lua)
+static tb_int_t xm_sandbox_pushline(lua_State* lua)
{
// read line
- tb_char_t data[1024];
+ tb_char_t data[LUA_PROMPT_BUFSIZE];
tb_size_t size = xm_sandbox_readline(data, sizeof(data), LUA_PROMPT2);
if (size)
{
@@ -204,14 +208,14 @@ static tb_int_t xm_sandbox_pushline(lua_State *lua)
}
// load code line
-static tb_int_t xm_sandbox_loadline(lua_State *lua, tb_int_t top)
+static tb_int_t xm_sandbox_loadline(lua_State* lua, tb_int_t top)
{
- // clear stack
+ // clear stack
lua_settop(lua, top);
// read first line
tb_int_t status;
- tb_char_t data[1024];
+ tb_char_t data[LUA_PROMPT_BUFSIZE];
tb_size_t size = xm_sandbox_readline(data + 7, sizeof(data) - 7, LUA_PROMPT);
if (size)
{
@@ -221,13 +225,13 @@ static tb_int_t xm_sandbox_loadline(lua_State *lua, tb_int_t top)
// patch "return "
tb_memcpy(data, "return ", 7);
-
+
// attempt to load "return ..."
status = luaL_loadbuffer(lua, data, size + 7, "=stdin");
// ok?
if (status != LUA_ERRSYNTAX) return status;
-
+
// pop error msg
lua_pop(lua, 1);
@@ -238,7 +242,7 @@ static tb_int_t xm_sandbox_loadline(lua_State *lua, tb_int_t top)
// load input line
while (1)
- {
+ {
/* repeat until gets a complete line
*
* stack: arg1(sandbox_scope) scriptbuffer(top) -> ...
@@ -250,15 +254,14 @@ static tb_int_t xm_sandbox_loadline(lua_State *lua, tb_int_t top)
if (!xm_sandbox_incomplete(lua, status)) break;
// get more input
- if (!xm_sandbox_pushline(lua))
- return -1;
+ if (!xm_sandbox_pushline(lua)) return -1;
// cancel multi-line input?
if (!tb_strcmp(lua_tostring(lua, -1), "q"))
{
lua_pop(lua, 2);
lua_pushstring(lua, "return ");
- continue ;
+ continue;
}
/* add a new line
@@ -268,7 +271,7 @@ static tb_int_t xm_sandbox_loadline(lua_State *lua, tb_int_t top)
lua_pushliteral(lua, "\n");
// between the two lines
- lua_insert(lua, -2);
+ lua_insert(lua, -2);
/* join them
*
@@ -279,7 +282,7 @@ static tb_int_t xm_sandbox_loadline(lua_State *lua, tb_int_t top)
}
// remove redundant scriptbuffer
- lua_remove(lua, -2);
+ lua_remove(lua, -2);
return status;
}
@@ -299,9 +302,9 @@ tb_int_t xm_sandbox_interactive(lua_State* lua)
*/
tb_int_t top = lua_gettop(lua);
- // enter interactive
+ // enter interactive
tb_int_t status;
- while ((status = xm_sandbox_loadline(lua, top)) != -1)
+ while ((status = xm_sandbox_loadline(lua, top)) != -1)
{
// execute codes
if (status == 0)
@@ -321,12 +324,13 @@ tb_int_t xm_sandbox_interactive(lua_State* lua)
}
// report errors
- if (status) xm_sandbox_report(lua);
+ if (status)
+ xm_sandbox_report(lua);
// print any results
- if (status == 0 && lua_gettop(lua) > top)
+ if (status == 0 && lua_gettop(lua) > top)
{
- // get results count
+ // get results count
tb_int_t count = lua_gettop(lua) - top;
/* dump results
@@ -341,7 +345,7 @@ tb_int_t xm_sandbox_interactive(lua_State* lua)
}
}
- // clear stack
+ // clear stack
lua_settop(lua, top);
tb_printl("");
tb_print_sync();
diff --git a/core/src/xmake/string/convert.c b/core/src/xmake/string/convert.c
index 32e5088ed..a6edd5692 100644
--- a/core/src/xmake/string/convert.c
+++ b/core/src/xmake/string/convert.c
@@ -48,15 +48,20 @@ typedef struct __xm_charset_entry_t
// the charsets, @note: type & name is sorted
static xm_charset_entry_t g_charsets[] =
{
- {TB_CHARSET_TYPE_ASCII, "ascii" }
-, {TB_CHARSET_TYPE_GB2312, "gb2312" }
-, {TB_CHARSET_TYPE_GBK, "gbk" }
-, {TB_CHARSET_TYPE_ISO8859, "iso8859" }
-, {TB_CHARSET_TYPE_UCS2, "ucs3" }
-, {TB_CHARSET_TYPE_UCS4, "ucs4" }
-, {TB_CHARSET_TYPE_UTF16, "utf16" }
-, {TB_CHARSET_TYPE_UTF32, "utf32" }
-, {TB_CHARSET_TYPE_UTF8, "utf8" }
+ {TB_CHARSET_TYPE_ANSI, "ansi" }
+, {TB_CHARSET_TYPE_ASCII, "ascii" }
+, {TB_CHARSET_TYPE_GB2312, "gb2312" }
+, {TB_CHARSET_TYPE_GBK, "gbk" }
+, {TB_CHARSET_TYPE_ISO8859, "iso8859" }
+, {TB_CHARSET_TYPE_UCS2, "ucs2" }
+, {TB_CHARSET_TYPE_UCS4, "ucs4" }
+, {TB_CHARSET_TYPE_UTF16, "utf16" }
+, {TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_BE, "utf16be" }
+, {TB_CHARSET_TYPE_UTF16 | TB_CHARSET_TYPE_LE, "utf16le" }
+, {TB_CHARSET_TYPE_UTF32, "utf32" }
+, {TB_CHARSET_TYPE_UTF32 | TB_CHARSET_TYPE_BE, "utf32be" }
+, {TB_CHARSET_TYPE_UTF32 | TB_CHARSET_TYPE_LE, "utf32le" }
+, {TB_CHARSET_TYPE_UTF8, "utf8" }
};
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -122,10 +127,10 @@ tb_int_t xm_string_convert(lua_State* lua)
tb_byte_t* dst_data = tb_malloc_bytes(dst_maxn);
if (dst_data && dst_maxn && (dst_size = tb_charset_conv_data(fcharset->type, tcharset->type, (tb_byte_t const*)src_cstr, (tb_size_t)src_size, dst_data, dst_maxn)) >= 0 && dst_size < dst_maxn)
{
- dst_data[dst_size] = '\0';
- lua_pushstring(lua, (tb_char_t const*)dst_data);
+ lua_pushlstring(lua, (tb_char_t const *)dst_data, dst_size);
}
else lua_pushnil(lua);
+ tb_free(dst_data);
}
// ok
diff --git a/core/src/xmake/winos/ansi.c b/core/src/xmake/winos/ansi.c
new file mode 100644
index 000000000..2d56d77a9
--- /dev/null
+++ b/core/src/xmake/winos/ansi.c
@@ -0,0 +1,169 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file ansi.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "ansi"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "ansi.h"
+#include <Windows.h>
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+static tb_int_t xm_expand_cp(tb_int_t cp)
+{
+ // check
+ tb_assert_and_check_return_val(cp >= 0 && cp <= 65535, 0);
+
+ if (cp == CP_OEMCP) return GetOEMCP();
+ if (cp == CP_ACP) return GetACP();
+ return cp;
+}
+
+tb_int_t xm_winos_console_cp(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ tb_int_t n = lua_gettop(lua);
+ if (n >= 1)
+ {
+ lua_Integer cp = luaL_checkinteger(lua, 1);
+ luaL_argcheck(lua, cp >= 0 && cp < 65536, 1, "invalid code page");
+ cp = xm_expand_cp((tb_uint_t)cp);
+ luaL_argcheck(lua, SetConsoleCP((tb_uint_t)cp), 1, "failed to set code page");
+ lua_pushinteger(lua, cp);
+ return 1;
+ }
+ else
+ {
+ tb_uint_t cp = GetConsoleCP();
+ lua_pushinteger(lua, (lua_Integer)cp);
+ return 1;
+ }
+}
+
+tb_int_t xm_winos_console_output_cp(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ tb_int_t n = lua_gettop(lua);
+ if (n >= 1)
+ {
+ lua_Integer cp = luaL_checkinteger(lua, 1);
+ luaL_argcheck(lua, cp >= 0 && cp < 65536, 1, "invalid code page");
+ cp = xm_expand_cp((tb_uint_t)cp);
+ luaL_argcheck(lua, SetConsoleOutputCP((tb_uint_t)cp), 1, "failed to set code page");
+ lua_pushinteger(lua, cp);
+ return 1;
+ }
+ else
+ {
+ tb_uint_t cp = GetConsoleOutputCP();
+ lua_pushinteger(lua, (lua_Integer)cp);
+ return 1;
+ }
+}
+
+tb_int_t xm_winos_cp_info(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ tb_int_t n = lua_gettop(lua);
+ lua_Integer cp = luaL_checkinteger(lua, 1);
+ luaL_argcheck(lua, cp >= 0 && cp < 65536, 1, "invalid code page");
+ CPINFOEX cp_info;
+ luaL_argcheck(lua, GetCPInfoEx((tb_uint_t)cp, 0, &cp_info), 1, "invalid code page");
+
+ lua_newtable(lua);
+
+ lua_pushliteral(lua, "name");
+ tb_char_t* namebuf = tb_malloc_cstr(sizeof(cp_info.CodePageName) * 2);
+ tb_assert_and_check_return_val(namebuf, 0);
+ tb_size_t namelen = tb_wtoa(namebuf, cp_info.CodePageName, sizeof(cp_info.CodePageName) * 2);
+ tb_assert_and_check_return_val(namelen < sizeof(cp_info.CodePageName) * 2, 0);
+ lua_pushlstring(lua, namebuf, namelen);
+ tb_free(namebuf);
+ lua_settable(lua, -3);
+
+ lua_pushliteral(lua, "max_char_size");
+ lua_pushinteger(lua, (lua_Integer)cp_info.MaxCharSize);
+ lua_settable(lua, -3);
+
+ lua_pushliteral(lua, "id");
+ lua_pushinteger(lua, (lua_Integer)cp_info.CodePage);
+ lua_settable(lua, -3);
+
+ lua_pushliteral(lua, "default_char");
+ lua_pushstring(lua, (tb_char_t const*)cp_info.DefaultChar);
+ lua_settable(lua, -3);
+
+ lua_pushliteral(lua, "lead_byte");
+ lua_createtable(lua, MAX_LEADBYTES / 2, 0);
+ for (tb_size_t i = 0; i < MAX_LEADBYTES && cp_info.LeadByte[i] != 0 && cp_info.LeadByte[i + 1] != 0; i += 2)
+ {
+ lua_pushinteger(lua, (i / 2) + 1);
+ lua_createtable(lua, 0, 2);
+
+ lua_pushliteral(lua, "from");
+ lua_pushinteger(lua, cp_info.LeadByte[i]);
+ lua_settable(lua, -3);
+
+ lua_pushliteral(lua, "to");
+ lua_pushinteger(lua, cp_info.LeadByte[i + 1]);
+ lua_settable(lua, -3);
+
+ lua_settable(lua, -3);
+ }
+ lua_settable(lua, -3);
+
+ return 1;
+}
+
+tb_int_t xm_winos_ansi_cp(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ tb_uint_t cp = GetACP();
+ lua_pushinteger(lua, (lua_Integer)cp);
+ return 1;
+}
+
+tb_int_t xm_winos_oem_cp(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ tb_uint_t cp = GetOEMCP();
+ lua_pushinteger(lua, (lua_Integer)cp);
+ return 1;
+}
+
diff --git a/core/src/xmake/winos/ansi.h b/core/src/xmake/winos/ansi.h
new file mode 100644
index 000000000..fe07d15ba
--- /dev/null
+++ b/core/src/xmake/winos/ansi.h
@@ -0,0 +1,29 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author OpportunityLiu
+ * @file ansi.h
+ *
+ */
+#ifndef XM_WINOS_ANSI_H
+#define XM_WINOS_ANSI_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+#endif
diff --git a/core/src/xmake/winos/registry_query.c b/core/src/xmake/winos/registry_query.c
index afee6192e..7f759278b 100644
--- a/core/src/xmake/winos/registry_query.c
+++ b/core/src/xmake/winos/registry_query.c
@@ -161,7 +161,7 @@ tb_int_t xm_winos_registry_query(lua_State* lua)
// get registry value size
DWORD valuesize = 0;
- if (RegQueryValueEx(keynew, valuename, tb_null, tb_null, tb_null, &valuesize) != ERROR_SUCCESS)
+ if (RegQueryValueExA(keynew, valuename, tb_null, tb_null, tb_null, &valuesize) != ERROR_SUCCESS)
{
lua_pushnil(lua);
lua_pushfstring(lua, "get registry value size failed: %s", path);
@@ -174,7 +174,7 @@ tb_int_t xm_winos_registry_query(lua_State* lua)
// get value result
type = 0;
- if (RegQueryValueEx(keynew, valuename, tb_null, &type, (LPBYTE)value, &valuesize) != ERROR_SUCCESS)
+ if (RegQueryValueExA(keynew, valuename, tb_null, &type, (LPBYTE)value, &valuesize) != ERROR_SUCCESS)
{
lua_pushnil(lua);
lua_pushfstring(lua, "get registry value failed: %s", path);
diff --git a/core/src/xmake/xmake.lua b/core/src/xmake/xmake.lua
index d1bd77107..c3df93473 100644
--- a/core/src/xmake/xmake.lua
+++ b/core/src/xmake/xmake.lua
@@ -9,6 +9,9 @@ target("xmake")
-- add defines
add_defines("__tb_prefix__=\"xmake\"")
+ if is_mode("debug") then
+ add_defines("__tb_debug__", {public = true})
+ end
-- set the auto-generated config.h
set_configdir("$(buildir)/$(plat)/$(arch)/$(mode)")
@@ -23,11 +26,15 @@ target("xmake")
if is_plat("windows") then
add_files("winos/*.c")
end
-
+
-- add readline
- add_options("readline")
+ add_options("readline")
+
if is_plat("windows") or has_config("curses") then
add_defines("XM_CONFIG_API_HAVE_CURSES")
end
+ if is_plat("windows") then
+ add_defines("UNICODE", "_UNICODE")
+ end