From 8d7cf092fd6f3f1cf68e6b48b8f3dc42ef40dcfa Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Wed, 13 Jun 2012 21:12:36 +0400
Subject: [PATCH] Add Lua API for access to some contextual and low-level info.
---
LUA_API.rst | 39 +++++++++++++++
Lua API.html | 52 +++++++++++++++----
library/LuaApi.cpp | 115 +++++++++++++++++++++++++++++++++++++++++++
library/LuaTools.cpp | 6 +--
4 files changed, 199 insertions(+), 13 deletions(-)
diff --git a/LUA_API.rst b/LUA_API.rst
index 0736b02b7..54105d045 100644
--- a/LUA_API.rst
+++ b/LUA_API.rst
@@ -607,6 +607,22 @@ One notable difference is that these explicit wrappers allow argument count
adjustment according to the usual lua rules, so trailing false/nil arguments
can be omitted.
+* ``dfhack.getOSType()``
+
+ Returns the OS type string from ``symbols.xml``.
+
+* ``dfhack.getDFVersion()``
+
+ Returns the DF version string from ``symbols.xml``.
+
+* ``dfhack.getDFPath()``
+
+ Returns the DF directory path.
+
+* ``dfhack.getHackPath()``
+
+ Returns the dfhack directory path, i.e. ``".../df/hack/"``.
+
* ``dfhack.isWorldLoaded()``
Checks if the world is loaded.
@@ -1102,6 +1118,29 @@ Constructions module
Returns *true, was_only_planned* if removed; or *false* if none found.
+Internal API
+------------
+
+These functions are intended for the use by dfhack developers,
+and are only documented here for completeness:
+
+* ``dfhack.internal.getAddress(name)``
+
+ Returns the global address ``name``, or *nil*.
+
+* ``dfhack.internal.setAddress(name, value)``
+
+ Sets the global address ``name``. Returns the value of ``getAddress`` before the change.
+
+* ``dfhack.internal.getBase()``
+
+ Returns the base address of the process.
+
+* ``dfhack.internal.getMemRanges()``
+
+ Returns a sequence of tables describing virtual memory ranges of the process.
+
+
Core interpreter context
========================
diff --git a/Lua API.html b/Lua API.html
index 568090a76..02e7abf3c 100644
--- a/Lua API.html
+++ b/Lua API.html
@@ -345,17 +345,18 @@ ul.auto-toc {
Burrows module
Buildings module
Constructions module
+Internal API
-Core interpreter context
-Plugins
@@ -862,6 +863,18 @@ One notable difference is that these explicit wrappers allow argument count
adjustment according to the usual lua rules, so trailing false/nil arguments
can be omitted.
+dfhack.getOSType()
+Returns the OS type string from symbols.xml.
+
+dfhack.getDFVersion()
+Returns the DF version string from symbols.xml.
+
+dfhack.getDFPath()
+Returns the DF directory path.
+
+dfhack.getHackPath()
+Returns the dfhack directory path, i.e. ".../df/hack/".
+
dfhack.isWorldLoaded()
Checks if the world is loaded.
@@ -1274,9 +1287,28 @@ Returns true, was_only_planned if removed; or false if none fo
+
+
+
These functions are intended for the use by dfhack developers,
+and are only documented here for completeness:
+
+dfhack.internal.getAddress(name)
+Returns the global address name, or nil.
+
+dfhack.internal.setAddress(name, value)
+Sets the global address name. Returns the value of getAddress before the change.
+
+dfhack.internal.getBase()
+Returns the base address of the process.
+
+dfhack.internal.getMemRanges()
+Returns a sequence of tables describing virtual memory ranges of the process.
+
+
+
-
+
While plugins can create any number of interpreter instances,
there is one special context managed by dfhack core. It is the
only context that can receive events from DF and plugins.
@@ -1307,7 +1339,7 @@ Using
timeout_active(id,nil) cancels the timer
-
+
An event is just a lua table with a predefined metatable that
contains a __call metamethod. When it is invoked, it loops
through the table with next and calls all contained values.
@@ -1333,14 +1365,14 @@ order using dfhack.safecall.
-
+
DFHack plugins may export native functions and events
to lua contexts. They are automatically imported by
mkmodule('plugins.<name>'); this means that a lua
module file is still necessary for require to read.
The following plugins have lua support.
-
+
Implements extended burrow manipulations.
Events:
-
+
Does not export any native functions as of now. Instead, it
calls lua code to perform the actual ordering of list items.
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index 8e8a3c4e3..aa168db3a 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -84,6 +84,8 @@ distribution.
using namespace DFHack;
using namespace DFHack::LuaWrapper;
+void dfhack_printerr(lua_State *S, const std::string &str);
+
void Lua::Push(lua_State *state, const Units::NoblePosition &pos)
{
lua_createtable(state, 0, 3);
@@ -640,10 +642,37 @@ static void OpenModule(lua_State *state, const char *mname,
/***** DFHack module *****/
+static std::string getOSType()
+{
+ switch (Core::getInstance().vinfo->getOS())
+ {
+ case OS_WINDOWS:
+ return "windows";
+
+ case OS_LINUX:
+ return "linux";
+
+ case OS_APPLE:
+ return "darwin";
+
+ default:
+ return "unknown";
+ }
+}
+
+static std::string getDFVersion() { return Core::getInstance().vinfo->getVersion(); }
+
+static std::string getDFPath() { return Core::getInstance().p->getPath(); }
+static std::string getHackPath() { return Core::getInstance().getHackPath(); }
+
static bool isWorldLoaded() { return Core::getInstance().isWorldLoaded(); }
static bool isMapLoaded() { return Core::getInstance().isMapLoaded(); }
static const LuaWrapper::FunctionReg dfhack_module[] = {
+ WRAP(getOSType),
+ WRAP(getDFVersion),
+ WRAP(getDFPath),
+ WRAP(getHackPath),
WRAP(isWorldLoaded),
WRAP(isMapLoaded),
WRAPM(Translation, TranslateName),
@@ -990,6 +1019,91 @@ static const luaL_Reg dfhack_constructions_funcs[] = {
{ NULL, NULL }
};
+/***** Internal module *****/
+
+static uint32_t getBase() { return Core::getInstance().p->getBase(); }
+
+static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
+ WRAP(getBase),
+ { NULL, NULL }
+};
+
+static int internal_getAddress(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ uint32_t addr = Core::getInstance().vinfo->getAddress(name);
+ if (addr)
+ lua_pushnumber(L, addr);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+static int internal_setAddress(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ uint32_t addr = luaL_checkint(L, 2);
+ internal_getAddress(L);
+
+ // Set the address
+ Core::getInstance().vinfo->setAddress(name, addr);
+
+ auto fields = df::global::_identity.getFields();
+
+ for (int i = 0; fields && fields[i].mode != struct_field_info::END; ++i)
+ {
+ if (fields[i].name != name)
+ continue;
+
+ *(void**)fields[i].offset = (void*)addr;
+ }
+
+ // Print via printerr, so that it is definitely logged to stderr.log.
+ std::string msg = stl_sprintf("
", name.c_str(), addr);
+ dfhack_printerr(L, msg);
+
+ return 1;
+}
+
+static int internal_getMemRanges(lua_State *L)
+{
+ std::vector
ranges;
+ Core::getInstance().p->getMemRanges(ranges);
+
+ lua_newtable(L);
+
+ for(size_t i = 0; i < ranges.size(); i++)
+ {
+ lua_newtable(L);
+ lua_pushnumber(L, (uint32_t)ranges[i].start);
+ lua_setfield(L, -2, "start");
+ lua_pushnumber(L, (uint32_t)ranges[i].end);
+ lua_setfield(L, -2, "end");
+ lua_pushstring(L, ranges[i].name);
+ lua_setfield(L, -2, "name");
+ lua_pushboolean(L, ranges[i].read);
+ lua_setfield(L, -2, "read");
+ lua_pushboolean(L, ranges[i].write);
+ lua_setfield(L, -2, "write");
+ lua_pushboolean(L, ranges[i].execute);
+ lua_setfield(L, -2, "execute");
+ lua_pushboolean(L, ranges[i].shared);
+ lua_setfield(L, -2, "shared");
+ lua_pushboolean(L, ranges[i].valid);
+ lua_setfield(L, -2, "valid");
+ lua_rawseti(L, -2, i+1);
+ }
+
+ return 1;
+}
+
+static const luaL_Reg dfhack_internal_funcs[] = {
+ { "getAddress", internal_getAddress },
+ { "setAddress", internal_setAddress },
+ { "getMemRanges", internal_getMemRanges },
+ { NULL, NULL }
+};
+
/************************
* Main Open function *
@@ -1009,4 +1123,5 @@ void OpenDFHackApi(lua_State *state)
OpenModule(state, "burrows", dfhack_burrows_module, dfhack_burrows_funcs);
OpenModule(state, "buildings", dfhack_buildings_module, dfhack_buildings_funcs);
OpenModule(state, "constructions", dfhack_constructions_module);
+ OpenModule(state, "internal", dfhack_internal_module, dfhack_internal_funcs);
}
diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp
index f794f6b41..752c341b2 100644
--- a/library/LuaTools.cpp
+++ b/library/LuaTools.cpp
@@ -66,6 +66,8 @@ using namespace DFHack::LuaWrapper;
lua_State *DFHack::Lua::Core::State = NULL;
+void dfhack_printerr(lua_State *S, const std::string &str);
+
inline void AssertCoreSuspend(lua_State *state)
{
assert(!Lua::IsCoreContext(state) || DFHack::Core::getInstance().isSuspended());
@@ -96,8 +98,6 @@ static void check_valid_ptr_index(lua_State *state, int val_index)
}
}
-static void dfhack_printerr(lua_State *S, const std::string &str);
-
static void signal_typeid_error(color_ostream *out, lua_State *state,
type_identity *type, const char *msg,
int val_index, bool perr, bool signal)
@@ -233,7 +233,7 @@ static int lua_dfhack_println(lua_State *S)
return 0;
}
-static void dfhack_printerr(lua_State *S, const std::string &str)
+void dfhack_printerr(lua_State *S, const std::string &str)
{
if (color_ostream *out = Lua::GetOutput(S))
out->printerr("%s\n", str.c_str());