371 lines
9.0 KiB
OpenEdge ABL
371 lines
9.0 KiB
OpenEdge ABL
%module luadchpp
|
|
%include "lua_fnptr.i"
|
|
|
|
/*
|
|
in addition to the elements defined here and in adchpp.i, the Lua interface also includes:
|
|
- scriptPath: absolute path to the script directory (not necessarily the current dir).
|
|
- loaded(filename), unloaded(filename): functions called (if they exist in the global environment)
|
|
after a script has been loaded or unloaded.
|
|
- loading(filename), unloading(filename): functions called (if they exist in the global environment)
|
|
before a script is being loaded or unloaded. return true to discard further processing.
|
|
*/
|
|
|
|
%inline %{
|
|
/* Deleter for per-entity objects */
|
|
static void free_lua_ref(void* data) {
|
|
SWIGLUA_REF* ref = reinterpret_cast<SWIGLUA_REF*>(data);
|
|
swiglua_ref_clear(ref);
|
|
delete ref;
|
|
}
|
|
%}
|
|
|
|
typedef unsigned int size_t;
|
|
|
|
%{
|
|
static adchpp::Core *getCurrentCore(lua_State *l) {
|
|
lua_getglobal(l, "currentCore");
|
|
void *core = lua_touserdata(l, lua_gettop(l));
|
|
lua_pop(l, 1);
|
|
return reinterpret_cast<Core*>(core);
|
|
}
|
|
|
|
namespace adchpp {
|
|
const std::string &getConfigPath(lua_State *l);
|
|
}
|
|
%}
|
|
|
|
%wrapper %{
|
|
|
|
static int traceback (lua_State *L) {
|
|
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
|
|
if (!lua_istable(L, -1)) {
|
|
printf("No debug table\n");
|
|
lua_pop(L, 1);
|
|
return 1;
|
|
}
|
|
lua_getfield(L, -1, "traceback");
|
|
if (!lua_isfunction(L, -1)) {
|
|
printf("No traceback in debug\n");
|
|
lua_pop(L, 2);
|
|
return 1;
|
|
}
|
|
|
|
lua_pushvalue(L, 1); /* pass error message */
|
|
lua_pushinteger(L, 2); /* skip this function and traceback */
|
|
lua_call(L, 2, 1); /* call debug.traceback */
|
|
return 1;
|
|
}
|
|
|
|
class RegistryItem : private boost::noncopyable {
|
|
public:
|
|
RegistryItem(lua_State* L_) : L(L_), index(luaL_ref(L, LUA_REGISTRYINDEX)) {
|
|
}
|
|
~RegistryItem() {
|
|
luaL_unref(L, LUA_REGISTRYINDEX, index);
|
|
}
|
|
|
|
void push() { lua_rawgeti(L, LUA_REGISTRYINDEX, index); }
|
|
private:
|
|
lua_State* L;
|
|
int index;
|
|
};
|
|
|
|
class LuaFunction {
|
|
public:
|
|
LuaFunction(lua_State* L_) : L(L_), registryItem(new RegistryItem(L_)) { }
|
|
|
|
void operator()() {
|
|
pushFunction();
|
|
docall(0, 0);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
docall(1, 0);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c, const std::string& str) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
lua_pushstring(L, str.c_str());
|
|
|
|
docall(2, 0);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c, int i) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
lua_pushinteger(L, i);
|
|
|
|
docall(2, 0);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c, adchpp::AdcCommand& cmd) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
SWIG_NewPointerObj(L, &cmd, SWIGTYPE_p_adchpp__AdcCommand, 0);
|
|
|
|
docall(2, 0);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c, adchpp::AdcCommand& cmd, bool& i) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
SWIG_NewPointerObj(L, &cmd, SWIGTYPE_p_adchpp__AdcCommand, 0);
|
|
lua_pushboolean(L, i);
|
|
|
|
if(docall(3, 1) != 0) {
|
|
return;
|
|
}
|
|
|
|
if(lua_isboolean(L, -1)) {
|
|
i &= lua_toboolean(L, -1) == 1;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c, const adchpp::AdcCommand& cmd, bool& i) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
SWIG_NewPointerObj(L, &cmd, SWIGTYPE_p_adchpp__AdcCommand, 0);
|
|
lua_pushboolean(L, i);
|
|
|
|
if(docall(3, 1) != 0) {
|
|
return;
|
|
}
|
|
|
|
if(lua_isboolean(L, -1)) {
|
|
i &= lua_toboolean(L, -1) == 1;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
|
|
void operator()(const adchpp::SimpleXML& s) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &s, SWIGTYPE_p_adchpp__SimpleXML, 0);
|
|
docall(1, 0);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c, const adchpp::StringList& cmd, bool& i) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
SWIG_NewPointerObj(L, &cmd, SWIGTYPE_p_std__vectorT_std__string_t, 0);
|
|
lua_pushboolean(L, i);
|
|
|
|
if(docall(3, 1) != 0) {
|
|
return;
|
|
}
|
|
|
|
if(lua_isboolean(L, -1)) {
|
|
i &= lua_toboolean(L, -1) == 1;
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
|
|
void operator()(adchpp::Entity& c, DCReason reason, const std::string& info) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &c, SWIGTYPE_p_adchpp__Entity, 0);
|
|
lua_pushnumber(L, reason);
|
|
lua_pushstring(L, info.c_str());
|
|
|
|
if(docall(3, 0) != 0) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
void operator()(adchpp::Bot& bot, const adchpp::BufferPtr& buf) {
|
|
pushFunction();
|
|
|
|
SWIG_NewPointerObj(L, &bot, SWIGTYPE_p_adchpp__Bot, 0);
|
|
SWIG_NewPointerObj(L, &buf, SWIGTYPE_p_shared_ptrT_adchpp__Buffer_t, 0);
|
|
|
|
docall(2, 0);
|
|
}
|
|
|
|
private:
|
|
void pushFunction() {
|
|
registryItem->push();
|
|
}
|
|
|
|
int docall(int narg, int nret) {
|
|
int status;
|
|
int base = lua_gettop(L) - narg; /* function index */
|
|
lua_pushcfunction(L, traceback); /* push traceback function */
|
|
lua_insert(L, base); /* put it under chunk and args */
|
|
status = lua_pcall(L, narg, nret, base);
|
|
lua_remove(L, base); /* remove traceback function */
|
|
if(status == LUA_ERRRUN) {
|
|
if (!lua_isnil(L, -1)) {
|
|
const char *msg = lua_tostring(L, -1);
|
|
if (msg == NULL) msg = "(error object is not a string)";
|
|
fprintf(stderr, "%d, %d: %s\n", status, lua_type(L, -1), msg);
|
|
} else {
|
|
fprintf(stderr, "Lua error without error");
|
|
}
|
|
lua_pop(L, 1);
|
|
} else if(status == LUA_ERRMEM) {
|
|
fprintf(stderr, "Lua memory allocation error\n");
|
|
} else if(status == LUA_ERRERR) {
|
|
fprintf(stderr, "Lua error function error\n");
|
|
} else if(status != 0) {
|
|
fprintf(stderr, "Unknown lua status: %d\n", status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
lua_State* L;
|
|
shared_ptr<RegistryItem> registryItem;
|
|
};
|
|
|
|
static int exec(lua_State* L) {
|
|
void* p;
|
|
if(SWIG_IsOK(SWIG_ConvertPtr(L, lua_upvalueindex(1), &p, SWIGTYPE_p_std__functionT_void_fF_t, 0))) {
|
|
(*reinterpret_cast<std::function<void ()>*>(p))();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
%}
|
|
|
|
%typemap(in, checkfn="lua_isnumber") int64_t,uint64_t,const int64_t&, const uint64_t&,
|
|
// include unsigned in here to bypass the standard typemap for unsigned numbers that fails with HUB_SID
|
|
uint32_t, const uint32_t&
|
|
{
|
|
$1 = ($1_ltype)lua_tonumber(L,$input);
|
|
}
|
|
|
|
%typemap(out) int64_t,uint64_t,const int64_t&, const uint64_t& {
|
|
lua_pushnumber(L, (lua_Number)$1); SWIG_arg++;
|
|
}
|
|
|
|
%typemap(in) std::function<void () > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(out) std::function<void ()> {
|
|
SWIG_NewPointerObj(L, new std::function<void ()>($1), SWIGTYPE_p_std__functionT_void_fF_t, 1);
|
|
lua_pushcclosure(L, exec, 1);
|
|
SWIG_arg++;
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity &) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity &, adchpp::AdcCommand &) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity &, adchpp::AdcCommand &, bool&) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity &, const adchpp::AdcCommand &, bool&) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity &, int) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity &, const std::string&) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (const SimpleXML&) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity &, const adchpp::StringList&, bool&) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Entity&, DCReason, const std::string&) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%typemap(in) std::function<void (adchpp::Bot&, const adchpp::BufferPtr&) > {
|
|
$1 = LuaFunction(L);
|
|
}
|
|
|
|
%include "embed.i"
|
|
|
|
%extend adchpp::AdcCommand {
|
|
bool hasParam(const char* name, size_t start) {
|
|
std::string tmp;
|
|
return self->getParam(name, start, tmp);
|
|
}
|
|
|
|
std::string getParam(const char* name, size_t start) {
|
|
std::string tmp;
|
|
if(self->getParam(name, start, tmp)) {
|
|
return tmp;
|
|
}
|
|
return std::string();
|
|
}
|
|
}
|
|
|
|
%extend adchpp::Entity {
|
|
SWIGLUA_REF getPluginData(const PluginDataHandle& handle) {
|
|
void* ret = $self->getPluginData(handle);
|
|
if(ret) {
|
|
return *reinterpret_cast<SWIGLUA_REF*>(ret);
|
|
}
|
|
return {0, 0};
|
|
}
|
|
|
|
void setPluginData(const PluginDataHandle& handle, SWIGLUA_REF data) {
|
|
$self->setPluginData(handle, reinterpret_cast<void*>(new SWIGLUA_REF(data)));
|
|
}
|
|
|
|
void clearPluginData(const PluginDataHandle& handle) {
|
|
$self->clearPluginData(handle);
|
|
}
|
|
}
|
|
|
|
%extend adchpp::PluginManager {
|
|
PluginDataHandle registerPluginData() {
|
|
return self->registerPluginData(free_lua_ref);
|
|
}
|
|
}
|
|
|
|
%extend std::map<std::string, int> {
|
|
std::vector<std::string> keys() {
|
|
std::vector<std::string> ret;
|
|
|
|
for(std::map<std::string, int>::const_iterator i = $self->begin(), iend = $self->end(); i != iend; ++i) {
|
|
ret.push_back(i->first);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
%inline %{
|
|
|
|
namespace adchpp {
|
|
ClientManager* getCM(lua_State* l) { return &getCurrentCore(l)->getClientManager(); }
|
|
LogManager* getLM(lua_State* l) { return &getCurrentCore(l)->getLogManager(); }
|
|
PluginManager* getPM(lua_State* l) { return &getCurrentCore(l)->getPluginManager(); }
|
|
SocketManager* getSM(lua_State* l) { return &getCurrentCore(l)->getSocketManager(); }
|
|
|
|
const std::string &getConfigPath(lua_State *l) { return getCurrentCore(l)->getConfigPath(); }
|
|
}
|
|
|
|
%}
|
|
|
|
%extend adchpp::Util {
|
|
static const std::string &getCfgPath(lua_State *l) { return adchpp::getConfigPath(l); }
|
|
}
|