49 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
50 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
51 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
54 #define ERR_WML LOG_STREAM(err, log_wml)
66 char const *m = luaL_checkstring(L, 2);
67 char const *
d =
static_cast<char *
>(lua_touserdata(L, 1));
69 if(lua_isstring(L, 3)) {
70 const char* pl = luaL_checkstring(L, 3);
71 int count = luaL_checkinteger(L, 4);
81 char*
d =
static_cast<char*
>(lua_touserdata(L, 1));
82 using namespace std::literals;
83 std::string str =
"textdomain: "s +
d;
96 char const *m = luaL_checklstring(L, 1, &l);
98 void *
p = lua_newuserdatauv(L, l + 1, 0);
114 switch (lua_type(L,
src)) {
117 dst += lua_tostring(L,
src);
150 lua_pushnumber(L,
t->size());
160 t->t_string::~t_string();
195 lua_pushstring(L,
t->c_str());
208 if (lua_isnumber(L, 2))
212 unsigned pos = lua_tointeger(L, 2) - 1;
213 if (pos >= len)
return 0;
214 std::advance(
i, pos);
216 lua_createtable(L, 2, 0);
217 lua_pushstring(L,
i.get_key().c_str());
218 lua_rawseti(L, -2, 1);
220 lua_rawseti(L, -2, 2);
224 char const *m = luaL_checkstring(L, 2);
225 if (strcmp(m,
"__literal") == 0) {
229 if (strcmp(m,
"__parsed") == 0) {
234 bool shallow_literal = strcmp(m,
"__shallow_literal") == 0;
235 if (shallow_literal || strcmp(m,
"__shallow_parsed") == 0)
243 lua_setfield(L, -2, key.c_str());
247 if (shallow_literal) {
248 i.disable_insertion();
249 i_end.disable_insertion();
251 for (
int j = 1;
i != i_end; ++
i, ++j)
254 lua_pushstring(L,
i.get_key().c_str());
255 lua_rawseti(L, -2, 1);
257 lua_rawseti(L, -2, 2);
258 lua_rawseti(L, -2, j);
271 std::vector<std::string> attributes;
273 attributes.push_back(key);
285 lua_pushinteger(L, v->
null() ? 0 :
313 lua_pushlstring(L, value.first.c_str(), value.first.length());
324 void*
p = lua_touserdata(L, 1);
327 #if defined(_MSC_VER)
328 #pragma warning(push)
329 #pragma warning(disable: 4189)
332 const_attr_itors* cai =
static_cast<const_attr_itors*
>(
p);
333 cai->~const_attr_itors();
335 #if defined(_MSC_VER)
350 lua_setmetatable(L, -2);
364 int i = luaL_checkinteger(L, 2);
367 if (range.first == range.second) {
370 std::pair<std::string, vconfig> value = *range.first++;
371 lua_pushinteger(L,
i + 1);
372 lua_createtable(L, 2, 0);
373 lua_pushlstring(L, value.first.c_str(), value.first.length());
374 lua_rawseti(L, -2, 1);
376 lua_rawseti(L, -2, 2);
385 void*
p = lua_touserdata(L, 1);
387 vcr->~vconfig_child_range();
399 lua_setmetatable(L, -2);
402 lua_pushinteger(L, 0);
425 static luaL_Reg
const callbacks[] {
430 luaL_setfuncs(L, callbacks, 0);
432 lua_pushstring(L,
"message domain");
433 lua_setfield(L, -2,
"__metatable");
435 return "Adding gettext metatable...\n";
445 static luaL_Reg
const callbacks[] {
455 luaL_setfuncs(L, callbacks, 0);
457 lua_createtable(L, 0, 1);
459 lua_setfield(L, -2,
"format");
461 lua_setfield(L, -2,
"vformat");
462 lua_setfield(L, -2,
"__index");
464 lua_pushstring(L,
"translatable string");
465 lua_setfield(L, -2,
"__metatable");
467 return "Adding tstring metatable...\n";
477 static luaL_Reg
const callbacks[] {
486 luaL_setfuncs(L, callbacks, 0);
488 lua_pushstring(L,
"wml object");
489 lua_setfield(L, -2,
"__metatable");
497 lua_pushstring(L,
"__gc");
502 lua_pushstring(L,
"__gc");
506 return "Adding vconfig metatable...\n";
511 void*
operator new(std::size_t sz, lua_State *L,
int nuv)
513 return lua_newuserdatauv(L, sz, nuv);
516 void operator delete(
void*, lua_State *L, int)
533 if(
n >= 2 && key[0] ==
'_' && key[1] ==
'_') {
536 return luaL_getmetafield(L, idx, key) != 0;
553 struct luaW_pushscalar_visitor
554 #ifdef USING_BOOST_VARIANT
555 : boost::static_visitor<>
559 luaW_pushscalar_visitor(lua_State *l): L(l) {}
561 void operator()(
const utils::monostate&)
const
563 void operator()(
bool b)
const
564 { lua_pushboolean(L,
b); }
565 void operator()(
int i)
const
566 { lua_pushinteger(L,
i); }
567 void operator()(
unsigned long long ull)
const
568 { lua_pushnumber(L, ull); }
569 void operator()(
double d)
const
570 { lua_pushnumber(L,
d); }
571 void operator()(
const std::string&
s)
const
572 { lua_pushstring(L,
s.c_str()); }
585 switch (lua_type(L,
index)) {
590 v = lua_tonumber(L, -1);
593 v = lua_tostring(L, -1);
612 switch (lua_type(L,
index)) {
614 str = lua_toboolean(L,
index) ?
"yes" :
"no";
618 str = lua_tostring(L,
index);
645 if(lua_isstring(L,
index)) {
656 if (!lua_checkstack(L, LUA_MINSTACK))
663 lua_pushstring(L, child_key.c_str());
664 lua_rawseti(L, -2, 1);
667 lua_rawseti(L, -2, 2);
668 lua_rawseti(L, -2, k++);
673 lua_setfield(L, -2, key.c_str());
679 if(lua_isstring(L, 2)) {
680 std::string k = lua_tostring(L, 2);
681 luaL_getmetafield(L, 1,
"__names");
682 auto names = lua_check<std::vector<std::string>>(L, -1);
683 auto iter = std::find(
names.begin(),
names.end(), k);
684 if(iter !=
names.end()) {
685 int i = std::distance(
names.begin(), iter) + 1;
686 lua_rawgeti(L, 1,
i);
695 luaL_getmetafield(L, 1,
"__names");
701 std::vector<std::string> elems;
702 for(
unsigned i = 1;
i <= lua_rawlen(L, 1);
i++) {
703 lua_getglobal(L,
"tostring");
704 lua_rawgeti(L, 1,
i);
706 elems.push_back(lua_tostring(L, -1));
714 lua_createtable(L,
names.size(), 0);
715 lua_createtable(L, 0, 4);
716 static luaL_Reg callbacks[] = {
722 luaL_setfuncs(L, callbacks, 0);
723 static const char baseName[] =
"named tuple";
724 std::ostringstream str;
725 str << baseName <<
'(';
729 for(
size_t i = 1;
i <
names.size();
i++) {
734 lua_setfield(L, -2,
"__metatable");
736 lua_setfield(L, -2,
"__names");
737 lua_setmetatable(L, -2);
744 lua_pushinteger(L, ml.
wml_x());
745 lua_rawseti(L, -2, 1);
747 lua_pushinteger(L, ml.
wml_y());
748 lua_rawseti(L, -2, 2);
752 if (!lua_checkstack(L, LUA_MINSTACK)) {
755 if (lua_isnoneornil(L,
index)) {
764 if (lua_istable(L,
index) || lua_isuserdata(L,
index)) {
766 int x_was_num = 0, y_was_num = 0;
767 lua_getfield(L,
index,
"x");
768 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
769 lua_getfield(L,
index,
"y");
770 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
772 if (!x_was_num || !y_was_num) {
775 if (lua_isuserdata(L,
index)) {
778 lua_rawgeti(L,
index, 1);
779 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
780 lua_rawgeti(L,
index, 2);
781 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
784 if (x_was_num && y_was_num) {
788 }
else if (lua_isnumber(L,
index) && lua_isnumber(L,
index + 1)) {
793 lua_remove(L,
index);
810 lua_createtable(L, locs.size(), 0);
814 lua_rawseti(L, -2,
i);
822 std::set<map_location> locs;
823 if(!lua_istable(L, idx)) {
827 int len = luaL_checkinteger(L, -1);
828 for(
int i = 1;
i <= len;
i++) {
846 #define return_misformed() \
847 do { lua_settop(L, initial_top); return false; } while (0)
852 if (!lua_checkstack(L, LUA_MINSTACK))
857 int initial_top = lua_gettop(L);
859 switch (lua_type(L,
index))
866 cfg = ptr->get_parsed_config();
880 for (
int i = 1, i_end = lua_rawlen(L,
index);
i <= i_end; ++
i)
884 lua_rawgeti(L, -1, 1);
885 char const *m = lua_tostring(L, -1);
887 lua_rawgeti(L, -2, 2);
894 for (lua_pushnil(L); lua_next(L,
index); lua_pop(L, 1))
896 int indextype = lua_type(L, -2);
897 if (indextype == LUA_TNUMBER)
continue;
899 const char* m = lua_tostring(L, -2);
902 if (lua_istable(L, -1)) {
903 int subindex = lua_absindex(L, -1);
904 std::ostringstream str;
905 for (
int i = 1, i_end = lua_rawlen(L, subindex);
i <= i_end; ++
i, lua_pop(L, 1)) {
906 lua_rawgeti(L, -1,
i);
909 if (
i > 1) str <<
',';
913 for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) {
920 lua_settop(L, initial_top);
924 #undef return_misformed
946 switch (lua_type(L,
index))
952 if (!ok)
return false;
953 vcfg =
vconfig(std::move(cfg));
981 lua_pushglobaltable(L);
982 for (
const std::string&
s :
path)
984 if (!lua_istable(L, -1))
goto discard;
985 lua_pushlstring(L,
s.c_str(),
s.size());
990 if (lua_isnil(L, -1)) {
1000 return lua_toboolean(L,
n) != 0;
1033 int variabletype = lua_type(L,
n);
1036 switch (variabletype) {
1051 goto default_explicit;
1076 lua_pushstring(L, key);
1077 lua_gettable(L,
index);
1078 if(lua_isnoneornil(L, -1)) {
1088 const char* str = lua_tolstring(L,
index, &len);
1090 throw luaL_error (L,
"not a string");
1092 return std::string_view(str, len);
1098 const char* str = lua_tolstring(L,
index, &len);
1102 return std::string_view(str, len);
1115 lua_setfield(L, LUA_REGISTRYINDEX,
executeKey);
1121 lua_getfield(L, LUA_REGISTRYINDEX,
executeKey);
1122 lua_insert(L, -2 - nArgs);
1124 int error_handler_index = lua_gettop(L) - nArgs - 1;
1129 int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
1135 lua_remove(L, error_handler_index);
1141 #pragma warning (push)
1142 #pragma warning (disable: 4706)
1144 bool luaW_pcall(lua_State *L,
int nArgs,
int nRets,
bool allow_wml_error)
1156 char const *m = lua_tostring(L, -1);
1158 if (allow_wml_error && strncmp(m,
"~wml:", 5) == 0) {
1160 char const *
e = strstr(m,
"stack traceback");
1162 ERR_WML << std::string(m,
e ?
e - m : strlen(m));
1163 }
else if (allow_wml_error && strncmp(m,
"~lua:", 5) == 0) {
1165 char const *
e =
nullptr, *em = m;
1166 while (em[0] && ((em = strstr(em + 1,
"stack traceback"))))
1168 #pragma warning (pop)
1171 ERR_LUA << std::string(m,
e ?
e - m : strlen(m));
1172 chat_message(
"Lua error", std::string(m,
e ?
e - m : strlen(m)));
1178 ERR_LUA <<
"Lua caught unknown exception";
1191 const char *
msg = lua_pushfstring(L,
"%s expected, got %s", tname, luaL_typename(L, narg));
1192 return luaL_argerror(L, narg,
msg);
1199 const char *
msg = lua_pushfstring(L,
"%s expected for '%s', got %s", tname, kpath, luaL_typename(L, narg));
1200 return luaL_argerror(L, narg,
msg);
std::vector< std::string > names
Variant for storing WML attributes.
std::string str(const std::string &fallback="") const
auto apply_visitor(const V &visitor) const
Visitor support: Applies a visitor to the underlying variant.
A config object defines a single node in a WML file, with access to child nodes.
const_attr_itors attribute_range() const
auto all_children_view() const
In-order iteration over all children.
static bool valid_tag(config_key_type name)
boost::iterator_range< const_attribute_iterator > const_attr_itors
static bool valid_attribute(config_key_type name)
attribute_map::value_type attribute
config & add_child(config_key_type key)
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)
static game_display * get_singleton()
display_chat_manager & get_chat_manager()
static void rethrow()
Rethrows the stored exception.
static int jail_depth
Depth of recursive luaW_pcall_internal() function calls.
const t_string_base & get() const
Additional functionality for a non-const variable_info.
Information on a WML variable.
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...
std::string get_error_message() const
bool exists_as_container() const
maybe_const_t< config, V > & as_container() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
bool exists_as_attribute() const
A variable-expanding proxy for the config class.
~vconfig()
Default destructor, but defined here for possibly faster compiles (templates sometimes can be rough o...
all_children_iterator ordered_begin() const
In-order iteration over all children.
bool has_attribute(const std::string &key) const
< Synonym for operator[]
static vconfig unconstructed_vconfig()
This is just a wrapper for the default constructor; it exists for historical reasons and to make it c...
config::attribute_value expand(const std::string &) const
const config & get_config() const
config get_parsed_config() const
all_children_iterator ordered_end() const
Definitions for the interface to Wesnoth Markup Language (WML).
Standard logging facilities (interface).
void luaW_pushconfig(lua_State *L, const config &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
void luaW_filltable(lua_State *L, const config &cfg)
Converts a config object to a Lua table.
void chat_message(const std::string &caption, const std::string &msg)
Displays a message in the chat window.
void push_error_handler(lua_State *L)
static const char executeKey[]
static lg::log_domain log_scripting_lua("scripting/lua")
bool luaW_iststring(lua_State *L, int index)
static const char vconfigKey[]
static int impl_namedtuple_tostring(lua_State *L)
void luaW_push_namedtuple(lua_State *L, const std::vector< std::string > &names)
Push an empty "named tuple" onto the stack.
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
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.
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.
void luaW_pushtstring(lua_State *L, const t_string &v)
Pushes a t_string on the top of the stack.
bool luaW_pushvariable(lua_State *L, variable_access_const &v)
bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
Gets an optional vconfig from either a table or a userdata.
void luaW_pushvconfig(lua_State *L, const vconfig &cfg)
Pushes a vconfig on the top of the stack.
bool luaW_toboolean(lua_State *L, int n)
static const char vconfigpairsKey[]
int luaW_type_error(lua_State *L, int narg, const char *tname)
#define return_misformed()
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.
std::string_view luaW_tostring(lua_State *L, int index)
static const char tstringKey[]
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.
static int impl_namedtuple_dir(lua_State *L)
static const char gettextKey[]
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.
bool luaW_totstring(lua_State *L, int index, t_string &str)
Converts a scalar to a translatable string.
bool luaW_tableget(lua_State *L, int index, const char *key)
std::string_view luaW_tostring_or_default(lua_State *L, int index, std::string_view def)
bool luaW_checkvariable(lua_State *L, variable_access_create &v, int n)
static lg::log_domain log_wml("wml")
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.
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
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.
vconfig luaW_checkvconfig(lua_State *L, int index, bool allow_missing)
Gets an optional vconfig from either a table or a userdata.
static int impl_namedtuple_get(lua_State *L)
bool luaW_tolocation(lua_State *L, int index, map_location &loc)
Converts an optional table or pair of integers to a map location object.
static const char vconfigipairsKey[]
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
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.
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
static int impl_tstring_concat(lua_State *L)
Appends a scalar to a t_string object (__concat metamethod).
std::pair< vconfig::all_children_iterator, vconfig::all_children_iterator > vconfig_child_range
int intf_textdomain(lua_State *L)
Creates an interface for gettext.
static int impl_vconfig_pairs(lua_State *L)
Construct an iterator to iterate through the attributes of a vconfig.
static int impl_vconfig_ipairs(lua_State *L)
Construct an iterator to iterate through the subtags of a vconfig.
static int impl_tstring_collect(lua_State *L)
Destroys a t_string object before it is collected (__gc metamethod).
static int impl_tstring_eq(lua_State *L)
static int impl_vconfig_ipairs_collect(lua_State *L)
Destroy a vconfig ipairs iterator.
std::string register_gettext_metatable(lua_State *L)
Adds the gettext metatable.
static int impl_tstring_lt(lua_State *L)
std::string register_vconfig_metatable(lua_State *L)
Adds the vconfig metatable.
static int impl_vconfig_get(lua_State *L)
Gets the parsed field of a vconfig object (_index metamethod).
static int impl_vconfig_pairs_collect(lua_State *L)
Destroy a vconfig pairs iterator.
std::string register_tstring_metatable(lua_State *L)
Adds the tstring metatable.
static int impl_gettext(lua_State *L)
Creates a t_string object (__call metamethod).
static int impl_gettext_tostr(lua_State *L)
static int impl_tstring_tostring(lua_State *L)
Converts a t_string object to a string (__tostring metamethod); that is, performs a translation.
static int impl_vconfig_size(lua_State *L)
Returns the number of a child of a vconfig object.
int intf_tovconfig(lua_State *L)
Creates a vconfig containing the WML table.
static int impl_tstring_len(lua_State *L)
static int impl_vconfig_pairs_iter(lua_State *L)
Iterate through the attributes of a vconfig.
static int impl_vconfig_dir(lua_State *L)
static int impl_vconfig_collect(lua_State *L)
Destroys a vconfig object before it is collected (__gc metamethod).
static int impl_tstring_le(lua_State *L)
static int impl_vconfig_ipairs_iter(lua_State *L)
Iterate through the subtags of a vconfig.
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.
int compare(const std::string &s1, const std::string &s2)
Case-sensitive lexicographical comparison.
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.
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
void lua_push(lua_State *L, const T &val)
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
Encapsulates the map of the game.
static map_location::direction n
static map_location::direction s