2013-11-03 20:16:23 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#include <lua.hpp>
|
2013-11-05 00:29:47 +00:00
|
|
|
#include <string>
|
2013-11-08 19:59:47 +00:00
|
|
|
#include "bindings/lua/util.h"
|
|
|
|
#include "bindings/lua/lua_exception.h"
|
2013-11-03 22:42:54 +00:00
|
|
|
|
2013-11-03 20:16:23 +00:00
|
|
|
namespace lean {
|
|
|
|
/**
|
|
|
|
\brief luaL_setfuncs replacement. The function luaL_setfuncs is only available in Lua 5.2.
|
|
|
|
*/
|
|
|
|
void setfuncs(lua_State * L, luaL_Reg const * l, int nup) {
|
|
|
|
luaL_checkstack(L, nup, "too many upvalues");
|
|
|
|
for (; l->name != NULL; l++) {
|
|
|
|
// fill the table with given functions
|
|
|
|
for (int i = 0; i < nup; i++) // copy upvalues to the top
|
|
|
|
lua_pushvalue(L, -nup);
|
|
|
|
lua_pushcclosure(L, l->func, nup); // closure with those upvalues
|
|
|
|
lua_setfield(L, -(nup + 2), l->name);
|
|
|
|
}
|
|
|
|
lua_pop(L, nup); // remove upvalues
|
|
|
|
}
|
2013-11-03 22:42:54 +00:00
|
|
|
|
2013-11-05 03:45:15 +00:00
|
|
|
/**
|
|
|
|
\brief luaL_testudata replacement.
|
|
|
|
*/
|
2013-11-05 19:35:09 +00:00
|
|
|
bool testudata(lua_State * L, int ud, char const * tname) {
|
|
|
|
void * p = lua_touserdata(L, ud);
|
|
|
|
if (p != nullptr) {
|
|
|
|
if (lua_getmetatable(L, ud)) {
|
|
|
|
luaL_getmetatable(L, tname);
|
|
|
|
if (!lua_rawequal(L, -1, -2))
|
|
|
|
p = nullptr;
|
|
|
|
lua_pop(L, 2);
|
|
|
|
return p;
|
|
|
|
}
|
2013-11-05 03:45:15 +00:00
|
|
|
}
|
2013-11-05 19:35:09 +00:00
|
|
|
return nullptr; // value is not a userdata with a metatable
|
2013-11-05 03:45:15 +00:00
|
|
|
}
|
|
|
|
|
2013-11-12 20:54:34 +00:00
|
|
|
int load(lua_State * L, lua_Reader reader, void * data, char const * source) {
|
|
|
|
#if LUA_VERSION_NUM < 502
|
|
|
|
return lua_load(L, reader, data, source);
|
|
|
|
#else
|
|
|
|
return lua_load(L, reader, data, source, nullptr);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-11-08 16:26:04 +00:00
|
|
|
size_t objlen(lua_State * L, int idx) {
|
2013-11-12 20:54:34 +00:00
|
|
|
#if LUA_VERSION_NUM < 502
|
2013-11-08 16:26:04 +00:00
|
|
|
return lua_objlen(L, idx);
|
|
|
|
#else
|
|
|
|
return lua_rawlen(L, idx);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-11-14 21:32:33 +00:00
|
|
|
int lessthan(lua_State * L, int idx1, int idx2) {
|
|
|
|
#if LUA_VERSION_NUM < 502
|
|
|
|
return lua_lessthan(L, idx1, idx2);
|
|
|
|
#else
|
|
|
|
return lua_compare(L, idx1, idx2, LUA_OPLT);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int equal(lua_State * L, int idx1, int idx2) {
|
|
|
|
#if LUA_VERSION_NUM < 502
|
|
|
|
return lua_equal(L, idx1, idx2);
|
|
|
|
#else
|
|
|
|
return lua_compare(L, idx1, idx2, LUA_OPEQ);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-11-08 19:59:47 +00:00
|
|
|
static void exec(lua_State * L) {
|
2013-11-14 00:30:59 +00:00
|
|
|
pcall(L, 0, LUA_MULTRET, 0);
|
2013-11-08 19:59:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dofile(lua_State * L, char const * fname) {
|
|
|
|
int result = luaL_loadfile(L, fname);
|
|
|
|
if (result)
|
|
|
|
throw lua_exception(lua_tostring(L, -1));
|
|
|
|
exec(L);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dostring(lua_State * L, char const * str) {
|
|
|
|
int result = luaL_loadstring(L, str);
|
|
|
|
if (result)
|
|
|
|
throw lua_exception(lua_tostring(L, -1));
|
|
|
|
exec(L);
|
|
|
|
}
|
|
|
|
|
2013-11-14 00:30:59 +00:00
|
|
|
void pcall(lua_State * L, int nargs, int nresults, int errorfun) {
|
|
|
|
int result = lua_pcall(L, nargs, nresults, errorfun);
|
|
|
|
if (result)
|
|
|
|
throw lua_exception(lua_tostring(L, -1));
|
|
|
|
}
|
|
|
|
|
2013-11-03 22:42:54 +00:00
|
|
|
int safe_function_wrapper(lua_State * L, lua_CFunction f){
|
|
|
|
static thread_local std::string _error_msg;
|
|
|
|
char const * error_msg;
|
|
|
|
try {
|
|
|
|
return f(L);
|
|
|
|
} catch (exception & e) {
|
|
|
|
_error_msg = e.what();
|
|
|
|
error_msg = _error_msg.c_str();
|
|
|
|
} catch (std::bad_alloc &) {
|
|
|
|
error_msg = "out of memory";
|
|
|
|
} catch (std::exception & e) {
|
|
|
|
_error_msg = e.what();
|
|
|
|
error_msg = _error_msg.c_str();
|
|
|
|
} catch(...) {
|
2013-11-05 02:12:53 +00:00
|
|
|
throw;
|
2013-11-03 22:42:54 +00:00
|
|
|
}
|
|
|
|
return luaL_error(L, error_msg);
|
|
|
|
}
|
2013-11-03 20:16:23 +00:00
|
|
|
}
|