Skip to content

Commit

Permalink
WIP longjmp-free rlua
Browse files Browse the repository at this point in the history
Mostly what's left is wrapping a lot of existing callbacks, and a lot of cleanup
  • Loading branch information
kyren committed Feb 19, 2018
1 parent 0450c9b commit 0b76fbd
Show file tree
Hide file tree
Showing 11 changed files with 721 additions and 408 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ default = ["builtin-lua"]
# * LUA_INTEGER is long long
# * LUA_NUMBER as double
# * LUA_EXTRASPACE is sizeof(void*)
builtin-lua = ["gcc"]
# * LUAI_MAXSTACK is 1000000
builtin-lua = []

[dependencies]
libc = { version = "0.2" }
failure = { version = "0.1.1" }
compiletest_rs = { version = "0.3", optional = true }

[build-dependencies]
gcc = { version = "0.3.52", optional = true }
rustc_version = { version = "0.2" }
gcc = { version = "0.3.52" }

[dev-dependencies]
rustyline = "1.0.0"
46 changes: 26 additions & 20 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
#[cfg(feature = "builtin-lua")]
extern crate gcc;
extern crate rustc_version;

use std::env;

fn main() {
let target_os = env::var("CARGO_CFG_TARGET_OS");
let target_family = env::var("CARGO_CFG_TARGET_FAMILY");
if target_family == Ok("windows".to_string())
&& rustc_version::version().unwrap() == rustc_version::Version::parse("1.24.0").unwrap()
{

if target_family == Ok("windows".to_string()) {
// Error handling is completely broken on windows with
// https://github.com/rust-lang/rust/pull/46833 merged, and this includes stable rustc
// 1.24.0+. `#[unwind]` fixes error handling on windows, but requires nightly! This
Expand All @@ -22,23 +19,25 @@ fn main() {
println!("cargo:rustc-cfg=unwind");
}

#[cfg(feature = "builtin-lua")]
{
let mut config = gcc::Build::new();
let mut config = gcc::Build::new();

if target_os == Ok("linux".to_string()) {
config.define("LUA_USE_LINUX", None);
} else if target_os == Ok("macos".to_string()) {
config.define("LUA_USE_MACOSX", None);
} else if target_family == Ok("unix".to_string()) {
config.define("LUA_USE_POSIX", None);
} else if target_family == Ok("windows".to_string()) {
config.define("LUA_USE_WINDOWS", None);
}

if target_os == Ok("linux".to_string()) {
config.define("LUA_USE_LINUX", None);
} else if target_os == Ok("macos".to_string()) {
config.define("LUA_USE_MACOSX", None);
} else if target_family == Ok("unix".to_string()) {
config.define("LUA_USE_POSIX", None);
} else if target_family == Ok("windows".to_string()) {
config.define("LUA_USE_WINDOWS", None);
}
if cfg!(debug_assertions) {
config.define("LUA_USE_APICHECK", None);
}

if cfg!(debug_assertions) {
config.define("LUA_USE_APICHECK", None);
}
#[cfg(feature = "builtin-lua")]
{
let mut config = config.clone();

config
.include("lua")
Expand Down Expand Up @@ -77,4 +76,11 @@ fn main() {
.file("lua/lzio.c")
.compile("liblua5.3.a");
}

config
.include("lua")
.include("cbits")
.file("cbits/macros.c")
.file("cbits/safe.c")
.compile("librlua_cbits.a");
}
78 changes: 78 additions & 0 deletions cbits/macros.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "lua.h"
#include "lauxlib.h"

void (lua_pop)(lua_State* state, int n) {
lua_pop(state, n);
}

void (lua_newtable)(lua_State* state) {
lua_newtable(state);
}

void (lua_pushcfunction)(lua_State* state, lua_CFunction function) {
lua_pushcfunction(state, function);
}

lua_Number (lua_tonumber)(lua_State* state, int index) {
return lua_tonumber(state, index);
}

lua_Integer (lua_tointeger)(lua_State* state, int index) {
return lua_tointeger(state, index);
}

char const* (lua_tostring)(lua_State* state, int index) {
return lua_tostring(state, index);
}

int (lua_isfunction)(lua_State* state, int index) {
return lua_isfunction(state, index);
}

int (lua_istable)(lua_State* state, int index) {
return lua_istable(state, index);
}

int (lua_islightuserdata)(lua_State* state, int index) {
return lua_islightuserdata(state, index);
}

int (lua_isnil)(lua_State* state, int index) {
return lua_isnil(state, index);
}

int (lua_isboolean)(lua_State* state, int index) {
return lua_isboolean(state, index);
}

int (lua_isthread)(lua_State* state, int index) {
return lua_isthread(state, index);
}

int (lua_isnone)(lua_State* state, int index) {
return lua_isnone(state, index);
}

void (lua_insert)(lua_State* state, int index) {
lua_insert(state, index);
}

void (lua_remove)(lua_State* state, int index) {
lua_remove(state, index);
}

void (lua_call)(lua_State* state, int nargs, int nresults) {
lua_call(state, nargs, nresults);
}

int (lua_pcall)(lua_State* state, int nargs, int nresults, int msgh) {
return lua_pcall(state, nargs, nresults, msgh);
}

void (lua_replace)(lua_State* state, int index) {
lua_replace(state, index);
}

int (luaL_loadbuffer)(lua_State* state, char const* buf, size_t size, char const* name) {
return luaL_loadbufferx(state, buf, size, name, NULL);
}
225 changes: 225 additions & 0 deletions cbits/safe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
#include "lua.h"
#include "lauxlib.h"

static int s_newtable(lua_State* state) {
lua_newtable(state);
return 1;
}

int plua_newtable(lua_State* state) {
lua_pushcfunction(state, s_newtable);
return lua_pcall(state, 0, 1, 0);
}

static int s_len(lua_State* state) {
lua_pushinteger(state, luaL_len(state, -1));
return 1;
}

int pluaL_len(lua_State* state, int index, lua_Integer* len) {
index = lua_absindex(state, index);
lua_pushcfunction(state, s_len);
lua_pushvalue(state, index);
int r = lua_pcall(state, 1, 1, 0);
if (r == LUA_OK) {
*len = lua_tointeger(state, -1);
lua_pop(state, 1);
}
return r;
}

static int s_geti(lua_State* state) {
lua_gettable(state, -2);
return 1;
}

int plua_geti(lua_State* state, int index, lua_Integer i) {
index = lua_absindex(state, index);
lua_pushcfunction(state, s_geti);
lua_pushvalue(state, index);
lua_pushinteger(state, i);
return lua_pcall(state, 2, 1, 0);
}

static int s_gettable(lua_State* state) {
lua_gettable(state, -2);
return 1;
}

int plua_gettable(lua_State* state, int index) {
index = lua_absindex(state, index);
lua_pushcfunction(state, s_gettable);
lua_pushvalue(state, index);
lua_rotate(state, -3, -1);
return lua_pcall(state, 2, 1, 0);
}

static int s_newthread(lua_State* state) {
lua_newthread(state);
return 1;
}

int plua_newthread(lua_State* state, lua_State** thread) {
lua_pushcfunction(state, s_newthread);
int r = lua_pcall(state, 0, 1, 0);
if (r == LUA_OK) {
*thread = lua_tothread(state, -1);
}
return r;
}

static int s_newuserdata(lua_State* state) {
size_t size = lua_tointeger(state, -1);
lua_pop(state, 1);
lua_newuserdata(state, size);
return 1;
}

int plua_newuserdata(lua_State* state, size_t size, void** ud) {
lua_pushcfunction(state, s_newuserdata);
lua_pushinteger(state, size);
int r = lua_pcall(state, 1, 1, 0);
if (r == LUA_OK) {
*ud = lua_touserdata(state, -1);
}
return r;
}

static int s_next(lua_State* state) {
if (lua_next(state, -2) == 0) {
return 0;
} else {
return 2;
}
}

int plua_next(lua_State* state, int index, int* res) {
int top = lua_gettop(state) - 1;
index = lua_absindex(state, index);
lua_pushcfunction(state, s_next);
lua_pushvalue(state, index);
lua_rotate(state, -3, -1);
int r = lua_pcall(state, 2, LUA_MULTRET, 0);
if (r == LUA_OK) {
if (lua_gettop(state) - top == 2) {
*res = 1;
} else {
*res = 0;
}
}
return r;
}

static int s_pushcclosure(lua_State* state) {
lua_CFunction cf = lua_tocfunction(state, -1);
lua_pop(state, 1);
lua_pushcclosure(state, cf, lua_gettop(state));
return 1;
}

int plua_pushcclosure(lua_State* state, lua_CFunction function, int n) {
lua_pushcfunction(state, s_pushcclosure);
lua_insert(state, -(n + 1));
lua_pushcfunction(state, function);
return lua_pcall(state, n + 1, 1, 0);
}

static int s_pushlstring(lua_State* state) {
char const* s = lua_touserdata(state, -2);
size_t len = lua_tointeger(state, -1);
lua_pop(state, 2);
lua_pushlstring(state, s, len);
return 1;
}

int plua_pushlstring(lua_State* state, char const* s, size_t len) {
lua_pushcfunction(state, s_pushlstring);
lua_pushlightuserdata(state, (void*)s);
lua_pushinteger(state, len);
return lua_pcall(state, 2, 1, 0);
}

static int s_pushstring(lua_State* state) {
char const* s = lua_touserdata(state, -1);
lua_pop(state, 1);
lua_pushstring(state, s);
return 1;
}

int plua_pushstring(lua_State* state, char const* s) {
lua_pushcfunction(state, s_pushstring);
lua_pushlightuserdata(state, (void*)s);
return lua_pcall(state, 1, 1, 0);
}

static int s_rawset(lua_State* state) {
lua_rawset(state, -3);
return 0;
}

int plua_rawset(lua_State* state, int index) {
lua_pushvalue(state, index);
lua_insert(state, -3);
lua_pushcfunction(state, s_rawset);
lua_insert(state, -4);
return lua_pcall(state, 3, 0, 0);
}

static int s_settable(lua_State* state) {
lua_settable(state, -3);
return 0;
}

int plua_settable(lua_State* state, int index) {
lua_pushvalue(state, index);
lua_insert(state, -3);
lua_pushcfunction(state, s_settable);
lua_insert(state, -4);
return lua_pcall(state, 3, 0, 0);
}

static int s_tostring(lua_State* state) {
char const** s = lua_touserdata(state, -1);
*s = lua_tostring(state, -2);
lua_pop(state, 1);
return 1;
}

int plua_tostring(lua_State* state, int index, char const** s) {
index = lua_absindex(state, index);
lua_pushcfunction(state, s_tostring);
lua_pushvalue(state, index);
lua_pushlightuserdata(state, s);
int r = lua_pcall(state, 2, 1, 0);
if (r == LUA_OK) {
lua_replace(state, index);
}
return r;
}

typedef int (*RustCallback)(lua_State*);
// Out of stack space in callback
static int const RCALL_STACK_ERR = -2;
// Throw the error at the top of the stack
static int const RCALL_ERR = -3;

static int s_call_rust(lua_State* state) {
RustCallback callback = lua_touserdata(state, lua_upvalueindex(1));
int ret = callback(state);

if (ret == LUA_MULTRET) {
return LUA_MULTRET;
} else if (ret == RCALL_STACK_ERR) {
return luaL_error(state, "stack overflow in rust callback");
} else if (ret == RCALL_ERR) {
return lua_error(state);
} else {
return ret;
}
}

int plua_pushrclosure(lua_State* state, RustCallback function, int n) {
lua_pushlightuserdata(state, function);
lua_insert(state, -(n + 1));
return plua_pushcclosure(state, s_call_rust, n + 1);
}
Loading

0 comments on commit 0b76fbd

Please sign in to comment.