diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | depends/lua/include/luaconf.h | 18 | ||||
| -rw-r--r-- | library/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | library/Core.cpp | 10 | ||||
| -rw-r--r-- | library/LuaTools.cpp | 364 | ||||
| -rw-r--r-- | library/LuaWrapper.cpp | 12 | ||||
| -rw-r--r-- | library/include/Core.h | 1 | ||||
| -rw-r--r-- | library/include/DataDefs.h | 35 | ||||
| -rw-r--r-- | library/include/LuaTools.h | 92 | ||||
| -rw-r--r-- | library/include/LuaWrapper.h | 2 | ||||
| -rw-r--r-- | library/lua/dfhack.lua | 5 | ||||
| -rw-r--r-- | plugins/Dfusion/dfusion.cpp | 104 | ||||
| -rw-r--r-- | plugins/Dfusion/include/lua_Console.h | 2 | ||||
| -rw-r--r-- | plugins/Dfusion/src/lua_Console.cpp | 73 |
14 files changed, 501 insertions, 225 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dde18db..60286c92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,8 @@ SET(DFHACK_DATA_DESTINATION hack) SET(DFHACK_PLUGIN_DESTINATION hack/plugins) # dfhack header files go here: SET(DFHACK_INCLUDES_DESTINATION hack/include) +# dfhack lua files go here: +SET(DFHACK_LUA_DESTINATION hack/lua) # the windows .lib file goes here: SET(DFHACK_DEVLIB_DESTINATION hack) diff --git a/depends/lua/include/luaconf.h b/depends/lua/include/luaconf.h index 7a3a03d3..fca66ce4 100644 --- a/depends/lua/include/luaconf.h +++ b/depends/lua/include/luaconf.h @@ -89,25 +89,21 @@ ** In Windows, any exclamation mark ('!') in the path is replaced by the ** path of the directory of the executable file of the current process. */ -#define LUA_LDIR "!\\lua\\" +#define LUA_LDIR "!\\hack\\lua\\" #define LUA_CDIR "!\\" #define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" ".\\?.lua" #define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" + LUA_CDIR"?.dll;" ".\\?.dll" #else /* }{ */ -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR +#define LUA_LDIR "./hack/lua/" +#define LUA_CDIR "./hack/" #define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" "./?.lua" #define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" + LUA_CDIR"?.so;" "./?.so" #endif /* } */ diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 9de419b9..f8b05a04 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -29,6 +29,7 @@ include/ColorText.h include/DataDefs.h include/DataIdentity.h include/LuaWrapper.h +include/LuaTools.h include/Error.h include/Export.h include/Hooks.h @@ -58,6 +59,7 @@ ColorText.cpp DataDefs.cpp LuaWrapper.cpp LuaTypes.cpp +LuaTools.cpp DataStatics.cpp DataStaticsCtor.cpp DataStaticsFields.cpp @@ -295,6 +297,10 @@ install(TARGETS dfhack-run dfhack-client LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION} RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION}) +install(DIRECTORY lua/ + DESTINATION ${DFHACK_LUA_DESTINATION} + FILES_MATCHING PATTERN "*.lua") + # Unused for so long that it's not even relevant now... if(BUILD_DEVEL) if(WIN32) diff --git a/library/Core.cpp b/library/Core.cpp index 4712be0a..8adbf374 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -757,6 +757,16 @@ std::string Core::getHotkeyCmd( void ) return returner; } +void Core::print(const char *format, ...) +{ + color_ostream_proxy proxy(getInstance().con); + + va_list args; + va_start(args,format); + proxy.vprint(format,args); + va_end(args); +} + void Core::printerr(const char *format, ...) { color_ostream_proxy proxy(getInstance().con); diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp new file mode 100644 index 00000000..b493f761 --- /dev/null +++ b/library/LuaTools.cpp @@ -0,0 +1,364 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "Internal.h" + +#include <string> +#include <vector> +#include <map> + +#include "MemAccess.h" +#include "Core.h" +#include "VersionInfo.h" +#include "tinythread.h" +// must be last due to MS stupidity +#include "DataDefs.h" +#include "DataIdentity.h" + +#include "LuaWrapper.h" +#include "LuaTools.h" + +#include "MiscUtils.h" + +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> + +using namespace DFHack; +using namespace DFHack::LuaWrapper; + +void DFHack::Lua::PushDFObject(lua_State *state, type_identity *type, void *ptr) +{ + push_object_internal(state, type, ptr, false); +} + +void *DFHack::Lua::GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type) +{ + return get_object_internal(state, type, val_index, exact_type, false); +} + +static int DFHACK_OSTREAM_TOKEN = 0; + +color_ostream *DFHack::Lua::GetOutput(lua_State *L) +{ + lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_OSTREAM_TOKEN); + auto rv = (color_ostream*)lua_touserdata(L, -1); + lua_pop(L, 1); + return rv; +} + +static void set_dfhack_output(lua_State *L, color_ostream *p) +{ + lua_pushlightuserdata(L, p); + lua_rawsetp(L, LUA_REGISTRYINDEX, &DFHACK_OSTREAM_TOKEN); +} + +static std::string lua_print_fmt(lua_State *L) +{ + /* Copied from lua source to fully replicate builtin print */ + int n = lua_gettop(L); /* number of arguments */ + lua_getglobal(L, "tostring"); + + std::stringstream ss; + + for (int i=1; i<=n; i++) { + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + const char *s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + luaL_error(L, "tostring must return a string to print"); + if (i>1) + ss << '\t'; + ss << s; + lua_pop(L, 1); /* pop result */ + } + + return ss.str(); +} + +static int lua_dfhack_print(lua_State *S) +{ + std::string str = lua_print_fmt(S); + if (color_ostream *out = Lua::GetOutput(S)) + *out << str; + else + Core::print("%s", str.c_str()); + return 0; +} + +static int lua_dfhack_println(lua_State *S) +{ + std::string str = lua_print_fmt(S); + if (color_ostream *out = Lua::GetOutput(S)) + *out << str << std::endl; + else + Core::print("%s\n", str.c_str()); + return 0; +} + +static int lua_dfhack_printerr(lua_State *S) +{ + std::string str = lua_print_fmt(S); + if (color_ostream *out = Lua::GetOutput(S)) + out->printerr("%s\n", str.c_str()); + else + Core::printerr("%s\n", str.c_str()); + return 0; +} + +static int traceback (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg) + luaL_traceback(L, L, msg, 1); + else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ + if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ + lua_pushliteral(L, "(no error message)"); + } + return 1; +} + +static void report_error(color_ostream &out, lua_State *L) +{ + const char *msg = lua_tostring(L, -1); + if (msg) + out.printerr("%s\n", msg); + else + out.printerr("In Lua::SafeCall: error message is not a string.\n", msg); + lua_pop(L, 1); +} + +bool DFHack::Lua::SafeCall(color_ostream &out, lua_State *L, int nargs, int nres, bool perr) +{ + int base = lua_gettop(L) - nargs; + + color_ostream *cur_out = Lua::GetOutput(L); + set_dfhack_output(L, &out); + + lua_pushcfunction(L, traceback); + lua_insert(L, base); + + bool ok = lua_pcall(L, nargs, nres, base) == LUA_OK; + + lua_remove(L, base); + set_dfhack_output(L, cur_out); + + if (!ok && perr) + report_error(out, L); + + return ok; +} + +bool DFHack::Lua::Require(color_ostream &out, lua_State *state, + const std::string &module, bool setglobal) +{ + lua_getglobal(state, "require"); + lua_pushstring(state, module.c_str()); + + if (!Lua::SafeCall(out, state, 1, 1)) + return false; + + if (setglobal) + lua_setglobal(state, module.c_str()); + else + lua_pop(state, 1); + + return true; +} + +static bool load_with_env(color_ostream &out, lua_State *state, const std::string &code, int eidx) +{ + if (luaL_loadstring(state, code.c_str()) != LUA_OK) + { + report_error(out, state); + return false; + } + + // Replace _ENV + lua_pushvalue(state, eidx); + + if (!lua_setupvalue(state, -2, 1)) + { + out.printerr("No _ENV upvalue.\n"); + return false; + } + + return true; +} + +bool DFHack::Lua::InterpreterLoop(color_ostream &out, lua_State *state, + const char *prompt, int env, const char *hfile) +{ + if (!out.is_console()) + return false; + if (!lua_checkstack(state, 20)) + return false; + + if (!hfile) + hfile = "lua.history"; + if (!prompt) + prompt = "lua"; + + DFHack::CommandHistory hist; + hist.load(hfile); + + out.print("Type quit to exit interactive lua interpreter.\n" + "Shortcuts:\n" + " '= foo' => '_1,_2,... = foo'\n" + " '! foo' => 'print(foo)'\n" + "Both assign the first result to '_'\n"); + + Console &con = static_cast<Console&>(out); + + // Make a proxy global environment. + lua_newtable(state); + lua_newtable(state); + if (env) + lua_pushvalue(state, env); + else + lua_rawgeti(state, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); + lua_setfield(state, -2, "__index"); + lua_setmetatable(state, -2); + + // Main interactive loop + int base = lua_gettop(state); + int vcnt = 1; + string curline; + string prompt_str = "[" + string(prompt) + "]# "; + + for (;;) { + lua_settop(state, base); + + con.lineedit(prompt_str,curline,hist); + + if (curline.empty()) + continue; + if (curline == "quit") + break; + + hist.add(curline); + + char pfix = curline[0]; + + if (pfix == '=' || pfix == '!') + { + curline = "return " + curline.substr(1); + + if (!load_with_env(out, state, curline, base)) + continue; + if (!SafeCall(out, state, 0, LUA_MULTRET)) + continue; + + int numret = lua_gettop(state) - base; + + if (numret >= 1) + { + lua_pushvalue(state, base+1); + lua_setfield(state, base, "_"); + + if (pfix == '!') + { + lua_pushcfunction(state, lua_dfhack_println); + lua_insert(state, base+1); + SafeCall(out, state, numret, 0); + continue; + } + } + + for (int i = 1; i <= numret; i++) + { + std::string name = stl_sprintf("_%d", vcnt++); + lua_pushvalue(state, base + i); + lua_setfield(state, base, name.c_str()); + + out.print("%s = ", name.c_str()); + + lua_pushcfunction(state, lua_dfhack_println); + lua_pushvalue(state, base + i); + SafeCall(out, state, 1, 0); + } + } + else + { + if (!load_with_env(out, state, curline, base)) + continue; + if (!SafeCall(out, state, 0, LUA_MULTRET)) + continue; + } + } + + lua_settop(state, base-1); + + hist.save(hfile); + return true; +} + +static int lua_dfhack_interpreter(lua_State *state) +{ + color_ostream *pstream = Lua::GetOutput(state); + if (!pstream) + luaL_error(state, "Cannot use dfhack.interpreter() without output."); + + int argc = lua_gettop(state); + + const char *prompt = (argc >= 1 ? lua_tostring(state, 1) : NULL); + int env = (argc >= 2 && !lua_isnil(state,2) ? 2 : 0); + const char *hfile = (argc >= 3 ? lua_tostring(state, 3) : NULL); + + lua_pushboolean(state, Lua::InterpreterLoop(*pstream, state, prompt, env, hfile)); + return 1; +} + +static const luaL_Reg dfhack_funcs[] = { + { "print", lua_dfhack_print }, + { "println", lua_dfhack_println }, + { "printerr", lua_dfhack_printerr }, + { "traceback", traceback }, + { "interpreter", lua_dfhack_interpreter }, + { NULL, NULL } +}; + +lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state) +{ + if (!state) + state = luaL_newstate(); + + luaL_openlibs(state); + AttachDFGlobals(state); + + // Replace the print function of the standard library + lua_pushcfunction(state, lua_dfhack_println); + lua_setglobal(state, "print"); + + // Create and initialize the dfhack global + lua_newtable(state); + luaL_setfuncs(state, dfhack_funcs, 0); + lua_setglobal(state, "dfhack"); + + // load dfhack.lua + Require(out, state, "dfhack"); + + return state; +} + diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp index 81712724..b9314f07 100644 --- a/library/LuaWrapper.cpp +++ b/library/LuaWrapper.cpp @@ -59,16 +59,6 @@ void LuaWrapper::field_error(lua_State *state, int index, const char *err, const mode, (cname ? cname : "?"), (fname ? fname : "?"), err); } -void DFHack::PushDFObject(lua_State *state, type_identity *type, void *ptr) -{ - push_object_internal(state, type, ptr, false); -} - -void *DFHack::GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type) -{ - return get_object_internal(state, type, val_index, exact_type, false); -} - /* */ static int change_error(lua_State *state) @@ -1320,7 +1310,7 @@ static int DoAttach(lua_State *state) * Initialize access to DF objects from the interpreter * context, unless it has already been done. */ -void DFHack::AttachDFGlobals(lua_State *state) +void LuaWrapper::AttachDFGlobals(lua_State *state) { if (luaL_newmetatable(state, DFHACK_TYPETABLE_NAME)) { diff --git a/library/include/Core.h b/library/include/Core.h index 10b95a47..f73ab08e 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -135,6 +135,7 @@ namespace DFHack DFHack::VersionInfo * vinfo; DFHack::Windows::df_window * screen_window; + static void print(const char *format, ...); static void printerr(const char *format, ...); private: diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index b2c86ec1..b9b4707d 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -360,23 +360,6 @@ namespace DFHack void InitDataDefGlobals(Core *core); - // LUA wrapper - - /** - * Make DF objects available to the given interpreter. - */ - DFHACK_EXPORT void AttachDFGlobals(lua_State *state); - - /** - * Push the pointer onto the stack as a wrapped DF object of the given type. - */ - DFHACK_EXPORT void PushDFObject(lua_State *state, type_identity *type, void *ptr); - - /** - * Check that the value is a wrapped DF object of the given type, and if so return the pointer. - */ - DFHACK_EXPORT void *GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type = false); - template<class T> T *ifnull(T *a, T *b) { return a ? a : b; } @@ -683,24 +666,6 @@ namespace DFHack { flagarray_to_string<T>(&tmp, val); return join_strings(sep, tmp); } - - // LUA wrapper - - /** - * Push the pointer onto the stack as a wrapped DF object of a specific type. - */ - template<class T> - void PushDFObject(lua_State *state, T *ptr) { - PushDFObject(state, df::identity_traits<T>::get(), ptr); - } - - /** - * Check that the value is a wrapped DF object of the correct type, and if so return the pointer. - */ - template<class T> - T *GetDFObject(lua_State *state, int val_index, bool exact_type = false) { - return (T*)GetDFObject(state, df::identity_traits<T>::get(), val_index, exact_type); - } } #define ENUM_ATTR(enum,attr,val) (df::enum_traits<df::enum>::attrs(val).attr) diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h new file mode 100644 index 00000000..32e35201 --- /dev/null +++ b/library/include/LuaTools.h @@ -0,0 +1,92 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once + +#include <string> +#include <sstream> +#include <vector> +#include <map> + +#include "DataDefs.h" + +#include <lua.h> +#include <lauxlib.h> + +namespace DFHack { namespace Lua { + /** + * Create or initialize a lua interpreter with access to DFHack tools. + */ + DFHACK_EXPORT lua_State *Open(color_ostream &out, lua_State *state = NULL); + + /** + * Load a module using require(). + */ + DFHACK_EXPORT bool Require(color_ostream &out, lua_State *state, + const std::string &module, bool setglobal = false); + + /** + * Push the pointer onto the stack as a wrapped DF object of the given type. + */ + DFHACK_EXPORT void PushDFObject(lua_State *state, type_identity *type, void *ptr); + + /** + * Check that the value is a wrapped DF object of the given type, and if so return the pointer. + */ + DFHACK_EXPORT void *GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type = false); + + /** + * Push the pointer onto the stack as a wrapped DF object of a specific type. + */ + template<class T> + void PushDFObject(lua_State *state, T *ptr) { + PushDFObject(state, df::identity_traits<T>::get(), ptr); + } + + /** + * Check that the value is a wrapped DF object of the correct type, and if so return the pointer. + */ + template<class T> + T *GetDFObject(lua_State *state, int val_index, bool exact_type = false) { + return (T*)GetDFObject(state, df::identity_traits<T>::get(), val_index, exact_type); + } + + /** + * Invoke lua function via pcall. Returns true if success. + * If an error is signalled, and perr is true, it is printed and popped from the stack. + */ + DFHACK_EXPORT bool SafeCall(color_ostream &out, lua_State *state, int nargs, int nres, bool perr = true); + + /** + * Returns the ostream passed to SafeCall. + */ + DFHACK_EXPORT color_ostream *GetOutput(lua_State *state); + + /** + * Run an interactive interpreter loop if possible, or return false. + */ + DFHACK_EXPORT bool InterpreterLoop(color_ostream &out, lua_State *state, + const char *prompt = NULL, int env = 0, const char *hfile = NULL); +}} + diff --git a/library/include/LuaWrapper.h b/library/include/LuaWrapper.h index d3f1337e..aa6e511b 100644 --- a/library/include/LuaWrapper.h +++ b/library/include/LuaWrapper.h @@ -214,5 +214,7 @@ namespace DFHack { namespace LuaWrapper { void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum); void IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct); + + void AttachDFGlobals(lua_State *state); }} diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua new file mode 100644 index 00000000..33d77432 --- /dev/null +++ b/library/lua/dfhack.lua @@ -0,0 +1,5 @@ +-- Common startup file for all dfhack plugins with lua support + +-- The global dfhack table is already created by C++ init +-- code. Feed it back to the require() mechanism. +return dfhack diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 9a277fb4..0886d2a3 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -21,6 +21,7 @@ #include "lua_FunctionCall.h" #include "lua_Offsets.h" #include "DataDefs.h" +#include "LuaTools.h" using std::vector; using std::string; @@ -42,11 +43,12 @@ DFhackCExport const char * plugin_name ( void ) return "dfusion"; } -DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) +DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands) { lua::state st=lua::glua::Get(); + //maybe remake it to run automaticaly - DFHack::AttachDFGlobals(st); + Lua::Open(out, st); lua::RegisterConsole(st); lua::RegisterProcess(st); @@ -64,11 +66,6 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> st.setglobal("WINDOWS"); #endif - st.getglobal("Console"); - st.getfield("println"); - st.setglobal("print"); - st.pop(); - commands.push_back(PluginCommand("dfusion","Run dfusion system (interactive i.e. can input further commands).",dfusion,true)); commands.push_back(PluginCommand("dfuse","Init dfusion system (not interactive).",dfuse,false)); commands.push_back(PluginCommand("lua", "Run interactive interpreter. Use 'lua <filename>' to run <filename> instead.",lua_run,true)); @@ -113,87 +110,6 @@ DFhackCExport command_result plugin_onupdate_DISABLED ( Core * c ) mymutex->unlock(); return CR_OK; } - -void InterpreterLoop(color_ostream &out) -{ - - DFHack::CommandHistory hist; - lua::state s=lua::glua::Get(); - string curline; - out.print("Type quit to exit interactive lua interpreter.\n" - "Shortcuts:\n" - " '= foo' => '_1,_2,... = foo'\n" - " '! foo' => 'print(foo)'\n" - "Both assign the first result to '_'\n"); - assert(out.is_console()); - Console &con = static_cast<Console&>(out); - int vcnt = 1; - - s.settop(0); - - for (;;) { - con.lineedit("[lua]# ",curline,hist); - - if (curline.empty()) - continue; - if (curline == "quit") - break; - - hist.add(curline); - - try - { - char pfix = curline[0]; - - if (pfix == '=' || pfix == '!') - { - curline = "return " + curline.substr(1); - - s.loadstring(curline); - s.pcall(0, LUA_MULTRET); - int numret = s.gettop(); - - if (numret >= 1) - { - s.pushvalue(1); - s.setglobal("_"); - - if (pfix == '!') - { - s.getglobal("print"); - s.insert(1); - s.pcall(numret,0); - numret = 0; - } - } - - for (int i = 1; i <= numret; i++) - { - std::string name = stl_sprintf("_%d", vcnt++); - s.pushvalue(i); - s.setglobal(name); - - con.print("%s = ", name.c_str()); - s.getglobal("print"); - s.pushvalue(i); - s.pcall(1,0); - } - } - else - { - s.loadstring(curline); - s.pcall(); - } - } - catch(lua::exception &e) - { - con.printerr("Error:%s\n",e.what()); - con.printerr("%s\n",lua::DebugDump(lua::glua::Get()).c_str()); - } - - s.settop(0); - } -} command_result lua_run_file (color_ostream &out, std::vector <std::string> ¶meters) { if(parameters.size()==0) @@ -207,14 +123,14 @@ command_result lua_run (color_ostream &out, std::vector <std::string> ¶meter { mymutex->lock(); lua::state s=lua::glua::Get(); - lua::SetConsole(s,out); + if(parameters.size()>0) { try{ s.loadfile(parameters[0]); //load file for(size_t i=1;i<parameters.size();i++) s.push(parameters[i]); - s.pcall(parameters.size()-1,0);// run it + Lua::SafeCall(out, s, parameters.size()-1,0);// run it } catch(lua::exception &e) { @@ -224,7 +140,7 @@ command_result lua_run (color_ostream &out, std::vector <std::string> ¶meter } else { - InterpreterLoop(out); + Lua::InterpreterLoop(out, s); } s.settop(0);// clean up mymutex->unlock(); @@ -235,12 +151,10 @@ void RunDfusion(color_ostream &out, std::vector <std::string> ¶meters) mymutex->lock(); lua::state s=lua::glua::Get(); try{ - s.getglobal("err"); - int errpos=s.gettop(); s.loadfile("dfusion/init.lua"); //load script for(size_t i=0;i<parameters.size();i++) s.push(parameters[i]); - s.pcall(parameters.size(),0,errpos);// run it + Lua::SafeCall(out, s, parameters.size(),0); } catch(lua::exception &e) { @@ -253,7 +167,6 @@ void RunDfusion(color_ostream &out, std::vector <std::string> ¶meters) command_result dfuse(color_ostream &out, std::vector <std::string> ¶meters) { lua::state s=lua::glua::Get(); - lua::SetConsole(s,out); s.push(1); s.setglobal("INIT"); RunDfusion(out,parameters); @@ -262,7 +175,6 @@ command_result dfuse(color_ostream &out, std::vector <std::string> ¶meters) command_result dfusion (color_ostream &out, std::vector <std::string> ¶meters) { lua::state s=lua::glua::Get(); - lua::SetConsole(s,out); s.push(); s.setglobal("INIT"); RunDfusion(out,parameters); diff --git a/plugins/Dfusion/include/lua_Console.h b/plugins/Dfusion/include/lua_Console.h index 227effa9..c6ac5011 100644 --- a/plugins/Dfusion/include/lua_Console.h +++ b/plugins/Dfusion/include/lua_Console.h @@ -7,7 +7,7 @@ namespace lua { void RegisterConsole(lua::state &st); -void SetConsole(lua::state &st,DFHack::color_ostream& stream); + } #endif
\ No newline at end of file diff --git a/plugins/Dfusion/src/lua_Console.cpp b/plugins/Dfusion/src/lua_Console.cpp index 2a8222af..881ba5d2 100644 --- a/plugins/Dfusion/src/lua_Console.cpp +++ b/plugins/Dfusion/src/lua_Console.cpp @@ -1,64 +1,12 @@ #include "lua_Console.h" +#include "LuaTools.h" #include <sstream> //TODO error management. Using lua error? or something other? static DFHack::color_ostream* GetConsolePtr(lua::state &st) { - int t=st.gettop(); - st.getglobal("Console"); - st.getfield("__pointer"); - DFHack::color_ostream* c=static_cast<DFHack::color_ostream*>(lua_touserdata(st,-1)); - st.settop(t); - return c; -} - -static std::string lua_print_fmt(lua_State *L) -{ - /* Copied from lua source to fully replicate builtin print */ - int n = lua_gettop(L); /* number of arguments */ - lua_getglobal(L, "tostring"); - - std::stringstream ss; - - for (int i=1; i<=n; i++) { - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - const char *s = lua_tostring(L, -1); /* get result */ - if (s == NULL) - luaL_error(L, "tostring must return a string to print"); - if (i>1) - ss << '\t'; - ss << s; - lua_pop(L, 1); /* pop result */ - } - - return ss.str(); -} - -static int lua_Console_print(lua_State *S) -{ - lua::state st(S); - DFHack::color_ostream* c=GetConsolePtr(st); - c->print("%s", lua_print_fmt(S).c_str()); - return 0; -} - -static int lua_Console_println(lua_State *S) -{ - lua::state st(S); - DFHack::color_ostream* c=GetConsolePtr(st); - c->print("%s\n", lua_print_fmt(S).c_str()); - return 0; -} - -static int lua_Console_printerr(lua_State *S) -{ - lua::state st(S); - DFHack::color_ostream* c=GetConsolePtr(st); - c->printerr("%s", lua_print_fmt(S).c_str()); - return 0; + return DFHack::Lua::GetOutput(st); } static int lua_Console_clear(lua_State *S) @@ -156,9 +104,6 @@ static int lua_Console_lineedit(lua_State *S) } const luaL_Reg lua_console_func[]= { - {"print",lua_Console_print}, - {"println",lua_Console_println}, - {"printerr",lua_Console_printerr}, {"clear",lua_Console_clear}, {"gotoxy",lua_Console_gotoxy}, {"color",lua_Console_color}, @@ -183,17 +128,3 @@ void lua::RegisterConsole(lua::state &st) //TODO add color consts st.setglobal("Console"); } -void lua::SetConsole(lua::state &st,DFHack::color_ostream& stream) -{ - int top=st.gettop(); - st.getglobal("Console"); - if(st.is<lua::nil>()) - { - st.pop(); - st.newtable(); - } - - st.pushlightuserdata(&stream); - st.setfield("__pointer"); - st.settop(top); -}
\ No newline at end of file |
