The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
lua_kernel_base.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2016 by Chris Beck <[email protected]>
3  Part of the Battle for Wesnoth Project http://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 "global.hpp"
18 
19 #include "exceptions.hpp"
20 #include "game_config.hpp"
21 #include "game_errors.hpp"
22 #include "log.hpp"
23 #include "lua_jailbreak_exception.hpp" // for tlua_jailbreak_exception
24 #include "seed_rng.hpp"
25 
26 #ifdef DEBUG_LUA
27 #include "scripting/debug_lua.hpp"
28 #endif
29 
30 #include "scripting/lua_common.hpp"
34 #include "scripting/lua_gui2.hpp"
36 #include "scripting/lua_rng.hpp"
37 #include "scripting/lua_types.hpp"
38 #include "scripting/push_check.hpp"
39 
40 #include "version.hpp" // for do_version_check, etc
41 
43 #include "utils/functional.hpp"
46 #include <boost/scoped_ptr.hpp>
47 
48 #include <cstring>
49 #include <exception>
50 #include <new>
51 #include <string>
52 #include <sstream>
53 #include <vector>
54 
55 #include "lua/lauxlib.h"
56 #include "lua/lua.h"
57 #include "lua/lualib.h"
58 
59 static lg::log_domain log_scripting_lua("scripting/lua");
60 #define DBG_LUA LOG_STREAM(debug, log_scripting_lua)
61 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
62 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
63 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
64 
65 // Registry key for metatable
66 static const char * Gen = "name generator";
67 
68 // Callback implementations
69 
70 /**
71  * Compares 2 version strings - which is newer.
72  * - Args 1,3: version strings
73  * - Arg 2: comparison operator (string)
74  * - Ret 1: comparison result
75  */
77 {
78  char const *v1 = luaL_checkstring(L, 1);
79 
81  if(vop == OP_INVALID) return luaL_argerror(L, 2, "unknown version comparison operator - allowed are ==, !=, <, <=, > and >=");
82 
83  char const *v2 = luaL_checkstring(L, 3);
84 
85  const bool result = do_version_check(version_info(v1), vop, version_info(v2));
86  lua_pushboolean(L, result);
87 
88  return 1;
89 }
90 
91 /**
92  * Replacement print function -- instead of printing to std::cout, print to the command log.
93  * Intended to be bound to this' command_log at registration time.
94  */
96 {
97  DBG_LUA << "intf_print called:\n";
98  size_t nargs = lua_gettop(L);
99 
100  for (size_t i = 1; i <= nargs; ++i) {
101  const char * str = lua_tostring(L,i);
102  if (!str) {
103  str = "";
104  }
105  if (i > 1) {
106  cmd_log_ << "\t"; //separate multiple args with tab character
107  }
108  cmd_log_ << str;
109  DBG_LUA << "'" << str << "'\n";
110  }
111 
112  cmd_log_ << "\n";
113  DBG_LUA << "\n";
114 
115  return 0;
116 }
117 
118 // The show-dialog call back is here implemented as a method of lua kernel, since it needs a pointer to external object CVideo
120 {
121  if (!video_) {
122  ERR_LUA << "Cannot show dialog, no video object is available to this lua kernel.";
123  lua_error(L);
124  return 0;
125  }
126 
127  return lua_gui2::show_dialog(L, *video_);
128 }
129 
131 {
132  if (!video_) {
133  ERR_LUA << "Cannot show dialog, no video object is available to this lua kernel.";
134  lua_error(L);
135  return 0;
136  }
137 
139 }
140 
142 {
143  if (!video_) {
144  ERR_LUA << "Cannot show dialog, no video object is available to this lua kernel.";
145  lua_error(L);
146  return 0;
147  }
148 
150 }
151 
152 // The show lua console callback is similarly a method of lua kernel
154 {
155  if (!video_) {
156  ERR_LUA << "Cannot show dialog, no video object is available to this lua kernel.";
157  lua_error(L);
158  return 0;
159  }
160 
161  if (cmd_log_.external_log_ != nullptr) {
162  std::string message = "There is already an external logger attached to this lua kernel, you cannot open the lua console right now.";
163  log_error(message.c_str());
164  cmd_log_ << message << "\n";
165  return 0;
166  }
167 
168  return lua_gui2::show_lua_console(L, *video_, this);
169 }
170 
172 {
173  name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
174  lua_pushstring(L, gen->generate().c_str());
175  return 1;
176 }
177 
179 {
180  name_generator* gen = static_cast<name_generator*>(lua_touserdata(L, 1));
181  gen->~name_generator();
182  return 0;
183 }
184 
186 {
188  name_generator* gen = nullptr;
189  if(type == "markov" || type == "markov_chain") {
190  std::vector<std::string> input;
191  if(lua_istable(L, 2)) {
192  input = lua_check<std::vector<std::string>>(L, 2);
193  } else {
194  input = utils::parenthetical_split(luaL_checkstring(L, 2), ',');
195  }
196  int chain_sz = luaL_optinteger(L, 3, 2);
197  int max_len = luaL_optinteger(L, 4, 12);
198  gen = new(lua_newuserdata(L, sizeof(markov_generator))) markov_generator(input, chain_sz, max_len);
199  // Ensure the pointer didn't change when cast
200  assert(static_cast<void*>(gen) == dynamic_cast<markov_generator*>(gen));
201  } else if(type == "context_free" || type == "cfg" || type == "CFG") {
203  if(lua_istable(L, 2)) {
204  std::map<std::string, std::vector<std::string>> data;
205  for(lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
206  if(!lua_isstring(L, -2)) {
207  lua_pushstring(L, "CFG generator: invalid nonterminal name (must be a string)");
208  return lua_error(L);
209  }
210  if(lua_isstring(L, -1)) {
211  data[lua_tostring(L,-2)] = utils::split(lua_tostring(L,-1),'|');
212  } else if(lua_istable(L, -1)) {
213  data[lua_tostring(L,-2)] = lua_check<std::vector<std::string>>(L, -1);
214  } else {
215  lua_pushstring(L, "CFG generator: invalid noterminal value (must be a string or list of strings)");
216  return lua_error(L);
217  }
218  }
219  if(!data.empty()) {
220  gen = new(buf) context_free_grammar_generator(data);
221  }
222  } else {
224  }
225  if(gen) {
226  assert(static_cast<void*>(gen) == dynamic_cast<context_free_grammar_generator*>(gen));
227  }
228  } else {
229  return luaL_argerror(L, 1, "should be either 'markov_chain' or 'context_free'");
230  }
231  static const char*const generic_err = "error initializing name generator";
232  if(!gen) {
233  lua_pushstring(L, generic_err);
234  return lua_error(L);
235  }
236  // We set the metatable now, even if the generator is invalid, so that it
237  // will be properly collected if it was invalid.
239  lua_setmetatable(L, -2);
240  if(!gen->is_valid()) {
241  lua_pushstring(L, generic_err);
242  return lua_error(L);
243  }
244  return 1;
245 }
246 
247 // End Callback implementations
248 
249 // Template which allows to push member functions to the lua kernel base into lua as C functions, using a shim
251 
252 template <member_callback method>
254  return ((lua_kernel_base::get_lua_kernel<lua_kernel_base>(L)).*method)(L);
255 }
256 
257 // Ctor, initialization
259  : mState(luaL_newstate())
260  , video_(video)
261  , cmd_log_()
262 {
264  lua_State *L = mState;
265 
266  cmd_log_ << "Initializing " << my_name() << "...\n";
267 
268  // Open safe libraries.
269  // Debug and OS are not, but most of their functions will be disabled below.
270  cmd_log_ << "Adding standard libs...\n";
271 
272  static const luaL_Reg safe_libs[] = {
273  { "", luaopen_base },
274  { "table", luaopen_table },
275  { "string", luaopen_string },
276  { "math", luaopen_math },
277  { "coroutine", luaopen_coroutine },
278  { "debug", luaopen_debug },
279  { "os", luaopen_os },
280  { "bit32", luaopen_bit32 }, // added in Lua 5.2
281  { nullptr, nullptr }
282  };
283  for (luaL_Reg const *lib = safe_libs; lib->func; ++lib)
284  {
285  luaL_requiref(L, lib->name, lib->func, 1);
286  lua_pop(L, 1); /* remove lib */
287  }
288 
289  // Disable functions from os which we don't want.
290  lua_getglobal(L, "os");
291  lua_pushnil(L);
292  while(lua_next(L, -2) != 0) {
293  lua_pop(L, 1);
294  char const* function = lua_tostring(L, -1);
295  if(strcmp(function, "clock") == 0 || strcmp(function, "date") == 0
296  || strcmp(function, "time") == 0 || strcmp(function, "difftime") == 0) continue;
297  lua_pushnil(L);
298  lua_setfield(L, -3, function);
299  }
300  lua_pop(L, 1);
301 
302  // Disable functions from debug which we don't want.
303  lua_getglobal(L, "debug");
304  lua_pushnil(L);
305  while(lua_next(L, -2) != 0) {
306  lua_pop(L, 1);
307  char const* function = lua_tostring(L, -1);
308  if(strcmp(function, "traceback") == 0 || strcmp(function, "getinfo") == 0) continue; //traceback is needed for our error handler
309  lua_pushnil(L); //getinfo is needed for ilua strict mode
310  lua_setfield(L, -3, function);
311  }
312  lua_pop(L, 1);
313 
314  // Delete dofile and loadfile.
315  lua_pushnil(L);
316  lua_setglobal(L, "dofile");
317  lua_pushnil(L);
318  lua_setglobal(L, "loadfile");
319 
320  // Store the error handler.
321  cmd_log_ << "Adding error handler...\n";
322 
324  , executeKey);
325  lua_getglobal(L, "debug");
326  lua_getfield(L, -1, "traceback");
327  lua_remove(L, -2);
329  lua_pop(L, 1);
330 
331  // Create the gettext metatable.
333 
334  // Create the tstring metatable.
336 
337 
338  lua_settop(L, 0);
339 
340  // Define the CPP_function metatable ( so we can override print to point to a C++ member function, add "show_dialog" for this kernel, etc. )
341  cmd_log_ << "Adding boost function proxy...\n";
342 
344 
345  // Add some callback from the wesnoth lib
346  cmd_log_ << "Registering basic wesnoth API...\n";
347 
348  static luaL_Reg const callbacks[] = {
349  { "compare_versions", &intf_compare_versions },
350  { "have_file", &lua_fileops::intf_have_file },
351  { "read_file", &lua_fileops::intf_read_file },
352  { "textdomain", &lua_common::intf_textdomain },
353  { "tovconfig", &lua_common::intf_tovconfig },
354  { "get_dialog_value", &lua_gui2::intf_get_dialog_value },
355  { "set_dialog_active", &lua_gui2::intf_set_dialog_active },
356  { "set_dialog_visible", &lua_gui2::intf_set_dialog_visible },
357  { "add_dialog_tree_node", &lua_gui2::intf_add_dialog_tree_node },
358  { "set_dialog_callback", &lua_gui2::intf_set_dialog_callback },
359  { "set_dialog_canvas", &lua_gui2::intf_set_dialog_canvas },
360  { "set_dialog_focus", &lua_gui2::intf_set_dialog_focus },
361  { "set_dialog_markup", &lua_gui2::intf_set_dialog_markup },
362  { "set_dialog_value", &lua_gui2::intf_set_dialog_value },
363  { "remove_dialog_item", &lua_gui2::intf_remove_dialog_item },
364  { "dofile", &dispatch<&lua_kernel_base::intf_dofile> },
365  { "require", &dispatch<&lua_kernel_base::intf_require> },
366  { "show_dialog", &dispatch<&lua_kernel_base::intf_show_dialog> },
367  { "show_message_dialog", &dispatch<&lua_kernel_base::intf_show_message_dialog> },
368  { "show_popup_dialog", &dispatch<&lua_kernel_base::intf_show_popup_dialog> },
369  { "show_lua_console", &dispatch<&lua_kernel_base::intf_show_lua_console> },
370  { "compile_formula", &lua_formula_bridge::intf_compile_formula},
371  { "eval_formula", &lua_formula_bridge::intf_eval_formula},
372  { "name_generator", &intf_name_generator },
373  { nullptr, nullptr }
374  };
375 
376 /*
377  lua_cpp::Reg const cpp_callbacks[] = {
378  { "dofile", std::bind(&lua_kernel_base::intf_dofile, this, _1)},
379  { "require", std::bind(&lua_kernel_base::intf_require, this, _1)},
380  { "show_dialog", std::bind(&lua_kernel_base::intf_show_dialog, this, _1)},
381  { "show_lua_console", std::bind(&lua_kernel_base::intf_show_lua_console, this, _1)},
382  };
383 */
384 
385  lua_getglobal(L, "wesnoth");
386  if (!lua_istable(L,-1)) {
387  lua_newtable(L);
388  }
389  luaL_setfuncs(L, callbacks, 0);
390  //lua_cpp::set_functions(L, cpp_callbacks, 0);
391  lua_setglobal(L, "wesnoth");
392 
393  // Override the print function
394  cmd_log_ << "Redirecting print function...\n";
395 
396  lua_getglobal(L, "print");
397  lua_setglobal(L, "std_print"); //storing original impl as 'std_print'
398  lua_settop(L, 0); //clear stack, just to be sure
399 
400  lua_pushcfunction(L, &dispatch<&lua_kernel_base::intf_print>);
401  lua_setglobal(L, "print");
402 
403  // Create the package table.
404  lua_getglobal(L, "wesnoth");
405  lua_newtable(L);
406  lua_setfield(L, -2, "package");
407  lua_pop(L, 1);
408 
409  // Get some callbacks for map locations
410  cmd_log_ << "Adding map_location table...\n";
411 
412  static luaL_Reg const map_callbacks[] = {
413  { "get_direction", &lua_map_location::intf_get_direction },
414  { "vector_sum", &lua_map_location::intf_vector_sum },
415  { "vector_negation", &lua_map_location::intf_vector_negation },
417  { "rotate_right_around_center", &lua_map_location::intf_rotate_right_around_center },
418  { "tiles_adjacent", &lua_map_location::intf_tiles_adjacent },
419  { "get_adjacent_tiles", &lua_map_location::intf_get_adjacent_tiles },
420  { "distance_between", &lua_map_location::intf_distance_between },
421  { "get_in_basis_N_NE", &lua_map_location::intf_get_in_basis_N_NE },
422  { "get_relative_dir", &lua_map_location::intf_get_relative_dir },
423  { "parse_direction", &lua_map_location::intf_parse_direction },
424  { "write_direction", &lua_map_location::intf_write_direction },
425  { nullptr, nullptr }
426  };
427 
428  // Create the map_location table.
429  lua_getglobal(L, "wesnoth");
430  lua_newtable(L);
431  luaL_setfuncs(L, map_callbacks, 0);
432  lua_setfield(L, -2, "map_location");
433  lua_pop(L,1);
434 
435  // Add mersenne twister rng wrapper
436  cmd_log_ << "Adding rng tables...\n";
438 
439  cmd_log_ << "Adding name generator metatable...\n";
441  static luaL_Reg const generator[] = {
442  { "__call", &impl_name_generator_call},
443  { "__gc", &impl_name_generator_collect},
444  { nullptr, nullptr}
445  };
446  luaL_setfuncs(L, generator, 0);
447 
448  // Create formula bridge metatables
450 
451  // Loading ilua:
452  cmd_log_ << "Loading ilua...\n";
453 
454  lua_settop(L, 0);
455  lua_pushstring(L, "lua/ilua.lua");
456  int result = intf_require(L);
457  if (result == 1) {
458  //run "ilua.set_strict()"
459  lua_pushstring(L, "set_strict");
460  lua_gettable(L, -2);
461  if (!protected_call(0,0, std::bind(&lua_kernel_base::log_error, this, _1, _2))) {
462  cmd_log_ << "Failed to activate strict mode.\n";
463  } else {
464  cmd_log_ << "Activated strict mode.\n";
465  }
466 
467  lua_setglobal(L, "ilua"); //save ilua table as a global
468  } else {
469  cmd_log_ << "Error: failed to load ilua.\n";
470  }
471  lua_settop(L, 0);
472 }
473 
475 {
476  lua_close(mState);
477 }
478 
479 void lua_kernel_base::log_error(char const * msg, char const * context)
480 {
481  ERR_LUA << context << ": " << msg;
482 }
483 
484 void lua_kernel_base::throw_exception(char const * msg, char const * context)
485 {
486  throw game::lua_error(msg, context);
487 }
488 
489 bool lua_kernel_base::protected_call(int nArgs, int nRets)
490 {
491  error_handler eh = std::bind(&lua_kernel_base::log_error, this, _1, _2 );
492  return protected_call(nArgs, nRets, eh);
493 }
494 
495 bool lua_kernel_base::load_string(char const * prog)
496 {
497  error_handler eh = std::bind(&lua_kernel_base::log_error, this, _1, _2 );
498  return load_string(prog, eh);
499 }
500 
501 bool lua_kernel_base::protected_call(int nArgs, int nRets, error_handler e_h)
502 {
503  return protected_call(mState, nArgs, nRets, e_h);
504 }
505 
506 bool lua_kernel_base::protected_call(lua_State * L, int nArgs, int nRets, error_handler e_h)
507 {
508  // Load the error handler before the function and its arguments.
510  , executeKey);
511 
513  lua_insert(L, -2 - nArgs);
514 
515  int error_handler_index = lua_gettop(L) - nArgs - 1;
516 
517  // Call the function.
518  int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
520 
521  // Remove the error handler.
522  lua_remove(L, error_handler_index);
523 
524  if (errcode != LUA_OK) {
525  char const * msg = lua_tostring(L, -1);
526  std::string message = msg ? msg : "null string";
527 
528  std::string context = "When executing, ";
529  if (errcode == LUA_ERRRUN) {
530  context += "Lua runtime error";
531  } else if (errcode == LUA_ERRERR) {
532  context += "Lua error in attached debugger";
533  } else if (errcode == LUA_ERRMEM) {
534  context += "Lua out of memory error";
535  } else if (errcode == LUA_ERRGCMM) {
536  context += "Lua error in garbage collection metamethod";
537  } else {
538  context += "unknown lua error";
539  }
540 
541  lua_pop(L, 1);
542 
543  e_h(message.c_str(), context.c_str());
544 
545  return false;
546  }
547 
548  return true;
549 }
550 
551 bool lua_kernel_base::load_string(char const * prog, error_handler e_h)
552 {
553  int errcode = luaL_loadstring(mState, prog);
554  if (errcode != LUA_OK) {
555  char const * msg = lua_tostring(mState, -1);
556  std::string message = msg ? msg : "null string";
557 
558  std::string context = "When parsing a string to lua, ";
559 
560  if (errcode == LUA_ERRSYNTAX) {
561  context += " a syntax error";
562  } else if(errcode == LUA_ERRMEM){
563  context += " a memory error";
564  } else if(errcode == LUA_ERRGCMM) {
565  context += " an error in garbage collection metamethod";
566  } else {
567  context += " an unknown error";
568  }
569 
570  lua_pop(mState, 1);
571 
572  e_h(message.c_str(), context.c_str());
573 
574  return false;
575  }
576  return true;
577 }
578 
580 {
581  int nArgs = 0;
582  if (const config& args = cfg.child("args")) {
583  luaW_pushconfig(this->mState, args);
584  ++nArgs;
585  }
586  run(cfg["code"].str().c_str(), nArgs);
587 }
588 // Call load_string and protected call. Make them throw exceptions.
589 //
590 void lua_kernel_base::throwing_run(const char * prog, int nArgs)
591 {
592  cmd_log_ << "$ " << prog << "\n";
593  error_handler eh = std::bind(&lua_kernel_base::throw_exception, this, _1, _2 );
594  load_string(prog, eh);
595  lua_insert(mState, -nArgs - 1);
596  protected_call(nArgs, 0, eh);
597 }
598 
599 // Do a throwing run, but if we catch a lua_error, reformat it with signature for this function and log it.
600 void lua_kernel_base::run(const char * prog, int nArgs)
601 {
602  try {
603  throwing_run(prog, nArgs);
604  } catch (game::lua_error & e) {
605  cmd_log_ << e.what() << "\n";
606  lua_kernel_base::log_error(e.what(), "In function lua_kernel::run()");
607  }
608 }
609 
610 // Tests if a program resolves to an expression, and pretty prints it if it is, otherwise it runs it normally. Throws exceptions.
611 void lua_kernel_base::interactive_run(char const * prog) {
612  std::string experiment = "ilua._pretty_print(";
613  experiment += prog;
614  experiment += ")";
615 
616  error_handler eh = std::bind(&lua_kernel_base::throw_exception, this, _1, _2 );
617 
618  try {
619  // Try to load the experiment without syntax errors
620  load_string(experiment.c_str(), eh);
621  } catch (game::lua_error &) {
622  throwing_run(prog, 0); // Since it failed, fall back to the usual throwing_run, on the original input.
623  return;
624  }
625  // experiment succeeded, now run but log normally.
626  cmd_log_ << "$ " << prog << "\n";
627  protected_call(0, 0, eh);
628 }
629 /**
630  * Loads and executes a Lua file.
631  * - Arg 1: string containing the file name.
632  * - Ret *: values returned by executing the file body.
633  */
635 {
636  if (lua_fileops::load_file(L) != 1) return 0;
637  //^ should end with the file contents loaded on the stack. actually it will call lua_error otherwise, the return 0 is redundant.
638 
639  error_handler eh = std::bind(&lua_kernel_base::log_error, this, _1, _2 );
640  protected_call(0, LUA_MULTRET, eh);
641  return lua_gettop(L);
642 }
643 
644 /**
645  * Loads and executes a Lua file, if there is no corresponding entry in wesnoth.package.
646  * Stores the result of the script in wesnoth.package and returns it.
647  * - Arg 1: string containing the file name.
648  * - Ret 1: value returned by the script.
649  */
651 {
652  const char * m = luaL_checkstring(L, 1);
653  if (!m) {
654  luaL_argerror(L, 1, "found a null string argument to wesnoth require");
655  }
656 
657  // Check if there is already an entry.
658 
659  lua_getglobal(L, "wesnoth");
660  lua_pushstring(L, "package");
661  lua_rawget(L, -2);
662  lua_pushvalue(L, 1);
663  lua_rawget(L, -2);
664  if (!lua_isnil(L, -1) && !game_config::debug_lua) return 1;
665  lua_pop(L, 1);
666  lua_pushvalue(L, 1);
667  // stack is now [packagename] [wesnoth] [package] [packagename]
668 
669  if (lua_fileops::load_file(L) != 1) return 0;
670  //^ should end with the file contents loaded on the stack. actually it will call lua_error otherwise, the return 0 is redundant.
671  // stack is now [packagename] [wesnoth] [package] [chunk]
672  DBG_LUA << "require: loaded a file, now calling it\n";
673 
674  if (!protected_call(L, 0, 1, std::bind(&lua_kernel_base::log_error, this, _1, _2))) return 0;
675  //^ historically if wesnoth.require fails it just yields nil and some logging messages, not a lua error
676  // stack is now [packagename] [wesnoth] [package] [results]
677 
678  lua_pushvalue(L, 1);
679  lua_pushvalue(L, -2);
680  // stack is now [packagename] [wesnoth] [package] [results] [packagename] [results]
681  // Add the return value to the table.
682 
683  lua_settable(L, -4);
684  // stack is now [packagename] [wesnoth] [package] [results]
685  return 1;
686 }
687 /**
688  * Loads the "package" package into the Lua environment.
689  * This action is inherently unsafe, as Lua scripts will now be able to
690  * load C libraries on their own, hence granting them the same privileges
691  * as the Wesnoth binary itsef.
692  */
694 {
695  lua_State *L = mState;
697  lua_pushstring(L, "package");
698  lua_call(L, 1, 0);
699 }
700 
701 /**
702  * Gets all the global variable names in the Lua environment. This is useful for tab completion.
703  */
704 std::vector<std::string> lua_kernel_base::get_global_var_names()
705 {
706  std::vector<std::string> ret;
707 
708  lua_State *L = mState;
709 
710  int idx = lua_gettop(L);
711  lua_getglobal(L, "_G");
712  lua_pushnil(L);
713 
714  while (lua_next(L, idx+1) != 0) {
715  if (lua_isstring(L, -2)) {
716  ret.push_back(lua_tostring(L,-2));
717  }
718  lua_pop(L,1);
719  }
720  lua_settop(L, idx);
721  return ret;
722 }
723 
724 /**
725  * Gets all attribute names of an extended variable name. This is useful for tab completion.
726  */
727 std::vector<std::string> lua_kernel_base::get_attribute_names(const std::string & input)
728 {
729  std::vector<std::string> ret;
730  std::string var_path = input; // it's convenient to make a copy, even if it's a little slower
731 
732  lua_State *L = mState;
733 
734  int base = lua_gettop(L);
735  lua_getglobal(L, "_G");
736 
737  size_t idx = var_path.find('.');
738  size_t last_dot = 0;
739  while (idx != std::string::npos ) {
740  last_dot += idx + 1; // Since idx was not npos, add it to the "last_dot" idx, so that last_dot keeps track of indices in input string
741  lua_pushstring(L, var_path.substr(0, idx).c_str()); //push the part of the path up to the period
742  lua_rawget(L, -2);
743 
744  if (!lua_istable(L,-1) && !lua_isuserdata(L,-1)) {
745  lua_settop(L, base);
746  return ret; //if we didn't get a table or userdata we can't proceed
747  }
748 
749  var_path = var_path.substr(idx+1); // chop off the part of the path we just dereferenced
750  idx = var_path.find('.'); // find the next .
751  }
752 
753  std::string prefix = input.substr(0, last_dot);
754 
755  lua_pushnil(L);
756  while (lua_next(L, -2) != 0) {
757  if (lua_isstring(L, -2)) {
758  ret.push_back(prefix + lua_tostring(L,-2));
759  }
760  lua_pop(L,1);
761  }
762  lua_settop(L, base);
763  return ret;
764 }
765 
767 {
768  return *reinterpret_cast<lua_kernel_base**>(reinterpret_cast<char*>(L) - LUA_KERNEL_BASE_OFFSET);
769 }
770 
772 {
773  return seed_rng::next_seed();
774 }
int dispatch(lua_State *L)
int intf_set_dialog_active(lua_State *L)
Sets a widget's state to active or inactive.
Definition: lua_gui2.cpp:676
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:888
int show_lua_console(lua_State *, CVideo &video, lua_kernel_base *lk)
Definition: lua_gui2.cpp:737
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
Definition: lapi.cpp:579
static int intf_name_generator(lua_State *L)
#define lua_pushcfunction(L, f)
Definition: lua.h:328
LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:622
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
Definition: lua_common.cpp:395
int intf_add_dialog_tree_node(lua_State *L)
Sets a widget's state to active or inactive.
Definition: lua_gui2.cpp:757
int intf_read_file(lua_State *L)
Checks if a file exists (not necessarily a Lua script).
LUALIB_API lua_State * luaL_newstate(void)
Definition: lauxlib.cpp:939
LUAMOD_API int luaopen_debug(lua_State *L)
Definition: ldblib.cpp:393
int intf_vector_zero(lua_State *L)
Expose map_location::ZERO to lua.
VERSION_COMP_OP parse_version_op(const std::string &op_str)
Definition: version.cpp:276
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:159
int intf_have_file(lua_State *L)
Checks if a file exists (not necessarily a Lua script).
Definition: lua_fileops.cpp:95
LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
Definition: lauxlib.cpp:693
const char * what() const
Definition: exceptions.hpp:35
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:571
#define LUA_MULTRET
Definition: lua.h:33
rng * generator
This generator is automatically synced during synced context.
Definition: random_new.cpp:52
std::function< void(char const *, char const *)> error_handler
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
boost::uint32_t uint32_t
Definition: xbrz.hpp:45
Definition: video.hpp:58
LUA_API void lua_getglobal(lua_State *L, const char *var)
Definition: lapi.cpp:602
GLenum GLenum GLenum input
Definition: glew.h:10668
GLfloat GLfloat v1
Definition: glew.h:1820
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: number...
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:154
virtual bool is_valid() const
LUAMOD_API int luaopen_math(lua_State *L)
Definition: lmathlib.cpp:269
LUA_API void lua_settable(lua_State *L, int idx)
Definition: lapi.cpp:741
#define LUA_KERNEL_BASE_OFFSET
Definition: luaconf.h:572
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:77
GLfloat GLfloat GLfloat v2
Definition: glew.h:1824
#define luaL_getmetatable(L, n)
Definition: lauxlib.h:130
virtual ~lua_kernel_base()
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:274
int intf_remove_dialog_item(lua_State *L)
Removes an entry from a list.
Definition: lua_gui2.cpp:501
int intf_show_dialog(lua_State *L)
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:626
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
static lg::log_domain log_scripting_lua("scripting/lua")
LUAMOD_API int luaopen_base(lua_State *L)
Definition: lbaselib.cpp:446
LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int narg, lua_Integer def)
Definition: lauxlib.cpp:409
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1169
int intf_distance_between(lua_State *L)
Expose map_location distance_between.
#define lua_pop(L, n)
Definition: lua.h:322
int intf_set_dialog_focus(lua_State *L)
Sets a widget to have the focus.
Definition: lua_gui2.cpp:664
lua_kernel_base(CVideo *ptr)
int intf_rotate_right_around_center(lua_State *L)
Expose map_location::rotate_right_around_center to lua.
int intf_parse_direction(lua_State *L)
Expose map_location parse_direction.
lua_CFunction func
Definition: lauxlib.h:24
int intf_eval_formula(lua_State *)
Evaluates a formula in the formula engine.
int show_dialog(lua_State *L, CVideo &video)
Displays a window.
Definition: lua_gui2.cpp:223
#define lua_pcall(L, n, r, f)
Definition: lua.h:258
int intf_get_relative_dir(lua_State *L)
Expose map_location get_relative_dir.
LUAMOD_API int luaopen_coroutine(lua_State *L)
Definition: lcorolib.cpp:150
LUA_API void lua_setglobal(lua_State *L, const char *var)
Definition: lapi.cpp:728
LUAMOD_API int luaopen_os(lua_State *L)
Definition: loslib.cpp:318
GLuint64EXT * result
Definition: glew.h:10727
void throwing_run(char const *prog, int nArgs)
Runs a plain script, but reports errors by throwing lua_error.
LUAMOD_API int luaopen_string(lua_State *L)
Definition: lstrlib.cpp:1013
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:268
int intf_show_lua_console(lua_State *L)
virtual ~name_generator()
LUAMOD_API int luaopen_table(lua_State *L)
Definition: ltablib.cpp:273
LUAMOD_API int luaopen_package(lua_State *L)
Definition: loadlib.cpp:689
void load_package()
Loads the "package" package into the Lua environment.
LUA_API void lua_close(lua_State *L)
Definition: lstate.cpp:316
bool protected_call(int nArgs, int nRets, error_handler)
int show_message_dialog(lua_State *L, CVideo &video)
Displays a message window.
Definition: lua_gui2.cpp:254
GLenum GLuint GLsizei const char * buf
Definition: glew.h:2498
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:806
static int impl_name_generator_collect(lua_State *L)
LUA_API void lua_remove(lua_State *L, int idx)
Definition: lapi.cpp:176
int intf_compile_formula(lua_State *)
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
int intf_set_dialog_canvas(lua_State *L)
Sets a canvas on a widget of the current dialog.
Definition: lua_gui2.cpp:643
#define lua_newtable(L)
Definition: lua.h:324
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:459
int intf_tiles_adjacent(lua_State *L)
Expose map_location tiles_adjacent.
bool load_string(char const *prog, error_handler)
int(lua_kernel_base::* member_callback)(lua_State *L)
void run(char const *prog, int nArgs=0)
Runs a plain script.
#define LUA_ERRGCMM
Definition: lua.h:49
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:274
luatypekey const executeKey
Definition: lua_types.cpp:27
LUA_API void * lua_touserdata(lua_State *L, int idx)
Definition: lapi.cpp:421
#define LUA_ERRERR
Definition: lua.h:50
int intf_write_direction(lua_State *L)
Expose map_location write_direction.
#define lua_isnil(L, n)
Definition: lua.h:333
static void rethrow()
Rethrows the stored exception.
int intf_print(lua_State *L)
Replacement print function – instead of printing to std::cout, print to the command log...
int intf_set_dialog_value(lua_State *L)
Sets the value of a widget on the current dialog.
Definition: lua_gui2.cpp:365
VERSION_COMP_OP
Definition: version.hpp:195
virtual std::string generate() const =0
LUA_API void lua_rawset(lua_State *L, int idx)
Definition: lapi.cpp:764
std::string register_metatables(lua_State *)
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
Definition: lua_common.cpp:376
int intf_get_in_basis_N_NE(lua_State *L)
Expose map_location get_in_basis_N_NE.
int show_popup_dialog(lua_State *L, CVideo &video)
Displays a popup message.
Definition: lua_gui2.cpp:351
LUALIB_API int luaL_argerror(lua_State *L, int narg, const char *extramsg)
Definition: lauxlib.cpp:152
size_t i
Definition: function.cpp:1057
#define LUA_ERRSYNTAX
Definition: lua.h:47
#define lua_tostring(L, i)
Definition: lua.h:345
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:112
static int intf_compare_versions(lua_State *L)
Compares 2 version strings - which is newer.
LUA_API void lua_insert(lua_State *L, int idx)
Definition: lapi.cpp:187
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:229
#define LUA_ERRMEM
Definition: lua.h:48
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.
virtual void log_error(char const *msg, char const *context="Lua error")
#define lua_call(L, n, r)
Definition: lua.h:252
int intf_set_dialog_callback(lua_State *L)
Sets a callback on a widget of the current dialog.
Definition: lua_gui2.cpp:561
#define DBG_LUA
Represents version numbers.
Definition: version.hpp:44
virtual boost::uint32_t get_random_seed()
LUA_API void lua_gettable(lua_State *L, int idx)
Definition: lapi.cpp:613
std::vector< std::string > get_global_var_names()
Gets all the global variable names in the Lua environment.
command_log cmd_log_
int intf_vector_sum(lua_State *L)
Expose map_location::vector_sum to lua.
#define LUA_REGISTRYINDEX
Definition: lua.h:39
static int impl_name_generator_call(lua_State *L)
std::vector< std::string > parenthetical_split(std::string const &val, const char separator, std::string const &left, std::string const &right, const int flags)
Splits a string based either on a separator where text within parenthesis is protected from splitting...
uint32_t next_seed()
Definition: seed_rng.cpp:52
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1099
std::vector< std::string > get_attribute_names(const std::string &var_path)
Gets all attribute names of an extended variable name.
const GLdouble * m
Definition: glew.h:6968
#define LUA_OK
Definition: lua.h:44
#define lua_istable(L, n)
Definition: lua.h:331
virtual void throw_exception(char const *msg, char const *context="Lua error")
void luaW_pushconfig(lua_State *L, config const &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:663
config & child(const std::string &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:658
Standard logging facilities (interface).
GLsizei GLenum GLuint GLuint GLsizei char * message
Definition: glew.h:2499
void register_metatable(lua_State *L)
#define ERR_LUA
LUAMOD_API int luaopen_bit32(lua_State *L)
Definition: lbitlib.cpp:207
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
virtual std::string my_name()
#define e
bool do_version_check(const version_info &a, VERSION_COMP_OP op, const version_info &b)
Definition: version.cpp:295
int intf_get_dialog_value(lua_State *L)
Gets the value of a widget on the current dialog.
Definition: lua_gui2.cpp:439
int intf_show_message_dialog(lua_State *L)
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
Definition: lauxlib.cpp:850
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
int intf_dofile(lua_State *L)
Loads and executes a Lua file.
int intf_tovconfig(lua_State *L)
Creates a vconfig containing the WML table.
Definition: lua_common.cpp:366
lua_State * mState
Interfaces for manipulating version numbers of engine, add-ons, etc.
LUA_API void lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:633
GLsizei const GLcharARB ** string
Definition: glew.h:4503
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:79
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:507
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:752
#define LUA_ERRRUN
Definition: lua.h:46
int intf_set_dialog_visible(lua_State *L)
Sets the visiblity of a widget in the current dialog.
Definition: lua_gui2.cpp:692
LUA_API int lua_next(lua_State *L, int idx)
Definition: lapi.cpp:1108
static lua_kernel_base *& get_lua_kernel_base_ptr(lua_State *L)
static const char * Gen
int intf_show_popup_dialog(lua_State *L)
#define luaL_checkstring(L, n)
Definition: lauxlib.h:115
Error used to report an error in a lua script or in the lua interpreter.
Definition: game_errors.hpp:53