summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorTimothy Collett2012-09-10 09:18:24 -0400
committerTimothy Collett2012-09-10 09:18:24 -0400
commit270351f510db516811117ab746a563560102c14b (patch)
tree40f05ca4e5c9aac7fd24071436921ca4748b8e47 /library
parentd5ae1fc4f217589d0a34c116237740475accb267 (diff)
parent45456b2230bd87bacc4bcd32515f530baafa8c04 (diff)
downloaddfhack-270351f510db516811117ab746a563560102c14b.tar.gz
dfhack-270351f510db516811117ab746a563560102c14b.tar.bz2
dfhack-270351f510db516811117ab746a563560102c14b.tar.xz
Merge branch 'master' of https://github.com/danaris/dfhack
Diffstat (limited to 'library')
-rw-r--r--library/CMakeLists.txt2
-rw-r--r--library/Core.cpp73
-rw-r--r--library/Hooks-darwin.cpp26
-rw-r--r--library/LuaApi.cpp9
-rw-r--r--library/LuaTools.cpp83
-rw-r--r--library/PluginManager.cpp8
-rw-r--r--library/Process-windows.cpp136
-rw-r--r--library/include/ColorText.h2
-rw-r--r--library/include/Core.h7
-rw-r--r--library/include/Hooks.h6
-rw-r--r--library/include/PluginManager.h2
-rw-r--r--library/lua/dfhack.lua6
-rw-r--r--library/lua/memscan.lua46
-rw-r--r--library/lua/utils.lua2
14 files changed, 331 insertions, 77 deletions
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 73f6c9ec..75485ff2 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -8,8 +8,8 @@ IF(UNIX)
OPTION(CONSOLE_NO_CATCH "Make the console not catch 'CTRL+C' events for easier debugging." OFF)
ENDIF()
-include_directories (include)
include_directories (proto)
+include_directories (include)
SET(PERL_EXECUTABLE "perl" CACHE FILEPATH "This is the perl executable to run in the codegen step. Tweak it if you need to run a specific one.")
diff --git a/library/Core.cpp b/library/Core.cpp
index f30e19c2..09344135 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -204,7 +204,7 @@ struct sortable
};
};
-static std::string getLuaHelp(std::string path)
+static std::string getScriptHelp(std::string path, std::string helpprefix)
{
ifstream script(path.c_str());
@@ -212,14 +212,14 @@ static std::string getLuaHelp(std::string path)
{
std::string help;
if (getline(script, help) &&
- help.substr(0,3) == "-- ")
- return help.substr(3);
+ help.substr(0,helpprefix.length()) == helpprefix)
+ return help.substr(helpprefix.length());
}
- return "Lua script.";
+ return "No help available.";
}
-static std::map<string,string> listLuaScripts(std::string path)
+static std::map<string,string> listScripts(PluginManager *plug_mgr, std::string path)
{
std::vector<string> files;
getdir(path, files);
@@ -229,10 +229,16 @@ static std::map<string,string> listLuaScripts(std::string path)
{
if (hasEnding(files[i], ".lua"))
{
- std::string help = getLuaHelp(path + files[i]);
+ std::string help = getScriptHelp(path + files[i], "-- ");
pset[files[i].substr(0, files[i].size()-4)] = help;
}
+ else if (plug_mgr->eval_ruby && hasEnding(files[i], ".rb"))
+ {
+ std::string help = getScriptHelp(path + files[i], "# ");
+
+ pset[files[i].substr(0, files[i].size()-3)] = help;
+ }
}
return pset;
}
@@ -275,31 +281,34 @@ static command_result runLuaScript(color_ostream &out, std::string name, vector<
return ok ? CR_OK : CR_FAILURE;
}
+static command_result runRubyScript(PluginManager *plug_mgr, std::string name, vector<string> &args)
+{
+ std::string rbcmd = "$script_args = [";
+ for (size_t i = 0; i < args.size(); i++)
+ rbcmd += "'" + args[i] + "', ";
+ rbcmd += "]\n";
+
+ rbcmd += "load './hack/scripts/" + name + ".rb'";
+
+ return plug_mgr->eval_ruby(rbcmd.c_str());
+}
+
command_result Core::runCommand(color_ostream &out, const std::string &command)
{
- //fprintf(stderr,"Inside runCommand");
- //fprintf(stderr," with command %s\n",command.c_str());
if (!command.empty())
{
- //fprintf(stderr,"Command is not empty, tokenizing\n");
vector <string> parts;
Core::cheap_tokenise(command,parts);
- //fprintf(stderr,"Tokenized, got %d parts\n",parts.size());
if(parts.size() == 0)
return CR_NOT_IMPLEMENTED;
string first = parts[0];
- //fprintf(stderr,"Erasing beginning\n");
parts.erase(parts.begin());
-
- //fprintf(stderr,"I think we're about there\n");
if (first[0] == '#')
return CR_OK;
cerr << "Invoking: " << command << endl;
-
- //fprintf(stderr,"Returning with the next recursion\n");
return runCommand(out, first, parts);
}
else
@@ -357,10 +366,16 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
return CR_OK;
}
}
- auto filename = getHackPath() + "scripts/" + parts[0] + ".lua";
- if (fileExists(filename))
+ auto filename = getHackPath() + "scripts/" + parts[0];
+ if (fileExists(filename + ".lua"))
+ {
+ string help = getScriptHelp(filename + ".lua", "-- ");
+ con.print("%s: %s\n", parts[0].c_str(), help.c_str());
+ return CR_OK;
+ }
+ if (plug_mgr->eval_ruby && fileExists(filename + ".rb"))
{
- string help = getLuaHelp(filename);
+ string help = getScriptHelp(filename + ".rb", "# ");
con.print("%s: %s\n", parts[0].c_str(), help.c_str());
return CR_OK;
}
@@ -508,7 +523,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
con.print(" %-22s- %s\n",(*iter).name.c_str(), (*iter).description.c_str());
con.reset_color();
}
- auto scripts = listLuaScripts(getHackPath() + "scripts/");
+ auto scripts = listScripts(plug_mgr, getHackPath() + "scripts/");
if (!scripts.empty())
{
con.print("\nscripts:\n");
@@ -613,9 +628,11 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
command_result res = plug_mgr->InvokeCommand(con, first, parts);
if(res == CR_NOT_IMPLEMENTED)
{
- auto filename = getHackPath() + "scripts/" + first + ".lua";
- if (fileExists(filename))
+ auto filename = getHackPath() + "scripts/" + first;
+ if (fileExists(filename + ".lua"))
res = runLuaScript(con, first, parts);
+ else if (plug_mgr->eval_ruby && fileExists(filename + ".rb"))
+ res = runRubyScript(plug_mgr, first, parts);
else
con.printerr("%s is not a recognized command.\n", first.c_str());
}
@@ -680,7 +697,7 @@ void fIOthread(void * iodata)
{
string command = "";
int ret = con.lineedit("[DFHack]# ",command, main_history);
- //fprintf(stderr,"Command: [%s]\n",command.c_str());
+ fprintf(stderr,"Command: [%s]\n",command.c_str());
if(ret == -2)
{
cerr << "Console is shutting down properly." << endl;
@@ -694,13 +711,13 @@ void fIOthread(void * iodata)
else if(ret)
{
// a proper, non-empty command was entered
- //fprintf(stderr,"Adding command to history\n");
+ fprintf(stderr,"Adding command to history\n");
main_history.add(command);
- //fprintf(stderr,"Saving history\n");
+ fprintf(stderr,"Saving history\n");
main_history.save("dfhack.history");
}
- //fprintf(stderr,"Running command\n");
+ fprintf(stderr,"Running command\n");
auto rv = core->runCommand(con, command);
@@ -1207,7 +1224,8 @@ bool Core::ncurses_wgetch(int in, int & out)
{
df::viewscreen * ws = Gui::GetCurrentScreen();
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(ws) &&
- df::global::ui->main.mode != ui_sidebar_mode::Hotkeys)
+ df::global::ui->main.mode != ui_sidebar_mode::Hotkeys &&
+ df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
{
setHotkeyCmd(df::global::ui->main.hotkeys[idx].name);
return false;
@@ -1355,7 +1373,8 @@ bool Core::SelectHotkey(int sym, int modifiers)
idx += 8;
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(screen) &&
- df::global::ui->main.mode != ui_sidebar_mode::Hotkeys)
+ df::global::ui->main.mode != ui_sidebar_mode::Hotkeys &&
+ df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
{
cmd = df::global::ui->main.hotkeys[idx].name;
}
diff --git a/library/Hooks-darwin.cpp b/library/Hooks-darwin.cpp
index ef89105d..190616b8 100644
--- a/library/Hooks-darwin.cpp
+++ b/library/Hooks-darwin.cpp
@@ -38,11 +38,11 @@ distribution.
#include <string>
#include <map>
-/*typedef struct interpose_s
+typedef struct interpose_s
{
void *new_func;
void *orig_func;
-} interpose_t;*/
+} interpose_t;
#include "DFHack.h"
#include "Core.h"
@@ -58,11 +58,18 @@ distribution.
};*/
+#define DYLD_INTERPOSE(_replacment,_replacee) __attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };
+
+DYLD_INTERPOSE(DFH_SDL_Init,SDL_Init);
+DYLD_INTERPOSE(DFH_SDL_PollEvent,SDL_PollEvent);
+DYLD_INTERPOSE(DFH_SDL_Quit,SDL_Quit);
+DYLD_INTERPOSE(DFH_SDL_NumJoysticks,SDL_NumJoysticks);
+
/*******************************************************************************
* SDL part starts here *
*******************************************************************************/
// hook - called for each game tick (or more often)
-DFhackCExport int SDL_NumJoysticks(void)
+DFhackCExport int DFH_SDL_NumJoysticks(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
return c.Update();
@@ -70,7 +77,7 @@ DFhackCExport int SDL_NumJoysticks(void)
// hook - called at program exit
static void (*_SDL_Quit)(void) = 0;
-DFhackCExport void SDL_Quit(void)
+DFhackCExport void DFH_SDL_Quit(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
c.Shutdown();
@@ -79,16 +86,16 @@ DFhackCExport void SDL_Quit(void)
_SDL_Quit();
}*/
- _SDL_Quit();
+ SDL_Quit();
}
// called by DF to check input events
static int (*_SDL_PollEvent)(SDL::Event* event) = 0;
-DFhackCExport int SDL_PollEvent(SDL::Event* event)
+DFhackCExport int DFH_SDL_PollEvent(SDL::Event* event)
{
pollevent_again:
// if SDL returns 0 here, it means there are no more events. return 0
- int orig_return = _SDL_PollEvent(event);
+ int orig_return = SDL_PollEvent(event);
if(!orig_return)
return 0;
// otherwise we have an event to filter
@@ -128,7 +135,7 @@ DFhackCExport int wgetch(WINDOW *win)
// hook - called at program start, initialize some stuffs we'll use later
static int (*_SDL_Init)(uint32_t flags) = 0;
-DFhackCExport int SDL_Init(uint32_t flags)
+DFhackCExport int DFH_SDL_Init(uint32_t flags)
{
// reroute stderr
fprintf(stderr,"dfhack: attempting to hook in\n");
@@ -158,6 +165,7 @@ DFhackCExport int SDL_Init(uint32_t flags)
DFHack::Core & c = DFHack::Core::getInstance();
//c.Init();
- int ret = _SDL_Init(flags);
+ //int ret = _SDL_Init(flags);
+ int ret = SDL_Init(flags);
return ret;
} \ No newline at end of file
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index 631b3c49..b0a085ec 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -1036,10 +1036,10 @@ static void *checkaddr(lua_State *L, int idx, bool allow_null = false)
return rv;
}
-static uint32_t getBase() { return Core::getInstance().p->getBase(); }
+static int getRebaseDelta() { return Core::getInstance().vinfo->getRebaseDelta(); }
static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
- WRAP(getBase),
+ WRAP(getRebaseDelta),
{ NULL, NULL }
};
@@ -1074,8 +1074,9 @@ static int internal_setAddress(lua_State *L)
}
// Print via printerr, so that it is definitely logged to stderr.log.
- std::string msg = stl_sprintf("<global-address name='%s' value='0x%x'/>", name.c_str(), addr);
- dfhack_printerr(L, msg);
+ uint32_t iaddr = addr - Core::getInstance().vinfo->getRebaseDelta();
+ fprintf(stderr, "Setting global '%s' to %x (%x)\n", name.c_str(), addr, iaddr);
+ fflush(stderr);
return 1;
}
diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp
index 752c341b..28571a0f 100644
--- a/library/LuaTools.cpp
+++ b/library/LuaTools.cpp
@@ -256,8 +256,11 @@ static int lua_dfhack_color(lua_State *S)
luaL_argerror(S, 1, "invalid color value");
color_ostream *out = Lua::GetOutput(S);
- if (out)
+ if (out) {
+ lua_pushinteger(S, (int)out->color());
out->color(color_ostream::color_value(cv));
+ return 1;
+ }
return 0;
}
@@ -423,10 +426,12 @@ static bool convert_to_exception(lua_State *L, int slevel, lua_State *thread = N
// Create a new exception for this thread
lua_newtable(L);
- luaL_where(L, 1);
+ luaL_where(L, slevel);
+ lua_setfield(L, -2, "where");
lua_pushstring(L, "coroutine resume failed");
- lua_concat(L, 2);
lua_setfield(L, -2, "message");
+ lua_getfield(L, -2, "verbose");
+ lua_setfield(L, -2, "verbose");
lua_swap(L);
lua_setfield(L, -2, "cause");
}
@@ -480,12 +485,57 @@ static int dfhack_onerror(lua_State *L)
return 1;
}
+static int dfhack_error(lua_State *L)
+{
+ luaL_checkany(L, 1);
+ lua_settop(L, 3);
+ int level = std::max(1, luaL_optint(L, 2, 1));
+
+ lua_pushvalue(L, 1);
+
+ if (convert_to_exception(L, level))
+ {
+ luaL_where(L, level);
+ lua_setfield(L, -2, "where");
+
+ if (!lua_isnil(L, 3))
+ {
+ lua_pushvalue(L, 3);
+ lua_setfield(L, -2, "verbose");
+ }
+ }
+
+ return lua_error(L);
+}
+
static int dfhack_exception_tostring(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 2);
+
+ if (lua_isnil(L, 2))
+ {
+ lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_EXCEPTION_META_TOKEN);
+ lua_getfield(L, -1, "verbose");
+ lua_insert(L, 2);
+ lua_settop(L, 2);
+ }
+
+ lua_getfield(L, 1, "verbose");
+
+ bool verbose =
+ lua_toboolean(L, 2) || lua_toboolean(L, 3) ||
+ (lua_isnil(L, 2) && lua_isnil(L, 3));
int base = lua_gettop(L);
+ if (verbose || lua_isnil(L, 3))
+ {
+ lua_getfield(L, 1, "where");
+ if (!lua_isstring(L, -1))
+ lua_pop(L, 1);
+ }
+
lua_getfield(L, 1, "message");
if (!lua_isstring(L, -1))
{
@@ -493,15 +543,26 @@ static int dfhack_exception_tostring(lua_State *L)
lua_pushstring(L, "(error message is not a string)");
}
- lua_pushstring(L, "\n");
- lua_getfield(L, 1, "stacktrace");
- if (!lua_isstring(L, -1))
- lua_pop(L, 2);
+ if (verbose)
+ {
+ lua_pushstring(L, "\n");
+ lua_getfield(L, 1, "stacktrace");
+ if (!lua_isstring(L, -1))
+ lua_pop(L, 2);
+ }
lua_pushstring(L, "\ncaused by:\n");
lua_getfield(L, 1, "cause");
if (lua_isnil(L, -1))
lua_pop(L, 2);
+ else if (lua_istable(L, -1))
+ {
+ lua_pushcfunction(L, dfhack_exception_tostring);
+ lua_swap(L);
+ lua_pushvalue(L, 2);
+ if (lua_pcall(L, 2, 1, 0) != LUA_OK)
+ error_tostring(L);
+ }
else
error_tostring(L);
@@ -652,7 +713,12 @@ static int dfhack_coauxwrap (lua_State *L) {
if (Lua::IsSuccess(r))
return lua_gettop(L);
else
+ {
+ if (lua_checkstack(L, LUA_MINSTACK))
+ convert_to_exception(L, 1);
+
return lua_error(L);
+ }
}
static int dfhack_cowrap (lua_State *L) {
@@ -1159,6 +1225,7 @@ static const luaL_Reg dfhack_funcs[] = {
{ "safecall", dfhack_safecall },
{ "saferesume", dfhack_saferesume },
{ "onerror", dfhack_onerror },
+ { "error", dfhack_error },
{ "call_with_finalizer", dfhack_call_with_finalizer },
{ "with_suspend", lua_dfhack_with_suspend },
{ "open_plugin", dfhack_open_plugin },
@@ -1359,6 +1426,8 @@ lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state)
lua_newtable(state);
lua_pushcfunction(state, dfhack_exception_tostring);
lua_setfield(state, -2, "__tostring");
+ lua_pushcfunction(state, dfhack_exception_tostring);
+ lua_setfield(state, -2, "tostring");
lua_dup(state);
lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_EXCEPTION_META_TOKEN);
lua_setfield(state, -2, "exception");
diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp
index ae8cc755..a314883e 100644
--- a/library/PluginManager.cpp
+++ b/library/PluginManager.cpp
@@ -188,6 +188,7 @@ bool Plugin::load(color_ostream &con)
plugin_shutdown = (command_result (*)(color_ostream &)) LookupPlugin(plug, "plugin_shutdown");
plugin_onstatechange = (command_result (*)(color_ostream &, state_change_event)) LookupPlugin(plug, "plugin_onstatechange");
plugin_rpcconnect = (RPCService* (*)(color_ostream &)) LookupPlugin(plug, "plugin_rpcconnect");
+ plugin_eval_ruby = (command_result (*)(const char*)) LookupPlugin(plug, "plugin_eval_ruby");
index_lua(plug);
this->name = *plug_name;
plugin_lib = plug;
@@ -538,6 +539,7 @@ PluginManager::PluginManager(Core * core)
const string searchstr = ".plug.dll";
#endif
cmdlist_mutex = new mutex();
+ eval_ruby = NULL;
vector <string> filez;
getdir(path, filez);
for(size_t i = 0; i < filez.size();i++)
@@ -620,6 +622,8 @@ void PluginManager::registerCommands( Plugin * p )
{
belongs[cmds[i].name] = p;
}
+ if (p->plugin_eval_ruby)
+ eval_ruby = p->plugin_eval_ruby;
cmdlist_mutex->unlock();
}
@@ -632,5 +636,7 @@ void PluginManager::unregisterCommands( Plugin * p )
{
belongs.erase(cmds[i].name);
}
+ if (p->plugin_eval_ruby)
+ eval_ruby = NULL;
cmdlist_mutex->unlock();
-} \ No newline at end of file
+}
diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp
index 944a773c..7eb6ff5f 100644
--- a/library/Process-windows.cpp
+++ b/library/Process-windows.cpp
@@ -233,19 +233,55 @@ struct HeapBlock
ULONG reserved;
};
*/
-// FIXME: NEEDS TESTING!
-// FIXME: <warmist> i noticed that if you enumerate it twice, second time it returns wrong .text region size
+
+static void GetDosNames(std::map<string, string> &table)
+{
+ // Partially based on example from msdn:
+ // Translate path with device name to drive letters.
+ TCHAR szTemp[512];
+ szTemp[0] = '\0';
+
+ if (GetLogicalDriveStrings(sizeof(szTemp)-1, szTemp))
+ {
+ TCHAR szName[MAX_PATH];
+ TCHAR szDrive[3] = " :";
+ BOOL bFound = FALSE;
+ TCHAR* p = szTemp;
+
+ do
+ {
+ // Copy the drive letter to the template string
+ *szDrive = *p;
+
+ // Look up each device name
+ if (QueryDosDevice(szDrive, szName, MAX_PATH))
+ table[szName] = szDrive;
+
+ // Go to the next NULL character.
+ while (*p++);
+ } while (*p); // end of string
+ }
+}
+
void Process::getMemRanges( vector<t_memrange> & ranges )
{
MEMORY_BASIC_INFORMATION MBI;
//map<char *, unsigned int> heaps;
uint64_t movingStart = 0;
+ PVOID LastAllocationBase = 0;
map <char *, string> nameMap;
+ map <string,string> dosDrives;
// get page size
SYSTEM_INFO si;
GetSystemInfo(&si);
uint64_t PageSize = si.dwPageSize;
+
+ // get dos drive names
+ GetDosNames(dosDrives);
+
+ ranges.clear();
+
// enumerate heaps
// HeapNodes(d->my_pid, heaps);
// go through all the VM regions, convert them to our internal format
@@ -254,52 +290,106 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
movingStart = ((uint64_t)MBI.BaseAddress + MBI.RegionSize);
if(movingStart % PageSize != 0)
movingStart = (movingStart / PageSize + 1) * PageSize;
- // skip empty regions and regions we share with other processes (DLLs)
- if( !(MBI.State & MEM_COMMIT) /*|| !(MBI.Type & MEM_PRIVATE)*/ )
+
+ // Skip unallocated address space
+ if (MBI.State & MEM_FREE)
continue;
+
+ // Find range and permissions
t_memrange temp;
+ memset(&temp, 0, sizeof(temp));
+
temp.start = (char *) MBI.BaseAddress;
temp.end = ((char *)MBI.BaseAddress + (uint64_t)MBI.RegionSize);
- temp.read = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READONLY || MBI.Protect & PAGE_READWRITE;
- temp.write = MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_READWRITE;
- temp.execute = MBI.Protect & PAGE_EXECUTE_READ || MBI.Protect & PAGE_EXECUTE_READWRITE || MBI.Protect & PAGE_EXECUTE;
- temp.valid = true;
- if(!GetModuleBaseName(d->my_handle, (HMODULE) temp.start, temp.name, 1024))
+ temp.valid = true;
+
+ if (!(MBI.State & MEM_COMMIT))
+ temp.valid = false; // reserved address space
+ else if (MBI.Protect & PAGE_EXECUTE)
+ temp.execute = true;
+ else if (MBI.Protect & PAGE_EXECUTE_READ)
+ temp.execute = temp.read = true;
+ else if (MBI.Protect & PAGE_EXECUTE_READWRITE)
+ temp.execute = temp.read = temp.write = true;
+ else if (MBI.Protect & PAGE_EXECUTE_WRITECOPY)
+ temp.execute = temp.read = temp.write = true;
+ else if (MBI.Protect & PAGE_READONLY)
+ temp.read = true;
+ else if (MBI.Protect & PAGE_READWRITE)
+ temp.read = temp.write = true;
+ else if (MBI.Protect & PAGE_WRITECOPY)
+ temp.read = temp.write = true;
+
+ // Merge areas with the same properties
+ if (!ranges.empty() && LastAllocationBase == MBI.AllocationBase)
{
- if(nameMap.count((char *)temp.start))
+ auto &last = ranges.back();
+
+ if (last.end == temp.start &&
+ last.valid == temp.valid && last.execute == temp.execute &&
+ last.read == temp.read && last.write == temp.write)
{
- // potential buffer overflow...
- strcpy(temp.name, nameMap[(char *)temp.start].c_str());
+ last.end = temp.end;
+ continue;
}
- else
+ }
+
+#if 1
+ // Find the mapped file name
+ if (GetMappedFileName(d->my_handle, temp.start, temp.name, 1024))
+ {
+ int vsize = strlen(temp.name);
+
+ // Translate NT name to DOS name
+ for (auto it = dosDrives.begin(); it != dosDrives.end(); ++it)
{
- // filter away shared segments without a name.
- if( !(MBI.Type & MEM_PRIVATE) )
+ int ksize = it->first.size();
+ if (strncmp(temp.name, it->first.data(), ksize) != 0)
continue;
- else
- temp.name[0]=0;
+
+ memcpy(temp.name, it->second.data(), it->second.size());
+ memmove(temp.name + it->second.size(), temp.name + ksize, vsize + 1 - ksize);
+ break;
}
}
else
+ temp.name[0] = 0;
+#else
+ // Find the executable name
+ char *base = (char*)MBI.AllocationBase;
+
+ if(nameMap.count(base))
+ {
+ strncpy(temp.name, nameMap[base].c_str(), 1023);
+ }
+ else if(GetModuleBaseName(d->my_handle, (HMODULE)base, temp.name, 1024))
{
+ std::string nm(temp.name);
+
+ nameMap[base] = nm;
+
// this is our executable! (could be generalized to pull segments from libs, but whatever)
- if(d->base == temp.start)
+ if(d->base == base)
{
for(int i = 0; i < d->pe_header.FileHeader.NumberOfSections; i++)
{
- char sectionName[9];
+ /*char sectionName[9];
memcpy(sectionName,d->sections[i].Name,8);
sectionName[8] = 0;
string nm;
nm.append(temp.name);
nm.append(" : ");
- nm.append(sectionName);
- nameMap[(char *)temp.start + d->sections[i].VirtualAddress] = nm;
+ nm.append(sectionName);*/
+ nameMap[base + d->sections[i].VirtualAddress] = nm;
}
}
- else
- continue;
}
+ else
+ temp.name[0] = 0;
+#endif
+
+ // Push the entry
+ LastAllocationBase = MBI.AllocationBase;
ranges.push_back(temp);
}
}
diff --git a/library/include/ColorText.h b/library/include/ColorText.h
index 105832ef..0cc286dc 100644
--- a/library/include/ColorText.h
+++ b/library/include/ColorText.h
@@ -111,6 +111,8 @@ namespace DFHack
void printerr(const char *format, ...);
void vprinterr(const char *format, va_list args);
+ /// Get color
+ color_value color() { return cur_color; }
/// Set color (ANSI color number)
void color(color_value c);
/// Reset color to default
diff --git a/library/include/Core.h b/library/include/Core.h
index e4d1080d..653298d8 100644
--- a/library/include/Core.h
+++ b/library/include/Core.h
@@ -83,10 +83,17 @@ namespace DFHack
// Better than tracking some weird variables all over the place.
class DFHACK_EXPORT Core
{
+#ifdef _DARWIN
+ friend int ::DFH_SDL_NumJoysticks(void);
+ friend void ::DFH_SDL_Quit(void);
+ friend int ::DFH_SDL_PollEvent(SDL::Event *);
+ friend int ::DFH_SDL_Init(uint32_t flags);
+#else
friend int ::SDL_NumJoysticks(void);
friend void ::SDL_Quit(void);
friend int ::SDL_PollEvent(SDL::Event *);
friend int ::SDL_Init(uint32_t flags);
+#endif
friend int ::wgetch(WINDOW * w);
friend int ::egg_init(void);
friend int ::egg_shutdown(void);
diff --git a/library/include/Hooks.h b/library/include/Hooks.h
index 418a5ce3..325af43e 100644
--- a/library/include/Hooks.h
+++ b/library/include/Hooks.h
@@ -44,6 +44,12 @@ namespace SDL
// these functions are here because they call into DFHack::Core and therefore need to
// be declared as friend functions/known
+#ifdef _DARWIN
+DFhackCExport int DFH_SDL_NumJoysticks(void);
+DFhackCExport void DFH_SDL_Quit(void);
+DFhackCExport int DFH_SDL_PollEvent(SDL::Event* event);
+DFhackCExport int DFH_SDL_Init(uint32_t flags);
+#endif
DFhackCExport int SDL_NumJoysticks(void);
DFhackCExport void SDL_Quit(void);
DFhackCExport int SDL_PollEvent(SDL::Event* event);
diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h
index b76df437..5da9fc92 100644
--- a/library/include/PluginManager.h
+++ b/library/include/PluginManager.h
@@ -209,6 +209,7 @@ namespace DFHack
command_result (*plugin_onupdate)(color_ostream &);
command_result (*plugin_onstatechange)(color_ostream &, state_change_event);
RPCService* (*plugin_rpcconnect)(color_ostream &);
+ command_result (*plugin_eval_ruby)(const char*);
};
class DFHACK_EXPORT PluginManager
{
@@ -237,6 +238,7 @@ namespace DFHack
{
return all_plugins.size();
}
+ command_result (*eval_ruby)(const char*);
// DATA
private:
tthread::mutex * cmdlist_mutex;
diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua
index 4cdb4c95..d56d4df6 100644
--- a/library/lua/dfhack.lua
+++ b/library/lua/dfhack.lua
@@ -49,6 +49,10 @@ function dfhack.pcall(f, ...)
return xpcall(f, dfhack.onerror, ...)
end
+function qerror(msg, level)
+ dfhack.error(msg, (level or 1) + 1, false)
+end
+
function dfhack.with_finalize(...)
return dfhack.call_with_finalizer(0,true,...)
end
@@ -64,6 +68,8 @@ function dfhack.with_temp_object(obj,fn,...)
return dfhack.call_with_finalizer(1,true,call_delete,obj,fn,obj,...)
end
+dfhack.exception.__index = dfhack.exception
+
-- Module loading
function mkmodule(module,env)
diff --git a/library/lua/memscan.lua b/library/lua/memscan.lua
index 95b9197b..970f821c 100644
--- a/library/lua/memscan.lua
+++ b/library/lua/memscan.lua
@@ -154,7 +154,8 @@ function MemoryArea.new(astart, aend)
int16_t = CheckedArray.new('int16_t',astart,aend),
uint16_t = CheckedArray.new('uint16_t',astart,aend),
int32_t = CheckedArray.new('int32_t',astart,aend),
- uint32_t = CheckedArray.new('uint32_t',astart,aend)
+ uint32_t = CheckedArray.new('uint32_t',astart,aend),
+ float = CheckedArray.new('float',astart,aend)
}
setmetatable(obj, MemoryArea)
return obj
@@ -168,7 +169,7 @@ function MemoryArea:__tostring()
return string.format('<MemoryArea: %x..%x>', self.start_addr, self.end_addr)
end
function MemoryArea:contains_range(start,size)
- return start >= self.start_addr and (start+size) <= self.end_addr
+ return size >= 0 and start >= self.start_addr and (start+size) <= self.end_addr
end
function MemoryArea:contains_obj(obj,count)
local size, base = df.sizeof(obj)
@@ -208,7 +209,8 @@ local function find_data_segment()
end
elseif mem.read and mem.write
and (string.match(mem.name,'/dwarfort%.exe$')
- or string.match(mem.name,'/Dwarf_Fortress$'))
+ or string.match(mem.name,'/Dwarf_Fortress$')
+ or string.match(mem.name,'Dwarf Fortress%.exe'))
then
data_start = mem.start_addr
data_end = mem.end_addr
@@ -233,7 +235,7 @@ function found_offset(name,val)
if not val then
print('Could not find offset '..name)
if not cval and not utils.prompt_yes_no('Continue with the script?') then
- error('User quit')
+ qerror('User quit')
end
return
end
@@ -250,6 +252,16 @@ function found_offset(name,val)
end
else
dfhack.internal.setAddress(name, val)
+
+ local ival = val - dfhack.internal.getRebaseDelta()
+ local entry = string.format("<global-address name='%s' value='0x%x'/>\n", name, ival)
+
+ local ccolor = dfhack.color(COLOR_LIGHTGREEN)
+ dfhack.print(entry)
+ dfhack.color(ccolor)
+
+ io.stdout:write(entry)
+ io.stdout:flush()
end
end
@@ -452,4 +464,30 @@ function DiffSearcher:find_counter(prompt,data_type,delta,action_prompt)
)
end
+-- Screen size
+
+function get_screen_size()
+ -- Use already known globals
+ if dfhack.internal.getAddress('init') then
+ local d = df.global.init.display
+ return d.grid_x, d.grid_y
+ end
+ if dfhack.internal.getAddress('gps') then
+ local g = df.global.gps
+ return g.dimx, g.dimy
+ end
+
+ -- Parse stdout.log for resize notifications
+ io.stdout:flush()
+
+ local w,h = 80,25
+ for line in io.lines('stdout.log') do
+ local cw, ch = string.match(line, '^Resizing grid to (%d+)x(%d+)$')
+ if cw and ch then
+ w, h = tonumber(cw), tonumber(ch)
+ end
+ end
+ return w,h
+end
+
return _ENV
diff --git a/library/lua/utils.lua b/library/lua/utils.lua
index 93ee840c..f303091d 100644
--- a/library/lua/utils.lua
+++ b/library/lua/utils.lua
@@ -379,7 +379,7 @@ function prompt_yes_no(msg,default)
elseif string.match(rv,'^[Nn]') then
return false
elseif rv == 'abort' then
- error('User abort in utils.prompt_yes_no()')
+ qerror('User abort in utils.prompt_yes_no()')
elseif rv == '' and default ~= nil then
return default
end