implement [lua]name=, fixes #3381

This commit is contained in:
gfgtdf 2018-08-10 17:21:44 +02:00
parent 50d94b3388
commit eba882b957
6 changed files with 20 additions and 19 deletions

View file

@ -267,7 +267,8 @@ end
function wml_actions.lua(cfg)
cfg = wml.shallow_literal(cfg)
local bytecode, message = load(cfg.code or "")
--fixme untested
local bytecode, message = load(cfg.code or "", cfg.name or "")
if not bytecode then error("~lua:" .. message, 0) end
bytecode(wml.get_child(cfg, "args"))
end

View file

@ -394,7 +394,7 @@ bool game_launcher::init_lua_script()
std::cerr << "\nRunning lua script: " << *cmdline_opts_.script_file << std::endl;
plugins_manager::get()->get_kernel_base()->run(full_script.c_str());
plugins_manager::get()->get_kernel_base()->run(full_script.c_str(), *cmdline_opts_.script_file);
} else {
std::cerr << "Encountered failure when opening script '" << *cmdline_opts_.script_file << "'\n";
error = true;

View file

@ -670,10 +670,10 @@ bool lua_kernel_base::protected_call(int nArgs, int nRets)
return this->protected_call(nArgs, nRets, eh);
}
bool lua_kernel_base::load_string(char const * prog)
bool lua_kernel_base::load_string(char const * prog, const std::string& name)
{
error_handler eh = std::bind(&lua_kernel_base::log_error, this, _1, _2 );
return this->load_string(prog, eh);
return this->load_string(prog, name, eh);
}
bool lua_kernel_base::protected_call(int nArgs, int nRets, error_handler e_h)
@ -716,11 +716,11 @@ bool lua_kernel_base::protected_call(lua_State * L, int nArgs, int nRets, error_
return true;
}
bool lua_kernel_base::load_string(char const * prog, error_handler e_h)
bool lua_kernel_base::load_string(char const * prog, const std::string& name, error_handler e_h)
{
// pass 't' to prevent loading bytecode which is unsafe and can be used to escape the sandbox.
// todo: maybe allow a 'name' parameter to give better error messages.
int errcode = luaL_loadbufferx(mState, prog, strlen(prog), /*name*/ prog, "t");
int errcode = luaL_loadbufferx(mState, prog, strlen(prog), name.empty() ? name.c_str() : prog, "t");
if (errcode != LUA_OK) {
char const * msg = lua_tostring(mState, -1);
std::string message = msg ? msg : "null string";
@ -753,24 +753,24 @@ void lua_kernel_base::run_lua_tag(const config& cfg)
luaW_pushconfig(this->mState, args);
++nArgs;
}
this->run(cfg["code"].str().c_str(), nArgs);
this->run(cfg["code"].str().c_str(), cfg["name"].str(), nArgs);
}
// Call load_string and protected call. Make them throw exceptions.
//
void lua_kernel_base::throwing_run(const char * prog, int nArgs)
void lua_kernel_base::throwing_run(const char * prog, const std::string& name, int nArgs)
{
cmd_log_ << "$ " << prog << "\n";
error_handler eh = std::bind(&lua_kernel_base::throw_exception, this, _1, _2 );
this->load_string(prog, eh);
this->load_string(prog, name, eh);
lua_insert(mState, -nArgs - 1);
this->protected_call(nArgs, 0, eh);
}
// Do a throwing run, but if we catch a lua_error, reformat it with signature for this function and log it.
void lua_kernel_base::run(const char * prog, int nArgs)
void lua_kernel_base::run(const char * prog, const std::string& name, int nArgs)
{
try {
this->throwing_run(prog, nArgs);
this->throwing_run(prog, name, nArgs);
} catch (const game::lua_error & e) {
cmd_log_ << e.what() << "\n";
lua_kernel_base::log_error(e.what(), "In function lua_kernel::run()");
@ -787,9 +787,9 @@ void lua_kernel_base::interactive_run(char const * prog) {
try {
// Try to load the experiment without syntax errors
this->load_string(experiment.c_str(), eh);
this->load_string(experiment.c_str(), "interactive", eh);
} catch (const game::lua_error &) {
this->throwing_run(prog, 0); // Since it failed, fall back to the usual throwing_run, on the original input.
this->throwing_run(prog, "interactive", 0); // Since it failed, fall back to the usual throwing_run, on the original input.
return;
}
// experiment succeeded, now run but log normally.

View file

@ -32,10 +32,10 @@ public:
void run_lua_tag(const config& cfg);
/** Runs a plain script. Doesn't throw lua_error.*/
void run(char const *prog, int nArgs = 0);
void run(char const *prog, const std::string& name, int nArgs = 0);
/** Runs a plain script, but reports errors by throwing lua_error.*/
void throwing_run(char const * prog, int nArgs);
void throwing_run(char const * prog, const std::string& name, int nArgs);
/** Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it normally. Throws exceptions.*/
void interactive_run(char const * prog);
@ -122,10 +122,10 @@ protected:
// Execute a protected call, taking a lua_State as argument. For functions pushed into the lua environment, this version should be used, or the function cannot be used by coroutines without segfaulting (since they have a different lua_State pointer). This version is called by the above version.
static bool protected_call(lua_State * L, int nArgs, int nRets, error_handler);
// Load a string onto the stack as a function. Returns true if successful, error handler is called if not.
bool load_string(char const * prog, error_handler);
bool load_string(char const * prog, const std::string& name, error_handler);
virtual bool protected_call(int nArgs, int nRets); // select default error handler polymorphically
virtual bool load_string(char const * prog); // select default error handler polymorphically
virtual bool load_string(char const * prog, const std::string& name); // select default error handler polymorphically
// dofile (using lua_fileops)
int intf_dofile(lua_State * L);

View file

@ -234,7 +234,7 @@ mapgen_lua_kernel::mapgen_lua_kernel()
void mapgen_lua_kernel::run_generator(const char * prog, const config & generator)
{
load_string(prog, std::bind(&lua_kernel_base::throw_exception, this, _1, _2));
load_string(prog, "", std::bind(&lua_kernel_base::throw_exception, this, _1, _2));
luaW_pushconfig(mState, generator);
protected_call(1, 1, std::bind(&lua_kernel_base::throw_exception, this, _1, _2));
}

View file

@ -556,7 +556,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_lua, child, use_undo, /*show*/, /*error_ha
resources::undo_stack->clear();
}
debug_cmd_notification("lua");
resources::lua_kernel->run(child["code"].str().c_str());
resources::lua_kernel->run(child["code"].str().c_str(), "debug command");
resources::controller->pump().flush_messages();
return true;