Pull console output support and REPL out of dfusion into core lib.

develop
Alexander Gavrilov 2012-03-31 15:40:54 +04:00
parent 9384f0c842
commit 0f41608ed4
14 changed files with 501 additions and 225 deletions

@ -82,6 +82,8 @@ SET(DFHACK_DATA_DESTINATION hack)
SET(DFHACK_PLUGIN_DESTINATION hack/plugins) SET(DFHACK_PLUGIN_DESTINATION hack/plugins)
# dfhack header files go here: # dfhack header files go here:
SET(DFHACK_INCLUDES_DESTINATION hack/include) SET(DFHACK_INCLUDES_DESTINATION hack/include)
# dfhack lua files go here:
SET(DFHACK_LUA_DESTINATION hack/lua)
# the windows .lib file goes here: # the windows .lib file goes here:
SET(DFHACK_DEVLIB_DESTINATION hack) SET(DFHACK_DEVLIB_DESTINATION hack)

@ -89,25 +89,21 @@
** In Windows, any exclamation mark ('!') in the path is replaced by the ** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process. ** 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_CDIR "!\\"
#define LUA_PATH_DEFAULT \ #define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" ".\\?.lua"
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua"
#define LUA_CPATH_DEFAULT \ #define LUA_CPATH_DEFAULT \
LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" LUA_CDIR"?.dll;" ".\\?.dll"
#else /* }{ */ #else /* }{ */
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" #define LUA_LDIR "./hack/lua/"
#define LUA_ROOT "/usr/local/" #define LUA_CDIR "./hack/"
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR
#define LUA_PATH_DEFAULT \ #define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" "./?.lua"
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua"
#define LUA_CPATH_DEFAULT \ #define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" LUA_CDIR"?.so;" "./?.so"
#endif /* } */ #endif /* } */

@ -29,6 +29,7 @@ include/ColorText.h
include/DataDefs.h include/DataDefs.h
include/DataIdentity.h include/DataIdentity.h
include/LuaWrapper.h include/LuaWrapper.h
include/LuaTools.h
include/Error.h include/Error.h
include/Export.h include/Export.h
include/Hooks.h include/Hooks.h
@ -58,6 +59,7 @@ ColorText.cpp
DataDefs.cpp DataDefs.cpp
LuaWrapper.cpp LuaWrapper.cpp
LuaTypes.cpp LuaTypes.cpp
LuaTools.cpp
DataStatics.cpp DataStatics.cpp
DataStaticsCtor.cpp DataStaticsCtor.cpp
DataStaticsFields.cpp DataStaticsFields.cpp
@ -295,6 +297,10 @@ install(TARGETS dfhack-run dfhack-client
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION} LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
RUNTIME 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... # Unused for so long that it's not even relevant now...
if(BUILD_DEVEL) if(BUILD_DEVEL)
if(WIN32) if(WIN32)

@ -757,6 +757,16 @@ std::string Core::getHotkeyCmd( void )
return returner; 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, ...) void Core::printerr(const char *format, ...)
{ {
color_ostream_proxy proxy(getInstance().con); color_ostream_proxy proxy(getInstance().con);

@ -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;
}

@ -59,16 +59,6 @@ void LuaWrapper::field_error(lua_State *state, int index, const char *err, const
mode, (cname ? cname : "?"), (fname ? fname : "?"), err); 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) 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 * Initialize access to DF objects from the interpreter
* context, unless it has already been done. * 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)) if (luaL_newmetatable(state, DFHACK_TYPETABLE_NAME))
{ {

@ -135,6 +135,7 @@ namespace DFHack
DFHack::VersionInfo * vinfo; DFHack::VersionInfo * vinfo;
DFHack::Windows::df_window * screen_window; DFHack::Windows::df_window * screen_window;
static void print(const char *format, ...);
static void printerr(const char *format, ...); static void printerr(const char *format, ...);
private: private:

@ -360,23 +360,6 @@ namespace DFHack
void InitDataDefGlobals(Core *core); 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> template<class T>
T *ifnull(T *a, T *b) { return a ? a : b; } T *ifnull(T *a, T *b) { return a ? a : b; }
@ -683,24 +666,6 @@ namespace DFHack {
flagarray_to_string<T>(&tmp, val); flagarray_to_string<T>(&tmp, val);
return join_strings(sep, tmp); 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) #define ENUM_ATTR(enum,attr,val) (df::enum_traits<df::enum>::attrs(val).attr)

@ -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);
}}

@ -214,5 +214,7 @@ namespace DFHack { namespace LuaWrapper {
void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum); 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 IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct);
void AttachDFGlobals(lua_State *state);
}} }}

@ -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

