Switch back to building Lua as C
In preparation for switching to LuaJIT, which doesn't support PUC Lua's thing of using C++ exceptions for lua_error. Requires replacing all uses of lua_error (and things calling lua_error) with custom versions that throw an exception instead and adding an exception -> lua error wrapper at all C++ -> Lua boundaries.
This commit is contained in:
parent
e3eb28ffd1
commit
9492192b73
64 changed files with 483 additions and 375 deletions
|
@ -86,7 +86,6 @@ CFLAGS_ICU = @ICU_I18N_CFLAGS@
|
|||
CFLAGS_LIBASS = @LIBASS_CFLAGS@
|
||||
CFLAGS_LIBCURL = @LIBCURL_CFLAGS@
|
||||
CFLAGS_LIBPULSE = @LIBPULSE_CFLAGS@
|
||||
CFLAGS_LUA = -I../vendor/lua/src
|
||||
CFLAGS_OPENAL = @OPENAL_CFLAGS@
|
||||
CFLAGS_OSS = @OSS_CFLAGS@
|
||||
CFLAGS_PORTAUDIO = @PORTAUDIO_CFLAGS@
|
||||
|
|
|
@ -4,7 +4,7 @@ PRECOMPILED_HEADER_NAME = ../libaegisub/lagi_pre.h
|
|||
|
||||
PROGRAM = aegisub-lua
|
||||
|
||||
CXXFLAGS += -I../libaegisub/include -I../src -I ../vendor/lua/src $(CXXFLAGS_WX)
|
||||
CXXFLAGS += -I../libaegisub/include -I../src -I.. -I../vendor/lua/src $(CXXFLAGS_WX)
|
||||
CPPFLAGS += $(CPPFLAGS_BOOST)
|
||||
|
||||
LIBS := -L../libaegisub -laegisub -L../vendor/lua -llua-aegisub $(LIBS)
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <lauxlib.h>
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
|
||||
using namespace agi::lua;
|
||||
|
||||
|
|
|
@ -122,7 +122,10 @@
|
|||
<ClCompile Include="$(SrcDir)common\vfr.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lua\modules.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lua\modules\lfs.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lua\modules\lpeg.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lua\modules\lpeg.c">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<ForcedIncludeFiles></ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lua\modules\re.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lua\script_reader.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lua\utils.cpp" />
|
||||
|
|
|
@ -310,7 +310,7 @@
|
|||
<ClCompile Include="$(SrcDir)lua\modules\lfs.cpp">
|
||||
<Filter>Lua\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lua\modules\lpeg.cpp">
|
||||
<ClCompile Include="$(SrcDir)lua\modules\lpeg.c">
|
||||
<Filter>Lua\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lua\modules\re.cpp">
|
||||
|
|
|
@ -23,35 +23,35 @@
|
|||
|
||||
<!-- Source files -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(SrcDir)lapi.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lauxlib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lbaselib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lcode.cpp" />
|
||||
<ClCompile Include="$(SrcDir)ldblib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)ldebug.cpp" />
|
||||
<ClCompile Include="$(SrcDir)ldo.cpp" />
|
||||
<ClCompile Include="$(SrcDir)ldump.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lfunc.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lgc.cpp" />
|
||||
<ClCompile Include="$(SrcDir)linit.cpp" />
|
||||
<ClCompile Include="$(SrcDir)liolib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)llex.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lmathlib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lmem.cpp" />
|
||||
<ClCompile Include="$(SrcDir)loadlib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lobject.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lopcodes.cpp" />
|
||||
<ClCompile Include="$(SrcDir)loslib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lparser.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lstate.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lstring.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lstrlib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)ltable.cpp" />
|
||||
<ClCompile Include="$(SrcDir)ltablib.cpp" />
|
||||
<ClCompile Include="$(SrcDir)ltm.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lundump.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lvm.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lzio.cpp" />
|
||||
<ClCompile Include="$(SrcDir)lapi.c" />
|
||||
<ClCompile Include="$(SrcDir)lauxlib.c" />
|
||||
<ClCompile Include="$(SrcDir)lbaselib.c" />
|
||||
<ClCompile Include="$(SrcDir)lcode.c" />
|
||||
<ClCompile Include="$(SrcDir)ldblib.c" />
|
||||
<ClCompile Include="$(SrcDir)ldebug.c" />
|
||||
<ClCompile Include="$(SrcDir)ldo.c" />
|
||||
<ClCompile Include="$(SrcDir)ldump.c" />
|
||||
<ClCompile Include="$(SrcDir)lfunc.c" />
|
||||
<ClCompile Include="$(SrcDir)lgc.c" />
|
||||
<ClCompile Include="$(SrcDir)linit.c" />
|
||||
<ClCompile Include="$(SrcDir)liolib.c" />
|
||||
<ClCompile Include="$(SrcDir)llex.c" />
|
||||
<ClCompile Include="$(SrcDir)lmathlib.c" />
|
||||
<ClCompile Include="$(SrcDir)lmem.c" />
|
||||
<ClCompile Include="$(SrcDir)loadlib.c" />
|
||||
<ClCompile Include="$(SrcDir)lobject.c" />
|
||||
<ClCompile Include="$(SrcDir)lopcodes.c" />
|
||||
<ClCompile Include="$(SrcDir)loslib.c" />
|
||||
<ClCompile Include="$(SrcDir)lparser.c" />
|
||||
<ClCompile Include="$(SrcDir)lstate.c" />
|
||||
<ClCompile Include="$(SrcDir)lstring.c" />
|
||||
<ClCompile Include="$(SrcDir)lstrlib.c" />
|
||||
<ClCompile Include="$(SrcDir)ltable.c" />
|
||||
<ClCompile Include="$(SrcDir)ltablib.c" />
|
||||
<ClCompile Include="$(SrcDir)ltm.c" />
|
||||
<ClCompile Include="$(SrcDir)lundump.c" />
|
||||
<ClCompile Include="$(SrcDir)lvm.c" />
|
||||
<ClCompile Include="$(SrcDir)lzio.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(SrcDir)lapi.h" />
|
||||
|
@ -81,7 +81,7 @@
|
|||
|
||||
<Target Name="CopyHeaders" BeforeTargets="Build">
|
||||
<Copy
|
||||
SourceFiles="$(SrcDir)lua.h;$(SrcDir)lualib.h;$(SrcDir)lauxlib.h;$(SrcDir)luaconf.h"
|
||||
SourceFiles="$(SrcDir)lua.h;$(SrcDir)lualib.h;$(SrcDir)lauxlib.h;$(SrcDir)luaconf.h;$(SrcDir)lua.hpp"
|
||||
DestinationFolder="$(AegisubSourceBase)include"
|
||||
SkipUnchangedFiles="true"
|
||||
/>
|
||||
|
|
|
@ -15,91 +15,91 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(SrcDir)lapi.cpp">
|
||||
<ClCompile Include="$(SrcDir)lapi.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lcode.cpp">
|
||||
<ClCompile Include="$(SrcDir)lcode.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)ldo.cpp">
|
||||
<ClCompile Include="$(SrcDir)ldo.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)ldump.cpp">
|
||||
<ClCompile Include="$(SrcDir)ldump.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lfunc.cpp">
|
||||
<ClCompile Include="$(SrcDir)lfunc.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lgc.cpp">
|
||||
<ClCompile Include="$(SrcDir)lgc.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)linit.cpp">
|
||||
<ClCompile Include="$(SrcDir)linit.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)llex.cpp">
|
||||
<ClCompile Include="$(SrcDir)llex.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lmem.cpp">
|
||||
<ClCompile Include="$(SrcDir)lmem.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lobject.cpp">
|
||||
<ClCompile Include="$(SrcDir)lobject.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lopcodes.cpp">
|
||||
<ClCompile Include="$(SrcDir)lopcodes.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lparser.cpp">
|
||||
<ClCompile Include="$(SrcDir)lparser.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lstate.cpp">
|
||||
<ClCompile Include="$(SrcDir)lstate.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lstring.cpp">
|
||||
<ClCompile Include="$(SrcDir)lstring.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)ldebug.cpp">
|
||||
<ClCompile Include="$(SrcDir)ldebug.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)ltable.cpp">
|
||||
<ClCompile Include="$(SrcDir)ltable.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)ltm.cpp">
|
||||
<ClCompile Include="$(SrcDir)ltm.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lundump.cpp">
|
||||
<ClCompile Include="$(SrcDir)lundump.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lvm.cpp">
|
||||
<ClCompile Include="$(SrcDir)lvm.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lzio.cpp">
|
||||
<ClCompile Include="$(SrcDir)lzio.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lbaselib.cpp">
|
||||
<ClCompile Include="$(SrcDir)lbaselib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)ltablib.cpp">
|
||||
<ClCompile Include="$(SrcDir)ltablib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)ldblib.cpp">
|
||||
<ClCompile Include="$(SrcDir)ldblib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)liolib.cpp">
|
||||
<ClCompile Include="$(SrcDir)liolib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lmathlib.cpp">
|
||||
<ClCompile Include="$(SrcDir)lmathlib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)loslib.cpp">
|
||||
<ClCompile Include="$(SrcDir)loslib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lstrlib.cpp">
|
||||
<ClCompile Include="$(SrcDir)lstrlib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)loadlib.cpp">
|
||||
<ClCompile Include="$(SrcDir)loadlib.c">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)lauxlib.cpp">
|
||||
<ClCompile Include="$(SrcDir)lauxlib.c">
|
||||
<Filter>Standard library</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -17,20 +17,20 @@
|
|||
<!-- Project specific configuration -->
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>LUABINS_LUABUILTASCPP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(SrcDir)..\..\lua51\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Source files -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(SrcDir)fwrite.cpp" />
|
||||
<ClCompile Include="$(SrcDir)load.cpp" />
|
||||
<ClCompile Include="$(SrcDir)luabins.cpp" />
|
||||
<ClCompile Include="$(SrcDir)luainternals.cpp" />
|
||||
<ClCompile Include="$(SrcDir)save.cpp" />
|
||||
<ClCompile Include="$(SrcDir)savebuffer.cpp" />
|
||||
<ClCompile Include="$(SrcDir)write.cpp" />
|
||||
<ClCompile Include="$(SrcDir)fwrite.c" />
|
||||
<ClCompile Include="$(SrcDir)load.c" />
|
||||
<ClCompile Include="$(SrcDir)luabins.c" />
|
||||
<ClCompile Include="$(SrcDir)luainternals.c" />
|
||||
<ClCompile Include="$(SrcDir)save.c" />
|
||||
<ClCompile Include="$(SrcDir)savebuffer.c" />
|
||||
<ClCompile Include="$(SrcDir)write.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(SrcDir)fwrite.h" />
|
||||
|
|
|
@ -9,25 +9,25 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(SrcDir)fwrite.cpp">
|
||||
<ClCompile Include="$(SrcDir)fwrite.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)load.cpp">
|
||||
<ClCompile Include="$(SrcDir)load.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)luabins.cpp">
|
||||
<ClCompile Include="$(SrcDir)luabins.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)luainternals.cpp">
|
||||
<ClCompile Include="$(SrcDir)luainternals.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)save.cpp">
|
||||
<ClCompile Include="$(SrcDir)save.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)savebuffer.cpp">
|
||||
<ClCompile Include="$(SrcDir)savebuffer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)write.cpp">
|
||||
<ClCompile Include="$(SrcDir)write.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -11,6 +11,7 @@ lagi_pre.h.gch: CXXFLAGS := $(CXXFLAGS)
|
|||
common/charset_conv.o: CXXFLAGS += $(CFLAGS_ICONV)
|
||||
common/parser.o: CXXFLAGS += -ftemplate-depth=256
|
||||
unix/path.o: CXXFLAGS += -DP_DATA=\"$(P_DATA)\" -DP_DOC=\"$(P_DOC)\" -DP_LOCALE=\"$(P_LOCALE)\"
|
||||
lua/**/*.o: CPPFLAGS += -I../vendor/lua/src
|
||||
|
||||
SRC += \
|
||||
common/parser.cpp \
|
||||
|
@ -43,7 +44,7 @@ SRC += \
|
|||
common/vfr.cpp \
|
||||
lua/modules.cpp \
|
||||
lua/modules/lfs.cpp \
|
||||
lua/modules/lpeg.cpp \
|
||||
lua/modules/lpeg.c \
|
||||
lua/modules/re.cpp \
|
||||
lua/script_reader.cpp \
|
||||
lua/utils.cpp \
|
||||
|
@ -68,3 +69,5 @@ EXTRA_DIST += osx/util.mm
|
|||
|
||||
include ../Makefile.target
|
||||
-include */*.d
|
||||
-include lua/*/*.d
|
||||
-include common/*/*.d
|
||||
|
|
|
@ -16,13 +16,22 @@
|
|||
|
||||
#include <libaegisub/fs.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <boost/exception/detail/attribute_noreturn.hpp>
|
||||
#include <lua.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
namespace agi { namespace lua {
|
||||
// Exception type for errors where the error details are on the lua stack
|
||||
struct error_tag {};
|
||||
|
||||
// Below are functionally equivalent to the luaL_ functions, but using a C++
|
||||
// exception for stack unwinding
|
||||
int BOOST_ATTRIBUTE_NORETURN error(lua_State *L, const char *fmt, ...);
|
||||
int BOOST_ATTRIBUTE_NORETURN argerror(lua_State *L, int narg, const char *extramsg);
|
||||
int BOOST_ATTRIBUTE_NORETURN typerror(lua_State *L, int narg, const char *tname);
|
||||
void argcheck(lua_State *L, bool cond, int narg, const char *msg);
|
||||
|
||||
inline void push_value(lua_State *L, bool value) { lua_pushboolean(L, value); }
|
||||
inline void push_value(lua_State *L, const char *value) { lua_pushstring(L, value); }
|
||||
|
@ -62,17 +71,51 @@ void push_value(lua_State *L, std::vector<T> const& value) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Wrap a function which may throw exceptions and make it trigger lua errors
|
||||
/// whenever it throws
|
||||
template<int (*func)(lua_State *L)>
|
||||
int exception_wrapper(lua_State *L) {
|
||||
try {
|
||||
return func(L);
|
||||
}
|
||||
catch (agi::Exception const& e) {
|
||||
push_value(L, e.GetChainedMessage());
|
||||
return lua_error(L);
|
||||
}
|
||||
catch (std::exception const& e) {
|
||||
push_value(L, e.what());
|
||||
return lua_error(L);
|
||||
}
|
||||
catch (error_tag) {
|
||||
// Error message is already on the stack
|
||||
return lua_error(L);
|
||||
}
|
||||
catch (...) {
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void set_field(lua_State *L, const char *name, T value) {
|
||||
push_value(L, value);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
template<int (*func)(lua_State *L)>
|
||||
void set_field(lua_State *L, const char *name) {
|
||||
push_value(L, exception_wrapper<func>);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
std::string get_string_or_default(lua_State *L, int idx);
|
||||
std::string get_string(lua_State *L, int idx);
|
||||
std::string check_string(lua_State *L, int idx);
|
||||
std::string get_global_string(lua_State *L, const char *name);
|
||||
|
||||
std::string check_string(lua_State *L, int idx);
|
||||
int check_int(lua_State *L, int idx);
|
||||
size_t check_uint(lua_State *L, int idx);
|
||||
void *check_udata(lua_State *L, int idx, const char *mt);
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T *make(lua_State *L, const char *mt, Args&&... args) {
|
||||
auto obj = static_cast<T*>(lua_newuserdata(L, sizeof(T)));
|
||||
|
@ -84,7 +127,7 @@ T *make(lua_State *L, const char *mt, Args&&... args) {
|
|||
|
||||
template<typename T>
|
||||
T& get(lua_State *L, int idx, const char *mt) {
|
||||
return *static_cast<T *>(luaL_checkudata(L, idx, mt));
|
||||
return *static_cast<T *>(check_udata(L, idx, mt));
|
||||
}
|
||||
|
||||
struct LuaForEachBreak {};
|
||||
|
@ -105,6 +148,8 @@ void lua_for_each(lua_State *L, Func&& func) {
|
|||
lua_pop(L, 1); // pop table
|
||||
}
|
||||
|
||||
/// Lua error handler which adds the stack trace to the error message, with
|
||||
/// moonscript line rewriting support
|
||||
int add_stack_trace(lua_State *L);
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
|
|
@ -18,12 +18,10 @@
|
|||
|
||||
#include "libaegisub/lua/utils.h"
|
||||
|
||||
#include <lualib.h>
|
||||
|
||||
extern "C" int luaopen_luabins(lua_State *L);
|
||||
extern "C" int luaopen_re_impl(lua_State *L);
|
||||
int luaopen_lfs(lua_State *L);
|
||||
int luaopen_lpeg(lua_State *L);
|
||||
extern "C" int luaopen_lfs(lua_State *L);
|
||||
extern "C" int luaopen_lpeg(lua_State *L);
|
||||
|
||||
namespace agi { namespace lua {
|
||||
int regex_init(lua_State *L);
|
||||
|
|
|
@ -24,32 +24,30 @@ using namespace agi::lua;
|
|||
using namespace agi::fs;
|
||||
namespace bfs = boost::filesystem;
|
||||
|
||||
template<typename Func>
|
||||
int call(lua_State *L, Func&& f) {
|
||||
template<void (*func)(lua_State *L)>
|
||||
int wrap(lua_State *L) {
|
||||
try {
|
||||
f();
|
||||
func(L);
|
||||
return 1;
|
||||
}
|
||||
catch (bfs::filesystem_error const& e) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, e.what());
|
||||
push_value(L, e.what());
|
||||
return 2;
|
||||
}
|
||||
catch (agi::Exception const& e) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, e.GetChainedMessage().c_str());
|
||||
push_value(L, e.GetChainedMessage());
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
template<void (*func)(lua_State *L)>
|
||||
int wrap(lua_State *L) {
|
||||
return call(L, [=] { func(L); });
|
||||
catch (error_tag) {
|
||||
return lua_error(L);
|
||||
}
|
||||
}
|
||||
|
||||
void chdir(lua_State *L) {
|
||||
bfs::current_path(check_string(L, 1));
|
||||
lua_pushboolean(L, true);
|
||||
push_value(L, true);
|
||||
}
|
||||
|
||||
void currentdir(lua_State *L) {
|
||||
|
@ -58,17 +56,17 @@ void currentdir(lua_State *L) {
|
|||
|
||||
void mkdir(lua_State *L) {
|
||||
CreateDirectory(check_string(L, 1));
|
||||
lua_pushboolean(L, true);
|
||||
push_value(L, true);
|
||||
}
|
||||
|
||||
void rmdir(lua_State *L) {
|
||||
Remove(check_string(L, 1));
|
||||
lua_pushboolean(L, true);
|
||||
push_value(L, true);
|
||||
}
|
||||
|
||||
void touch(lua_State *L) {
|
||||
Touch(check_string(L, 1));
|
||||
lua_pushboolean(L, true);
|
||||
push_value(L, true);
|
||||
}
|
||||
|
||||
int dir_next(lua_State *L) {
|
||||
|
@ -88,18 +86,13 @@ int dir_close(lua_State *L) {
|
|||
}
|
||||
|
||||
int dir(lua_State *L) {
|
||||
try {
|
||||
const path p = check_string(L, 1);
|
||||
push_value(L, dir_next);
|
||||
make<agi::fs::DirectoryIterator>(L, "aegisub.lfs.dir", check_string(L, 1), "");
|
||||
return 2;
|
||||
}
|
||||
catch (agi::Exception const& e) {
|
||||
return luaL_error(L, "%s", e.GetChainedMessage().c_str());
|
||||
}
|
||||
const path p = check_string(L, 1);
|
||||
push_value(L, dir_next);
|
||||
make<agi::fs::DirectoryIterator>(L, "aegisub.lfs.dir", check_string(L, 1), "");
|
||||
return 2;
|
||||
}
|
||||
|
||||
int attributes(lua_State *L) {
|
||||
void attributes(lua_State *L) {
|
||||
static std::pair<const char *, void (*)(lua_State *, path const&)> fields[] = {
|
||||
{"mode", [](lua_State *L, path const& p) {
|
||||
switch (status(p).type()) {
|
||||
|
@ -119,45 +112,43 @@ int attributes(lua_State *L) {
|
|||
{"size", [](lua_State *L, path const& p) { push_value(L, Size(p)); }}
|
||||
};
|
||||
|
||||
return call(L, [=] {
|
||||
const path p = check_string(L, 1);
|
||||
const path p = check_string(L, 1);
|
||||
|
||||
const auto field = get_string(L, 2);
|
||||
if (!field.empty()) {
|
||||
for (const auto getter : fields) {
|
||||
if (field == getter.first) {
|
||||
getter.second(L, p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
luaL_error(L, "Invalid attribute name: %s", field.c_str());
|
||||
}
|
||||
|
||||
lua_createtable(L, 0, boost::size(fields));
|
||||
const auto field = get_string(L, 2);
|
||||
if (!field.empty()) {
|
||||
for (const auto getter : fields) {
|
||||
getter.second(L, p);
|
||||
lua_setfield(L, -2, getter.first);
|
||||
if (field == getter.first) {
|
||||
getter.second(L, p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
error(L, "Invalid attribute name: %s", field.c_str());
|
||||
}
|
||||
|
||||
lua_createtable(L, 0, boost::size(fields));
|
||||
for (const auto getter : fields) {
|
||||
getter.second(L, p);
|
||||
lua_setfield(L, -2, getter.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int luaopen_lfs(lua_State *L) {
|
||||
extern "C" int luaopen_lfs(lua_State *L) {
|
||||
if (luaL_newmetatable(L, "aegisub.lfs.dir")) {
|
||||
set_field(L, "__gc", dir_close);
|
||||
set_field<dir_close>(L, "__gc");
|
||||
|
||||
lua_createtable(L, 0, 2);
|
||||
set_field(L, "next", dir_next);
|
||||
set_field(L, "close", dir_close);
|
||||
set_field<dir_next>(L, "next");
|
||||
set_field<dir_close>(L, "close");
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
const struct luaL_Reg lib[] = {
|
||||
{"attributes", attributes},
|
||||
{"attributes", wrap<attributes>},
|
||||
{"chdir", wrap<chdir>},
|
||||
{"currentdir", wrap<currentdir>},
|
||||
{"dir", dir},
|
||||
{"dir", exception_wrapper<dir>},
|
||||
{"mkdir", wrap<mkdir>},
|
||||
{"rmdir", wrap<rmdir>},
|
||||
{"touch", wrap<touch>},
|
||||
|
|
|
@ -31,7 +31,7 @@ boost::smatch& get_smatch(lua_State *L) {
|
|||
}
|
||||
|
||||
int regex_matches(lua_State *L) {
|
||||
lua_pushboolean(L, u32regex_match(check_string(L, 2), get_regex(L)));
|
||||
push_value(L, u32regex_match(check_string(L, 2), get_regex(L)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -52,9 +52,9 @@ int regex_match(lua_State *L) {
|
|||
}
|
||||
|
||||
int regex_get_match(lua_State *L) {
|
||||
auto match = get_smatch(L);
|
||||
int idx = luaL_checkinteger(L, 2) - 1;
|
||||
if (static_cast<size_t>(idx) > match.size() || !match[idx].matched) {
|
||||
auto& match = get_smatch(L);
|
||||
auto idx = check_uint(L, 2) - 1;
|
||||
if (idx > match.size() || !match[idx].matched) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
@ -65,9 +65,10 @@ int regex_get_match(lua_State *L) {
|
|||
}
|
||||
|
||||
int regex_search(lua_State *L) {
|
||||
auto re = get_regex(L);
|
||||
std::string str = check_string(L, 2);
|
||||
int start = luaL_checkinteger(L, 3) - 1;
|
||||
auto& re = get_regex(L);
|
||||
auto str = check_string(L, 2);
|
||||
auto start = check_uint(L, 3) - 1;
|
||||
argcheck(L, start <= str.size(), 3, "out of bounds");
|
||||
boost::smatch result;
|
||||
if (!u32regex_search(str.cbegin() + start, str.cend(), result, re,
|
||||
start > 0 ? boost::match_prev_avail | boost::match_not_bob : boost::match_default))
|
||||
|
@ -82,10 +83,10 @@ int regex_search(lua_State *L) {
|
|||
}
|
||||
|
||||
int regex_replace(lua_State *L) {
|
||||
auto re = get_regex(L);
|
||||
auto& re = get_regex(L);
|
||||
const auto replacement = check_string(L, 2);
|
||||
const std::string str = check_string(L, 3);
|
||||
int max_count = luaL_checkinteger(L, 4);
|
||||
const auto str = check_string(L, 3);
|
||||
int max_count = check_int(L, 4);
|
||||
|
||||
// Can't just use regex_replace here since it can only do one or infinite replacements
|
||||
auto match = boost::u32regex_iterator<std::string::const_iterator>(begin(str), end(str), re);
|
||||
|
@ -110,8 +111,8 @@ int regex_replace(lua_State *L) {
|
|||
}
|
||||
|
||||
int regex_compile(lua_State *L) {
|
||||
std::string pattern(check_string(L, 1));
|
||||
int flags = luaL_checkinteger(L, 2);
|
||||
auto pattern(check_string(L, 1));
|
||||
int flags = check_int(L, 2);
|
||||
auto re = make<boost::u32regex>(L, "aegisub.regex");
|
||||
|
||||
try {
|
||||
|
@ -175,23 +176,23 @@ int regex_init_flags(lua_State *L) {
|
|||
|
||||
extern "C" int luaopen_re_impl(lua_State *L) {
|
||||
if (luaL_newmetatable(L, "aegisub.regex")) {
|
||||
set_field(L, "__gc", regex_gc);
|
||||
set_field<regex_gc>(L, "__gc");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
if (luaL_newmetatable(L, "aegisub.smatch")) {
|
||||
set_field(L, "__gc", smatch_gc);
|
||||
set_field<smatch_gc>(L, "__gc");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lua_createtable(L, 0, 8);
|
||||
set_field(L, "matches", regex_matches);
|
||||
set_field(L, "search", regex_search);
|
||||
set_field(L, "match", regex_match);
|
||||
set_field(L, "get_match", regex_get_match);
|
||||
set_field(L, "replace", regex_replace);
|
||||
set_field(L, "compile", regex_compile);
|
||||
set_field(L, "process_flags", regex_process_flags);
|
||||
set_field(L, "init_flags", regex_init_flags);
|
||||
set_field<regex_matches>(L, "matches");
|
||||
set_field<regex_search>(L, "search");
|
||||
set_field<regex_match>(L, "match");
|
||||
set_field<regex_get_match>(L, "get_match");
|
||||
set_field<regex_replace>(L, "replace");
|
||||
set_field<regex_compile>(L, "compile");
|
||||
set_field<regex_process_flags>(L, "process_flags");
|
||||
set_field<regex_init_flags>(L, "init_flags");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -47,18 +47,19 @@ namespace agi { namespace lua {
|
|||
if (!agi::fs::HasExtension(filename, "moon"))
|
||||
return luaL_loadbuffer(L, buff, size, filename.string().c_str()) == 0;
|
||||
|
||||
// Save the text we'll be loading for the line number rewriting in the
|
||||
// error handling
|
||||
push_value(L, buff);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, ("raw moonscript: " + filename.string()).c_str());
|
||||
|
||||
// We have a MoonScript file, so we need to load it with that
|
||||
// It might be nice to have a dedicated lua state for compiling
|
||||
// MoonScript to Lua
|
||||
if (luaL_dostring(L, "return require('moonscript').loadstring"))
|
||||
return false; // Leaves error message on stack
|
||||
|
||||
// Save the text we'll be loading for the line number rewriting in the
|
||||
// error handling
|
||||
lua_pushlstring(L, buff, size);
|
||||
lua_pushstring(L, filename.string().c_str());
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, ("raw moonscript: " + filename.string()).c_str());
|
||||
|
||||
push_value(L, filename);
|
||||
if (lua_pcall(L, 2, 2, 0))
|
||||
return false; // Leaves error message on stack
|
||||
|
||||
|
@ -74,13 +75,13 @@ namespace agi { namespace lua {
|
|||
|
||||
static int module_loader(lua_State *L) {
|
||||
int pretop = lua_gettop(L);
|
||||
std::string module(luaL_checkstring(L, -1));
|
||||
std::string module(check_string(L, -1));
|
||||
boost::replace_all(module, ".", LUA_DIRSEP);
|
||||
|
||||
// Get the lua package include path (which the user may have modified)
|
||||
lua_getglobal(L, "package");
|
||||
lua_getfield(L, -1, "path");
|
||||
std::string package_paths(luaL_checkstring(L, -1));
|
||||
std::string package_paths(check_string(L, -1));
|
||||
lua_pop(L, 2);
|
||||
|
||||
boost::char_separator<char> sep(";");
|
||||
|
@ -99,7 +100,7 @@ namespace agi { namespace lua {
|
|||
|
||||
try {
|
||||
if (!LoadFile(L, path))
|
||||
return luaL_error(L, "Error loading Lua module \"%s\":\n%s", path.string().c_str(), luaL_checkstring(L, 1));
|
||||
return error(L, "Error loading Lua module \"%s\":\n%s", path.string().c_str(), check_string(L, 1).c_str());
|
||||
break;
|
||||
}
|
||||
catch (agi::fs::FileNotFound const&) {
|
||||
|
@ -109,7 +110,7 @@ namespace agi { namespace lua {
|
|||
// Not an error so swallow and continue on
|
||||
}
|
||||
catch (agi::Exception const& e) {
|
||||
return luaL_error(L, "Error loading Lua module \"%s\":\n%s", path.string().c_str(), e.GetChainedMessage().c_str());
|
||||
return error(L, "Error loading Lua module \"%s\":\n%s", path.string().c_str(), e.GetChainedMessage().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,7 @@ namespace agi { namespace lua {
|
|||
|
||||
// Replace the default lua module loader with our unicode compatible one
|
||||
lua_getfield(L, -1, "loaders");
|
||||
push_value(L, module_loader);
|
||||
push_value(L, exception_wrapper<module_loader>);
|
||||
lua_rawseti(L, -2, 2);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable warnings for noreturn functions having return types
|
||||
#pragma warning(disable: 4645 4646)
|
||||
#endif
|
||||
|
||||
namespace agi { namespace lua {
|
||||
std::string get_string_or_default(lua_State *L, int idx) {
|
||||
size_t len = 0;
|
||||
|
@ -39,12 +44,6 @@ std::string get_string(lua_State *L, int idx) {
|
|||
return std::string(str ? str : "", len);
|
||||
}
|
||||
|
||||
std::string check_string(lua_State *L, int idx) {
|
||||
size_t len = 0;
|
||||
const char *str = luaL_checklstring(L, idx, &len);
|
||||
return std::string(str ? str : "", len);
|
||||
}
|
||||
|
||||
std::string get_global_string(lua_State *L, const char *name) {
|
||||
lua_getglobal(L, name);
|
||||
std::string ret;
|
||||
|
@ -54,6 +53,41 @@ std::string get_global_string(lua_State *L, const char *name) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string check_string(lua_State *L, int idx) {
|
||||
size_t len = 0;
|
||||
const char *str = lua_tolstring(L, idx, &len);
|
||||
if (!str) typerror(L, idx, "string");
|
||||
return std::string(str, len);
|
||||
}
|
||||
|
||||
int check_int(lua_State *L, int idx) {
|
||||
auto v = lua_tointeger(L, idx);
|
||||
if (v == 0 && !lua_isnumber(L, idx))
|
||||
typerror(L, idx, "number");
|
||||
return v;
|
||||
}
|
||||
|
||||
size_t check_uint(lua_State *L, int idx) {
|
||||
auto v = lua_tointeger(L, idx);
|
||||
if (v == 0 && !lua_isnumber(L, idx))
|
||||
typerror(L, idx, "number");
|
||||
if (v < 0)
|
||||
argerror(L, idx, "must be >= 0");
|
||||
return static_cast<size_t>(v);
|
||||
}
|
||||
|
||||
void *check_udata(lua_State *L, int idx, const char *mt) {
|
||||
void *p = lua_touserdata(L, idx);
|
||||
if (!p) typerror(L, idx, mt);
|
||||
if (!lua_getmetatable(L, idx)) typerror(L, idx, mt);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, mt);
|
||||
if (!lua_rawequal(L, -1, -2)) typerror(L, idx, mt);
|
||||
|
||||
lua_pop(L, 2);
|
||||
return p;
|
||||
}
|
||||
|
||||
static int moon_line(lua_State *L, int lua_line, std::string const& file) {
|
||||
if (luaL_dostring(L, "return require 'moonscript.line_tables'")) {
|
||||
lua_pop(L, 1); // pop error message
|
||||
|
@ -147,6 +181,37 @@ int add_stack_trace(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int BOOST_ATTRIBUTE_NORETURN error(lua_State *L, const char *fmt, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
luaL_where(L, 1);
|
||||
lua_pushvfstring(L, fmt, argp);
|
||||
va_end(argp);
|
||||
lua_concat(L, 2);
|
||||
throw error_tag();
|
||||
}
|
||||
|
||||
int BOOST_ATTRIBUTE_NORETURN argerror(lua_State *L, int narg, const char *extramsg) {
|
||||
lua_Debug ar;
|
||||
if (!lua_getstack(L, 0, &ar))
|
||||
error(L, "bad argument #%d (%s)", narg, extramsg);
|
||||
lua_getinfo(L, "n", &ar);
|
||||
if (strcmp(ar.namewhat, "method") == 0 && --narg == 0)
|
||||
error(L, "calling '%s' on bad self (%s)", ar.name, extramsg);
|
||||
if (!ar.name) ar.name = "?";
|
||||
error(L, "bad argument #%d to '%s' (%s)",
|
||||
narg, ar.name, extramsg);
|
||||
}
|
||||
|
||||
int BOOST_ATTRIBUTE_NORETURN typerror(lua_State *L, int narg, const char *tname) {
|
||||
const char *msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
tname, luaL_typename(L, narg));
|
||||
argerror(L, narg, msg);
|
||||
}
|
||||
|
||||
void argcheck(lua_State *L, bool cond, int narg, const char *msg) {
|
||||
if (!cond) argerror(L, narg, msg);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void LuaStackcheck::check_stack(int additional) {
|
||||
|
|
|
@ -106,7 +106,7 @@ charset_detect.o: CXXFLAGS += -D_X86_
|
|||
font_file_lister_fontconfig.o: CXXFLAGS += $(CFLAGS_FONTCONFIG)
|
||||
text_file_reader.o: CXXFLAGS += -D_X86_
|
||||
video_provider_manager.o: CXXFLAGS += $(CFLAGS_FFMS2)
|
||||
auto4_lua.o auto4_lua_assfile.o auto4_lua_dialog.o auto4_lua_progresssink.o: CXXFLAGS += $(CFLAGS_LUA)
|
||||
auto4_lua.o auto4_lua_assfile.o auto4_lua_dialog.o auto4_lua_progresssink.o: CPPFLAGS += -I../vendor/lua/src
|
||||
|
||||
SRC += \
|
||||
MatroskaParser.c \
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace {
|
|||
|
||||
wxString check_wxstring(lua_State *L, int idx)
|
||||
{
|
||||
return wxString::FromUTF8(luaL_checkstring(L, idx));
|
||||
return to_wx(check_string(L, idx));
|
||||
}
|
||||
|
||||
void set_context(lua_State *L, const agi::Context *c)
|
||||
|
@ -134,7 +134,7 @@ namespace {
|
|||
|
||||
int clipboard_set(lua_State *L)
|
||||
{
|
||||
std::string str(luaL_checkstring(L, 1));
|
||||
std::string str(check_string(L, 1));
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
|
@ -158,8 +158,8 @@ namespace {
|
|||
int clipboard_init(lua_State *L)
|
||||
{
|
||||
lua_createtable(L, 0, 2);
|
||||
set_field(L, "get", clipboard_get);
|
||||
set_field(L, "set", clipboard_set);
|
||||
set_field<clipboard_get>(L, "get");
|
||||
set_field<clipboard_set>(L, "set");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ namespace {
|
|||
};
|
||||
|
||||
template<typename TableIter>
|
||||
int pairs(lua_State *L) {
|
||||
int pairs(lua_State *L) BOOST_NOEXCEPT {
|
||||
// If the metamethod is defined, call it instead
|
||||
if (luaL_getmetafield(L, 1, TableIter::method())) {
|
||||
lua_pushvalue(L, 1);
|
||||
|
@ -258,7 +258,7 @@ namespace {
|
|||
|
||||
int decode_path(lua_State *L)
|
||||
{
|
||||
std::string path = luaL_checkstring(L, 1);
|
||||
std::string path = check_string(L, 1);
|
||||
lua_pop(L, 1);
|
||||
push_value(L, config::path->Decode(path));
|
||||
return 1;
|
||||
|
@ -267,13 +267,13 @@ namespace {
|
|||
int cancel_script(lua_State *L)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return lua_error(L);
|
||||
throw error_tag();
|
||||
}
|
||||
|
||||
int lua_text_textents(lua_State *L)
|
||||
{
|
||||
luaL_argcheck(L, lua_istable(L, 1), 1, "");
|
||||
luaL_argcheck(L, lua_isstring(L, 2), 2, "");
|
||||
argcheck(L, !!lua_istable(L, 1), 1, "");
|
||||
argcheck(L, !!lua_isstring(L, 2), 2, "");
|
||||
|
||||
// have to check that it looks like a style table before actually converting
|
||||
// if it's a dialogue table then an active AssFile object is required
|
||||
|
@ -282,7 +282,7 @@ namespace {
|
|||
std::string actual_class{lua_tostring(L, -1)};
|
||||
boost::to_lower(actual_class);
|
||||
if (actual_class != "style")
|
||||
return luaL_error(L, "Not a style entry");
|
||||
return error(L, "Not a style entry");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
@ -291,11 +291,11 @@ namespace {
|
|||
auto st = dynamic_cast<AssStyle*>(et.get());
|
||||
lua_pop(L, 1);
|
||||
if (!st)
|
||||
return luaL_error(L, "Not a style entry");
|
||||
return error(L, "Not a style entry");
|
||||
|
||||
double width, height, descent, extlead;
|
||||
if (!Automation4::CalculateTextExtents(st, luaL_checkstring(L, 2), width, height, descent, extlead))
|
||||
return luaL_error(L, "Some internal error occurred calculating text_extents");
|
||||
if (!Automation4::CalculateTextExtents(st, check_string(L, 2), width, height, descent, extlead))
|
||||
return error(L, "Some internal error occurred calculating text_extents");
|
||||
|
||||
push_value(L, width);
|
||||
push_value(L, height);
|
||||
|
@ -429,7 +429,7 @@ namespace {
|
|||
lua_setglobal(L, "dofile");
|
||||
lua_pushnil(L);
|
||||
lua_setglobal(L, "loadfile");
|
||||
push_value(L, LuaInclude);
|
||||
push_value(L, exception_wrapper<LuaInclude>);
|
||||
lua_setglobal(L, "include");
|
||||
|
||||
// replace pairs and ipairs with lua 5.2-style versions
|
||||
|
@ -459,19 +459,19 @@ namespace {
|
|||
lua_pushstring(L, "aegisub");
|
||||
lua_createtable(L, 0, 12);
|
||||
|
||||
set_field(L, "register_macro", LuaCommand::LuaRegister);
|
||||
set_field(L, "register_filter", LuaExportFilter::LuaRegister);
|
||||
set_field(L, "text_extents", lua_text_textents);
|
||||
set_field(L, "frame_from_ms", frame_from_ms);
|
||||
set_field(L, "ms_from_frame", ms_from_frame);
|
||||
set_field(L, "video_size", video_size);
|
||||
set_field(L, "keyframes", get_keyframes);
|
||||
set_field(L, "decode_path", decode_path);
|
||||
set_field(L, "cancel", cancel_script);
|
||||
set_field<LuaCommand::LuaRegister>(L, "register_macro");
|
||||
set_field<LuaExportFilter::LuaRegister>(L, "register_filter");
|
||||
set_field<lua_text_textents>(L, "text_extents");
|
||||
set_field<frame_from_ms>(L, "frame_from_ms");
|
||||
set_field<ms_from_frame>(L, "ms_from_frame");
|
||||
set_field<video_size>(L, "video_size");
|
||||
set_field<get_keyframes>(L, "keyframes");
|
||||
set_field<decode_path>(L, "decode_path");
|
||||
set_field<cancel_script>(L, "cancel");
|
||||
set_field(L, "lua_automation_version", 4);
|
||||
set_field(L, "__init_clipboard", clipboard_init);
|
||||
set_field(L, "file_name", get_file_name);
|
||||
set_field(L, "gettext", get_translation);
|
||||
set_field<clipboard_init>(L, "__init_clipboard");
|
||||
set_field<get_file_name>(L, "file_name");
|
||||
set_field<get_translation>(L, "gettext");
|
||||
|
||||
// store aegisub table to globals
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
|
@ -550,8 +550,7 @@ namespace {
|
|||
{
|
||||
for (auto macro : macros) {
|
||||
if (macro->name() == command->name()) {
|
||||
luaL_error(L,
|
||||
"A macro named '%s' is already defined in script '%s'",
|
||||
error(L, "A macro named '%s' is already defined in script '%s'",
|
||||
command->StrDisplay(nullptr).utf8_str().data(), name.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -581,7 +580,7 @@ namespace {
|
|||
{
|
||||
const LuaScript *s = GetScriptObject(L);
|
||||
|
||||
const std::string filename(luaL_checkstring(L, 1));
|
||||
const std::string filename(check_string(L, 1));
|
||||
agi::fs::path filepath;
|
||||
|
||||
// Relative or absolute path
|
||||
|
@ -596,10 +595,10 @@ namespace {
|
|||
}
|
||||
|
||||
if (!agi::fs::FileExists(filepath))
|
||||
return luaL_error(L, "Lua include not found: %s", filename.c_str());
|
||||
return error(L, "Lua include not found: %s", filename.c_str());
|
||||
|
||||
if (!LoadFile(L, filepath))
|
||||
return luaL_error(L, "Error loading Lua include \"%s\":\n%s", filename.c_str(), luaL_checkstring(L, 1));
|
||||
return error(L, "Error loading Lua include \"%s\":\n%s", filename.c_str(), check_string(L, 1).c_str());
|
||||
|
||||
int pretop = lua_gettop(L) - 1; // don't count the function value itself
|
||||
lua_call(L, 0, LUA_MULTRET);
|
||||
|
@ -677,10 +676,10 @@ namespace {
|
|||
, cmd_type(cmd::COMMAND_NORMAL)
|
||||
{
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "filename");
|
||||
cmd_name = str(boost::format("automation/lua/%s/%s") % luaL_checkstring(L, -1) % luaL_checkstring(L, 1));
|
||||
cmd_name = str(boost::format("automation/lua/%s/%s") % check_string(L, -1) % check_string(L, 1));
|
||||
|
||||
if (!lua_isfunction(L, 3))
|
||||
luaL_error(L, "The macro processing function must be a function");
|
||||
error(L, "The macro processing function must be a function");
|
||||
|
||||
if (lua_isfunction(L, 4))
|
||||
cmd_type |= cmd::COMMAND_VALIDATE;
|
||||
|
@ -899,11 +898,11 @@ namespace {
|
|||
|
||||
// LuaFeatureFilter
|
||||
LuaExportFilter::LuaExportFilter(lua_State *L)
|
||||
: ExportFilter(luaL_checkstring(L, 1), lua_tostring(L, 2), lua_tointeger(L, 3))
|
||||
: ExportFilter(check_string(L, 1), lua_tostring(L, 2), lua_tointeger(L, 3))
|
||||
, LuaFeature(L)
|
||||
{
|
||||
if (!lua_isfunction(L, 4))
|
||||
luaL_error(L, "The filter processing function must be a function");
|
||||
error(L, "The filter processing function must be a function");
|
||||
|
||||
// new table for containing the functions for this feature
|
||||
lua_createtable(L, 0, 2);
|
||||
|
|
|
@ -131,13 +131,13 @@ namespace Automation4 {
|
|||
void LuaAssFile::CheckAllowModify()
|
||||
{
|
||||
if (!can_modify)
|
||||
luaL_error(L, "Attempt to modify subtitles in read-only feature context.");
|
||||
error(L, "Attempt to modify subtitles in read-only feature context.");
|
||||
}
|
||||
|
||||
void LuaAssFile::CheckBounds(int idx)
|
||||
{
|
||||
if (idx <= 0 || idx > (int)lines.size())
|
||||
luaL_error(L, "Requested out-of-range line from subtitle file: %d", idx);
|
||||
error(L, "Requested out-of-range line from subtitle file: %d", idx);
|
||||
}
|
||||
|
||||
void LuaAssFile::AssEntryToLua(lua_State *L, size_t idx)
|
||||
|
@ -239,89 +239,82 @@ namespace Automation4 {
|
|||
// convert it to a real AssEntry object, and pop the table from the stack
|
||||
|
||||
if (!lua_istable(L, -1))
|
||||
luaL_error(L, "Can't convert a non-table value to AssEntry");
|
||||
error(L, "Can't convert a non-table value to AssEntry");
|
||||
|
||||
lua_getfield(L, -1, "class");
|
||||
if (!lua_isstring(L, -1))
|
||||
luaL_error(L, "Table lacks 'class' field, can't convert to AssEntry");
|
||||
error(L, "Table lacks 'class' field, can't convert to AssEntry");
|
||||
|
||||
std::string lclass(lua_tostring(L, -1));
|
||||
boost::to_lower(lclass);
|
||||
lua_pop(L, 1);
|
||||
|
||||
std::unique_ptr<AssEntry> result;
|
||||
|
||||
try {
|
||||
if (lclass == "info")
|
||||
result = agi::make_unique<AssInfo>(get_string_field(L, "key", "info"), get_string_field(L, "value", "info"));
|
||||
else if (lclass == "style") {
|
||||
auto sty = new AssStyle;
|
||||
result.reset(sty);
|
||||
sty->name = get_string_field(L, "name", "style");
|
||||
sty->font = get_string_field(L, "fontname", "style");
|
||||
sty->fontsize = get_double_field(L, "fontsize", "style");
|
||||
sty->primary = get_string_field(L, "color1", "style");
|
||||
sty->secondary = get_string_field(L, "color2", "style");
|
||||
sty->outline = get_string_field(L, "color3", "style");
|
||||
sty->shadow = get_string_field(L, "color4", "style");
|
||||
sty->bold = get_bool_field(L, "bold", "style");
|
||||
sty->italic = get_bool_field(L, "italic", "style");
|
||||
sty->underline = get_bool_field(L, "underline", "style");
|
||||
sty->strikeout = get_bool_field(L, "strikeout", "style");
|
||||
sty->scalex = get_double_field(L, "scale_x", "style");
|
||||
sty->scaley = get_double_field(L, "scale_y", "style");
|
||||
sty->spacing = get_double_field(L, "spacing", "style");
|
||||
sty->angle = get_double_field(L, "angle", "style");
|
||||
sty->borderstyle = get_int_field(L, "borderstyle", "style");
|
||||
sty->outline_w = get_double_field(L, "outline", "style");
|
||||
sty->shadow_w = get_double_field(L, "shadow", "style");
|
||||
sty->alignment = get_int_field(L, "align", "style");
|
||||
sty->Margin[0] = get_int_field(L, "margin_l", "style");
|
||||
sty->Margin[1] = get_int_field(L, "margin_r", "style");
|
||||
sty->Margin[2] = get_int_field(L, "margin_t", "style");
|
||||
sty->encoding = get_int_field(L, "encoding", "style");
|
||||
sty->UpdateData();
|
||||
}
|
||||
else if (lclass == "dialogue") {
|
||||
assert(ass != 0); // since we need AssFile::AddExtradata
|
||||
auto dia = new AssDialogue;
|
||||
result.reset(dia);
|
||||
|
||||
dia->Comment = get_bool_field(L, "comment", "dialogue");
|
||||
dia->Layer = get_int_field(L, "layer", "dialogue");
|
||||
dia->Start = get_int_field(L, "start_time", "dialogue");
|
||||
dia->End = get_int_field(L, "end_time", "dialogue");
|
||||
dia->Style = get_string_field(L, "style", "dialogue");
|
||||
dia->Actor = get_string_field(L, "actor", "dialogue");
|
||||
dia->Margin[0] = get_int_field(L, "margin_l", "dialogue");
|
||||
dia->Margin[1] = get_int_field(L, "margin_r", "dialogue");
|
||||
dia->Margin[2] = get_int_field(L, "margin_t", "dialogue");
|
||||
dia->Effect = get_string_field(L, "effect", "dialogue");
|
||||
dia->Text = get_string_field(L, "text", "dialogue");
|
||||
|
||||
lua_getfield(L, -1, "extra");
|
||||
std::vector<uint32_t> new_ids;
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
auto key = get_string_or_default(L, -2);
|
||||
auto value = get_string_or_default(L, -1);
|
||||
new_ids.push_back(ass->AddExtradata(key, value));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
dia->ExtradataIds = new_ids;
|
||||
}
|
||||
else {
|
||||
luaL_error(L, "Found line with unknown class: %s", lclass.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
if (lclass == "info")
|
||||
result = agi::make_unique<AssInfo>(get_string_field(L, "key", "info"), get_string_field(L, "value", "info"));
|
||||
else if (lclass == "style") {
|
||||
auto sty = new AssStyle;
|
||||
result.reset(sty);
|
||||
sty->name = get_string_field(L, "name", "style");
|
||||
sty->font = get_string_field(L, "fontname", "style");
|
||||
sty->fontsize = get_double_field(L, "fontsize", "style");
|
||||
sty->primary = get_string_field(L, "color1", "style");
|
||||
sty->secondary = get_string_field(L, "color2", "style");
|
||||
sty->outline = get_string_field(L, "color3", "style");
|
||||
sty->shadow = get_string_field(L, "color4", "style");
|
||||
sty->bold = get_bool_field(L, "bold", "style");
|
||||
sty->italic = get_bool_field(L, "italic", "style");
|
||||
sty->underline = get_bool_field(L, "underline", "style");
|
||||
sty->strikeout = get_bool_field(L, "strikeout", "style");
|
||||
sty->scalex = get_double_field(L, "scale_x", "style");
|
||||
sty->scaley = get_double_field(L, "scale_y", "style");
|
||||
sty->spacing = get_double_field(L, "spacing", "style");
|
||||
sty->angle = get_double_field(L, "angle", "style");
|
||||
sty->borderstyle = get_int_field(L, "borderstyle", "style");
|
||||
sty->outline_w = get_double_field(L, "outline", "style");
|
||||
sty->shadow_w = get_double_field(L, "shadow", "style");
|
||||
sty->alignment = get_int_field(L, "align", "style");
|
||||
sty->Margin[0] = get_int_field(L, "margin_l", "style");
|
||||
sty->Margin[1] = get_int_field(L, "margin_r", "style");
|
||||
sty->Margin[2] = get_int_field(L, "margin_t", "style");
|
||||
sty->encoding = get_int_field(L, "encoding", "style");
|
||||
sty->UpdateData();
|
||||
}
|
||||
catch (agi::Exception const& e) {
|
||||
luaL_error(L, e.GetMessage().c_str());
|
||||
else if (lclass == "dialogue") {
|
||||
assert(ass != 0); // since we need AssFile::AddExtradata
|
||||
auto dia = new AssDialogue;
|
||||
result.reset(dia);
|
||||
|
||||
dia->Comment = get_bool_field(L, "comment", "dialogue");
|
||||
dia->Layer = get_int_field(L, "layer", "dialogue");
|
||||
dia->Start = get_int_field(L, "start_time", "dialogue");
|
||||
dia->End = get_int_field(L, "end_time", "dialogue");
|
||||
dia->Style = get_string_field(L, "style", "dialogue");
|
||||
dia->Actor = get_string_field(L, "actor", "dialogue");
|
||||
dia->Margin[0] = get_int_field(L, "margin_l", "dialogue");
|
||||
dia->Margin[1] = get_int_field(L, "margin_r", "dialogue");
|
||||
dia->Margin[2] = get_int_field(L, "margin_t", "dialogue");
|
||||
dia->Effect = get_string_field(L, "effect", "dialogue");
|
||||
dia->Text = get_string_field(L, "text", "dialogue");
|
||||
|
||||
lua_getfield(L, -1, "extra");
|
||||
std::vector<uint32_t> new_ids;
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
auto key = get_string_or_default(L, -2);
|
||||
auto value = get_string_or_default(L, -1);
|
||||
new_ids.push_back(ass->AddExtradata(key, value));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
dia->ExtradataIds = new_ids;
|
||||
}
|
||||
else {
|
||||
error(L, "Found line with unknown class: %s", lclass.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int LuaAssFile::ObjectIndexRead(lua_State *L)
|
||||
|
@ -359,7 +352,7 @@ namespace Automation4 {
|
|||
else {
|
||||
// idiot
|
||||
lua_pop(L, 1);
|
||||
return luaL_error(L, "Invalid indexing in Subtitle File object: '%s'", idx);
|
||||
return error(L, "Invalid indexing in Subtitle File object: '%s'", idx);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -367,7 +360,7 @@ namespace Automation4 {
|
|||
|
||||
default:
|
||||
// crap, user is stupid!
|
||||
return luaL_error(L, "Attempt to index a Subtitle File object with value of type '%s'.", lua_typename(L, lua_type(L, 2)));
|
||||
return error(L, "Attempt to index a Subtitle File object with value of type '%s'.", lua_typename(L, lua_type(L, 2)));
|
||||
}
|
||||
|
||||
assert(false);
|
||||
|
@ -427,7 +420,7 @@ namespace Automation4 {
|
|||
|
||||
CheckAllowModify();
|
||||
|
||||
int n = luaL_checkint(L, 2);
|
||||
int n = check_int(L, 2);
|
||||
if (n < 0) {
|
||||
// insert line so new index is n
|
||||
lua_remove(L, 1);
|
||||
|
@ -475,20 +468,20 @@ namespace Automation4 {
|
|||
int itemcount = lua_gettop(L);
|
||||
if (itemcount == 0) return;
|
||||
|
||||
std::vector<int> ids;
|
||||
std::vector<size_t> ids;
|
||||
if (itemcount == 1 && lua_istable(L, 1)) {
|
||||
lua_pushvalue(L, 1);
|
||||
lua_for_each(L, [&] {
|
||||
int n = luaL_checkint(L, -1);
|
||||
luaL_argcheck(L, n > 0 && n <= (int)lines.size(), 1, "Out of range line index");
|
||||
size_t n = check_uint(L, -1);
|
||||
argcheck(L, n > 0 && n <= lines.size(), 1, "Out of range line index");
|
||||
ids.push_back(n - 1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
ids.reserve(itemcount);
|
||||
while (itemcount > 0) {
|
||||
int n = luaL_checkint(L, itemcount);
|
||||
luaL_argcheck(L, n > 0 && n <= (int)lines.size(), itemcount, "Out of range line index");
|
||||
size_t n = check_uint(L, -1);
|
||||
argcheck(L, n > 0 && n <= lines.size(), itemcount, "Out of range line index");
|
||||
ids.push_back(n - 1);
|
||||
--itemcount;
|
||||
}
|
||||
|
@ -515,8 +508,8 @@ namespace Automation4 {
|
|||
{
|
||||
CheckAllowModify();
|
||||
|
||||
size_t a = std::max<size_t>(luaL_checkinteger(L, 1), 1) - 1;
|
||||
size_t b = std::min<size_t>(luaL_checkinteger(L, 2), lines.size());
|
||||
size_t a = std::max<size_t>(check_uint(L, 1), 1) - 1;
|
||||
size_t b = std::min<size_t>(check_uint(L, 2), lines.size());
|
||||
|
||||
if (a >= b) return;
|
||||
|
||||
|
@ -563,13 +556,13 @@ namespace Automation4 {
|
|||
{
|
||||
CheckAllowModify();
|
||||
|
||||
int before = luaL_checkinteger(L, 1);
|
||||
size_t before = check_uint(L, 1);
|
||||
|
||||
// + 1 to allow appending at the end of the file
|
||||
luaL_argcheck(L, before > 0 && before <= (int)lines.size() + 1, 1,
|
||||
argcheck(L, before > 0 && before <= lines.size() + 1, 1,
|
||||
"Out of range line index");
|
||||
|
||||
if (before == (int)lines.size() + 1) {
|
||||
if (before == lines.size() + 1) {
|
||||
lua_remove(L, 1);
|
||||
ObjectAppend(L);
|
||||
return;
|
||||
|
@ -606,8 +599,8 @@ namespace Automation4 {
|
|||
|
||||
int LuaAssFile::IterNext(lua_State *L)
|
||||
{
|
||||
int i = luaL_checkint(L, 2);
|
||||
if (i >= (int)lines.size()) {
|
||||
size_t i = check_uint(L, 2);
|
||||
if (i >= lines.size()) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
@ -621,7 +614,7 @@ namespace Automation4 {
|
|||
{
|
||||
auto e = LuaToAssEntry(L, ass);
|
||||
auto dia = dynamic_cast<AssDialogue*>(e.get());
|
||||
luaL_argcheck(L, dia, 1, "Subtitle line must be a dialogue line");
|
||||
argcheck(L, !!dia, 1, "Subtitle line must be a dialogue line");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
|
@ -655,14 +648,14 @@ namespace Automation4 {
|
|||
void LuaAssFile::LuaSetUndoPoint(lua_State *L)
|
||||
{
|
||||
if (!can_set_undo)
|
||||
luaL_error(L, "Attempt to set an undo point in a context where it makes no sense to do so.");
|
||||
error(L, "Attempt to set an undo point in a context where it makes no sense to do so.");
|
||||
|
||||
if (modification_type) {
|
||||
pending_commits.emplace_back();
|
||||
PendingCommit& back = pending_commits.back();
|
||||
|
||||
back.modification_type = modification_type;
|
||||
back.mesage = wxString::FromUTF8(luaL_checkstring(L, 1));
|
||||
back.mesage = to_wx(check_string(L, 1));
|
||||
back.lines = lines;
|
||||
modification_type = 0;
|
||||
}
|
||||
|
@ -674,7 +667,7 @@ namespace Automation4 {
|
|||
auto ud = lua_touserdata(L, idx);
|
||||
auto laf = *static_cast<LuaAssFile **>(ud);
|
||||
if (!allow_expired && laf->references < 2)
|
||||
luaL_error(L, "Subtitles object is no longer valid");
|
||||
error(L, "Subtitles object is no longer valid");
|
||||
return laf;
|
||||
}
|
||||
|
||||
|
@ -741,19 +734,19 @@ namespace Automation4 {
|
|||
|
||||
// make the metatable
|
||||
lua_createtable(L, 0, 5);
|
||||
set_field(L, "__index", closure_wrapper<&LuaAssFile::ObjectIndexRead>);
|
||||
set_field(L, "__newindex", closure_wrapper_v<&LuaAssFile::ObjectIndexWrite, false>);
|
||||
set_field(L, "__len", closure_wrapper<&LuaAssFile::ObjectGetLen>);
|
||||
set_field(L, "__gc", closure_wrapper_v<&LuaAssFile::ObjectGarbageCollect, true>);
|
||||
set_field(L, "__ipairs", closure_wrapper<&LuaAssFile::ObjectIPairs>);
|
||||
set_field<closure_wrapper<&LuaAssFile::ObjectIndexRead>>(L, "__index");
|
||||
set_field<closure_wrapper_v<&LuaAssFile::ObjectIndexWrite, false>>(L, "__newindex");
|
||||
set_field<closure_wrapper<&LuaAssFile::ObjectGetLen>>(L, "__len");
|
||||
set_field<closure_wrapper_v<&LuaAssFile::ObjectGarbageCollect, true>>(L, "__gc");
|
||||
set_field<closure_wrapper<&LuaAssFile::ObjectIPairs>>(L, "__ipairs");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// register misc functions
|
||||
// assume the "aegisub" global table exists
|
||||
lua_getglobal(L, "aegisub");
|
||||
|
||||
set_field(L, "parse_karaoke_data", closure_wrapper<&LuaAssFile::LuaParseKaraokeData>);
|
||||
set_field(L, "set_undo_point", closure_wrapper_v<&LuaAssFile::LuaSetUndoPoint, false>);
|
||||
set_field<closure_wrapper<&LuaAssFile::LuaParseKaraokeData>>(L, "parse_karaoke_data");
|
||||
set_field<closure_wrapper_v<&LuaAssFile::LuaSetUndoPoint, false>>(L, "set_undo_point");
|
||||
|
||||
lua_pop(L, 1); // pop "aegisub" table
|
||||
|
||||
|
|
|
@ -413,13 +413,13 @@ namespace Automation4 {
|
|||
|
||||
// assume top of stack now contains a dialog table
|
||||
if (!lua_istable(L, 1))
|
||||
luaL_error(L, "Cannot create config dialog from something non-table");
|
||||
error(L, "Cannot create config dialog from something non-table");
|
||||
|
||||
// Ok, so there is a table with controls
|
||||
lua_pushvalue(L, 1);
|
||||
lua_for_each(L, [&] {
|
||||
if (!lua_istable(L, -1))
|
||||
luaL_error(L, "bad control table entry");
|
||||
error(L, "bad control table entry");
|
||||
|
||||
std::string controlclass = get_field(L, "class");
|
||||
boost::to_lower(controlclass);
|
||||
|
@ -449,7 +449,7 @@ namespace Automation4 {
|
|||
// FIXME
|
||||
ctl = agi::make_unique<LuaControl::Edit>(L);
|
||||
else
|
||||
luaL_error(L, "bad control table entry");
|
||||
error(L, "bad control table entry");
|
||||
|
||||
controls.emplace_back(std::move(ctl));
|
||||
});
|
||||
|
@ -457,19 +457,19 @@ namespace Automation4 {
|
|||
if (include_buttons && lua_istable(L, 2)) {
|
||||
lua_pushvalue(L, 2);
|
||||
lua_for_each(L, [&]{
|
||||
buttons.emplace_back(-1, luaL_checkstring(L, -1));
|
||||
buttons.emplace_back(-1, check_string(L, -1));
|
||||
});
|
||||
}
|
||||
|
||||
if (include_buttons && lua_istable(L, 3)) {
|
||||
lua_pushvalue(L, 3);
|
||||
lua_for_each(L, [&]{
|
||||
int id = string_to_wx_id(luaL_checkstring(L, -2));
|
||||
std::string label = luaL_checkstring(L, -1);
|
||||
int id = string_to_wx_id(check_string(L, -2));
|
||||
std::string label = check_string(L, -1);
|
||||
auto btn = boost::find_if(buttons,
|
||||
[&](std::pair<int, std::string>& btn) { return btn.second == label; });
|
||||
if (btn == end(buttons))
|
||||
luaL_error(L, "Invalid button for id %s", lua_tostring(L, -2));
|
||||
error(L, "Invalid button for id %s", lua_tostring(L, -2));
|
||||
btn->first = id;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -38,11 +38,14 @@
|
|||
|
||||
#include <wx/filedlg.h>
|
||||
|
||||
using namespace agi::lua;
|
||||
|
||||
namespace {
|
||||
void set_field_to_closure(lua_State *L, const char *name, lua_CFunction fn, int ps_idx = -3)
|
||||
template<lua_CFunction fn>
|
||||
void set_field_to_closure(lua_State *L, const char *name, int ps_idx = -3)
|
||||
{
|
||||
lua_pushvalue(L, ps_idx);
|
||||
lua_pushcclosure(L, fn, 1);
|
||||
lua_pushcclosure(L, exception_wrapper<fn>, 1);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
|
@ -54,15 +57,15 @@ namespace {
|
|||
|
||||
wxString check_wxstring(lua_State *L, int idx)
|
||||
{
|
||||
return wxString::FromUTF8(luaL_checkstring(L, idx));
|
||||
return to_wx(check_string(L, idx));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Automation4 {
|
||||
LuaProgressSink::LuaProgressSink(lua_State *L, ProgressSink *ps, bool allow_config_dialog)
|
||||
: L(L)
|
||||
: L(L)
|
||||
{
|
||||
ProgressSink **ud = (ProgressSink**)lua_newuserdata(L, sizeof(ProgressSink*));
|
||||
auto ud = (ProgressSink**)lua_newuserdata(L, sizeof(ProgressSink*));
|
||||
*ud = ps;
|
||||
|
||||
// register progress reporting stuff
|
||||
|
@ -70,25 +73,25 @@ namespace Automation4 {
|
|||
|
||||
// Create aegisub.progress table
|
||||
lua_createtable(L, 0, 5);
|
||||
set_field_to_closure(L, "set", LuaSetProgress);
|
||||
set_field_to_closure(L, "task", LuaSetTask);
|
||||
set_field_to_closure(L, "title", LuaSetTitle);
|
||||
set_field_to_closure(L, "is_cancelled", LuaGetCancelled);
|
||||
set_field_to_closure<LuaSetProgress>(L, "set");
|
||||
set_field_to_closure<LuaSetTask>(L, "task");
|
||||
set_field_to_closure<LuaSetTitle>(L, "title");
|
||||
set_field_to_closure<LuaGetCancelled>(L, "is_cancelled");
|
||||
lua_setfield(L, -2, "progress");
|
||||
|
||||
// Create aegisub.debug table
|
||||
lua_createtable(L, 0, 4);
|
||||
set_field_to_closure(L, "out", LuaDebugOut);
|
||||
set_field_to_closure<LuaDebugOut>(L, "out");
|
||||
lua_setfield(L, -2, "debug");
|
||||
|
||||
// Set aegisub.log
|
||||
set_field_to_closure(L, "log", LuaDebugOut, -2);
|
||||
set_field_to_closure<LuaDebugOut>(L, "log", -2);
|
||||
|
||||
if (allow_config_dialog) {
|
||||
lua_createtable(L, 0, 3);
|
||||
set_field_to_closure(L, "display", LuaDisplayDialog);
|
||||
set_field_to_closure(L, "open", LuaDisplayOpenDialog);
|
||||
set_field_to_closure(L, "save", LuaDisplaySaveDialog);
|
||||
set_field_to_closure<LuaDisplayDialog>(L, "display");
|
||||
set_field_to_closure<LuaDisplayOpenDialog>(L, "open");
|
||||
set_field_to_closure<LuaDisplaySaveDialog>(L, "save");
|
||||
lua_setfield(L, -2, "dialog");
|
||||
}
|
||||
|
||||
|
@ -124,13 +127,13 @@ namespace Automation4 {
|
|||
|
||||
int LuaProgressSink::LuaSetTask(lua_State *L)
|
||||
{
|
||||
GetObjPointer(L, lua_upvalueindex(1))->SetMessage(luaL_checkstring(L, 1));
|
||||
GetObjPointer(L, lua_upvalueindex(1))->SetMessage(check_string(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaProgressSink::LuaSetTitle(lua_State *L)
|
||||
{
|
||||
GetObjPointer(L, lua_upvalueindex(1))->SetTitle(luaL_checkstring(L, 1));
|
||||
GetObjPointer(L, lua_upvalueindex(1))->SetTitle(check_string(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -170,12 +173,12 @@ namespace Automation4 {
|
|||
luaL_where(L, 1);
|
||||
lua_insert(L, 1);
|
||||
lua_concat(L, 2);
|
||||
lua_error(L);
|
||||
throw error_tag();
|
||||
}
|
||||
}
|
||||
|
||||
// Top of stack is now a string to output
|
||||
ps->Log(luaL_checkstring(L, 1));
|
||||
ps->Log(check_string(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
62
vendor/lua/Makefile
vendored
62
vendor/lua/Makefile
vendored
|
@ -2,39 +2,39 @@ include ../../Makefile.inc
|
|||
|
||||
LIB = liblua-aegisub.a
|
||||
|
||||
CXXFLAGS += -Wno-empty-body -Wno-deprecated-declarations -DLUA_USE_DLOPEN -DLUA_USE_POSIX
|
||||
CFLAGS += -Wno-empty-body -Wno-deprecated-declarations -Wno-unused-const-variable -DLUA_USE_POSIX
|
||||
|
||||
SRC = \
|
||||
src/lapi.cpp \
|
||||
src/lauxlib.cpp \
|
||||
src/lbaselib.cpp \
|
||||
src/lcode.cpp \
|
||||
src/ldblib.cpp \
|
||||
src/ldebug.cpp \
|
||||
src/ldo.cpp \
|
||||
src/ldump.cpp \
|
||||
src/lfunc.cpp \
|
||||
src/lgc.cpp \
|
||||
src/linit.cpp \
|
||||
src/liolib.cpp \
|
||||
src/llex.cpp \
|
||||
src/lmathlib.cpp \
|
||||
src/lmem.cpp \
|
||||
src/loadlib.cpp \
|
||||
src/lobject.cpp \
|
||||
src/lopcodes.cpp \
|
||||
src/loslib.cpp \
|
||||
src/lparser.cpp \
|
||||
src/lstate.cpp \
|
||||
src/lstring.cpp \
|
||||
src/lstrlib.cpp \
|
||||
src/ltable.cpp \
|
||||
src/ltablib.cpp \
|
||||
src/ltm.cpp \
|
||||
src/lundump.cpp \
|
||||
src/lvm.cpp \
|
||||
src/lzio.cpp \
|
||||
src/print.cpp
|
||||
src/lapi.c \
|
||||
src/lauxlib.c \
|
||||
src/lbaselib.c \
|
||||
src/lcode.c \
|
||||
src/ldblib.c \
|
||||
src/ldebug.c \
|
||||
src/ldo.c \
|
||||
src/ldump.c \
|
||||
src/lfunc.c \
|
||||
src/lgc.c \
|
||||
src/linit.c \
|
||||
src/liolib.c \
|
||||
src/llex.c \
|
||||
src/lmathlib.c \
|
||||
src/lmem.c \
|
||||
src/loadlib.c \
|
||||
src/lobject.c \
|
||||
src/lopcodes.c \
|
||||
src/loslib.c \
|
||||
src/lparser.c \
|
||||
src/lstate.c \
|
||||
src/lstring.c \
|
||||
src/lstrlib.c \
|
||||
src/ltable.c \
|
||||
src/ltablib.c \
|
||||
src/ltm.c \
|
||||
src/lundump.c \
|
||||
src/lvm.c \
|
||||
src/lzio.c \
|
||||
src/print.c
|
||||
|
||||
HEADER = src/*.h
|
||||
|
||||
|
|
10
vendor/lua/src/lua.hpp
vendored
Normal file
10
vendor/lua/src/lua.hpp
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
// lua.hpp
|
||||
// Lua header files for C++
|
||||
// <<extern "C">> not supplied automatically because Lua also compiles as C++
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
16
vendor/luabins/Makefile
vendored
16
vendor/luabins/Makefile
vendored
|
@ -2,16 +2,16 @@ include ../../Makefile.inc
|
|||
|
||||
LIB = libluabins.a
|
||||
|
||||
CXXFLAGS += -I../lua/src -DLUABINS_LUABUILTASCPP
|
||||
CPPFLAGS += -I../lua/src
|
||||
|
||||
SRC = \
|
||||
src/fwrite.cpp \
|
||||
src/load.cpp \
|
||||
src/luabins.cpp \
|
||||
src/luainternals.cpp \
|
||||
src/save.cpp \
|
||||
src/savebuffer.cpp \
|
||||
src/write.cpp
|
||||
src/fwrite.c \
|
||||
src/load.c \
|
||||
src/luabins.c \
|
||||
src/luainternals.c \
|
||||
src/save.c \
|
||||
src/savebuffer.c \
|
||||
src/write.c
|
||||
|
||||
HEADER = \
|
||||
src/fwrite.h \
|
||||
|
|
Loading…
Reference in a new issue