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