|
@@ -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 */
|
|
|
+}
|