The Battle for Wesnoth  1.15.1+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"
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_common.hpp"
35 #include "scripting/lua_gui2.hpp"
37 #include "scripting/lua_rng.hpp"
38 #include "scripting/push_check.hpp"
39 
40 #include "game_version.hpp" // for do_version_check, etc
41 #include "picture.hpp"
42 
43 #include "formula/string_utils.hpp"
46 #include "serialization/parser.hpp"
48 #include "utils/functional.hpp"
49 #include "utils/name_generator.hpp"
52 #include "variable.hpp" // for config_variable_set
53 
54 #include <cstring>
55 #include <exception>
56 #include <new>
57 #include <string>
58 #include <sstream>
59 #include <vector>
60 #include <fstream>
61 
62 #include "lua/lauxlib.h"
63 #include "lua/lua.h"
64 #include "lua/lualib.h"
65 
66 static lg::log_domain log_scripting_lua("scripting/lua");
67 static lg::log_domain log_user("scripting/lua/user");
68 #define DBG_LUA LOG_STREAM(debug, log_scripting_lua)
69 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
70 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
71 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
72 
73 // Registry key for metatable
74 static const char * Gen = "name generator";
75 
76 // Callback implementations
77 
78 /**
79  * Compares 2 version strings - which is newer.
80  * - Args 1,3: version strings
81  * - Arg 2: comparison operator (string)
82  * - Ret 1: comparison result
83  */
85 {
86  char const *v1 = luaL_checkstring(L, 1);
87 
89  if(vop == OP_INVALID) return luaL_argerror(L, 2, "unknown version comparison operator - allowed are ==, !=, <, <=, > and >=");
90 
91  char const *v2 = luaL_checkstring(L, 3);
92 
93  const bool result = do_version_check(version_info(v1), vop, version_info(v2));
94  lua_pushboolean(L, result);
95 
96  return 1;
97 }
98 
99 /**
100  * Replacement print function -- instead of printing to std::cout, print to the command log.
101  * Intended to be bound to this' command_log at registration time.
102  */
104 {
105  DBG_LUA << "intf_print called:\n";
106  std::size_t nargs = lua_gettop(L);
107 
108  lua_getglobal(L, "tostring");
109  for (std::size_t i = 1; i <= nargs; ++i) {
110  lua_pushvalue(L, -1); // function to call: "tostring"
111  lua_pushvalue(L, i); // value to pass through tostring() before printing
112  lua_call(L, 1, 1);
113  const char * str = lua_tostring(L, -1);
114  if (!str) {
115  LOG_LUA << "'tostring' must return a value to 'print'\n";
116  str = "";
117  }
118  if (i > 1) {
119  cmd_log_ << "\t"; //separate multiple args with tab character
120  }
121  cmd_log_ << str;
122  DBG_LUA << "'" << str << "'\n";
123  lua_pop(L, 1); // Pop the output of tostrring()
124  }
125  lua_pop(L, 1); // Pop 'tostring' global
126 
127  cmd_log_ << "\n";
128  DBG_LUA << "\n";
129 
130  return 0;
131 }
132 
133 /**
134  * Replacement load function. Mostly the same as regular load, but disallows loading binary chunks
135  * due to CVE-2018-1999023.
136  */
137 static int intf_load(lua_State* L)
138 {
139  std::string chunk = luaL_checkstring(L, 1);
140  const char* name = luaL_optstring(L, 2, chunk.c_str());
141  std::string mode = luaL_optstring(L, 3, "t");
142  bool override_env = !lua_isnone(L, 4);
143 
144  if(mode != "t") {
145  return luaL_argerror(L, 3, "binary chunks are not allowed for security reasons");
146  }
147 
148  int result = luaL_loadbufferx(L, chunk.data(), chunk.length(), name, "t");
149  if(result != LUA_OK) {
150  lua_pushnil(L);
151  // Move the nil as the first return value, like Lua's own load() does.
152  lua_insert(L, -2);
153 
154  return 2;
155  }
156 
157  if(override_env) {
158  // Copy "env" to the top of the stack.
159  lua_pushvalue(L, 4);
160  // Set "env" as the first upvalue.
161  const char* upvalue_name = lua_setupvalue(L, -2, 1);
162  if(upvalue_name == nullptr) {
163  // lua_setupvalue() didn't remove the copy of "env" from the stack, so we need to do it ourselves.
164  lua_pop(L, 1);
165  }
166  }
167 
168  return 1;
169 }
170 
171 // The show lua console callback is similarly a method of lua kernel
173 {
174  if (cmd_log_.external_log_) {
175  std::string message = "There is already an external logger attached to this lua kernel, you cannot open the lua console right now.";
176  log_error(message.c_str());
177  cmd_log_ << message << "\n";
178  return 0;
179  }
180 
181  return lua_gui2::show_lua_console(L, this);
182 }
183 
185 {
186  name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
187  lua_pushstring(L, gen->generate().c_str());
188  return 1;
189 }
190 
192 {
193  name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
194  gen->~name_generator();
195  return 0;
196 }
197 
199 {
200  std::string type = luaL_checkstring(L, 1);
201  name_generator* gen = nullptr;
202  try {
203  if(type == "markov" || type == "markov_chain") {
204  std::vector<std::string> input;
205  if(lua_istable(L, 2)) {
206  input = lua_check<std::vector<std::string>>(L, 2);
207  } else {
208  input = utils::parenthetical_split(luaL_checkstring(L, 2), ',');
209  }
210  int chain_sz = luaL_optinteger(L, 3, 2);
211  int max_len = luaL_optinteger(L, 4, 12);
212  gen = new(L) markov_generator(input, chain_sz, max_len);
213  // Ensure the pointer didn't change when cast
214  assert(static_cast<void*>(gen) == dynamic_cast<markov_generator*>(gen));
215  } else if(type == "context_free" || type == "cfg" || type == "CFG") {
216  if(lua_istable(L, 2)) {
217  std::map<std::string, std::vector<std::string>> data;
218  for(lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
219  if(lua_type(L, -2) != LUA_TSTRING) {
220  lua_pushstring(L, "CFG generator: invalid nonterminal name (must be a string)");
221  return lua_error(L);
222  }
223  if(lua_isstring(L, -1)) {
224  data[lua_tostring(L,-2)] = utils::split(lua_tostring(L,-1),'|');
225  } else if(lua_istable(L, -1)) {
226  data[lua_tostring(L,-2)] = lua_check<std::vector<std::string>>(L, -1);
227  } else {
228  lua_pushstring(L, "CFG generator: invalid noterminal value (must be a string or list of strings)");
229  return lua_error(L);
230  }
231  }
232  if(!data.empty()) {
233  gen = new(L) context_free_grammar_generator(data);
234  }
235  } else {
237  }
238  if(gen) {
239  assert(static_cast<void*>(gen) == dynamic_cast<context_free_grammar_generator*>(gen));
240  }
241  } else {
242  return luaL_argerror(L, 1, "should be either 'markov_chain' or 'context_free'");
243  }
244  }
245  catch (const name_generator_invalid_exception& ex) {
246  lua_pushstring(L, ex.what());
247  return lua_error(L);
248  }
249 
250  // We set the metatable now, even if the generator is invalid, so that it
251  // will be properly collected if it was invalid.
253  lua_setmetatable(L, -2);
254 
255  return 1;
256 }
257 
258 /**
259 * Returns a random numer, same interface as math.random.
260 */
261 static int intf_random(lua_State *L)
262 {
263  if (lua_isnoneornil(L, 1)) {
264  double r = static_cast<double>(randomness::generator->next_random());
265  double r_max = static_cast<double>(std::numeric_limits<uint32_t>::max());
266  lua_push(L, r / (r_max + 1));
267  return 1;
268  }
269  else {
270  int32_t min;
271  int32_t max;
272  if (lua_isnumber(L, 2)) {
273  min = lua_check<int32_t>(L, 1);
274  max = lua_check<int32_t>(L, 2);
275  }
276  else {
277  min = 1;
278  max = lua_check<int32_t>(L, 1);
279  }
280  if (min > max) {
281  return luaL_argerror(L, 1, "min > max");
282  }
283  lua_push(L, randomness::generator->get_random_int(min, max));
284  return 1;
285  }
286 }
287 
289 {
290  config cfg = luaW_checkconfig(L, 1);
291  config filter = luaW_checkconfig(L, 2);
292  lua_pushboolean(L, cfg.matches(filter));
293  return 1;
294 }
295 
296 /**
297 * Logs a message
298 * Arg 1: (optional) Logger
299 * Arg 2: Message
300 */
301 static int intf_log(lua_State *L) {
302  const std::string& logger = lua_isstring(L, 2) ? luaL_checkstring(L, 1) : "";
303  std::string msg = lua_isstring(L, 2) ? luaL_checkstring(L, 2) : luaL_checkstring(L, 1);
304  if(msg.empty() || msg.back() != '\n') {
305  msg += '\n';
306  }
307 
308  if(logger == "err" || logger == "error") {
309  LOG_STREAM(err, log_user) << msg;
310  } else if(logger == "warn" || logger == "wrn" || logger == "warning") {
312  } else if((logger == "debug" || logger == "dbg")) {
314  } else {
316  }
317  return 0;
318 }
319 
320 /**
321  * Logs a deprecation message. See deprecation.cpp for details
322  * Arg 1: Element to be deprecated.
323  * Arg 2: Deprecation level.
324  * Arg 3: Version when element may be removed.
325  * Arg 4: Additional detail message.
326  */
328  const std::string elem = luaL_checkstring(L, 1);
329  // This could produce an invalid deprecation level, but that possibility is handled in deprecated_message()
331  const std::string ver_str = lua_isnoneornil(L, 3) ? "" : luaL_checkstring(L, 3);
332  const std::string detail = luaW_checktstring(L, 4);
333  const version_info ver = ver_str.empty() ? game_config::wesnoth_version.str() : ver_str;
334  const std::string msg = deprecated_message(elem, level, ver, detail);
335  if(level < DEP_LEVEL::INDEFINITE || level >= DEP_LEVEL::REMOVED) {
336  // Invalid deprecation level or level 4 deprecation should raise an interpreter error
337  lua_push(L, msg);
338  return lua_error(L);
339  }
340  return 0;
341 }
342 
343 /**
344 * Gets the dimension of an image.
345 * - Arg 1: string.
346 * - Ret 1: width.
347 * - Ret 2: height.
348 */
350  char const *m = luaL_checkstring(L, 1);
351  image::locator img(m);
352  if(!img.file_exists()) return 0;
353  surface s = get_image(img);
354  lua_pushinteger(L, s->w);
355  lua_pushinteger(L, s->h);
356  return 2;
357 }
358 
359 /**
360 * Returns the time stamp, exactly as [set_variable] time=stamp does.
361 * - Ret 1: integer
362 */
364  lua_pushinteger(L, SDL_GetTicks());
365  return 1;
366 }
367 
368 static int intf_format(lua_State* L)
369 {
370  config cfg = luaW_checkconfig(L, 2);
371  config_variable_set variables(cfg);
372  if(lua_isstring(L, 1)) {
373  std::string str = lua_tostring(L, 1);
375  return 1;
376  }
377  t_string str = luaW_checktstring(L, 1);
379  return 1;
380 }
381 
382 template<bool conjunct>
384 {
385  const t_string empty = luaW_checktstring(L, 1);
386  auto values = lua_check<std::vector<t_string>>(L, 2);
387  lua_push(L, (conjunct ? utils::format_conjunct_list : utils::format_disjunct_list)(empty, values));
388  return 1;
389 }
390 
392 {
393  lua_push(L, get_language().localename);
394  return 1;
395 }
396 
397 /**
398 * Dumps a wml table or userdata wml object into a pretty string.
399 * - Arg 1: wml table or vconfig userdata
400 * - Ret 1: string
401 */
402 static int intf_wml_tostring(lua_State* L) {
403  const config& arg = luaW_checkconfig(L, 1);
404  std::ostringstream stream;
405  write(stream, arg);
406  lua_pushstring(L, stream.str().c_str());
407  return 1;
408 }
409 
410 /**
411  * Loads a WML file into a config
412  * - Arg 1: WML file path
413  * - Arg 2: (optional) Array of preprocessor defines, or false to skip preprocessing (true is also valid)
414  * - Arg 3: (optional) Path to a schema file for validation (omit for no validation)
415  * - Ret: config
416  */
417 static int intf_load_wml(lua_State* L)
418 {
419  std::string file = luaL_checkstring(L, 1);
420  bool preprocess = true;
421  preproc_map defines_map;
422  if(lua_type(L, 2) == LUA_TBOOLEAN) {
423  preprocess = luaW_toboolean(L, 2);
424  } else if(lua_type(L, 2) == LUA_TTABLE || lua_type(L, 2) == LUA_TUSERDATA) {
425  lua_len(L, 2);
426  int n = lua_tonumber(L, -1);
427  lua_pop(L, 1);
428  for(int i = 0; i < n; i++) {
429  lua_geti(L, 2, i);
430  if(!lua_isstring(L, -1)) {
431  return luaL_argerror(L, 2, "expected bool or array of strings");
432  }
433  std::string define = lua_tostring(L, -1);
434  lua_pop(L, 1);
435  if(!define.empty()) {
436  defines_map.emplace(define, preproc_define(define));
437  }
438  }
439  } else if(!lua_isnoneornil(L, 2)) {
440  return luaL_argerror(L, 2, "expected bool or array of strings");
441  }
442  std::string schema_path = luaL_optstring(L, 3, "");
443  std::shared_ptr<schema_validation::schema_validator> validator;
444  if(!schema_path.empty()) {
445  validator.reset(new schema_validation::schema_validator(filesystem::get_wml_location(schema_path)));
446  validator->set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
447  }
448  std::string wml_file = filesystem::get_wml_location(file);
450  config result;
451  if(preprocess) {
452  stream = preprocess_file(wml_file, &defines_map);
453  } else {
454  stream.reset(new std::ifstream(wml_file));
455  }
456  read(result, *stream, validator.get());
457  luaW_pushconfig(L, result);
458  return 1;
459 }
460 
461 /**
462  * Parses a WML string into a config; does not preprocess or validate
463  * - Arg 1: WML string
464  * - Ret: config
465  */
466 static int intf_parse_wml(lua_State* L)
467 {
468  std::string wml = luaL_checkstring(L, 1);
469  std::string schema_path = luaL_optstring(L, 2, "");
470  std::shared_ptr<schema_validation::schema_validator> validator;
471  if(!schema_path.empty()) {
472  validator.reset(new schema_validation::schema_validator(filesystem::get_wml_location(schema_path)));
473  validator->set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
474  }
475  config result;
476  read(result, wml, validator.get());
477  luaW_pushconfig(L, result);
478  return 1;
479 }
480 
481 /**
482  * Returns a clone (deep copy) of the passed config, which can be either a normal config or a vconfig
483  * If it is a vconfig, the underlying config is also cloned.
484  * - Arg 1: a config
485  * - Ret: the cloned config
486  */
487 static int intf_clone_wml(lua_State* L)
488 {
489  const vconfig* vcfg = nullptr;
490  const config& cfg = luaW_checkconfig(L, 1, vcfg);
491  if(vcfg) {
492  config clone_underlying = vcfg->get_config();
493  vconfig clone(clone_underlying);
494  luaW_pushvconfig(L, clone);
495  } else {
496  luaW_pushconfig(L, cfg);
497  }
498  return 1;
499 }
500 
501 // End Callback implementations
502 
503 // Template which allows to push member functions to the lua kernel base into lua as C functions, using a shim
505 
506 template <member_callback method>
508  return ((lua_kernel_base::get_lua_kernel<lua_kernel_base>(L)).*method)(L);
509 }
510 
511 // Ctor, initialization
513  : mState(luaL_newstate())
514  , cmd_log_()
515 {
517  lua_State *L = mState;
518 
519  cmd_log_ << "Initializing " << my_name() << "...\n";
520 
521  // Open safe libraries.
522  // Debug and OS are not, but most of their functions will be disabled below.
523  cmd_log_ << "Adding standard libs...\n";
524 
525  static const luaL_Reg safe_libs[] {
526  { "", luaopen_base },
527  { "table", luaopen_table },
528  { "string", luaopen_string },
529  { "math", luaopen_math },
530  { "coroutine", luaopen_coroutine },
531  { "debug", luaopen_debug },
532  { "os", luaopen_os },
533  { "utf8", luaopen_utf8 }, // added in Lua 5.3
534  { nullptr, nullptr }
535  };
536  for (luaL_Reg const *lib = safe_libs; lib->func; ++lib)
537  {
538  luaL_requiref(L, lib->name, lib->func, 1);
539  lua_pop(L, 1); /* remove lib */
540  }
541 
542  // Disable functions from os which we don't want.
543  lua_getglobal(L, "os");
544  lua_pushnil(L);
545  while(lua_next(L, -2) != 0) {
546  lua_pop(L, 1);
547  char const* function = lua_tostring(L, -1);
548  if(strcmp(function, "clock") == 0 || strcmp(function, "date") == 0
549  || strcmp(function, "time") == 0 || strcmp(function, "difftime") == 0) continue;
550  lua_pushnil(L);
551  lua_setfield(L, -3, function);
552  }
553  lua_pop(L, 1);
554 
555  // Disable functions from debug which we don't want.
556  lua_getglobal(L, "debug");
557  lua_pushnil(L);
558  while(lua_next(L, -2) != 0) {
559  lua_pop(L, 1);
560  char const* function = lua_tostring(L, -1);
561  if(strcmp(function, "traceback") == 0 || strcmp(function, "getinfo") == 0) continue; //traceback is needed for our error handler
562  lua_pushnil(L); //getinfo is needed for ilua strict mode
563  lua_setfield(L, -3, function);
564  }
565  lua_pop(L, 1);
566 
567  // Delete dofile and loadfile.
568  lua_pushnil(L);
569  lua_setglobal(L, "dofile");
570  lua_pushnil(L);
571  lua_setglobal(L, "loadfile");
572 
573  // Store the error handler.
574  cmd_log_ << "Adding error handler...\n";
576 
577  // Create the gettext metatable.
579 
580  // Create the tstring metatable.
582 
583 
584  lua_settop(L, 0);
585 
586  // Define the CPP_function metatable ( so we can override print to point to a C++ member function, add "show_dialog" for this kernel, etc. )
587  cmd_log_ << "Adding boost function proxy...\n";
588 
590 
591  // Add some callback from the wesnoth lib
592  cmd_log_ << "Registering basic wesnoth API...\n";
593 
594  static luaL_Reg const callbacks[] {
595  { "compare_versions", &intf_compare_versions },
596  { "debug", &intf_wml_tostring },
597  { "deprecated_message", &intf_deprecated_message },
598  { "have_file", &lua_fileops::intf_have_file },
599  { "read_file", &lua_fileops::intf_read_file },
600  { "textdomain", &lua_common::intf_textdomain },
601  { "tovconfig", &lua_common::intf_tovconfig },
602  { "get_dialog_value", &lua_gui2::intf_get_dialog_value },
603  { "set_dialog_tooltip", &lua_gui2::intf_set_dialog_tooltip },
604  { "set_dialog_active", &lua_gui2::intf_set_dialog_active },
605  { "set_dialog_visible", &lua_gui2::intf_set_dialog_visible },
606  { "add_dialog_tree_node", &lua_gui2::intf_add_dialog_tree_node },
607  { "add_widget_definition", &lua_gui2::intf_add_widget_definition },
608  { "set_dialog_callback", &lua_gui2::intf_set_dialog_callback },
609  { "set_dialog_canvas", &lua_gui2::intf_set_dialog_canvas },
610  { "set_dialog_focus", &lua_gui2::intf_set_dialog_focus },
611  { "set_dialog_markup", &lua_gui2::intf_set_dialog_markup },
612  { "set_dialog_value", &lua_gui2::intf_set_dialog_value },
613  { "remove_dialog_item", &lua_gui2::intf_remove_dialog_item },
614  { "dofile", &dispatch<&lua_kernel_base::intf_dofile> },
615  { "require", &dispatch<&lua_kernel_base::intf_require> },
616  { "kernel_type", &dispatch<&lua_kernel_base::intf_kernel_type> },
617  { "show_dialog", &lua_gui2::show_dialog },
618  { "show_menu", &lua_gui2::show_menu },
619  { "show_message_dialog", &lua_gui2::show_message_dialog },
620  { "show_popup_dialog", &lua_gui2::show_popup_dialog },
621  { "show_story", &lua_gui2::show_story },
622  { "show_message_box", &lua_gui2::show_message_box },
623  { "show_lua_console", &dispatch<&lua_kernel_base::intf_show_lua_console> },
624  { "compile_formula", &lua_formula_bridge::intf_compile_formula},
625  { "eval_formula", &lua_formula_bridge::intf_eval_formula},
626  { "name_generator", &intf_name_generator },
627  { "random", &intf_random },
628  { "wml_matches_filter", &intf_wml_matches_filter },
629  { "log", &intf_log },
630  { "get_image_size", &intf_get_image_size },
631  { "get_time_stamp", &intf_get_time_stamp },
632  { "format", &intf_format },
633  { "format_conjunct_list", &intf_format_list<true> },
634  { "format_disjunct_list", &intf_format_list<false> },
635  { "get_language", &intf_get_language },
636  { nullptr, nullptr }
637  };
638 
639  lua_getglobal(L, "wesnoth");
640  if (!lua_istable(L,-1)) {
641  lua_newtable(L);
642  }
643  luaL_setfuncs(L, callbacks, 0);
644  //lua_cpp::set_functions(L, cpp_callbacks, 0);
645  lua_setglobal(L, "wesnoth");
646 
647  static luaL_Reg const wml_callbacks[]= {
648  { "load", &intf_load_wml},
649  { "parse", &intf_parse_wml},
650  { "clone", &intf_clone_wml},
651  { nullptr, nullptr },
652  };
653  lua_newtable(L);
654  luaL_setfuncs(L, wml_callbacks, 0);
655  lua_setglobal(L, "wml");
656 
657  // Override the print function
658  cmd_log_ << "Redirecting print function...\n";
659 
660  lua_getglobal(L, "print");
661  lua_setglobal(L, "std_print"); //storing original impl as 'std_print'
662  lua_settop(L, 0); //clear stack, just to be sure
663 
664  lua_pushcfunction(L, &dispatch<&lua_kernel_base::intf_print>);
665  lua_setglobal(L, "print");
666 
668  lua_setglobal(L, "load");
669  lua_pushnil(L);
670  lua_setglobal(L, "loadstring");
671 
672  cmd_log_ << "Initializing package repository...\n";
673  // Create the package table.
674  lua_getglobal(L, "wesnoth");
675  lua_newtable(L);
676  lua_setfield(L, -2, "package");
677  lua_pop(L, 1);
678  lua_settop(L, 0);
679  lua_pushstring(L, "lua/package.lua");
680  int res = intf_require(L);
681  if(res != 1) {
682  cmd_log_ << "Error: Failed to initialize package repository. Falling back to less flexible C++ implementation.\n";
683  }
684 
685  // Get some callbacks for map locations
686  cmd_log_ << "Adding map table...\n";
687 
688  static luaL_Reg const map_callbacks[] {
689  { "get_direction", &lua_map_location::intf_get_direction },
690  { "vector_sum", &lua_map_location::intf_vector_sum },
691  { "vector_diff", &lua_map_location::intf_vector_diff },
692  { "vector_negation", &lua_map_location::intf_vector_negation },
693  { "rotate_right_around_center", &lua_map_location::intf_rotate_right_around_center },
694  { "tiles_adjacent", &lua_map_location::intf_tiles_adjacent },
695  { "get_adjacent_tiles", &lua_map_location::intf_get_adjacent_tiles },
696  { "distance_between", &lua_map_location::intf_distance_between },
697  { "get_in_basis_N_NE", &lua_map_location::intf_get_in_basis_N_NE },
698  { "get_relative_dir", &lua_map_location::intf_get_relative_dir },
699  { nullptr, nullptr }
700  };
701 
702  // Create the map_location table.
703  lua_getglobal(L, "wesnoth");
704  lua_newtable(L);
705  luaL_setfuncs(L, map_callbacks, 0);
706  lua_setfield(L, -2, "map");
707  lua_pop(L, 1);
708 
709  // Create the game_config variable with its metatable.
710  cmd_log_ << "Adding game_config table...\n";
711 
712  lua_getglobal(L, "wesnoth");
713  lua_newuserdata(L, 0);
714  lua_createtable(L, 0, 3);
715  lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_get>);
716  lua_setfield(L, -2, "__index");
717  lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_set>);
718  lua_setfield(L, -2, "__newindex");
719  lua_pushstring(L, "game config");
720  lua_setfield(L, -2, "__metatable");
721  lua_setmetatable(L, -2);
722  lua_setfield(L, -2, "game_config");
723  lua_pop(L, 1);
724 
725  // Add mersenne twister rng wrapper
726  cmd_log_ << "Adding rng tables...\n";
728 
729  cmd_log_ << "Adding name generator metatable...\n";
731  static luaL_Reg const generator[] {
732  { "__call", &impl_name_generator_call},
733  { "__gc", &impl_name_generator_collect},
734  { nullptr, nullptr}
735  };
736  luaL_setfuncs(L, generator, 0);
737 
738  // Create formula bridge metatables
740 
741  // Loading ilua:
742  cmd_log_ << "Loading ilua...\n";
743 
744  lua_settop(L, 0);
745  luaW_getglobal(L, "wesnoth", "require");
746  lua_pushstring(L, "lua/ilua.lua");
747  if(protected_call(1, 1)) {
748  //run "ilua.set_strict()"
749  lua_pushstring(L, "set_strict");
750  lua_gettable(L, -2);
751  if (!this->protected_call(0,0, std::bind(&lua_kernel_base::log_error, this, _1, _2))) {
752  cmd_log_ << "Failed to activate strict mode.\n";
753  } else {
754  cmd_log_ << "Activated strict mode.\n";
755  }
756 
757  lua_setglobal(L, "ilua"); //save ilua table as a global
758  } else {
759  cmd_log_ << "Error: failed to load ilua.\n";
760  }
761  lua_settop(L, 0);
762 }
763 
765 {
766  for (const auto& pair : this->registered_widget_definitions_) {
767  gui2::remove_single_widget_definition(std::get<0>(pair), std::get<1>(pair));
768  }
769  lua_close(mState);
770 }
771 
772 void lua_kernel_base::log_error(char const * msg, char const * context)
773 {
774  ERR_LUA << context << ": " << msg << '\n';
775 }
776 
777 void lua_kernel_base::throw_exception(char const * msg, char const * context)
778 {
779  throw game::lua_error(msg, context);
780 }
781 
782 bool lua_kernel_base::protected_call(int nArgs, int nRets)
783 {
784  error_handler eh = std::bind(&lua_kernel_base::log_error, this, _1, _2 );
785  return this->protected_call(nArgs, nRets, eh);
786 }
787 
788 bool lua_kernel_base::load_string(char const * prog, const std::string& name)
789 {
790  error_handler eh = std::bind(&lua_kernel_base::log_error, this, _1, _2 );
791  return this->load_string(prog, name, eh);
792 }
793 
794 bool lua_kernel_base::protected_call(int nArgs, int nRets, error_handler e_h)
795 {
796  return this->protected_call(mState, nArgs, nRets, e_h);
797 }
798 
799 bool lua_kernel_base::protected_call(lua_State * L, int nArgs, int nRets, error_handler e_h)
800 {
801  int errcode = luaW_pcall_internal(L, nArgs, nRets);
802 
803  if (errcode != LUA_OK) {
804  char const * msg = lua_tostring(L, -1);
805 
806  std::string context = "When executing, ";
807  if (errcode == LUA_ERRRUN) {
808  context += "Lua runtime error: ";
809  } else if (errcode == LUA_ERRERR) {
810  context += "Lua error in attached debugger: ";
811  } else if (errcode == LUA_ERRMEM) {
812  context += "Lua out of memory error: ";
813  } else if (errcode == LUA_ERRGCMM) {
814  context += "Lua error in garbage collection metamethod: ";
815  } else {
816  context += "unknown lua error: ";
817  }
818  if(lua_isstring(L, -1)) {
819  context += msg ? msg : "null string";
820  } else {
821  context += lua_typename(L, lua_type(L, -1));
822  }
823 
824  lua_pop(L, 1);
825 
826  e_h(context.c_str(), "Lua Error");
827 
828  return false;
829  }
830 
831  return true;
832 }
833 
834 bool lua_kernel_base::load_string(char const * prog, const std::string& name, error_handler e_h)
835 {
836  // pass 't' to prevent loading bytecode which is unsafe and can be used to escape the sandbox.
837  // todo: maybe allow a 'name' parameter to give better error messages.
838  int errcode = luaL_loadbufferx(mState, prog, strlen(prog), name.empty() ? name.c_str() : prog, "t");
839  if (errcode != LUA_OK) {
840  char const * msg = lua_tostring(mState, -1);
841  std::string message = msg ? msg : "null string";
842 
843  std::string context = "When parsing a string to lua, ";
844 
845  if (errcode == LUA_ERRSYNTAX) {
846  context += " a syntax error";
847  } else if(errcode == LUA_ERRMEM){
848  context += " a memory error";
849  } else if(errcode == LUA_ERRGCMM) {
850  context += " an error in garbage collection metamethod";
851  } else {
852  context += " an unknown error";
853  }
854 
855  lua_pop(mState, 1);
856 
857  e_h(message.c_str(), context.c_str());
858 
859  return false;
860  }
861  return true;
862 }
863 
865 {
866  int nArgs = 0;
867  if (const config& args = cfg.child("args")) {
868  luaW_pushconfig(this->mState, args);
869  ++nArgs;
870  }
871  this->run(cfg["code"].str().c_str(), cfg["name"].str(), nArgs);
872 }
873 // Call load_string and protected call. Make them throw exceptions.
874 //
875 void lua_kernel_base::throwing_run(const char * prog, const std::string& name, int nArgs)
876 {
877  cmd_log_ << "$ " << prog << "\n";
878  error_handler eh = std::bind(&lua_kernel_base::throw_exception, this, _1, _2 );
879  this->load_string(prog, name, eh);
880  lua_insert(mState, -nArgs - 1);
881  this->protected_call(nArgs, 0, eh);
882 }
883 
884 // Do a throwing run, but if we catch a lua_error, reformat it with signature for this function and log it.
885 void lua_kernel_base::run(const char * prog, const std::string& name, int nArgs)
886 {
887  try {
888  this->throwing_run(prog, name, nArgs);
889  } catch (const game::lua_error & e) {
890  cmd_log_ << e.what() << "\n";
891  lua_kernel_base::log_error(e.what(), "In function lua_kernel::run()");
892  }
893 }
894 
895 // Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it normally. Throws exceptions.
896 void lua_kernel_base::interactive_run(char const * prog) {
897  std::string experiment = "ilua._pretty_print(";
898  experiment += prog;
899  experiment += ")";
900 
901  error_handler eh = std::bind(&lua_kernel_base::throw_exception, this, _1, _2 );
902 
903  try {
904  // Try to load the experiment without syntax errors
905  this->load_string(experiment.c_str(), "interactive", eh);
906  } catch (const game::lua_error &) {
907  this->throwing_run(prog, "interactive", 0); // Since it failed, fall back to the usual throwing_run, on the original input.
908  return;
909  }
910  // experiment succeeded, now run but log normally.
911  cmd_log_ << "$ " << prog << "\n";
912  this->protected_call(0, 0, eh);
913 }
914 /**
915  * Loads and executes a Lua file.
916  * - Arg 1: string containing the file name.
917  * - Ret *: values returned by executing the file body.
918  */
920 {
921  luaL_checkstring(L, 1);
922  lua_rotate(L, 1, -1);
923  if (lua_fileops::load_file(L) != 1) return 0;
924  //^ should end with the file contents loaded on the stack. actually it will call lua_error otherwise, the return 0 is redundant.
925  lua_rotate(L, 1, 1);
926  // Using a non-protected call here appears to fix an issue in plugins.
927  // The protected call isn't technically necessary anyway, because this function is called from Lua code,
928  // which should already be in a protected environment.
929  lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
930  return lua_gettop(L);
931 }
932 
933 /**
934  * Loads and executes a Lua file, if there is no corresponding entry in wesnoth.package.
935  * Stores the result of the script in wesnoth.package and returns it.
936  * - Arg 1: string containing the file name.
937  * - Ret 1: value returned by the script.
938  */
940 {
941  const char * m = luaL_checkstring(L, 1);
942  if(!m) {
943  return luaL_argerror(L, 1, "found a null string argument to wesnoth require");
944  }
945 
946  // Check if there is already an entry.
947 
948  lua_getglobal(L, "wesnoth");
949  lua_pushstring(L, "package");
950  lua_rawget(L, -2);
951  lua_pushvalue(L, 1);
952  lua_rawget(L, -2);
953  if(!lua_isnil(L, -1) && !game_config::debug_lua) {
954  return 1;
955  }
956  lua_pop(L, 1);
957  lua_pushvalue(L, 1);
958  // stack is now [packagename] [wesnoth] [package] [packagename]
959 
960  if(lua_fileops::load_file(L) != 1) {
961  // should end with the file contents loaded on the stack. actually it will call lua_error otherwise, the return 0 is redundant.
962  // stack is now [packagename] [wesnoth] [package] [chunk]
963  return 0;
964  }
965  DBG_LUA << "require: loaded a file, now calling it\n";
966 
967  if (!this->protected_call(L, 0, 1, std::bind(&lua_kernel_base::log_error, this, _1, _2))) {
968  // historically if wesnoth.require fails it just yields nil and some logging messages, not a lua error
969  return 0;
970  }
971  // stack is now [packagename] [wesnoth] [package] [results]
972 
973  lua_pushvalue(L, 1);
974  lua_pushvalue(L, -2);
975  // stack is now [packagename] [wesnoth] [package] [results] [packagename] [results]
976  // Add the return value to the table.
977 
978  lua_settable(L, -4);
979  // stack is now [packagename] [wesnoth] [package] [results]
980  return 1;
981 }
983 {
984  lua_push(L, my_name());
985  return 1;
986 }
988 {
989  char const *m = luaL_checkstring(L, 2);
1002  return 0;
1003 }
1005 {
1006  std::string err_msg = "unknown modifiable property of game_config: ";
1007  err_msg += luaL_checkstring(L, 2);
1008  return luaL_argerror(L, 2, err_msg.c_str());
1009 }
1010 /**
1011  * Loads the "package" package into the Lua environment.
1012  * This action is inherently unsafe, as Lua scripts will now be able to
1013  * load C libraries on their own, hence granting them the same privileges
1014  * as the Wesnoth binary itself.
1015  */
1017 {
1018  lua_State *L = mState;
1020  lua_pushstring(L, "package");
1021  lua_call(L, 1, 0);
1022 }
1023 
1025 {
1026  lua_State* L = mState;
1027  lua_settop(L, 0);
1028  cmd_log_ << "Loading core...\n";
1029  luaW_getglobal(L, "wesnoth", "require");
1030  lua_pushstring(L, "lua/core.lua");
1031  if(!protected_call(1, 1)) {
1032  cmd_log_ << "Error: Failed to load core.\n";
1033  }
1034  lua_settop(L, 0);
1035 }
1036 
1037 /**
1038  * Gets all the global variable names in the Lua environment. This is useful for tab completion.
1039  */
1040 std::vector<std::string> lua_kernel_base::get_global_var_names()
1041 {
1042  std::vector<std::string> ret;
1043 
1044  lua_State *L = mState;
1045 
1046  int idx = lua_gettop(L);
1047  lua_getglobal(L, "_G");
1048  lua_pushnil(L);
1049 
1050  while (lua_next(L, idx+1) != 0) {
1051  if (lua_isstring(L, -2)) {
1052  ret.push_back(lua_tostring(L,-2));
1053  }
1054  lua_pop(L,1);
1055  }
1056  lua_settop(L, idx);
1057  return ret;
1058 }
1059 
1060 /**
1061  * Gets all attribute names of an extended variable name. This is useful for tab completion.
1062  */
1063 std::vector<std::string> lua_kernel_base::get_attribute_names(const std::string & input)
1064 {
1065  std::vector<std::string> ret;
1066  std::string base_path = input;
1067  std::size_t last_dot = base_path.find_last_of('.');
1068  std::string partial_name = base_path.substr(last_dot + 1);
1069  base_path.erase(last_dot);
1070  std::string load = "return " + base_path;
1071 
1072  lua_State* L = mState;
1073  int save_stack = lua_gettop(L);
1074  int result = luaL_loadstring(L, load.c_str());
1075  if(result != LUA_OK) {
1076  // 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.
1077  LOG_LUA << "Error when attempting tab completion:\n";
1078  LOG_LUA << luaL_checkstring(L, -1) << '\n';
1079  // Just return an empty list; no matches were found
1080  lua_settop(L, save_stack);
1081  return ret;
1082  }
1083 
1084  luaW_pcall(L, 0, 1);
1085  if(lua_istable(L, -1) || lua_isuserdata(L, -1)) {
1086  int top = lua_gettop(L);
1087  int obj = lua_absindex(L, -1);
1088  if(luaL_getmetafield(L, obj, "__tab_enum") == LUA_TFUNCTION) {
1089  lua_pushvalue(L, obj);
1090  lua_pushlstring(L, partial_name.c_str(), partial_name.size());
1091  luaW_pcall(L, 2, 1);
1092  ret = lua_check<std::vector<std::string>>(L, -1);
1093  } else if(lua_type(L, -1) != LUA_TTABLE) {
1094  LOG_LUA << "Userdata missing __tab_enum meta-function for tab completion";
1095  lua_settop(L, save_stack);
1096  return ret;
1097  } else {
1098  lua_settop(L, top);
1099  // Metafunction not found, so use lua_next to enumerate the table
1100  for(lua_pushnil(L); lua_next(L, obj); lua_pop(L, 1)) {
1101  if(lua_type(L, -2) == LUA_TSTRING) {
1102  std::string attr = lua_tostring(L, -2);
1103  if(attr.empty()) {
1104  continue;
1105  }
1106  if(!isalpha(attr[0]) && attr[0] != '_') {
1107  continue;
1108  }
1109  if(std::any_of(attr.begin(), attr.end(), [](char c){
1110  return !isalpha(c) && !isdigit(c) && c != '_';
1111  })) {
1112  continue;
1113  }
1114  if(attr.substr(0, partial_name.size()) == partial_name) {
1115  ret.push_back(base_path + "." + attr);
1116  }
1117  }
1118  }
1119  }
1120  }
1121  lua_settop(L, save_stack);
1122  return ret;
1123 }
1124 
1126 {
1127  #ifdef __GNUC__
1128  #pragma GCC diagnostic push
1129  #pragma GCC diagnostic ignored "-Wold-style-cast"
1130  #endif
1131  return *reinterpret_cast<lua_kernel_base**>(lua_getextraspace(L));
1132  #ifdef __GNUC__
1133  #pragma GCC diagnostic pop
1134  #endif
1135 }
1136 
1138 {
1139  return seed_rng::next_seed();
1140 }
int dispatch(lua_State *L)
int intf_set_dialog_active(lua_State *L)
Sets a widget&#39;s state to active or inactive.
Definition: lua_gui2.cpp:857
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:971
#define lua_isnoneornil(L, n)
Definition: lua.h:359
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: picture.cpp:875
static int intf_name_generator(lua_State *L)
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:684
#define lua_pushcfunction(L, f)
Definition: lua.h:350
int show_lua_console(lua_State *, lua_kernel_base *lk)
Definition: lua_gui2.cpp:922
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:420
bool matches(const config &filter) const
Definition: config.cpp:1229
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
Definition: lua_common.cpp:419
std::string format_conjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a conjunctive list.
int intf_add_dialog_tree_node(lua_State *L)
Sets a widget&#39;s state to active or inactive.
Definition: lua_gui2.cpp:942
int intf_read_file(lua_State *L)
Reads a file into a string, or a directory into a list of files therein.
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with &#39;$&#39; in the string &#39;str&#39; with the equivalent ...
static int intf_clone_wml(lua_State *L)
Returns a clone (deep copy) of the passed config, which can be either a normal config or a vconfig If...
LUALIB_API lua_State * luaL_newstate(void)
Definition: lauxlib.cpp:1026
LUAMOD_API int luaopen_debug(lua_State *L)
Definition: ldblib.cpp:452
int show_story(lua_State *L)
Displays a story screen.
Definition: lua_gui2.cpp:377
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:712
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:172
#define lua_isnone(L, n)
Definition: lua.h:358
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:251
int village_support
Definition: game_config.cpp:55
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.
static int intf_format(lua_State *L)
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.
#define LUA_TUSERDATA
Definition: lua.h:71
LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
Definition: lauxlib.cpp:764
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:557
VERSION_COMP_OP parse_version_op(const std::string &op_str)
#define LUA_MULTRET
Definition: lua.h:34
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:90
std::string generate(const std::map< std::string, std::string > &variables) const
static int intf_format_list(lua_State *L)
int show_dialog(lua_State *L)
Displays a window.
Definition: lua_gui2.cpp:234
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:772
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:167
LUA_API int lua_gettable(lua_State *L, int idx)
Definition: lapi.cpp:612
LUAMOD_API int luaopen_math(lua_State *L)
Definition: lmathlib.cpp:398
LUA_API int lua_getglobal(lua_State *L, const char *name)
Definition: lapi.cpp:605
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition: config.cpp:742
LUA_API void lua_settable(lua_State *L, int idx)
Definition: lapi.cpp:766
#define return_string_attrib(name, accessor)
Definition: lua_common.hpp:217
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:83
#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:647
std::string format_disjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a disjunctive list.
#define luaL_getmetatable(L, n)
Definition: lauxlib.h:135
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:440
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
#define lua_tonumber(L, i)
Definition: lua.h:341
#define LUA_TFUNCTION
Definition: lua.h:70
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:289
int show_message_dialog(lua_State *L)
Displays a message window.
Definition: lua_gui2.cpp:265
int intf_remove_dialog_item(lua_State *L)
Removes an entry from a list.
Definition: lua_gui2.cpp:691
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:371
static int intf_wml_tostring(lua_State *L)
Dumps a wml table or userdata wml object into a pretty string.
int intf_set_dialog_markup(lua_State *L)
Enables/disables Pango markup on the label of a widget of the current dialog.
Definition: lua_gui2.cpp:802
#define LOG_STREAM(level, domain)
Definition: log.hpp:189
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)
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:160
int intf_add_widget_definition(lua_State *L)
Definition: lua_gui2.cpp:967
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
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:486
int rest_heal_amount
Definition: game_config.cpp:61
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1184
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:344
int intf_set_dialog_focus(lua_State *L)
Sets a widget to have the focus.
Definition: lua_gui2.cpp:845
int intf_rotate_right_around_center(lua_State *L)
Expose map_location::rotate_right_around_center to lua.
lua_CFunction func
Definition: lauxlib.h:33
int intf_eval_formula(lua_State *)
Evaluates a formula in the formula engine.
One of the realizations of serialization/validator.hpp abstract validator.
static const char * name(const std::vector< SDL_Joystick *> &joysticks, const std::size_t index)
Definition: joystick.cpp:48
int intf_get_relative_dir(lua_State *L)
Expose map_location get_relative_dir.
#define LUA_TSTRING
Definition: lua.h:68
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Definition: parser.cpp:762
LUAMOD_API int luaopen_coroutine(lua_State *L)
Definition: lcorolib.cpp:164
LUALIB_API int luaL_argerror(lua_State *L, int arg, const char *extramsg)
Definition: lauxlib.cpp:164
LUAMOD_API int luaopen_os(lua_State *L)
Definition: loslib.cpp:405
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:226
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:851
LUAMOD_API int luaopen_string(lua_State *L)
Definition: lstrlib.cpp:1579
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:283
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:870
static int intf_get_language(lua_State *L)
void read(config &cfg, std::istream &in, abstract_validator *validator)
Definition: parser.cpp:625
LUALIB_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t size, const char *name, const char *mode)
Definition: lauxlib.cpp:755
int intf_show_lua_console(lua_State *L)
static lg::log_domain log_user("scripting/lua/user")
virtual ~name_generator()
LUAMOD_API int luaopen_table(lua_State *L)
Definition: ltablib.cpp:441
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:602
static int intf_deprecated_message(lua_State *L)
Logs a deprecation message.
LUAMOD_API int luaopen_package(lua_State *L)
Definition: loadlib.cpp:767
void load_package()
Loads the package library into lua environment.
LUA_API void lua_close(lua_State *L)
Definition: lstate.cpp:341
bool protected_call(int nArgs, int nRets, error_handler)
int intf_set_dialog_tooltip(lua_State *L)
Sets the value of a widget on the current dialog.
Definition: lua_gui2.cpp:582
#define lua_getextraspace(L)
Definition: lua.h:339
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:479
std::unique_ptr< std::istream > scoped_istream
Definition: filesystem.hpp:39
int kill_experience
Definition: game_config.cpp:57
static int intf_parse_wml(lua_State *L)
Parses a WML string into a config; does not preprocess or validate.
LUA_API void lua_setglobal(lua_State *L, const char *name)
Definition: lapi.cpp:759
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:846
int show_menu(lua_State *L)
Displays a popup menu at the current mouse position Best used from a [set_menu_item], to show a submenu.
Definition: lua_gui2.cpp:390
static int impl_name_generator_collect(lua_State *L)
const char * what() const noexcept
Definition: exceptions.hpp:37
int intf_compile_formula(lua_State *)
int(lua_kernel_base::* member_callback)(lua_State *L)
int intf_set_dialog_canvas(lua_State *L)
Sets a canvas on a widget of the current dialog.
Definition: lua_gui2.cpp:821
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
Definition: lua_common.cpp:994
#define lua_newtable(L)
Definition: lua.h:346
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:450
LUA_API const char * lua_setupvalue(lua_State *L, int funcindex, int n)
Definition: lapi.cpp:1236
int intf_tiles_adjacent(lua_State *L)
Expose map_location tiles_adjacent.
LUA_API void lua_len(lua_State *L, int idx)
Definition: lapi.cpp:1156
LUAMOD_API int() luaopen_utf8(lua_State *L)
Definition: lutf8lib.cpp:250
virtual int impl_game_config_get(lua_State *L)
#define LUA_ERRGCMM
Definition: lua.h:52
int show_popup_dialog(lua_State *L)
Displays a popup message.
Definition: lua_gui2.cpp:363
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:299
LUA_API void * lua_touserdata(lua_State *L, int idx)
Definition: lapi.cpp:413
#define LUA_ERRERR
Definition: lua.h:53
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:355
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:933
int intf_set_dialog_value(lua_State *L)
Sets the value of a widget on the current dialog.
Definition: lua_gui2.cpp:453
logger & err()
Definition: log.cpp:78
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int arg)
Definition: lauxlib.cpp:430
std::string get_wml_location(const std::string &filename, const std::string &current_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn&#39;t pres...
std::string register_metatables(lua_State *)
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
Definition: lua_common.cpp:400
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:799
int village_income
Definition: game_config.cpp:54
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:261
virtual uint32_t get_random_seed()
#define LUA_ERRSYNTAX
Definition: lua.h:50
#define lua_tostring(L, i)
Definition: lua.h:366
static int intf_get_time_stamp(lua_State *L)
Returns the time stamp, exactly as [set_variable] time=stamp does.
static int intf_load_wml(lua_State *L)
Loads a WML file into a config.
static int intf_compare_versions(lua_State *L)
Compares 2 version strings - which is newer.
LUA_API void lua_rotate(lua_State *L, int idx, int n)
Definition: lapi.cpp:207
int combat_experience
Definition: game_config.cpp:58
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:237
const bool & debug
#define debug(x)
#define LUA_ERRMEM
Definition: lua.h:51
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:276
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:274
int intf_set_dialog_callback(lua_State *L)
Sets a callback on a widget of the current dialog.
Definition: lua_gui2.cpp:751
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 return_bool_attrib(name, accessor)
Definition: lua_common.hpp:242
static int impl_name_generator_call(lua_State *L)
uint32_t next_seed()
Definition: seed_rng.cpp:45
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1114
logger & warn()
Definition: log.cpp:84
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:47
#define lua_istable(L, n)
Definition: lua.h:353
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")
static int intf_wml_matches_filter(lua_State *L)
#define lua_insert(L, idx)
Definition: lua.h:369
void luaW_pushvconfig(lua_State *L, const vconfig &cfg)
Pushes a vconfig on the top of the stack.
Definition: lua_common.cpp:509
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
const config & get_config() const
Definition: variable.hpp:75
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
LUA_API int lua_geti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:628
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.
std::map< std::string, struct preproc_define > preproc_map
#define e
Realization of serialization/validator.hpp abstract validator.
int intf_get_dialog_value(lua_State *L)
Gets the value of a widget on the current dialog.
Definition: lua_gui2.cpp:600
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
Definition: lauxlib.cpp:934
void push_error_handler(lua_State *L)
Definition: lua_common.cpp:988
int show_message_box(lua_State *L)
Displays a simple message box.
Definition: lua_gui2.cpp:416
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
int intf_dofile(lua_State *L)
Loads and executes a Lua file.
mock_char c
int intf_tovconfig(lua_State *L)
Creates a vconfig containing the WML table.
Definition: lua_common.cpp:390
lua_State * mState
static int intf_load(lua_State *L)
Replacement load function.
t_string interpolate_variables_into_tstring(const t_string &tstr, const variable_set &variables)
Function that does the same as the above, for t_stringS.
#define LUA_TTABLE
Definition: lua.h:69
static map_location::DIRECTION n
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:466
void throwing_run(char const *prog, const std::string &name, int nArgs)
Runs a plain script, but reports errors by throwing lua_error.
#define luaL_optstring(L, n, d)
Definition: lauxlib.h:125
bool file_exists() const
Tests whether the file the locater points at exists.
Definition: picture.cpp:668
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 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:491
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:777
#define LUA_ERRRUN
Definition: lua.h:49
#define LUA_TBOOLEAN
Definition: lua.h:65
int intf_set_dialog_visible(lua_State *L)
Sets the visiblity of a widget in the current dialog.
Definition: lua_gui2.cpp:875
LUA_API int lua_next(lua_State *L, int idx)
Definition: lapi.cpp:1123
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:257
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:124
Error used to report an error in a lua script or in the lua interpreter.
Definition: game_errors.hpp:53