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());
209 if (lua_isnumber(L, 2))
213 unsigned pos = lua_tointeger(L, 2) - 1;
214 if (pos >= len)
return 0;
215 std::advance(
i, pos);
217 tuple_builder.push(L);
218 lua_pushstring(L,
i.get_key().c_str());
219 lua_rawseti(L, -2, 1);
221 lua_rawseti(L, -2, 2);
225 char const *m = luaL_checkstring(L, 2);
226 if (strcmp(m,
"__literal") == 0) {
230 if (strcmp(m,
"__parsed") == 0) {
235 bool shallow_literal = strcmp(m,
"__shallow_literal") == 0;
236 if (shallow_literal || strcmp(m,
"__shallow_parsed") == 0)
244 lua_setfield(L, -2, key.c_str());
248 if (shallow_literal) {
249 i.disable_insertion();
250 i_end.disable_insertion();
252 for (
int j = 1;
i != i_end; ++
i, ++j)
254 tuple_builder.push(L);
255 lua_pushlstring(L,
i.get_key().c_str(),
i.get_key().size());
256 lua_rawseti(L, -2, 1);
258 lua_rawseti(L, -2, 2);
259 lua_rawseti(L, -2, j);
272 std::vector<std::string> attributes;
274 attributes.push_back(key);
286 lua_pushinteger(L, v->
null() ? 0 :
314 lua_pushlstring(L, value.first.c_str(), value.first.length());
325 void*
p = lua_touserdata(L, 1);
328 #if defined(_MSC_VER)
329 #pragma warning(push)
330 #pragma warning(disable: 4189)
333 const_attr_itors* cai =
static_cast<const_attr_itors*
>(
p);
334 cai->~const_attr_itors();
336 #if defined(_MSC_VER)
351 lua_setmetatable(L, -2);
376 static luaL_Reg
const callbacks[] {
381 luaL_setfuncs(L, callbacks, 0);
383 lua_pushstring(L,
"message domain");
384 lua_setfield(L, -2,
"__metatable");
386 return "Adding gettext metatable...\n";
396 static luaL_Reg
const callbacks[] {
406 luaL_setfuncs(L, callbacks, 0);
408 lua_createtable(L, 0, 1);
410 lua_setfield(L, -2,
"format");
412 lua_setfield(L, -2,
"vformat");
413 lua_setfield(L, -2,
"__index");
415 lua_pushstring(L,
"translatable string");
416 lua_setfield(L, -2,
"__metatable");
418 return "Adding tstring metatable...\n";
428 static luaL_Reg
const callbacks[] {
436 luaL_setfuncs(L, callbacks, 0);
438 lua_pushstring(L,
"wml object");
439 lua_setfield(L, -2,
"__metatable");
447 lua_pushstring(L,
"__gc");
451 return "Adding vconfig metatable...\n";
459 lua_geti(
state_, -1, arg_index);
465 lua_geti(
state_, value_index, arg_index);
473 void*
operator new(std::size_t sz, lua_State *L,
int nuv)
475 return lua_newuserdatauv(L, sz, nuv);
478 void operator delete(
void*, lua_State *L, int)
495 if(
n >= 2 && key[0] ==
'_' && key[1] ==
'_') {
498 return luaL_getmetafield(L, idx, key) != 0;
515 struct luaW_pushscalar_visitor
516 #ifdef USING_BOOST_VARIANT
517 : boost::static_visitor<>
521 luaW_pushscalar_visitor(lua_State *l): L(l) {}
523 void operator()(
const utils::monostate&)
const
525 void operator()(
bool b)
const
526 { lua_pushboolean(L,
b); }
527 void operator()(
int i)
const
528 { lua_pushinteger(L,
i); }
529 void operator()(
unsigned long long ull)
const
530 { lua_pushnumber(L, ull); }
531 void operator()(
double d)
const
532 { lua_pushnumber(L,
d); }
533 void operator()(
const std::string&
s)
const
534 { lua_pushlstring(L,
s.c_str(),
s.size()); }
547 switch (lua_type(L,
index)) {
552 v = lua_tonumber(L, -1);
574 switch (lua_type(L,
index)) {
576 str = lua_toboolean(L,
index) ?
"yes" :
"no";
580 str = lua_tostring(L,
index);
607 if(lua_isstring(L,
index)) {
620 if (!lua_checkstack(L, LUA_MINSTACK))
626 tuple_builder.
push(L);
627 lua_pushstring(L, child_key.c_str());
628 lua_rawseti(L, -2, 1);
631 lua_rawseti(L, -2, 2);
632 lua_rawseti(L, -2, k++);
637 lua_setfield(L, -2, key.c_str());
643 if(lua_type(L, 2) == LUA_TSTRING) {
644 std::string k = lua_tostring(L, 2);
645 luaL_getmetafield(L, 1,
"__names");
646 auto names = lua_check<std::vector<std::string>>(L, -1);
648 if(iter !=
names.end()) {
649 int i = std::distance(
names.begin(), iter) + 1;
650 lua_rawgeti(L, 1,
i);
659 if(lua_type(L, 2) == LUA_TSTRING) {
660 std::string k = lua_tostring(L, 2);
661 luaL_getmetafield(L, 1,
"__names");
662 auto names = lua_check<std::vector<std::string>>(L, -1);
664 if(iter !=
names.end()) {
665 int i = std::distance(
names.begin(), iter) + 1;
667 lua_rawseti(L, 1,
i);
679 luaL_getmetafield(L, 1,
"__names");
685 std::vector<std::string> elems;
686 for(
unsigned i = 1;
i <= lua_rawlen(L, 1);
i++) {
687 lua_getglobal(L,
"tostring");
688 lua_rawgeti(L, 1,
i);
690 elems.push_back(lua_tostring(L, -1));
698 if(lua_type(L, 1) != LUA_TTABLE || lua_type(L, 2) != LUA_TTABLE) {
700 lua_pushboolean(L,
false);
703 luaL_getmetafield(L, 1,
"__name");
704 luaL_getmetafield(L, 2,
"__name");
705 if(!lua_rawequal(L, 3, 4))
goto NOT_EQUAL;
708 luaL_getmetafield(L, 1,
"__names");
709 luaL_getmetafield(L, 2,
"__names");
710 auto lnames = lua_check<std::vector<std::string>>(L, 3);
711 auto rnames = lua_check<std::vector<std::string>>(L, 4);
712 if(lnames != rnames)
goto NOT_EQUAL;
715 for(std::size_t
i = 1;
i <= lnames.size();
i++) {
716 lua_rawgeti(L, 1,
i);
717 lua_rawgeti(L, 2,
i);
718 if(!lua_compare(L, 3, 4, LUA_OPEQ))
goto NOT_EQUAL;
723 lua_pushboolean(L,
true);
729 , key_{ build_key(
names) }
735 lua_createtable(L,
names_.size(), 0);
737 if (luaL_newmetatable(L,
key_.c_str()) != 0) {
738 static luaL_Reg callbacks[] = {
746 luaL_setfuncs(L, callbacks, 0);
748 lua_pushlstring(L,
key_.c_str(),
key_.size());
749 lua_setfield(L, -2,
"__metatable");
751 lua_setfield(L, -2,
"__names");
755 lua_setmetatable(L, -2);
760 std::ostringstream str;
765 for(std::size_t
i = 1;
i <
names.size();
i++) {
773 std::vector<std::string>
names;
774 if(luaL_getmetafield(L, idx,
"__name")) {
775 if(lua_check<std::string>(L, -1) ==
"named tuple") {
776 luaL_getmetafield(L, idx,
"__names");
777 names = lua_check<std::vector<std::string>>(L, -1);
789 tuple_builder.
push(L);
791 lua_pushinteger(L, ml.
wml_x());
792 lua_rawseti(L, -2, 1);
794 lua_pushinteger(L, ml.
wml_y());
795 lua_rawseti(L, -2, 2);
799 if (!lua_checkstack(L, LUA_MINSTACK)) {
802 if (lua_isnoneornil(L,
index)) {
811 if (lua_istable(L,
index) || lua_isuserdata(L,
index)) {
813 int x_was_num = 0, y_was_num = 0;
814 lua_getfield(L,
index,
"x");
815 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
816 lua_getfield(L,
index,
"y");
817 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
819 if (!x_was_num || !y_was_num) {
822 if (lua_isuserdata(L,
index)) {
825 lua_rawgeti(L,
index, 1);
826 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
827 lua_rawgeti(L,
index, 2);
828 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
831 if (x_was_num && y_was_num) {
835 }
else if (lua_isnumber(L,
index) && lua_isnumber(L,
index + 1)) {
840 lua_remove(L,
index);
857 lua_createtable(L, locs.size(), 0);
861 lua_rawseti(L, -2,
i);
869 std::set<map_location> locs;
870 if(!lua_istable(L, idx)) {
874 int len = luaL_checkinteger(L, -1);
875 for(
int i = 1;
i <= len;
i++) {
894 int top = lua_gettop(
s.L);
896 for(
int i = 1;
i <= top;
i++) {
898 lua_pushvalue(
s.L,
i);
900 auto value = luaL_checkstring(
s.L, -1);
902 os <<
'[' <<
i <<
']' << value <<
'\n';
904 if(top == 0) os <<
"(empty)\n";
909 #define return_misformed() \
910 do { lua_settop(L, initial_top); return false; } while (0)
915 if (!lua_checkstack(L, LUA_MINSTACK))
920 int initial_top = lua_gettop(L);
922 switch (lua_type(L,
index))
929 cfg = ptr->get_parsed_config();
943 for (
int i = 1, i_end = lua_rawlen(L,
index);
i <= i_end; ++
i)
947 lua_rawgeti(L, -1, 1);
948 char const *m = lua_tostring(L, -1);
950 lua_rawgeti(L, -2, 2);
957 for (lua_pushnil(L); lua_next(L,
index); lua_pop(L, 1))
959 int indextype = lua_type(L, -2);
960 if (indextype == LUA_TNUMBER)
continue;
962 const char* m = lua_tostring(L, -2);
965 if (lua_istable(L, -1)) {
966 int subindex = lua_absindex(L, -1);
967 std::ostringstream str;
968 for (
int i = 1, i_end = lua_rawlen(L, subindex);
i <= i_end; ++
i, lua_pop(L, 1)) {
969 lua_rawgeti(L, -1,
i);
972 if (
i > 1) str <<
',';
976 for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) {
983 lua_settop(L, initial_top);
987 #undef return_misformed
1009 switch (lua_type(L,
index))
1015 if (!ok)
return false;
1044 lua_pushglobaltable(L);
1045 for (
const std::string&
s :
path)
1047 if (!lua_istable(L, -1))
goto discard;
1048 lua_pushlstring(L,
s.c_str(),
s.size());
1053 if (lua_isnil(L, -1)) {
1063 return lua_toboolean(L,
n) != 0;
1096 int variabletype = lua_type(L,
n);
1099 switch (variabletype) {
1114 goto default_explicit;
1139 lua_pushstring(L, key);
1140 lua_gettable(L,
index);
1141 if(lua_isnoneornil(L, -1)) {
1150 std::size_t len = 0;
1151 const char* str = lua_tolstring(L,
index, &len);
1153 throw luaL_error (L,
"not a string");
1155 return std::string_view(str, len);
1160 std::size_t len = 0;
1161 const char* str = lua_tolstring(L,
index, &len);
1165 return std::string_view(str, len);
1178 lua_setfield(L, LUA_REGISTRYINDEX,
executeKey);
1184 lua_getfield(L, LUA_REGISTRYINDEX,
executeKey);
1185 lua_insert(L, -2 - nArgs);
1187 int error_handler_index = lua_gettop(L) - nArgs - 1;
1192 int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
1198 lua_remove(L, error_handler_index);
1204 #pragma warning (push)
1205 #pragma warning (disable: 4706)
1207 bool luaW_pcall(lua_State *L,
int nArgs,
int nRets,
bool allow_wml_error)
1219 char const *m = lua_tostring(L, -1);
1221 if (allow_wml_error && strncmp(m,
"~wml:", 5) == 0) {
1223 char const *
e = strstr(m,
"stack traceback");
1225 ERR_WML << std::string(m,
e ?
e - m : strlen(m));
1226 }
else if (allow_wml_error && strncmp(m,
"~lua:", 5) == 0) {
1228 char const *
e =
nullptr, *em = m;
1229 while (em[0] && ((em = strstr(em + 1,
"stack traceback"))))
1231 #pragma warning (pop)
1234 ERR_LUA << std::string(m,
e ?
e - m : strlen(m));
1235 chat_message(
"Lua error", std::string(m,
e ?
e - m : strlen(m)));
1241 ERR_LUA <<
"Lua caught unknown exception";
1254 const char *
msg = lua_pushfstring(L,
"%s expected, got %s", tname, luaL_typename(L, narg));
1255 return luaL_argerror(L, narg,
msg);
1262 const char *
msg = lua_pushfstring(L,
"%s expected for '%s', got %s", tname, kpath, luaL_typename(L, narg));
1263 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.
Efficiently creates new LUA "named tuples" with the specified field names.
static int impl_set(lua_State *L)
static std::string build_key(const std::vector< std::string > &names)
static int impl_tostring(lua_State *L)
lua_named_tuple_builder(const std::vector< std::string > &names)
static int impl_compare(lua_State *L)
void push(lua_State *L) const
Push an empty "named tuple" onto the stack.
static int impl_dir(lua_State *L)
const std::vector< std::string > names_
static int impl_get(lua_State *L)
static constexpr std::string_view base_name_
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[]
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 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)
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.
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.
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