@ -21,6 +21,7 @@
#include "lua_FunctionCall.h" #include "lua_FunctionCall.h"
#include "lua_Offsets.h" #include "lua_Offsets.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "LuaTools.h"
using std::vector; using std::vector;
using std::string; using std::string;
@ -42,11 +43,12 @@ DFhackCExport const char * plugin_name ( void )
return "dfusion"; 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(); lua::state st=lua::glua::Get();
//maybe remake it to run automaticaly //maybe remake it to run automaticaly
DFHack::AttachDFGlobals(st); Lua::Open(out, st);
lua::RegisterConsole(st); lua::RegisterConsole(st);
lua::RegisterProcess(st); lua::RegisterProcess(st);
@ -64,11 +66,6 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
st.setglobal("WINDOWS"); st.setglobal("WINDOWS");
#endif #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("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("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)); 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(); mymutex->unlock();
return CR_OK; 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> &parameters) command_result lua_run_file (color_ostream &out, std::vector <std::string> &parameters)
{ {
if(parameters.size()==0) if(parameters.size()==0)
@ -207,14 +123,14 @@ command_result lua_run (color_ostream &out, std::vector <std::string> &parameter
{ {
mymutex->lock(); mymutex->lock();
lua::state s=lua::glua::Get(); lua::state s=lua::glua::Get();
lua::SetConsole(s,out);
if(parameters.size()>0) if(parameters.size()>0)
{ {
try{ try{
s.loadfile(parameters[0]); //load file s.loadfile(parameters[0]); //load file
for(size_t i=1;i<parameters.size();i++) for(size_t i=1;i<parameters.size();i++)
s.push(parameters[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) catch(lua::exception &e)
{ {
@ -224,7 +140,7 @@ command_result lua_run (color_ostream &out, std::vector <std::string> &parameter
} }
else else
{ {
InterpreterLoop(out); Lua::InterpreterLoop(out, s);
} }
s.settop(0);// clean up s.settop(0);// clean up
mymutex->unlock(); mymutex->unlock();
@ -235,12 +151,10 @@ void RunDfusion(color_ostream &out, std::vector <std::string> &parameters)
mymutex->lock(); mymutex->lock();
lua::state s=lua::glua::Get(); lua::state s=lua::glua::Get();
try{ try{
s.getglobal("err");
int errpos=s.gettop();
s.loadfile("dfusion/init.lua"); //load script s.loadfile("dfusion/init.lua"); //load script
for(size_t i=0;i<parameters.size();i++) for(size_t i=0;i<parameters.size();i++)
s.push(parameters[i]); s.push(parameters[i]);
s.pcall(parameters.size(),0,errpos);// run it Lua::SafeCall(out, s, parameters.size(),0);
} }
catch(lua::exception &e) catch(lua::exception &e)
{ {
@ -253,7 +167,6 @@ void RunDfusion(color_ostream &out, std::vector <std::string> &parameters)
command_result dfuse(color_ostream &out, std::vector <std::string> &parameters) command_result dfuse(color_ostream &out, std::vector <std::string> &parameters)
{ {
lua::state s=lua::glua::Get(); lua::state s=lua::glua::Get();
lua::SetConsole(s,out);
s.push(1); s.push(1);
s.setglobal("INIT"); s.setglobal("INIT");
RunDfusion(out,parameters); RunDfusion(out,parameters);
@ -262,7 +175,6 @@ command_result dfuse(color_ostream &out, std::vector <std::string> &parameters)
command_result dfusion (color_ostream &out, std::vector <std::string> &parameters) command_result dfusion (color_ostream &out, std::vector <std::string> &parameters)
{ {
lua::state s=lua::glua::Get(); lua::state s=lua::glua::Get();
lua::SetConsole(s,out);
s.push(); s.push();
s.setglobal("INIT"); s.setglobal("INIT");
RunDfusion(out,parameters); RunDfusion(out,parameters);

@ -7,7 +7,7 @@ namespace lua
{ {
void RegisterConsole(lua::state &st); void RegisterConsole(lua::state &st);
void SetConsole(lua::state &st,DFHack::color_ostream& stream);
} }
#endif #endif

@ -1,64 +1,12 @@
#include "lua_Console.h" #include "lua_Console.h"
#include "LuaTools.h"
#include <sstream> #include <sstream>
//TODO error management. Using lua error? or something other? //TODO error management. Using lua error? or something other?
static DFHack::color_ostream* GetConsolePtr(lua::state &st) static DFHack::color_ostream* GetConsolePtr(lua::state &st)
{ {
int t=st.gettop(); return DFHack::Lua::GetOutput(st);
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;
} }
static int lua_Console_clear(lua_State *S) 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[]= const luaL_Reg lua_console_func[]=
{ {
{"print",lua_Console_print},
{"println",lua_Console_println},
{"printerr",lua_Console_printerr},
{"clear",lua_Console_clear}, {"clear",lua_Console_clear},
{"gotoxy",lua_Console_gotoxy}, {"gotoxy",lua_Console_gotoxy},
{"color",lua_Console_color}, {"color",lua_Console_color},
@ -183,17 +128,3 @@ void lua::RegisterConsole(lua::state &st)
//TODO add color consts //TODO add color consts
st.setglobal("Console"); 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);
}