summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Orlenko <zxteam@protonmail.com>2019-10-14 22:21:30 +0100
committerAlex Orlenko <zxteam@protonmail.com>2019-10-17 17:05:42 +0100
commitc4fd7a9faf35fb9435d0eea63fcb586c1b5da9fb (patch)
treeca48c33057b43a651d8b9baaa4de508f54492801 /src
parent676ffc0dfd93480e7f6b183163c20c7484011312 (diff)
downloadmlua-c4fd7a9faf35fb9435d0eea63fcb586c1b5da9fb.zip
Lua 5.1 support
Diffstat (limited to 'src')
-rw-r--r--src/error.rs2
-rw-r--r--src/ffi/compat53.rs668
-rw-r--r--src/ffi/glue/glue.c56
-rw-r--r--src/ffi/lauxlib.rs90
-rw-r--r--src/ffi/lua.rs183
-rw-r--r--src/ffi/luaconf.rs18
-rw-r--r--src/ffi/lualib.rs11
-rw-r--r--src/ffi/mod.rs95
-rw-r--r--src/lua.rs41
-rw-r--r--src/scope.rs15
-rw-r--r--src/userdata.rs11
-rw-r--r--src/util.rs20
12 files changed, 1082 insertions, 128 deletions
diff --git a/src/error.rs b/src/error.rs
index f670d1b..8431503 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -31,6 +31,7 @@ pub enum Error {
/// Lua garbage collector error, aka `LUA_ERRGCMM`.
///
/// The Lua VM returns this error when there is an error running a `__gc` metamethod.
+ #[cfg(feature = "lua53")]
GarbageCollectorError(StdString),
/// A mutable callback has triggered Lua code that has called the same mutable callback again.
///
@@ -137,6 +138,7 @@ impl fmt::Display for Error {
Error::MemoryError(ref msg) => {
write!(fmt, "memory error: {}", msg)
}
+ #[cfg(feature = "lua53")]
Error::GarbageCollectorError(ref msg) => {
write!(fmt, "garbage collector error: {}", msg)
}
diff --git a/src/ffi/compat53.rs b/src/ffi/compat53.rs
new file mode 100644
index 0000000..2b58ebc
--- /dev/null
+++ b/src/ffi/compat53.rs
@@ -0,0 +1,668 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2019 A. Orlenko
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+// Based on github.com/keplerproject/lua-compat-5.3
+
+use std::mem;
+use std::os::raw::{c_char, c_int, c_void};
+use std::ptr;
+
+use super::lauxlib::{
+ luaL_Reg, luaL_callmeta, luaL_checkstack, luaL_checktype, luaL_error, luaL_getmetafield_51,
+ luaL_getmetatable, luaL_loadbuffer, luaL_newmetatable_51,
+};
+
+use super::lua::{
+ self, lua_CFunction, lua_Debug, lua_Integer, lua_Number, lua_State, lua_call, lua_concat,
+ lua_createtable, lua_equal, lua_error, lua_getfenv, lua_getfield_51, lua_getinfo,
+ lua_getmetatable, lua_getstack, lua_gettable_51, lua_gettop, lua_insert, lua_isnumber,
+ lua_isstring, lua_istable, lua_lessthan, lua_newtable, lua_newuserdata, lua_next, lua_objlen,
+ lua_pop, lua_pushboolean, lua_pushcclosure, lua_pushcfunction, lua_pushfstring,
+ lua_pushinteger, lua_pushlightuserdata, lua_pushliteral, lua_pushlstring_51, lua_pushnil,
+ lua_pushnumber, lua_pushstring_51, lua_pushthread, lua_pushvalue, lua_rawequal, lua_rawget_51,
+ lua_rawgeti_51, lua_rawset, lua_remove, lua_replace, lua_resume_51, lua_setfenv, lua_setfield,
+ lua_setglobal, lua_setmetatable, lua_settable, lua_settop, lua_toboolean, lua_tointeger,
+ lua_tolstring, lua_tonumber, lua_topointer, lua_tostring, lua_touserdata, lua_type,
+ lua_typename,
+};
+
+unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) {
+ while a < b {
+ lua_pushvalue(L, a);
+ lua_pushvalue(L, b);
+ lua_replace(L, a);
+ lua_replace(L, b);
+ a += 1;
+ b -= 1;
+ }
+}
+
+const COMPAT53_LEVELS1: c_int = 12; // size of the first part of the stack
+const COMPAT53_LEVELS2: c_int = 10; // size of the second part of the stack
+
+unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int {
+ let mut ar: lua_Debug = mem::zeroed();
+ let (mut li, mut le) = (1, 1);
+ // find an upper bound
+ while lua_getstack(L, le, &mut ar) != 0 {
+ li = le;
+ le *= 2;
+ }
+ // do a binary search
+ while li < le {
+ let m = (li + le) / 2;
+ if lua_getstack(L, m, &mut ar) != 0 {
+ li = m + 1
+ } else {
+ le = m;
+ }
+ }
+ le - 1
+}
+
+unsafe fn compat53_checkmode(
+ L: *mut lua_State,
+ mode: *const c_char,
+ modename: *const c_char,
+ err: c_int,
+) -> c_int {
+ unsafe fn strchr(s: *const c_char, c: c_char) -> *const c_char {
+ let mut st = s;
+ while *st != 0 && *st != c {
+ st = st.offset(1);
+ }
+ if *st == c {
+ st
+ } else {
+ ptr::null()
+ }
+ }
+
+ if mode != ptr::null() && strchr(mode, *modename) == ptr::null() {
+ lua_pushfstring(
+ L,
+ cstr!("attempt to load a %s chunk (mode is '%s')"),
+ modename,
+ mode,
+ );
+ return err;
+ }
+ lua::LUA_OK
+}
+
+unsafe fn compat53_findfield(L: *mut lua_State, objidx: c_int, level: c_int) -> c_int {
+ if level == 0 || lua_istable(L, -1) == 0 {
+ return 0; // not found
+ }
+
+ lua_pushnil(L); // start 'next' loop
+ while lua_next(L, -2) != 0 {
+ // for each pair in table
+ if lua_type(L, -2) == lua::LUA_TSTRING {
+ // ignore non-string keys
+ if lua_rawequal(L, objidx, -1) != 0 {
+ // found object?
+ lua_pop(L, 1); // remove value (but keep name)
+ return 1;
+ } else if compat53_findfield(L, objidx, level - 1) != 0 {
+ // try recursively
+ lua_remove(L, -2); // remove table (but keep name)
+ lua_pushliteral(L, ".");
+ lua_insert(L, -2); // place '.' between the two names
+ lua_concat(L, 3);
+ return 1;
+ }
+ }
+ lua_pop(L, 1); // remove value
+ }
+ return 0; // not found
+}
+
+unsafe fn compat53_pushglobalfuncname(L: *mut lua_State, ar: *mut lua_Debug) -> c_int {
+ let top = lua_gettop(L);
+ lua_getinfo(L, cstr!("f"), ar); // push function
+ lua_pushvalue(L, lua::LUA_GLOBALSINDEX);
+ if compat53_findfield(L, top + 1, 2) != 0 {
+ lua_copy(L, -1, top + 1); // move name to proper place
+ lua_pop(L, 2); // remove pushed values
+ return 1;
+ } else {
+ lua_settop(L, top); // remove function and global table
+ return 0;
+ }
+}
+
+unsafe fn compat53_pushfuncname(L: *mut lua_State, ar: *mut lua_Debug) {
+ if *(*ar).namewhat != b'\0' as c_char {
+ // is there a name?
+ lua_pushfstring(L, cstr!("function '%s'"), (*ar).name);
+ } else if *(*ar).what == b'm' as c_char {
+ // main?
+ lua_pushliteral(L, "main chunk");
+ } else if *(*ar).what == b'C' as c_char {
+ if compat53_pushglobalfuncname(L, ar) != 0 {
+ lua_pushfstring(L, cstr!("function '%s'"), lua_tostring(L, -1));
+ lua_remove(L, -2); // remove name
+ } else {
+ lua_pushliteral(L, "?");
+ }
+ } else {
+ lua_pushfstring(
+ L,
+ cstr!("function <%s:%d>"),
+ (*ar).short_src.as_ptr(),
+ (*ar).linedefined,
+ );
+ }
+}
+
+unsafe fn compat53_call_lua(L: *mut lua_State, code: &str, nargs: c_int, nret: c_int) {
+ lua_rawgetp(L, lua::LUA_REGISTRYINDEX, code.as_ptr() as *const c_void);
+ if lua_type(L, -1) != lua::LUA_TFUNCTION {
+ lua_pop(L, 1);
+ if luaL_loadbuffer(
+ L,
+ code.as_ptr() as *const c_char,
+ code.as_bytes().len(),
+ cstr!("=none"),
+ ) != 0
+ {
+ lua_error(L);
+ }
+ lua_pushvalue(L, -1);
+ lua_rawsetp(L, lua::LUA_REGISTRYINDEX, code.as_ptr() as *const c_void);
+ }
+ lua_insert(L, -nargs - 1);
+ lua_call(L, nargs, nret);
+}
+
+//
+// lua ported functions
+//
+
+#[inline(always)]
+pub fn lua_upvalueindex(i: c_int) -> c_int {
+ lua::LUA_GLOBALSINDEX - i
+}
+
+pub unsafe fn lua_absindex(L: *mut lua_State, mut idx: c_int) -> c_int {
+ if idx < 0 && idx > lua::LUA_REGISTRYINDEX {
+ idx += lua_gettop(L) + 1;
+ }
+ idx
+}
+
+pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) {
+ idx = lua_absindex(L, idx);
+ let n_elems = lua_gettop(L) - idx + 1;
+ if n < 0 {
+ n += n_elems;
+ }
+ if n > 0 && n < n_elems {
+ luaL_checkstack(L, 2, cstr!("not enough stack slots available"));
+ n = n_elems - n;
+ compat53_reverse(L, idx, idx + n - 1);
+ compat53_reverse(L, idx + n, idx + n_elems - 1);
+ compat53_reverse(L, idx, idx + n_elems - 1);
+ }
+}
+
+pub unsafe fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int) {
+ let abs_to = lua_absindex(L, toidx);
+ luaL_checkstack(L, 1, cstr!("not enough stack slots"));
+ lua_pushvalue(L, fromidx);
+ lua_replace(L, abs_to);
+}
+
+pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int {
+ if lua_type(L, idx) == lua::LUA_TNUMBER {
+ let n = lua_tonumber(L, idx);
+ let i = lua_tointeger(L, idx);
+ if i as f64 == n {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+pub unsafe fn lua_tonumberx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Number {
+ let n = lua_tonumber(L, i);
+ if isnum != ptr::null_mut() {
+ *isnum = if n != 0.0 || lua_isnumber(L, i) != 0 {
+ 1
+ } else {
+ 0
+ };
+ }
+ return n;
+}
+
+pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer {
+ let mut ok = 0;
+ let n = lua_tonumberx(L, i, &mut ok);
+ if ok != 0 {
+ if n == n as lua_Integer as lua_Number {
+ if isnum != ptr::null_mut() {
+ *isnum = 1;
+ }
+ return n as lua_Integer;
+ }
+ }
+ if isnum != ptr::null_mut() {
+ *isnum = 0;
+ }
+ return 0;
+}
+
+pub unsafe fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize {
+ lua_objlen(L, idx)
+}
+
+pub unsafe fn lua_compare(L: *mut lua_State, mut idx1: c_int, mut idx2: c_int, op: c_int) -> c_int {
+ match op {
+ lua::LUA_OPEQ => lua_equal(L, idx1, idx2),
+ lua::LUA_OPLT => lua_lessthan(L, idx1, idx2),
+ lua::LUA_OPLE => {
+ luaL_checkstack(L, 5, cstr!("not enough stack slots"));
+ idx1 = lua_absindex(L, idx1);
+ idx2 = lua_absindex(L, idx2);
+ lua_pushvalue(L, idx1);
+ lua_pushvalue(L, idx2);
+ compat53_call_lua(L, "local a,b=...\nreturn a<=b\n", 2, 1);
+ let result = lua_toboolean(L, -1);
+ lua_pop(L, 1);
+ result
+ }
+ _ => luaL_error(L, cstr!("invalid 'op' argument for lua_compare")),
+ }
+}
+
+pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char {
+ if l == 0 {
+ lua_pushlstring_51(L, cstr!(""), 0);
+ } else {
+ lua_pushlstring_51(L, s, l);
+ }
+ lua_tostring(L, -1)
+}
+
+pub unsafe fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char {
+ lua_pushstring_51(L, s);
+ lua_tostring(L, -1)
+}
+
+pub unsafe fn lua_gettable(L: *mut lua_State, idx: c_int) -> c_int {
+ lua_gettable_51(L, idx);
+ lua_type(L, -1)
+}
+
+pub unsafe fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int {
+ lua_getfield_51(L, idx, k);
+ lua_type(L, -1)
+}
+
+pub unsafe fn lua_geti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) -> c_int {
+ idx = lua_absindex(L, idx);
+ lua_pushinteger(L, n);
+ lua_gettable(L, idx);
+ lua_type(L, -1)
+}
+
+// A new version which returns c_int
+pub unsafe fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int {
+ lua_rawget_51(L, idx);
+ lua_type(L, -1)
+}
+
+// A new version which returns c_int
+pub unsafe fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int {
+ lua_rawgeti_51(L, idx, n);
+ lua_type(L, -1)
+}
+
+pub unsafe fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int {
+ let abs_i = lua_absindex(L, idx);
+ lua_pushlightuserdata(L, p as *mut c_void);
+ lua_rawget(L, abs_i);
+ lua_type(L, -1)
+}
+
+pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int {
+ lua_getfenv(L, idx);
+ lua_type(L, -1)
+}
+
+pub unsafe fn lua_seti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) {
+ luaL_checkstack(L, 1, cstr!("not enough stack slots available"));
+ idx = lua_absindex(L, idx);
+ lua_pushinteger(L, n);
+ lua_insert(L, -2);
+ lua_settable(L, idx);
+}
+
+pub unsafe fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void) {
+ let abs_i = lua_absindex(L, idx);
+ luaL_checkstack(L, 1, cstr!("not enough stack slots"));
+ lua_pushlightuserdata(L, p as *mut c_void);
+ lua_insert(L, -2);
+ lua_rawset(L, abs_i);
+}
+
+pub unsafe fn lua_setuservalue(L: *mut lua_State, idx: c_int) {
+ luaL_checktype(L, -1, lua::LUA_TTABLE);
+ lua_setfenv(L, idx);
+}
+
+pub unsafe fn lua_resume(L: *mut lua_State, _from: *mut lua_State, narg: c_int) -> c_int {
+ lua_resume_51(L, narg)
+}
+
+pub unsafe fn lua_len(L: *mut lua_State, idx: c_int) {
+ match lua_type(L, idx) {
+ lua::LUA_TSTRING => {
+ lua_pushnumber(L, lua_objlen(L, idx) as lua_Number);
+ }
+ lua::LUA_TTABLE => {
+ if luaL_callmeta(L, idx, cstr!("__len")) == 0 {
+ lua_pushnumber(L, lua_objlen(L, idx) as lua_Number);
+ }
+ }
+ lua::LUA_TUSERDATA if luaL_callmeta(L, idx, cstr!("__len")) != 0 => {}
+ _ => {
+ luaL_error(
+ L,
+ cstr!("attempt to get length of a %s value"),
+ lua_typename(L, lua_type(L, idx)),
+ );
+ }
+ }
+}
+
+// TODO: lua_stringtonumber
+
+pub unsafe fn lua_getextraspace(L: *mut lua_State) -> *mut c_void {
+ use super::glue::LUA_EXTRASPACE;
+
+ luaL_checkstack(L, 4, cstr!("not enough stack slots available"));
+ lua_pushliteral(L, "__compat53_extraspace");
+ lua_pushvalue(L, -1);
+ lua_rawget(L, lua::LUA_REGISTRYINDEX);
+ if lua_istable(L, -1) == 0 {
+ lua_pop(L, 1);
+ lua_createtable(L, 0, 2);
+ lua_createtable(L, 0, 1);
+ lua_pushliteral(L, "k");
+ lua_setfield(L, -2, cstr!("__mode"));
+ lua_setmetatable(L, -2);
+ lua_pushvalue(L, -2);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, lua::LUA_REGISTRYINDEX);
+ }
+ lua_replace(L, -2);
+ let is_main = lua_pushthread(L);
+ lua_rawget(L, -2);
+ let mut _ptr = lua_touserdata(L, -1);
+ if _ptr == ptr::null_mut() {
+ lua_pop(L, 1);
+ _ptr = lua_newuserdata(L, LUA_EXTRASPACE as usize);
+ if is_main != 0 {
+ // mem::size_of::<c_void>() == 1
+ ptr::write_bytes(_ptr, 0, LUA_EXTRASPACE as usize);
+ lua_pushthread(L);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, -4);
+ lua_pushboolean(L, 1);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, -4);
+ } else {
+ lua_pushboolean(L, 1);
+ lua_rawget(L, -3);
+ let mptr = lua_touserdata(L, -1);
+ if mptr != ptr::null_mut() {
+ ptr::copy_nonoverlapping(mptr, _ptr, LUA_EXTRASPACE as usize)
+ } else {
+ ptr::write_bytes(_ptr, 0, LUA_EXTRASPACE as usize);
+ }
+ lua_pop(L, 1);
+ lua_pushthread(L);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, -4);
+ }
+ }
+ lua_pop(L, 2);
+ return _ptr;
+}
+
+#[inline(always)]
+pub unsafe fn lua_pushglobaltable(L: *mut lua_State) {
+ lua_pushvalue(L, lua::LUA_GLOBALSINDEX);
+}
+
+//
+// lauxlib ported functions
+//
+
+pub unsafe fn luaL_checkversion(_L: *mut lua_State) {
+ // Void
+}
+
+pub unsafe fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int {
+ if luaL_getmetafield_51(L, obj, e) != 0 {
+ lua_type(L, -1)
+ } else {
+ lua::LUA_TNIL
+ }
+}
+
+pub unsafe fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int {
+ if luaL_newmetatable_51(L, tname) != 0 {
+ lua_pushstring(L, tname);
+ lua_setfield(L, -2, cstr!("__name"));
+ 1
+ } else {
+ 0
+ }
+}
+
+pub unsafe fn luaL_loadbufferx(
+ L: *mut lua_State,
+ buff: *const c_char,
+ sz: usize,
+ name: *const c_char,
+ mode: *const c_char,
+) -> c_int {
+ let status = if sz > 0 && *buff as u8 == lua::LUA_SIGNATURE[0] {
+ compat53_checkmode(L, mode, cstr!("binary"), lua::LUA_ERRSYNTAX)
+ } else {
+ compat53_checkmode(L, mode, cstr!("text"), lua::LUA_ERRSYNTAX)
+ };
+ if status != lua::LUA_OK {
+ return status;
+ }
+ luaL_loadbuffer(L, buff, sz, name)
+}
+
+pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer {
+ let mut isnum = 0;
+ luaL_checkstack(L, 1, cstr!("not enough stack slots"));
+ lua_len(L, idx);
+ let res = lua_tointegerx(L, -1, &mut isnum);
+ lua::lua_pop(L, 1);
+ if isnum == 0 {
+ luaL_error(L, cstr!("object length is not an integer"));
+ }
+ res
+}
+
+pub unsafe fn luaL_traceback(
+ L: *mut lua_State,
+ L1: *mut lua_State,
+ msg: *const c_char,
+ mut level: c_int,
+) {
+ let mut ar: lua_Debug = std::mem::zeroed();
+ let top = lua_gettop(L);
+ let numlevels = compat53_countlevels(L1);
+ let mark = if numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2 {
+ COMPAT53_LEVELS1
+ } else {
+ 0
+ };
+
+ if msg != ptr::null() {
+ lua_pushfstring(L, cstr!("%s\n"), msg);
+ }
+ lua_pushliteral(L, "stack traceback:");
+ while lua_getstack(L1, level, &mut ar) != 0 {
+ level += 1;
+ if level == mark {
+ // too many levels?
+ lua_pushliteral(L, "\n\t..."); // add a '...'
+ level = numlevels - COMPAT53_LEVELS2; // and skip to last ones
+ } else {
+ lua_getinfo(L1, cstr!("Slnt"), &mut ar);
+ lua_pushfstring(L, cstr!("\n\t%s:"), cstr!("ok") /*ar.short_src*/);
+ if ar.currentline > 0 {
+ lua_pushfstring(L, cstr!("%d:"), ar.currentline);
+ }
+ lua_pushliteral(L, " in ");
+ compat53_pushfuncname(L, &mut ar);
+ lua_concat(L, lua_gettop(L) - top);
+ }
+ }
+ lua_concat(L, lua_gettop(L) - top);
+}
+
+pub unsafe fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char {
+ if luaL_callmeta(L, idx, cstr!("__tostring")) == 0 {
+ let t = lua_type(L, idx);
+ match t {
+ lua::LUA_TNIL => {
+ lua_pushliteral(L, "nil");
+ }
+ lua::LUA_TSTRING | lua::LUA_TNUMBER => {
+ lua_pushvalue(L, idx);
+ }
+ lua::LUA_TBOOLEAN => {
+ if lua_toboolean(L, idx) == 0 {
+ lua_pushliteral(L, "false");
+ } else {
+ lua_pushliteral(L, "true");
+ }
+ }
+ _ => {
+ let tt = luaL_getmetafield(L, idx, cstr!("__name"));
+ let name = if tt == lua::LUA_TSTRING {
+ lua_tostring(L, -1)
+ } else {
+ lua_typename(L, t)
+ };
+ lua_pushfstring(L, cstr!("%s: %p"), name, lua_topointer(L, idx));
+ if tt != lua::LUA_TNIL {
+ lua_replace(L, -2);
+ }
+ }
+ };
+ } else {
+ if lua_isstring(L, -1) == 0 {
+ luaL_error(L, cstr!("'__tostring' must return a string"));
+ }
+ }
+ lua_tolstring(L, -1, len)
+}
+
+pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) {
+ luaL_checkstack(L, 1, cstr!("not enough stack slots"));
+ luaL_getmetatable(L, tname);
+ lua_setmetatable(L, -2);
+}
+
+pub unsafe fn luaL_testudata(L: *mut lua_State, i: c_int, tname: *const c_char) -> *mut c_void {
+ let mut p = lua_touserdata(L, i);
+ luaL_checkstack(L, 2, cstr!("not enough stack slots"));
+ if p == ptr::null_mut() || lua_getmetatable(L, i) == 0 {
+ return ptr::null_mut();
+ } else {
+ luaL_getmetatable(L, tname);
+ let res = lua_rawequal(L, -1, -2);
+ lua_pop(L, 2);
+ if res == 0 {
+ p = ptr::null_mut();
+ }
+ }
+ return p;
+}
+
+pub unsafe fn luaL_setfuncs(L: *mut lua_State, mut l: *const luaL_Reg, nup: c_int) {
+ luaL_checkstack(L, nup + 1, cstr!("too many upvalues"));
+ while (*l).name != ptr::null() {
+ // fill the table with given functions
+ l = l.offset(1);
+ lua_pushstring(L, (*l).name);
+ for _ in 0..nup {
+ // copy upvalues to the top
+ lua_pushvalue(L, -(nup + 1));
+ }
+ lua_pushcclosure(L, (*l).func, nup); // closure with those upvalues
+ lua_settable(L, -(nup + 3)); // table must be below the upvalues, the name and the closure
+ }
+ lua_pop(L, nup); // remove upvalues
+}
+
+pub unsafe fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int {
+ let abs_i = lua_absindex(L, idx);
+ luaL_checkstack(L, 3, cstr!("not enough stack slots"));
+ lua_pushstring(L, fname);
+ lua_gettable(L, abs_i);
+ if lua_istable(L, -1) != 0 {
+ return 1;
+ }
+ lua_pop(L, 1);
+ lua_newtable(L);
+ lua_pushstring(L, fname);
+ lua_pushvalue(L, -2);
+ lua_settable(L, abs_i);
+ return 0;
+}
+
+pub unsafe fn luaL_requiref(
+ L: *mut lua_State,
+ modname: *const c_char,
+ openf: lua_CFunction,
+ glb: c_int,
+) {
+ luaL_checkstack(L, 3, cstr!("not enough stack slots available"));
+ luaL_getsubtable(L, lua::LUA_REGISTRYINDEX, cstr!("_LOADED"));
+ if lua_getfield(L, -1, modname) == lua::LUA_TNIL {
+ lua_pop(L, 1);
+ lua_pushcfunction(L, openf);
+ lua_pushstring(L, modname);
+ lua_call(L, 1, 1);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -3, modname);
+ }
+ if glb != 0 {
+ lua_pushvalue(L, -1);
+ lua_setglobal(L, modname);
+ }
+ lua_replace(L, -2);
+}
diff --git a/src/ffi/glue/glue.c b/src/ffi/glue/glue.c
index 65249d6..d50bbd9 100644
--- a/src/ffi/glue/glue.c
+++ b/src/ffi/glue/glue.c
@@ -1,5 +1,6 @@
// The MIT License (MIT)
//
+// Copyright (c) 2019 A. Orlenko
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,6 +30,10 @@
#include <lua.h>
#include <lualib.h>
+#ifndef LUA_EXTRASPACE
+#define LUA_EXTRASPACE (sizeof(void*))
+#endif
+
// Macros taken from https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
#define xstr(s) str(s)
#define str(s) #s
@@ -43,23 +48,30 @@ typedef struct rs_item {
};
} rs_item;
-#define TY_INT 0
-#define TY_LUAINT 1
-#define TY_STR 2
-#define TY_TYPE 3
-#define TY_COMMENT 4
-#define TY_RAW 5
+#define TY_INT 0
#define RS_INT(name, val) \
{ TY_INT, name, .int_val = val }
+
+#if LUA_VERSION_NUM == 503
+#define TY_LUAINT 1
#define RS_LUAINT(name, val) \
{ TY_LUAINT, name, .lua_int_val = val }
+#endif
+
+#define TY_STR 2
#define RS_STR(name, val) \
{ TY_STR, name, .str_val = val }
+
+#define TY_TYPE 3
#define RS_TYPE(name, val) \
{ TY_TYPE, name, .str_val = val }
+
+#define TY_COMMENT 4
#define RS_COMMENT(val) \
{ TY_COMMENT, NULL, .str_val = val }
+
+#define TY_RAW 5
#define RS_RAW(val) \
{ TY_RAW, NULL, .str_val = val }
@@ -102,7 +114,7 @@ size_t escape(const char *in, char *out, size_t szout) {
size_t written = 0;
char cur;
- while (cur = *in++) {
+ while ((cur = *in++)) {
switch (cur) {
case '\\':
if (!try_write(&out, cur, 2, &written, szout))
@@ -127,10 +139,12 @@ int write_int_item(FILE *f, const char *name, int value) {
return fprintf(f, "pub const %s: c_int = %d;\n", name, value);
}
+#if LUA_VERSION_NUM == 503
int write_lua_int_item(FILE *f, const char *name, LUA_INTEGER value) {
return fprintf(f, "pub const %s: LUA_INTEGER = " LUA_INTEGER_FMT ";\n", name,
value);
}
+#endif
int write_str_item(FILE *f, const char *name, const char *value) {
size_t len = strlen(value);
@@ -157,8 +171,10 @@ int write_item(FILE *f, const rs_item *c) {
switch (c->type) {
case TY_INT:
return write_int_item(f, c->name, c->int_val);
+#if LUA_VERSION_NUM == 503
case TY_LUAINT:
return write_lua_int_item(f, c->name, c->lua_int_val);
+#endif
case TY_STR:
return write_str_item(f, c->name, c->str_val);
case TY_TYPE:
@@ -205,43 +221,37 @@ int main(int argc, const char **argv) {
// == luaconf.h ==========================================================
RS_COMMENT("luaconf.h"),
- RS_STR("LUA_VDIR", LUA_VDIR),
RS_STR("LUA_PATH_DEFAULT", LUA_PATH_DEFAULT),
RS_STR("LUA_CPATH_DEFAULT", LUA_CPATH_DEFAULT),
RS_STR("LUA_DIRSEP", LUA_DIRSEP),
RS_INT("LUA_EXTRASPACE", LUA_EXTRASPACE),
RS_INT("LUA_IDSIZE", LUA_IDSIZE),
- // RS_INT("LUAI_MAXSHORTLEN", LUAI_MAXSHORTLEN),
- // RS_TYPE("LUA_KCONTEXT", xstr(LUA_KCONTEXT)),
- RS_INT("LUAI_BITSINT", LUAI_BITSINT),
- // LUA_INT32? LUAI_UMEM? LUAI_MEM?
- RS_INT("LUAI_MAXSTACK", LUAI_MAXSTACK),
RS_INT("LUAL_BUFFERSIZE", LUAL_BUFFERSIZE),
RS_TYPE("LUA_NUMBER",
sizeof(LUA_NUMBER) > sizeof(float) ? "c_double" : "c_float"),
- RS_TYPE("LUA_UNSIGNED", rs_uint_type(sizeof(LUA_UNSIGNED))),
RS_TYPE("LUA_INTEGER", rs_int_type(sizeof(LUA_INTEGER))),
- RS_LUAINT("LUA_MAXINTEGER", LUA_MAXINTEGER),
- RS_LUAINT("LUA_MININTEGER", LUA_MININTEGER),
+#if LUA_VERSION_NUM == 503
+ RS_TYPE("LUA_UNSIGNED", rs_uint_type(sizeof(LUA_UNSIGNED))),
+#endif
// == lua.h ==============================================================
RS_COMMENT("lua.h"),
- RS_STR("LUA_VERSION_MAJOR", LUA_VERSION_MAJOR),
- RS_STR("LUA_VERSION_MINOR", LUA_VERSION_MINOR),
RS_INT("LUA_VERSION_NUM", LUA_VERSION_NUM),
- RS_STR("LUA_VERSION_RELEASE", LUA_VERSION_RELEASE),
RS_STR("LUA_VERSION", LUA_VERSION),
RS_STR("LUA_RELEASE", LUA_RELEASE),
- RS_STR("LUA_COPYRIGHT", LUA_COPYRIGHT),
- RS_STR("LUA_AUTHORS", LUA_AUTHORS),
RS_INT("LUA_REGISTRYINDEX", LUA_REGISTRYINDEX),
+#if LUA_VERSION_NUM == 501
+ RS_INT("LUA_ENVIRONINDEX", LUA_ENVIRONINDEX),
+ RS_INT("LUA_GLOBALSINDEX", LUA_GLOBALSINDEX),
+#endif
// == lauxlib.h ==========================================================
RS_COMMENT("lauxlib.h"),
+#if LUA_VERSION_NUM == 503
RS_INT("LUAL_NUMSIZES", LUAL_NUMSIZES),
- RS_STR("LUA_FILEHANDLE", LUA_FILEHANDLE),
+#endif
// == lualib.h ===========================================================
@@ -251,8 +261,10 @@ int main(int argc, const char **argv) {
RS_STR("LUA_IOLIBNAME", LUA_IOLIBNAME),
RS_STR("LUA_OSLIBNAME", LUA_OSLIBNAME),
RS_STR("LUA_STRLIBNAME", LUA_STRLIBNAME),
+#if LUA_VERSION_NUM == 503
RS_STR("LUA_UTF8LIBNAME", LUA_UTF8LIBNAME),
RS_STR("LUA_BITLIBNAME", LUA_BITLIBNAME),
+#endif
RS_STR("LUA_MATHLIBNAME", LUA_MATHLIBNAME),
RS_STR("LUA_DBLIBNAME", LUA_DBLIBNAME),
RS_STR("LUA_LOADLIBNAME", LUA_LOADLIBNAME),
diff --git a/src/ffi/lauxlib.rs b/src/ffi/lauxlib.rs
index 5a9c5c8..941755f 100644
--- a/src/ffi/lauxlib.rs
+++ b/src/ffi/lauxlib.rs
@@ -1,5 +1,6 @@
// The MIT License (MIT)
//
+// Copyright (c) 2019 A. Orlenko
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,10 +27,16 @@ use std::os::raw::{c_char, c_int, c_long, c_void};
use std::ptr;
use super::lua::{self, lua_CFunction, lua_Integer, lua_Number, lua_State};
-use super::luaconf::LUAL_BUFFERSIZE;
+#[cfg(feature = "lua53")]
pub use super::glue::LUAL_NUMSIZES;
-pub use super::glue::LUA_FILEHANDLE;
+
+#[cfg(not(feature = "lua53"))]
+pub use super::compat53::{
+ luaL_checkversion, luaL_getmetafield, luaL_getsubtable, luaL_len, luaL_loadbufferx,
+ luaL_newmetatable, luaL_requiref, luaL_setfuncs, luaL_setmetatable, luaL_testudata,
+ luaL_tolstring, luaL_traceback,
+};
// extra error code for 'luaL_load'
pub const LUA_ERRFILE: c_int = lua::LUA_ERRERR + 1;
@@ -40,6 +47,7 @@ pub struct luaL_Reg {
pub func: lua_CFunction,
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn luaL_checkversion(L: *mut lua_State) {
luaL_checkversion_(
@@ -50,10 +58,17 @@ pub unsafe fn luaL_checkversion(L: *mut lua_State) {
}
extern "C" {
+ #[cfg(feature = "lua53")]
pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: usize);
+ #[cfg(feature = "lua53")]
pub fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "luaL_getmetafield"]
+ pub fn luaL_getmetafield_51(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
+
pub fn luaL_callmeta(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char;
pub fn luaL_argerror(L: *mut lua_State, arg: c_int, l: *const c_char) -> c_int;
pub fn luaL_checklstring(L: *mut lua_State, arg: c_int, l: *mut usize) -> *const c_char;
@@ -72,13 +87,20 @@ extern "C" {
pub fn luaL_checktype(L: *mut lua_State, arg: c_int, t: c_int);
pub fn luaL_checkany(L: *mut lua_State, arg: c_int);
+ #[cfg(feature = "lua53")]
pub fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "luaL_newmetatable"]
+ pub fn luaL_newmetatable_51(L: *mut lua_State, tname: *const c_char) -> c_int;
+
+ #[cfg(feature = "lua53")]
pub fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char);
+ #[cfg(feature = "lua53")]
pub fn luaL_testudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
pub fn luaL_where(L: *mut lua_State, lvl: c_int);
- pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> c_int;
+ pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;
// TODO: test this
pub fn luaL_checkoption(
@@ -88,7 +110,9 @@ extern "C" {
lst: *const *const c_char,
) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn luaL_fileresult(L: *mut lua_State, stat: c_int, fname: *const c_char) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn luaL_execresult(L: *mut lua_State, stat: c_int) -> c_int;
}
@@ -100,16 +124,21 @@ extern "C" {
pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;
pub fn luaL_unref(L: *mut lua_State, t: c_int, r: c_int);
+ #[cfg(feature = "lua53")]
pub fn luaL_loadfilex(L: *mut lua_State, filename: *const c_char, mode: *const c_char)
-> c_int;
+ #[cfg(not(feature = "lua53"))]
+ pub fn luaL_loadfile(L: *mut lua_State, filename: *const c_char) -> c_int;
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int {
luaL_loadfilex(L, f, ptr::null())
}
extern "C" {
+ #[cfg(feature = "lua53")]
pub fn luaL_loadbufferx(
L: *mut lua_State,
buff: *const c_char,
@@ -117,10 +146,18 @@ extern "C" {
name: *const c_char,
mode: *const c_char,
) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ pub fn luaL_loadbuffer(
+ L: *mut lua_State,
+ buff: *const c_char,
+ sz: usize,
+ name: *const c_char,
+ ) -> c_int;
pub fn luaL_loadstring(L: *mut lua_State, s: *const c_char) -> c_int;
pub fn luaL_newstate() -> *mut lua_State;
+ #[cfg(feature = "lua53")]
pub fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer;
pub fn luaL_gsub(
@@ -130,12 +167,16 @@ extern "C" {
r: *const c_char,
) -> *const c_char;
+ #[cfg(feature = "lua53")]
pub fn luaL_setfuncs(L: *mut lua_State, l: *const luaL_Reg, nup: c_int);
+ #[cfg(feature = "lua53")]
pub fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn luaL_traceback(L: *mut lua_State, L1: *mut lua_State, msg: *const c_char, level: c_int);
+ #[cfg(feature = "lua53")]
pub fn luaL_requiref(
L: *mut lua_State,
modname: *const c_char,
@@ -238,6 +279,7 @@ pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) {
// luaL_opt would be implemented here but it is undocumented, so it's omitted
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn luaL_loadbuffer(
L: *mut lua_State,
@@ -248,46 +290,6 @@ pub unsafe fn luaL_loadbuffer(
luaL_loadbufferx(L, s, sz, n, ptr::null())
}
-#[repr(C)]
-pub struct luaL_Buffer {
- pub b: *mut c_char,
- pub size: usize,
- pub n: usize,
- pub L: *mut lua_State,
- pub initb: [c_char; LUAL_BUFFERSIZE as usize],
-}
-
-// TODO: Test this thoroughly
-#[inline(always)]
-pub unsafe fn luaL_addchar(B: *mut luaL_Buffer, c: c_char) {
- // (B)->n < (B) -> size || luaL_prepbuffsize((B), 1)
- if (*B).n < (*B).size {
- luaL_prepbuffsize(B, 1);
- }
- // (B)->b[(B)->n++] = (c)
- let offset = (*B).b.offset((*B).n as isize);
- ptr::write(offset, c);
- (*B).n += 1;
-}
-
-#[inline(always)]
-pub unsafe fn luaL_addsize(B: *mut luaL_Buffer, s: usize) {
- (*B).n += s;
-}
-
-extern "C" {
- pub fn luaL_buffinit(L: *mut lua_State, B: *mut luaL_Buffer);
- pub fn luaL_prepbuffsize(B: *mut luaL_Buffer, sz: usize) -> *mut c_char;
- pub fn luaL_addlstring(B: *mut luaL_Buffer, s: *const c_char, l: usize);
- pub fn luaL_addstring(B: *mut luaL_Buffer, s: *const c_char);
- pub fn luaL_addvalue(B: *mut luaL_Buffer);
- pub fn luaL_pushresult(B: *mut luaL_Buffer);
- pub fn luaL_pushresultsize(B: *mut luaL_Buffer, sz: usize);
- pub fn luaL_buffinitsize(L: *mut lua_State, B: *mut luaL_Buffer, sz: usize) -> *mut c_char;
-}
-
-pub unsafe fn luaL_prepbuffer(B: *mut luaL_Buffer) -> *mut c_char {
- luaL_prepbuffsize(B, LUAL_BUFFERSIZE as usize)
-}
+// TODO: Add buffer API
// omitted: old module system compatibility
diff --git a/src/ffi/lua.rs b/src/ffi/lua.rs
index 3c29a04..ae14a6b 100644
--- a/src/ffi/lua.rs
+++ b/src/ffi/lua.rs
@@ -1,5 +1,6 @@
// The MIT License (MIT)
//
+// Copyright (c) 2019 A. Orlenko
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -22,20 +23,33 @@
//! Contains definitions from `lua.h`.
-use std::os::raw::{c_char, c_int, c_uchar, c_void};
+#[cfg(feature = "lua53")]
+use std::os::raw::c_uchar;
+use std::os::raw::{c_char, c_int, c_void};
use std::ptr;
use super::luaconf;
+pub use super::glue::{LUA_RELEASE, LUA_VERSION, LUA_VERSION_NUM};
+
pub use super::glue::LUA_REGISTRYINDEX;
-pub use super::glue::{LUA_AUTHORS, LUA_COPYRIGHT, LUA_RELEASE, LUA_VERSION};
-pub use super::glue::{LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_NUM, LUA_VERSION_RELEASE};
+#[cfg(not(feature = "lua53"))]
+pub use super::glue::{LUA_ENVIRONINDEX, LUA_GLOBALSINDEX};
pub const LUA_SIGNATURE: &'static [u8] = b"\x1bLua";
// option for multiple returns in 'lua_pcall' and 'lua_call'
pub const LUA_MULTRET: c_int = -1;
+#[cfg(not(feature = "lua53"))]
+pub use super::compat53::{
+ lua_absindex, lua_compare, lua_copy, lua_getextraspace, lua_getfield, lua_geti, lua_gettable,
+ lua_getuservalue, lua_isinteger, lua_len, lua_pushglobaltable, lua_pushlstring, lua_pushstring,
+ lua_rawget, lua_rawgeti, lua_rawgetp, lua_rawlen, lua_rawsetp, lua_resume, lua_rotate,
+ lua_seti, lua_setuservalue, lua_tointegerx, lua_tonumberx, lua_upvalueindex,
+};
+
+#[cfg(feature = "lua53")]
#[inline(always)]
pub fn lua_upvalueindex(i: c_int) -> c_int {
LUA_REGISTRYINDEX - i
@@ -47,7 +61,11 @@ pub const LUA_YIELD: c_int = 1;
pub const LUA_ERRRUN: c_int = 2;
pub const LUA_ERRSYNTAX: c_int = 3;
pub const LUA_ERRMEM: c_int = 4;
+#[cfg(feature = "lua53")]
pub const LUA_ERRGCMM: c_int = 5;
+#[cfg(not(feature = "lua53"))]
+pub const LUA_ERRERR: c_int = 5;
+#[cfg(feature = "lua53")]
pub const LUA_ERRERR: c_int = 6;
pub type lua_State = c_void;
@@ -65,14 +83,18 @@ pub const LUA_TFUNCTION: c_int = 6;
pub const LUA_TUSERDATA: c_int = 7;
pub const LUA_TTHREAD: c_int = 8;
+#[cfg(feature = "lua53")]
pub const LUA_NUMTAGS: c_int = 9;
// minimum stack available to a C function
pub const LUA_MINSTACK: c_int = 20;
// predefined values in the registry
+#[cfg(feature = "lua53")]
pub const LUA_RIDX_MAINTHREAD: lua_Integer = 1;
+#[cfg(feature = "lua53")]
pub const LUA_RIDX_GLOBALS: lua_Integer = 2;
+#[cfg(feature = "lua53")]
pub const LUA_RIDX_LAST: lua_Integer = LUA_RIDX_GLOBALS;
/// A Lua number, usually equivalent to `f64`.
@@ -82,15 +104,18 @@ pub type lua_Number = luaconf::LUA_NUMBER;
pub type lua_Integer = luaconf::LUA_INTEGER;
// unsigned integer type
+#[cfg(feature = "lua53")]
pub type lua_Unsigned = luaconf::LUA_UNSIGNED;
// type for continuation-function contexts
+#[cfg(feature = "lua53")]
pub type lua_KContext = luaconf::LUA_KCONTEXT;
/// Type for native functions that can be passed to Lua.
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;
// Type for continuation functions
+#[cfg(feature = "lua53")]
pub type lua_KFunction =
unsafe extern "C" fn(L: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int;
@@ -116,14 +141,24 @@ extern "C" {
pub fn lua_atpanic(L: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction;
+ #[cfg(feature = "lua53")]
pub fn lua_version(L: *mut lua_State) -> *const lua_Number;
// basic stack manipulation
+ #[cfg(feature = "lua53")]
pub fn lua_absindex(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_gettop(L: *mut lua_State) -> c_int;
pub fn lua_settop(L: *mut lua_State, idx: c_int);
pub fn lua_pushvalue(L: *mut lua_State, idx: c_int);
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_remove(L: *mut lua_State, idx: c_int);
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_insert(L: *mut lua_State, idx: c_int);
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_replace(L: *mut lua_State, idx: c_int);
+ #[cfg(feature = "lua53")]
pub fn lua_rotate(L: *mut lua_State, idx: c_int, n: c_int);
+ #[cfg(feature = "lua53")]
pub fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int);
pub fn lua_checkstack(L: *mut lua_State, sz: c_int) -> c_int;
@@ -133,15 +168,25 @@ extern "C" {
pub fn lua_isnumber(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_isstring(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_iscfunction(L: *mut lua_State, idx: c_int) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_isuserdata(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_type(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_typename(L: *mut lua_State, tp: c_int) -> *const c_char;
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_tonumber(L: *mut lua_State, idx: c_int) -> lua_Number;
+ #[cfg(feature = "lua53")]
pub fn lua_tonumberx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Number;
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_tointeger(L: *mut lua_State, idx: c_int) -> lua_Integer;
+ #[cfg(feature = "lua53")]
pub fn lua_tointegerx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Integer;
pub fn lua_toboolean(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char;
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_objlen(L: *mut lua_State, idx: c_int) -> usize;
+ #[cfg(feature = "lua53")]
pub fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize;
pub fn lua_tocfunction(L: *mut lua_State, idx: c_int) -> lua_CFunction;
pub fn lua_touserdata(L: *mut lua_State, idx: c_int) -> *mut c_void;
@@ -150,22 +195,37 @@ extern "C" {
}
// Comparison and arithmetic functions
+#[cfg(feature = "lua53")]
pub const LUA_OPADD: c_int = 0;
+#[cfg(feature = "lua53")]
pub const LUA_OPSUB: c_int = 1;
+#[cfg(feature = "lua53")]
pub const LUA_OPMUL: c_int = 2;
+#[cfg(feature = "lua53")]
pub const LUA_OPMOD: c_int = 3;
+#[cfg(feature = "lua53")]
pub const LUA_OPPOW: c_int = 4;
+#[cfg(feature = "lua53")]
pub const LUA_OPDIV: c_int = 5;
+#[cfg(feature = "lua53")]
pub const LUA_OPIDIV: c_int = 6;
+#[cfg(feature = "lua53")]
pub const LUA_OPBAND: c_int = 7;
+#[cfg(feature = "lua53")]
pub const LUA_OPBOR: c_int = 8;
+#[cfg(feature = "lua53")]
pub const LUA_OPBXOR: c_int = 9;
+#[cfg(feature = "lua53")]
pub const LUA_OPSHL: c_int = 10;
+#[cfg(feature = "lua53")]
pub const LUA_OPSHR: c_int = 11;
+#[cfg(feature = "lua53")]
pub const LUA_OPUNM: c_int = 12;
+#[cfg(feature = "lua53")]
pub const LUA_OPBNOT: c_int = 13;
extern "C" {
+ #[cfg(feature = "lua53")]
pub fn lua_arith(L: *mut lua_State, op: c_int);
}
@@ -174,7 +234,12 @@ pub const LUA_OPLT: c_int = 1;
pub const LUA_OPLE: c_int = 2;
extern "C" {
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_equal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
pub fn lua_rawequal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_lessthan(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn lua_compare(L: *mut lua_State, idx1: c_int, idx2: c_int, op: c_int) -> c_int;
}
@@ -183,8 +248,19 @@ extern "C" {
pub fn lua_pushnil(L: *mut lua_State);
pub fn lua_pushnumber(L: *mut lua_State, n: lua_Number);
pub fn lua_pushinteger(L: *mut lua_State, n: lua_Integer);
+
+ #[cfg(feature = "lua53")]
pub fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "lua_pushlstring"]
+ pub fn lua_pushlstring_51(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char;
+
+ #[cfg(feature = "lua53")]
pub fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "lua_pushstring"]
+ pub fn lua_pushstring_51(L: *mut lua_State, s: *const c_char) -> *const c_char;
+
// TODO: omitted:
// lua_pushvfstring
pub fn lua_pushfstring(L: *mut lua_State, fmt: *const c_char, ...) -> *const c_char;
@@ -196,35 +272,70 @@ extern "C" {
// get functions (Lua -> stack)
extern "C" {
+ #[cfg(feature = "lua53")]
pub fn lua_getglobal(L: *mut lua_State, var: *const c_char) -> c_int;
+
+ #[cfg(feature = "lua53")]
pub fn lua_gettable(L: *mut lua_State, idx: c_int) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "lua_gettable"]
+ pub fn lua_gettable_51(L: *mut lua_State, idx: c_int) -> c_int;
+
+ #[cfg(feature = "lua53")]
pub fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "lua_getfield"]
+ pub fn lua_getfield_51(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int;
+
+ #[cfg(feature = "lua53")]
pub fn lua_geti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int;
+
+ #[cfg(feature = "lua53")]
pub fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "lua_rawget"]
+ pub fn lua_rawget_51(L: *mut lua_State, idx: c_int);
+
+ #[cfg(feature = "lua53")]
pub fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "lua_rawgeti"]
+ pub fn lua_rawgeti_51(L: *mut lua_State, idx: c_int, n: lua_Integer);
+
+ #[cfg(feature = "lua53")]
pub fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int;
pub fn lua_createtable(L: *mut lua_State, narr: c_int, nrec: c_int);
pub fn lua_newuserdata(L: *mut lua_State, sz: usize) -> *mut c_void;
pub fn lua_getmetatable(L: *mut lua_State, objindex: c_int) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_getfenv(L: *mut lua_State, idx: c_int);
}
// set functions (stack -> Lua)
extern "C" {
+ #[cfg(feature = "lua53")]
pub fn lua_setglobal(L: *mut lua_State, var: *const c_char);
pub fn lua_settable(L: *mut lua_State, idx: c_int);
pub fn lua_setfield(L: *mut lua_State, idx: c_int, k: *const c_char);
+ #[cfg(feature = "lua53")]
pub fn lua_seti(L: *mut lua_State, idx: c_int, n: lua_Integer);
pub fn lua_rawset(L: *mut lua_State, idx: c_int);
pub fn lua_rawseti(L: *mut lua_State, idx: c_int, n: lua_Integer);
+ #[cfg(feature = "lua53")]
pub fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void);
pub fn lua_setmetatable(L: *mut lua_State, objindex: c_int) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn lua_setuservalue(L: *mut lua_State, idx: c_int);
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_setfenv(L: *mut lua_State, idx: c_int) -> c_int;
}
// 'load' and 'call' functions (load and run Lua code)
extern "C" {
+ #[cfg(feature = "lua53")]
pub fn lua_callk(
L: *mut lua_State,
nargs: c_int,
@@ -232,6 +343,7 @@ extern "C" {
ctx: lua_KContext,
k: Option<lua_KFunction>,
);
+ #[cfg(feature = "lua53")]
pub fn lua_pcallk(
L: *mut lua_State,
nargs: c_int,
@@ -240,6 +352,10 @@ extern "C" {
ctx: lua_KContext,
k: Option<lua_KFunction>,
) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_call(L: *mut lua_State, nargs: c_int, nresults: c_int);
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_pcall(L: *mut lua_State, nargs: c_int, nresults: c_int, errfunc: c_int) -> c_int;
pub fn lua_load(
L: *mut lua_State,
reader: lua_Reader,
@@ -247,6 +363,7 @@ extern "C" {
chunkname: *const c_char,
mode: *const c_char,
) -> c_int;
+ // FIXME
pub fn lua_dump(
L: *mut lua_State,
writer: lua_Writer,
@@ -255,11 +372,13 @@ extern "C" {
) -> c_int;
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_call(L: *mut lua_State, n: c_int, r: c_int) {
lua_callk(L, n, r, 0, None)
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_pcall(L: *mut lua_State, n: c_int, r: c_int, f: c_int) -> c_int {
lua_pcallk(L, n, r, f, 0, None)
@@ -267,17 +386,28 @@ pub unsafe fn lua_pcall(L: *mut lua_State, n: c_int, r: c_int, f: c_int) -> c_in
// coroutine functions
extern "C" {
+ #[cfg(feature = "lua53")]
pub fn lua_yieldk(
L: *mut lua_State,
nresults: c_int,
ctx: lua_KContext,
k: Option<lua_KFunction>,
) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ pub fn lua_yield(L: *mut lua_State, nresults: c_int) -> c_int;
+
+ #[cfg(feature = "lua53")]
pub fn lua_resume(L: *mut lua_State, from: *mut lua_State, narg: c_int) -> c_int;
+ #[cfg(not(feature = "lua53"))]
+ #[link_name = "lua_resume"]
+ pub fn lua_resume_51(L: *mut lua_State, narg: c_int) -> c_int;
+
pub fn lua_status(L: *mut lua_State) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn lua_isyieldable(L: *mut lua_State) -> c_int;
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_yield(L: *mut lua_State, n: c_int) -> c_int {
lua_yieldk(L, n, 0, None)
@@ -292,6 +422,7 @@ pub const LUA_GCCOUNTB: c_int = 4;
pub const LUA_GCSTEP: c_int = 5;
pub const LUA_GCSETPAUSE: c_int = 6;
pub const LUA_GCSETSTEPMUL: c_int = 7;
+#[cfg(feature = "lua53")]
pub const LUA_GCISRUNNING: c_int = 9;
extern "C" {
@@ -303,7 +434,9 @@ extern "C" {
pub fn lua_error(L: *mut lua_State) -> !;
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
pub fn lua_concat(L: *mut lua_State, n: c_int);
+ #[cfg(feature = "lua53")]
pub fn lua_len(L: *mut lua_State, idx: c_int);
+ #[cfg(feature = "lua53")]
pub fn lua_stringtonumber(L: *mut lua_State, s: *const c_char) -> usize;
pub fn lua_getallocf(L: *mut lua_State, ud: *mut *mut c_void) -> lua_Alloc;
pub fn lua_setallocf(L: *mut lua_State, f: lua_Alloc, ud: *mut c_void);
@@ -311,16 +444,19 @@ extern "C" {
// some useful macros
// here, implemented as Rust functions
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_getextraspace(L: *mut lua_State) -> *mut c_void {
L.offset(-super::glue::LUA_EXTRASPACE as isize) as *mut c_void
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_tonumber(L: *mut lua_State, i: c_int) -> lua_Number {
lua_tonumberx(L, i, ptr::null_mut())
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer {
lua_tointegerx(L, i, ptr::null_mut())
@@ -387,7 +523,6 @@ pub unsafe fn lua_isnoneornil(L: *mut lua_State, n: c_int) -> c_int {
(lua_type(L, n) <= 0) as c_int
}
-// TODO: Test
#[inline(always)]
pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &'static str) -> *const c_char {
use std::ffi::CString;
@@ -395,6 +530,19 @@ pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &'static str) -> *const c_ch
lua_pushlstring(L, c_str.as_ptr(), c_str.as_bytes().len())
}
+#[cfg(not(feature = "lua53"))]
+#[inline(always)]
+pub unsafe fn lua_setglobal(L: *mut lua_State, var: *const c_char) {
+ lua_setfield(L, LUA_GLOBALSINDEX, var)
+}
+
+#[cfg(not(feature = "lua53"))]
+#[inline(always)]
+pub unsafe fn lua_getglobal(L: *mut lua_State, var: *const c_char) -> c_int {
+ lua_getfield(L, LUA_GLOBALSINDEX, var)
+}
+
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_pushglobaltable(L: *mut lua_State) -> c_int {
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
@@ -405,17 +553,20 @@ pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
lua_tolstring(L, i, ptr::null_mut())
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_insert(L: *mut lua_State, idx: c_int) {
lua_rotate(L, idx, 1)
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_remove(L: *mut lua_State, idx: c_int) {
lua_rotate(L, idx, -1);
lua_pop(L, 1)
}
+#[cfg(feature = "lua53")]
#[inline(always)]
pub unsafe fn lua_replace(L: *mut lua_State, idx: c_int) {
lua_copy(L, -1, idx);
@@ -437,7 +588,7 @@ pub const LUA_MASKLINE: c_int = 1 << (LUA_HOOKLINE as usize);
pub const LUA_MASKCOUNT: c_int = 1 << (LUA_HOOKCOUNT as usize);
/// Type for functions to be called on debug events.
-pub type lua_Hook = Option<extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug)>;
+pub type lua_Hook = extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug);
extern "C" {
pub fn lua_getstack(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) -> c_int;
@@ -447,15 +598,18 @@ extern "C" {
pub fn lua_getupvalue(L: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char;
pub fn lua_setupvalue(L: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char;
+ #[cfg(feature = "lua53")]
pub fn lua_upvalueid(L: *mut lua_State, fidx: c_int, n: c_int) -> *mut c_void;
+ #[cfg(feature = "lua53")]
pub fn lua_upvaluejoin(L: *mut lua_State, fidx1: c_int, n1: c_int, fidx2: c_int, n2: c_int);
pub fn lua_sethook(L: *mut lua_State, func: lua_Hook, mask: c_int, count: c_int);
- pub fn lua_gethook(L: *mut lua_State) -> lua_Hook;
+ pub fn lua_gethook(L: *mut lua_State) -> Option<lua_Hook>;
pub fn lua_gethookmask(L: *mut lua_State) -> c_int;
pub fn lua_gethookcount(L: *mut lua_State) -> c_int;
}
+#[cfg(feature = "lua53")]
#[repr(C)]
pub struct lua_Debug {
pub event: c_int,
@@ -474,3 +628,20 @@ pub struct lua_Debug {
// lua.h mentions this is for private use
i_ci: *mut c_void,
}
+
+#[cfg(not(feature = "lua53"))]
+#[repr(C)]
+pub struct lua_Debug {
+ pub event: c_int,
+ pub name: *const c_char,
+ pub namewhat: *const c_char,
+ pub what: *const c_char,
+ pub source: *const c_char,
+ pub currentline: c_int,
+ pub nups: c_int,
+ pub linedefined: c_int,
+ pub lastlinedefined: c_int,
+ pub short_src: [c_char; luaconf::LUA_IDSIZE as usize],
+ // lua.h mentions this is for private use
+ i_ci: c_int,
+}
diff --git a/src/ffi/luaconf.rs b/src/ffi/luaconf.rs
index ad33352..f966b46 100644
--- a/src/ffi/luaconf.rs
+++ b/src/ffi/luaconf.rs
@@ -1,5 +1,6 @@
// The MIT License (MIT)
//
+// Copyright (c) 2019 A. Orlenko
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -25,24 +26,13 @@
pub use super::glue::LUAL_BUFFERSIZE;
pub use super::glue::LUA_INTEGER;
pub use super::glue::LUA_NUMBER;
+#[cfg(feature = "lua53")]
pub use super::glue::LUA_UNSIGNED;
pub use super::glue::LUA_IDSIZE;
-pub use super::glue::{LUA_MAXINTEGER, LUA_MININTEGER};
-pub use super::glue::LUAI_MAXSTACK;
+#[cfg(feature = "lua53")]
pub use super::glue::LUAL_NUMSIZES;
+#[cfg(feature = "lua53")]
pub type LUA_KCONTEXT = isize; // intptr_t
-
-use std::os::raw::c_int;
-
-#[inline(always)]
-pub unsafe fn lua_numtointeger(n: LUA_NUMBER, p: *mut LUA_INTEGER) -> c_int {
- if n >= (LUA_MININTEGER as LUA_NUMBER) && n < -(LUA_MININTEGER as LUA_NUMBER) {
- *p = n as LUA_INTEGER;
- 1
- } else {
- 0
- }
-}
diff --git a/src/ffi/lualib.rs b/src/ffi/lualib.rs
index 520e499..b3c4998 100644
--- a/src/ffi/lualib.rs
+++ b/src/ffi/lualib.rs
@@ -1,5 +1,6 @@
// The MIT License (MIT)
//
+// Copyright (c) 2019 A. Orlenko
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -27,18 +28,24 @@ use std::os::raw::c_int;
use super::lua::lua_State;
pub use super::glue::{
- LUA_BITLIBNAME, LUA_COLIBNAME, LUA_DBLIBNAME, LUA_IOLIBNAME, LUA_LOADLIBNAME, LUA_MATHLIBNAME,
- LUA_OSLIBNAME, LUA_STRLIBNAME, LUA_TABLIBNAME, LUA_UTF8LIBNAME,
+ LUA_COLIBNAME, LUA_DBLIBNAME, LUA_IOLIBNAME, LUA_LOADLIBNAME, LUA_MATHLIBNAME, LUA_OSLIBNAME,
+ LUA_STRLIBNAME, LUA_TABLIBNAME,
};
+#[cfg(feature = "lua53")]
+pub use super::glue::{LUA_BITLIBNAME, LUA_UTF8LIBNAME};
+
extern "C" {
pub fn luaopen_base(L: *mut lua_State) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn luaopen_coroutine(L: *mut lua_State) -> c_int;
pub fn luaopen_table(L: *mut lua_State) -> c_int;
pub fn luaopen_io(L: *mut lua_State) -> c_int;
pub fn luaopen_os(L: *mut lua_State) -> c_int;
pub fn luaopen_string(L: *mut lua_State) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn luaopen_utf8(L: *mut lua_State) -> c_int;
+ #[cfg(feature = "lua53")]
pub fn luaopen_bit32(L: *mut lua_State) -> c_int;
pub fn luaopen_math(L: *mut lua_State) -> c_int;
pub fn luaopen_debug(L: *mut lua_State) -> c_int;
diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs
index 8e41355..14ac3c0 100644
--- a/src/ffi/mod.rs
+++ b/src/ffi/mod.rs
@@ -1,5 +1,6 @@
// The MIT License (MIT)
//
+// Copyright (c) 2019 A. Orlenko
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,22 +30,23 @@ use std::os::raw::c_int;
// This is more or less in the order it appears in the Lua manual, with the
// exception of constants, which appear scattered throughout the manual text.
-// luaconf.h functions
-pub use self::luaconf::lua_numtointeger;
-
// C API types
pub use self::lua::{
- lua_Alloc, lua_CFunction, lua_Debug, lua_Hook, lua_Integer, lua_KContext, lua_KFunction,
- lua_Number, lua_Reader, lua_State, lua_Unsigned, lua_Writer,
+ lua_Alloc, lua_CFunction, lua_Debug, lua_Hook, lua_Integer, lua_Number, lua_Reader, lua_State,
+ lua_Writer,
};
+#[cfg(feature = "lua53")]
+pub use self::lua::{lua_KContext, lua_KFunction, lua_Unsigned};
+
+#[cfg(not(feature = "lua53"))]
+pub use self::lua::lua_setfenv;
+
// C API functions
pub use self::lua::{
lua_absindex,
- lua_arith,
lua_atpanic,
lua_call,
- lua_callk,
lua_checkstack,
lua_close,
lua_compare,
@@ -84,7 +86,6 @@ pub use self::lua::{
lua_istable,
lua_isthread,
lua_isuserdata,
- lua_isyieldable,
lua_len,
lua_load,
lua_newstate,
@@ -93,7 +94,6 @@ pub use self::lua::{
lua_newuserdata,
lua_next,
lua_pcall,
- lua_pcallk,
lua_pop,
lua_pushboolean,
lua_pushcclosure,
@@ -135,7 +135,6 @@ pub use self::lua::{
lua_setupvalue,
lua_setuservalue,
lua_status,
- lua_stringtonumber,
lua_toboolean,
lua_tocfunction,
lua_tointeger,
@@ -149,61 +148,76 @@ pub use self::lua::{
lua_touserdata,
lua_type,
lua_typename,
- lua_upvalueid,
lua_upvalueindex,
- lua_upvaluejoin,
- lua_version,
lua_xmove,
lua_yield,
- lua_yieldk,
+};
+
+#[cfg(feature = "lua53")]
+pub use self::lua::{
+ lua_arith, lua_callk, lua_isyieldable, lua_pcallk, lua_stringtonumber, lua_upvalueid,
+ lua_upvaluejoin, lua_version, lua_yieldk,
};
// auxiliary library types
-pub use self::lauxlib::{luaL_Buffer, luaL_Reg};
+pub use self::lauxlib::luaL_Reg;
// auxiliary library functions
pub use self::lauxlib::{
- luaL_addchar, luaL_addlstring, luaL_addsize, luaL_addstring, luaL_addvalue, luaL_argcheck,
- luaL_argerror, luaL_buffinit, luaL_buffinitsize, luaL_callmeta, luaL_checkany, luaL_checkint,
- luaL_checkinteger, luaL_checklong, luaL_checklstring, luaL_checknumber, luaL_checkoption,
- luaL_checkstack, luaL_checkstring, luaL_checktype, luaL_checkudata, luaL_checkversion,
- luaL_dofile, luaL_dostring, luaL_error, luaL_execresult, luaL_fileresult, luaL_getmetafield,
- luaL_getmetatable, luaL_getsubtable, luaL_gsub, luaL_len, luaL_loadbuffer, luaL_loadbufferx,
- luaL_loadfile, luaL_loadfilex, luaL_loadstring, luaL_newlib, luaL_newlibtable,
+ luaL_argcheck, luaL_argerror, luaL_callmeta, luaL_checkany, luaL_checkint, luaL_checkinteger,
+ luaL_checklong, luaL_checklstring, luaL_checknumber, luaL_checkoption, luaL_checkstack,
+ luaL_checkstring, luaL_checktype, luaL_checkudata, luaL_dofile, luaL_dostring, luaL_error,
+ luaL_getmetafield, luaL_getmetatable, luaL_getsubtable, luaL_gsub, luaL_len, luaL_loadbuffer,
+ luaL_loadbufferx, luaL_loadfile, luaL_loadstring, luaL_newlib, luaL_newlibtable,
luaL_newmetatable, luaL_newstate, luaL_optint, luaL_optinteger, luaL_optlong, luaL_optlstring,
- luaL_optnumber, luaL_optstring, luaL_prepbuffer, luaL_prepbuffsize, luaL_pushresult,
- luaL_pushresultsize, luaL_ref, luaL_requiref, luaL_setfuncs, luaL_setmetatable, luaL_testudata,
- luaL_tolstring, luaL_traceback, luaL_typename, luaL_unref, luaL_where,
+ luaL_optnumber, luaL_optstring, luaL_ref, luaL_requiref, luaL_setfuncs, luaL_setmetatable,
+ luaL_testudata, luaL_tolstring, luaL_traceback, luaL_typename, luaL_unref, luaL_where,
};
+#[cfg(feature = "lua53")]
+pub use self::lauxlib::{luaL_checkversion, luaL_execresult, luaL_fileresult, luaL_loadfilex};
+
// lualib.h functions
pub use self::lualib::{
- luaL_openlibs, luaopen_base, luaopen_bit32, luaopen_coroutine, luaopen_debug, luaopen_io,
- luaopen_math, luaopen_os, luaopen_package, luaopen_string, luaopen_table, luaopen_utf8,
+ luaL_openlibs, luaopen_base, luaopen_debug, luaopen_io, luaopen_math, luaopen_os,
+ luaopen_package, luaopen_string, luaopen_table,
};
+#[cfg(feature = "lua53")]
+pub use self::lualib::{luaopen_bit32, luaopen_coroutine, luaopen_utf8};
+
// constants from lua.h
pub use self::lua::{
- LUA_ERRERR, LUA_ERRGCMM, LUA_ERRMEM, LUA_ERRRUN, LUA_ERRSYNTAX, LUA_GCCOLLECT, LUA_GCCOUNT,
- LUA_GCCOUNTB, LUA_GCISRUNNING, LUA_GCRESTART, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCSTEP,
- LUA_GCSTOP, LUA_HOOKCALL, LUA_HOOKCOUNT, LUA_HOOKLINE, LUA_HOOKRET, LUA_HOOKTAILCALL,
- LUA_MASKCALL, LUA_MASKCOUNT, LUA_MASKLINE, LUA_MASKRET, LUA_MINSTACK, LUA_MULTRET, LUA_OK,
- LUA_OPADD, LUA_OPBAND, LUA_OPBNOT, LUA_OPBOR, LUA_OPBXOR, LUA_OPDIV, LUA_OPEQ, LUA_OPIDIV,
- LUA_OPLE, LUA_OPLT, LUA_OPMOD, LUA_OPMUL, LUA_OPPOW, LUA_OPSHL, LUA_OPSHR, LUA_OPSUB,
- LUA_OPUNM, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS, LUA_RIDX_MAINTHREAD, LUA_TBOOLEAN,
- LUA_TFUNCTION, LUA_TLIGHTUSERDATA, LUA_TNIL, LUA_TNONE, LUA_TNUMBER, LUA_TSTRING, LUA_TTABLE,
- LUA_TTHREAD, LUA_TUSERDATA, LUA_YIELD,
+ LUA_ERRERR, LUA_ERRMEM, LUA_ERRRUN, LUA_ERRSYNTAX, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB,
+ LUA_GCRESTART, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCSTEP, LUA_GCSTOP, LUA_HOOKCALL,
+ LUA_HOOKCOUNT, LUA_HOOKLINE, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_MASKCALL, LUA_MASKCOUNT,
+ LUA_MASKLINE, LUA_MASKRET, LUA_MINSTACK, LUA_MULTRET, LUA_OK, LUA_OPEQ, LUA_OPLE, LUA_OPLT,
+ LUA_REGISTRYINDEX, LUA_TBOOLEAN, LUA_TFUNCTION, LUA_TLIGHTUSERDATA, LUA_TNIL, LUA_TNONE,
+ LUA_TNUMBER, LUA_TSTRING, LUA_TTABLE, LUA_TTHREAD, LUA_TUSERDATA, LUA_YIELD,
+};
+
+#[cfg(feature = "lua53")]
+pub use self::lua::{
+ LUA_ERRGCMM, LUA_GCISRUNNING, LUA_OPADD, LUA_OPBAND, LUA_OPBNOT, LUA_OPBOR, LUA_OPBXOR,
+ LUA_OPDIV, LUA_OPIDIV, LUA_OPMOD, LUA_OPMUL, LUA_OPPOW, LUA_OPSHL, LUA_OPSHR, LUA_OPSUB,
+ LUA_OPUNM, LUA_RIDX_GLOBALS, LUA_RIDX_MAINTHREAD,
};
+#[cfg(not(feature = "lua53"))]
+pub use self::lua::{LUA_ENVIRONINDEX, LUA_GLOBALSINDEX};
+
// constants from lauxlib.h
-pub use self::lauxlib::{LUA_ERRFILE, LUA_FILEHANDLE, LUA_NOREF, LUA_REFNIL};
+pub use self::lauxlib::{LUA_ERRFILE, LUA_NOREF, LUA_REFNIL};
// constants from lualib.h
pub use self::lualib::{
- LUA_BITLIBNAME, LUA_COLIBNAME, LUA_DBLIBNAME, LUA_IOLIBNAME, LUA_LOADLIBNAME, LUA_MATHLIBNAME,
- LUA_OSLIBNAME, LUA_STRLIBNAME, LUA_TABLIBNAME, LUA_UTF8LIBNAME,
+ LUA_COLIBNAME, LUA_DBLIBNAME, LUA_IOLIBNAME, LUA_LOADLIBNAME, LUA_MATHLIBNAME, LUA_OSLIBNAME,
+ LUA_STRLIBNAME, LUA_TABLIBNAME,
};
+#[cfg(feature = "lua53")]
+pub use self::lualib::{LUA_BITLIBNAME, LUA_UTF8LIBNAME};
+
// Not actually defined in lua.h / luaconf.h
pub const LUA_MAX_UPVALUES: c_int = 255;
@@ -212,6 +226,9 @@ mod glue {
include!(concat!(env!("OUT_DIR"), "/glue.rs"));
}
+#[cfg(not(feature = "lua53"))]
+mod compat53;
+
mod lauxlib;
mod lua;
mod luaconf;
diff --git a/src/lua.rs b/src/lua.rs
index d0c1c8c..73e9011 100644
--- a/src/lua.rs
+++ b/src/lua.rs
@@ -16,6 +16,8 @@ use crate::table::Table;
use crate::thread::Thread;
use crate::types::{Callback, Integer, LightUserData, LuaRef, Number, RegistryKey};
use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataMethods};
+#[cfg(not(feature = "lua53"))]
+use crate::util::set_main_state;
use crate::util::{
assert_stack, callback_error, check_stack, get_main_state, get_userdata, get_wrapped_error,
init_error_registry, init_userdata_metatable, pop_error, protect_lua, protect_lua_closure,
@@ -34,9 +36,41 @@ pub struct Lua {
unsafe impl Send for Lua {}
impl Lua {
+ // Creates a new Lua state and loads standard library without the debug library.
+ #[doc(hidden)]
+ pub fn new() -> Lua {
+ unsafe {
+ let state = ffi::luaL_newstate();
+
+ ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
+ #[cfg(feature = "lua53")]
+ ffi::luaL_requiref(state, cstr!("coroutine"), ffi::luaopen_coroutine, 1);
+ ffi::luaL_requiref(state, cstr!("table"), ffi::luaopen_table, 1);
+ ffi::luaL_requiref(state, cstr!("io"), ffi::luaopen_io, 1);
+ ffi::luaL_requiref(state, cstr!("os"), ffi::luaopen_os, 1);
+ ffi::luaL_requiref(state, cstr!("string"), ffi::luaopen_string, 1);
+ #[cfg(feature = "lua53")]
+ ffi::luaL_requiref(state, cstr!("utf8"), ffi::luaopen_utf8, 1);
+ ffi::luaL_requiref(state, cstr!("math"), ffi::luaopen_math, 1);
+ ffi::luaL_requiref(state, cstr!("package"), ffi::luaopen_package, 1);
+ #[cfg(feature = "lua53")]
+ ffi::lua_pop(state, 9);
+ #[cfg(not(feature = "lua53"))]
+ ffi::lua_pop(state, 7);
+
+ Lua::init_from_ptr(state)
+ }
+ }
+
/// Constructs a new Lua instance from the existing state.
pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua {
+ #[cfg(feature = "lua53")]
let main_state = get_main_state(state);
+ #[cfg(not(feature = "lua53"))]
+ let main_state = {
+ set_main_state(state);
+ state
+ };
let main_state_top = ffi::lua_gettop(state);
let ref_thread = mlua_expect!(
@@ -113,6 +147,7 @@ impl Lua {
}
/// Returns true if the garbage collector is currently running automatically.
+ #[cfg(feature = "lua53")]
pub fn gc_is_running(&self) -> bool {
unsafe { ffi::lua_gc(self.main_state, ffi::LUA_GCISRUNNING, 0) != 0 }
}
@@ -231,7 +266,10 @@ impl Lua {
ffi::LUA_OK => {
if let Some(env) = env {
self.push_value(env)?;
+ #[cfg(feature = "lua53")]
ffi::lua_setupvalue(self.state, -2, 1);
+ #[cfg(not(feature = "lua53"))]
+ ffi::lua_setfenv(self.state, -2);
}
Ok(Function(self.pop_ref()))
}
@@ -421,7 +459,10 @@ impl Lua {
unsafe {
let _sg = StackGuard::new(self.state);
assert_stack(self.state, 2);
+ #[cfg(feature = "lua53")]
ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
+ #[cfg(not(feature = "lua53"))]
+ ffi::lua_pushvalue(self.state, ffi::LUA_GLOBALSINDEX);
Table(self.pop_ref())
}
}
diff --git a/src/scope.rs b/src/scope.rs
index 238e52d..2c88083 100644
--- a/src/scope.rs
+++ b/src/scope.rs
@@ -175,6 +175,12 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
assert_stack(lua.state, 1);
lua.push_ref(&u.0);
ffi::lua_getuservalue(lua.state, -1);
+ #[cfg(not(feature = "lua53"))]
+ {
+ ffi::lua_pushinteger(lua.state, 1);
+ ffi::lua_gettable(lua.state, -2);
+ ffi::lua_remove(lua.state, -2);
+ }
return ffi::lua_touserdata(lua.state, -1)
== check_data.as_ptr() as *mut c_void;
}
@@ -239,7 +245,16 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
assert_stack(lua.state, 6);
push_userdata(lua.state, ())?;
+ #[cfg(feature = "lua53")]
ffi::lua_pushlightuserdata(lua.state, data.as_ptr() as *mut c_void);
+ #[cfg(not(feature = "lua53"))]
+ protect_lua_closure(lua.state, 0, 1, |state| {
+ // Lua 5.1 allows to store only table. Then we will wrap the value.
+ ffi::lua_createtable(state, 1, 0);
+ ffi::lua_pushinteger(state, 1);
+ ffi::lua_pushlightuserdata(state, data.as_ptr() as *mut c_void);
+ ffi::lua_settable(state, -3);
+ })?;
ffi::lua_setuservalue(lua.state, -2);
protect_lua_closure(lua.state, 0, 1, move |state| {
diff --git a/src/userdata.rs b/src/userdata.rs
index 5a52165..617e0c1 100644
--- a/src/userdata.rs
+++ b/src/userdata.rs
@@ -335,6 +335,14 @@ impl<'lua> AnyUserData<'lua> {
/// [`get_user_value`]: #method.get_user_value
pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
let lua = self.0.lua;
+ #[cfg(not(feature = "lua53"))]
+ let v = {
+ // Lua 5.1 allows to store only table. Then we will wrap the value.
+ let t = lua.create_table()?;
+ t.raw_set(1, v)?;
+ crate::Value::Table(t)
+ };
+ #[cfg(feature = "lua53")]
let v = v.to_lua(lua)?;
unsafe {
let _sg = StackGuard::new(lua.state);
@@ -358,6 +366,9 @@ impl<'lua> AnyUserData<'lua> {
ffi::lua_getuservalue(lua.state, -1);
lua.pop_value()
};
+ #[cfg(not(feature = "lua53"))]
+ return crate::Table::from_lua(res, lua)?.get(1);
+ #[cfg(feature = "lua53")]
V::from_lua(res, lua)
}
diff --git a/src/util.rs b/src/util.rs
index acae9ae..513d35f 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -192,7 +192,8 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
Error::SyntaxError {
// This seems terrible, but as far as I can tell, this is exactly what the
// stock Lua REPL does.
- incomplete_input: err_string.ends_with("<eof>"),
+ incomplete_input: err_string.ends_with("<eof>")
+ || err_string.ends_with("'<eof>'"),
message: err_string,
}
}
@@ -204,6 +205,7 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
Error::RuntimeError(err_string)
}
ffi::LUA_ERRMEM => Error::MemoryError(err_string),
+ #[cfg(feature = "lua53")]
ffi::LUA_ERRGCMM => Error::GarbageCollectorError(err_string),
_ => mlua_panic!("unrecognized lua error code"),
}
@@ -441,9 +443,23 @@ pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
1
}
+// Does not call lua_checkstack, uses 2 stack spaces.
+#[cfg(not(feature = "lua53"))]
+pub unsafe fn set_main_state(state: *mut ffi::lua_State) {
+ ffi::lua_pushlightuserdata(state, &MAIN_THREAD_REGISTRY_KEY as *const u8 as *mut c_void);
+ ffi::lua_pushthread(state);
+ ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX);
+}
+
// Does not call lua_checkstack, uses 1 stack space.
pub unsafe fn get_main_state(state: *mut ffi::lua_State) -> *mut ffi::lua_State {
+ #[cfg(feature = "lua53")]
ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_MAINTHREAD);
+ #[cfg(not(feature = "lua53"))]
+ {
+ ffi::lua_pushlightuserdata(state, &MAIN_THREAD_REGISTRY_KEY as *const u8 as *mut c_void);
+ ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
+ }
let main_state = ffi::lua_tothread(state, -1);
ffi::lua_pop(state, 1);
main_state
@@ -735,6 +751,8 @@ unsafe fn get_destructed_userdata_metatable(state: *mut ffi::lua_State) {
ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
}
+#[cfg(not(feature = "lua53"))]
+static MAIN_THREAD_REGISTRY_KEY: u8 = 0;
static ERROR_METATABLE_REGISTRY_KEY: u8 = 0;
static PANIC_METATABLE_REGISTRY_KEY: u8 = 0;
static DESTRUCTED_USERDATA_METATABLE: u8 = 0;