48 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
49 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
50 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
53 #define ERR_WML LOG_STREAM(err, log_wml)
65 char const *m = luaL_checkstring(L, 2);
66 char const *
d =
static_cast<char *
>(lua_touserdata(L, 1));
68 if(lua_isstring(L, 3)) {
69 const char* pl = luaL_checkstring(L, 3);
70 int count = luaL_checkinteger(L, 4);
80 char*
d =
static_cast<char*
>(lua_touserdata(L, 1));
81 using namespace std::literals;
82 std::string str =
"textdomain: "s +
d;
95 char const *m = luaL_checklstring(L, 1, &l);
97 void *
p = lua_newuserdatauv(L, l + 1, 0);
113 switch (lua_type(L,
src)) {
116 dst += lua_tostring(L,
src);
149 lua_pushnumber(L,
t->size());
159 t->t_string::~t_string();
194 lua_pushstring(L,
t->c_str());
207 if (lua_isnumber(L, 2))
211 unsigned pos = lua_tointeger(L, 2) - 1;
212 if (pos >= len)
return 0;
213 std::advance(
i, pos);
216 lua_pushstring(L,
i.get_key().c_str());
217 lua_rawseti(L, -2, 1);
219 lua_rawseti(L, -2, 2);
223 char const *m = luaL_checkstring(L, 2);
224 if (strcmp(m,
"__literal") == 0) {
228 if (strcmp(m,
"__parsed") == 0) {
233 bool shallow_literal = strcmp(m,
"__shallow_literal") == 0;
234 if (shallow_literal || strcmp(m,
"__shallow_parsed") == 0)
242 lua_setfield(L, -2, key.c_str());
246 if (shallow_literal) {
247 i.disable_insertion();
248 i_end.disable_insertion();
250 for (
int j = 1;
i != i_end; ++
i, ++j)
253 lua_pushlstring(L,
i.get_key().c_str(),
i.get_key().size());
254 lua_rawseti(L, -2, 1);
256 lua_rawseti(L, -2, 2);
257 lua_rawseti(L, -2, j);
270 std::vector<std::string> attributes;
272 attributes.push_back(key);
284 lua_pushinteger(L, v->
null() ? 0 :
312 lua_pushlstring(L, value.first.c_str(), value.first.length());
323 void*
p = lua_touserdata(L, 1);
326 #if defined(_MSC_VER)
327 #pragma warning(push)
328 #pragma warning(disable: 4189)
331 const_attr_itors* cai =
static_cast<const_attr_itors*
>(
p);
332 cai->~const_attr_itors();
334 #if defined(_MSC_VER)
349 lua_setmetatable(L, -2);
374 static luaL_Reg
const callbacks[] {
379 luaL_setfuncs(L, callbacks, 0);
381 lua_pushstring(L,
"message domain");
382 lua_setfield(L, -2,
"__metatable");
384 return "Adding gettext metatable...\n";
394 static luaL_Reg
const callbacks[] {
404 luaL_setfuncs(L, callbacks, 0);
406 lua_createtable(L, 0, 1);
408 lua_setfield(L, -2,
"format");
410 lua_setfield(L, -2,
"vformat");
411 lua_setfield(L, -2,
"__index");
413 lua_pushstring(L,
"translatable string");
414 lua_setfield(L, -2,
"__metatable");
416 return "Adding tstring metatable...\n";
426 static luaL_Reg
const callbacks[] {
434 luaL_setfuncs(L, callbacks, 0);
436 lua_pushstring(L,
"wml object");
437 lua_setfield(L, -2,
"__metatable");
445 lua_pushstring(L,
"__gc");
449 return "Adding vconfig metatable...\n";
457 lua_geti(
state_, -1, arg_index);
463 lua_geti(
state_, value_index, arg_index);
471 void*
operator new(std::size_t sz, lua_State *L,
int nuv)
473 return lua_newuserdatauv(L, sz, nuv);
476 void operator delete(
void*, lua_State *L, int)
493 if(
n >= 2 && key[0] ==
'_' && key[1] ==
'_') {
496 return luaL_getmetafield(L, idx, key) != 0;
513 struct luaW_pushscalar_visitor
514 #ifdef USING_BOOST_VARIANT
515 : boost::static_visitor<>
519 luaW_pushscalar_visitor(lua_State *l): L(l) {}
521 void operator()(
const utils::monostate&)
const
523 void operator()(
bool b)
const
524 { lua_pushboolean(L,
b); }
525 void operator()(
int i)
const
526 { lua_pushinteger(L,
i); }
527 void operator()(
unsigned long long ull)
const
528 { lua_pushnumber(L, ull); }
529 void operator()(
double d)
const
530 { lua_pushnumber(L,
d); }
531 void operator()(
const std::string&
s)
const
532 { lua_pushlstring(L,
s.c_str(),
s.size()); }
545 switch (lua_type(L,
index)) {
550 v = lua_tonumber(L, -1);
572 switch (lua_type(L,
index)) {
574 str = lua_toboolean(L,
index) ?
"yes" :
"no";
578 str = lua_tostring(L,
index);
605 if(lua_isstring(L,
index)) {
616 if (!lua_checkstack(L, LUA_MINSTACK))
623 lua_pushstring(L, child_key.c_str());
624 lua_rawseti(L, -2, 1);
627 lua_rawseti(L, -2, 2);
628 lua_rawseti(L, -2, k++);
633 lua_setfield(L, -2, key.c_str());
639 if(lua_type(L, 2) == LUA_TSTRING) {
640 std::string k = lua_tostring(L, 2);
641 luaL_getmetafield(L, 1,
"__names");
642 auto names = lua_check<std::vector<std::string>>(L, -1);
644 if(iter !=
names.end()) {
645 int i = std::distance(
names.begin(), iter) + 1;
646 lua_rawgeti(L, 1,
i);
655 if(lua_type(L, 2) == LUA_TSTRING) {
656 std::string k = lua_tostring(L, 2);
657 luaL_getmetafield(L, 1,
"__names");
658 auto names = lua_check<std::vector<std::string>>(L, -1);
660 if(iter !=
names.end()) {
661 int i = std::distance(
names.begin(), iter) + 1;
663 lua_rawseti(L, 1,
i);
675 luaL_getmetafield(L, 1,
"__names");
681 std::vector<std::string> elems;
682 for(
unsigned i = 1;
i <= lua_rawlen(L, 1);
i++) {
683 lua_getglobal(L,
"tostring");
684 lua_rawgeti(L, 1,
i);
686 elems.push_back(lua_tostring(L, -1));
694 if(lua_type(L, 1) != LUA_TTABLE || lua_type(L, 2) != LUA_TTABLE) {
696 lua_pushboolean(L,
false);
699 luaL_getmetafield(L, 1,
"__name");
700 luaL_getmetafield(L, 2,
"__name");
701 if(!lua_rawequal(L, 3, 4))
goto NOT_EQUAL;
704 luaL_getmetafield(L, 1,
"__names");
705 luaL_getmetafield(L, 2,
"__names");
706 auto lnames = lua_check<std::vector<std::string>>(L, 3);
707 auto rnames = lua_check<std::vector<std::string>>(L, 4);
708 if(lnames != rnames)
goto NOT_EQUAL;
711 for(std::size_t
i = 1;
i <= lnames.size();
i++) {
712 lua_rawgeti(L, 1,
i);
713 lua_rawgeti(L, 2,
i);
714 if(!lua_compare(L, 3, 4, LUA_OPEQ))
goto NOT_EQUAL;
719 lua_pushboolean(L,
true);
725 lua_createtable(L,
names.size(), 0);
726 lua_createtable(L, 0, 8);
727 static luaL_Reg callbacks[] = {
735 luaL_setfuncs(L, callbacks, 0);
736 static const char baseName[] =
"named tuple";
737 std::ostringstream str;
738 str << baseName <<
'(';
742 for(std::size_t
i = 1;
i <
names.size();
i++) {
747 lua_setfield(L, -2,
"__metatable");
749 lua_setfield(L, -2,
"__names");
750 lua_pushstring(L,
"named tuple");
751 lua_setfield(L, -2,
"__name");
752 lua_setmetatable(L, -2);
756 std::vector<std::string>
names;
757 if(luaL_getmetafield(L, idx,
"__name")) {
758 if(lua_check<std::string>(L, -1) ==
"named tuple") {
759 luaL_getmetafield(L, idx,
"__names");
760 names = lua_check<std::vector<std::string>>(L, -1);
772 lua_pushinteger(L, ml.
wml_x());
773 lua_rawseti(L, -2, 1);
775 lua_pushinteger(L, ml.
wml_y());
776 lua_rawseti(L, -2, 2);
780 if (!lua_checkstack(L, LUA_MINSTACK)) {
783 if (lua_isnoneornil(L,
index)) {
792 if (lua_istable(L,
index) || lua_isuserdata(L,
index)) {
794 int x_was_num = 0, y_was_num = 0;
795 lua_getfield(L,
index,
"x");
796 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
797 lua_getfield(L,
index,
"y");
798 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
800 if (!x_was_num || !y_was_num) {
803 if (lua_isuserdata(L,
index)) {
806 lua_rawgeti(L,
index, 1);
807 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
808 lua_rawgeti(L,
index, 2);
809 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
812 if (x_was_num && y_was_num) {
816 }
else if (lua_isnumber(L,
index) && lua_isnumber(L,
index + 1)) {
821 lua_remove(L,
index);
838 lua_createtable(L, locs.size(), 0);
842 lua_rawseti(L, -2,
i);
850 std::set<map_location> locs;
851 if(!lua_istable(L, idx)) {
855 int len = luaL_checkinteger(L, -1);
856 for(
int i = 1;
i <= len;
i++) {
875 int top = lua_gettop(
s.L);
877 for(
int i = 1;
i <= top;
i++) {
879 lua_pushvalue(
s.L,
i);
881 auto value = luaL_checkstring(
s.L, -1);
883 os <<
'[' <<
i <<
']' << value <<
'\n';
885 if(top == 0) os <<
"(empty)\n";
890 #define return_misformed() \
891 do { lua_settop(L, initial_top); return false; } while (0)
896 if (!lua_checkstack(L, LUA_MINSTACK))
901 int initial_top = lua_gettop(L);
903 switch (lua_type(L,
index))
910 cfg = ptr->get_parsed_config();
924 for (
int i = 1, i_end = lua_rawlen(L,
index);
i <= i_end; ++
i)
928 lua_rawgeti(L, -1, 1);
929 char const *m = lua_tostring(L, -1);
931 lua_rawgeti(L, -2, 2);
938 for (lua_pushnil(L); lua_next(L,
index); lua_pop(L, 1))
940 int indextype = lua_type(L, -2);
941 if (indextype == LUA_TNUMBER)
continue;
943 const char* m = lua_tostring(L, -2);
946 if (lua_istable(L, -1)) {
947 int subindex = lua_absindex(L, -1);
948 std::ostringstream str;
949 for (
int i = 1, i_end = lua_rawlen(L, subindex);
i <= i_end; ++
i, lua_pop(L, 1)) {
950 lua_rawgeti(L, -1,
i);
953 if (
i > 1) str <<
',';
957 for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) {
964 lua_settop(L, initial_top);
968 #undef return_misformed
990 switch (lua_type(L,
index))
996 if (!ok)
return false;
1025 lua_pushglobaltable(L);
1026 for (
const std::string&
s :
path)
1028 if (!lua_istable(L, -1))
goto discard;
1029 lua_pushlstring(L,
s.c_str(),
s.size());
1034 if (lua_isnil(L, -1)) {
1044 return lua_toboolean(L,
n) != 0;
1077 int variabletype = lua_type(L,
n);
1080 switch (variabletype) {
1095 goto default_explicit;
1120 lua_pushstring(L, key);
1121 lua_gettable(L,
index);
1122 if(lua_isnoneornil(L, -1)) {
1131 std::size_t len = 0;
1132 const char* str = lua_tolstring(L,
index, &len);
1134 throw luaL_error (L,
"not a string");
1136 return std::string_view(str, len);
1141 std::size_t len = 0;
1142 const char* str = lua_tolstring(L,
index, &len);
1146 return std::string_view(str, len);
1159 lua_setfield(L, LUA_REGISTRYINDEX,
executeKey);
1165 lua_getfield(L, LUA_REGISTRYINDEX,
executeKey);
1166 lua_insert(L, -2 - nArgs);
1168 int error_handler_index = lua_gettop(L) - nArgs - 1;
1173 int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
1179 lua_remove(L, error_handler_index);
1185 #pragma warning (push)
1186 #pragma warning (disable: 4706)
1188 bool luaW_pcall(lua_State *L,
int nArgs,
int nRets,
bool allow_wml_error)
1200 char const *m = lua_tostring(L, -1);
1202 if (allow_wml_error && strncmp(m,
"~wml:", 5) == 0) {
1204 char const *
e = strstr(m,
"stack traceback");
1206 ERR_WML << std::string(m,
e ?
e - m : strlen(m));
1207 }
else if (allow_wml_error && strncmp(m,
"~lua:", 5) == 0) {
1209 char const *
e =
nullptr, *em = m;
1210 while (em[0] && ((em = strstr(em + 1,
"stack traceback"))))
1212 #pragma warning (pop)
1215 ERR_LUA << std::string(m,
e ?
e - m : strlen(m));
1216 chat_message(
"Lua error", std::string(m,
e ?
e - m : strlen(m)));
1222 ERR_LUA <<
"Lua caught unknown exception";
1235 const char *
msg = lua_pushfstring(L,
"%s expected, got %s", tname, luaL_typename(L, narg));
1236 return luaL_argerror(L, narg,
msg);
1243 const char *
msg = lua_pushfstring(L,
"%s expected for '%s', got %s", tname, kpath, luaL_typename(L, narg));
1244 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.
static bool valid_tag(std::string_view name)
config & add_child(std::string_view key)
const_attr_itors attribute_range() const
auto all_children_view() const
In-order iteration over all children.
static bool valid_attribute(std::string_view name)
boost::iterator_range< const_attribute_iterator > const_attr_itors
attribute_map::value_type attribute
void add_chat_message(const std::chrono::system_clock::time_point &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.
Shallow wrapper around lua_geti which pops the top variable from the Lua stack when destroyed.
scoped_lua_argument(lua_State *L, int arg_index)
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.
std::vector< std::string > luaW_to_namedtuple(lua_State *L, int idx)
Get the keys of a "named tuple" from the stack.
bool luaW_tableget(lua_State *L, int index, const char *key)
static int impl_namedtuple_set(lua_State *L)
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")
static int impl_namedtuple_compare(lua_State *L)
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.
std::ostream & operator<<(std::ostream &os, const luaW_PrintStack &s)
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.
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
luaW_PrintStack luaW_debugstack(lua_State *L)
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).
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_tstring_collect(lua_State *L)
Destroys a t_string object before it is collected (__gc metamethod).
static int impl_tstring_eq(lua_State *L)
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 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(std::string_view 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.
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
void lua_push(lua_State *L, const T &val)
static std::string flush(std::ostringstream &s)
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