summaryrefslogtreecommitdiff
path: root/library/Core.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/Core.cpp')
-rw-r--r--library/Core.cpp193
1 files changed, 153 insertions, 40 deletions
diff --git a/library/Core.cpp b/library/Core.cpp
index 826576b7..8a8d39e0 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -126,8 +126,34 @@ struct Core::Private
void Core::cheap_tokenise(string const& input, vector<string> &output)
{
string *cur = NULL;
+ size_t i = 0;
- for (size_t i = 0; i < input.size(); i++) {
+ // Check the first non-space character
+ while (i < input.size() && isspace(input[i])) i++;
+
+ // Special verbatim argument mode?
+ if (i < input.size() && input[i] == ':')
+ {
+ // Read the command
+ std::string cmd;
+ i++;
+ while (i < input.size() && !isspace(input[i]))
+ cmd.push_back(input[i++]);
+ if (!cmd.empty())
+ output.push_back(cmd);
+
+ // Find the argument
+ while (i < input.size() && isspace(input[i])) i++;
+
+ if (i < input.size())
+ output.push_back(input.substr(i));
+
+ return;
+ }
+
+ // Otherwise, parse in the regular quoted mode
+ for (; i < input.size(); i++)
+ {
unsigned char c = input[i];
if (isspace(c)) {
cur = NULL;
@@ -219,28 +245,30 @@ static std::string getScriptHelp(std::string path, std::string helpprefix)
return "No help available.";
}
-static std::map<string,string> listScripts(PluginManager *plug_mgr, std::string path)
+static void listScripts(PluginManager *plug_mgr, std::map<string,string> &pset, std::string path, bool all, std::string prefix = "")
{
std::vector<string> files;
getdir(path, files);
- std::map<string,string> pset;
for (size_t i = 0; i < files.size(); i++)
{
if (hasEnding(files[i], ".lua"))
{
std::string help = getScriptHelp(path + files[i], "-- ");
- pset[files[i].substr(0, files[i].size()-4)] = help;
+ pset[prefix + 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;
+ pset[prefix + files[i].substr(0, files[i].size()-3)] = help;
+ }
+ else if (all && !files[i].empty() && files[i][0] != '.')
+ {
+ listScripts(plug_mgr, pset, path+files[i]+"/", all, prefix+files[i]+"/");
}
}
- return pset;
}
static bool fileExists(std::string path)
@@ -335,7 +363,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
con.print("Basic commands:\n"
" help|?|man - This text.\n"
" help COMMAND - Usage help for the given command.\n"
- " ls|dir [PLUGIN] - List available commands. Optionally for single plugin.\n"
+ " ls|dir [-a] [PLUGIN] - List available commands. Optionally for single plugin.\n"
" cls - Clear the console.\n"
" fpause - Force DF to pause.\n"
" die - Force DF to close immediately\n"
@@ -358,7 +386,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
continue;
if (pcmd.isHotkeyCommand())
- con.color(Console::COLOR_CYAN);
+ con.color(COLOR_CYAN);
con.print("%s: %s\n",pcmd.name.c_str(), pcmd.description.c_str());
con.reset_color();
if (!pcmd.usage.empty())
@@ -469,6 +497,12 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
}
else if(first == "ls" || first == "dir")
{
+ bool all = false;
+ if (parts.size() && parts[0] == "-a")
+ {
+ all = true;
+ vector_erase_at(parts, 0);
+ }
if(parts.size())
{
string & plugname = parts[0];
@@ -481,7 +515,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
{
const PluginCommand & pcmd = (plug->operator[](j));
if (pcmd.isHotkeyCommand())
- con.color(Console::COLOR_CYAN);
+ con.color(COLOR_CYAN);
con.print(" %-22s - %s\n",pcmd.name.c_str(), pcmd.description.c_str());
con.reset_color();
}
@@ -491,7 +525,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
con.print(
"builtin:\n"
" help|?|man - This text or help specific to a plugin.\n"
- " ls [PLUGIN] - List available commands. Optionally for single plugin.\n"
+ " ls [-a] [PLUGIN] - List available commands. Optionally for single plugin.\n"
" cls - Clear the console.\n"
" fpause - Force DF to pause.\n"
" die - Force DF to close immediately\n"
@@ -519,11 +553,12 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
for(auto iter = out.begin();iter != out.end();iter++)
{
if ((*iter).recolor)
- con.color(Console::COLOR_CYAN);
+ con.color(COLOR_CYAN);
con.print(" %-22s- %s\n",(*iter).name.c_str(), (*iter).description.c_str());
con.reset_color();
}
- auto scripts = listScripts(plug_mgr, getHackPath() + "scripts/");
+ std::map<string, string> scripts;
+ listScripts(plug_mgr, scripts, getHackPath() + "scripts/", all);
if (!scripts.empty())
{
con.print("\nscripts:\n");
@@ -1027,35 +1062,41 @@ int Core::TileUpdate()
return true;
}
-// should always be from simulation thread!
-int Core::Update()
+int Core::ClaimSuspend(bool force_base)
{
- if(errorstate)
- return -1;
+ auto tid = this_thread::get_id();
+ lock_guard<mutex> lock(d->AccessMutex);
- // Pretend this thread has suspended the core in the usual way
+ if (force_base || d->df_suspend_depth <= 0)
{
- lock_guard<mutex> lock(d->AccessMutex);
-
assert(d->df_suspend_depth == 0);
- d->df_suspend_thread = this_thread::get_id();
- d->df_suspend_depth = 1000;
- }
- // Initialize the core
- bool first_update = false;
-
- if(!started)
+ d->df_suspend_thread = tid;
+ d->df_suspend_depth = 1000000;
+ return 1000000;
+ }
+ else
{
- first_update = true;
- Init();
- if(errorstate)
- return -1;
- Lua::Core::Reset(con, "core init");
+ assert(d->df_suspend_thread == tid);
+ return ++d->df_suspend_depth;
}
+}
- color_ostream_proxy out(con);
+void Core::DisclaimSuspend(int level)
+{
+ auto tid = this_thread::get_id();
+ lock_guard<mutex> lock(d->AccessMutex);
+ assert(d->df_suspend_depth == level && d->df_suspend_thread == tid);
+
+ if (level == 1000000)
+ d->df_suspend_depth = 0;
+ else
+ --d->df_suspend_depth;
+}
+
+void Core::doUpdate(color_ostream &out, bool first_update)
+{
Lua::Core::Reset(out, "DF code execution");
if (first_update)
@@ -1129,15 +1170,36 @@ int Core::Update()
// Execute per-frame handlers
onUpdate(out);
- // Release the fake suspend lock
+ out << std::flush;
+}
+
+// should always be from simulation thread!
+int Core::Update()
+{
+ if(errorstate)
+ return -1;
+
+ color_ostream_proxy out(con);
+
+ // Pretend this thread has suspended the core in the usual way,
+ // and run various processing hooks.
{
- lock_guard<mutex> lock(d->AccessMutex);
+ CoreSuspendClaimer suspend(true);
- assert(d->df_suspend_depth == 1000);
- d->df_suspend_depth = 0;
- }
+ // Initialize the core
+ bool first_update = false;
- out << std::flush;
+ if(!started)
+ {
+ first_update = true;
+ Init();
+ if(errorstate)
+ return -1;
+ Lua::Core::Reset(con, "core init");
+ }
+
+ doUpdate(out, first_update);
+ }
// wake waiting tools
// do not allow more tools to join in while we process stuff here
@@ -1158,7 +1220,7 @@ int Core::Update()
// destroy condition
delete nc;
// check lua stack depth
- Lua::Core::Reset(con, "suspend");
+ Lua::Core::Reset(out, "suspend");
}
return 0;
@@ -1198,6 +1260,7 @@ int Core::Shutdown ( void )
if(errorstate)
return true;
errorstate = 1;
+ CoreSuspendClaimer suspend;
if(plug_mgr)
{
delete plug_mgr;
@@ -1232,7 +1295,7 @@ bool Core::ncurses_wgetch(int in, int & out)
// FIXME: copypasta, push into a method!
if(df::global::ui && df::global::gview)
{
- df::viewscreen * ws = Gui::GetCurrentScreen();
+ df::viewscreen * ws = Gui::getCurViewscreen();
if (strict_virtual_cast<df::viewscreen_dwarfmodest>(ws) &&
df::global::ui->main.mode != ui_sidebar_mode::Hotkeys &&
df::global::ui->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
@@ -1548,6 +1611,56 @@ void ClassNameCheck::getKnownClassNames(std::vector<std::string> &names)
names.push_back(*it);
}
+bool Process::patchMemory(void *target, const void* src, size_t count)
+{
+ uint8_t *sptr = (uint8_t*)target;
+ uint8_t *eptr = sptr + count;
+
+ // Find the valid memory ranges
+ std::vector<t_memrange> ranges;
+ getMemRanges(ranges);
+
+ unsigned start = 0;
+ while (start < ranges.size() && ranges[start].end <= sptr)
+ start++;
+ if (start >= ranges.size() || ranges[start].start > sptr)
+ return false;
+
+ unsigned end = start+1;
+ while (end < ranges.size() && ranges[end].start < eptr)
+ {
+ if (ranges[end].start != ranges[end-1].end)
+ return false;
+ end++;
+ }
+ if (ranges[end-1].end < eptr)
+ return false;
+
+ // Verify current permissions
+ for (unsigned i = start; i < end; i++)
+ if (!ranges[i].valid || !(ranges[i].read || ranges[i].execute) || ranges[i].shared)
+ return false;
+
+ // Apply writable permissions & update
+ bool ok = true;
+
+ for (unsigned i = start; i < end && ok; i++)
+ {
+ t_memrange perms = ranges[i];
+ perms.write = perms.read = true;
+ if (!setPermisions(perms, perms))
+ ok = false;
+ }
+
+ if (ok)
+ memmove(target, src, count);
+
+ for (unsigned i = start; i < end && ok; i++)
+ setPermisions(ranges[i], ranges[i]);
+
+ return ok;
+}
+
/*******************************************************************************
M O D U L E S
*******************************************************************************/