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