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", |