Add basic lua expression support to memview

Currently just supports basic field accesses (world.x, screen.y.z).
No support for world.x - 4, etc.

Closes #976
develop
lethosor 2016-08-24 16:20:30 -04:00
parent 7487f44fc8
commit 6ce470ad57
5 changed files with 111 additions and 2 deletions

@ -652,4 +652,25 @@ function df_shortcut_env()
return env return env
end end
df_env = df_shortcut_env()
function df_expr_to_ref(expr)
expr = expr:gsub('%["(.-)"%]', function(field) return '.' .. field end)
:gsub('%[\'(.-)\'%]', function(field) return '.' .. field end)
local parts = split_string(expr, '%.')
local obj = df_env[parts[1]]
for i = 2, #parts do
if i == #parts and type(obj[parts[i]]) ~= 'userdata' then
obj = obj:_field(parts[i])
else
obj = obj[parts[i]]
end
end
return obj
end
function addressof(obj)
return select(2, obj:sizeof())
end
return _ENV return _ENV

@ -10,7 +10,7 @@ DFHACK_PLUGIN(dumpmats dumpmats.cpp)
DFHACK_PLUGIN(eventExample eventExample.cpp) DFHACK_PLUGIN(eventExample eventExample.cpp)
DFHACK_PLUGIN(frozen frozen.cpp) DFHACK_PLUGIN(frozen frozen.cpp)
DFHACK_PLUGIN(kittens kittens.cpp) DFHACK_PLUGIN(kittens kittens.cpp)
DFHACK_PLUGIN(memview memview.cpp) DFHACK_PLUGIN(memview memview.cpp memutils.cpp LINK_LIBRARIES lua)
DFHACK_PLUGIN(nestboxes nestboxes.cpp) DFHACK_PLUGIN(nestboxes nestboxes.cpp)
DFHACK_PLUGIN(notes notes.cpp) DFHACK_PLUGIN(notes notes.cpp)
DFHACK_PLUGIN(onceExample onceExample.cpp) DFHACK_PLUGIN(onceExample onceExample.cpp)

@ -0,0 +1,71 @@
#include <string>
#include "Core.h"
#include "LuaTools.h"
#include "LuaWrapper.h"
using namespace DFHack;
using namespace DFHack::LuaWrapper;
using namespace std;
namespace memutils {
static lua_State *state;
static color_ostream_proxy *out;
struct initializer {
Lua::StackUnwinder *unwinder;
initializer()
{
if (!out)
out = new color_ostream_proxy(Core::getInstance().getConsole());
if (!state)
state = Lua::Open(*out);
unwinder = new Lua::StackUnwinder(state);
}
~initializer()
{
delete unwinder;
}
};
struct cleaner {
~cleaner()
{
if (state)
{
lua_close(state);
state = NULL;
}
if (out)
{
delete out;
out = NULL;
}
}
};
static cleaner g_cleaner;
void *lua_expr_to_addr(const char *expr)
{
initializer init;
Lua::PushModulePublic(*out, state, "utils", "df_expr_to_ref");
lua_pushstring(state, expr);
if (!Lua::SafeCall(*out, state, 1, 1))
{
out->printerr("Failed to evaluate %s\n", expr);
return NULL;
}
Lua::PushModulePublic(*out, state, "utils", "addressof");
lua_swap(state);
if (!Lua::SafeCall(*out, state, 1, 1) || !lua_isinteger(state, -1))
{
out->printerr("Failed to get address: %s\n", expr);
return NULL;
}
auto addr = uintptr_t(lua_tointeger(state, -1));
return (void*)addr;
}
}

@ -0,0 +1,3 @@
namespace memutils {
void *lua_expr_to_addr(const char *expr);
}

@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include "memutils.h"
using std::vector; using std::vector;
using std::string; using std::string;
using namespace DFHack; using namespace DFHack;
@ -138,7 +140,19 @@ command_result memview (color_ostream &out, vector <string> & parameters)
{ {
mymutex->lock(); mymutex->lock();
Core::getInstance().p->getMemRanges(memdata.ranges); Core::getInstance().p->getMemRanges(memdata.ranges);
if (parameters.empty())
{
memdata.addr = 0;
}
else if (toLower(parameters[0].substr(0, 2)) == "0x")
{
memdata.addr = (void *)convert(parameters[0],true); memdata.addr = (void *)convert(parameters[0],true);
}
else
{
memdata.addr = memutils::lua_expr_to_addr(parameters[0].c_str());
}
if(memdata.addr==0) if(memdata.addr==0)
{ {
Deinit(); Deinit();