The Battle for Wesnoth  1.15.7+dev
lua_common.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 
15 /**
16  * @file
17  * Contains code common to the application and game lua kernels which
18  * cannot or should not go into the lua kernel base files.
19  *
20  * Currently contains implementation functions related to vconfig and
21  * gettext, also some macros to assist in writing C lua callbacks.
22  */
23 
24 #include "scripting/lua_common.hpp"
25 
26 #include "config.hpp"
27 #include "scripting/push_check.hpp"
28 #include "scripting/lua_unit.hpp"
29 #include "tstring.hpp" // for t_string
30 #include "variable.hpp" // for vconfig
31 #include "log.hpp"
32 #include "gettext.hpp"
34 #include "game_display.hpp"
35 
36 #include <cstring>
37 #include <iterator> // for distance, advance
38 #include <new> // for operator new
39 #include <string> // for string, basic_string
40 
41 #include "lua/lauxlib.h"
42 #include "lua/lua.h"
43 
44 static const char gettextKey[] = "gettext";
45 static const char vconfigKey[] = "vconfig";
46 static const char vconfigpairsKey[] = "vconfig pairs";
47 static const char vconfigipairsKey[] = "vconfig ipairs";
48 static const char tstringKey[] = "translatable string";
49 static const char executeKey[] = "err";
50 
51 static lg::log_domain log_scripting_lua("scripting/lua");
52 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
53 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
54 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
55 
56 namespace lua_common {
57 
58 /**
59  * Creates a t_string object (__call metamethod).
60  * - Arg 1: userdata containing the domain.
61  * - Arg 2: string to translate.
62  * - Ret 1: string containing the translatable string.
63  */
64 static int impl_gettext(lua_State *L)
65 {
66  char const *m = luaL_checkstring(L, 2);
67  char const *d = static_cast<char *>(lua_touserdata(L, 1));
68  // Hidden metamethod, so d has to be a string. Use it to create a t_string.
69  if(lua_isstring(L, 3)) {
70  const char* pl = luaL_checkstring(L, 3);
71  int count = luaL_checkinteger(L, 4);
72  luaW_pushtstring(L, t_string(m, pl, count, d));
73  } else {
74  luaW_pushtstring(L, t_string(m, d));
75  }
76  return 1;
77 }
78 
80 {
81  char* d = static_cast<char*>(lua_touserdata(L, 1));
82  using namespace std::literals;
83  std::string str = "textdomain: "s + d;
84  lua_push(L, str);
85  return 1;
86 }
87 
88 /**
89  * Creates an interface for gettext
90  * - Arg 1: string containing the domain.
91  * - Ret 1: a full userdata with __call pointing to lua_gettext.
92  */
94 {
95  std::size_t l;
96  char const *m = luaL_checklstring(L, 1, &l);
97 
98  void *p = lua_newuserdata(L, l + 1);
99  memcpy(p, m, l + 1);
100 
102  return 1;
103 }
104 
105 /**
106  * Converts a Lua value at position @a src and appends it to @a dst.
107  * @note This function is private to lua_tstring_concat. It expects two things.
108  * First, the t_string metatable is at the top of the stack on entry. (It
109  * is still there on exit.) Second, the caller hasn't any valuable object
110  * with dynamic lifetime, since they would be leaked on error.
111  */
112 static void tstring_concat_aux(lua_State *L, t_string &dst, int src)
113 {
114  switch (lua_type(L, src)) {
115  case LUA_TNUMBER:
116  case LUA_TSTRING:
117  dst += lua_tostring(L, src);
118  return;
119  case LUA_TUSERDATA:
120  // Compare its metatable with t_string's metatable.
121  if (t_string * src_ptr = static_cast<t_string *> (luaL_testudata(L, src, tstringKey))) {
122  dst += *src_ptr;
123  return;
124  }
125  //intentional fall-through
126  default:
127  luaW_type_error(L, src, "string");
128  }
129 }
130 
131 /**
132  * Appends a scalar to a t_string object (__concat metamethod).
133  */
135 {
136  // Create a new t_string.
137  t_string *t = new(L) t_string;
139 
140  // Append both arguments to t.
141  tstring_concat_aux(L, *t, 1);
142  tstring_concat_aux(L, *t, 2);
143 
144  return 1;
145 }
146 
148 {
149  t_string* t = static_cast<t_string*>(lua_touserdata(L, 1));
150  lua_pushnumber(L, t->size());
151  return 1;
152 }
153 
154 /**
155  * Destroys a t_string object before it is collected (__gc metamethod).
156  */
158 {
159  t_string *t = static_cast<t_string *>(lua_touserdata(L, 1));
160  t->t_string::~t_string();
161  return 0;
162 }
163 
165 {
166  t_string *t1 = static_cast<t_string *>(luaL_checkudata(L, 1, tstringKey));
167  t_string *t2 = static_cast<t_string *>(luaL_checkudata(L, 2, tstringKey));
168  lua_pushboolean(L, translation::compare(t1->get(), t2->get()) < 0);
169  return 1;
170 }
171 
173 {
174  t_string *t1 = static_cast<t_string *>(luaL_checkudata(L, 1, tstringKey));
175  t_string *t2 = static_cast<t_string *>(luaL_checkudata(L, 2, tstringKey));
176  lua_pushboolean(L, translation::compare(t1->get(), t2->get()) < 1);
177  return 1;
178 }
179 
181 {
182  t_string *t1 = static_cast<t_string *>(lua_touserdata(L, 1));
183  t_string *t2 = static_cast<t_string *>(lua_touserdata(L, 2));
184  lua_pushboolean(L, translation::compare(t1->get(), t2->get()) == 0);
185  return 1;
186 }
187 
188 /**
189  * Converts a t_string object to a string (__tostring metamethod);
190  * that is, performs a translation.
191  */
193 {
194  t_string *t = static_cast<t_string *>(lua_touserdata(L, 1));
195  lua_pushstring(L, t->c_str());
196  return 1;
197 }
198 
199 /**
200  * Gets the parsed field of a vconfig object (_index metamethod).
201  * Special fields __literal, __shallow_literal, __parsed, and
202  * __shallow_parsed, return Lua tables.
203  */
205 {
206  vconfig *v = static_cast<vconfig *>(lua_touserdata(L, 1));
207 
208  if (lua_isnumber(L, 2))
209  {
211  unsigned len = std::distance(i, v->ordered_end());
212  unsigned pos = lua_tointeger(L, 2) - 1;
213  if (pos >= len) return 0;
214  std::advance(i, pos);
215 
216  lua_createtable(L, 2, 0);
217  lua_pushstring(L, i.get_key().c_str());
218  lua_rawseti(L, -2, 1);
219  luaW_pushvconfig(L, i.get_child());
220  lua_rawseti(L, -2, 2);
221  return 1;
222  }
223 
224  char const *m = luaL_checkstring(L, 2);
225  if (strcmp(m, "__literal") == 0) {
226  luaW_pushconfig(L, v->get_config());
227  return 1;
228  }
229  if (strcmp(m, "__parsed") == 0) {
231  return 1;
232  }
233 
234  bool shallow_literal = strcmp(m, "__shallow_literal") == 0;
235  if (shallow_literal || strcmp(m, "__shallow_parsed") == 0)
236  {
237  lua_newtable(L);
238  for (const config::attribute &a : v->get_config().attribute_range()) {
239  if (shallow_literal)
240  luaW_pushscalar(L, a.second);
241  else
242  luaW_pushscalar(L, v->expand(a.first));
243  lua_setfield(L, -2, a.first.c_str());
244  }
246  i_end = v->ordered_end();
247  if (shallow_literal) {
248  i.disable_insertion();
249  i_end.disable_insertion();
250  }
251  for (int j = 1; i != i_end; ++i, ++j)
252  {
253  lua_createtable(L, 2, 0);
254  lua_pushstring(L, i.get_key().c_str());
255  lua_rawseti(L, -2, 1);
256  luaW_pushvconfig(L, i.get_child());
257  lua_rawseti(L, -2, 2);
258  lua_rawseti(L, -2, j);
259  }
260  return 1;
261  }
262 
263  if (v->null() || !v->has_attribute(m)) return 0;
264  luaW_pushscalar(L, (*v)[m]);
265  return 1;
266 }
267 
268 /**
269  * Returns the number of a child of a vconfig object.
270  */
272 {
273  vconfig *v = static_cast<vconfig *>(lua_touserdata(L, 1));
274  lua_pushinteger(L, v->null() ? 0 :
275  std::distance(v->ordered_begin(), v->ordered_end()));
276  return 1;
277 }
278 
279 /**
280  * Destroys a vconfig object before it is collected (__gc metamethod).
281  */
283 {
284  vconfig *v = static_cast<vconfig *>(lua_touserdata(L, 1));
285  v->~vconfig();
286  return 0;
287 }
288 
289 /**
290  * Iterate through the attributes of a vconfig
291  */
293 {
294  vconfig vcfg = luaW_checkvconfig(L, 1);
296  config::const_attr_itors& range = *static_cast<config::const_attr_itors*>(p);
297  if (range.empty()) {
298  return 0;
299  }
300  config::attribute value = range.front();
301  range.pop_front();
302  lua_pushlstring(L, value.first.c_str(), value.first.length());
303  luaW_pushscalar(L, vcfg[value.first]);
304  return 2;
305 }
306 
307 /**
308  * Destroy a vconfig pairs iterator
309  */
311 {
312  typedef config::const_attr_itors const_attr_itors;
313  void* p = lua_touserdata(L, 1);
314 
315  // Triggers a false positive of C4189 with Visual Studio. Suppress.
316 #if defined(_MSC_VER)
317 #pragma warning(push)
318 #pragma warning(disable: 4189)
319 #endif
320 
321  const_attr_itors* cai = static_cast<const_attr_itors*>(p);
322  cai->~const_attr_itors();
323 
324 #if defined(_MSC_VER)
325 #pragma warning(pop)
326 #endif
327 
328  return 0;
329 }
330 
331 /**
332  * Construct an iterator to iterate through the attributes of a vconfig
333  */
335 {
336  vconfig vcfg = luaW_checkvconfig(L, 1);
339  lua_setmetatable(L, -2);
341  lua_pushvalue(L, 1);
342  return 2;
343 }
344 
345 typedef std::pair<vconfig::all_children_iterator, vconfig::all_children_iterator> vconfig_child_range;
346 
347 /**
348  * Iterate through the subtags of a vconfig
349  */
351 {
352  luaW_checkvconfig(L, 1);
353  int i = luaL_checkinteger(L, 2);
355  vconfig_child_range& range = *static_cast<vconfig_child_range*>(p);
356  if (range.first == range.second) {
357  return 0;
358  }
359  std::pair<std::string, vconfig> value = *range.first++;
360  lua_pushinteger(L, i + 1);
361  lua_createtable(L, 2, 0);
362  lua_pushlstring(L, value.first.c_str(), value.first.length());
363  lua_rawseti(L, -2, 1);
364  luaW_pushvconfig(L, value.second);
365  lua_rawseti(L, -2, 2);
366  return 2;
367 }
368 
369 /**
370  * Destroy a vconfig ipairs iterator
371  */
373 {
374  void* p = lua_touserdata(L, 1);
375  vconfig_child_range* vcr = static_cast<vconfig_child_range*>(p);
376  vcr->~vconfig_child_range();
377  return 0;
378 }
379 
380 /**
381  * Construct an iterator to iterate through the subtags of a vconfig
382  */
384 {
385  vconfig cfg = luaW_checkvconfig(L, 1);
386  new(L) vconfig_child_range(cfg.ordered_begin(), cfg.ordered_end());
388  lua_setmetatable(L, -2);
390  lua_pushvalue(L, 1);
391  lua_pushinteger(L, 0);
392  return 3;
393 }
394 
395 /**
396  * Creates a vconfig containing the WML table.
397  * - Arg 1: WML table.
398  * - Ret 1: vconfig userdata.
399  */
401 {
402  vconfig vcfg = luaW_checkvconfig(L, 1);
403  luaW_pushvconfig(L, vcfg);
404  return 1;
405 }
406 
407 /**
408  * Adds the gettext metatable
409  */
411 {
413 
414  static luaL_Reg const callbacks[] {
415  { "__call", &impl_gettext},
416  { "__tostring", &impl_gettext_tostr},
417  { nullptr, nullptr }
418  };
419  luaL_setfuncs(L, callbacks, 0);
420 
421  lua_pushstring(L, "message domain");
422  lua_setfield(L, -2, "__metatable");
423 
424  return "Adding gettext metatable...\n";
425 }
426 
427 /**
428  * Adds the tstring metatable
429  */
431 {
433 
434  static luaL_Reg const callbacks[] {
435  { "__concat", &impl_tstring_concat},
436  { "__gc", &impl_tstring_collect},
437  { "__tostring", &impl_tstring_tostring},
438  { "__len", &impl_tstring_len},
439  { "__lt", &impl_tstring_lt},
440  { "__le", &impl_tstring_le},
441  { "__eq", &impl_tstring_eq},
442  { nullptr, nullptr }
443  };
444  luaL_setfuncs(L, callbacks, 0);
445 
446  lua_createtable(L, 0, 1);
447  luaW_getglobal(L, "string", "format");
448  lua_setfield(L, -2, "format");
449  luaW_getglobal(L, "stringx", "vformat");
450  lua_setfield(L, -2, "vformat");
451  lua_setfield(L, -2, "__index");
452 
453  lua_pushstring(L, "translatable string");
454  lua_setfield(L, -2, "__metatable");
455 
456  return "Adding tstring metatable...\n";
457 }
458 
459 /**
460  * Adds the vconfig metatable
461  */
463 {
465 
466  static luaL_Reg const callbacks[] {
467  { "__gc", &impl_vconfig_collect},
468  { "__index", &impl_vconfig_get},
469  { "__len", &impl_vconfig_size},
470  { "__pairs", &impl_vconfig_pairs},
471  { "__ipairs", &impl_vconfig_ipairs},
472  { nullptr, nullptr }
473  };
474  luaL_setfuncs(L, callbacks, 0);
475 
476  lua_pushstring(L, "wml object");
477  lua_setfield(L, -2, "__metatable");
478 
479  // Metatables for the iterator userdata
480 
481  // I don't bother setting __metatable because this
482  // userdata is only ever stored in the iterator's
483  // upvalues, so it's never visible to the user.
485  lua_pushstring(L, "__gc");
487  lua_rawset(L, -3);
488 
490  lua_pushstring(L, "__gc");
492  lua_rawset(L, -3);
493 
494  return "Adding vconfig metatable...\n";
495 }
496 
497 } // end namespace lua_common
498 
499 void* operator new(std::size_t sz, lua_State *L)
500 {
501  return lua_newuserdata(L, sz);
502 }
503 
504 void operator delete(void*, lua_State *L)
505 {
506  // Not sure if this is needed since it's a no-op
507  // It's only called if a constructor throws while using the above operator new
508  // By removing the userdata from the stack, this should ensure that Lua frees it
509  lua_pop(L, 1);
510 }
511 
512 bool luaW_getmetafield(lua_State *L, int idx, const char* key)
513 {
514  if(key == nullptr) {
515  return false;
516  }
517  int n = strlen(key);
518  if(n == 0) {
519  return false;
520  }
521  if(n >= 2 && key[0] == '_' && key[1] == '_') {
522  return false;
523  }
524  return luaL_getmetafield(L, idx, key) != 0;
525 }
526 
527 void luaW_pushvconfig(lua_State *L, const vconfig& cfg)
528 {
529  new(L) vconfig(cfg);
531 }
532 
534 {
535  new(L) t_string(v);
537 }
538 
539 
540 namespace {
541  struct luaW_pushscalar_visitor : boost::static_visitor<>
542  {
543  lua_State *L;
544  luaW_pushscalar_visitor(lua_State *l): L(l) {}
545 
546  void operator()(const boost::blank&) const
547  { lua_pushnil(L); }
548  void operator()(bool b) const
549  { lua_pushboolean(L, b); }
550  void operator()(int i) const
551  { lua_pushinteger(L, i); }
552  void operator()(unsigned long long ull) const
553  { lua_pushnumber(L, ull); }
554  void operator()(double d) const
555  { lua_pushnumber(L, d); }
556  void operator()(const std::string& s) const
557  { lua_pushstring(L, s.c_str()); }
558  void operator()(const t_string& s) const
559  { luaW_pushtstring(L, s); }
560  };
561 }//unnamed namespace for luaW_pushscalar_visitor
562 
564 {
565  v.apply_visitor(luaW_pushscalar_visitor(L));
566 }
567 
569 {
570  switch (lua_type(L, index)) {
571  case LUA_TBOOLEAN:
572  v = luaW_toboolean(L, -1);
573  break;
574  case LUA_TNUMBER:
575  v = lua_tonumber(L, -1);
576  break;
577  case LUA_TSTRING:
578  v = lua_tostring(L, -1);
579  break;
580  case LUA_TUSERDATA:
581  {
582  if (t_string * tptr = static_cast<t_string *>(luaL_testudata(L, -1, tstringKey))) {
583  v = *tptr;
584  break;
585  } else {
586  return false;
587  }
588  }
589  default:
590  return false;
591  }
592  return true;
593 }
594 
596 {
597  switch (lua_type(L, index)) {
598  case LUA_TBOOLEAN:
599  str = lua_toboolean(L, index) ? "yes" : "no";
600  break;
601  case LUA_TNUMBER:
602  case LUA_TSTRING:
603  str = lua_tostring(L, index);
604  break;
605  case LUA_TUSERDATA:
606  {
607  if (t_string * tstr = static_cast<t_string *> (luaL_testudata(L, index, tstringKey))) {
608  str = *tstr;
609  break;
610  } else {
611  return false;
612  }
613  }
614  default:
615  return false;
616  }
617  return true;
618 }
619 
621 {
622  t_string result;
623  if (!luaW_totstring(L, index, result))
624  luaW_type_error(L, index, "translatable string");
625  return result;
626 }
627 
629 {
630  if(lua_isstring(L, index)) {
631  return true;
632  }
633  if(lua_isuserdata(L, index) && luaL_testudata(L, index, tstringKey)) {
634  return true;
635  }
636  return false;
637 }
638 
639 void luaW_filltable(lua_State *L, const config& cfg)
640 {
641  if (!lua_checkstack(L, LUA_MINSTACK))
642  return;
643 
644  int k = 1;
645  for (const config::any_child &ch : cfg.all_children_range())
646  {
647  lua_createtable(L, 2, 0);
648  lua_pushstring(L, ch.key.c_str());
649  lua_rawseti(L, -2, 1);
650  lua_newtable(L);
651  luaW_filltable(L, ch.cfg);
652  lua_rawseti(L, -2, 2);
653  lua_rawseti(L, -2, k++);
654  }
655  for (const config::attribute &attr : cfg.attribute_range())
656  {
657  luaW_pushscalar(L, attr.second);
658  lua_setfield(L, -2, attr.first.c_str());
659  }
660 }
661 
663 {
664  lua_createtable(L, 2, 0);
665 
666  lua_pushinteger(L, ml.wml_x());
667  lua_rawseti(L, -2, 1);
668 
669  lua_pushinteger(L, ml.wml_y());
670  lua_rawseti(L, -2, 2);
671 }
672 
674  if (!lua_checkstack(L, LUA_MINSTACK)) {
675  return false;
676  }
677  if (lua_isnoneornil(L, index)) {
678  // Need this special check because luaW_tovconfig returns true in this case
679  return false;
680  }
681 
683 
684  index = lua_absindex(L, index);
685 
686  if (lua_istable(L, index) || luaW_tounit(L, index) || luaW_tovconfig(L, index, dummy_vcfg)) {
687  map_location result;
688  int x_was_num = 0, y_was_num = 0;
689  lua_getfield(L, index, "x");
690  result.set_wml_x(lua_tonumberx(L, -1, &x_was_num));
691  lua_getfield(L, index, "y");
692  result.set_wml_y(lua_tonumberx(L, -1, &y_was_num));
693  lua_pop(L, 2);
694  if (!x_was_num || !y_was_num) {
695  // If we get here and it was userdata, checking numeric indices won't help
696  // (It won't help if it was a config either, but there's no easy way to check that.)
697  if (lua_isuserdata(L, index)) {
698  return false;
699  }
700  lua_rawgeti(L, index, 1);
701  result.set_wml_x(lua_tonumberx(L, -1, &x_was_num));
702  lua_rawgeti(L, index, 2);
703  result.set_wml_y(lua_tonumberx(L, -1, &y_was_num));
704  lua_pop(L, 2);
705  }
706  if (x_was_num && y_was_num) {
707  loc = result;
708  return true;
709  }
710  } else if (lua_isnumber(L, index) && lua_isnumber(L, index + 1)) {
711  // If it's a number, then we consume two elements on the stack
712  // Since we have no way of notifying the caller that we have
713  // done this, we remove the first number from the stack.
714  loc.set_wml_x(lua_tonumber(L, index));
715  lua_remove(L, index);
716  loc.set_wml_y(lua_tonumber(L, index));
717  return true;
718  }
719  return false;
720 }
721 
723 {
724  map_location result;
725  if (!luaW_tolocation(L, index, result))
726  luaW_type_error(L, index, "location");
727  return result;
728 }
729 
730 void luaW_pushconfig(lua_State *L, const config& cfg)
731 {
732  lua_newtable(L);
733  luaW_filltable(L, cfg);
734 }
735 
736 
737 
738 
739 #define return_misformed() \
740  do { lua_settop(L, initial_top); return false; } while (0)
741 
742 bool luaW_toconfig(lua_State *L, int index, config &cfg)
743 {
744  if (!lua_checkstack(L, LUA_MINSTACK))
745  return false;
746 
747  // Get the absolute index of the table.
748  index = lua_absindex(L, index);
749  int initial_top = lua_gettop(L);
750 
751  switch (lua_type(L, index))
752  {
753  case LUA_TTABLE:
754  break;
755  case LUA_TUSERDATA:
756  {
757  if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) {
758  cfg = ptr->get_parsed_config();
759  return true;
760  } else {
761  return false;
762  }
763  }
764  case LUA_TNONE:
765  case LUA_TNIL:
766  return true;
767  default:
768  return false;
769  }
770 
771  // First convert the children (integer indices).
772  for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i)
773  {
774  lua_rawgeti(L, index, i);
775  if (!lua_istable(L, -1)) return_misformed();
776  lua_rawgeti(L, -1, 1);
777  char const *m = lua_tostring(L, -1);
778  if (!m || !config::valid_tag(m)) return_misformed();
779  lua_rawgeti(L, -2, 2);
780  if (!luaW_toconfig(L, -1, cfg.add_child(m)))
782  lua_pop(L, 3);
783  }
784 
785  // Then convert the attributes (string indices).
786  for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1))
787  {
788  int indextype = lua_type(L, -2);
789  if (indextype == LUA_TNUMBER) continue;
790  if (indextype != LUA_TSTRING) return_misformed();
791  const char* m = lua_tostring(L, -2);
793  config::attribute_value &v = cfg[m];
794  if (lua_istable(L, -1)) {
795  int subindex = lua_absindex(L, -1);
796  std::ostringstream str;
797  for (int i = 1, i_end = lua_rawlen(L, subindex); i <= i_end; ++i, lua_pop(L, 1)) {
798  lua_rawgeti(L, -1, i);
800  if (!luaW_toscalar(L, -1, item)) return_misformed();
801  if (i > 1) str << ',';
802  str << item;
803  }
804  // If there are any string keys, it's malformed
805  for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) {
806  if (lua_type(L, -2) != LUA_TNUMBER) return_misformed();
807  }
808  v = str.str();
809  } else if (!luaW_toscalar(L, -1, v)) return_misformed();
810  }
811 
812  lua_settop(L, initial_top);
813  return true;
814 }
815 
816 #undef return_misformed
817 
818 
820 {
821  config result;
822  if (!luaW_toconfig(L, index, result))
823  luaW_type_error(L, index, "WML table");
824  return result;
825 }
826 
828 {
829  config result = luaW_checkconfig(L, index);
830  if(void* p = luaL_testudata(L, index, vconfigKey)) {
831  vcfg = static_cast<vconfig*>(p);
832  }
833  return result;
834 }
835 
836 bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
837 {
838  switch (lua_type(L, index))
839  {
840  case LUA_TTABLE:
841  {
842  config cfg;
843  bool ok = luaW_toconfig(L, index, cfg);
844  if (!ok) return false;
845  vcfg = vconfig(std::move(cfg));
846  break;
847  }
848  case LUA_TUSERDATA:
849  if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) {
850  vcfg = *ptr;
851  } else {
852  return false;
853  }
854  case LUA_TNONE:
855  case LUA_TNIL:
856  break;
857  default:
858  return false;
859  }
860  return true;
861 }
862 
863 vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing)
864 {
866  if (!luaW_tovconfig(L, index, result) || (!allow_missing && result.null()))
867  luaW_type_error(L, index, "WML table");
868  return result;
869 }
870 
871 bool luaW_getglobal(lua_State *L, const std::vector<std::string>& path)
872 {
874  for (const std::string& s : path)
875  {
876  if (!lua_istable(L, -1)) goto discard;
877  lua_pushlstring(L, s.c_str(), s.size());
878  lua_rawget(L, -2);
879  lua_remove(L, -2);
880  }
881 
882  if (lua_isnil(L, -1)) {
883  discard:
884  lua_pop(L, 1);
885  return false;
886  }
887  return true;
888 }
889 
891 {
892  return lua_toboolean(L,n) != 0;
893 }
894 
896 {
897  try
898  {
899  if(v.exists_as_attribute())
900  {
901  luaW_pushscalar(L, v.as_scalar());
902  return true;
903  }
904  else if(v.exists_as_container())
905  {
906  lua_newtable(L);
908  return true;
909  }
910  else
911  {
912  lua_pushnil(L);
913  return true;
914  }
915  }
916  catch (const invalid_variablename_exception&)
917  {
918  WRN_LUA << v.get_error_message() << "\n";
919  return false;
920  }
921 }
922 
924 {
925  int variabletype = lua_type(L, n);
926  try
927  {
928  switch (variabletype) {
929  case LUA_TBOOLEAN:
930  v.as_scalar() = luaW_toboolean(L, n);
931  return true;
932  case LUA_TNUMBER:
933  v.as_scalar() = lua_tonumber(L, n);
934  return true;
935  case LUA_TSTRING:
936  v.as_scalar() = lua_tostring(L, n);
937  return true;
938  case LUA_TUSERDATA:
939  if (t_string * t_str = static_cast<t_string*> (luaL_testudata(L, n, tstringKey))) {
940  v.as_scalar() = *t_str;
941  return true;
942  }
943  goto default_explicit;
944  case LUA_TTABLE:
945  {
946  config &cfg = v.as_container();
947  cfg.clear();
948  if (luaW_toconfig(L, n, cfg)) {
949  return true;
950  }
951  FALLTHROUGH;
952  }
953  default:
954  default_explicit:
955  return luaW_type_error(L, n, "WML table or scalar") != 0;
956 
957  }
958  }
959  catch (const invalid_variablename_exception&)
960  {
961  WRN_LUA << v.get_error_message() << " when attempting to write a '" << lua_typename(L, variabletype) << "'\n";
962  return false;
963  }
964 }
965 
966 bool luaW_tableget(lua_State *L, int index, const char* key)
967 {
968  index = lua_absindex(L, index);
969  lua_pushstring(L, key);
970  lua_gettable(L, index);
971  if(lua_isnoneornil(L, -1)) {
972  lua_pop(L, 1);
973  return false;
974  }
975  return true;
976 }
977 
979 {
980  size_t len = 0;
981  const char* str = lua_tolstring(L, index, &len);
982  if(!str) {
983  throw luaL_error (L, "not a string");
984  }
985  return utils::string_view(str, len);
986 }
987 
989 {
990  size_t len = 0;
991  const char* str = lua_tolstring(L, index, &len);
992  if(!str) {
993  return def;
994  }
995  return utils::string_view(str, len);
996 }
997 
998 void chat_message(const std::string& caption, const std::string& msg)
999 {
1000  if (!game_display::get_singleton()) return;
1003 }
1004 
1006 {
1007  luaW_getglobal(L, "debug", "traceback");
1009 }
1010 
1011 int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
1012 {
1013  // Load the error handler before the function and its arguments.
1015  lua_insert(L, -2 - nArgs);
1016 
1017  int error_handler_index = lua_gettop(L) - nArgs - 1;
1018 
1019  // Call the function.
1020  int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
1021 
1023 
1024  // Remove the error handler.
1025  lua_remove(L, error_handler_index);
1026 
1027  return errcode;
1028 }
1029 
1030 #ifdef _MSC_VER
1031 #pragma warning (push)
1032 #pragma warning (disable: 4706)
1033 #endif
1034 bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
1035 {
1036  int res = luaW_pcall_internal(L, nArgs, nRets);
1037 
1038  if (res)
1039  {
1040  /*
1041  * When an exception is thrown which doesn't derive from
1042  * std::exception m will be nullptr pointer.
1043  */
1044  char const *m = lua_tostring(L, -1);
1045  if(m) {
1046  if (allow_wml_error && strncmp(m, "~wml:", 5) == 0) {
1047  m += 5;
1048  char const *e = strstr(m, "stack traceback");
1049  lg::wml_error() << std::string(m, e ? e - m : strlen(m));
1050  } else if (allow_wml_error && strncmp(m, "~lua:", 5) == 0) {
1051  m += 5;
1052  char const *e = nullptr, *em = m;
1053  while (em[0] && ((em = strstr(em + 1, "stack traceback"))))
1054 #ifdef _MSC_VER
1055 #pragma warning (pop)
1056 #endif
1057  e = em;
1058  chat_message("Lua error", std::string(m, e ? e - m : strlen(m)));
1059  } else {
1060  ERR_LUA << m << '\n';
1061  chat_message("Lua error", m);
1062  }
1063  } else {
1064  chat_message("Lua caught unknown exception", "");
1065  }
1066  lua_pop(L, 1);
1067  return false;
1068  }
1069 
1070  return true;
1071 }
1072 
1073 // Originally luaL_typerror, now deprecated.
1074 // Easier to define it for Wesnoth and not have to worry about it if we update Lua.
1075 int luaW_type_error(lua_State *L, int narg, const char *tname) {
1076  const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, narg));
1077  return luaL_argerror(L, narg, msg);
1078 }
1079 
1080 // An alternate version which raises an error for a key in a table.
1081 // In this version, narg should refer to the stack index of the table rather than the stack index of the key.
1082 // kpath should be the key name or a string such as "key[idx].key2" specifying a path to the key.
1083 int luaW_type_error (lua_State *L, int narg, const char* kpath, const char *tname) {
1084  const char *msg = lua_pushfstring(L, "%s expected for '%s', got %s", tname, kpath, luaL_typename(L, narg));
1085  return luaL_argerror(L, narg, msg);
1086 }
void set_wml_y(int v)
Definition: location.hpp:161
#define WRN_LUA
Definition: lua_common.cpp:53
bool luaW_checkvariable(lua_State *L, variable_access_create &v, int n)
Definition: lua_common.cpp:923
bool luaW_tableget(lua_State *L, int index, const char *key)
Definition: lua_common.cpp:966
void chat_message(const std::string &caption, const std::string &msg)
Displays a message in the chat window.
Definition: lua_common.cpp:998
static int impl_vconfig_collect(lua_State *L)
Destroys a vconfig object before it is collected (__gc metamethod).
Definition: lua_common.cpp:282
#define lua_isnoneornil(L, n)
Definition: lua.h:359
LUALIB_API void * luaL_checkudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:333
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
static bool valid_tag(config_key_type name)
Definition: config.cpp:185
utils::string_view luaW_tostring(lua_State *L, int index)
Definition: lua_common.cpp:978
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
Definition: lua_common.cpp:430
static lg::log_domain log_scripting_lua("scripting/lua")
LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *pisnum)
Definition: lapi.cpp:345
const_all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:921
bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
Gets an optional vconfig from either a table or a userdata.
Definition: lua_common.cpp:836
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:730
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:172
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:251
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.
all_children_iterator ordered_begin() const
In-order iteration over all children.
Definition: variable.cpp:477
#define LUA_TUSERDATA
Definition: lua.h:71
int luaW_type_error(lua_State *L, int narg, const char *tname)
bool exists_as_attribute() const
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:557
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:658
Variant for storing WML attributes.
#define a
static int impl_gettext(lua_State *L)
Creates a t_string object (__call metamethod).
Definition: lua_common.cpp:64
int compare(const std::string &s1, const std::string &s2)
Case-sensitive lexicographical comparison.
Definition: gettext.cpp:457
maybe_const_t< config::attribute_value, V > & as_scalar() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
bool has_attribute(const std::string &key) const
< Synonym for operator[]
Definition: variable.hpp:106
static int impl_vconfig_get(lua_State *L)
Gets the parsed field of a vconfig object (_index metamethod).
Definition: lua_common.cpp:204
LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:817
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
static int impl_tstring_len(lua_State *L)
Definition: lua_common.cpp:147
bool luaW_pushvariable(lua_State *L, variable_access_const &v)
Definition: lua_common.cpp:895
attribute_map::value_type attribute
Definition: config.hpp:229
LUA_API int lua_gettable(lua_State *L, int idx)
Definition: lapi.cpp:612
#define lua_remove(L, idx)
Definition: lua.h:371
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:93
#define lua_tointeger(L, i)
Definition: lua.h:342
int wml_x() const
Definition: location.hpp:157
~vconfig()
Default destructor, but defined here for possibly faster compiles (templates sometimes can be rough o...
Definition: variable.cpp:137
LUA_API int lua_rawget(lua_State *L, int idx)
Definition: lapi.cpp:647
void set_wml_x(int v)
Definition: location.hpp:160
const char * c_str() const
Definition: tstring.hpp:187
static int impl_vconfig_ipairs(lua_State *L)
Construct an iterator to iterate through the subtags of a vconfig.
Definition: lua_common.cpp:383
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
static bool valid_attribute(config_key_type name)
Definition: config.cpp:208
#define luaL_typename(L, i)
Definition: lauxlib.h:127
LUA_API int lua_checkstack(lua_State *L, int n)
Definition: lapi.cpp:97
Additional functionality for a non-const variable_info.
const t_string_base & get() const
Definition: tstring.hpp:195
maybe_const_t< config, V > & as_container() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
void clear()
Definition: config.cpp:863
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:289
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n)
Definition: lapi.cpp:532
#define d
#define ERR_LUA
Definition: lua_common.cpp:54
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:312
std::string str
Definition: statement.cpp:110
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:400
basic_string_view< char, std::char_traits< char > > string_view
std::string get_key() const
Definition: variable.cpp:444
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:722
Definitions for the interface to Wesnoth Markup Language (WML).
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:160
const_attr_itors attribute_range() const
Definition: config.cpp:809
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1184
void add_chat_message(const std::time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
#define lua_pop(L, n)
Definition: lua.h:344
std::string::size_type size() const
Definition: tstring.hpp:183
#define return_misformed()
Definition: lua_common.cpp:739
#define b
size_t len
Definition: result_set.cpp:277
#define lua_upvalueindex(i)
Definition: lua.h:43
#define lua_pcall(L, n, r, f)
Definition: lua.h:278
#define LUA_TSTRING
Definition: lua.h:68
LUALIB_API int luaL_argerror(lua_State *L, int arg, const char *extramsg)
Definition: lauxlib.cpp:164
std::string register_vconfig_metatable(lua_State *L)
Adds the vconfig metatable.
Definition: lua_common.cpp:462
#define LUA_TNONE
Definition: lua.h:62
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:871
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:890
static int impl_tstring_concat(lua_State *L)
Appends a scalar to a t_string object (__concat metamethod).
Definition: lua_common.cpp:134
unit * luaW_tounit(lua_State *L, int index, bool only_on_map)
Converts a Lua value to a unit pointer.
Definition: lua_unit.cpp:145
#define LUA_TNIL
Definition: lua.h:64
int wml_y() const
Definition: location.hpp:158
all_children_iterator ordered_end() const
Definition: variable.cpp:482
void luaW_pushtstring(lua_State *L, const t_string &v)
Pushes a t_string on the top of the stack.
Definition: lua_common.cpp:533
LUA_API int lua_toboolean(lua_State *L, int idx)
Definition: lapi.cpp:367
void luaW_filltable(lua_State *L, const config &cfg)
Converts a config object to a Lua table.
Definition: lua_common.cpp:639
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:620
void luaW_pushscalar(lua_State *L, const config::attribute_value &v)
Converts an attribute value into a Lua object pushed at the top of the stack.
Definition: lua_common.cpp:563
#define lua_pushglobaltable(L)
Definition: lua.h:363
static int impl_gettext_tostr(lua_State *L)
Definition: lua_common.cpp:79
LUA_API const char * lua_pushlstring(lua_State *L, const char *s, size_t len)
Definition: lapi.cpp:479
#define LUA_TNUMBER
Definition: lua.h:67
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:846
std::string path
Definition: game_config.cpp:39
static const char vconfigKey[]
Definition: lua_common.cpp:45
config get_parsed_config() const
Definition: variable.cpp:176
LUA_API const char * lua_tolstring(lua_State *L, int idx, size_t *len)
Definition: lapi.cpp:373
boost::iterator_range< const_attribute_iterator > const_attr_itors
Definition: config.hpp:289
LUALIB_API void * luaL_testudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:318
static void rethrow()
Rethrows the stored exception.
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
#define lua_newtable(L)
Definition: lua.h:346
static int impl_vconfig_pairs_collect(lua_State *L)
Destroy a vconfig pairs iterator.
Definition: lua_common.cpp:310
static int impl_tstring_tostring(lua_State *L)
Converts a t_string object to a string (__tostring metamethod); that is, performs a translation...
Definition: lua_common.cpp:192
LUA_API void lua_pushnil(lua_State *L)
Definition: lapi.cpp:450
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:458
static int impl_vconfig_pairs(lua_State *L)
Construct an iterator to iterate through the attributes of a vconfig.
Definition: lua_common.cpp:334
Encapsulates the map of the game.
Definition: location.hpp:42
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:742
bool luaW_totstring(lua_State *L, int index, t_string &str)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:595
static int impl_vconfig_size(lua_State *L)
Returns the number of a child of a vconfig object.
Definition: lua_common.cpp:271
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_isnil(L, n)
Definition: lua.h:355
static const char vconfigpairsKey[]
Definition: lua_common.cpp:46
std::size_t i
Definition: function.cpp:933
static int impl_tstring_eq(lua_State *L)
Definition: lua_common.cpp:180
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:291
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int arg)
Definition: lauxlib.cpp:430
static int impl_tstring_lt(lua_State *L)
Definition: lua_common.cpp:164
LUA_API void lua_rawset(lua_State *L, int idx)
Definition: lapi.cpp:801
config::attribute_value expand(const std::string &) const
Definition: variable.cpp:349
static const char gettextKey[]
Definition: lua_common.cpp:44
bool luaW_iststring(lua_State *L, int index)
Definition: lua_common.cpp:628
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
Definition: lua_common.cpp:410
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:819
mock_party p
static int impl_tstring_le(lua_State *L)
Definition: lua_common.cpp:172
static map_location::DIRECTION s
static int impl_vconfig_ipairs_collect(lua_State *L)
Destroy a vconfig ipairs iterator.
Definition: lua_common.cpp:372
std::string get_error_message() const
#define lua_tostring(L, i)
Definition: lua.h:366
#define LUA_MINSTACK
Definition: lua.h:79
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:237
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
LUA_API int lua_isnumber(lua_State *L, int idx)
Definition: lapi.cpp:276
static vconfig unconstructed_vconfig()
This is just a wrapper for the default constructor; it exists for historical reasons and to make it c...
Definition: variable.cpp:152
LUALIB_API int luaL_error(lua_State *L, const char *fmt,...)
Definition: lauxlib.cpp:223
config & add_child(config_key_type key)
Definition: config.cpp:476
std::pair< vconfig::all_children_iterator, vconfig::all_children_iterator > vconfig_child_range
Definition: lua_common.cpp:345
LUA_API size_t lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:392
display_chat_manager & get_chat_manager()
#define LUA_REGISTRYINDEX
Definition: lua.h:42
bool luaW_getmetafield(lua_State *L, int idx, const char *key)
Like luaL_getmetafield, but returns false if key is an empty string or begins with two underscores...
Definition: lua_common.cpp:512
static const char executeKey[]
Definition: lua_common.cpp:49
Information on a WML variable.
static int impl_vconfig_ipairs_iter(lua_State *L)
Iterate through the subtags of a vconfig.
Definition: lua_common.cpp:350
double t
Definition: astarsearch.cpp:64
#define lua_istable(L, n)
Definition: lua.h:353
bool exists_as_container() const
void luaW_pushlocation(lua_State *L, const map_location &ml)
Converts a map location object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:662
#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:527
bool luaW_toscalar(lua_State *L, int index, config::attribute_value &v)
Converts the value at the top of the stack to an attribute value.
Definition: lua_common.cpp:568
A variable-expanding proxy for the config class.
Definition: variable.hpp:44
const config & get_config() const
Definition: variable.hpp:82
Standard logging facilities (interface).
V::result_type apply_visitor(const V &visitor) const
Applies a visitor to the underlying variant.
LUA_API const char * lua_pushfstring(lua_State *L, const char *fmt,...)
Definition: lapi.cpp:519
vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing)
Gets an optional vconfig from either a table or a userdata.
Definition: lua_common.cpp:863
static const char tstringKey[]
Definition: lua_common.cpp:48
#define e
static const char vconfigipairsKey[]
Definition: lua_common.cpp:47
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)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
bool null() const
Definition: variable.hpp:80
static int impl_tstring_collect(lua_State *L)
Destroys a t_string object before it is collected (__gc metamethod).
Definition: lua_common.cpp:157
static void tstring_concat_aux(lua_State *L, t_string &dst, int src)
Converts a Lua value at position src and appends it to dst.
Definition: lua_common.cpp:112
int intf_tovconfig(lua_State *L)
Creates a vconfig containing the WML table.
Definition: lua_common.cpp:400
LUA_API int lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:622
#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
static int impl_vconfig_pairs_iter(lua_State *L)
Iterate through the attributes of a vconfig.
Definition: lua_common.cpp:292
LUALIB_API const char * luaL_checklstring(lua_State *L, int arg, size_t *len)
Definition: lauxlib.cpp:390
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_TBOOLEAN
Definition: lua.h:65
LUA_API int lua_next(lua_State *L, int idx)
Definition: lapi.cpp:1123
utils::string_view luaW_tostring_or_default(lua_State *L, int index, utils::string_view def)
Definition: lua_common.cpp:988
bool luaW_tolocation(lua_State *L, int index, map_location &loc)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:673
LUA_API const char * lua_typename(lua_State *L, int t)
Definition: lapi.cpp:257
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:384
static game_display * get_singleton()
std::string str(const std::string &fallback="") const
#define luaL_checkstring(L, n)
Definition: lauxlib.h:124