The Battle for Wesnoth  1.15.12+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_newuserdatauv(L, l + 1, 0);
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, int nuv)
500 {
501  return lua_newuserdatauv(L, sz, nuv);
502 }
503 
504 void operator delete(void*, lua_State *L, int)
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
542 #ifdef USING_BOOST_VARIANT
543  : boost::static_visitor<>
544 #endif
545  {
546  lua_State *L;
547  luaW_pushscalar_visitor(lua_State *l): L(l) {}
548 
549  void operator()(const utils::monostate&) const
550  { lua_pushnil(L); }
551  void operator()(bool b) const
552  { lua_pushboolean(L, b); }
553  void operator()(int i) const
554  { lua_pushinteger(L, i); }
555  void operator()(unsigned long long ull) const
556  { lua_pushnumber(L, ull); }
557  void operator()(double d) const
558  { lua_pushnumber(L, d); }
559  void operator()(const std::string& s) const
560  { lua_pushstring(L, s.c_str()); }
561  void operator()(const t_string& s) const
562  { luaW_pushtstring(L, s); }
563  };
564 }//unnamed namespace for luaW_pushscalar_visitor
565 
567 {
568  v.apply_visitor(luaW_pushscalar_visitor(L));
569 }
570 
572 {
573  switch (lua_type(L, index)) {
574  case LUA_TBOOLEAN:
575  v = luaW_toboolean(L, -1);
576  break;
577  case LUA_TNUMBER:
578  v = lua_tonumber(L, -1);
579  break;
580  case LUA_TSTRING:
581  v = lua_tostring(L, -1);
582  break;
583  case LUA_TUSERDATA:
584  {
585  if (t_string * tptr = static_cast<t_string *>(luaL_testudata(L, -1, tstringKey))) {
586  v = *tptr;
587  break;
588  } else {
589  return false;
590  }
591  }
592  default:
593  return false;
594  }
595  return true;
596 }
597 
599 {
600  switch (lua_type(L, index)) {
601  case LUA_TBOOLEAN:
602  str = lua_toboolean(L, index) ? "yes" : "no";
603  break;
604  case LUA_TNUMBER:
605  case LUA_TSTRING:
606  str = lua_tostring(L, index);
607  break;
608  case LUA_TUSERDATA:
609  {
610  if (t_string * tstr = static_cast<t_string *> (luaL_testudata(L, index, tstringKey))) {
611  str = *tstr;
612  break;
613  } else {
614  return false;
615  }
616  }
617  default:
618  return false;
619  }
620  return true;
621 }
622 
624 {
625  t_string result;
626  if (!luaW_totstring(L, index, result))
627  luaW_type_error(L, index, "translatable string");
628  return result;
629 }
630 
632 {
633  if(lua_isstring(L, index)) {
634  return true;
635  }
636  if(lua_isuserdata(L, index) && luaL_testudata(L, index, tstringKey)) {
637  return true;
638  }
639  return false;
640 }
641 
642 void luaW_filltable(lua_State *L, const config& cfg)
643 {
644  if (!lua_checkstack(L, LUA_MINSTACK))
645  return;
646 
647  int k = 1;
648  for (const config::any_child &ch : cfg.all_children_range())
649  {
650  lua_createtable(L, 2, 0);
651  lua_pushstring(L, ch.key.c_str());
652  lua_rawseti(L, -2, 1);
653  lua_newtable(L);
654  luaW_filltable(L, ch.cfg);
655  lua_rawseti(L, -2, 2);
656  lua_rawseti(L, -2, k++);
657  }
658  for (const config::attribute &attr : cfg.attribute_range())
659  {
660  luaW_pushscalar(L, attr.second);
661  lua_setfield(L, -2, attr.first.c_str());
662  }
663 }
664 
666 {
667  lua_createtable(L, 2, 0);
668 
669  lua_pushinteger(L, ml.wml_x());
670  lua_rawseti(L, -2, 1);
671 
672  lua_pushinteger(L, ml.wml_y());
673  lua_rawseti(L, -2, 2);
674 }
675 
677  if (!lua_checkstack(L, LUA_MINSTACK)) {
678  return false;
679  }
680  if (lua_isnoneornil(L, index)) {
681  // Need this special check because luaW_tovconfig returns true in this case
682  return false;
683  }
684 
686 
687  index = lua_absindex(L, index);
688 
689  if (lua_istable(L, index) || luaW_tounit(L, index) || luaW_tovconfig(L, index, dummy_vcfg)) {
690  map_location result;
691  int x_was_num = 0, y_was_num = 0;
692  lua_getfield(L, index, "x");
693  result.set_wml_x(lua_tonumberx(L, -1, &x_was_num));
694  lua_getfield(L, index, "y");
695  result.set_wml_y(lua_tonumberx(L, -1, &y_was_num));
696  lua_pop(L, 2);
697  if (!x_was_num || !y_was_num) {
698  // If we get here and it was userdata, checking numeric indices won't help
699  // (It won't help if it was a config either, but there's no easy way to check that.)
700  if (lua_isuserdata(L, index)) {
701  return false;
702  }
703  lua_rawgeti(L, index, 1);
704  result.set_wml_x(lua_tonumberx(L, -1, &x_was_num));
705  lua_rawgeti(L, index, 2);
706  result.set_wml_y(lua_tonumberx(L, -1, &y_was_num));
707  lua_pop(L, 2);
708  }
709  if (x_was_num && y_was_num) {
710  loc = result;
711  return true;
712  }
713  } else if (lua_isnumber(L, index) && lua_isnumber(L, index + 1)) {
714  // If it's a number, then we consume two elements on the stack
715  // Since we have no way of notifying the caller that we have
716  // done this, we remove the first number from the stack.
717  loc.set_wml_x(lua_tonumber(L, index));
718  lua_remove(L, index);
719  loc.set_wml_y(lua_tonumber(L, index));
720  return true;
721  }
722  return false;
723 }
724 
726 {
727  map_location result;
728  if (!luaW_tolocation(L, index, result))
729  luaW_type_error(L, index, "location");
730  return result;
731 }
732 
733 void luaW_pushconfig(lua_State *L, const config& cfg)
734 {
735  lua_newtable(L);
736  luaW_filltable(L, cfg);
737 }
738 
739 
740 
741 
742 #define return_misformed() \
743  do { lua_settop(L, initial_top); return false; } while (0)
744 
745 bool luaW_toconfig(lua_State *L, int index, config &cfg)
746 {
747  if (!lua_checkstack(L, LUA_MINSTACK))
748  return false;
749 
750  // Get the absolute index of the table.
751  index = lua_absindex(L, index);
752  int initial_top = lua_gettop(L);
753 
754  switch (lua_type(L, index))
755  {
756  case LUA_TTABLE:
757  break;
758  case LUA_TUSERDATA:
759  {
760  if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) {
761  cfg = ptr->get_parsed_config();
762  return true;
763  } else {
764  return false;
765  }
766  }
767  case LUA_TNONE:
768  case LUA_TNIL:
769  return true;
770  default:
771  return false;
772  }
773 
774  // First convert the children (integer indices).
775  for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i)
776  {
777  lua_rawgeti(L, index, i);
778  if (!lua_istable(L, -1)) return_misformed();
779  lua_rawgeti(L, -1, 1);
780  char const *m = lua_tostring(L, -1);
781  if (!m || !config::valid_tag(m)) return_misformed();
782  lua_rawgeti(L, -2, 2);
783  if (!luaW_toconfig(L, -1, cfg.add_child(m)))
785  lua_pop(L, 3);
786  }
787 
788  // Then convert the attributes (string indices).
789  for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1))
790  {
791  int indextype = lua_type(L, -2);
792  if (indextype == LUA_TNUMBER) continue;
793  if (indextype != LUA_TSTRING) return_misformed();
794  const char* m = lua_tostring(L, -2);
796  config::attribute_value &v = cfg[m];
797  if (lua_istable(L, -1)) {
798  int subindex = lua_absindex(L, -1);
799  std::ostringstream str;
800  for (int i = 1, i_end = lua_rawlen(L, subindex); i <= i_end; ++i, lua_pop(L, 1)) {
801  lua_rawgeti(L, -1, i);
803  if (!luaW_toscalar(L, -1, item)) return_misformed();
804  if (i > 1) str << ',';
805  str << item;
806  }
807  // If there are any string keys, it's malformed
808  for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) {
809  if (lua_type(L, -2) != LUA_TNUMBER) return_misformed();
810  }
811  v = str.str();
812  } else if (!luaW_toscalar(L, -1, v)) return_misformed();
813  }
814 
815  lua_settop(L, initial_top);
816  return true;
817 }
818 
819 #undef return_misformed
820 
821 
823 {
824  config result;
825  if (!luaW_toconfig(L, index, result))
826  luaW_type_error(L, index, "WML table");
827  return result;
828 }
829 
831 {
832  config result = luaW_checkconfig(L, index);
833  if(void* p = luaL_testudata(L, index, vconfigKey)) {
834  vcfg = static_cast<vconfig*>(p);
835  }
836  return result;
837 }
838 
839 bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
840 {
841  switch (lua_type(L, index))
842  {
843  case LUA_TTABLE:
844  {
845  config cfg;
846  bool ok = luaW_toconfig(L, index, cfg);
847  if (!ok) return false;
848  vcfg = vconfig(std::move(cfg));
849  break;
850  }
851  case LUA_TUSERDATA:
852  if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) {
853  vcfg = *ptr;
854  } else {
855  return false;
856  }
857  case LUA_TNONE:
858  case LUA_TNIL:
859  break;
860  default:
861  return false;
862  }
863  return true;
864 }
865 
866 vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing)
867 {
869  if (!luaW_tovconfig(L, index, result) || (!allow_missing && result.null()))
870  luaW_type_error(L, index, "WML table");
871  return result;
872 }
873 
874 bool luaW_getglobal(lua_State *L, const std::vector<std::string>& path)
875 {
877  for (const std::string& s : path)
878  {
879  if (!lua_istable(L, -1)) goto discard;
880  lua_pushlstring(L, s.c_str(), s.size());
881  lua_rawget(L, -2);
882  lua_remove(L, -2);
883  }
884 
885  if (lua_isnil(L, -1)) {
886  discard:
887  lua_pop(L, 1);
888  return false;
889  }
890  return true;
891 }
892 
894 {
895  return lua_toboolean(L,n) != 0;
896 }
897 
899 {
900  try
901  {
902  if(v.exists_as_attribute())
903  {
904  luaW_pushscalar(L, v.as_scalar());
905  return true;
906  }
907  else if(v.exists_as_container())
908  {
909  lua_newtable(L);
911  return true;
912  }
913  else
914  {
915  lua_pushnil(L);
916  return true;
917  }
918  }
919  catch (const invalid_variablename_exception&)
920  {
921  WRN_LUA << v.get_error_message() << "\n";
922  return false;
923  }
924 }
925 
927 {
928  int variabletype = lua_type(L, n);
929  try
930  {
931  switch (variabletype) {
932  case LUA_TBOOLEAN:
933  v.as_scalar() = luaW_toboolean(L, n);
934  return true;
935  case LUA_TNUMBER:
936  v.as_scalar() = lua_tonumber(L, n);
937  return true;
938  case LUA_TSTRING:
939  v.as_scalar() = lua_tostring(L, n);
940  return true;
941  case LUA_TUSERDATA:
942  if (t_string * t_str = static_cast<t_string*> (luaL_testudata(L, n, tstringKey))) {
943  v.as_scalar() = *t_str;
944  return true;
945  }
946  goto default_explicit;
947  case LUA_TTABLE:
948  {
949  config &cfg = v.as_container();
950  cfg.clear();
951  if (luaW_toconfig(L, n, cfg)) {
952  return true;
953  }
954  [[fallthrough]];
955  }
956  default:
957  default_explicit:
958  return luaW_type_error(L, n, "WML table or scalar") != 0;
959 
960  }
961  }
962  catch (const invalid_variablename_exception&)
963  {
964  WRN_LUA << v.get_error_message() << " when attempting to write a '" << lua_typename(L, variabletype) << "'\n";
965  return false;
966  }
967 }
968 
969 bool luaW_tableget(lua_State *L, int index, const char* key)
970 {
971  index = lua_absindex(L, index);
972  lua_pushstring(L, key);
973  lua_gettable(L, index);
974  if(lua_isnoneornil(L, -1)) {
975  lua_pop(L, 1);
976  return false;
977  }
978  return true;
979 }
980 
981 std::string_view luaW_tostring(lua_State *L, int index)
982 {
983  size_t len = 0;
984  const char* str = lua_tolstring(L, index, &len);
985  if(!str) {
986  throw luaL_error (L, "not a string");
987  }
988  return std::string_view(str, len);
989 }
990 
991 std::string_view luaW_tostring_or_default(lua_State *L, int index, std::string_view def)
992 {
993  size_t len = 0;
994  const char* str = lua_tolstring(L, index, &len);
995  if(!str) {
996  return def;
997  }
998  return std::string_view(str, len);
999 }
1000 
1001 void chat_message(const std::string& caption, const std::string& msg)
1002 {
1003  if (!game_display::get_singleton()) return;
1004  game_display::get_singleton()->get_chat_manager().add_chat_message(std::time(nullptr), caption, 0, msg,
1006 }
1007 
1009 {
1010  luaW_getglobal(L, "debug", "traceback");
1012 }
1013 
1014 int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
1015 {
1016  // Load the error handler before the function and its arguments.
1018  lua_insert(L, -2 - nArgs);
1019 
1020  int error_handler_index = lua_gettop(L) - nArgs - 1;
1021 
1022  // Call the function.
1023  int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
1024 
1026 
1027  // Remove the error handler.
1028  lua_remove(L, error_handler_index);
1029 
1030  return errcode;
1031 }
1032 
1033 #ifdef _MSC_VER
1034 #pragma warning (push)
1035 #pragma warning (disable: 4706)
1036 #endif
1037 bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
1038 {
1039  int res = luaW_pcall_internal(L, nArgs, nRets);
1040 
1041  if (res)
1042  {
1043  /*
1044  * When an exception is thrown which doesn't derive from
1045  * std::exception m will be nullptr pointer.
1046  */
1047  char const *m = lua_tostring(L, -1);
1048  if(m) {
1049  if (allow_wml_error && strncmp(m, "~wml:", 5) == 0) {
1050  m += 5;
1051  char const *e = strstr(m, "stack traceback");
1052  lg::wml_error() << std::string(m, e ? e - m : strlen(m));
1053  } else if (allow_wml_error && strncmp(m, "~lua:", 5) == 0) {
1054  m += 5;
1055  char const *e = nullptr, *em = m;
1056  while (em[0] && ((em = strstr(em + 1, "stack traceback"))))
1057 #ifdef _MSC_VER
1058 #pragma warning (pop)
1059 #endif
1060  e = em;
1061  chat_message("Lua error", std::string(m, e ? e - m : strlen(m)));
1062  } else {
1063  ERR_LUA << m << '\n';
1064  chat_message("Lua error", m);
1065  }
1066  } else {
1067  chat_message("Lua caught unknown exception", "");
1068  }
1069  lua_pop(L, 1);
1070  return false;
1071  }
1072 
1073  return true;
1074 }
1075 
1076 // Originally luaL_typerror, now deprecated.
1077 // Easier to define it for Wesnoth and not have to worry about it if we update Lua.
1078 int luaW_type_error(lua_State *L, int narg, const char *tname) {
1079  const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, narg));
1080  return luaL_argerror(L, narg, msg);
1081 }
1082 
1083 // An alternate version which raises an error for a key in a table.
1084 // In this version, narg should refer to the stack index of the table rather than the stack index of the key.
1085 // kpath should be the key name or a string such as "key[idx].key2" specifying a path to the key.
1086 int luaW_type_error (lua_State *L, int narg, const char* kpath, const char *tname) {
1087  const char *msg = lua_pushfstring(L, "%s expected for '%s', got %s", tname, kpath, luaL_typename(L, narg));
1088  return luaL_argerror(L, narg, msg);
1089 }
void set_wml_y(int v)
Definition: location.hpp:156
#define WRN_LUA
Definition: lua_common.cpp:53
bool luaW_checkvariable(lua_State *L, variable_access_create &v, int n)
Definition: lua_common.cpp:926
bool luaW_tableget(lua_State *L, int index, const char *key)
Definition: lua_common.cpp:969
void chat_message(const std::string &caption, const std::string &msg)
Displays a message in the chat window.
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:379
LUALIB_API void * luaL_checkudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:345
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:728
#define lua_pushcfunction(L, f)
Definition: lua.h:370
static bool valid_tag(config_key_type name)
Definition: config.cpp:179
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:355
const_all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:953
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:839
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:733
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:173
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:260
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:480
#define LUA_TUSERDATA
Definition: lua.h:72
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:581
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:710
Variant for storing WML attributes.
#define a
std::string_view luaW_tostring_or_default(lua_State *L, int index, std::string_view def)
Definition: lua_common.cpp:991
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:456
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:99
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:889
LUALIB_API int luaL_getmetafield(lua_State *L, int obj, const char *event)
Definition: lauxlib.cpp:823
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:168
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:898
attribute_map::value_type attribute
Definition: config.hpp:220
LUA_API int lua_gettable(lua_State *L, int idx)
Definition: lapi.cpp:640
#define lua_remove(L, idx)
Definition: lua.h:391
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
Definition: lua_common.cpp:93
#define lua_tointeger(L, i)
Definition: lua.h:362
int wml_x() const
Definition: location.hpp:152
~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:698
void set_wml_x(int v)
Definition: location.hpp:155
const char * c_str() const
Definition: tstring.hpp:191
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:361
static bool valid_attribute(config_key_type name)
Definition: config.cpp:202
#define luaL_typename(L, i)
Definition: lauxlib.h:141
LUA_API int lua_checkstack(lua_State *L, int n)
Definition: lapi.cpp:98
Additional functionality for a non-const variable_info.
const t_string_base & get() const
Definition: tstring.hpp:199
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:895
LUA_API int lua_isuserdata(lua_State *L, int idx)
Definition: lapi.cpp:298
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n)
Definition: lapi.cpp:555
#define d
#define ERR_LUA
Definition: lua_common.cpp:54
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:324
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:384
std::string get_key() const
Definition: variable.cpp:447
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:725
Definitions for the interface to Wesnoth Markup Language (WML).
LUA_API int lua_absindex(lua_State *L, int idx)
Definition: lapi.cpp:161
const_attr_itors attribute_range() const
Definition: config.cpp:833
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:364
std::string::size_type size() const
Definition: tstring.hpp:187
#define return_misformed()
Definition: lua_common.cpp:742
#define b
#define lua_upvalueindex(i)
Definition: lua.h:45
#define lua_pcall(L, n, r, f)
Definition: lua.h:287
#define LUA_TSTRING
Definition: lua.h:69
LUALIB_API int luaL_argerror(lua_State *L, int arg, const char *extramsg)
Definition: lauxlib.cpp:175
std::string register_vconfig_metatable(lua_State *L)
Adds the vconfig metatable.
Definition: lua_common.cpp:462
#define LUA_TNONE
Definition: lua.h:63
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil...
Definition: lua_common.cpp:874
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:292
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:893
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:142
#define LUA_TNIL
Definition: lua.h:65
LUA_API void * lua_newuserdatauv(lua_State *L, size_t size, int nuvalue)
Definition: lapi.cpp:1311
int wml_y() const
Definition: location.hpp:153
all_children_iterator ordered_end() const
Definition: variable.cpp:485
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:375
void luaW_filltable(lua_State *L, const config &cfg)
Converts a config object to a Lua table.
Definition: lua_common.cpp:642
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:623
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:566
#define lua_pushglobaltable(L)
Definition: lua.h:383
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:502
#define LUA_TNUMBER
Definition: lua.h:68
LUA_API int lua_setmetatable(lua_State *L, int objindex)
Definition: lapi.cpp:901
std::string path
Definition: game_config.cpp:38
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:381
boost::iterator_range< const_attribute_iterator > const_attr_itors
Definition: config.hpp:280
LUALIB_API void * luaL_testudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:330
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:366
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:473
LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.cpp:481
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:37
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:745
bool luaW_totstring(lua_State *L, int index, t_string &str)
Converts a scalar to a translatable string.
Definition: lua_common.cpp:598
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:311
LUA_API void * lua_touserdata(lua_State *L, int idx)
Definition: lapi.cpp:432
#define lua_isnil(L, n)
Definition: lua.h:375
static const char vconfigpairsKey[]
Definition: lua_common.cpp:46
std::size_t i
Definition: function.cpp:940
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:288
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int arg)
Definition: lauxlib.cpp:442
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:877
config::attribute_value expand(const std::string &) const
Definition: variable.cpp:352
static const char gettextKey[]
Definition: lua_common.cpp:44
bool luaW_iststring(lua_State *L, int index)
Definition: lua_common.cpp:631
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:822
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:386
#define LUA_MINSTACK
Definition: lua.h:80
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.cpp:246
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:285
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:234
config & add_child(config_key_type key)
Definition: config.cpp:500
std::pair< vconfig::all_children_iterator, vconfig::all_children_iterator > vconfig_child_range
Definition: lua_common.cpp:345
display_chat_manager & get_chat_manager()
LUA_API lua_Unsigned lua_rawlen(lua_State *L, int idx)
Definition: lapi.cpp:402
#define LUA_REGISTRYINDEX
Definition: lua.h:44
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:373
bool exists_as_container() const
std::string_view luaW_tostring(lua_State *L, int index)
Definition: lua_common.cpp:981
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:665
#define lua_insert(L, idx)
Definition: lua.h:389
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:571
A variable-expanding proxy for the config class.
Definition: variable.hpp:44
const config & get_config() const
Definition: variable.hpp:75
Standard logging facilities (interface).
auto apply_visitor(const V &visitor) const
Visitor support: Applies a visitor to the underlying variant.
LUA_API const char * lua_pushfstring(lua_State *L, const char *fmt,...)
Definition: lapi.cpp:542
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:866
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:904
void push_error_handler(lua_State *L)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
bool null() const
Definition: variable.hpp:72
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:655
#define LUA_TTABLE
Definition: lua.h:70
static map_location::DIRECTION n
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:489
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:402
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:514
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:837
#define LUA_TBOOLEAN
Definition: lua.h:66
LUA_API int lua_next(lua_State *L, int idx)
Definition: lapi.cpp:1220
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:676
LUA_API const char * lua_typename(lua_State *L, int t)
Definition: lapi.cpp:266
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:409
static game_display * get_singleton()
std::string str(const std::string &fallback="") const
#define luaL_checkstring(L, n)
Definition: lauxlib.h:138