summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author彭宣正 <[email protected]>2022-09-05 19:02:21 +0800
committer彭宣正 <[email protected]>2022-09-05 19:02:21 +0800
commitfb53526b29c8092aed85ec73f17b470df379e95a (patch)
treee86299eee557ae966a7ec0586ed261230852d285 /src
parenta113b321346908f982574fa421c14813511e1b06 (diff)
✨ feat(TSG-11870): 重构lua代码
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt10
-rw-r--r--src/elua.h (renamed from src/tsg_lua_interface.h)19
-rw-r--r--src/elua_func.cpp1572
-rw-r--r--src/tsg_lua_func.cpp1945
4 files changed, 1585 insertions, 1961 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ac7c491..a00dd77 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -4,14 +4,10 @@ aux_source_directory(. DIR_LIB_SRCS)
include_directories("${LUAJIT_INSTALL_PREFIX}/include/luajit-2.1")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -shared -fPIC")
-SET(CMAKE_CXX_DEBUG_FLAGS "${CMAKE_CXX_DEBUG_FLAGS} -DTSG_LUA_DEBUG")
+SET(CMAKE_CXX_DEBUG_FLAGS "${CMAKE_CXX_DEBUG_FLAGS} -Delua_DEBUG")
SET(CMAKE_BUILD_TYPE "Release")
-option(TSG_LUA_DEBUG "If enabled, the SDK will be print debuginfo." OFF)
-
-if (TSG_LUA_DEBUG)
- add_definitions(-DTSG_LUA_DEBUG)
-endif()
+option(elua_DEBUG "If enabled, the SDK will be print debuginfo." OFF)
if (BUILD_STATIC_LIB)
add_library(${lib_name}_static STATIC ${DIR_LIB_SRCS})
@@ -34,5 +30,5 @@ else()
install(TARGETS ${lib_name}_shared LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib COMPONENT LIBRARIES)
endif()
-install(FILES ${CMAKE_SOURCE_DIR}/src/tsg_lua_interface.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/MESA COMPONENT HEADER)
+install(FILES ${CMAKE_SOURCE_DIR}/src/elua.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/MESA COMPONENT HEADER)
install(PROGRAMS ${CMAKE_SOURCE_DIR}/example/checktools/checktools.lua DESTINATION ${LUAJIT_INSTALL_PREFIX}/bin COMPONENT LIBRARIES) \ No newline at end of file
diff --git a/src/tsg_lua_interface.h b/src/elua.h
index d0a753d..b080a3f 100644
--- a/src/tsg_lua_interface.h
+++ b/src/elua.h
@@ -32,7 +32,7 @@ struct elua_data
struct elua_vm;
-/* function name: elua_vm_create
+/* function name: elua_create_vm
* input: char *name the name of virtual machine, default: "TSG"
* return value: elua_handle successed,return a virtual machine; failed, return NULL*/
struct elua_vm *elua_create_vm(const char *vm_name);
@@ -41,7 +41,7 @@ int elua_remove_function(struct elua_vm *vm, const char *elua_function);
const char *elua_get_last_error_string(struct elua_vm *vm);
-/* function name: destory_lua
+/* function name: destroy_lua
* input: elua_handle L a virtual machine
* return value: int successed, return 0; failed, return error code */
int elua_destroy_vm(struct elua_vm *vm);
@@ -75,14 +75,14 @@ int elua_register_cbinding(struct elua_vm *vm, const char *func_space_name, cons
struct elua_context;
-/* function name: elua_script_context_malloc
+/* function name: elua_context_malloc
* input: elua_handle L
- * return value: elua_script_context failed, return NULL; successed, return a context*/
+ * return value: elua_context failed, return NULL; successed, return a context*/
struct elua_context *elua_create_context(struct elua_vm *vm, const char *ctx_name);
-/* function name: elua_script_context_free
+/* function name: elua_context_free
* input: elua_handle L
- * input: elua_script_context context context waiting to free
+ * input: elua_context context context waiting to free
* return value: int successed, return 0; failed, return -1 */
int elua_destroy_context(struct elua_context *ctx);
@@ -95,15 +95,16 @@ struct elua_script;
*
* return value: int successed, return a script id which is bigger than 1; failed, return error code */
struct elua_script *elua_cache_script(struct elua_vm *vm, const char *script, size_t script_len, size_t timeout_ms);
+struct elua_script *elua_cache_script_file(struct elua_vm *vm, const char *script, size_t timeout_ms);
-/* function name: elua_cache_exec
+/* function name: elua_execute_script
* input: elua_handle L a virtual machine
* size_t script_id a script id
* struct elua_data_t in data waiting to be handled
* void *userdata can get the userdata with elua_get_userdata(L)
- * elua_script_context context Can accessed with lua-name.context in lua script
+ * elua_context context Can accessed with lua-name.context in lua script
* size_t timeout_ms Maximum time to run the script.if timeout_ms > 0, jit.off; timeout_ms == 0, jit.on, not expired.
- * output: struct elua_arg_t *outvalue Requires input of an expected type that is not NIL, the type of the result that will be output after the call is complete
+ * output: struct estruct elua_data *outvalue Requires input of an expected type that is not NIL, the type of the result that will be output after the call is complete
* return value: int successed, return 0; failed, return error code */
int elua_execute_script(struct elua_script *escript, const char *input, size_t input_len, void *userdata, struct elua_context *ctx, struct elua_data *output);
diff --git a/src/elua_func.cpp b/src/elua_func.cpp
new file mode 100644
index 0000000..f550e47
--- /dev/null
+++ b/src/elua_func.cpp
@@ -0,0 +1,1572 @@
+/*************************************************************************
+ > File Name: elua_func.c
+ > Author: pxz
+ > Created Time: Wed 08 Jul 2020 03:45:55 PM CST
+ ************************************************************************/
+extern "C"
+{
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+#include<setjmp.h>
+#include<time.h>
+#include "lualib.h"
+#include "luajit.h"
+#include "lauxlib.h"
+}
+#include"elua.h"
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b))?(a):(b))
+#endif
+
+
+#define MAX_BEGIN_CODE_SIZE 23
+#define MAX_END_CODE_SIZE 22
+
+#define TEXT_BEGIN_CODE "return function()"
+#define TEXT_BEGIN_SIZE (sizeof(TEXT_BEGIN_CODE) - 1)
+#define TEXT_INIT_CODE "\nlocal newglobaltable = {}\nsetmetatable(newglobaltable, {__index = _G})\nsetfenv(1, newglobaltable)"
+#define TEXT_INIT_SIZE (sizeof(TEXT_INIT_CODE) - 1)
+#define TEXT_END_CODE "\nend"
+#define TEXT_END_SIZE (sizeof(TEXT_END_CODE) - 1)
+
+/* bytecode for luajit 2.0 */
+#define LJ20_BYTECODE_END_STRIPPED \
+ "\x14\x03\x00\x01\x00\x01\x00\x03" \
+ "\x31\x00\x00\x00\x30\x00\x00\x80\x48\x00\x02\x00" \
+ "\x00\x00"
+#define LJ20_BYTECODE_END_SIZE (sizeof(LJ20_BYTECODE_END_STRIPPED) - 1)
+
+/* bytecode for luajit 2.1 */
+#define LJ21_BYTECODE_END_STRIPPED \
+ "\x14\x03\x00\x01\x00\x01\x00\x03" \
+ "\x33\x00\x00\x00\x32\x00\x00\x80\x4c\x00\x02\x00" \
+ "\x00\x00"
+
+#define LJ21_BYTECODE_END_SIZE (sizeof(LJ21_BYTECODE_END_STRIPPED) - 1)
+
+/* bytecode for both */
+#define LJ_BYTECODE_LEN_STRIPPED 22
+#define LJ_HEADERSIZE 5
+#define LJ_BCDUMP_F_BE 0x01
+#define LJ_BCDUMP_F_STRIP 0x02
+#define LJ21_BCDUMP_VERSION 2
+#define LJ20_BCDUMP_VERSION 1
+#define LJ_SIGNATURE "\x1b\x4c\x4a"
+
+// #define EXEC_ERROR_INFO_NUM ((int)(sizeof(exec_error) / sizeof(exec_error_massage_t)))
+// #define SYNTAX_ERROR_INFO_NUM ((int)(sizeof(syntax_error) / sizeof(char *)))
+
+
+// typedef struct{
+// const char *err_info1;
+// const char *err_info2;
+// }exec_error_massage_t;
+
+enum{
+ elua_READER_BUFFSIZE = 4096
+};
+
+typedef enum{
+ elua_TEXT_FILE,
+ elua_BC_LUA,
+ elua_BC_LJ
+}elua_clfactory_file_type_t;
+
+typedef struct{
+ const char *s;
+ elua_clfactory_file_type_t file_type;
+ int sent_begin;
+ int sent_end;
+ int size;
+
+ size_t begin_code_len;
+ size_t end_code_len;
+ size_t rest_len;
+ const char *begin_code_ptr;
+ const char *end_code_ptr;
+}elua_clfactory_buffer_t;
+
+typedef struct{
+ FILE *f;
+ elua_clfactory_file_type_t file_type;
+ int extraline;
+ int sent_begin;
+ int sent_end;
+
+ size_t begin_code_len;
+ size_t end_code_len;
+ size_t rest_len;
+ union{
+ const char *ptr;
+ char str[MAX_BEGIN_CODE_SIZE];
+ }begin_code;
+ const char *end_code_ptr;
+
+ char buff[elua_READER_BUFFSIZE];
+}elua_clfactory_file_t;
+
+typedef struct elua_private_info
+{
+ jmp_buf *elua_exception;
+ char elua_name[1024];
+ void *userdata;
+ int errcode;
+ char errmsg[1024];
+ int elua_mode;
+#define elua_JIT_ON 0
+#define elua_JIT_OFF 1
+ long time_now;
+ long time_limit;
+ bool is_expired; //not return error from C, when the script was ran in C and time out,
+ // keep this status and not return error until the script run in LUA
+ int lua_stack_top;
+}elua_private_info_t;
+
+typedef struct elua_context
+{
+ int context_id;
+ char *context_name;
+ lua_State *el;
+}elua_context_t;
+
+// static const char *syntax_error[] =
+// {
+// "'end' expected", /* ERR_SCRIPT_END_EXPECTED */
+// "'then' expected", /* ERR_SCRIPT_THEN_EXPECTED */
+// "'do' expected", /* ERR_SCRIPT_DO_EXPECTED */
+// "'<eof>' expected", /* ERR_SCRIPT_EOF_EXPECTED */
+// "'=' or 'in' expected", /* ERR_SCRIPT_EQUAL_IN_EXPECTED */
+// "unexpected symbol", /* ERR_SCRIPT_UNEXPECTED_SYMBOL */
+// "'<name>' expected", /* ERR_SCRIPT_NAME_EXPECT */
+// "')' expected", /* ERR_SCRIPT_RIGHT_CURVES_BRACKET */
+// "'}' expected", /* ERR_SCRIPT_RIGHT_CURLY_BRACKET */
+// };
+
+// static exec_error_massage_t exec_error[] =
+// {
+// {"bad argument", "(string expected, got nil)"}, /* ERR_SCRIPT_STRING_EXPECTED_BUT_NIL */
+// {"bad argument", "(string expected, got boolean)"}, /* ERR_SCRIPT_STRING_EXPECTED_BUT_BOOL */
+// {"bad argument", "(string expected, got table)"}, /* ERR_SCRIPT_STRING_EXPECTED_BUT_TABLE */
+// {"attempt to call global", "(a nil value)"}, /* ERR_SCRIPT_CALL_GLOBAL_BUT_NIL */
+// };
+
+static long mstime()
+{
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return now.tv_sec * 1000 + now.tv_nsec/1000000;
+}
+
+static long elua_clfactory_file_size(FILE *f)
+{
+ long cur_pos, len;
+ cur_pos = ftell(f);
+ if (cur_pos == -1)
+ {
+ return -1;
+ }
+
+ if (fseek(f, 0, SEEK_END) != 0)
+ {
+ return -1;
+ }
+
+ len = ftell(f);
+ if (len == -1)
+ {
+ return -1;
+ }
+
+ if (fseek(f, cur_pos, SEEK_SET) != 0)
+ {
+ return -1;
+ }
+
+ return len;
+}
+
+static void elua_clfactory_file_text_prepare(elua_clfactory_file_t *lf)
+{
+ lf->begin_code.ptr = TEXT_BEGIN_CODE;
+ lf->begin_code_len = TEXT_BEGIN_SIZE;
+ lf->end_code_ptr = TEXT_END_CODE;
+ lf->end_code_len = TEXT_END_SIZE;
+}
+
+static int elua_clfactory_bytecode_buffer_prepare(elua_clfactory_buffer_t *ls, char *errmsg)
+{
+ int little_endian, version, stripped;
+
+ if (ls == NULL)
+ return -1;
+
+ if (ls->file_type == elua_BC_LJ)
+ {
+ /* get bytecode header */
+ if (ls->size <= LJ_HEADERSIZE)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] script is bad.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ ls->size--;
+ /* get bytecode version */
+ version = (int)(ls->s[3]);
+
+ /* compare bytecode header */
+ if (strncmp(ls->s, LJ_SIGNATURE, sizeof(LJ_SIGNATURE) - 1))
+ {
+ snprintf(errmsg, 1023, "[%s:%d] bad byte-code header.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ /* little endian or big little endian */
+ little_endian = !((ls->s[4]) & LJ_BCDUMP_F_BE);
+ if (little_endian == 0)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] not support byte-code coding by big-endian.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ /* stripped or debug */
+ stripped = (ls->s[4]) & LJ_BCDUMP_F_STRIP;
+ if (!stripped)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] not support byte-code include debug-info.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ ls->end_code_len = LJ_BYTECODE_LEN_STRIPPED;
+ if (version == LJ21_BCDUMP_VERSION)
+ {
+ ls->end_code_ptr = LJ21_BYTECODE_END_STRIPPED;
+ }
+#if 0
+ else if (version == LJ20_BCDUMP_VERSION)
+ {
+ ls->end_code_ptr = LJ20_BYTECODE_END_STRIPPED;
+ }
+#endif
+ else
+ {
+ snprintf(errmsg, 1023, "[%s:%d] bytecode format version unsupported.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int elua_clfactory_bytecode_file_prepare(elua_clfactory_file_t *lf, char *errmsg)
+{
+ *lf->begin_code.str = LUA_SIGNATURE[0];
+ if (lf->file_type == elua_BC_LJ)
+ {
+ /* get bytecode header */
+ size_t size = fread(lf->begin_code.str + 1, 1, LJ_HEADERSIZE - 1, lf->f);
+ if (size != LJ_HEADERSIZE - 1)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] can not read header.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ /* get bytecode version */
+ int version = *(lf->begin_code.str + 3);
+
+ /* compare bytecode header */
+ if (strncmp(lf->begin_code.str, LJ_SIGNATURE, sizeof(LJ_SIGNATURE) - 1))
+ {
+ snprintf(errmsg, 1023, "[%s:%d] bad byte-code header.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ lf->begin_code_len = LJ_HEADERSIZE;
+
+ /* little endian or big little endian */
+ int little_endian = !((*(lf->begin_code.str + 4)) & LJ_BCDUMP_F_BE);
+ if (little_endian == 0)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] not support byte-code coding by big-endian.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ /* stripped or debug */
+ int stripped = (*(lf->begin_code.str + 4)) & LJ_BCDUMP_F_STRIP;
+ if (!stripped)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] not support byte-code include debug-info.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ if (version == LJ21_BCDUMP_VERSION)
+ {
+ lf->end_code_ptr = LJ21_BYTECODE_END_STRIPPED;
+ lf->end_code_len = LJ_BYTECODE_LEN_STRIPPED;
+ }else if (version == LJ20_BCDUMP_VERSION)
+ {
+ lf->end_code_ptr = LJ20_BYTECODE_END_STRIPPED;
+ lf->end_code_len = LJ_BYTECODE_LEN_STRIPPED;
+ }else
+ {
+ snprintf(errmsg, 1023, "[%s:%d] bytecode format version unsupported.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ long fsize = elua_clfactory_file_size(lf->f);
+ if (fsize < 0)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] script is bad.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ lf->rest_len = fsize - LJ_HEADERSIZE;
+ }
+ return 0;
+}
+
+static const char * elua_gets(lua_State *L, void *ud, size_t *size)
+{
+ (void)L;
+ elua_clfactory_buffer_t *ls = (elua_clfactory_buffer_t *)ud;
+ if (ls->file_type == elua_TEXT_FILE)
+ {
+ if (ls->sent_begin == 0)
+ {
+ ls->sent_begin = 1;
+ *size = ls->begin_code_len;
+ return ls->begin_code_ptr;
+ }
+ }
+ if (ls->size == 0)
+ {
+ if (ls->sent_end == 0)
+ {
+ ls->sent_end = 1;
+ *size = ls->end_code_len;
+ return ls->end_code_ptr;
+ }
+ return NULL;
+ }
+
+ if (ls->file_type == elua_BC_LJ)
+ {
+#if 0
+ lf->rest_len -= ls->size;
+ if (lf->rest_len == 0)
+ {
+ if (--ls->size == 0 && lf->sent_end == 0)
+ {
+ lf->sent_end = 1;
+ *size = lf->end_code_len;
+
+ return lf->end_code_ptr;
+ }
+ }
+#endif
+ }
+
+ *size = ls->size;
+ ls->size = 0;
+
+ return ls->s;
+}
+
+static const char * elua_getf(lua_State *L, void *ud, size_t *size)
+{
+ (void)L;
+ elua_clfactory_file_t *lf = (elua_clfactory_file_t *)ud;
+ if (lf->extraline == 1)
+ {
+ lf->extraline = 0;
+ *size = 1;
+ return "\n";
+ }
+
+ if (lf->sent_begin == 0)
+ {
+ lf->sent_begin = 1;
+ *size = lf->begin_code_len;
+ if (lf->file_type == elua_TEXT_FILE)
+ {
+ return lf->begin_code.ptr;
+ }else
+ {
+ return lf->begin_code.str;
+ }
+ }
+ size_t num = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
+ if (num == 0)
+ {
+ if (lf->sent_end == 0)
+ {
+ lf->sent_end = 1;
+ *size = lf->end_code_len;
+ return lf->end_code_ptr;
+ }
+ return NULL;
+ }
+
+ if (lf->file_type == elua_BC_LJ)
+ {
+ lf->rest_len -= num;
+ if (lf->rest_len == 0)
+ {
+ if (--num == 0 && lf->sent_end == 0)
+ {
+ lf->sent_end = 1;
+ *size = lf->end_code_len;
+
+ return lf->end_code_ptr;
+ }
+ }
+ }
+ *size = num;
+ return lf->buff;
+}
+
+static int c_lua_atpanic(lua_State *L)
+{
+ char *s = NULL;
+ size_t len = 0;
+ jmp_buf *elua_exception;
+ elua_private_info_t *elua_info = NULL;
+
+ elua_info = (elua_private_info_t *)lua_getexdata(L);
+ elua_exception = elua_info->elua_exception;
+ if (lua_type(L, -1) == LUA_TSTRING)
+ {
+ s = (char *)lua_tolstring(L, -1, &len);
+ }
+
+ if (s == NULL)
+ {
+ s = (char *)"unknow reason";
+ len = strlen(s);
+ }
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] lua atpanic:lua VM creashed, reson:%*s.", __FUNCTION__, __LINE__, (int)len, s);
+ longjmp(*elua_exception, 1);
+}
+
+int elua_memmem(lua_State *L)
+{
+ const char *src;
+ const char *dest;
+ size_t src_len, dest_len;
+ const char *ret;
+ int start, end;
+ int parameter_num = lua_gettop(L);
+ if (parameter_num != 4)
+ {
+ return 0;
+ }
+
+ src = lua_tostring(L, -4);
+ src_len = lua_tointeger(L, -3);
+ dest = lua_tostring(L, -2);
+ dest_len = lua_tointeger(L, -1);
+
+ if (!src || !dest || !src_len || !dest_len)
+ {
+ return 0;
+ }
+
+ ret = (const char *)memmem(src, src_len, dest, dest_len);
+ if (ret == NULL)
+ {
+ return 0;
+ }
+ start = ret - src;
+ end = start + dest_len;
+ lua_pushinteger(L, start);
+ lua_pushinteger(L, end);
+
+ return 2;
+}
+
+struct elua_vm
+{
+ lua_State *L;
+};
+
+static void luaMaskCountHook(struct elua_vm *vm, lua_Debug *ar)
+{
+ lua_State *L = (lua_State *)vm;
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+
+ if (elua_info->is_expired == true)
+ {
+ if (ar->what && memcmp(ar->what, "C", 1) == 0)
+ {
+ return;
+ }
+ else
+ {
+ lua_pushstring(L, "Lua script killed by time out.");
+ lua_error(L);
+ return;
+ }
+ }
+
+ long elapsed = mstime() - elua_info->time_now;
+ if ( elua_info->time_limit > 0 && elapsed > elua_info->time_limit)
+ {
+ //printf("elasped:%ld\n", elapsed);
+ if (ar->what && memcmp(ar->what, "C", 1) == 0)
+ {
+ elua_info->is_expired = true;
+ // reset the interval to a shorter time
+ int hook_granularity = elua_info->time_limit * 1000000 / 1000; //about time_limt / 1000
+ lua_sethook(L, (lua_Hook)luaMaskCountHook, LUA_MASKCOUNT, hook_granularity);
+ }
+ else
+ {
+ lua_pushstring(L, "Lua script killed by time out.");
+ lua_error(L);
+ }
+ }
+}
+
+static int elua_set_script_timeout(struct lua_State *L, int ms)
+{
+ if (L == NULL)
+ {
+ return -1;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (ms < 0)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ elua_info->time_limit = ms;
+ if (ms == 0)
+ {
+ elua_info->elua_mode = elua_JIT_ON;
+ luaJIT_setmode(L, 1, LUAJIT_MODE_FUNC | LUAJIT_MODE_ON);
+ }
+ else
+ {
+ elua_info->elua_mode = elua_JIT_OFF;
+ luaJIT_setmode(L, 1, LUAJIT_MODE_FUNC | LUAJIT_MODE_OFF);
+ int hook_granularity = ms * 1000000 / 20; // about ms / 20
+ lua_sethook(L, (lua_Hook)luaMaskCountHook, LUA_MASKCOUNT, hook_granularity);
+ }
+
+ return 0;
+}
+
+struct elua_vm *elua_create_vm(const char *name)
+{
+ if (name == NULL)
+ {
+ name = "TSG";
+ }
+ lua_State *L;
+ jmp_buf *elua_exception = (jmp_buf *)malloc(sizeof(jmp_buf));
+ if (elua_exception == NULL)
+ {
+ return NULL;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)calloc(1, sizeof(elua_private_info_t));
+ if (elua_info == NULL)
+ {
+ free(elua_exception);
+ return NULL;
+ }
+
+ L = luaL_newstate();
+ if (L == NULL)
+ {
+ free(elua_exception);
+ free(elua_info);
+ return NULL;
+ }
+ elua_info->elua_exception = elua_exception;
+ int len = strlen(name);
+ memcpy(elua_info->elua_name, name, MIN(1023, len));
+ elua_info->elua_name[len] = '\0';
+ elua_info->userdata = NULL;
+ lua_setexdata(L, elua_info);
+ lua_atpanic(L, c_lua_atpanic);
+ luaL_openlibs(L);
+ lua_newtable(L);
+ lua_pushcfunction(L, elua_memmem);
+ lua_setfield(L, -2, "memmem");
+ lua_setglobal(L, name);
+
+ return (struct elua_vm *)L;
+}
+
+static int elua_script_check_and_clfactory(struct elua_vm *vm, const char *script, int script_len, elua_clfactory_buffer_t *ls, char *errmsg)
+{
+ int i = 0;
+ int sharp = 0;
+
+ if (script[0] == '#')
+ {
+ for (i = 0; i < ls->size; i++)
+ {
+ if (script[i] == '\n')
+ {
+ /* skip extra line */
+ ls->s = &script[i];
+ ls->size = script_len - i;
+ break;
+ }
+ }
+ if (i == ls->size)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] Script syntax error.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ sharp = 1;
+ }
+ if (script[i] == LUA_SIGNATURE[0])
+ {
+ /* use luajit virtual machine rather then la virtual machine */
+ ls->file_type = elua_BC_LJ;
+ if (sharp)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] Script is bad.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ int status = elua_clfactory_bytecode_buffer_prepare(ls, errmsg);
+ if (status != 0)
+ {
+ return status;
+ }
+
+ }else
+ {
+ ls->file_type = elua_TEXT_FILE;
+ ls->begin_code_ptr = TEXT_BEGIN_CODE;
+ ls->begin_code_len = TEXT_BEGIN_SIZE;
+ ls->end_code_ptr = TEXT_END_CODE;
+ ls->end_code_len = TEXT_END_SIZE;
+ }
+
+ return 0;
+}
+
+static int elua_load_buff(lua_State *L, elua_clfactory_buffer_t *ls, char *errmsg)
+{
+ int ret = lua_load(L, elua_gets, ls, "string");
+ if (ret != 0)
+ {
+ if (ret == LUA_ERRMEM)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] Lua memory is not enough.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ else if (lua_isstring(L, -1))
+ {
+ const char *err = lua_tostring(L, -1);
+ snprintf(errmsg, 1023, "[%s:%d] %s.", __FUNCTION__, __LINE__, err);
+ return -1;
+ }
+ else
+ {
+ snprintf(errmsg, 1023, "[%s:%d] Lua load failed.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+struct elua_script
+{
+ size_t script_id;
+ size_t timeout_ms;
+ elua_vm *vm;
+};
+
+struct elua_script *elua_cache_script(struct elua_vm *vm, const char *script, size_t script_len, size_t timeout_ms)
+{
+ size_t script_id = 0;
+ const char *err = NULL;
+ int ret = 0;
+ elua_clfactory_buffer_t ls;
+ lua_State *L = (lua_State *)vm;
+
+ if (L == NULL)
+ {
+ return NULL;
+ }
+
+ elua_private_info_t * elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (script == NULL || script_len == 0)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ memset(&ls, 0, sizeof(elua_clfactory_buffer_t));
+ ls.s = script;
+ ls.size = script_len;
+ ls.sent_begin = 0;
+ ls.sent_end = 0;
+
+ lua_settop(L, 0);
+ ret = elua_script_check_and_clfactory(vm, script, script_len, &ls, elua_info->errmsg);
+ if (ret < 0)
+ {
+ return NULL;
+ }
+
+ ret = elua_load_buff(L, &ls, elua_info->errmsg);
+ if (ret < 0)
+ {
+ return NULL;
+ }
+
+ if (lua_pcall(L, 0, LUA_MULTRET, 0))
+ {
+ err = lua_tostring(L, -1);
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] %s.", __FUNCTION__, __LINE__, err);
+ return NULL;
+ }
+
+ script_id = luaL_ref(L, LUA_REGISTRYINDEX);
+ if ((script_id == (size_t)LUA_REFNIL) || (script_id == (size_t)LUA_NOREF))
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Lua cache failed.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ struct elua_script *escript = (struct elua_script *)malloc(sizeof(elua_script));
+ escript->script_id = script_id;
+ escript->timeout_ms = timeout_ms;
+ escript->vm = vm;
+
+ return escript;
+}
+
+struct elua_script *elua_cache_script_file(struct elua_vm *vm, const char *script, size_t timeout_ms)
+{
+ size_t script_id;
+ const char *err = NULL;
+ int ret = 0;
+ int sharp = 0;
+ elua_clfactory_file_t lf;
+ lua_State *L = (lua_State *)vm;
+
+
+ if (L == NULL)
+ {
+ return NULL;
+ }
+ elua_private_info_t * elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (script == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ lf.extraline = 0;
+ lf.sent_begin = 0;
+ lf.sent_end = 0;
+ lf.file_type = elua_TEXT_FILE;
+
+ lf.f = fopen(script, "r");
+ if (lf.f == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] script %s not exist.", __FUNCTION__, __LINE__, script);
+ return NULL;
+ }
+ int c = getc(lf.f);
+ if (c == '#')
+ {
+ lf.extraline = 1;
+ while ((c = getc(lf.f)) != EOF && c != '\n')
+ {
+ /* skip first line */
+ }
+ if (c == '\n')
+ {
+ c = getc(lf.f);
+ }
+ sharp = 1;
+ }
+
+ if (c == LUA_SIGNATURE[0])
+ {
+ lf.f = freopen(script, "rb", lf.f);
+ if (lf.f == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] script %s not exist.", __FUNCTION__, __LINE__, script);
+ return NULL;
+ }
+ lf.file_type = elua_BC_LJ;
+ if (sharp)
+ {
+ /*
+ * Loading bytecode with an extra header is disabled for security
+ * reasons. This may circumvent the usual check for bytecode vs.
+ * Lua code by looking at the first char. Since this is a potential
+ * security violation no attempt is made to echo the chunkname either.
+ */
+ fclose(lf.f);
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] script %s is bad.", __FUNCTION__, __LINE__, script);
+ return NULL;
+ }
+
+ while((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0])
+ {
+ /* skip eventual "#! ..." */
+ }
+ int status = elua_clfactory_bytecode_file_prepare(&lf, elua_info->errmsg);
+ if(status != 0)
+ {
+ return NULL;
+ }
+ lf.extraline = 0;
+ }else
+ {
+ elua_clfactory_file_text_prepare(&lf);
+ ungetc(c, lf.f);
+ }
+ lua_settop(L, 0);
+ ret = lua_load(L, elua_getf, &lf, script);
+ fclose(lf.f);
+ if (ret != 0)
+ {
+ if (ret == LUA_ERRMEM)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Lua memory is not enough.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ else if (lua_isstring(L, -1))
+ {
+ err = lua_tostring(L, -1);
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] %s.", __FUNCTION__, __LINE__, err);
+ return NULL;
+ }
+ else
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] lua load failed.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ }
+ /* set new globaltable */
+ lua_createtable(L, 0, 1);
+ lua_pushvalue(L, -1);
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ lua_setfield(L, -2, "__index");
+ lua_setmetatable(L, -2);
+ lua_setfenv(L, -2);
+
+ if (lua_pcall(L, 0, LUA_MULTRET, 0))
+ {
+ err = lua_tostring(L, -1);
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] %s.", __FUNCTION__, __LINE__, err);
+ return NULL;
+ }
+
+ /* cache script */
+ script_id = luaL_ref(L, LUA_REGISTRYINDEX);
+ if ((script_id == (size_t)LUA_REFNIL) || (script_id == (size_t)LUA_NOREF))
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] luaL_ref failed.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ struct elua_script *escript = (struct elua_script *)malloc(sizeof(elua_script));
+ escript->script_id = script_id;
+ escript->timeout_ms = timeout_ms;
+ escript->vm = vm;
+
+ return escript;
+}
+
+int elua_cleanup_script(struct elua_script *script)
+{
+ if (script == NULL)
+ {
+ return -1;
+ }
+
+ lua_State *L = (lua_State *)script->vm;
+ if (L == NULL)
+ {
+ return -1;
+ }
+
+ luaL_unref(L, LUA_REGISTRYINDEX, script->script_id);
+
+ return 0;
+}
+
+int elua_destroy_vm(struct elua_vm *vm)
+{
+ elua_private_info_t *elua_info = NULL;
+ lua_State *L = (lua_State *)vm;
+
+ if (L == NULL)
+ {
+ return -1;
+ }
+ elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (elua_info != NULL)
+ {
+ if (elua_info->elua_exception != NULL)
+ {
+ free(elua_info->elua_exception);
+ }
+ free(elua_info);
+ }
+
+ lua_close(L);
+ return 0;
+}
+
+
+void *elua_get_execute_userdata(struct elua_vm *vm)
+{
+ lua_State *L = (lua_State *)vm;
+ if (vm == NULL)
+ {
+ return NULL;
+ }
+ elua_private_info_t * elua_info = (elua_private_info_t *)lua_getexdata(L);
+
+ if (elua_info != NULL)
+ {
+ return elua_info->userdata;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+int elua_register_cbinding(struct elua_vm *vm, const char *elua_func_namespace, const char *elua_func_name, elua_cbinding_func_ptr const function)
+{
+ lua_State *L = (lua_State *)vm;
+ if (L == NULL)
+ {
+ return -1;
+ }
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (elua_func_name == NULL || function == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ lua_getglobal(L, elua_info->elua_name);
+ if (elua_func_namespace != NULL)
+ {
+ lua_getfield(L, -1, elua_func_namespace);
+ int ret = lua_type(L, -1);
+ if (ret != LUA_TTABLE)
+ {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ lua_pushcfunction(L, (lua_CFunction)function);
+ lua_setfield(L, -2, elua_func_name);
+ lua_setfield(L, -2, elua_func_namespace);
+ }
+ else
+ {
+ lua_pushcfunction(L, (lua_CFunction)function);
+ lua_setfield(L, -2, elua_func_name);
+ }
+ }
+ else
+ {
+ lua_pushcfunction(L, (lua_CFunction)function);
+ lua_setfield(L, -2, elua_func_name);
+ }
+ lua_settop(L, 0);
+
+ return 0;
+}
+
+elua_context_t *elua_create_context(struct elua_vm *vm, const char *ctx_name)
+{
+ lua_State *L = (lua_State *)vm;
+ if (L == NULL)
+ {
+ return NULL;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (ctx_name == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ lua_newtable(L);
+ int context_id = luaL_ref(L, LUA_REGISTRYINDEX);
+ if (context_id == LUA_REFNIL || context_id == LUA_NOREF)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] luaL_ref failed.", __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ lua_settop(L, 0);
+
+ struct elua_context *context = (struct elua_context *)malloc(sizeof(struct elua_context));
+ context->context_id = context_id;
+ int len = strlen(ctx_name);
+ context->context_name = (char *)malloc(len+1);
+ memcpy(context->context_name, ctx_name, len);
+ context->context_name[len] = '\0';
+ context->el = (lua_State *)vm;
+
+ return context;
+}
+
+int elua_destroy_context(struct elua_context *context)
+{
+ if (context == NULL)
+ {
+ return -1;
+ }
+
+ lua_pushnil(context->el);
+ lua_setglobal(context->el, context->context_name);
+ luaL_unref(context->el, LUA_REGISTRYINDEX, context->context_id);
+
+ if (context->context_name != NULL)
+ {
+ free(context->context_name);
+ context->context_name = NULL;
+ }
+ free(context);
+
+ return 0;
+}
+
+static void elua_set_context(lua_State *L, const char *elua_name, int context_id, const char *context_name)
+{
+ if (L != NULL && elua_name != NULL && context_id != LUA_REFNIL && context_id != LUA_NOREF && context_name != NULL)
+ {
+ lua_getglobal(L, elua_name);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, context_id);
+ lua_setfield(L, -2, context_name);
+ lua_pop(L, 1);
+ }
+}
+
+static void elua_set_data(lua_State *L, const char *elua_name, const char *data, int data_len)
+{
+ if (L != NULL && elua_name != NULL && data != NULL && data_len > 0)
+ {
+ int top = lua_gettop(L);
+ lua_getglobal(L, elua_name);
+ lua_pushlstring(L, data, data_len);
+ lua_setfield(L, -2, "data");
+ lua_settop(L, top);
+ }
+}
+
+static int elua_call_script(lua_State *L, int script_id, char *errmsg)
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, script_id);
+
+ if (lua_pcall(L, 0, LUA_MULTRET, 0))
+ {
+ const char *err = lua_tostring(L, -1);
+ snprintf(errmsg, 1023, "[%s:%d] %s.", __FUNCTION__, __LINE__, err);
+ return -1;
+ }
+ return 0;
+}
+
+static int elua_vm_return_value(lua_State *L, struct elua_data *output, char *errmsg)
+{
+ if (output == NULL)
+ {
+ //Do not care about return value
+ lua_settop(L, 0);
+ }
+ else
+ {
+ int num = lua_gettop(L);
+ if (num == 0)
+ {
+ // return nothing
+ snprintf(errmsg, 1023, "[%s:%d] script return nothing.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ else if (num == 2)
+ {
+ output->len = lua_tonumber(L, -2);
+ if (output->len < 1)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] script out_len is %zu.", __FUNCTION__, __LINE__, output->len);
+ return -1;
+ }
+ }
+ else if (num > 2)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] the script return too many values, the num of value is %d, %s.", __FUNCTION__, __LINE__, num, lua_tostring(L, 0-num));
+ return -1;
+ }
+
+ size_t lua_ret_type = lua_type(L, -1);
+ elua_type actual_ret_type;
+
+ switch (lua_ret_type)
+ {
+ case LUA_TNIL:
+ actual_ret_type = NIL;
+ break;
+ case LUA_TSTRING:
+ if (output->type == STRING && output->string != NULL)
+ {
+ memcpy(output->string, lua_tostring(L, -1), output->len);
+ }
+ actual_ret_type = STRING;
+ break;
+ case LUA_TBOOLEAN:
+ output->true_or_false = lua_toboolean(L, -1);
+ output->len = sizeof(int);
+ actual_ret_type = BOOLEAN;
+ break;
+ case LUA_TNUMBER:
+ output->integer = lua_tointeger(L, -1);
+ output->len = sizeof(lua_Integer);
+ actual_ret_type = INTEGER;
+ break;
+ default:
+ snprintf(errmsg, 1023, "[%s:%d] the out_type of return value is invalid.", __FUNCTION__, __LINE__);
+ output->len = 0;
+ return -1;
+ }
+
+ if (actual_ret_type != output->type)
+ {
+ snprintf(errmsg, 1023, "[%s:%d] expect out_type is %d, actual out_type is:%zu.", __FUNCTION__, __LINE__, output->type, lua_ret_type);
+ output->type = actual_ret_type;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int elua_execute_script(struct elua_script *escript, const char *input, size_t input_len, void *userdata, struct elua_context *ctx, struct elua_data *output)
+{
+ if (escript == NULL)
+ {
+ return -1;
+ }
+
+ lua_State *L = (lua_State *)escript->vm;
+ if (L == NULL)
+ {
+ return -1;
+ }
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+
+ if (input == NULL || input_len == 0)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] input or input_len is invaild.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ size_t timeout_ms = escript->timeout_ms;
+ elua_info->userdata = userdata;
+ if (ctx != NULL)
+ {
+ elua_set_context(L, elua_info->elua_name, ctx->context_id, ctx->context_name);
+ }
+
+ elua_set_script_timeout(L, timeout_ms);
+
+ jmp_buf *elua_exception;
+
+ elua_info = (elua_private_info_t *)lua_getexdata(L);
+ elua_exception = elua_info->elua_exception;
+
+ elua_set_data(L, elua_info->elua_name, input, input_len);
+
+ if (setjmp(*elua_exception) == 0)
+ {
+ if (elua_info->time_limit > 0)
+ {
+ elua_info->time_now = mstime();
+ }
+ lua_settop(L, 0);
+ int ret = elua_call_script(L, escript->script_id, elua_info->errmsg);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ ret = elua_vm_return_value(L, output, elua_info->errmsg);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ else
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] exec script failed.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+const char *elua_get_last_error_string(struct elua_vm *vm)
+{
+ lua_State *L = (lua_State *)vm;
+ if (L == NULL)
+ {
+ return "The vm is invalid.";
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+
+ return (const char *)elua_info->errmsg;
+}
+
+int elua_remove_function(struct elua_vm *vm, const char *elua_function)
+{
+ lua_State *L = (lua_State *)vm;
+ if (L == NULL)
+ {
+ return -1;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (elua_function == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ lua_pushnil(L);
+ lua_setglobal(L, elua_function);
+ lua_settop(L, 0);
+
+ return 0;
+}
+
+int elua_cbinding_get_input_params_num(struct elua_vm *vm)
+{
+ lua_State *L = (lua_State *)vm;
+ if (L == NULL)
+ {
+ return -1;
+ }
+ return lua_gettop(L);
+}
+
+int elua_cbinding_get_input_param(struct elua_vm *vm, int param_index, struct elua_data *param)
+{
+ lua_State *L = (lua_State *)vm;
+ if (L == NULL)
+ {
+ return -1;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (param_index < 1 || param == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ int num = lua_gettop(L);
+ if (param_index > num)
+ {
+ return 0;
+ }
+
+ int type = lua_type(L, param_index);
+ switch (type)
+ {
+ case LUA_TBOOLEAN:
+ param->type = BOOLEAN;
+ param->true_or_false = lua_toboolean(L, param_index);
+ param->len = sizeof(int);
+ break;
+ case LUA_TNUMBER:
+ param->type = INTEGER;
+ param->integer = lua_tonumber(L, param_index);
+ param->len = sizeof(lua_Integer);
+ break;
+ case LUA_TSTRING:
+ param->type = STRING;
+ param->string = (char *)lua_tostring(L, param_index);
+ param->len = strlen(param->string);
+ break;
+ default:
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] the out_type of param value is invalid.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ return 1;
+}
+
+struct elua_table
+{
+ int index;
+ lua_State *el;
+ bool is_table_value;
+};
+
+struct elua_table *elua_create_table(struct elua_vm *vm)
+{
+ struct lua_State *L = (struct lua_State *)vm;
+ if (L == NULL)
+ {
+ return NULL;
+ }
+
+ struct elua_table *etab = (struct elua_table *)malloc(sizeof(struct elua_table));
+ lua_newtable(L);
+ etab->index = lua_gettop(L);
+ etab->is_table_value = false;
+ etab->el = L;
+
+ return etab;
+}
+
+//int elua_table_add_element(struct elua_table *table, struct elua_data *key, struct elua_data *value)
+int elua_add_table(struct elua_table *table, struct elua_data *key, struct elua_data *value)
+{
+ if (table == NULL)
+ {
+ return -2;
+ }
+
+ lua_State *L = table->el;
+ if (L == NULL)
+ {
+ return -1;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(table->el);
+ if(key->type != STRING && key->type != INTEGER)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] the type of key is invalid.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ int top = lua_gettop(L);
+ if (key->type == STRING)
+ {
+ lua_pushlstring(L, key->string, key->len);
+ }
+ else
+ {
+ lua_pushinteger(L, key->integer);
+ }
+
+ switch (value->type)
+ {
+ case NIL:
+ lua_pushnil(L);
+ break;
+ case STRING:
+ lua_pushlstring(L, value->string, value->len);
+ break;
+ case INTEGER:
+ lua_pushinteger(L, value->integer);
+ break;
+ case BOOLEAN:
+ lua_pushboolean(L, value->true_or_false);
+ break;
+ case TABLE:
+ lua_pushvalue(L, value->table->index);
+ default:
+ lua_settop(L, top);
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] the type of value is not invalid.", __FUNCTION__, __LINE__);
+ return -1;
+ break;
+ }
+
+ lua_rawset(L, table->index);
+ return 0;
+}
+
+//int elua_table_update_element(struct elua_table *table, struct elua_data *key, struct elua_data *value)
+int elua_update_table(struct elua_table *table, struct elua_data *key, struct elua_data *value)
+{
+ return elua_add_table(table, key, value);
+}
+
+//int elua_table_delet_element(struct elua_table *table, struct elua_data *key, struct elua_data *value)
+int elua_delete_table(struct elua_table *table, struct elua_data *key)
+{
+ struct elua_data value;
+ value.type = NIL;
+ return elua_add_table(table, key, &value);
+}
+
+//struct elua_data *elua_table_search_element(struct elua_table *table, struct elua_data *key)
+int elua_search_table(struct elua_table *table, struct elua_data *key, struct elua_data *value)
+{
+ if (table == NULL)
+ {
+ return -1;
+ }
+
+ lua_State *L = table->el;
+ if (L == NULL)
+ {
+ return -1;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(table->el);
+ if(key->type != STRING && key->type != INTEGER)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] the type of key is invalid.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ if (key->type == STRING)
+ {
+ lua_pushlstring(L, key->string, key->len);
+ }
+ else
+ {
+ lua_pushinteger(L, key->integer);
+ }
+
+ lua_rawget(L, table->index);
+ int type = lua_type(L, -1);
+ switch(type)
+ {
+ case LUA_TBOOLEAN:
+ value->type = BOOLEAN;
+ value->true_or_false = lua_toboolean(L, -1);
+ break;
+ case LUA_TNIL:
+ value->type = NIL;
+ break;
+ case LUA_TSTRING:
+ value->type = STRING;
+ value->string = (char *)lua_tostring(L, -1);
+ break;
+ case LUA_TNUMBER:
+ value->type = INTEGER;
+ value->integer = lua_tointeger(L, -1);
+ break;
+ case LUA_TTABLE:
+ value->type = TABLE;
+ //TODO 需要提供table 遍历函数
+ break;
+ }
+
+ return 0;
+}
+
+void elua_destroy_table(struct elua_table *table)
+{
+ if (table == NULL)
+ {
+ return;
+ }
+
+ lua_State *L = table->el;
+ if (L == NULL)
+ {
+ return;
+ }
+
+ lua_remove(L, table->index);
+ free(table);
+ return;
+}
+
+int elua_cbinding_set_output_params(struct elua_vm *vm, struct elua_data *params, int params_num)
+{
+ lua_State *L = (lua_State *)vm;
+ if (L == NULL)
+ {
+ return -1;
+ }
+
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if(params == NULL || params_num <= 0)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameters error.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ int top = lua_gettop(L);
+ if (top != 0)
+ {
+ if (top == elua_info->lua_stack_top)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] You have called this function already.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+ }
+
+ int i;
+ for (i = 0; i < params_num; i++)
+ {
+ switch(params[i].type)
+ {
+ case NIL:
+ lua_pushnil(L);
+ break;
+ case STRING:
+ lua_pushlstring(L, params[i].string, params[i].len);
+ break;
+ case INTEGER:
+ lua_pushinteger(L, params[i].integer);
+ break;
+ case BOOLEAN:
+ lua_pushboolean(L, params[i].true_or_false);
+ break;
+ case TABLE:
+ lua_pushvalue(L, params[i].table->index);
+ break;
+ default:
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] the type of param is invalid.", __FUNCTION__, __LINE__);
+ return i;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int elua_cbinding_return(struct elua_vm *vm, struct elua_data *data)
+{
+ lua_State *L = (lua_State *)vm;
+ elua_private_info_t *elua_info = (elua_private_info_t *)lua_getexdata(L);
+ if (data == NULL)
+ {
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] Parameter error.", __FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ switch(data->type)
+ {
+ case NIL:
+ lua_pushnil(L);
+ break;
+ case STRING:
+ lua_pushlstring(L, data->string, data->len);
+ break;
+ case INTEGER:
+ lua_pushinteger(L, data->integer);
+ break;
+ case BOOLEAN:
+ if (data->true_or_false)
+ {
+ lua_pushnil(L);
+ }
+ else
+ {
+ lua_pushinteger(L, data->true_or_false);
+ }
+ break;
+ default:
+ snprintf(elua_info->errmsg, 1023, "[%s:%d] the out_type of param value is invalid.", __FUNCTION__, __LINE__);
+ return -1;
+ break;
+ }
+
+ return 0;
+}
diff --git a/src/tsg_lua_func.cpp b/src/tsg_lua_func.cpp
deleted file mode 100644
index 2255033..0000000
--- a/src/tsg_lua_func.cpp
+++ /dev/null
@@ -1,1945 +0,0 @@
-/*************************************************************************
- > File Name: tsg_lua_func.c
- > Author: pxz
- > Created Time: Wed 08 Jul 2020 03:45:55 PM CST
- ************************************************************************/
-extern "C"
-{
-#include<stdio.h>
-#include<stdlib.h>
-#include<string.h>
-#include<setjmp.h>
-#include<time.h>
-#include "lualib.h"
-#include "luajit.h"
-#include "lauxlib.h"
-}
-#include"tsg_lua_interface.h"
-
-#ifndef MIN
-#define MIN(a,b) (((a) < (b))?(a):(b))
-#endif
-
-#ifndef TSG_MAX_LUA_ID
-#define TSG_MAX_LUA_ID 256
-#endif
-
-#define MAX_BEGIN_CODE_SIZE 23
-#define MAX_END_CODE_SIZE 22
-
-#define TEXT_BEGIN_CODE "return function()"
-#define TEXT_BEGIN_SIZE (sizeof(TEXT_BEGIN_CODE) - 1)
-#define TEXT_INIT_CODE "\nlocal newglobaltable = {}\nsetmetatable(newglobaltable, {__index = _G})\nsetfenv(1, newglobaltable)"
-#define TEXT_INIT_SIZE (sizeof(TEXT_INIT_CODE) - 1)
-#define TEXT_END_CODE "\nend"
-#define TEXT_END_SIZE (sizeof(TEXT_END_CODE) - 1)
-
-/* bytecode for luajit 2.0 */
-#define LJ20_BYTECODE_END_STRIPPED \
- "\x14\x03\x00\x01\x00\x01\x00\x03" \
- "\x31\x00\x00\x00\x30\x00\x00\x80\x48\x00\x02\x00" \
- "\x00\x00"
-#define LJ20_BYTECODE_END_SIZE (sizeof(LJ20_BYTECODE_END_STRIPPED) - 1)
-
-/* bytecode for luajit 2.1 */
-#define LJ21_BYTECODE_END_STRIPPED \
- "\x14\x03\x00\x01\x00\x01\x00\x03" \
- "\x33\x00\x00\x00\x32\x00\x00\x80\x4c\x00\x02\x00" \
- "\x00\x00"
-
-#define LJ21_BYTECODE_END_SIZE (sizeof(LJ21_BYTECODE_END_STRIPPED) - 1)
-
-/* bytecode for both */
-#define LJ_BYTECODE_LEN_STRIPPED 22
-#define LJ_HEADERSIZE 5
-#define LJ_BCDUMP_F_BE 0x01
-#define LJ_BCDUMP_F_STRIP 0x02
-#define LJ21_BCDUMP_VERSION 2
-#define LJ20_BCDUMP_VERSION 1
-#define LJ_SIGNATURE "\x1b\x4c\x4a"
-
-#define EXEC_ERROR_INFO_NUM ((int)(sizeof(exec_error) / sizeof(exec_error_massage_t)))
-#define SYNTAX_ERROR_INFO_NUM ((int)(sizeof(syntax_error) / sizeof(char *)))
-
-
-typedef struct{
- const char *err_info1;
- const char *err_info2;
-}exec_error_massage_t;
-
-enum{
- TSG_LUA_READER_BUFFSIZE = 4096
-};
-
-typedef enum{
- TSG_LUA_TEXT_FILE,
- TSG_LUA_BC_LUA,
- TSG_LUA_BC_LJ
-}tsg_lua_clfactory_file_type_t;
-
-typedef struct{
- const char *s;
- tsg_lua_clfactory_file_type_t file_type;
- int sent_begin;
- int sent_end;
- int size;
-
- size_t begin_code_len;
- size_t end_code_len;
- size_t rest_len;
- const char *begin_code_ptr;
- const char *end_code_ptr;
-}tsg_lua_clfactory_buffer_t;
-
-typedef struct{
- FILE *f;
- tsg_lua_clfactory_file_type_t file_type;
- int extraline;
- int sent_begin;
- int sent_end;
-
- size_t begin_code_len;
- size_t end_code_len;
- size_t rest_len;
- union{
- const char *ptr;
- char str[MAX_BEGIN_CODE_SIZE];
- }begin_code;
- const char *end_code_ptr;
-
- char buff[TSG_LUA_READER_BUFFSIZE];
-}tsg_lua_clfactory_file_t;
-
-struct lua_private_info_t
-{
- jmp_buf *lua_exception;
- char lua_name[1024];
- void *userdata;
- int errcode;
- int tsg_lua_mode;
-#define TSG_LUA_JIT_ON 0
-#define TSG_LUA_JIT_OFF 1
- long time_now;
- long time_limit;
- bool is_expired; //not return error from C, when the script was ran in C and time out,
- // keep this status and not return error until the script run in LUA
-};
-
-//static jmp_buf lua_exception[TSG_MAX_LUA_ID];
-
-static const char *syntax_error[] =
-{
- "'end' expected", /* ERR_SCRIPT_END_EXPECTED */
- "'then' expected", /* ERR_SCRIPT_THEN_EXPECTED */
- "'do' expected", /* ERR_SCRIPT_DO_EXPECTED */
- "'<eof>' expected", /* ERR_SCRIPT_EOF_EXPECTED */
- "'=' or 'in' expected", /* ERR_SCRIPT_EQUAL_IN_EXPECTED */
- "unexpected symbol", /* ERR_SCRIPT_UNEXPECTED_SYMBOL */
- "'<name>' expected", /* ERR_SCRIPT_NAME_EXPECT */
- "')' expected", /* ERR_SCRIPT_RIGHT_CURVES_BRACKET */
- "'}' expected", /* ERR_SCRIPT_RIGHT_CURLY_BRACKET */
-};
-
-static exec_error_massage_t exec_error[] =
-{
- {"bad argument", "(string expected, got nil)"}, /* ERR_SCRIPT_STRING_EXPECTED_BUT_NIL */
- {"bad argument", "(string expected, got boolean)"}, /* ERR_SCRIPT_STRING_EXPECTED_BUT_BOOL */
- {"bad argument", "(string expected, got table)"}, /* ERR_SCRIPT_STRING_EXPECTED_BUT_TABLE */
- {"attempt to call global", "(a nil value)"}, /* ERR_SCRIPT_CALL_GLOBAL_BUT_NIL */
-};
-
-static long mstime()
-{
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- return now.tv_sec * 1000 + now.tv_nsec/1000000;
-}
-
-static void debuginfo(const char *info, const char *file, size_t line)
-{
-#ifdef TSG_LUA_DEBUG
- printf("error: [%s:%zu]%s\n", file, line, info);
-#else
- (void)info;
- (void)file;
- (void)line;
-#endif
- return ;
-}
-
-static long tsg_lua_clfactory_file_size(FILE *f)
-{
- long cur_pos, len;
- cur_pos = ftell(f);
- if (cur_pos == -1)
- {
- return -1;
- }
-
- if (fseek(f, 0, SEEK_END) != 0)
- {
- return -1;
- }
-
- len = ftell(f);
- if (len == -1)
- {
- return -1;
- }
-
- if (fseek(f, cur_pos, SEEK_SET) != 0)
- {
- return -1;
- }
-
- return len;
-}
-
-static void tsg_lua_clfactory_file_text_prepare(tsg_lua_clfactory_file_t *lf)
-{
- lf->begin_code.ptr = TEXT_BEGIN_CODE;
- lf->begin_code_len = TEXT_BEGIN_SIZE;
- lf->end_code_ptr = TEXT_END_CODE;
- lf->end_code_len = TEXT_END_SIZE;
-}
-
-static int tsg_lua_clfactory_bytecode_buffer_prepare(tsg_lua_clfactory_buffer_t *ls)
-{
- int little_endian, version, stripped;
-
- if (ls == NULL)
- return -1;
-
- if (ls->file_type == TSG_LUA_BC_LJ)
- {
- /* get bytecode header */
- if (ls->size <= LJ_HEADERSIZE)
- {
- debuginfo("script is bad", __FILE__, __LINE__);
- return ERR_SCRIPT_IS_BAD;
- }
-
- ls->size--;
- /* get bytecode version */
- version = (int)(ls->s[3]);
-
- /* compare bytecode header */
- if (strncmp(ls->s, LJ_SIGNATURE, sizeof(LJ_SIGNATURE) - 1))
- {
- debuginfo("bad byte-code header", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_BAD_HEADER;
- }
-
- /* little endian or big little endian */
- little_endian = !((ls->s[4]) & LJ_BCDUMP_F_BE);
- if (little_endian == 0)
- {
- debuginfo("not support byte-code coding by big-endian", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_NOT_SUPPORT_BIG_ENDIAN;
- }
-
- /* stripped or debug */
- stripped = (ls->s[4]) & LJ_BCDUMP_F_STRIP;
- if (!stripped)
- {
- debuginfo("not support byte-code include debug-info", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_NOT_SUPPORT_DEBUG;
- }
-
- ls->end_code_len = LJ_BYTECODE_LEN_STRIPPED;
- if (version == LJ21_BCDUMP_VERSION)
- {
- ls->end_code_ptr = LJ21_BYTECODE_END_STRIPPED;
- }
-#if 0
- else if (version == LJ20_BCDUMP_VERSION)
- {
- ls->end_code_ptr = LJ20_BYTECODE_END_STRIPPED;
- }
-#endif
- else
- {
- debuginfo("bytecode format version unsupported", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_VERSION_UNSUPPORTED;
- }
- }
- return 0;
-}
-
-static int tsg_lua_clfactory_bytecode_file_prepare(tsg_lua_clfactory_file_t *lf)
-{
- *lf->begin_code.str = LUA_SIGNATURE[0];
- if (lf->file_type == TSG_LUA_BC_LJ)
- {
- /* get bytecode header */
- size_t size = fread(lf->begin_code.str + 1, 1, LJ_HEADERSIZE - 1, lf->f);
- if (size != LJ_HEADERSIZE - 1)
- {
- debuginfo("can not read header", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_NO_HEADER;
- }
-
- /* get bytecode version */
- int version = *(lf->begin_code.str + 3);
-
- /* compare bytecode header */
- if (strncmp(lf->begin_code.str, LJ_SIGNATURE, sizeof(LJ_SIGNATURE) - 1))
- {
- debuginfo("bad byte-code header", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_BAD_HEADER;
- }
-
- lf->begin_code_len = LJ_HEADERSIZE;
-
- /* little endian or big little endian */
- int little_endian = !((*(lf->begin_code.str + 4)) & LJ_BCDUMP_F_BE);
- if (little_endian == 0)
- {
- debuginfo("not support byte-code coding by big-endian", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_NOT_SUPPORT_BIG_ENDIAN;
- }
-
- /* stripped or debug */
- int stripped = (*(lf->begin_code.str + 4)) & LJ_BCDUMP_F_STRIP;
- if (!stripped)
- {
- debuginfo("not support byte-code include debug-info", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_NOT_SUPPORT_DEBUG;
- }
-
- if (version == LJ21_BCDUMP_VERSION)
- {
- lf->end_code_ptr = LJ21_BYTECODE_END_STRIPPED;
- lf->end_code_len = LJ_BYTECODE_LEN_STRIPPED;
- }else if (version == LJ20_BCDUMP_VERSION)
- {
- lf->end_code_ptr = LJ20_BYTECODE_END_STRIPPED;
- lf->end_code_len = LJ_BYTECODE_LEN_STRIPPED;
- }else
- {
- debuginfo("bytecode format version unsupported", __FILE__, __LINE__);
- return ERR_SCRIPT_BYTECODE_VERSION_UNSUPPORTED;
- }
- long fsize = tsg_lua_clfactory_file_size(lf->f);
- if (fsize < 0)
- {
- return ERR_SCRIPT_IS_BAD;
- }
- lf->rest_len = fsize - LJ_HEADERSIZE;
- }
- return 0;
-}
-
-static const char * tsg_lua_gets(lua_State *L, void *ud, size_t *size)
-{
- (void)L;
- tsg_lua_clfactory_buffer_t *ls = (tsg_lua_clfactory_buffer_t *)ud;
- if (ls->file_type == TSG_LUA_TEXT_FILE)
- {
- if (ls->sent_begin == 0)
- {
- ls->sent_begin = 1;
- *size = ls->begin_code_len;
- return ls->begin_code_ptr;
- }
- }
- if (ls->size == 0)
- {
- if (ls->sent_end == 0)
- {
- ls->sent_end = 1;
- *size = ls->end_code_len;
- return ls->end_code_ptr;
- }
- return NULL;
- }
-
- if (ls->file_type == TSG_LUA_BC_LJ)
- {
-#if 0
- lf->rest_len -= ls->size;
- if (lf->rest_len == 0)
- {
- if (--ls->size == 0 && lf->sent_end == 0)
- {
- lf->sent_end = 1;
- *size = lf->end_code_len;
-
- return lf->end_code_ptr;
- }
- }
-#endif
- }
-
- *size = ls->size;
- ls->size = 0;
-
- return ls->s;
-}
-
-static const char * tsg_lua_getf(lua_State *L, void *ud, size_t *size)
-{
- (void)L;
- tsg_lua_clfactory_file_t *lf = (tsg_lua_clfactory_file_t *)ud;
- if (lf->extraline == 1)
- {
- lf->extraline = 0;
- *size = 1;
- return "\n";
- }
-
- if (lf->sent_begin == 0)
- {
- lf->sent_begin = 1;
- *size = lf->begin_code_len;
- if (lf->file_type == TSG_LUA_TEXT_FILE)
- {
- return lf->begin_code.ptr;
- }else
- {
- return lf->begin_code.str;
- }
- }
- size_t num = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
- if (num == 0)
- {
- if (lf->sent_end == 0)
- {
- lf->sent_end = 1;
- *size = lf->end_code_len;
- return lf->end_code_ptr;
- }
- return NULL;
- }
-
- if (lf->file_type == TSG_LUA_BC_LJ)
- {
- lf->rest_len -= num;
- if (lf->rest_len == 0)
- {
- if (--num == 0 && lf->sent_end == 0)
- {
- lf->sent_end = 1;
- *size = lf->end_code_len;
-
- return lf->end_code_ptr;
- }
- }
- }
- *size = num;
- return lf->buff;
-}
-
-static int c_lua_atpanic(lua_State *L)
-{
- char *s = NULL;
- char err[255];
- size_t len = 0;
- jmp_buf *lua_exception;
- struct lua_private_info_t *lua_info = NULL;
-
- lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- lua_exception = lua_info->lua_exception;
- if (lua_type(L, -1) == LUA_TSTRING)
- {
- s = (char *)lua_tolstring(L, -1, &len);
- }
-
- if (s == NULL)
- {
- s = (char *)"unknow reason";
- len = strlen(s);
- }
- sprintf(err, "lua atpanic:lua VM creashed, reason:%*s\n", (int)len, s);
- debuginfo(err, __FILE__, __LINE__);
- longjmp(*lua_exception, 1);
-}
-
-int tsg_lua_memmem(lua_State *L)
-{
- const char *src;
- const char *dest;
- size_t src_len, dest_len;
- const char *ret;
- int start, end;
- int parameter_num = lua_gettop(L);
- if (parameter_num != 4)
- {
- return 0;
- }
-
- src = lua_tostring(L, -4);
- src_len = lua_tointeger(L, -3);
- dest = lua_tostring(L, -2);
- dest_len = lua_tointeger(L, -1);
-
- if (!src || !dest || !src_len || !dest_len)
- {
- return 0;
- }
-
- ret = (const char *)memmem(src, src_len, dest, dest_len);
- if (ret == NULL)
- {
- return 0;
- }
- start = ret - src;
- end = start + dest_len;
- lua_pushinteger(L, start);
- lua_pushinteger(L, end);
-
- return 2;
-}
-
-tsg_lua_handle tsg_lua_vm_create_with_name(const char *name)
-{
- if (name == NULL)
- {
- name = "TSG";
- }
- lua_State *L;
- jmp_buf *lua_exception = (jmp_buf *)malloc(sizeof(jmp_buf));
- if (lua_exception == NULL)
- {
- return NULL;
- }
-
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)calloc(1, sizeof(struct lua_private_info_t));
- if (lua_info == NULL)
- {
- free(lua_exception);
- return NULL;
- }
-
- L = luaL_newstate();
- if (L == NULL)
- {
- free(lua_exception);
- free(lua_info);
- return NULL;
- }
- lua_info->lua_exception = lua_exception;
- int len = strlen(name);
- memcpy(lua_info->lua_name, name, MIN(1023, len));
- lua_info->lua_name[len] = '\0';
- lua_info->userdata = NULL;
- lua_info->errcode = 0;
- lua_setexdata(L, lua_info);
- lua_atpanic(L, c_lua_atpanic);
- luaL_openlibs(L);
- lua_newtable(L);
- lua_pushcfunction(L, tsg_lua_memmem);
- lua_setfield(L, -2, "memmem");
- lua_setglobal(L, name);
-#if 1
- char code[1024];
- memset(code, 0, 1024);
- snprintf(code, 1023, "local ffi = require(\"ffi\")\n"\
- "ffi.cdef[[char *memmem(const char *haystack, size_t haystacklen, const char *needle, size_t needlelen);]]\n"\
- "%s.ffi = ffi\n"\
- "%s.C = ffi.C", name, name);
- if (luaL_dostring(L, code))
- {
- const char *err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- free(lua_exception);
- free(lua_info);
- lua_close(L);
- return NULL;
- }
-#endif
- return L;
-}
-
-tsg_lua_handle tsg_lua_vm_create()
-{
- return tsg_lua_vm_create_with_name((const char *)NULL);
-}
-
-int tsg_lua_exec_file(tsg_lua_handle L, const char *script, const char *in, size_t in_len, char *out, size_t *out_len, size_t *out_type)
-{
- const char *err = NULL;
- int ret = 0;
- int i = 0;
- int sharp = 0;
- tsg_lua_clfactory_file_t lf;
- jmp_buf *lua_exception;
- struct lua_private_info_t *lua_info;
- int return_value = 0;
-
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
- if (script == NULL)
- {
- debuginfo("script is null.", __FILE__, __LINE__);
- return ERR_SCRIPT_ISNULL;
- }
-
- if (in == NULL)
- {
- debuginfo("input is null.", __FILE__, __LINE__);
- return ERR_INPUT_ISNULL;
- }
-
- if (in_len < 1)
- {
- debuginfo("in_len is invailed", __FILE__, __LINE__);
- return ERR_IN_LEN_INVAILD;
- }
-
- if (out_type == NULL || *out_type < STRING || *out_type > BOOLEAN)
- {
- debuginfo("out_type is invailed", __FILE__, __LINE__);
- return ERR_EXPECT_TYPE_IS_NIL;
- }
-
- lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- lua_exception = lua_info->lua_exception;
-
- lf.extraline = 0;
- lf.sent_begin = 0;
- lf.sent_end = 0;
- lf.file_type = TSG_LUA_TEXT_FILE;
-
- lf.f = fopen(script, "r");
- if (lf.f == NULL)
- {
- return ERR_SCRIPT_NOT_EXIT;
- }
- int c = getc(lf.f);
- if (c == '#')
- {
- lf.extraline = 1;
- while ((c = getc(lf.f)) != EOF && c != '\n')
- {
- /* skip first line */
- }
- if (c == '\n')
- {
- c = getc(lf.f);
- }
- sharp = 1;
- }
-
- if (c == LUA_SIGNATURE[0])
- {
- lf.f = freopen(script, "rb", lf.f);
- if (lf.f == NULL)
- {
- return ERR_SCRIPT_NOT_EXIT;
- }
-
- lf.file_type = TSG_LUA_BC_LJ;
- if (sharp)
- {
- /*
- * Loading bytecode with an extra header is disabled for security
- * reasons. This may circumvent the usual check for bytecode vs.
- * Lua code by looking at the first char. Since this is a potential
- * security violation no attempt is made to echo the chunkname either.
- */
- fclose(lf.f);
- return ERR_SCRIPT_IS_BAD;
- }
-
- while((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0])
- {
- /* skip eventual "#! ..." */
- }
- int status = tsg_lua_clfactory_bytecode_file_prepare(&lf);
- if(status != 0)
- {
- fclose(lf.f);
- return status;
- }
- lf.extraline = 0;
- }else
- {
- tsg_lua_clfactory_file_text_prepare(&lf);
- ungetc(c, lf.f);
- }
- lua_settop(L, 0);
- ret = lua_load(L, tsg_lua_getf, &lf, script);
- fclose(lf.f);
- if (ret != 0)
- {
- if (ret == LUA_ERRMEM)
- {
- return ERR_MEM_NOT_ENOUGH;
- }
- else if (lua_isstring(L, -1))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
- else
- {
- return ERR_UNKNOWN;
- }
- }
- /* set new globaltable */
- lua_createtable(L, 0, 1);
- lua_pushvalue(L, -1);
- lua_pushvalue(L, LUA_GLOBALSINDEX);
- lua_setfield(L, -2, "__index");
- lua_setmetatable(L, -2);
- lua_setfenv(L, -2);
-
- if (lua_pcall(L, 0, LUA_MULTRET, 0))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
-
- /* input data waiting to be handled */
- lua_getglobal(L, lua_info->lua_name);
- lua_pushlstring(L, in, in_len);
- lua_setfield(L, -2, "data");
- lua_settop(L, 1);
-
- if (setjmp(*lua_exception) == 0)
- {
- if (lua_info->time_limit > 0)
- {
- lua_info->time_now = mstime();
- }
- if (lua_pcall(L, 0, LUA_MULTRET, 0))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < EXEC_ERROR_INFO_NUM; i++)
- {
- if ((strstr(err, exec_error[i].err_info1)) && (strstr(err, exec_error[i].err_info2)))
- return ERR_SCRIPT_EXEC_ERROR - (i + 1);
- }
- if (strcmp(err, "Lua script killed by time out.") == 0)
- {
- return ERR_SCRIPT_TIMEOUT;
- }
- return ERR_SCRIPT_EXEC_ERROR;
- }
- int num = lua_gettop(L);
- if (num == 0)
- {
- //return nothing
- debuginfo("script return nothing", __FILE__, __LINE__);
- return ERR_RETURN_TYPE_NOT_MATCH_EXPECT;
- }
- else if (num == 2)
- {
- *out_len = lua_tonumber(L, -2);
- if (*out_len < 1)
- {
- debuginfo("script out_len is 0", __FILE__, __LINE__);
- return ERR_SCRIPT_RETURN_LEN_INVAILD;
- }
- }
- else if (num > 2)
- {
- char err_buf[255];
- sprintf((char *)err_buf,"num:%d", num);
- debuginfo(err_buf, __FILE__, __LINE__);
- return ERR_SCRIPT_RETURN_TOO_MUCH;
- }
-
- size_t lua_ret_type = lua_type(L, -1);
- size_t actual_out_type = NIL;
-
- switch(lua_ret_type)
- {
- case LUA_TNIL:
- debuginfo("script return nil", __FILE__, __LINE__);
- actual_out_type = NIL;
- *out_type = NIL;
- *out_len = 0;
- return_value = ERR_RETUNR_NIL;
- break;
- case LUA_TSTRING:
- memcpy(out, lua_tostring(L, -1), *out_len);
- actual_out_type = STRING;
- break;
- case LUA_TBOOLEAN:
- out[0] = lua_toboolean(L, -1);
- *out_len = 1;
- actual_out_type = BOOLEAN;
- break;
- case LUA_TNUMBER:
- *(long *)out = lua_tointeger(L, -1);
- *out_len = 8;
- actual_out_type = INTEGER;
- break;
- default:
- char err_buf[255];
- sprintf((char *)err_buf, "out_type:%d", (lua_type(L, -1)));
- debuginfo(err_buf, __FILE__, __LINE__);
- *out_len = 0;
- return ERR_SCRIPT_RETURN_TYPE_INVAILD;
- }
- if (actual_out_type != *out_type && actual_out_type != NIL)
- {
- char err_buf[255];
- sprintf((char *)err_buf, "expect out_type is:%zu, actual out_type is:%zu", *out_type, actual_out_type);
- debuginfo(err_buf, __FILE__, __LINE__);
- *out_type = actual_out_type;
- return_value = ERR_RETURN_TYPE_NOT_MATCH_EXPECT;
- }
- }else
- {
- return ERR_SCRIPT_EXEC_ERROR;
- }
-
- return return_value;
-}
-
-
-int tsg_lua_exec(tsg_lua_handle L, const char *script, size_t script_len, const char *in, size_t in_len, char *out, size_t *out_len, size_t *out_type)
-{
- const char *err = NULL;
- int ret = 0;
- int i = 0;
- int sharp = 0;
- tsg_lua_clfactory_buffer_t ls;
- struct lua_private_info_t *lua_info = NULL;
- jmp_buf *lua_exception;
- int return_value = 0;
-
- memset(&ls, 0, sizeof(tsg_lua_clfactory_buffer_t));
-
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
- if (script == NULL)
- {
- debuginfo("script is null.", __FILE__, __LINE__);
- return ERR_SCRIPT_ISNULL;
- }
-
- if (in == NULL)
- {
- debuginfo("input is null.", __FILE__, __LINE__);
- return ERR_INPUT_ISNULL;
- }
-
- if (in_len < 1)
- {
- debuginfo("in_len is invailed", __FILE__, __LINE__);
- return ERR_IN_LEN_INVAILD;
- }
-
- if (out_type == NULL || *out_type < STRING || *out_type > BOOLEAN)
- {
- debuginfo("out_type is invailed", __FILE__, __LINE__);
- return ERR_EXPECT_TYPE_IS_NIL;
- }
-
- lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- lua_exception = lua_info->lua_exception;
-
- ls.s = script;
- ls.size = script_len;
- ls.sent_begin = 0;
- ls.sent_end = 0;
-
- if (script[0] == '#')
- {
- for (i = 0; i < ls.size; i++)
- {
- if (script[i] == '\n')
- {
- /* skip extra line */
- ls.s = &script[i];
- ls.size = script_len - i;
- break;
- }
- }
- if (i == ls.size)
- {
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
- sharp = 1;
- }
- if (script[i] == LUA_SIGNATURE[0])
- {
- /* use luajit virtual machine rather then lua virtual machine */
- ls.file_type = TSG_LUA_BC_LJ;
- if (sharp)
- {
- return ERR_SCRIPT_IS_BAD;
- }
- int status = tsg_lua_clfactory_bytecode_buffer_prepare(&ls);
- if (status != 0)
- {
- return status;
- }
-
- }else
- {
- ls.file_type = TSG_LUA_TEXT_FILE;
- ls.begin_code_ptr = TEXT_BEGIN_CODE;
- ls.begin_code_len = TEXT_BEGIN_SIZE;
- ls.end_code_ptr = TEXT_END_CODE;
- ls.end_code_len = TEXT_END_SIZE;
- }
- lua_settop(L, 0);
- ret = lua_load(L, tsg_lua_gets, &ls, "main");
- if (ret != 0)
- {
- if (ret == LUA_ERRMEM)
- {
- return ERR_MEM_NOT_ENOUGH;
- }
- else if (lua_isstring(L, -1))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
- else
- {
- return ERR_UNKNOWN;
- }
- }
- /* set new globaltable */
- lua_createtable(L, 0, 1);
- lua_pushvalue(L, -1);
- lua_pushvalue(L, LUA_GLOBALSINDEX);
- lua_setfield(L, -2, "__index");
- lua_setmetatable(L, -2);
- lua_setfenv(L, -2);
- if (lua_pcall(L, 0, LUA_MULTRET, 0))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
-
- /* input data waiting to be handled */
- lua_getglobal(L, lua_info->lua_name);
- lua_pushlstring(L, in, in_len);
- lua_setfield(L, -2, "data");
- lua_settop(L, 1);
- if (setjmp(*lua_exception) == 0)
- {
- if (lua_info->time_limit > 0)
- {
- lua_info->time_now = mstime();
- }
- if (lua_pcall(L, 0, LUA_MULTRET, 0))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < EXEC_ERROR_INFO_NUM; i++)
- {
- if ((strstr(err, exec_error[i].err_info1)) && (strstr(err, exec_error[i].err_info2)))
- return ERR_SCRIPT_EXEC_ERROR - (i + 1);
- }
- if (strcmp(err, "Lua script killed by time out.") == 0)
- {
- return ERR_SCRIPT_TIMEOUT;
- }
- return ERR_SCRIPT_EXEC_ERROR;
- }
- int num = lua_gettop(L);
- if (num == 0)
- {
- //return nothing
- debuginfo("script return nothing", __FILE__, __LINE__);
- return ERR_RETURN_TYPE_NOT_MATCH_EXPECT;
- }
- else if (num == 2)
- {
- *out_len = lua_tonumber(L, -2);
- if (*out_len < 1)
- {
- debuginfo("script out_len is 0", __FILE__, __LINE__);
- return ERR_SCRIPT_RETURN_LEN_INVAILD;
- }
- }
- else if (num > 2)
- {
- char err_buf[255];
- sprintf((char *)err_buf, "num:%d", num);
- debuginfo(err_buf, __FILE__, __LINE__);
- return ERR_SCRIPT_RETURN_TOO_MUCH;
- }
-
- size_t lua_ret_type = lua_type(L, -1);
- size_t actual_out_type = NIL;
-
- switch(lua_ret_type)
- {
- case LUA_TNIL:
- debuginfo("script return nil", __FILE__, __LINE__);
- *out_type = NIL;
- actual_out_type = NIL;
- return_value = ERR_RETUNR_NIL;
- break;
- case LUA_TSTRING:
- memcpy(out, lua_tostring(L, -1), *out_len);
- actual_out_type = STRING;
- break;
- case LUA_TBOOLEAN:
- out[0] = lua_toboolean(L, -1);
- *out_len = 1;
- actual_out_type = BOOLEAN;
- break;
- case LUA_TNUMBER:
- *(size_t *)out = lua_tointeger(L, -1);
- *out_len = 8;
- actual_out_type = INTEGER;
- break;
- default:
- char err_buf[255];
- sprintf((char *)err_buf, "out_type:%d", (lua_type(L, -1)));
- debuginfo(err_buf, __FILE__, __LINE__);
- *out_len = 0;
- return ERR_SCRIPT_RETURN_TYPE_INVAILD;
- }
-
- if (actual_out_type != *out_type && actual_out_type != NIL)
- {
- char err_buf[255];
- sprintf((char *)err_buf, "expect out_type is:%zu, actual out_type is:%zu ", *out_type, actual_out_type);
- debuginfo(err_buf, __FILE__, __LINE__);
- return_value = ERR_RETURN_TYPE_NOT_MATCH_EXPECT;
- }
- }else
- {
- return ERR_SCRIPT_EXEC_ERROR;
- }
-
- return return_value;
-}
-
-int tsg_lua_cache_script(tsg_lua_handle L, const char *script, size_t script_len)
-{
- size_t script_id = 0;
- const char *err = NULL;
- int ret = 0;
- int i = 0;
- int sharp = 0;
- tsg_lua_clfactory_buffer_t ls;
-
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
- if (script == NULL)
- {
- debuginfo("script is null.", __FILE__, __LINE__);
- return ERR_SCRIPT_ISNULL;
- }
-
- memset(&ls, 0, sizeof(tsg_lua_clfactory_buffer_t));
- ls.s = script;
- ls.size = script_len;
- ls.sent_begin = 0;
- ls.sent_end = 0;
-
- if (script[0] == '#')
- {
- for (i = 0; i < ls.size; i++)
- {
- if (script[i] == '\n')
- {
- /* skip extra line */
- ls.s = &script[i];
- ls.size = script_len - i;
- break;
- }
- }
- if (i == ls.size)
- {
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
- sharp = 1;
- }
- if (script[i] == LUA_SIGNATURE[0])
- {
- /* use luajit virtual machine rather then la virtual machine */
- ls.file_type = TSG_LUA_BC_LJ;
- if (sharp)
- {
- return ERR_SCRIPT_IS_BAD;
- }
-
- int status = tsg_lua_clfactory_bytecode_buffer_prepare(&ls);
- if (status != 0)
- {
- return status;
- }
-
- }else
- {
- ls.file_type = TSG_LUA_TEXT_FILE;
- ls.begin_code_ptr = TEXT_BEGIN_CODE;
- ls.begin_code_len = TEXT_BEGIN_SIZE;
- ls.end_code_ptr = TEXT_END_CODE;
- ls.end_code_len = TEXT_END_SIZE;
- }
-
- lua_settop(L, 0);
- ret = lua_load(L, tsg_lua_gets, &ls, "string");
- if (ret != 0)
- {
- if (ret == LUA_ERRMEM)
- {
- return ERR_MEM_NOT_ENOUGH;
- }
- else if (lua_isstring(L, -1))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
- else
- {
- return ERR_UNKNOWN;
- }
- }
- if (lua_pcall(L, 0, LUA_MULTRET, 0))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
-
- script_id = luaL_ref(L, LUA_REGISTRYINDEX);
- if ((script_id == (size_t)LUA_REFNIL) || (script_id == (size_t)LUA_NOREF))
- {
- debuginfo("lua cache failed.", __FILE__, __LINE__);
- return ERR_LUA_CACHE_FAILED;
- }
-
- return script_id;
-}
-
-int tsg_lua_cache_script_file(tsg_lua_handle L, const char *script)
-{
- size_t script_id;
- const char *err = NULL;
- int ret = 0;
- int sharp = 0;
- tsg_lua_clfactory_file_t lf;
-
-
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
- if (script == NULL)
- {
- debuginfo("script is null.", __FILE__, __LINE__);
- return ERR_SCRIPT_ISNULL;
- }
- lf.extraline = 0;
- lf.sent_begin = 0;
- lf.sent_end = 0;
- lf.file_type = TSG_LUA_TEXT_FILE;
-
- lf.f = fopen(script, "r");
- if (lf.f == NULL)
- {
- return ERR_SCRIPT_NOT_EXIT;
- }
- int c = getc(lf.f);
- if (c == '#')
- {
- lf.extraline = 1;
- while ((c = getc(lf.f)) != EOF && c != '\n')
- {
- /* skip first line */
- }
- if (c == '\n')
- {
- c = getc(lf.f);
- }
- sharp = 1;
- }
-
- if (c == LUA_SIGNATURE[0])
- {
- lf.f = freopen(script, "rb", lf.f);
- if (lf.f == NULL)
- {
- return ERR_SCRIPT_NOT_EXIT;
- }
- lf.file_type = TSG_LUA_BC_LJ;
- if (sharp)
- {
- /*
- * Loading bytecode with an extra header is disabled for security
- * reasons. This may circumvent the usual check for bytecode vs.
- * Lua code by looking at the first char. Since this is a potential
- * security violation no attempt is made to echo the chunkname either.
- */
- fclose(lf.f);
- return ERR_SCRIPT_IS_BAD;
- }
-
- while((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0])
- {
- /* skip eventual "#! ..." */
- }
- int status = tsg_lua_clfactory_bytecode_file_prepare(&lf);
- if(status != 0)
- {
- return status;
- }
- lf.extraline = 0;
- }else
- {
- tsg_lua_clfactory_file_text_prepare(&lf);
- ungetc(c, lf.f);
- }
- lua_settop(L, 0);
- ret = lua_load(L, tsg_lua_getf, &lf, script);
- fclose(lf.f);
- if (ret != 0)
- {
- if (ret == LUA_ERRMEM)
- {
- return ERR_MEM_NOT_ENOUGH;
- }
- else if (lua_isstring(L, -1))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (int i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
- else
- {
- return ERR_UNKNOWN;
- }
- }
- /* set new globaltable */
- lua_createtable(L, 0, 1);
- lua_pushvalue(L, -1);
- lua_pushvalue(L, LUA_GLOBALSINDEX);
- lua_setfield(L, -2, "__index");
- lua_setmetatable(L, -2);
- lua_setfenv(L, -2);
-
- if (lua_pcall(L, 0, LUA_MULTRET, 0))
- {
- err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (int i = 0; i < SYNTAX_ERROR_INFO_NUM; i++)
- {
- if (strstr(err, syntax_error[i]))
- {
- return ERR_SCRIPT_SYNTAX_ERROR - (i + 1);
- }
- }
- return ERR_SCRIPT_SYNTAX_ERROR;
- }
-
- /* cache script */
- script_id = luaL_ref(L, LUA_REGISTRYINDEX);
- if ((script_id == (size_t)LUA_REFNIL) || (script_id == (size_t)LUA_NOREF))
- {
- debuginfo("lua cache failed.", __FILE__, __LINE__);
- return ERR_LUA_CACHE_FAILED;
- }
-
- return script_id;
-}
-
-int tsg_lua_uncache_script(tsg_lua_handle L, size_t script_id)
-{
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
-
- luaL_unref(L, LUA_REGISTRYINDEX, script_id);
-
- return 0;
-}
-
-int tsg_lua_cache_exec(tsg_lua_handle L, size_t script_id, const char *in, size_t in_len, char *out, size_t *out_len, size_t *out_type)
-{
- struct lua_private_info_t *lua_info = NULL;
- jmp_buf *lua_exception;
- int return_value = 0;
-
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
- if (script_id < 1)
- {
- debuginfo("script_id is invaild.", __FILE__, __LINE__);
- return ERR_SCRIPT_ID_INVAILD;
- }
- if (in == NULL)
- {
- debuginfo("input is null.", __FILE__, __LINE__);
- return ERR_INPUT_ISNULL;
- }
- if (in_len < 1)
- {
- debuginfo("in_len is invailed", __FILE__, __LINE__);
- return ERR_IN_LEN_INVAILD;
- }
- if (out_type == NULL || *out_type < STRING || *out_type > BOOLEAN)
- {
- debuginfo("out_type is invailed", __FILE__, __LINE__);
- return ERR_EXPECT_TYPE_IS_NIL;
- }
-
- lua_settop(L, 0);
- lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- lua_exception = lua_info->lua_exception;
-
- lua_rawgeti(L, LUA_REGISTRYINDEX, script_id);
- lua_getglobal(L, lua_info->lua_name);
- lua_pushlstring(L, in, in_len);
- lua_setfield(L, -2, "data");
- lua_settop(L, 1);
-
- if (setjmp(*lua_exception) == 0)
- {
- if (lua_info->time_limit > 0)
- {
- lua_info->time_now = mstime();
- }
- if (lua_pcall(L, 0, LUA_MULTRET, 0))
- {
- const char *err = lua_tostring(L, -1);
- debuginfo(err, __FILE__, __LINE__);
- for (int i = 0; i < EXEC_ERROR_INFO_NUM; i++)
- {
- if ((strstr(err, exec_error[i].err_info1)) && (strstr(err, exec_error[i].err_info2)))
- return ERR_SCRIPT_EXEC_ERROR - (i + 1);
- }
- if (strcmp(err, "Lua script killed by time out.") == 0)
- {
- return ERR_SCRIPT_TIMEOUT;
- }
- return ERR_SCRIPT_EXEC_ERROR;
- }
- int num = lua_gettop(L);
- if (num == 0)
- {
- //return nothing
- debuginfo("script return nothing", __FILE__, __LINE__);
- return ERR_RETURN_TYPE_NOT_MATCH_EXPECT;
- }
- else if (num == 2)
- {
- *out_len = lua_tonumber(L, -2);
- if (*out_len < 1)
- {
- debuginfo("script out_len is 0", __FILE__, __LINE__);
- return ERR_SCRIPT_RETURN_LEN_INVAILD;
- }
- }
- else if (num > 2)
- {
- char err_buf[255];
- sprintf((char *)err_buf,"num:%d", num);
- debuginfo(err_buf, __FILE__, __LINE__);
- return ERR_SCRIPT_RETURN_TOO_MUCH;
- }
-
- size_t lua_ret_type = lua_type(L, -1);
- size_t actual_ret_type = 0;
-
- switch(lua_ret_type)
- {
- case LUA_TNIL:
- debuginfo("script return nil", __FILE__, __LINE__);
- *out_type = NIL;
- actual_ret_type = NIL;
- return_value = ERR_RETUNR_NIL;
- break;
- case LUA_TSTRING:
- memcpy(out, lua_tostring(L, -1), *out_len);
- actual_ret_type = STRING;
- break;
- case LUA_TBOOLEAN:
- out[0] = lua_toboolean(L, -1);
- *out_len = 1;
- actual_ret_type = BOOLEAN;
- break;
- case LUA_TNUMBER:
- *(size_t *)out = lua_tointeger(L, -1);
- *out_len = 8;
- actual_ret_type = INTEGER;
- break;
- default:
- char err_buf[255];
- sprintf((char *)err_buf,"out_type:%d", lua_type(L, -1));
- debuginfo(err_buf, __FILE__, __LINE__);
- *out_len = 0;
- return ERR_SCRIPT_RETURN_TYPE_INVAILD;
- }
-
- if (actual_ret_type != *out_type && actual_ret_type != NIL)
- {
- char err_buf[255];
- sprintf((char *)err_buf, "expect out_type is:%zu, actual out_type is:%zu ", *out_type, actual_ret_type);
- debuginfo(err_buf, __FILE__, __LINE__);
- *out_type = actual_ret_type;
- return_value = ERR_RETURN_TYPE_NOT_MATCH_EXPECT;
- }
-
- }else
- {
- return ERR_SCRIPT_EXEC_ERROR;
- }
-
- return return_value;
-}
-
-int tsg_destory_lua(tsg_lua_handle L)
-{
- struct lua_private_info_t *lua_info = NULL;
-
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
- lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- if (lua_info != NULL)
- {
- if (lua_info->lua_exception != NULL)
- {
- free(lua_info->lua_exception);
- }
- free(lua_info);
- }
-
- lua_close(L);
- return 0;
-}
-
-int c_pull_param_from_lua(tsg_lua_handle L, int *argc, struct lua_arg_t **argv)
-{
- if (L == NULL)
- {
- return ERR_PARAMETER;
- }
-
- *argc = lua_gettop(L);
- if (*argc == 0)
- {
- *argv = NULL;
- return 0;
- }
-
- struct lua_arg_t *value = (struct lua_arg_t *)calloc(*argc, sizeof(struct lua_arg_t));
- // memset(argv, 0, argc * sizeof(struct lua_arg_t));
-
- const char *str = NULL;
- for (int i = 0; i < *argc; i++)
- {
- int type = lua_type(L, i - *argc);
- switch (type)
- {
- case LUA_TBOOLEAN:
- value[i].type = BOOLEAN;
- value[i].flag = lua_toboolean(L, i - *argc);
- break;
- case LUA_TNUMBER:
- value[i].type = INTEGER;
- value[i].num = lua_tonumber(L, i - *argc);
- break;
- case LUA_TSTRING:
- value[i].type = STRING;
- str = lua_tostring(L, i - *argc);
- value[i].len = strlen(str);
- value[i].str = (char *)malloc(value[i].len+1);
- memcpy(value[i].str, str, value[i].len);
- value[i].str[value[i].len] = '\0';
- break;
- default:
- free_param_form_lua(*argc, value);
- *argc = 0;
- *argv = NULL;
- return ERR_LUA_FUNCTION_ARGV;
- }
- }
-
- *argv = value;
-
- return 0;
-}
-
-int free_param_form_lua(int argc, lua_arg_t *argv)
-{
- if (argc == 0 || argv == NULL)
- {
- return 0;
- }
-
- for(int i = 0; i < argc; i++)
- {
- if (argv[i].type == STRING)
- {
- free(argv[i].str);
- argv[i].str = NULL;
- }
- }
-
- free(argv);
- //*argv = NULL;
-
- return 0;
-}
-
-int c_push_string_into_lua(tsg_lua_handle L, const char *str, size_t len)
-{
- if (L == NULL || str == NULL)
- {
- return ERR_PARAMETER;
- }
-
- lua_pushlstring(L, str, len);
- return 0;
-}
-
-int c_push_num_into_lua(tsg_lua_handle L, long num)
-{
- if (L == NULL )
- {
- return ERR_PARAMETER;
- }
-
- lua_pushinteger(L, num);
- return 0;
-}
-
-int c_push_bool_into_lua(tsg_lua_handle L, bool flag)
-{
- if (L == NULL)
- {
- return ERR_PARAMETER;
- }
-
- if (flag == false)
- {
- lua_pushnil(L);
- }
- else
- {
- lua_pushinteger(L, flag);
- }
-
- return 0;
-}
-
-int c_push_nil_into_lua(tsg_lua_handle L)
-{
- if (L == NULL)
- {
- return ERR_PARAMETER;
- }
-
- lua_pushnil(L);
- return 0;
-}
-
-int c_push_table_into_lua(tsg_lua_handle L, const char **key_list, const char **value_list, size_t list_len)
-{
- if (L == NULL || key_list == NULL || value_list == NULL)
- {
- return ERR_PARAMETER;
- }
-
- lua_createtable(L, list_len, 0);
- for (size_t i = 0; i < list_len; i++)
- {
- if (key_list[i] != NULL && value_list[i] != NULL)
- {
- lua_pushlstring(L, key_list[i], strlen(key_list[i]));
- lua_pushlstring(L, value_list[i], strlen(value_list[i]));
- lua_rawset(L, -3);
- }
- }
-
- return 1;
-}
-
-void *lua_get_userdata(tsg_lua_handle L)
-{
- struct lua_private_info_t * lua_info = (struct lua_private_info_t *)lua_getexdata(L);
-
- if (lua_info != NULL)
- {
- return lua_info->userdata;
- }
- else
- {
- return NULL;
- }
-}
-
-int lua_register_function(tsg_lua_handle L, const char *function_set, const char *function_name, lua_function_ptr const function)
-{
- if (L == NULL || function_name == NULL || function == NULL)
- {
- return ERR_PARAMETER;
- }
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- if (lua_info == NULL)
- {
- return ERR_LUA_PRIVATE_INFO_IS_NIL;
- }
-
- lua_getglobal(L, lua_info->lua_name);
- if (function_set != NULL)
- {
- lua_getfield(L, -1, function_set);
- int ret = lua_type(L, -1);
- if (ret != LUA_TTABLE)
- {
- lua_pop(L, 1);
- lua_newtable(L);
- lua_pushcfunction(L, function);
- lua_setfield(L, -2, function_name);
- lua_setfield(L, -2, function_set);
- }
- else
- {
- lua_pushcfunction(L, function);
- lua_setfield(L, -2, function_name);
- }
- }
- else
- {
- lua_pushcfunction(L, function);
- lua_setfield(L, -2, function_name);
- }
- lua_settop(L, 0);
-
- return 0;
-}
-
-struct lua_script_context_t
-{
- int context_id;
-};
-
-struct lua_script_context_t *lua_script_context_malloc(tsg_lua_handle L)
-{
- if (L == NULL)
- {
- return NULL;
- }
-
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- if (lua_info == NULL)
- {
- return NULL;
- }
- lua_newtable(L);
- int context_id = luaL_ref(L, LUA_REGISTRYINDEX);
- if (context_id == LUA_REFNIL || context_id == LUA_NOREF)
- {
- lua_info->errcode = ERR_LUA_CACHE_FAILED;
- return NULL;
- }
-
- lua_settop(L, 0);
-
- struct lua_script_context_t *context = (struct lua_script_context_t *)malloc(sizeof(struct lua_script_context_t));
- context->context_id = context_id;
-
- return context;
-}
-
-int lua_script_context_free(tsg_lua_handle L, struct lua_script_context_t *context)
-{
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
- if (context == NULL)
- {
- return ERR_PARAMETER;
- }
-
- luaL_unref(L, LUA_REGISTRYINDEX, context->context_id);
- free(context);
-
- return 0;
-}
-
-int lua_cache_exec(tsg_lua_handle L, size_t script_id, struct lua_data_t in, void *userdata, lua_script_context context, size_t timeout_ms, struct lua_arg_t *outvalue)
-{
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
-
- if (outvalue == NULL || in.data == NULL || in.len == 0)
- {
- return ERR_PARAMETER;
- }
-
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- if (lua_info == NULL)
- {
- return ERR_LUA_PRIVATE_INFO_IS_NIL;
- }
-
- lua_info->userdata = userdata;
- if (context != NULL && context->context_id != LUA_REFNIL && context->context_id != LUA_NOREF)
- {
- lua_getglobal(L, lua_info->lua_name);
- lua_rawgeti(L, LUA_REGISTRYINDEX, context->context_id);
- lua_setfield(L, -2, "context");
- lua_settop(L, 0);
- }
-
- if (timeout_ms > 0)
- {
- lua_set_script_timeout(L, timeout_ms);
- }
- else
- {
- luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_ON);
- }
-
- return tsg_lua_cache_exec(L, script_id, in.data, in.len, outvalue->str, &outvalue->len, &outvalue->type);
-}
-
-int lua_exec(tsg_lua_handle L, struct lua_data_t script, struct lua_data_t in, void *userdata, lua_script_context context, size_t timeout_ms, struct lua_arg_t *outvalue)
-{
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
-
- if (outvalue == NULL || in.data == NULL || in.len == 0 || script.data == NULL || script.len == 0)
- {
- return ERR_PARAMETER;
- }
-
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- if (lua_info == NULL)
- {
- return ERR_LUA_PRIVATE_INFO_IS_NIL;
- }
-
- lua_info->userdata = userdata;
- if (context != NULL && context->context_id != LUA_REFNIL && context->context_id != LUA_NOREF)
- {
- lua_getglobal(L, lua_info->lua_name);
- lua_rawgeti(L, LUA_REGISTRYINDEX, context->context_id);
- lua_setfield(L, -2, "context");
- lua_settop(L, 0);
- }
-
- if (timeout_ms > 0)
- {
- lua_set_script_timeout(L, timeout_ms);
- }
- else
- {
- luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_ON);
- }
-
- return tsg_lua_exec(L, script.data, script.len, in.data, in.len, outvalue->str, &outvalue->len, &outvalue->type);
-}
-
-int lua_exec_file(tsg_lua_handle L, const char *script, struct lua_data_t in, void *userdata, lua_script_context context, size_t timeout_ms, struct lua_arg_t *outvalue)
-{
- if (L == NULL)
- {
- debuginfo("lua VM is null.", __FILE__, __LINE__);
- return ERR_LUAVM_ISNULL;
- }
-
- if (outvalue == NULL || in.data == NULL || in.len == 0 || script == NULL)
- {
- return ERR_PARAMETER;
- }
-
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- if (lua_info == NULL)
- {
- return ERR_LUA_PRIVATE_INFO_IS_NIL;
- }
-
- lua_info->userdata = userdata;
- if (context != NULL && context->context_id != LUA_REFNIL && context->context_id != LUA_NOREF)
- {
- lua_getglobal(L, lua_info->lua_name);
- lua_rawgeti(L, LUA_REGISTRYINDEX, context->context_id);
- lua_setfield(L, -2, "context");
- lua_settop(L, 0);
- }
-
- if (timeout_ms > 0)
- {
- lua_set_script_timeout(L, timeout_ms);
- }
- else
- {
- luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_ON);
- }
-
- return tsg_lua_exec_file(L, script, in.data, in.len, outvalue->str, &outvalue->len, &outvalue->type);
-}
-
-int lua_get_error_code(tsg_lua_handle L)
-{
- if (L == NULL)
- {
- return ERR_LUAVM_ISNULL;
- }
-
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
-
- return lua_info->errcode;
-}
-
-int lua_remove_cmd(tsg_lua_handle L, const char *cmd)
-{
- if (L == NULL || cmd == NULL)
- {
- return ERR_PARAMETER;
- }
-
- lua_pushnil(L);
- lua_setglobal(L, cmd);
-
- lua_settop(L, 0);
-
- return 0;
-}
-
-static void luaMaskCountHook(tsg_lua_handle L, lua_Debug *ar)
-{
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
-
- if (lua_info->is_expired == true)
- {
- if (ar->what && memcmp(ar->what, "C", 1) == 0)
- {
- return;
- }
- else
- {
- lua_pushstring(L, "Lua script killed by time out.");
- lua_error(L);
- return;
- }
- }
-
- long elapsed = mstime() - lua_info->time_now;
- if ( lua_info->time_limit > 0 && elapsed > lua_info->time_limit)
- {
- //printf("elasped:%ld\n", elapsed);
- if (ar->what && memcmp(ar->what, "C", 1) == 0)
- {
- lua_info->is_expired = true;
- // reset the interval to a shorter time
- int hook_granularity = lua_info->time_limit * 1000000 / 1000; //about time_limt / 1000
- lua_sethook(L, luaMaskCountHook, LUA_MASKCOUNT, hook_granularity);
- }
- else
- {
- lua_pushstring(L, "Lua script killed by time out.");
- lua_error(L);
- }
- }
-}
-
-int lua_set_script_timeout(tsg_lua_handle L, int ms)
-{
- if (L == NULL || ms < 0)
- {
- return ERR_PARAMETER;
- }
-
- struct lua_private_info_t *lua_info = (struct lua_private_info_t *)lua_getexdata(L);
- if (lua_info == NULL)
- {
- return ERR_LUA_PRIVATE_INFO_IS_NIL;
- }
-
- lua_info->time_limit = ms;
- if (ms == 0)
- {
- lua_info->tsg_lua_mode = TSG_LUA_JIT_ON;
- luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_ON);
- }
- else
- {
- lua_info->tsg_lua_mode = TSG_LUA_JIT_OFF;
- luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_OFF);
- }
-
- int hook_granularity = ms * 1000000 / 20; //about ms / 20
- lua_sethook(L, luaMaskCountHook, LUA_MASKCOUNT, hook_granularity);
-
- return 0;
-} \ No newline at end of file