52 #define LOG_LUA LOG_STREAM(info, log_scripting_lua)
53 #define WRN_LUA LOG_STREAM(warn, log_scripting_lua)
54 #define ERR_LUA LOG_STREAM(err, log_scripting_lua)
57 #define ERR_WML LOG_STREAM(err, log_wml)
69 char const *m = luaL_checkstring(L, 2);
70 char const *
d =
static_cast<char *
>(lua_touserdata(L, 1));
72 if(lua_isstring(L, 3)) {
73 const char* pl = luaL_checkstring(L, 3);
74 int count = luaL_checkinteger(L, 4);
84 char*
d =
static_cast<char*
>(lua_touserdata(L, 1));
85 using namespace std::literals;
86 std::string str =
"textdomain: "s +
d;
99 char const *m = luaL_checklstring(L, 1, &l);
101 void *
p = lua_newuserdatauv(L, l + 1, 0);
117 switch (lua_type(L, src)) {
120 dst += lua_tostring(L, src);
153 lua_pushnumber(L,
t->size());
163 t->t_string::~t_string();
198 lua_pushstring(L,
t->c_str());
211 if (lua_isnumber(L, 2))
215 unsigned pos = lua_tointeger(L, 2) - 1;
216 if (pos >= len)
return 0;
217 std::advance(
i, pos);
219 lua_createtable(L, 2, 0);
220 lua_pushstring(L,
i.get_key().c_str());
221 lua_rawseti(L, -2, 1);
223 lua_rawseti(L, -2, 2);
227 char const *m = luaL_checkstring(L, 2);
228 if (strcmp(m,
"__literal") == 0) {
232 if (strcmp(m,
"__parsed") == 0) {
237 bool shallow_literal = strcmp(m,
"__shallow_literal") == 0;
238 if (shallow_literal || strcmp(m,
"__shallow_parsed") == 0)
246 lua_setfield(L, -2,
a.first.c_str());
250 if (shallow_literal) {
251 i.disable_insertion();
252 i_end.disable_insertion();
254 for (
int j = 1;
i != i_end; ++
i, ++j)
256 lua_createtable(L, 2, 0);
257 lua_pushstring(L,
i.get_key().c_str());
258 lua_rawseti(L, -2, 1);
260 lua_rawseti(L, -2, 2);
261 lua_rawseti(L, -2, j);
274 std::vector<std::string> attributes;
276 attributes.push_back(key);
288 lua_pushinteger(L, v->
null() ? 0 :
316 lua_pushlstring(L, value.first.c_str(), value.first.length());
327 void*
p = lua_touserdata(L, 1);
330 #if defined(_MSC_VER)
331 #pragma warning(push)
332 #pragma warning(disable: 4189)
335 const_attr_itors* cai =
static_cast<const_attr_itors*
>(
p);
336 cai->~const_attr_itors();
338 #if defined(_MSC_VER)
353 lua_setmetatable(L, -2);
367 int i = luaL_checkinteger(L, 2);
370 if (range.first == range.second) {
373 std::pair<std::string, vconfig> value = *range.first++;
374 lua_pushinteger(L,
i + 1);
375 lua_createtable(L, 2, 0);
376 lua_pushlstring(L, value.first.c_str(), value.first.length());
377 lua_rawseti(L, -2, 1);
379 lua_rawseti(L, -2, 2);
388 void*
p = lua_touserdata(L, 1);
390 vcr->~vconfig_child_range();
402 lua_setmetatable(L, -2);
405 lua_pushinteger(L, 0);
428 static luaL_Reg
const callbacks[] {
433 luaL_setfuncs(L, callbacks, 0);
435 lua_pushstring(L,
"message domain");
436 lua_setfield(L, -2,
"__metatable");
438 return "Adding gettext metatable...\n";
448 static luaL_Reg
const callbacks[] {
458 luaL_setfuncs(L, callbacks, 0);
460 lua_createtable(L, 0, 1);
462 lua_setfield(L, -2,
"format");
464 lua_setfield(L, -2,
"vformat");
465 lua_setfield(L, -2,
"__index");
467 lua_pushstring(L,
"translatable string");
468 lua_setfield(L, -2,
"__metatable");
470 return "Adding tstring metatable...\n";
480 static luaL_Reg
const callbacks[] {
489 luaL_setfuncs(L, callbacks, 0);
491 lua_pushstring(L,
"wml object");
492 lua_setfield(L, -2,
"__metatable");
500 lua_pushstring(L,
"__gc");
505 lua_pushstring(L,
"__gc");
509 return "Adding vconfig metatable...\n";
514 void*
operator new(std::size_t sz, lua_State *L,
int nuv)
516 return lua_newuserdatauv(L, sz, nuv);
519 void operator delete(
void*, lua_State *L, int)
536 if(
n >= 2 && key[0] ==
'_' && key[1] ==
'_') {
539 return luaL_getmetafield(L, idx, key) != 0;
556 struct luaW_pushscalar_visitor
557 #ifdef USING_BOOST_VARIANT
558 : boost::static_visitor<>
562 luaW_pushscalar_visitor(lua_State *l): L(l) {}
564 void operator()(
const utils::monostate&)
const
566 void operator()(
bool b)
const
567 { lua_pushboolean(L,
b); }
568 void operator()(
int i)
const
569 { lua_pushinteger(L,
i); }
570 void operator()(
unsigned long long ull)
const
571 { lua_pushnumber(L, ull); }
572 void operator()(
double d)
const
573 { lua_pushnumber(L,
d); }
574 void operator()(
const std::string&
s)
const
575 { lua_pushstring(L,
s.c_str()); }
588 switch (lua_type(L,
index)) {
593 v = lua_tonumber(L, -1);
596 v = lua_tostring(L, -1);
615 switch (lua_type(L,
index)) {
617 str = lua_toboolean(L,
index) ?
"yes" :
"no";
621 str = lua_tostring(L,
index);
648 if(lua_isstring(L,
index)) {
659 if (!lua_checkstack(L, LUA_MINSTACK))
666 lua_pushstring(L, ch.key.c_str());
667 lua_rawseti(L, -2, 1);
670 lua_rawseti(L, -2, 2);
671 lua_rawseti(L, -2, k++);
676 lua_setfield(L, -2, attr.first.c_str());
682 if(lua_isstring(L, 2)) {
683 std::string k = lua_tostring(L, 2);
684 luaL_getmetafield(L, 1,
"__names");
685 auto names = lua_check<std::vector<std::string>>(L, -1);
686 auto iter = std::find(
names.begin(),
names.end(), k);
687 if(iter !=
names.end()) {
688 int i = std::distance(
names.begin(), iter) + 1;
689 lua_rawgeti(L, 1,
i);
698 luaL_getmetafield(L, 1,
"__names");
704 std::vector<std::string> elems;
705 for(
unsigned i = 1;
i <= lua_rawlen(L, 1);
i++) {
706 lua_getglobal(L,
"tostring");
707 lua_rawgeti(L, 1,
i);
709 elems.push_back(lua_tostring(L, -1));
717 lua_createtable(L,
names.size(), 0);
718 lua_createtable(L, 0, 4);
719 static luaL_Reg callbacks[] = {
725 luaL_setfuncs(L, callbacks, 0);
726 lua_pushliteral(L,
"named tuple");
727 lua_setfield(L, -2,
"__metatable");
729 lua_setfield(L, -2,
"__names");
730 lua_setmetatable(L, -2);
737 lua_pushinteger(L, ml.
wml_x());
738 lua_rawseti(L, -2, 1);
740 lua_pushinteger(L, ml.
wml_y());
741 lua_rawseti(L, -2, 2);
745 if (!lua_checkstack(L, LUA_MINSTACK)) {
748 if (lua_isnoneornil(L,
index)) {
757 if (lua_istable(L,
index) || lua_isuserdata(L,
index)) {
759 int x_was_num = 0, y_was_num = 0;
760 lua_getfield(L,
index,
"x");
761 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
762 lua_getfield(L,
index,
"y");
763 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
765 if (!x_was_num || !y_was_num) {
768 if (lua_isuserdata(L,
index)) {
771 lua_rawgeti(L,
index, 1);
772 result.
set_wml_x(lua_tointegerx(L, -1, &x_was_num));
773 lua_rawgeti(L,
index, 2);
774 result.
set_wml_y(lua_tointegerx(L, -1, &y_was_num));
777 if (x_was_num && y_was_num) {
781 }
else if (lua_isnumber(L,
index) && lua_isnumber(L,
index + 1)) {
786 lua_remove(L,
index);
803 lua_createtable(L, locs.size(), 0);
807 lua_rawseti(L, -2,
i);
815 std::set<map_location> locs;
816 if(!lua_istable(L, idx)) {
820 int len = luaL_checkinteger(L, -1);
821 for(
int i = 1;
i <= len;
i++) {
839 #define return_misformed() \
840 do { lua_settop(L, initial_top); return false; } while (0)
845 if (!lua_checkstack(L, LUA_MINSTACK))
850 int initial_top = lua_gettop(L);
852 switch (lua_type(L,
index))
859 cfg = ptr->get_parsed_config();
873 for (
int i = 1, i_end = lua_rawlen(L,
index);
i <= i_end; ++
i)
877 lua_rawgeti(L, -1, 1);
878 char const *m = lua_tostring(L, -1);
880 lua_rawgeti(L, -2, 2);
887 for (lua_pushnil(L); lua_next(L,
index); lua_pop(L, 1))
889 int indextype = lua_type(L, -2);
890 if (indextype == LUA_TNUMBER)
continue;
892 const char* m = lua_tostring(L, -2);
895 if (lua_istable(L, -1)) {
896 int subindex = lua_absindex(L, -1);
897 std::ostringstream str;
898 for (
int i = 1, i_end = lua_rawlen(L, subindex);
i <= i_end; ++
i, lua_pop(L, 1)) {
899 lua_rawgeti(L, -1,
i);
902 if (
i > 1) str <<
',';
906 for (lua_pushnil(L); lua_next(L, subindex); lua_pop(L, 1)) {
913 lua_settop(L, initial_top);
917 #undef return_misformed
939 switch (lua_type(L,
index))
945 if (!ok)
return false;
946 vcfg =
vconfig(std::move(cfg));
974 lua_pushglobaltable(L);
975 for (
const std::string&
s :
path)
977 if (!lua_istable(L, -1))
goto discard;
978 lua_pushlstring(L,
s.c_str(),
s.size());
983 if (lua_isnil(L, -1)) {
993 return lua_toboolean(L,
n) != 0;
1026 int variabletype = lua_type(L,
n);
1029 switch (variabletype) {
1044 goto default_explicit;
1069 lua_pushstring(L, key);
1070 lua_gettable(L,
index);
1071 if(lua_isnoneornil(L, -1)) {
1081 const char* str = lua_tolstring(L,
index, &len);
1083 throw luaL_error (L,
"not a string");
1085 return std::string_view(str, len);
1091 const char* str = lua_tolstring(L,
index, &len);
1095 return std::string_view(str, len);
1108 lua_setfield(L, LUA_REGISTRYINDEX,
executeKey);
1114 lua_getfield(L, LUA_REGISTRYINDEX,
executeKey);
1115 lua_insert(L, -2 - nArgs);
1117 int error_handler_index = lua_gettop(L) - nArgs - 1;
1120 int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
1125 lua_remove(L, error_handler_index);
1131 #pragma warning (push)
1132 #pragma warning (disable: 4706)
1134 bool luaW_pcall(lua_State *L,
int nArgs,
int nRets,
bool allow_wml_error)
1144 char const *m = lua_tostring(L, -1);
1146 if (allow_wml_error && strncmp(m,
"~wml:", 5) == 0) {
1148 char const *
e = strstr(m,
"stack traceback");
1150 ERR_WML << std::string(m,
e ?
e - m : strlen(m));
1151 }
else if (allow_wml_error && strncmp(m,
"~lua:", 5) == 0) {
1153 char const *
e =
nullptr, *em = m;
1154 while (em[0] && ((em = strstr(em + 1,
"stack traceback"))))
1156 #pragma warning (pop)
1159 chat_message(
"Lua error", std::string(m,
e ?
e - m : strlen(m)));
1177 const char *
msg = lua_pushfstring(L,
"%s expected, got %s", tname, luaL_typename(L, narg));
1178 return luaL_argerror(L, narg,
msg);
1185 const char *
msg = lua_pushfstring(L,
"%s expected for '%s', got %s", tname, kpath, luaL_typename(L, narg));
1186 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
static bool valid_tag(config_key_type name)
const_all_children_itors all_children_range() const
In-order iteration over all children.
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.
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
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::pair< std::string, unsigned > item
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)
Encapsulates the map of the game.
static map_location::DIRECTION n
static map_location::DIRECTION s