|  | @@ -19,6 +19,10 @@
 | 
	
		
			
				|  |  |  #define _CRT_SEQURE_NO_WARNINGS
 | 
	
		
			
				|  |  |  #include "la_util.h"
 | 
	
		
			
				|  |  |  #include "la_interface.h"
 | 
	
		
			
				|  |  | +#include "lua.h"
 | 
	
		
			
				|  |  | +#include "lauxlib.h"
 | 
	
		
			
				|  |  | +#include "lualib.h"
 | 
	
		
			
				|  |  | +#include "luajit.h"
 | 
	
		
			
				|  |  |  #include <stdio.h>
 | 
	
		
			
				|  |  |  #include <stdlib.h>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -2225,4 +2229,201 @@ void laSpinLock(SYSLOCK* lock) {
 | 
	
		
			
				|  |  |  void laSpinUnlock(SYSLOCK* lock) {
 | 
	
		
			
				|  |  |      pthread_spin_unlock(lock);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//======================================= lua utils
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static const char *progname = LUA_PROGNAME;
 | 
	
		
			
				|  |  | +static int traceback(lua_State *L){
 | 
	
		
			
				|  |  | +  if (!lua_isstring(L, 1)) { /* Non-string error object? Try metamethod. */
 | 
	
		
			
				|  |  | +    if (lua_isnoneornil(L, 1) ||
 | 
	
		
			
				|  |  | +	!luaL_callmeta(L, 1, "__tostring") ||
 | 
	
		
			
				|  |  | +	!lua_isstring(L, -1))
 | 
	
		
			
				|  |  | +      return 1;  /* Return non-string error object. */
 | 
	
		
			
				|  |  | +    lua_remove(L, 1);  /* Replace object by result of __tostring metamethod. */
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  luaL_traceback(L, L, lua_tostring(L, 1), 1);
 | 
	
		
			
				|  |  | +  return 1;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void l_message(const char *msg){
 | 
	
		
			
				|  |  | +  if (progname) { fputs(progname, stderr); fputc(':', stderr); fputc(' ', stderr); }
 | 
	
		
			
				|  |  | +  fputs(msg, stderr); fputc('\n', stderr);
 | 
	
		
			
				|  |  | +  fflush(stderr);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +static int report(lua_State *L, int status){
 | 
	
		
			
				|  |  | +  if (status && !lua_isnil(L, -1)) {
 | 
	
		
			
				|  |  | +    const char *msg = lua_tostring(L, -1);
 | 
	
		
			
				|  |  | +    if (msg == NULL) msg = "(error object is not a string)";
 | 
	
		
			
				|  |  | +    l_message(msg);
 | 
	
		
			
				|  |  | +    lua_pop(L, 1);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return status;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +static int docall(lua_State *L, int narg, int clear){
 | 
	
		
			
				|  |  | +  int status;
 | 
	
		
			
				|  |  | +  int base = lua_gettop(L) - narg;  /* function index */
 | 
	
		
			
				|  |  | +  lua_pushcfunction(L, traceback);  /* push traceback function */
 | 
	
		
			
				|  |  | +  lua_insert(L, base);  /* put it under chunk and args */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  lua_remove(L, base);  /* remove traceback function */
 | 
	
		
			
				|  |  | +  /* force a complete garbage collection in case of errors */
 | 
	
		
			
				|  |  | +  if (status != LUA_OK) lua_gc(L, LUA_GCCOLLECT, 0);
 | 
	
		
			
				|  |  | +  return status;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +static void write_prompt(lua_State *L, int firstline){
 | 
	
		
			
				|  |  | +  const char *p;
 | 
	
		
			
				|  |  | +  lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2");
 | 
	
		
			
				|  |  | +  p = lua_tostring(L, -1);
 | 
	
		
			
				|  |  | +  if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2;
 | 
	
		
			
				|  |  | +  fputs(p, stdout);
 | 
	
		
			
				|  |  | +  fflush(stdout);
 | 
	
		
			
				|  |  | +  lua_pop(L, 1);  /* remove global */
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +static int incomplete(lua_State *L, int status){
 | 
	
		
			
				|  |  | +  if (status == LUA_ERRSYNTAX) {
 | 
	
		
			
				|  |  | +    size_t lmsg;
 | 
	
		
			
				|  |  | +    const char *msg = lua_tolstring(L, -1, &lmsg);
 | 
	
		
			
				|  |  | +    const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1);
 | 
	
		
			
				|  |  | +    if (strstr(msg, LUA_QL("<eof>")) == tp) {
 | 
	
		
			
				|  |  | +      lua_pop(L, 1);
 | 
	
		
			
				|  |  | +      return 1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return 0;  /* else... */
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +static int pushline(lua_State *L, int firstline){
 | 
	
		
			
				|  |  | +  char buf[LUA_MAXINPUT];
 | 
	
		
			
				|  |  | +  write_prompt(L, firstline);
 | 
	
		
			
				|  |  | +  if (fgets(buf, LUA_MAXINPUT, stdin)) {
 | 
	
		
			
				|  |  | +    size_t len = strlen(buf);
 | 
	
		
			
				|  |  | +    if (len > 0 && buf[len-1] == '\n')
 | 
	
		
			
				|  |  | +      buf[len-1] = '\0';
 | 
	
		
			
				|  |  | +    if (firstline && buf[0] == '=')
 | 
	
		
			
				|  |  | +      lua_pushfstring(L, "return %s", buf+1);
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      lua_pushstring(L, buf);
 | 
	
		
			
				|  |  | +    return 1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +static int loadline(lua_State *L){
 | 
	
		
			
				|  |  | +  int status;
 | 
	
		
			
				|  |  | +  lua_settop(L, 0);
 | 
	
		
			
				|  |  | +  if (!pushline(L, 1))
 | 
	
		
			
				|  |  | +    return -1;  /* no input */
 | 
	
		
			
				|  |  | +  for (;;) {  /* repeat until gets a complete line */
 | 
	
		
			
				|  |  | +    status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
 | 
	
		
			
				|  |  | +    if (!incomplete(L, status)) break;  /* cannot try to add lines? */
 | 
	
		
			
				|  |  | +    if (!pushline(L, 0))  /* no more input? */
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    lua_pushliteral(L, "\n");  /* add a new line... */
 | 
	
		
			
				|  |  | +    lua_insert(L, -2);  /* ...between the two lines */
 | 
	
		
			
				|  |  | +    lua_concat(L, 3);  /* join them */
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  lua_remove(L, 1);  /* remove line */
 | 
	
		
			
				|  |  | +  return status;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void dotty(lua_State *L){
 | 
	
		
			
				|  |  | +  int status;
 | 
	
		
			
				|  |  | +  const char *oldprogname = progname;
 | 
	
		
			
				|  |  | +  progname = NULL;
 | 
	
		
			
				|  |  | +  while ((status = loadline(L)) != -1) {
 | 
	
		
			
				|  |  | +    if (status == LUA_OK) status = docall(L, 0, 0);
 | 
	
		
			
				|  |  | +    report(L, status);
 | 
	
		
			
				|  |  | +    if (status == LUA_OK && lua_gettop(L) > 0) {  /* any result to print? */
 | 
	
		
			
				|  |  | +      lua_getglobal(L, "print");
 | 
	
		
			
				|  |  | +      lua_insert(L, 1);
 | 
	
		
			
				|  |  | +      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
 | 
	
		
			
				|  |  | +	l_message(lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
 | 
	
		
			
				|  |  | +				  lua_tostring(L, -1)));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  lua_settop(L, 0);  /* clear stack */
 | 
	
		
			
				|  |  | +  fputs("\n", stdout);
 | 
	
		
			
				|  |  | +  fflush(stdout);
 | 
	
		
			
				|  |  | +  progname = oldprogname;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int lalua_Log(lua_State *L) {
 | 
	
		
			
				|  |  | +  int n = lua_gettop(L); int i;
 | 
	
		
			
				|  |  | +  lua_getglobal(L, "tostring");
 | 
	
		
			
				|  |  | +  for (i=1; i<=n; i++) {
 | 
	
		
			
				|  |  | +    const char *s;
 | 
	
		
			
				|  |  | +    lua_pushvalue(L, -1);  /* tostring function */
 | 
	
		
			
				|  |  | +    lua_pushvalue(L, i);   /* value to print */
 | 
	
		
			
				|  |  | +    lua_call(L, 1, 1);
 | 
	
		
			
				|  |  | +    s = lua_tostring(L, -1);  /* get result */
 | 
	
		
			
				|  |  | +    if (s == NULL) return luaL_error(L, LUA_QL("tostring") " must return a string to "LUA_QL("use `log`"));
 | 
	
		
			
				|  |  | +    if (i>1) logPrint("    ");
 | 
	
		
			
				|  |  | +    logPrint(s); lua_pop(L, 1);  /* pop result */
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  logPrint("\n");
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void la_LuaJITLoadLibs(){
 | 
	
		
			
				|  |  | +    lua_State *L=MAIN.L;
 | 
	
		
			
				|  |  | +    lua_gc(MAIN.L, LUA_GCSTOP, 0);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    luaL_openlibs(MAIN.L);
 | 
	
		
			
				|  |  | +    lua_register(L,"log",lalua_Log);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    lua_gc(MAIN.L, LUA_GCRESTART, -1);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int terLoadLine(char* buf, int firstline){
 | 
	
		
			
				|  |  | +    lua_State *L=MAIN.L;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if(!MAIN.TerminalIncomplete){ lua_settop(L, 0); }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    size_t len = strlen(buf); if(len>=512){ buf[512]=0; }
 | 
	
		
			
				|  |  | +    if(len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
 | 
	
		
			
				|  |  | +    if(firstline && buf[0] == '=') lua_pushfstring(L, "return %s", buf+1);
 | 
	
		
			
				|  |  | +    else lua_pushstring(L, buf);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(MAIN.TerminalIncomplete){
 | 
	
		
			
				|  |  | +        lua_pushliteral(L, "\n"); lua_insert(L, -2); lua_concat(L, 3);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    int status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "terLoadLine");
 | 
	
		
			
				|  |  | +    if(incomplete(L,status)){
 | 
	
		
			
				|  |  | +        MAIN.TerminalIncomplete=1;
 | 
	
		
			
				|  |  | +    }else{
 | 
	
		
			
				|  |  | +        MAIN.TerminalIncomplete=0;
 | 
	
		
			
				|  |  | +        lua_remove(L, 1);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(status==LUA_OK && (!MAIN.TerminalIncomplete)){
 | 
	
		
			
				|  |  | +        status = docall(L, 0, 0);
 | 
	
		
			
				|  |  | +        report(L, status);
 | 
	
		
			
				|  |  | +        if (status == LUA_OK && lua_gettop(L) > 0) {  /* any result to print? */
 | 
	
		
			
				|  |  | +        lua_getglobal(L, "log");
 | 
	
		
			
				|  |  | +        lua_insert(L, 1);
 | 
	
		
			
				|  |  | +        if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
 | 
	
		
			
				|  |  | +        l_message(lua_pushfstring(L, "error calling " LUA_QL("log") " (%s)",
 | 
	
		
			
				|  |  | +                    lua_tostring(L, -1)));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return status;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void la_PrintLuaJITStatus(){
 | 
	
		
			
				|  |  | +    lua_State *L=MAIN.L;
 | 
	
		
			
				|  |  | +    logPrint(LUAJIT_VERSION " -- " LUAJIT_COPYRIGHT ". " LUAJIT_URL "\n");
 | 
	
		
			
				|  |  | +    int n; const char *s;
 | 
	
		
			
				|  |  | +    lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
 | 
	
		
			
				|  |  | +    lua_getfield(L, -1, "jit"); lua_remove(L, -2);  /* Get jit.* module table. */
 | 
	
		
			
				|  |  | +    lua_getfield(L, -1, "status"); lua_remove(L, -2);
 | 
	
		
			
				|  |  | +    n = lua_gettop(L);
 | 
	
		
			
				|  |  | +    lua_call(L, 0, LUA_MULTRET);
 | 
	
		
			
				|  |  | +    logPrint(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF");
 | 
	
		
			
				|  |  | +    for (n++; (s = lua_tostring(L, n)); n++) {
 | 
	
		
			
				|  |  | +        logPrint("%s ",s);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    putc('\n', stdout);
 | 
	
		
			
				|  |  | +    lua_settop(L, 0);  /* clear stack */
 | 
	
		
			
				|  |  | +}
 |