The Battle for Wesnoth  1.15.12+dev
lua_kernel_base.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by Chris Beck <render787@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 
17 #include "game_config.hpp"
18 #include "game_errors.hpp"
19 #include "gui/core/gui_definition.hpp" // for remove_single_widget_definition
20 #include "log.hpp"
21 #include "lua_jailbreak_exception.hpp" // for lua_jailbreak_exception
22 #include "random.hpp"
23 #include "seed_rng.hpp"
24 #include "deprecation.hpp"
25 #include "language.hpp" // for get_language
26 
27 #ifdef DEBUG_LUA
28 #include "scripting/debug_lua.hpp"
29 #endif
30 
31 #include "scripting/lua_color.hpp"
32 #include "scripting/lua_common.hpp"
36 #include "scripting/lua_gui2.hpp"
37 #include "scripting/lua_wml.hpp"
40 #include "scripting/lua_rng.hpp"
41 #include "scripting/lua_widget.hpp"
42 #include "scripting/push_check.hpp"
43 
44 #include "game_version.hpp" // for do_version_check, etc
45 #include "picture.hpp"
46 
47 #include <functional>
48 #include "utils/name_generator.hpp"
51 
52 #include <cstring>
53 #include <exception>
54 #include <new>
55 #include <string>
56 #include <sstream>
57 #include <vector>
58 
59 #include "lua/lauxlib.h"
60 #include "lua/lua.h"
61 #include "lua/lualib.h"
62 
63 static lg::log_domain log_scripting_lua("scripting/lua");
64 static lg::log_domain log_user("scripting/lua/user");
65 #define DBG_LUA LOG_STREAM(debug, log_scripting_lua)
66 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
67 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
68 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
69 
70 // Registry key for metatable
71 static const char * Gen = "name generator";
72 // Registry key for lua interpreter environment
73 static const char * Interp = "lua interpreter";
74 
75 // Callback implementations
76 
77 /**
78  * Compares 2 version strings - which is newer.
79  * - Args 1,3: version strings
80  * - Arg 2: comparison operator (string)
81  * - Ret 1: comparison result
82  */
84 {
85  char const *v1 = luaL_checkstring(L, 1);
86 
88  if(vop == OP_INVALID) return luaL_argerror(L, 2, "unknown version comparison operator - allowed are ==, !=, <, <=, > and >=");
89 
90  char const *v2 = luaL_checkstring(L, 3);
91 
92  const bool result = do_version_check(version_info(v1), vop, version_info(v2));
93  lua_pushboolean(L, result);
94 
95  return 1;
96 }
97 
98 /**
99  * Replacement print function -- instead of printing to std::cout, print to the command log.
100  * Intended to be bound to this' command_log at registration time.
101  */
103 {
104  DBG_LUA << "intf_print called:\n";
105  std::size_t nargs = lua_gettop(L);
106 
107  lua_getglobal(L, "tostring");
108  for (std::size_t i = 1; i <= nargs; ++i) {
109  lua_pushvalue(L, -1); // function to call: "tostring"
110  lua_pushvalue(L, i); // value to pass through tostring() before printing
111  lua_call(L, 1, 1);
112  const char * str = lua_tostring(L, -1);
113  if (!str) {
114  LOG_LUA << "'tostring' must return a value to 'print'\n";
115  str = "";
116  }
117  if (i > 1) {
118  cmd_log_ << "\t"; //separate multiple args with tab character
119  }
120  cmd_log_ << str;
121  DBG_LUA << "'" << str << "'\n";
122  lua_pop(L, 1); // Pop the output of tostrring()
123  }
124  lua_pop(L, 1); // Pop 'tostring' global
125 
126  cmd_log_ << "\n";
127  DBG_LUA << "\n";
128 
129  return 0;
130 }
131 
132 static void impl_warn(void* p, const char* msg, int tocont) {
133  static const char*const prefix = "Warning:\n ";
134  static std::ostringstream warning(prefix);
135  warning.seekp(0, std::ios::end);
136  warning << msg << ' ';
137  if(!tocont) {
138  auto L = reinterpret_cast<lua_State*>(p);
139  luaW_getglobal(L, "debug", "traceback");
140  lua_push(L, warning.str());
141  lua_pushinteger(L, 2);
142  lua_call(L, 2, 1);
143  auto& lk = lua_kernel_base::get_lua_kernel<lua_kernel_base>(L);
144  lk.add_log_to_console(luaL_checkstring(L, -1));
145  warning.str(prefix);
146  }
147 }
148 
149 void lua_kernel_base::add_log_to_console(const std::string& msg) {
150  cmd_log_ << msg << "\n";
151  DBG_LUA << "'" << msg << "'\n";
152 }
153 
154 /**
155  * Replacement load function. Mostly the same as regular load, but disallows loading binary chunks
156  * due to CVE-2018-1999023.
157  */
158 static int intf_load(lua_State* L)
159 {
160  std::string chunk = luaL_checkstring(L, 1);
161  const char* name = luaL_optstring(L, 2, chunk.c_str());
162  std::string mode = luaL_optstring(L, 3, "t");
163  bool override_env = !lua_isnone(L, 4);
164 
165  if(mode != "t") {
166  return luaL_argerror(L, 3, "binary chunks are not allowed for security reasons");
167  }
168 
169  int result = luaL_loadbufferx(L, chunk.data(), chunk.length(), name, "t");
170  if(result != LUA_OK) {
171  lua_pushnil(L);
172  // Move the nil as the first return value, like Lua's own load() does.
173  lua_insert(L, -2);
174 
175  return 2;
176  }
177 
178  if(override_env) {
179  // Copy "env" to the top of the stack.
180  lua_pushvalue(L, 4);
181  // Set "env" as the first upvalue.
182  const char* upvalue_name = lua_setupvalue(L, -2, 1);
183  if(upvalue_name == nullptr) {
184  // lua_setupvalue() didn't remove the copy of "env" from the stack, so we need to do it ourselves.
185  lua_pop(L, 1);
186  }
187  }
188 
189  return 1;
190 }
191 
192 // The show lua console callback is similarly a method of lua kernel
194 {
195  if (cmd_log_.external_log_) {
196  std::string message = "There is already an external logger attached to this lua kernel, you cannot open the lua console right now.";
197  log_error(message.c_str());
198  cmd_log_ << message << "\n";
199  return 0;
200  }
201 
202  return lua_gui2::show_lua_console(L, this);
203 }
204 
206 {
207  name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
208  lua_pushstring(L, gen->generate().c_str());
209  return 1;
210 }
211 
213 {
214  name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
215  gen->~name_generator();
216  return 0;
217 }
218 
220 {
221  std::string type = luaL_checkstring(L, 1);
222  name_generator* gen = nullptr;
223  try {
224  if(type == "markov" || type == "markov_chain") {
225  std::vector<std::string> input;
226  if(lua_istable(L, 2)) {
227  input = lua_check<std::vector<std::string>>(L, 2);
228  } else {
229  input = utils::parenthetical_split(luaW_checktstring(L, 2), ',');
230  }
231  int chain_sz = luaL_optinteger(L, 3, 2);
232  int max_len = luaL_optinteger(L, 4, 12);
233  gen = new(L) markov_generator(input, chain_sz, max_len);
234  // Ensure the pointer didn't change when cast
235  assert(static_cast<void*>(gen) == dynamic_cast<markov_generator*>(gen));
236  } else if(type == "context_free" || type == "cfg" || type == "CFG") {
237  if(lua_istable(L, 2)) {
238  std::map<std::string, std::vector<std::string>> data;
239  for(lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
240  if(lua_type(L, -2) != LUA_TSTRING) {
241  lua_pushstring(L, "CFG generator: invalid nonterminal name (must be a string)");
242  return lua_error(L);
243  }
244  if(lua_isstring(L, -1)) {
245  auto& productions = data[lua_tostring(L,-2)] = utils::split(luaW_checktstring(L,-1).str(), '|');
246  if(productions.size() > 1) {
247  deprecated_message("wesnoth.name_generator('cfg', {nonterminal = 'a|b'})", DEP_LEVEL::INDEFINITE, "1.17", "Non-terminals should now be assigned an array of productions instead of a single string containing productions separated by | - but a single string is fine if it's only one production");
248  }
249  } else if(lua_istable(L, -1)) {
250  const auto& split = lua_check<std::vector<t_string>>(L, -1);
251  auto& productions = data[lua_tostring(L,-2)];
252  std::transform(split.begin(), split.end(), std::back_inserter(productions), std::mem_fn(&t_string::str));
253  } else {
254  lua_pushstring(L, "CFG generator: invalid nonterminal value (must be a string or list of strings)");
255  return lua_error(L);
256  }
257  }
258  if(!data.empty()) {
259  gen = new(L) context_free_grammar_generator(data);
260  }
261  } else {
263  }
264  if(gen) {
265  assert(static_cast<void*>(gen) == dynamic_cast<context_free_grammar_generator*>(gen));
266  }
267  } else {
268  return luaL_argerror(L, 1, "should be either 'markov_chain' or 'context_free'");
269  }
270  }
271  catch (const name_generator_invalid_exception& ex) {
272  lua_pushstring(L, ex.what());
273  return lua_error(L);
274  }
275 
276  // We set the metatable now, even if the generator is invalid, so that it
277  // will be properly collected if it was invalid.
279  lua_setmetatable(L, -2);
280 
281  return 1;
282 }
283 
284 /**
285 * Returns a random numer, same interface as math.random.
286 */
287 static int intf_random(lua_State *L)
288 {
289  if (lua_isnoneornil(L, 1)) {
290  double r = static_cast<double>(randomness::generator->next_random());
291  double r_max = static_cast<double>(std::numeric_limits<uint32_t>::max());
292  lua_push(L, r / (r_max + 1));
293  return 1;
294  }
295  else {
296  int32_t min;
297  int32_t max;
298  if (lua_isnumber(L, 2)) {
299  min = lua_check<int32_t>(L, 1);
300  max = lua_check<int32_t>(L, 2);
301  }
302  else {
303  min = 1;
304  max = lua_check<int32_t>(L, 1);
305  }
306  if (min > max) {
307  return luaL_argerror(L, 1, "min > max");
308  }
309  lua_push(L, randomness::generator->get_random_int(min, max));
310  return 1;
311  }
312 }
313 
314 /**
315 * Logs a message
316 * Arg 1: (optional) Logger
317 * Arg 2: Message
318 */
319 static int intf_log(lua_State *L) {
320  const std::string& logger = lua_isstring(L, 2) ? luaL_checkstring(L, 1) : "";
321  std::string msg = lua_isstring(L, 2) ? luaL_checkstring(L, 2) : luaL_checkstring(L, 1);
322  if(msg.empty() || msg.back() != '\n') {
323  msg += '\n';
324  }
325 
326  if(logger == "err" || logger == "error") {
327  LOG_STREAM(err, log_user) << msg;
328  } else if(logger == "warn" || logger == "wrn" || logger == "warning") {
330  } else if((logger == "debug" || logger == "dbg")) {
332  } else {
334  }
335  return 0;
336 }
337 
338 /**
339  * Logs a deprecation message. See deprecation.cpp for details
340  * Arg 1: Element to be deprecated.
341  * Arg 2: Deprecation level.
342  * Arg 3: Version when element may be removed.
343  * Arg 4: Additional detail message.
344  */
346  const std::string elem = luaL_checkstring(L, 1);
347  // This could produce an invalid deprecation level, but that possibility is handled in deprecated_message()
349  const std::string ver_str = lua_isnoneornil(L, 3) ? "" : luaL_checkstring(L, 3);
350  const std::string detail = luaW_checktstring(L, 4);
351  const version_info ver = ver_str.empty() ? game_config::wesnoth_version.str() : ver_str;
352  const std::string msg = deprecated_message(elem, level, ver, detail);
353  if(level < DEP_LEVEL::INDEFINITE || level >= DEP_LEVEL::REMOVED) {
354  // Invalid deprecation level or level 4 deprecation should raise an interpreter error
355  lua_push(L, msg);
356  return lua_error(L);
357  }
358  lua_warning(L, msg.c_str(), false);
359  return 0;
360 }
361 
362 /**
363 * Gets the dimension of an image.
364 * - Arg 1: string.
365 * - Ret 1: width.
366 * - Ret 2: height.
367 */
369  char const *m = luaL_checkstring(L, 1);
370  image::locator img(m);
371  if(!img.file_exists()) return 0;
372  surface s = get_image(img);
373  lua_pushinteger(L, s->w);
374  lua_pushinteger(L, s->h);
375  return 2;
376 }
377 
378 /**
379 * Returns the time stamp, exactly as [set_variable] time=stamp does.
380 * - Ret 1: integer
381 */
383  lua_pushinteger(L, SDL_GetTicks());
384  return 1;
385 }
386 
388 {
389  lua_push(L, get_language().localename);
390  return 1;
391 }
392 
393 // End Callback implementations
394 
395 // Template which allows to push member functions to the lua kernel base into lua as C functions, using a shim
397 
398 template <member_callback method>
400  return ((lua_kernel_base::get_lua_kernel<lua_kernel_base>(L)).*method)(L);
401 }
402 
403 // Ctor, initialization
405  : mState(luaL_newstate())
406  , cmd_log_()
407 {
409  lua_State *L = mState;
410 
411  cmd_log_ << "Initializing " << my_name() << "...\n";
412 
413  // Define the CPP_function metatable ( so we can override print to point to a C++ member function, add certain functions for this kernel, etc. )
414  // Do it first of all in case C++ functions are ever used in the core Wesnoth libs loaded in the next step
415  cmd_log_ << "Adding boost function proxy...\n";
416 
418 
419  // Open safe libraries.
420  // Debug and OS are not, but most of their functions will be disabled below.
421  cmd_log_ << "Adding standard libs...\n";
422 
423  static const luaL_Reg safe_libs[] {
424  { "", luaopen_base },
425  { "table", luaopen_table },
426  { "string", luaopen_string },
427  { "math", luaopen_math },
428  { "coroutine", luaopen_coroutine },
429  { "debug", luaopen_debug },
430  { "os", luaopen_os },
431  { "utf8", luaopen_utf8 }, // added in Lua 5.3
432  // Wesnoth libraries
433  { "stringx",lua_stringx::luaW_open },
434  { "wml", lua_wml::luaW_open },
435  { "gui", lua_gui2::luaW_open },
436  { nullptr, nullptr }
437  };
438  for (luaL_Reg const *lib = safe_libs; lib->func; ++lib)
439  {
440  luaL_requiref(L, lib->name, lib->func, true);
441  lua_pop(L, 1); /* remove lib */
442  }
443 
444  // Disable functions from os which we don't want.
445  lua_getglobal(L, "os");
446  lua_pushnil(L);
447  while(lua_next(L, -2) != 0) {
448  lua_pop(L, 1);
449  char const* function = lua_tostring(L, -1);
450  if(strcmp(function, "clock") == 0 || strcmp(function, "date") == 0
451  || strcmp(function, "time") == 0 || strcmp(function, "difftime") == 0) continue;
452  lua_pushnil(L);
453  lua_setfield(L, -3, function);
454  }
455  lua_pop(L, 1);
456 
457  // Delete dofile and loadfile.
458  lua_pushnil(L);
459  lua_setglobal(L, "dofile");
460  lua_pushnil(L);
461  lua_setglobal(L, "loadfile");
462 
463  // Store the error handler.
464  cmd_log_ << "Adding error handler...\n";
466 
467 
468  lua_settop(L, 0);
469 
470  // Add some callback from the wesnoth lib
471  cmd_log_ << "Registering basic wesnoth API...\n";
472 
473  static luaL_Reg const callbacks[] {
474  { "compare_versions", &intf_compare_versions },
475  { "deprecated_message", &intf_deprecated_message },
476  { "have_file", &lua_fileops::intf_have_file },
477  { "read_file", &lua_fileops::intf_read_file },
478  { "canonical_path", &lua_fileops::intf_canonical_path },
479  { "textdomain", &lua_common::intf_textdomain },
480  { "dofile", &dispatch<&lua_kernel_base::intf_dofile> },
481  { "require", &dispatch<&lua_kernel_base::intf_require> },
482  { "kernel_type", &dispatch<&lua_kernel_base::intf_kernel_type> },
483  { "compile_formula", &lua_formula_bridge::intf_compile_formula},
484  { "eval_formula", &lua_formula_bridge::intf_eval_formula},
485  { "name_generator", &intf_name_generator },
486  { "random", &intf_random },
487  { "log", &intf_log },
488  { "get_image_size", &intf_get_image_size },
489  { "get_time_stamp", &intf_get_time_stamp },
490  { "get_language", &intf_get_language },
491  { nullptr, nullptr }
492  };
493 
494  lua_getglobal(L, "wesnoth");
495  if (!lua_istable(L,-1)) {
496  lua_newtable(L);
497  }
498  luaL_setfuncs(L, callbacks, 0);
499  //lua_cpp::set_functions(L, cpp_callbacks, 0);
500  lua_setglobal(L, "wesnoth");
501 
502  // Create the gettext metatable.
504  // Create the tstring metatable.
506 
508 
509  // Override the print function
510  cmd_log_ << "Redirecting print function...\n";
511 
512  lua_getglobal(L, "print");
513  lua_setglobal(L, "std_print"); //storing original impl as 'std_print'
514  lua_settop(L, 0); //clear stack, just to be sure
515 
516  lua_setwarnf(L, &::impl_warn, L);
517  lua_pushcfunction(L, &dispatch<&lua_kernel_base::intf_print>);
518  lua_setglobal(L, "print");
519 
521  lua_setglobal(L, "load");
522  lua_pushnil(L);
523  lua_setglobal(L, "loadstring");
524 
525  cmd_log_ << "Initializing package repository...\n";
526  // Create the package table.
527  lua_getglobal(L, "wesnoth");
528  lua_newtable(L);
529  lua_setfield(L, -2, "package");
530  lua_pop(L, 1);
531  lua_settop(L, 0);
532  lua_pushstring(L, "lua/package.lua");
533  int res = intf_require(L);
534  if(res != 1) {
535  cmd_log_ << "Error: Failed to initialize package repository. Falling back to less flexible C++ implementation.\n";
536  }
537 
538  // Get some callbacks for map locations
539  cmd_log_ << "Adding map table...\n";
540 
541  static luaL_Reg const map_callbacks[] {
542  { "get_direction", &lua_map_location::intf_get_direction },
543  { "vector_sum", &lua_map_location::intf_vector_sum },
544  { "vector_diff", &lua_map_location::intf_vector_diff },
545  { "vector_negation", &lua_map_location::intf_vector_negation },
546  { "rotate_right_around_center", &lua_map_location::intf_rotate_right_around_center },
547  { "are_hexes_adjacent", &lua_map_location::intf_tiles_adjacent },
548  { "get_adjacent_hexes", &lua_map_location::intf_get_adjacent_tiles },
549  { "get_hexes_in_radius", &lua_map_location::intf_get_tiles_in_radius },
550  { "distance_between", &lua_map_location::intf_distance_between },
551  { "get_in_basis_N_NE", &lua_map_location::intf_get_in_basis_N_NE },
552  { "get_relative_dir", &lua_map_location::intf_get_relative_dir },
553  { nullptr, nullptr }
554  };
555 
556  // Create the map_location table.
557  lua_getglobal(L, "wesnoth");
558  lua_newtable(L);
559  luaL_setfuncs(L, map_callbacks, 0);
560  lua_setfield(L, -2, "map");
561  lua_pop(L, 1);
562 
563  // Create the game_config variable with its metatable.
564  cmd_log_ << "Adding game_config table...\n";
565 
566  lua_getglobal(L, "wesnoth");
567  lua_newuserdatauv(L, 0, 0);
568  lua_createtable(L, 0, 3);
569  lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_get>);
570  lua_setfield(L, -2, "__index");
571  lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_set>);
572  lua_setfield(L, -2, "__newindex");
573  lua_pushstring(L, "game config");
574  lua_setfield(L, -2, "__metatable");
575  lua_setmetatable(L, -2);
576  lua_setfield(L, -2, "game_config");
577  lua_pop(L, 1);
578 
579  // Add mersenne twister rng wrapper
580  cmd_log_ << "Adding rng tables...\n";
582 
583  cmd_log_ << "Adding name generator metatable...\n";
585  static luaL_Reg const generator[] {
586  { "__call", &impl_name_generator_call},
587  { "__gc", &impl_name_generator_collect},
588  { nullptr, nullptr}
589  };
590  luaL_setfuncs(L, generator, 0);
591 
592  // Create formula bridge metatables
594 
596 
597  // Create the Lua interpreter table
598  cmd_log_ << "Sandboxing Lua interpreter...\nTo make variables visible outside the interpreter, assign to _G.variable.\n";
599  cmd_log_ << "The special variable _ holds the result of the last expression (if any).\n";
600  lua_newtable(L);
601  lua_createtable(L, 0, 1);
602  lua_getglobal(L, "_G");
603  lua_setfield(L, -2, "__index");
604  lua_setmetatable(L, -2);
606 
607  // Loading ilua:
608  cmd_log_ << "Loading ilua...\n";
609 
610  lua_settop(L, 0);
611  luaW_getglobal(L, "wesnoth", "require");
612  lua_pushstring(L, "lua/ilua.lua");
613  if(protected_call(1, 1)) {
614  //run "ilua.set_strict()"
615  lua_pushstring(L, "set_strict");
616  lua_gettable(L, -2);
617  if (!this->protected_call(0,0, std::bind(&lua_kernel_base::log_error, this, std::placeholders::_1, std::placeholders::_2))) {
618  cmd_log_ << "Failed to activate strict mode.\n";
619  } else {
620  cmd_log_ << "Activated strict mode.\n";
621  }
622 
623  lua_setglobal(L, "ilua"); //save ilua table as a global
624  } else {
625  cmd_log_ << "Error: failed to load ilua.\n";
626  }
627  lua_settop(L, 0);
628 
629  // Disable functions from debug which we don't want.
630  // We do this last because ilua needs to be able to use debug.getmetatable
631  lua_getglobal(L, "debug");
632  lua_pushnil(L);
633  while(lua_next(L, -2) != 0) {
634  lua_pop(L, 1);
635  char const* function = lua_tostring(L, -1);
636  if(strcmp(function, "traceback") == 0 || strcmp(function, "getinfo") == 0) continue; //traceback is needed for our error handler
637  lua_pushnil(L); //getinfo is needed for ilua strict mode
638  lua_setfield(L, -3, function);
639  }
640  lua_pop(L, 1);
641 }
642 
644 {
645  for (const auto& pair : this->registered_widget_definitions_) {
646  gui2::remove_single_widget_definition(std::get<0>(pair), std::get<1>(pair));
647  }
648  lua_close(mState);
649 }
650 
651 void lua_kernel_base::log_error(char const * msg, char const * context)
652 {
653  ERR_LUA << context << ": " << msg << '\n';
654 }
655 
656 void lua_kernel_base::throw_exception(char const * msg, char const * context)
657 {
658  throw game::lua_error(msg, context);
659 }
660 
661 bool lua_kernel_base::protected_call(int nArgs, int nRets)
662 {
663  error_handler eh = std::bind(&lua_kernel_base::log_error, this, std::placeholders::_1, std::placeholders::_2 );
664  return this->protected_call(nArgs, nRets, eh);
665 }
666 
667 bool lua_kernel_base::load_string(char const * prog, const std::string& name)
668 {
669  error_handler eh = std::bind(&lua_kernel_base::log_error, this, std::placeholders::_1, std::placeholders::_2 );
670  return this->load_string(prog, name, eh);
671 }
672 
673 bool lua_kernel_base::protected_call(int nArgs, int nRets, error_handler e_h)
674 {
675  return this->protected_call(mState, nArgs, nRets, e_h);
676 }
677 
678 bool lua_kernel_base::protected_call(lua_State * L, int nArgs, int nRets, error_handler e_h)
679 {
680  int errcode = luaW_pcall_internal(L, nArgs, nRets);
681 
682  if (errcode != LUA_OK) {
683  char const * msg = lua_tostring(L, -1);
684 
685  std::string context = "When executing, ";
686  if (errcode == LUA_ERRRUN) {
687  context += "Lua runtime error: ";
688  } else if (errcode == LUA_ERRERR) {
689  context += "Lua error in attached debugger: ";
690  } else if (errcode == LUA_ERRMEM) {
691  context += "Lua out of memory error: ";
692  } else {
693  context += "unknown lua error: ";
694  }
695  if(lua_isstring(L, -1)) {
696  context += msg ? msg : "null string";
697  } else {
698  context += lua_typename(L, lua_type(L, -1));
699  }
700 
701  lua_pop(L, 1);
702 
703  e_h(context.c_str(), "Lua Error");
704 
705  return false;
706  }
707 
708  return true;
709 }
710 
711 bool lua_kernel_base::load_string(char const * prog, const std::string& name, error_handler e_h)
712 {
713  // pass 't' to prevent loading bytecode which is unsafe and can be used to escape the sandbox.
714  int errcode = luaL_loadbufferx(mState, prog, strlen(prog), name.empty() ? name.c_str() : prog, "t");
715  if (errcode != LUA_OK) {
716  char const * msg = lua_tostring(mState, -1);
717  std::string message = msg ? msg : "null string";
718 
719  std::string context = "When parsing a string to lua, ";
720 
721  if (errcode == LUA_ERRSYNTAX) {
722  context += " a syntax error";
723  } else if(errcode == LUA_ERRMEM){
724  context += " a memory error";
725  } else {
726  context += " an unknown error";
727  }
728 
729  lua_pop(mState, 1);
730 
731  e_h(message.c_str(), context.c_str());
732 
733  return false;
734  }
735  return true;
736 }
737 
739 {
740  int nArgs = 0;
741  if (const config& args = cfg.child("args")) {
742  luaW_pushconfig(this->mState, args);
743  ++nArgs;
744  }
745  this->run(cfg["code"].str().c_str(), cfg["name"].str(), nArgs);
746 }
747 // Call load_string and protected call. Make them throw exceptions.
748 //
749 void lua_kernel_base::throwing_run(const char * prog, const std::string& name, int nArgs, bool in_interpreter)
750 {
751  cmd_log_ << "$ " << prog << "\n";
752  error_handler eh = std::bind(&lua_kernel_base::throw_exception, this, std::placeholders::_1, std::placeholders::_2 );
753  this->load_string(prog, name, eh);
754  if(in_interpreter) {
756  if(lua_setupvalue(mState, -2, 1) == nullptr)
757  lua_pop(mState, 1);
758  }
759  lua_insert(mState, -nArgs - 1);
760  this->protected_call(nArgs, in_interpreter ? LUA_MULTRET : 0, eh);
761 }
762 
763 // Do a throwing run, but if we catch a lua_error, reformat it with signature for this function and log it.
764 void lua_kernel_base::run(const char * prog, const std::string& name, int nArgs)
765 {
766  try {
767  this->throwing_run(prog, name, nArgs);
768  } catch (const game::lua_error & e) {
769  cmd_log_ << e.what() << "\n";
770  lua_kernel_base::log_error(e.what(), "In function lua_kernel::run()");
771  }
772 }
773 
774 // Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it normally. Throws exceptions.
775 void lua_kernel_base::interactive_run(char const * prog) {
776  std::string experiment = "return ";
777  experiment += prog;
778  int top = lua_gettop(mState);
779 
780  error_handler eh = std::bind(&lua_kernel_base::throw_exception, this, std::placeholders::_1, std::placeholders::_2 );
781  luaW_getglobal(mState, "ilua", "_pretty_print");
782 
783  try {
784  // Try to load the experiment without syntax errors
785  this->load_string(experiment.c_str(), "interactive", eh);
787  if(lua_setupvalue(mState, -2, 1) == nullptr)
788  lua_pop(mState, 1);
789  } catch (const game::lua_error &) {
790  this->throwing_run(prog, "interactive", 0, true); // Since it failed, fall back to the usual throwing_run, on the original input.
791  if(lua_gettop(mState) == top + 1) {
792  // Didn't return anything
793  lua_settop(mState, top);
794  return;
795  } else goto PRINT;
796  }
797  // experiment succeeded, now run but log normally.
798  cmd_log_ << "$ " << prog << "\n";
799  this->protected_call(0, LUA_MULTRET, eh);
800 PRINT:
801  int nRets = lua_gettop(mState) - top - 1;
802  {
803  // Assign first result to _
805  int env_idx = lua_gettop(mState);
806  lua_pushvalue(mState, top + 2);
807  lua_setfield(mState, -2, "_");
808  // Now duplicate EVERY result and pass it to table.pack, assigning to _all
809  luaW_getglobal(mState, "table", "pack");
810  for(int i = top + 2; i < env_idx; i++)
812  this->protected_call(nRets, 1, eh);
813  lua_setfield(mState, -2, "_all");
814  lua_pop(mState, 1);
815  }
816  // stack is now ilua._pretty_print followed by any results of prog
817  this->protected_call(lua_gettop(mState) - top - 1, 0, eh);
818 }
819 /**
820  * Loads and executes a Lua file.
821  * - Arg 1: string containing the file name.
822  * - Ret *: values returned by executing the file body.
823  */
825 {
826  luaL_checkstring(L, 1);
827  lua_rotate(L, 1, -1);
828  if (lua_fileops::load_file(L) != 1) return 0;
829  //^ should end with the file contents loaded on the stack. actually it will call lua_error otherwise, the return 0 is redundant.
830  lua_rotate(L, 1, 1);
831  // Using a non-protected call here appears to fix an issue in plugins.
832  // The protected call isn't technically necessary anyway, because this function is called from Lua code,
833  // which should already be in a protected environment.
834  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
835  return lua_gettop(L);
836 }
837 
838 /**
839  * Loads and executes a Lua file, if there is no corresponding entry in wesnoth.package.
840  * Stores the result of the script in wesnoth.package and returns it.
841  * - Arg 1: string containing the file name.
842  * - Ret 1: value returned by the script.
843  */
845 {
846  const char * m = luaL_checkstring(L, 1);
847  if(!m) {
848  return luaL_argerror(L, 1, "found a null string argument to wesnoth require");
849  }
850 
851  // Check if there is already an entry.
852 
853  lua_getglobal(L, "wesnoth");
854  lua_pushstring(L, "package");
855  lua_rawget(L, -2);
856  lua_pushvalue(L, 1);
857  lua_rawget(L, -2);
858  if(!lua_isnil(L, -1) && !game_config::debug_lua) {
859  return 1;
860  }
861  lua_pop(L, 1);
862  lua_pushvalue(L, 1);
863  // stack is now [packagename] [wesnoth] [package] [packagename]
864 
865  if(lua_fileops::load_file(L) != 1) {
866  // should end with the file contents loaded on the stack. actually it will call lua_error otherwise, the return 0 is redundant.
867  // stack is now [packagename] [wesnoth] [package] [chunk]
868  return 0;
869  }
870  DBG_LUA << "require: loaded a file, now calling it\n";
871 
872  if (!this->protected_call(L, 0, 1, std::bind(&lua_kernel_base::log_error, this, std::placeholders::_1, std::placeholders::_2))) {
873  // historically if wesnoth.require fails it just yields nil and some logging messages, not a lua error
874  return 0;
875  }
876  // stack is now [packagename] [wesnoth] [package] [results]
877 
878  lua_pushvalue(L, 1);
879  lua_pushvalue(L, -2);
880  // stack is now [packagename] [wesnoth] [package] [results] [packagename] [results]
881  // Add the return value to the table.
882 
883  lua_settable(L, -4);
884  // stack is now [packagename] [wesnoth] [package] [results]
885  return 1;
886 }
888 {
889  lua_push(L, my_name());
890  return 1;
891 }
893 {
894  char const *m = luaL_checkstring(L, 2);
908  return 0;
909 }
911 {
912  std::string err_msg = "unknown modifiable property of game_config: ";
913  err_msg += luaL_checkstring(L, 2);
914  return luaL_argerror(L, 2, err_msg.c_str());
915 }
916 /**
917  * Loads the "package" package into the Lua environment.
918  * This action is inherently unsafe, as Lua scripts will now be able to
919  * load C libraries on their own, hence granting them the same privileges
920  * as the Wesnoth binary itself.
921  */
923 {
924  lua_State *L = mState;
926  lua_pushstring(L, "package");
927  lua_call(L, 1, 0);
928 }
929 
931 {
932  lua_State* L = mState;
933  lua_settop(L, 0);
934  cmd_log_ << "Loading core...\n";
935  luaW_getglobal(L, "wesnoth", "require");
936  lua_pushstring(L, "lua/core");
937  if(!protected_call(1, 1)) {
938  cmd_log_ << "Error: Failed to load core.\n";
939  }
940  lua_settop(L, 0);
941 }
942 
943 /**
944  * Gets all the global variable names in the Lua environment. This is useful for tab completion.
945  */
946 std::vector<std::string> lua_kernel_base::get_global_var_names()
947 {
948  std::vector<std::string> ret;
949 
950  lua_State *L = mState;
951 
952  int idx = lua_gettop(L);
953  lua_getglobal(L, "_G");
954  lua_pushnil(L);
955 
956  while (lua_next(L, idx+1) != 0) {
957  if (lua_isstring(L, -2)) {
958  ret.push_back(lua_tostring(L,-2));
959  }
960  lua_pop(L,1);
961  }
962  lua_settop(L, idx);
963  return ret;
964 }
965 
966 /**
967  * Gets all attribute names of an extended variable name. This is useful for tab completion.
968  */
969 std::vector<std::string> lua_kernel_base::get_attribute_names(const std::string & input)
970 {
971  std::vector<std::string> ret;
972  std::string base_path = input;
973  std::size_t last_dot = base_path.find_last_of('.');
974  std::string partial_name = base_path.substr(last_dot + 1);
975  base_path.erase(last_dot);
976  std::string load = "return " + base_path;
977 
978  lua_State* L = mState;
979  int save_stack = lua_gettop(L);
980  int result = luaL_loadstring(L, load.c_str());
981  if(result != LUA_OK) {
982  // This isn't at error level because it's a really low priority error; it just means the user tried to tab-complete something that doesn't exist.
983  LOG_LUA << "Error when attempting tab completion:\n";
984  LOG_LUA << luaL_checkstring(L, -1) << '\n';
985  // Just return an empty list; no matches were found
986  lua_settop(L, save_stack);
987  return ret;
988  }
989 
990  luaW_pcall(L, 0, 1);
991  if(lua_istable(L, -1) || lua_isuserdata(L, -1)) {
992  int top = lua_gettop(L);
993  int obj = lua_absindex(L, -1);
994  if(luaL_getmetafield(L, obj, "__tab_enum") == LUA_TFUNCTION) {
995  lua_pushvalue(L, obj);
996  lua_pushlstring(L, partial_name.c_str(), partial_name.size());
997  luaW_pcall(L, 2, 1);
998  ret = lua_check<std::vector<std::string>>(L, -1);
999  } else if(lua_type(L, -1) != LUA_TTABLE) {
1000  LOG_LUA << "Userdata missing __tab_enum meta-function for tab completion";
1001  lua_settop(L, save_stack);
1002  return ret;
1003  } else {
1004  lua_settop(L, top);
1005  // Metafunction not found, so use lua_next to enumerate the table
1006  for(lua_pushnil(L); lua_next(L, obj); lua_pop(L, 1)) {
1007  if(lua_type(L, -2) == LUA_TSTRING) {
1008  std::string attr = lua_tostring(L, -2);
1009  if(attr.empty()) {
1010  continue;
1011  }
1012  if(!isalpha(attr[0]) && attr[0] != '_') {
1013  continue;
1014  }
1015  if(std::any_of(attr.begin(), attr.end(), [](char c){
1016  return !isalpha(c) && !isdigit(c) && c != '_';
1017  })) {
1018  continue;
1019  }
1020  if(attr.substr(0, partial_name.size()) == partial_name) {
1021  ret.push_back(base_path + "." + attr);
1022  }
1023  }
1024  }
1025  }
1026  }
1027  lua_settop(L, save_stack);
1028  return ret;
1029 }
1030 
1032 {
1033  #ifdef __GNUC__
1034  #pragma GCC diagnostic push
1035  #pragma GCC diagnostic ignored "-Wold-style-cast"
1036  #endif
1037  return *reinterpret_cast<lua_kernel_base**>(lua_getextraspace(L));
1038  #ifdef __GNUC__
1039  #pragma GCC diagnostic pop
1040  #endif
1041 }
1042 
1044 {
1045  return seed_rng::next_seed();
1046 }
int dispatch(lua_State *L)
VERSION_COMP_OP
void interactive_run(char const *prog)
Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it nor...
LUALIB_API void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb)
Definition: lauxlib.cpp:945
#define lua_isnoneornil(L, n)
Definition: lua.h:379
surface get_image(const image::locator &i_locator, TYPE type)
Caches and returns an image.
Definition: picture.cpp:815
static int intf_name_generator(lua_State *L)
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:728
#define lua_pushcfunction(L, f)
Definition: lua.h:370
int show_lua_console(lua_State *, lua_kernel_base *lk)
Definition: lua_gui2.cpp:240
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:414
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
Definition: lua_common.cpp:430
int intf_read_file(lua_State *L)
Reads a file into a string, or a directory into a list of files therein.
LUALIB_API lua_State * luaL_newstate(void)
Definition: lauxlib.cpp:1065
LUAMOD_API int luaopen_debug(lua_State *L)
Definition: ldblib.cpp:478
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:733
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:173
#define lua_isnone(L, n)
Definition: lua.h:378
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:260
int village_support
Definition: game_config.cpp:54
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
Calls a Lua function stored below its nArgs arguments at the top of the stack.
int intf_have_file(lua_State *L)
Checks if a file exists (not necessarily a Lua script).
Interfaces for manipulating version numbers of engine, add-ons, etc.
static int intf_get_image_size(lua_State *L)
Gets the dimension of an image.
LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
Definition: lauxlib.cpp:815
int intf_canonical_path(lua_State *L)
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:581
VERSION_COMP_OP parse_version_op(const std::string &op_str)
#define LUA_MULTRET
Definition: lua.h:36
std::vector< game_tip > load(const config &cfg)
Loads the tips from a config.
Definition: tips.cpp:35
std::function< void(char const *, char const *)> error_handler
logger & info()
Definition: log.cpp:88
std::string generate(const std::map< std::string, std::string > &variables) const
int intf_get_direction(lua_State *L)
Expose map_location::get_direction function to lua Arg 1: a location Arg 2: a direction Arg 3: (optio...
LUALIB_API int luaL_getmetafield(lua_State *L, int obj, const char *event)
Definition: lauxlib.cpp:823
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:168
LUA_API int lua_gettable(lua_State *L, int idx)
Definition: lapi.cpp:640
LUAMOD_API int luaopen_math(lua_State *L)
Definition: lmathlib.cpp:750
LUA_API int lua_getglobal(lua_State *L, const char *name)
Definition: lapi.cpp:632
LUA_API void lua_settable(lua_State *L, int idx)
Definition: lapi.cpp:821
#define return_string_attrib(name, accessor)
Definition: lua_common.hpp:226
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:93
#define LOG_LUA
std::vector< std::tuple< std::string, std::string > > registered_widget_definitions_
LUA_API int lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:698
#define luaL_getmetatable(L, n)
Definition: lauxlib.h:149
int intf_kernel_type(lua_State *L)
virtual ~lua_kernel_base()
LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int arg, lua_Integer def)
Definition: lauxlib.cpp:452
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
#define LUA_TFUNCTION
Definition: lua.h:71
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:298
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:384
#define LOG_STREAM(level, domain)
Definition: log.hpp:209
static lg::log_domain log_scripting_lua("scripting/lua")
bool do_version_check(const version_info &a, VERSION_COMP_OP op, const version_info &b)
int luaW_open(lua_State *L)
Definition: lua_gui2.cpp:273
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:161
int intf_vector_diff(lua_State *L)
Expose map_location::vector_difference to lua.
LUAMOD_API int luaopen_base(lua_State *L)
Definition: lbaselib.cpp:515
int rest_heal_amount
Definition: game_config.cpp:60
int intf_distance_between(lua_State *L)
Expose map_location distance_between.
void remove_single_widget_definition(const std::string &widget_type, const std::string &definition_id)
Removes a widget definition from the default GUI.
#define lua_pop(L, n)
Definition: lua.h:364
int intf_rotate_right_around_center(lua_State *L)
Expose map_location::rotate_right_around_center to lua.
lua_CFunction func
Definition: lauxlib.h:39
int intf_eval_formula(lua_State *)
Evaluates a formula in the formula engine.
static void impl_warn(void *p, const char *msg, int tocont)
int intf_get_relative_dir(lua_State *L)
Expose map_location get_relative_dir.
#define LUA_TSTRING
Definition: lua.h:69
LUAMOD_API int luaopen_coroutine(lua_State *L)
Definition: lcorolib.cpp:203
void lua_warning(lua_State *L, const char *msg, int tocont)
Definition: lapi.cpp:1303
LUALIB_API int luaL_argerror(lua_State *L, int arg, const char *extramsg)
Definition: lauxlib.cpp:175
LUAMOD_API int luaopen_os(lua_State *L)
Definition: loslib.cpp:426
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
Definition: deprecation.cpp:29
#define return_int_attrib(name, accessor)
Definition: lua_common.hpp:235
void load_core()
Loads the "core" library into the Lua environment.
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil...
Definition: lua_common.cpp:874
LUAMOD_API int luaopen_string(lua_State *L)
Definition: lstrlib.cpp:1797
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:292
int luaW_open(lua_State *L)
static int intf_get_language(lua_State *L)
LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t size, const char *name, const char *mode)
Definition: lauxlib.cpp:806
int intf_show_lua_console(lua_State *L)
static lg::log_domain log_user("scripting/lua/user")
virtual ~name_generator()
LUA_API void * lua_newuserdatauv(lua_State *L, size_t size, int nuvalue)
Definition: lapi.cpp:1311
LUAMOD_API int luaopen_table(lua_State *L)
Definition: ltablib.cpp:424
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:623
static int intf_deprecated_message(lua_State *L)
Logs a deprecation message.
LUAMOD_API int luaopen_package(lua_State *L)
Definition: loadlib.cpp:736
void load_package()
Loads the package library into lua environment.
LUA_API void lua_close(lua_State *L)
Definition: lstate.cpp:405
bool protected_call(int nArgs, int nRets, error_handler)
#define lua_getextraspace(L)
Definition: lua.h:359
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:502
int kill_experience
Definition: game_config.cpp:56
LUA_API void lua_setglobal(lua_State *L, const char *name)
Definition: lapi.cpp:813
std::string register_metatables(lua_State *L)
Definition: lua_color.cpp:135
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:901
static int impl_name_generator_collect(lua_State *L)
const char * what() const noexcept
Definition: exceptions.hpp:35
int intf_compile_formula(lua_State *)
int(lua_kernel_base::* member_callback)(lua_State *L)
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
#define lua_newtable(L)
Definition: lua.h:366
int luaW_open(lua_State *L)
Definition: lua_wml.cpp:244
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:473
LUA_API const char * lua_setupvalue(lua_State *L, int funcindex, int n)
Definition: lapi.cpp:1366
int intf_tiles_adjacent(lua_State *L)
Expose map_location tiles_adjacent.
LUAMOD_API int() luaopen_utf8(lua_State *L)
Definition: lutf8lib.cpp:283
Generic locator abstracting the location of an image.
Definition: picture.hpp:59
virtual int impl_game_config_get(lua_State *L)
void register_metatable(lua_State *L)
Definition: lua_widget.cpp:192
int intf_vector_negation(lua_State *L)
Expose map_location::vector_negation to lua.
LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:311
LUA_API void * lua_touserdata(lua_State *L, int idx)
Definition: lapi.cpp:432
#define LUA_ERRERR
Definition: lua.h:54
void run(char const *prog, const std::string &name, int nArgs=0)
Runs a plain script.
static int intf_random(lua_State *L)
Returns a random numer, same interface as math.random.
#define lua_isnil(L, n)
Definition: lua.h:375
int intf_print(lua_State *L)
Replacement print function – instead of printing to std::cout, print to the command log...
std::size_t i
Definition: function.cpp:940
logger & err()
Definition: log.cpp:76
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int arg)
Definition: lauxlib.cpp:442
std::string register_metatables(lua_State *)
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
Definition: lua_common.cpp:410
mock_party p
int village_income
Definition: game_config.cpp:53
int intf_get_in_basis_N_NE(lua_State *L)
Expose map_location get_in_basis_N_NE.
static map_location::DIRECTION s
const language_def & get_language()
Definition: language.cpp:316
virtual uint32_t get_random_seed()
#define LUA_ERRSYNTAX
Definition: lua.h:52
#define lua_tostring(L, i)
Definition: lua.h:386
static int intf_get_time_stamp(lua_State *L)
Returns the time stamp, exactly as [set_variable] time=stamp does.
static int intf_compare_versions(lua_State *L)
Compares 2 version strings - which is newer.
void throwing_run(char const *prog, const std::string &name, int nArgs, bool in_interpreter=false)
Runs a plain script, but reports errors by throwing lua_error.
LUA_API void lua_rotate(lua_State *L, int idx, int n)
Definition: lapi.cpp:217
int combat_experience
Definition: game_config.cpp:57
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:246
const bool & debug
#define debug(x)
#define LUA_ERRMEM
Definition: lua.h:53
int intf_get_adjacent_tiles(lua_State *L)
Expose map_location get_adjacent_tiles.
int load_file(lua_State *L)
Loads a Lua file and pushes the contents on the stack.
LUA_API int lua_isnumber(lua_State *L, int idx)
Definition: lapi.cpp:285
virtual void log_error(char const *msg, char const *context="Lua error")
Error reporting mechanisms, used by virtual methods protected_call and load_string.
const version_info wesnoth_version(VERSION)
rng * generator
This generator is automatically synced during synced context.
Definition: random.cpp:60
bool load_string(char const *prog, const std::string &name, error_handler)
#define lua_call(L, n, r)
Definition: lua.h:283
virtual int impl_game_config_set(lua_State *L)
#define DBG_LUA
Represents version numbers.
std::vector< std::string > get_global_var_names()
Get tab completion strings.
command_log cmd_log_
int intf_vector_sum(lua_State *L)
Expose map_location::vector_sum to lua.
#define LUA_REGISTRYINDEX
Definition: lua.h:44
#define return_bool_attrib(name, accessor)
Definition: lua_common.hpp:251
static int impl_name_generator_call(lua_State *L)
uint32_t next_seed()
Definition: seed_rng.cpp:31
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1205
logger & warn()
Definition: log.cpp:82
std::vector< std::string > get_attribute_names(const std::string &var_path)
Gets all attribute names of an extended variable name.
#define LUA_OK
Definition: lua.h:49
#define lua_istable(L, n)
Definition: lua.h:373
std::vector< std::string > split(const config_attribute_value &val)
DEP_LEVEL
See https://wiki.wesnoth.org/CompatibilityStandards for more info.
Definition: deprecation.hpp:19
virtual void throw_exception(char const *msg, char const *context="Lua error")
#define lua_insert(L, idx)
Definition: lua.h:389
Standard logging facilities (interface).
std::string str() const
Serializes the version number into string form.
uint32_t next_random()
Provides the next random draw.
Definition: random.cpp:84
int intf_get_tiles_in_radius(lua_State *L)
Expose map_location get_tiles_in_radius.
void lua_setwarnf(lua_State *L, lua_WarnFunction f, void *ud)
Definition: lapi.cpp:1295
void register_metatable(lua_State *L)
#define ERR_LUA
virtual std::string my_name()
User-visible name of the lua kernel that they are talking to.
#define e
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
Definition: lauxlib.cpp:904
void push_error_handler(lua_State *L)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
int intf_dofile(lua_State *L)
Loads and executes a Lua file.
mock_char c
const std::string & str() const
Definition: tstring.hpp:190
static const char * Interp
LUA_API int lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:655
lua_State * mState
static int intf_load(lua_State *L)
Replacement load function.
#define LUA_TTABLE
Definition: lua.h:70
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:489
#define luaL_optstring(L, n, d)
Definition: lauxlib.h:139
bool file_exists() const
Tests whether the file the locator points at exists.
Definition: picture.cpp:658
int intf_require(lua_State *L)
Loads and executes a Lua file, if there is no corresponding entry in wesnoth.package.
void load_tables(lua_State *L)
Creates the metatable for RNG objects, and adds the Rng table which contains the constructor.
Definition: lua_rng.cpp:80
void add_log_to_console(const std::string &msg)
void run_lua_tag(const config &cfg)
Runs a [lua] tag.
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:514
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:837
#define LUA_ERRRUN
Definition: lua.h:51
LUA_API int lua_next(lua_State *L, int idx)
Definition: lapi.cpp:1220
const char * what() const noexcept
static lua_kernel_base *& get_lua_kernel_base_ptr(lua_State *L)
LUA_API const char * lua_typename(lua_State *L, int t)
Definition: lapi.cpp:266
static const char * Gen
std::vector< std::string > parenthetical_split(const std::string &val, const char separator, const std::string &left, const std::string &right, const int flags)
Splits a string based either on a separator, except then the text appears within specified parenthesi...
static int intf_log(lua_State *L)
Logs a message Arg 1: (optional) Logger Arg 2: Message.
#define luaL_checkstring(L, n)
Definition: lauxlib.h:138
Error used to report an error in a lua script or in the lua interpreter.
Definition: game_errors.hpp:53