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