Initial commit

This commit is contained in:
InoriRus
2021-12-01 19:29:27 +10:00
parent b1e7dcdc5d
commit 43f49c8763
1843 changed files with 1111694 additions and 0 deletions
+329
View File
@@ -0,0 +1,329 @@
#include "Kyty/Scripts/BuildTools.h"
#include "Kyty/Core/ByteBuffer.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/Database.h"
#include "Kyty/Core/DateTime.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/Debug.h"
#include "Kyty/Core/File.h"
#include "Kyty/Core/String.h"
#include "Kyty/Scripts/Scripts.h"
namespace Kyty::BuildTools {
KYTY_SCRIPT_FUNC(call_func)
{
return 0;
}
void call_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(rd_func)
{
return 0;
}
void rd_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(copy_func)
{
String src;
String dst;
if (Scripts::ArgGetVarCount() == 2)
{
src = Scripts::ArgGetVar(0).ToString();
dst = Scripts::ArgGetVar(1).ToString();
} else
{
EXIT("invalid args\n");
}
Core::File::CreateDirectories(dst.DirectoryWithoutFilename());
Core::File::CopyFile(src, dst);
return 0;
}
void copy_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(move_func)
{
String src;
String dst;
if (Scripts::ArgGetVarCount() == 2)
{
src = Scripts::ArgGetVar(0).ToString();
dst = Scripts::ArgGetVar(1).ToString();
} else
{
EXIT("invalid args\n");
}
Core::File::CreateDirectories(dst.DirectoryWithoutFilename());
if (!Core::File::MoveFile(src, dst))
{
EXIT("move\n");
}
return 0;
}
void move_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(sync_func)
{
String src;
String dst;
int del = 1;
if (Scripts::ArgGetVarCount() == 2)
{
src = Scripts::ArgGetVar(0).ToString();
dst = Scripts::ArgGetVar(1).ToString();
} else if (Scripts::ArgGetVarCount() == 3)
{
src = Scripts::ArgGetVar(0).ToString();
dst = Scripts::ArgGetVar(1).ToString();
del = Scripts::ArgGetVar(1).ToInteger();
} else
{
EXIT("invalid args\n");
}
Core::File::SyncDirectories(src, dst, del != 0);
return 0;
}
void sync_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(str_to_file_func)
{
String str;
String dst;
if (Scripts::ArgGetVarCount() == 2)
{
str = Scripts::ArgGetVar(0).ToString();
dst = Scripts::ArgGetVar(1).ToString();
} else
{
EXIT("invalid args\n");
}
Core::File f;
f.Create(dst);
f.SetEncoding(Core::File::Encoding::Utf8);
if (!f.IsInvalid())
{
f.Write(str);
}
f.Close();
return 0;
}
void str_to_file_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(replace_str_func)
{
String str1;
String str2;
String dst;
if (Scripts::ArgGetVarCount() == 3)
{
str1 = Scripts::ArgGetVar(0).ToString();
str2 = Scripts::ArgGetVar(1).ToString();
dst = Scripts::ArgGetVar(2).ToString();
} else
{
EXIT("invalid args\n");
}
Core::DateTime at;
Core::DateTime wt;
Core::File::GetLastAccessAndWriteTimeUTC(dst, &at, &wt);
Core::File f;
f.Open(dst, Core::File::Mode::Read);
f.SetEncoding(Core::File::Encoding::Utf8);
bool ok = false;
if (!f.IsInvalid())
{
String s = f.ReadWholeString();
s = s.ReplaceStr(str1, str2, String::Case::Insensitive);
f.Close();
f.Create(dst);
f.SetEncoding(Core::File::Encoding::Utf8);
if (!f.IsInvalid())
{
f.Write(s);
ok = true;
}
}
f.Close();
if (ok)
{
Core::File::SetLastAccessAndWriteTimeUTC(dst, at, wt);
}
return 0;
}
void replace_str_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(map_to_csv_func)
{
String mode;
String src;
String dst;
if (Scripts::ArgGetVarCount() == 3)
{
mode = Scripts::ArgGetVar(0).ToString();
src = Scripts::ArgGetVar(1).ToString();
dst = Scripts::ArgGetVar(2).ToString();
} else
{
EXIT("invalid args\n");
}
Core::DebugMap map;
if (Core::File::IsFileExisting(src))
{
Core::File::DeleteFile(dst);
printf("[ map] %s: %s -> %s\n", mode.C_Str(), src.C_Str(), dst.C_Str());
if (mode.EqualNoCase(U"mingw_ld_32") || mode.EqualNoCase(U"clang_ld_32"))
{
map.LoadGnuLd(src, 32);
map.DumpMap(dst);
} else if (mode.EqualNoCase(U"mingw_ld_64") || mode.EqualNoCase(U"clang_ld_64"))
{
map.LoadGnuLd(src, 64);
map.DumpMap(dst);
} else if (mode.EqualNoCase(U"clang_lld_64"))
{
map.LoadLlvmLld(src, 64);
map.DumpMap(dst);
} else if (mode.EqualNoCase(U"msvc_link_32"))
{
map.LoadMsvcLink(src, 32);
map.DumpMap(dst);
} else if (mode.EqualNoCase(U"msvc_link_64") || mode.EqualNoCase(U"msvc_lld_link_64"))
{
map.LoadMsvcLink(src, 64);
map.DumpMap(dst);
} else
{
printf("unknown map: %s\n", mode.C_Str());
}
}
return 0;
}
void map_to_csv_help()
{
// TODO(#108)
}
void atlas_repack_help()
{
// TODO(#108)
}
KYTY_SCRIPT_FUNC(db_key_func)
{
if (Scripts::ArgGetVarCount() != 3)
{
EXIT("invalid args\n");
}
String database = Scripts::ArgGetVar(0).ToString();
String password = Scripts::ArgGetVar(1).ToString();
int legacy = Scripts::ArgGetVar(2).ToInteger();
Core::Database::Connection db;
db.Open(database, Core::Database::Connection::Mode::ReadOnly);
if (db.IsInvalid() || db.IsError())
{
EXIT("Can't open file: %s\n", database.C_Str());
}
db.SetPassword(password, legacy);
auto key = db.GetKey();
FOR (i, key)
{
printf("%s0x%02" PRIx8 "%s", (i > 0 ? ", " : "{ "), std::to_integer<uint8_t>(key.At(i)), (i == key_size_ - 1 ? " }\n" : ""));
}
db.Close();
return 0;
}
void db_key_help()
{
// TODO(#108)
}
void Init()
{
Scripts::RegisterFunc("sync", BuildTools::sync_func, BuildTools::sync_help);
Scripts::RegisterFunc("copy", BuildTools::copy_func, BuildTools::copy_help);
Scripts::RegisterFunc("map_to_csv", BuildTools::map_to_csv_func, BuildTools::map_to_csv_help);
Scripts::RegisterFunc("str_to_file", BuildTools::str_to_file_func, BuildTools::str_to_file_help);
Scripts::RegisterFunc("replace_str", BuildTools::replace_str_func, BuildTools::replace_str_help);
Scripts::RegisterFunc("db_key", BuildTools::db_key_func, BuildTools::db_key_help);
}
KYTY_SUBSYSTEM_INIT(BuildTools)
{
BuildTools::Init();
}
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(BuildTools) {}
KYTY_SUBSYSTEM_DESTROY(BuildTools) {}
} // namespace Kyty::BuildTools
+923
View File
@@ -0,0 +1,923 @@
#include "Kyty/Scripts/Scripts.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/File.h"
#include "Kyty/Core/Hashmap.h"
#include "Kyty/Core/MemoryAlloc.h"
#include "Kyty/Core/RefCounter.h"
#include "Kyty/Core/SafeDelete.h"
#include "Kyty/Core/Threads.h"
#include "Kyty/Scripts/LuaCpp.h"
// IWYU pragma: no_include <sec_api/string_s.h>
namespace Kyty::Scripts {
using Core::File;
using Core::Hashmap;
using Core::mem_tracker_disable;
using Core::mem_tracker_enable;
static thread_local lua_State* g_lua_state = nullptr;
static thread_local String* g_lua_error = nullptr;
struct HelpFuncList
{
Hashmap<String, help_func_t> map;
};
static thread_local HelpFuncList* g_help_list = nullptr;
static const luaL_Reg g_loadedlibs[] = {{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_BITLIBNAME, luaopen_bit32},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug},
{nullptr, nullptr}};
static void lua_my_openlibs(lua_State* l)
{
for (const luaL_Reg* lib = g_loadedlibs; lib->func != nullptr; lib++)
{
luaL_requiref(l, lib->name, lib->func, 1);
lua_pop(l, 1);
}
}
void scripts_file_lib_reg();
static void load_libs()
{
lua_my_openlibs(g_lua_state);
scripts_file_lib_reg();
}
static void lua_init()
{
if (g_lua_state == nullptr)
{
mem_tracker_disable();
g_lua_state = luaL_newstate();
if (g_lua_state == nullptr)
{
EXIT("Lua state is NULL");
}
load_libs();
g_help_list = new HelpFuncList;
mem_tracker_enable();
}
}
KYTY_SUBSYSTEM_INIT(Scripts)
{
g_lua_state = nullptr;
g_lua_error = nullptr;
g_help_list = nullptr;
if (RunString(U"_script_check_a = _script_check_b") != ScriptError::Ok || RunString(U"_a _b _c _d") != ScriptError::SyntaxError ||
RunString(U"_script_check_a = _script_check_b[1]") != ScriptError::RunError)
{
KYTY_SUBSYSTEM_FAIL("Can't run Lua scripts");
}
ResetErrMsg();
}
KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Scripts) {}
KYTY_SUBSYSTEM_DESTROY(Scripts)
{
// lua_close(g_lua_state);
}
void script_dbg_dump_stack(const String& prefix)
{
lua_init();
printf("%s\n", prefix.C_Str());
int top = lua_gettop(g_lua_state);
for (int i = 1; i <= top; i++)
{
int t = lua_type(g_lua_state, i);
printf("%d: %s, n: %g\n", i, lua_typename(g_lua_state, t), lua_tonumber(g_lua_state, i));
}
}
ScriptError LoadString(const String& source)
{
lua_init();
int err = luaL_loadstring(g_lua_state, source.C_Str());
// printf("source:\n%s\n", source.C_Str());
// printf("binary:\n");
// ScriptVar::ReadVar(-1).DbgPrint(0);
if (err != LUA_OK)
{
ScriptVar s = ScriptVar::ReadVar(-1, false);
SetErrMsg(s.ToString());
lua_pop(g_lua_state, 1);
}
if (err == LUA_ERRSYNTAX)
{
return ScriptError::SyntaxError;
}
if (err != LUA_OK)
{
return ScriptError::UnknownError;
}
return ScriptError::Ok;
}
ScriptError Run()
{
lua_init();
int err = lua_pcall(g_lua_state, 0, LUA_MULTRET, 0);
// int top = lua_gettop(g_lua_state);
if (err != LUA_OK)
{
// script_dbg_dump_stack("");
ScriptVar s = ScriptVar::ReadVar(-1, false);
SetErrMsg(s.ToString());
lua_pop(g_lua_state, 1);
}
// EXIT_IF(lua_gettop(g_lua_state));
if (err == LUA_ERRRUN)
{
return ScriptError::RunError;
}
if (err != LUA_OK)
{
return ScriptError::UnknownError;
}
return ScriptError::Ok;
}
ScriptError RunFile(const String& file_name)
{
lua_init();
// EXIT_IF(lua_gettop(g_lua_state) > 0);
File f(file_name, File::Mode::Read);
f.SetEncoding(File::Encoding::Utf8);
if (f.IsInvalid())
{
return ScriptError::FileError;
}
String str = f.ReadWholeString();
f.Close();
// TODO(#117): load and run binary files
ScriptError status = LoadString(str);
if (status != ScriptError::Ok)
{
return status;
}
status = Run();
return status;
}
ScriptError RunString(const String& source)
{
lua_init();
// EXIT_IF(lua_gettop(g_lua_state) > 0);
ScriptError status = LoadString(source);
if (status != ScriptError::Ok)
{
return status;
}
status = Run();
return status;
}
void RegisterSystemFunc(const char* name, script_func_t func)
{
lua_init();
// EXIT_IF(GlobalGetVar(name).IsNil());
lua_register(g_lua_state, name, reinterpret_cast<lua_CFunction>(func));
}
void RegisterFunc(const char* name, script_func_t func, help_func_t help)
{
lua_init();
String n = String::FromUtf8(name);
EXIT_IF(!GlobalGetVar(n).IsNil());
EXIT_IF(g_help_list->map.Contains(n));
lua_register(g_lua_state, name, reinterpret_cast<lua_CFunction>(func));
g_help_list->map.Put(n, help);
}
void UnregisterFunc(const char* name)
{
lua_init();
String n = String::FromUtf8(name);
EXIT_IF(!GlobalGetVar(n).IsCFunction());
EXIT_IF(!g_help_list->map.Contains(n));
RunString(n + U" = nil");
g_help_list->map.Remove(n);
}
int ArgGetVarCount()
{
lua_init();
return lua_gettop(g_lua_state);
}
void ArgDbgDump()
{
lua_init();
int num = ArgGetVarCount();
for (int i = 0; i < num; i++)
{
printf("--[%d]--\n", i);
ArgGetVar(i).DbgPrint(0);
}
}
void PrintHelp()
{
lua_init();
FOR_HASH (g_help_list->map)
{
printf("Lua function: %s\n", g_help_list->map.Key().C_Str());
auto f = g_help_list->map.Value();
f();
}
}
class ScriptVar::ScriptVarPrivate: public Core::RefCounter<Core::DummyMutex>
{
public:
ScriptVarPrivate() = default;
bool is_table = {false};
bool is_nil = {true};
bool is_function = {false};
bool is_c_function = {false};
bool is_double = {false};
#if KYTY_LUA_VER == KYTY_LUA_5_3
bool is_integer = {false};
#endif
bool is_string = {false};
bool is_userdata = {false};
double val_double = {0.0};
bool val_bool = {false};
#if KYTY_LUA_VER == KYTY_LUA_5_3
int64_t val_integer = {0};
#endif
String val_string;
ScriptTable val_table;
ScriptFunction val_function;
void* val_userdata = {nullptr};
};
// ScriptVar::ScriptVarPrivate::ScriptVarPrivate()
// : is_table(false), is_nil(true), is_function(false), is_c_function(false), is_double(false),
//#if KYTY_LUA_VER == KYTY_LUA_5_3
// is_integer(false),
//#endif
// is_string(false), is_userdata(false), val_double(0.0), val_bool(false),
//#if KYTY_LUA_VER == KYTY_LUA_5_3
// val_integer(0),
//#endif
// val_userdata(nullptr)
//{
//}
void ScriptVar::DbgPrint(int depth) const
{
lua_init();
for (int i = 0; i < depth; i++)
{
printf(" ");
}
if (m_p->is_nil)
{
printf("nil\n");
} else if (m_p->is_table)
{
printf("Table:\n");
m_p->val_table.DbgPrint(depth + 1);
} else if (m_p->is_c_function)
{
printf("CFunction\n");
} else if (m_p->is_function)
{
printf("Function:\n");
printf("%s\n", m_p->val_function.ToDbgString().C_Str());
} else if (m_p->is_userdata)
{
printf("Userdata: %016" PRIx64 "\n", reinterpret_cast<uint64_t>(m_p->val_userdata));
} else
{
#if KYTY_LUA_VER == KYTY_LUA_5_3
printf("d: %g, i: %" PRIi64 " s: %s\n", val_double, val_integer, val_string.C_Str());
#else
printf("d: %g, s: %s\n", m_p->val_double, m_p->val_string.C_Str());
#endif
}
}
ScriptVar::ScriptVar(): m_p(new ScriptVarPrivate)
{
// m_p = new ScriptVarPrivate;
}
ScriptVar::~ScriptVar()
{
if (m_p != nullptr)
{
m_p->Release();
}
}
ScriptVar::ScriptVar(const ScriptVar& src)
{
src.m_p->CopyPtr(&m_p, src.m_p);
}
ScriptVar::ScriptVar(ScriptVar&& src) noexcept: m_p(src.m_p)
{
// m_p = src.m_p;
src.m_p = nullptr;
}
ScriptVar& ScriptVar::operator=(const ScriptVar& src)
{
if (this != &src && m_p != src.m_p)
{
if (m_p != nullptr)
{
m_p->Release();
}
src.m_p->CopyPtr(&m_p, src.m_p);
}
return *this;
}
ScriptVar& ScriptVar::operator=(ScriptVar&& src) noexcept
{
if (m_p != src.m_p)
{
if (m_p != nullptr)
{
m_p->Release();
}
m_p = src.m_p;
src.m_p = nullptr;
}
return *this;
}
ScriptVar ScriptVar::ReadVar(int index, bool with_metatable_index)
{
lua_init();
ScriptVar r;
EXIT_IF(index == 0);
// script_dbg_dump_stack(String::FromPrintf("script_read_var( %d )", index));
if (index < 0)
{
index = lua_gettop(g_lua_state) + index + 1;
}
lua_pushvalue(g_lua_state, index);
// printf("sizeof(lua_Integer) = %d\n", (int)sizeof(lua_Integer));
// printf("LUA_INTEGER_FRMLEN = %s\n", LUA_INTEGER_FRMLEN);
// printf("LUA_MAXINTEGER = %" PRIi64"\n", (int64_t)LUA_MAXINTEGER);
// printf("LUA_MININTEGER = %" PRIi64"\n", (int64_t)LUA_MININTEGER);
r.m_p->val_double = lua_tonumber(g_lua_state, -1);
r.m_p->val_bool = (lua_toboolean(g_lua_state, -1) != 0);
#if KYTY_LUA_VER == KYTY_LUA_5_3
Read.m_p->val_integer = lua_tointeger(g_lua_state, -1);
#endif
r.m_p->val_string = String::FromUtf8(lua_tostring(g_lua_state, -1));
r.m_p->val_userdata = lua_touserdata(g_lua_state, -1);
r.m_p->is_c_function = (lua_iscfunction(g_lua_state, -1) != 0);
r.m_p->is_double = (lua_isnumber(g_lua_state, -1) != 0);
r.m_p->is_function = lua_isfunction(g_lua_state, -1);
#if KYTY_LUA_VER == KYTY_LUA_5_3
Read.is_integer = lua_isinteger(g_lua_state, -1);
if (!Read.is_integer)
{
Read.is_integer = lua_tointeger(g_lua_state, -1) != 0 || lua_tostring(g_lua_state, -1) == String("0");
}
#endif
r.m_p->is_nil = lua_isnil(g_lua_state, -1);
r.m_p->is_string = (lua_isstring(g_lua_state, -1) != 0);
r.m_p->is_table = lua_istable(g_lua_state, -1);
r.m_p->is_userdata = (lua_isuserdata(g_lua_state, -1) != 0);
if (r.m_p->is_function)
{
r.m_p->val_function.LoadFromStack();
}
lua_pop(g_lua_state, 1);
if (r.m_p->is_table)
{
lua_pushnil(g_lua_state); /* first key */
// script_dbg_dump_stack(String::FromPrintf("is_table"));
while (lua_next(g_lua_state, index) != 0)
{
// script_dbg_dump_stack(String::FromPrintf("after_next"));
int top = lua_gettop(g_lua_state);
/* uses 'key' (at index top-2+1) and 'value' (at index top-1+1) */
ScriptVar k = ReadVar(top - 2 + 1, with_metatable_index);
ScriptVar v = ReadVar(top - 1 + 1, with_metatable_index);
r.m_p->val_table.Add(k, v);
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(g_lua_state, 1);
// script_dbg_dump_stack(String::FromPrintf("end_of_while"));
}
// lua_pop(g_lua_state, 1);
// script_dbg_dump_stack(String::FromPrintf("last_pop"));
if (with_metatable_index)
{
if (lua_getmetatable(g_lua_state, index) != 0)
{
ScriptVar metatable = ReadVar(-1, true);
ScriptVar parent = metatable.At(U"__index");
if (parent.IsTable())
{
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
for (const auto& p: parent.GetPairs())
{
if (r.At(p.GetKey().ToString()).IsNil())
{
r.m_p->val_table.Add(p.GetKey(), p.GetValue());
}
}
}
lua_pop(g_lua_state, 1);
}
}
}
return r;
}
bool ScriptVar::IsTable() const
{
return m_p->is_table;
}
bool ScriptVar::IsNil() const
{
return m_p->is_nil;
}
bool ScriptVar::IsFunction() const
{
return m_p->is_function;
}
bool ScriptVar::IsCFunction() const
{
return m_p->is_c_function;
}
bool ScriptVar::IsDouble() const
{
return m_p->is_double;
}
#if KYTY_LUA_VER == KYTY_LUA_5_3
bool ScriptVar::IsInteger() const
{
return m_p->is_integer;
}
#else
bool ScriptVar::IsInteger() const
{
return m_p->is_double && double(int32_t(m_p->val_double)) == m_p->val_double;
}
#endif
bool ScriptVar::IsString() const
{
return m_p->is_string;
}
bool ScriptVar::IsUserdata() const
{
return m_p->is_string;
}
#if KYTY_LUA_VER == KYTY_LUA_5_3
int64_t ScriptVar::ToInteger() const
{
return val_integer;
}
#else
int32_t ScriptVar::ToInteger() const
{
return IsInteger() ? int32_t(m_p->val_double) : 0;
}
#endif
double ScriptVar::ToDouble() const
{
return m_p->val_double;
}
float ScriptVar::ToFloat() const
{
return static_cast<float>(m_p->val_double);
}
bool ScriptVar::ToBool() const
{
return m_p->val_bool;
}
String ScriptVar::ToString() const
{
return m_p->val_string;
}
void* ScriptVar::ToUserdata() const
{
return m_p->val_userdata;
}
const ScriptTable& ScriptVar::ToTable() const
{
return m_p->val_table;
}
const ScriptTable::List& ScriptVar::GetPairs() const
{
return m_p->val_table.GetList();
}
ScriptVar ScriptVar::At(int64_t key) const
{
return m_p->val_table.At(static_cast<double>(key));
}
ScriptVar ScriptVar::At(const String& key) const
{
return m_p->val_table.At(key);
}
ScriptVar ScriptVar::At(const char* key) const
{
return m_p->val_table.At(String::FromUtf8(key));
}
ScriptVar ScriptVar::At(double key) const
{
return m_p->val_table.At(key);
}
uint32_t ScriptVar::Count() const
{
return m_p->val_table.Count();
}
uint32_t ScriptVar::Size() const
{
return m_p->val_table.Count();
}
ScriptVar ScriptVar::GetKey(uint32_t index) const
{
return m_p->val_table.GetKey(index);
}
ScriptVar ScriptVar::GetValue(uint32_t index) const
{
return m_p->val_table.GetValue(index);
}
void script_global_dbg_dump_var(const String& var_name)
{
lua_init();
lua_getglobal(g_lua_state, var_name.C_Str());
ScriptVar r = ScriptVar::ReadVar(-1, false);
r.DbgPrint(0);
lua_pop(g_lua_state, 1);
}
ScriptVar GlobalGetVar(const String& var_name)
{
lua_init();
lua_getglobal(g_lua_state, var_name.C_Str());
ScriptVar ret = ScriptVar::ReadVar(-1, false);
lua_pop(g_lua_state, 1);
return ret;
}
ScriptVar GlobalGetVarWithParent(const String& var_name)
{
lua_init();
lua_getglobal(g_lua_state, var_name.C_Str());
ScriptVar ret = ScriptVar::ReadVar(-1, true);
lua_pop(g_lua_state, 1);
return ret;
}
void SetErrMsg(const String& msg)
{
lua_init();
if (g_lua_error == nullptr)
{
g_lua_error = new String();
}
*g_lua_error = msg;
}
const String& GetErrMsg()
{
lua_init();
if (g_lua_error == nullptr)
{
g_lua_error = new String();
}
return *g_lua_error;
}
void ResetErrMsg()
{
lua_init();
delete g_lua_error;
g_lua_error = nullptr;
}
ScriptVar ArgGetVar(int index)
{
lua_init();
ScriptVar ret = ScriptVar::ReadVar(index + 1, false);
return ret;
}
ScriptVar ArgGetVarWithParent(int index)
{
lua_init();
ScriptVar ret = ScriptVar::ReadVar(index + 1, true);
return ret;
}
void PushString(const String& str)
{
lua_init();
lua_pushstring(g_lua_state, str.C_Str());
}
void PushDouble(double d)
{
lua_init();
lua_pushnumber(g_lua_state, static_cast<lua_Number>(d));
}
#if KYTY_LUA_VER == KYTY_LUA_5_3
void PushInteger(int64_t i)
{
lua_init();
lua_pushinteger(g_lua_state, i);
}
#else
void PushInteger(int32_t i)
{
lua_init();
PushDouble(double(i));
}
#endif
#if KYTY_LUA_VER == KYTY_LUA_5_3
ScriptVar ScriptTable::At(int64_t m_key) const
{
lua_init();
FOR (i, keys)
{
const ScriptVar& v = keys.At(i);
if (v.IsInteger() && v.ToInteger() == m_key)
{
return values.At(i);
}
}
return ScriptVar();
}
#endif
ScriptVar ScriptTable::At(const String& key) const
{
lua_init();
// FOR(i, keys)
for (const auto& p: m_pairs)
{
const ScriptVar& v = p.GetKey();
if (v.IsString() && v.ToString() == key)
{
return p.GetValue();
}
}
return ScriptVar();
}
ScriptVar ScriptTable::At(double key) const
{
lua_init();
// FOR(i, keys)
for (const auto& p: m_pairs)
{
const ScriptVar& v = p.GetKey();
if (v.IsDouble() && v.ToDouble() == key)
{
return p.GetValue();
}
}
return ScriptVar();
}
void ScriptTable::DbgPrint(int depth) const
{
lua_init();
// FOR(k, keys)
int k = 0;
for (const auto& p: m_pairs)
{
for (int i = 0; i < depth; i++)
{
printf(" ");
}
printf("--- %d ---\n", k++);
for (int i = 0; i < depth; i++)
{
printf(" ");
}
printf("Key:\n");
p.GetKey().DbgPrint(depth);
for (int i = 0; i < depth; i++)
{
printf(" ");
}
printf("Value:\n");
p.GetValue().DbgPrint(depth);
}
}
void ScriptTable::Add(const ScriptVar& k, const ScriptVar& v)
{
lua_init();
ScriptPair p(k, v);
m_pairs.Add(p);
// keys.Add(k);
// values.Add(v);
}
ScriptVar ScriptTable::GetKey(uint32_t index) const
{
lua_init();
return m_pairs.At(index).GetKey();
}
ScriptVar ScriptTable::GetValue(uint32_t index) const
{
lua_init();
return m_pairs.At(index).GetValue();
}
void ScriptFuncResult::SetError(const String& msg)
{
m_ok = false;
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
strncpy_s(m_msg, SCRIPT_FUNC_ERR_SIZE + 1, msg.C_Str(), SCRIPT_FUNC_ERR_SIZE);
#else
strncpy(m_msg, msg.C_Str(), SCRIPT_FUNC_ERR_SIZE);
#endif
m_msg[SCRIPT_FUNC_ERR_SIZE] = '\0';
}
void ScriptFuncResult::ThrowError()
{
lua_init();
if (!m_ok)
{
lua_pushstring(g_lua_state, m_msg);
lua_error(g_lua_state);
}
}
void ScriptFunction::LoadFromStack()
{
lua_init();
#if KYTY_LUA_VER == KYTY_LUA_5_3
lua_dump(g_lua_state, reinterpret_cast<lua_Writer>(LuaWriter), this, 0);
#else
lua_dump(g_lua_state, reinterpret_cast<lua_Writer>(LuaWriter), this);
#endif
}
String ScriptFunction::ToDbgString() const
{
lua_init();
String str;
FOR (i, m_dump)
{
str += String::FromPrintf("%02" PRIx8 "", m_dump.At(i));
}
return str;
}
int ScriptFunction::LuaWriter(LuaState* /*LS*/, const void* p, size_t sz, void* ud)
{
lua_init();
auto* f = static_cast<ScriptFunction*>(ud);
EXIT_IF(sizeof(size_t) > 4 && (static_cast<uint64_t>(sz) >> 32u) > 0);
f->m_dump.Add(static_cast<const uint8_t*>(p), static_cast<uint32_t>(sz));
return 0;
}
ScriptPair::ScriptPair(const ScriptVar& key, const ScriptVar& value): m_key(new ScriptVar(key)), m_value(new ScriptVar(value)) {}
ScriptPair::~ScriptPair()
{
Delete(m_key);
Delete(m_value);
}
ScriptPair::ScriptPair(const ScriptPair& src): m_key(new ScriptVar(*src.m_key)), m_value(new ScriptVar(*src.m_value)) {}
} // namespace Kyty::Scripts
+126
View File
@@ -0,0 +1,126 @@
#include "Kyty/Core/String.h"
#include "Kyty/Scripts/LuaCpp.h"
#include "Kyty/Scripts/Scripts.h"
namespace Kyty::Scripts {
// void script_dbg_dump_stack(const String &prefix);
static String create_error(ScriptError err, const String& msg1, const String& msg2)
{
String err_str = String::FromPrintf("%s %s\n", msg1.C_Str(), msg2.C_Str());
switch (err)
{
case ScriptError::FileError: err_str += String::FromPrintf("file error\n"); break;
case ScriptError::SyntaxError: err_str += String::FromPrintf("syntax error:\n%s\n", GetErrMsg().C_Str()); break;
case ScriptError::RunError: err_str += String::FromPrintf("run error:\n%s\n", GetErrMsg().C_Str()); break;
case ScriptError::UnknownError:
default: err_str += String::FromPrintf("unknown error\n");
}
return err_str;
}
KYTY_STATIC_SCRIPT_FUNC(dofile)
{
KYTY_SCRIPT_FUNC_BEGIN();
if (Scripts::ArgGetVarCount() != 1)
{
KYTY_SCRIPT_THROW_ERROR(U"invalid args\n");
}
String file_name = Scripts::ArgGetVar(0).ToString();
ScriptError err = RunFile(file_name);
if (err != ScriptError::Ok)
{
KYTY_SCRIPT_THROW_ERROR(create_error(err, U"can't run file", file_name));
}
return Scripts::ArgGetVarCount() - 1;
}
KYTY_STATIC_SCRIPT_FUNC(require)
{
KYTY_SCRIPT_FUNC_BEGIN();
if (Scripts::ArgGetVarCount() != 1)
{
KYTY_SCRIPT_THROW_ERROR(U"invalid args\n");
}
// s: name
String file_name = Scripts::ArgGetVar(0).ToString();
String::Utf8 name = file_name.utf8_str();
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); // s: name, _LOADED
lua_getfield(L, 2, name.GetData()); // s: name, _LOADED, module
if (lua_toboolean(L, -1) != 0)
{ /* is it there? */
return 1; /* package is already loaded */
}
/* else must load package */
lua_pop(L, 1); // s: name, _LOADED
lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); // s: name, _LOADED, _PRELOADED
lua_getfield(L, 3, name.GetData()); // s: name, _LOADED, _PRELOADED, loader
if (!lua_isnil(L, -1))
{
lua_pop(L, 2); // s: name, _LOADED
String rs = String::FromPrintf(R"(return package.preload["%s"]("%s"))", name.GetData(), name.GetData());
ScriptError err = RunString(rs); // s: name, _LOADED, module
if (err != ScriptError::Ok)
{
KYTY_SCRIPT_THROW_ERROR(create_error(err, U"can't run", rs));
}
} else
{
file_name = file_name.ReplaceChar(U'.', U'/') + U".lua";
ScriptError err = RunFile(file_name); // s: name, _LOADED, module
if (err != ScriptError::Ok)
{
KYTY_SCRIPT_THROW_ERROR(create_error(err, U"can't run file", file_name));
}
}
if (lua_gettop(L) == 2)
{
lua_pushnil(L); // s: name, _LOADED, nil
}
if (!lua_isnil(L, -1))
{ /* non-nil return? */
lua_setfield(L, 2, name.GetData()); /* _LOADED[name] = module */ // s: name, _LOADED
}
lua_getfield(L, 2, name.GetData()); // s: name, _LOADED, module
if (lua_isnil(L, -1))
{ /* module set no value? */
lua_pushboolean(L, 1); /* use true as result */ // s: name, _LOADED, module, true
lua_pushvalue(L, -1); /* extra copy to be returned */ // s: name, _LOADED, true, true
lua_setfield(L, 2, name.GetData()); /* _LOADED[name] = true */ // s: name, _LOADED, true
}
return 1;
}
void scripts_file_lib_reg()
{
RegisterSystemFunc("dofile", dofile);
RegisterSystemFunc("require", require);
}
} // namespace Kyty::Scripts
+77
View File
@@ -0,0 +1,77 @@
#include "Kyty/Scripts/ScriptsLoader.h"
#include "Kyty/Core/MemoryAlloc.h"
#include "Kyty/Scripts/Scripts.h"
namespace Kyty::Scripts {
static String* g_load_err = nullptr;
void SetLoadError(const String& err)
{
Core::mem_tracker_disable();
if (g_load_err == nullptr)
{
g_load_err = new String;
}
String s = err.IsEmpty() ? U"" : String::FromPrintf("%s", err.C_Str());
if (g_load_err->IsEmpty())
{
*g_load_err = s;
} else
{
*g_load_err = *g_load_err + U"\n" + s;
}
Core::mem_tracker_enable();
}
void ResetLoadError()
{
Core::mem_tracker_disable();
if (g_load_err == nullptr)
{
g_load_err = new String;
}
*g_load_err = U"";
Core::mem_tracker_enable();
}
String GetLoadError()
{
return ((g_load_err != nullptr) && !g_load_err->IsEmpty()) ? String::FromPrintf("%s", (*g_load_err).C_Str()) : U"";
}
bool RunScript(const String& lua_file_name)
{
Scripts::ScriptError err = Scripts::RunFile(lua_file_name);
if (err != Scripts::ScriptError::Ok)
{
String err_str = String::FromPrintf("can't run file %s\n", lua_file_name.C_Str());
switch (err)
{
case Scripts::ScriptError::FileError: err_str += String::FromPrintf("file error\n"); break;
case Scripts::ScriptError::SyntaxError:
err_str += String::FromPrintf("syntax error:\n%s\n", Scripts::GetErrMsg().C_Str());
break;
case Scripts::ScriptError::RunError:
err_str += String::FromPrintf("run error:\n%s\n", Scripts::GetErrMsg().C_Str());
break;
case Scripts::ScriptError::UnknownError:
default: err_str += U"unknown error\n";
}
SetLoadError(err_str);
return false;
}
return true;
}
} // namespace Kyty::Scripts