summaryrefslogtreecommitdiff
path: root/src/ffi
diff options
context:
space:
mode:
Diffstat (limited to 'src/ffi')
-rw-r--r--src/ffi/glue/glue.c247
-rw-r--r--src/ffi/lauxlib.rs264
-rw-r--r--src/ffi/lua.rs439
-rw-r--r--src/ffi/luaconf.rs49
-rw-r--r--src/ffi/lualib.rs47
-rw-r--r--src/ffi/mod.rs310
6 files changed, 1356 insertions, 0 deletions
diff --git a/src/ffi/glue/glue.c b/src/ffi/glue/glue.c
new file mode 100644
index 0000000..7cc5c4a
--- /dev/null
+++ b/src/ffi/glue/glue.c
@@ -0,0 +1,247 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2014 J.C. Moyer
+//
+// 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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+// Macros taken from https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
+#define xstr(s) str(s)
+#define str(s) #s
+
+typedef struct rs_item {
+ int type;
+ const char* name;
+ union {
+ int int_val;
+ const char* str_val;
+ LUA_INTEGER lua_int_val;
+ };
+} 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 RS_INT(name, val) {TY_INT, name, .int_val=val}
+#define RS_LUAINT(name, val) {TY_LUAINT, name, .lua_int_val=val}
+#define RS_STR(name, val) {TY_STR, name, .str_val=val}
+#define RS_TYPE(name, val) {TY_TYPE, name, .str_val=val}
+#define RS_COMMENT(val) {TY_COMMENT, NULL, .str_val=val}
+#define RS_RAW(val) {TY_RAW, NULL, .str_val=val}
+
+const char* rs_int_type(int width) {
+ switch (width) {
+ default:
+ case 2: return "i16";
+ case 4: return "i32";
+ case 8: return "i64";
+ }
+}
+
+const char* rs_uint_type(int width) {
+ switch (width) {
+ default:
+ case 2: return "u16";
+ case 4: return "u32";
+ case 8: return "u64";
+ }
+}
+
+int try_write(char** str, char c, size_t n, size_t* written, size_t szstr) {
+ if (szstr - *written < n) {
+ return 0;
+ }
+ for (; n; n--, *written++) *(*str)++ = c;
+ return 1;
+}
+
+// converts \ in a string to \\ so that it can be used as a rust string literal
+// ensures that `out` will always have a null terminating character
+size_t escape(const char* in, char* out, size_t szout) {
+ size_t written = 0;
+ char cur;
+
+ while (cur = *in++) {
+ switch (cur) {
+ case '\\':
+ if (!try_write(&out, cur, 2, &written, szout)) goto finalize;
+ break;
+ default:
+ if (!try_write(&out, cur, 1, &written, szout)) goto finalize;
+ break;
+ }
+ }
+
+finalize:
+ if (written + 1 <= szout) {
+ *out++ = '\0';
+ written++;
+ }
+ return written;
+}
+
+int write_int_item(FILE* f, const char* name, int value) {
+ return fprintf(f, "pub const %s: c_int = %d;\n", name, value);
+}
+
+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);
+}
+
+int write_str_item(FILE* f, const char* name, const char* value) {
+ size_t len = strlen(value);
+ size_t bufsz = len * 2 + 1;
+ char* buf = malloc(bufsz);
+ int ret;
+ escape(value, buf, bufsz);
+ ret = fprintf(f, "pub const %s: &'static str = \"%s\";\n", name, buf);
+ free(buf);
+ return ret;
+}
+
+int write_type(FILE* f, const char* name, const char* value) {
+ return fprintf(f, "pub type %s = %s;\n", name, value);
+}
+
+int write_comment(FILE* f, const char* value) {
+ return fprintf(f, "/* %s */\n", value);
+}
+
+int write_raw(FILE* f, const char* value) {
+ return fputs(value, f) >= 0;
+}
+
+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);
+ case TY_LUAINT: return write_lua_int_item(f, c->name, c->lua_int_val);
+ case TY_STR: return write_str_item(f, c->name, c->str_val);
+ case TY_TYPE: return write_type(f, c->name, c->str_val);
+ case TY_COMMENT: return write_comment(f, c->str_val);
+ case TY_RAW: return write_raw(f, c->str_val);
+ default: return 0;
+ }
+}
+
+int write_items_(FILE* f, const rs_item items[], size_t num) {
+ size_t i;
+ for (i = 0; i < num; i++) {
+ if (!write_item(f, &items[i])) return 0;
+ }
+ return 1;
+}
+
+#define write_items(f, cs) write_items_(f, cs, sizeof(cs)/sizeof(cs[0]))
+
+int main(int argc, const char** argv) {
+ if (argc <= 1) {
+ printf("usage: %s <filename>\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ const char* filename = argv[1];
+
+ FILE* f = fopen(filename, "w");
+
+ if (!f) {
+ printf("could not open file: errno = %d\n", errno);
+ return EXIT_FAILURE;
+ }
+
+ const rs_item glue_entries[] = {
+ RS_COMMENT("this file was generated by glue.c; do not modify it by hand"),
+ RS_RAW("use libc::*;\n"),
+
+ // == 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),
+
+ // == 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),
+
+ // == lauxlib.h ===========================================================
+
+ RS_COMMENT("lauxlib.h"),
+ RS_INT("LUAL_NUMSIZES", LUAL_NUMSIZES),
+ RS_STR("LUA_FILEHANDLE", LUA_FILEHANDLE),
+
+ // == lualib.h ============================================================
+
+ RS_COMMENT("lualib.h"),
+ RS_STR("LUA_COLIBNAME", LUA_COLIBNAME),
+ RS_STR("LUA_TABLIBNAME", LUA_TABLIBNAME),
+ RS_STR("LUA_IOLIBNAME", LUA_IOLIBNAME),
+ RS_STR("LUA_OSLIBNAME", LUA_OSLIBNAME),
+ RS_STR("LUA_STRLIBNAME", LUA_STRLIBNAME),
+ RS_STR("LUA_UTF8LIBNAME", LUA_UTF8LIBNAME),
+ RS_STR("LUA_BITLIBNAME", LUA_BITLIBNAME),
+ RS_STR("LUA_MATHLIBNAME", LUA_MATHLIBNAME),
+ RS_STR("LUA_DBLIBNAME", LUA_DBLIBNAME),
+ RS_STR("LUA_LOADLIBNAME", LUA_LOADLIBNAME),
+ };
+
+ if (!write_items(f, glue_entries)) {
+ printf("%s: error generating %s; aborting\n", argv[0], filename);
+ return EXIT_FAILURE;
+ }
+
+ fclose(f);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/ffi/lauxlib.rs b/src/ffi/lauxlib.rs
new file mode 100644
index 0000000..83ac690
--- /dev/null
+++ b/src/ffi/lauxlib.rs
@@ -0,0 +1,264 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2014 J.C. Moyer
+//
+// 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.
+
+//! Contains definitions from `lauxlib.h`.
+
+use libc::{c_int, c_long, c_char, c_void, size_t};
+use ffi::lua;
+use ffi::lua::{lua_State, lua_CFunction, lua_Integer, lua_Number};
+use ffi::luaconf::LUAL_BUFFERSIZE;
+use std::ptr;
+
+pub use super::glue::LUAL_NUMSIZES;
+pub use super::glue::LUA_FILEHANDLE;
+
+// extra error code for 'luaL_load'
+pub const LUA_ERRFILE: c_int = lua::LUA_ERRERR + 1;
+
+#[repr(C)]
+pub struct luaL_Reg {
+ pub name: *const c_char,
+ pub func: lua_CFunction,
+}
+
+
+#[inline(always)]
+pub unsafe fn luaL_checkversion(L: *mut lua_State) {
+ luaL_checkversion_(L, lua::LUA_VERSION_NUM as lua_Number, LUAL_NUMSIZES as size_t)
+}
+
+extern {
+ pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: size_t);
+
+ pub fn luaL_getmetafield(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;
+ pub fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut size_t) -> *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 size_t) -> *const c_char;
+ pub fn luaL_optlstring(L: *mut lua_State, arg: c_int, def: *const c_char, l: *mut size_t) -> *const c_char;
+ pub fn luaL_checknumber(L: *mut lua_State, arg: c_int) -> lua_Number;
+ pub fn luaL_optnumber(L: *mut lua_State, arg: c_int, def: lua_Number) -> lua_Number;
+ pub fn luaL_checkinteger(L: *mut lua_State, arg: c_int) -> lua_Integer;
+ pub fn luaL_optinteger(L: *mut lua_State, arg: c_int, def: lua_Integer) -> lua_Integer;
+
+ pub fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char);
+ 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);
+
+ pub fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int;
+ pub fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char);
+ 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;
+
+ // TODO: test this
+ pub fn luaL_checkoption(L: *mut lua_State, arg: c_int, def: *const c_char, lst: *const *const c_char) -> c_int;
+
+ pub fn luaL_fileresult(L: *mut lua_State, stat: c_int, fname: *const c_char) -> c_int;
+ pub fn luaL_execresult(L: *mut lua_State, stat: c_int) -> c_int;
+}
+
+// pre-defined references
+pub const LUA_NOREF: c_int = -2;
+pub const LUA_REFNIL: c_int = -1;
+
+extern {
+ 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);
+
+ pub fn luaL_loadfilex(L: *mut lua_State, filename: *const c_char, mode: *const c_char) -> c_int;
+}
+
+#[inline(always)]
+pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int {
+ luaL_loadfilex(L, f, ptr::null())
+}
+
+extern {
+ pub fn luaL_loadbufferx(L: *mut lua_State, buff: *const c_char, sz: size_t, name: *const c_char, mode: *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;
+
+ pub fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer;
+
+ pub fn luaL_gsub(L: *mut lua_State, s: *const c_char, p: *const c_char, r: *const c_char) -> *const c_char;
+
+ pub fn luaL_setfuncs(L: *mut lua_State, l: *const luaL_Reg, nup: c_int);
+
+ pub fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int;
+
+ pub fn luaL_traceback(L: *mut lua_State, L1: *mut lua_State, msg: *const c_char, level: c_int);
+
+ pub fn luaL_requiref(L: *mut lua_State, modname: *const c_char, openf: lua_CFunction, glb: c_int);
+}
+
+#[inline(always)]
+#[allow(unused_variables)]
+pub unsafe fn luaL_newlibtable(L: *mut lua_State, l: *const luaL_Reg) {
+ // TODO: figure out how to pass an appropriate hint for the second param
+ // this involves correcting the second parameter's type; in C this is
+ // sizeof(l)/sizeof(l[0])
+ lua::lua_createtable(L, 0, 0)
+}
+
+#[inline(always)]
+pub unsafe fn luaL_newlib(L: *mut lua_State, l: *const luaL_Reg) {
+ luaL_checkversion(L);
+ luaL_newlibtable(L, l);
+ luaL_setfuncs(L, l, 0)
+}
+
+#[inline(always)]
+pub unsafe fn luaL_argcheck(L: *mut lua_State, cond: c_int, arg: c_int, extramsg: *const c_char) {
+ if cond == 0 {
+ luaL_argerror(L, arg, extramsg);
+ }
+}
+
+#[inline(always)]
+pub unsafe fn luaL_checkstring(L: *mut lua_State, n: c_int) -> *const c_char {
+ luaL_checklstring(L, n, ptr::null_mut())
+}
+
+#[inline(always)]
+pub unsafe fn luaL_optstring(L: *mut lua_State, n: c_int, d: *const c_char) -> *const c_char {
+ luaL_optlstring(L, n, d, ptr::null_mut())
+}
+
+// From 5.3 user manual:
+// Macros to project non-default integer types (luaL_checkint, luaL_optint,
+// luaL_checklong, luaL_optlong) were deprecated. Use their equivalent over
+// lua_Integer with a type cast (or, when possible, use lua_Integer in your
+// code).
+#[inline(always)]
+//#[deprecated]
+pub unsafe fn luaL_checkint(L: *mut lua_State, n: c_int) -> c_int {
+ luaL_checkinteger(L, n) as c_int
+}
+
+#[inline(always)]
+//#[deprecated]
+pub unsafe fn luaL_optint(L: *mut lua_State, n: c_int, d: c_int) -> c_int {
+ luaL_optinteger(L, n, d as lua_Integer) as c_int
+}
+
+#[inline(always)]
+//#[deprecated]
+pub unsafe fn luaL_checklong(L: *mut lua_State, n: c_int) -> c_long {
+ luaL_checkinteger(L, n) as c_long
+}
+
+#[inline(always)]
+//#[deprecated]
+pub unsafe fn luaL_optlong(L: *mut lua_State, n: c_int, d: c_long) -> c_long {
+ luaL_optinteger(L, n, d as lua_Integer) as c_long
+}
+
+#[inline(always)]
+pub unsafe fn luaL_typename(L: *mut lua_State, i: c_int) -> *const c_char {
+ lua::lua_typename(L, lua::lua_type(L, i))
+}
+
+#[inline(always)]
+pub unsafe fn luaL_dofile(L: *mut lua_State, filename: *const c_char) -> c_int {
+ let status = luaL_loadfile(L, filename);
+ if status == 0 {
+ lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0)
+ } else {
+ status
+ }
+}
+
+#[inline(always)]
+pub unsafe fn luaL_dostring(L: *mut lua_State, s: *const c_char) -> c_int {
+ let status = luaL_loadstring(L, s);
+ if status == 0 {
+ lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0)
+ } else {
+ status
+ }
+}
+
+#[inline(always)]
+pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) {
+ lua::lua_getfield(L, lua::LUA_REGISTRYINDEX, n);
+}
+
+// luaL_opt would be implemented here but it is undocumented, so it's omitted
+
+#[inline(always)]
+pub unsafe fn luaL_loadbuffer(L: *mut lua_State, s: *const c_char, sz: size_t, n: *const c_char) -> c_int {
+ luaL_loadbufferx(L, s, sz, n, ptr::null())
+}
+
+#[repr(C)]
+pub struct luaL_Buffer {
+ pub b: *mut c_char,
+ pub size: size_t,
+ pub n: size_t,
+ 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: size_t) {
+ (*B).n += s;
+}
+
+extern {
+ pub fn luaL_buffinit(L: *mut lua_State, B: *mut luaL_Buffer);
+ pub fn luaL_prepbuffsize(B: *mut luaL_Buffer, sz: size_t) -> *mut c_char;
+ pub fn luaL_addlstring(B: *mut luaL_Buffer, s: *const c_char, l: size_t);
+ 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: size_t);
+ pub fn luaL_buffinitsize(L: *mut lua_State, B: *mut luaL_Buffer, sz: size_t) -> *mut c_char;
+}
+
+pub unsafe fn luaL_prepbuffer(B: *mut luaL_Buffer) -> *mut c_char {
+ luaL_prepbuffsize(B, LUAL_BUFFERSIZE as size_t)
+}
+
+#[repr(C)]
+pub struct luaL_Stream {
+ pub f: *mut ::libc::FILE,
+ pub closef: lua_CFunction
+}
+
+// omitted: old module system compatibility
diff --git a/src/ffi/lua.rs b/src/ffi/lua.rs
new file mode 100644
index 0000000..141402c
--- /dev/null
+++ b/src/ffi/lua.rs
@@ -0,0 +1,439 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2014 J.C. Moyer
+//
+// 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.
+
+//! Contains definitions from `lua.h`.
+
+use libc::{c_void, c_int, c_char, c_uchar, size_t};
+use ffi::luaconf;
+use std::ptr;
+
+pub use super::glue::{LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_NUM, LUA_VERSION_RELEASE};
+pub use super::glue::{LUA_VERSION, LUA_RELEASE, LUA_COPYRIGHT, LUA_AUTHORS};
+pub use super::glue::{LUA_REGISTRYINDEX};
+
+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;
+
+#[inline(always)]
+pub fn lua_upvalueindex(i: c_int) -> c_int {
+ LUA_REGISTRYINDEX - i
+}
+
+// thread status
+pub const LUA_OK: c_int = 0;
+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;
+pub const LUA_ERRGCMM: c_int = 5;
+pub const LUA_ERRERR: c_int = 6;
+
+pub type lua_State = c_void;
+
+// basic types
+pub const LUA_TNONE: c_int = -1;
+
+pub const LUA_TNIL: c_int = 0;
+pub const LUA_TBOOLEAN: c_int = 1;
+pub const LUA_TLIGHTUSERDATA: c_int = 2;
+pub const LUA_TNUMBER: c_int = 3;
+pub const LUA_TSTRING: c_int = 4;
+pub const LUA_TTABLE: c_int = 5;
+pub const LUA_TFUNCTION: c_int = 6;
+pub const LUA_TUSERDATA: c_int = 7;
+pub const LUA_TTHREAD: c_int = 8;
+
+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
+pub const LUA_RIDX_MAINTHREAD: lua_Integer = 1;
+pub const LUA_RIDX_GLOBALS: lua_Integer = 2;
+pub const LUA_RIDX_LAST: lua_Integer = LUA_RIDX_GLOBALS;
+
+/// A Lua number, usually equivalent to `f64`.
+pub type lua_Number = luaconf::LUA_NUMBER;
+
+/// A Lua integer, usually equivalent to `i64`.
+pub type lua_Integer = luaconf::LUA_INTEGER;
+
+// unsigned integer type
+pub type lua_Unsigned = luaconf::LUA_UNSIGNED;
+
+// type for continuation-function contexts
+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
+pub type lua_KFunction = unsafe extern "C" fn(L: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int;
+
+// Type for functions that read/write blocks when loading/dumping Lua chunks
+pub type lua_Reader = unsafe extern "C" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut size_t) -> *const c_char;
+pub type lua_Writer = unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: size_t, ud: *mut c_void) -> c_int;
+
+/// Type for memory-allocation functions.
+pub type lua_Alloc = unsafe extern "C" fn(ud: *mut c_void, ptr: *mut c_void, osize: size_t, nsize: size_t) -> *mut c_void;
+
+extern "C" {
+ // state manipulation
+ pub fn lua_newstate(f: lua_Alloc, ud: *mut c_void) -> *mut lua_State;
+ pub fn lua_close(L: *mut lua_State);
+ pub fn lua_newthread(L: *mut lua_State) -> *mut lua_State;
+
+ pub fn lua_atpanic(L: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction;
+
+ pub fn lua_version(L: *mut lua_State) -> *const lua_Number;
+
+ // basic stack manipulation
+ 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);
+ pub fn lua_rotate(L: *mut lua_State, idx: c_int, n: c_int);
+ 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;
+
+ pub fn lua_xmove(from: *mut lua_State, to: *mut lua_State, n: c_int);
+
+ // access functions (stack -> 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;
+ 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;
+
+ pub fn lua_tonumberx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Number;
+ 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 size_t) -> *const c_char;
+ pub fn lua_rawlen(L: *mut lua_State, idx: c_int) -> size_t;
+ 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;
+ pub fn lua_tothread(L: *mut lua_State, idx: c_int) -> *mut lua_State;
+ pub fn lua_topointer(L: *mut lua_State, idx: c_int) -> *const c_void;
+}
+
+// Comparison and arithmetic functions
+pub const LUA_OPADD: c_int = 0;
+pub const LUA_OPSUB: c_int = 1;
+pub const LUA_OPMUL: c_int = 2;
+pub const LUA_OPMOD: c_int = 3;
+pub const LUA_OPPOW: c_int = 4;
+pub const LUA_OPDIV: c_int = 5;
+pub const LUA_OPIDIV: c_int = 6;
+pub const LUA_OPBAND: c_int = 7;
+pub const LUA_OPBOR: c_int = 8;
+pub const LUA_OPBXOR: c_int = 9;
+pub const LUA_OPSHL: c_int = 10;
+pub const LUA_OPSHR: c_int = 11;
+pub const LUA_OPUNM: c_int = 12;
+pub const LUA_OPBNOT: c_int = 13;
+
+extern "C" {
+ pub fn lua_arith(L: *mut lua_State, op: c_int);
+}
+
+pub const LUA_OPEQ: c_int = 0;
+pub const LUA_OPLT: c_int = 1;
+pub const LUA_OPLE: c_int = 2;
+
+extern "C" {
+ pub fn lua_rawequal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
+ pub fn lua_compare(L: *mut lua_State, idx1: c_int, idx2: c_int, op: c_int) -> c_int;
+}
+
+// push functions (C -> stack)
+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);
+ pub fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: size_t) -> *const c_char;
+ pub fn lua_pushstring(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;
+ pub fn lua_pushcclosure(L: *mut lua_State, f: lua_CFunction, n: c_int);
+ pub fn lua_pushboolean(L: *mut lua_State, b: c_int);
+ pub fn lua_pushlightuserdata(L: *mut lua_State, p: *mut c_void);
+ pub fn lua_pushthread(L: *mut lua_State) -> c_int;
+}
+
+// get functions (Lua -> stack)
+extern "C" {
+ pub fn lua_getglobal(L: *mut lua_State, var: *const c_char) -> c_int;
+ pub fn lua_gettable(L: *mut lua_State, idx: c_int) -> c_int;
+ pub fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int;
+ pub fn lua_geti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int;
+ pub fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int;
+ pub fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int;
+ 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: size_t) -> *mut c_void;
+ pub fn lua_getmetatable(L: *mut lua_State, objindex: c_int) -> c_int;
+ pub fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int;
+}
+
+// set functions (stack -> Lua)
+extern "C" {
+ 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);
+ 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);
+ 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;
+ pub fn lua_setuservalue(L: *mut lua_State, idx: c_int);
+}
+
+// 'load' and 'call' functions (load and run Lua code)
+extern "C" {
+ pub fn lua_callk(L: *mut lua_State, nargs: c_int, nresults: c_int, ctx: lua_KContext, k: Option<lua_KFunction>);
+ pub fn lua_pcallk(L: *mut lua_State, nargs: c_int, nresults: c_int, errfunc: c_int, ctx: lua_KContext, k: Option<lua_KFunction>) -> c_int;
+ pub fn lua_load(L: *mut lua_State, reader: lua_Reader, dt: *mut c_void, chunkname: *const c_char, mode: *const c_char) -> c_int;
+ pub fn lua_dump(L: *mut lua_State, writer: lua_Writer, data: *mut c_void, strip: c_int) -> c_int;
+}
+
+#[inline(always)]
+pub unsafe fn lua_call(L: *mut lua_State, n: c_int, r: c_int) {
+ lua_callk(L, n, r, 0, None)
+}
+
+#[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)
+}
+
+// coroutine functions
+extern "C" {
+ pub fn lua_yieldk(L: *mut lua_State, nresults: c_int, ctx: lua_KContext, k: Option<lua_KFunction>) -> c_int;
+ pub fn lua_resume(L: *mut lua_State, from: *mut lua_State, narg: c_int) -> c_int;
+ pub fn lua_status(L: *mut lua_State) -> c_int;
+ pub fn lua_isyieldable(L: *mut lua_State) -> c_int;
+}
+
+#[inline(always)]
+pub unsafe fn lua_yield(L: *mut lua_State, n: c_int) -> c_int {
+ lua_yieldk(L, n, 0, None)
+}
+
+// garbage-collection function and options
+pub const LUA_GCSTOP: c_int = 0;
+pub const LUA_GCRESTART: c_int = 1;
+pub const LUA_GCCOLLECT: c_int = 2;
+pub const LUA_GCCOUNT: c_int = 3;
+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;
+pub const LUA_GCISRUNNING: c_int = 9;
+
+extern {
+ pub fn lua_gc(L: *mut lua_State, what: c_int, data: c_int) -> c_int;
+}
+
+// miscellaneous functions
+extern {
+ 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);
+ pub fn lua_len(L: *mut lua_State, idx: c_int);
+ pub fn lua_stringtonumber(L: *mut lua_State, s: *const c_char) -> size_t;
+ 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);
+}
+
+// some useful macros
+// here, implemented as Rust functions
+#[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
+}
+
+#[inline(always)]
+pub unsafe fn lua_tonumber(L: *mut lua_State, i: c_int) -> lua_Number {
+ lua_tonumberx(L, i, ptr::null_mut())
+}
+
+#[inline(always)]
+pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer {
+ lua_tointegerx(L, i, ptr::null_mut())
+}
+
+#[inline(always)]
+pub unsafe fn lua_pop(L: *mut lua_State, n: c_int) {
+ lua_settop(L, -n - 1)
+}
+
+#[inline(always)]
+pub unsafe fn lua_newtable(L: *mut lua_State) {
+ lua_createtable(L, 0, 0)
+}
+
+#[inline(always)]
+pub unsafe fn lua_register(L: *mut lua_State, n: *const c_char, f: lua_CFunction) {
+ lua_pushcfunction(L, f);
+ lua_setglobal(L, n)
+}
+
+#[inline(always)]
+pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) {
+ lua_pushcclosure(L, f, 0)
+}
+
+#[inline(always)]
+pub unsafe fn lua_isfunction(L: *mut lua_State, n: c_int) -> c_int {
+ (lua_type(L, n) == LUA_TFUNCTION) as c_int
+}
+
+#[inline(always)]
+pub unsafe fn lua_istable(L: *mut lua_State, n: c_int) -> c_int {
+ (lua_type(L, n) == LUA_TTABLE) as c_int
+}
+
+#[inline(always)]
+pub unsafe fn lua_islightuserdata(L: *mut lua_State, n: c_int) -> c_int {
+ (lua_type(L, n) == LUA_TLIGHTUSERDATA) as c_int
+}
+
+#[inline(always)]
+pub unsafe fn lua_isnil(L: *mut lua_State, n: c_int) -> c_int {
+ (lua_type(L, n) == LUA_TNIL) as c_int
+}
+
+#[inline(always)]
+pub unsafe fn lua_isboolean(L: *mut lua_State, n: c_int) -> c_int {
+ (lua_type(L, n) == LUA_TBOOLEAN) as c_int
+}
+
+#[inline(always)]
+pub unsafe fn lua_isthread(L: *mut lua_State, n: c_int) -> c_int {
+ (lua_type(L, n) == LUA_TTHREAD) as c_int
+}
+
+#[inline(always)]
+pub unsafe fn lua_isnone(L: *mut lua_State, n: c_int) -> c_int {
+ (lua_type(L, n) == LUA_TNONE) as c_int
+}
+
+#[inline(always)]
+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;
+ let c_str = CString::new(s).unwrap();
+ lua_pushlstring(L, c_str.as_ptr(), c_str.as_bytes().len() as size_t)
+}
+
+#[inline(always)]
+pub unsafe fn lua_pushglobaltable(L: *mut lua_State) -> c_int {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
+}
+
+#[inline(always)]
+pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
+ lua_tolstring(L, i, ptr::null_mut())
+}
+
+#[inline(always)]
+pub unsafe fn lua_insert(L: *mut lua_State, idx: c_int) {
+ lua_rotate(L, idx, 1)
+}
+
+#[inline(always)]
+pub unsafe fn lua_remove(L: *mut lua_State, idx: c_int) {
+ lua_rotate(L, idx, -1);
+ lua_pop(L, 1)
+}
+
+#[inline(always)]
+pub unsafe fn lua_replace(L: *mut lua_State, idx: c_int) {
+ lua_copy(L, -1, idx);
+ lua_pop(L, 1)
+}
+
+// Debug API
+// Event codes
+pub const LUA_HOOKCALL: c_int = 0;
+pub const LUA_HOOKRET: c_int = 1;
+pub const LUA_HOOKLINE: c_int = 2;
+pub const LUA_HOOKCOUNT: c_int = 3;
+pub const LUA_HOOKTAILCALL: c_int = 4;
+
+// Event masks
+pub const LUA_MASKCALL: c_int = 1 << (LUA_HOOKCALL as usize);
+pub const LUA_MASKRET: c_int = 1 << (LUA_HOOKRET as usize);
+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)>;
+
+extern "C" {
+ pub fn lua_getstack(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) -> c_int;
+ pub fn lua_getinfo(L: *mut lua_State, what: *const c_char, ar: *mut lua_Debug) -> c_int;
+ pub fn lua_getlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char;
+ pub fn lua_setlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char;
+ 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;
+
+ pub fn lua_upvalueid(L: *mut lua_State, fidx: c_int, n: c_int) -> *mut c_void;
+ 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_gethookmask(L: *mut lua_State) -> c_int;
+ pub fn lua_gethookcount(L: *mut lua_State) -> c_int;
+}
+
+#[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 linedefined: c_int,
+ pub lastlinedefined: c_int,
+ pub nups: c_uchar,
+ pub nparams: c_uchar,
+ pub isvararg: c_char,
+ pub istailcall: c_char,
+ pub short_src: [c_char; luaconf::LUA_IDSIZE as usize],
+ // lua.h mentions this is for private use
+ i_ci: *mut c_void,
+}
+
diff --git a/src/ffi/luaconf.rs b/src/ffi/luaconf.rs
new file mode 100644
index 0000000..05de95d
--- /dev/null
+++ b/src/ffi/luaconf.rs
@@ -0,0 +1,49 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2014 J.C. Moyer
+//
+// 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.
+
+//! Contains definitions from `luaconf.h`.
+
+pub use super::glue::LUAL_BUFFERSIZE;
+pub use super::glue::LUA_NUMBER;
+pub use super::glue::LUA_INTEGER;
+pub use super::glue::LUA_UNSIGNED;
+
+pub use super::glue::{LUA_IDSIZE};
+pub use super::glue::{LUA_MININTEGER, LUA_MAXINTEGER};
+
+pub use super::glue::LUAI_MAXSTACK;
+pub use super::glue::LUAL_NUMSIZES;
+
+pub use super::glue::LUA_KCONTEXT;
+
+use libc::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
new file mode 100644
index 0000000..a0bd5dc
--- /dev/null
+++ b/src/ffi/lualib.rs
@@ -0,0 +1,47 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2014 J.C. Moyer
+//
+// 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.
+
+//! Contains definitions from `lualib.h`.
+
+use ffi::lua::lua_State;
+use libc::c_int;
+
+pub use super::glue::{
+ LUA_COLIBNAME, LUA_TABLIBNAME, LUA_IOLIBNAME, LUA_OSLIBNAME, LUA_STRLIBNAME,
+ LUA_UTF8LIBNAME, LUA_BITLIBNAME, LUA_MATHLIBNAME, LUA_DBLIBNAME, LUA_LOADLIBNAME
+};
+
+extern "C" {
+ pub fn luaopen_base(L: *mut lua_State) -> c_int;
+ 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;
+ pub fn luaopen_utf8(L: *mut lua_State) -> c_int;
+ 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;
+ pub fn luaopen_package(L: *mut lua_State) -> c_int;
+
+ pub fn luaL_openlibs(L: *mut lua_State);
+}
diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs
new file mode 100644
index 0000000..fbe9416
--- /dev/null
+++ b/src/ffi/mod.rs
@@ -0,0 +1,310 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2014 J.C. Moyer
+//
+// 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.
+
+//! Low level bindings to Lua.
+
+#![allow(non_camel_case_types, non_snake_case, dead_code)]
+
+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_KContext,
+ lua_Debug,
+ lua_Hook,
+ lua_Integer,
+ lua_KFunction,
+ lua_Number,
+ lua_Reader,
+ lua_State,
+ lua_Unsigned,
+ lua_Writer
+};
+
+// C API functions
+pub use self::lua::{
+ lua_absindex,
+ lua_arith,
+ lua_atpanic,
+ lua_call,
+ lua_callk,
+ lua_checkstack,
+ lua_close,
+ lua_compare,
+ lua_concat,
+ lua_copy,
+ lua_createtable,
+ lua_dump,
+ lua_error,
+ lua_gc,
+ lua_getallocf,
+ lua_getextraspace,
+ lua_getfield,
+ lua_getglobal,
+ lua_gethook,
+ lua_gethookcount,
+ lua_gethookmask,
+ lua_geti,
+ lua_getinfo,
+ lua_getlocal,
+ lua_getmetatable,
+ lua_getstack,
+ lua_gettable,
+ lua_gettop,
+ lua_getupvalue,
+ lua_getuservalue,
+ lua_insert,
+ lua_isboolean,
+ lua_iscfunction,
+ lua_isfunction,
+ lua_isinteger,
+ lua_islightuserdata,
+ lua_isnil,
+ lua_isnone,
+ lua_isnoneornil,
+ lua_isnumber,
+ lua_isstring,
+ lua_istable,
+ lua_isthread,
+ lua_isuserdata,
+ lua_isyieldable,
+ lua_len,
+ lua_load,
+ lua_newstate,
+ lua_newtable,
+ lua_newthread,
+ lua_newuserdata,
+ lua_next,
+ lua_pcall,
+ lua_pcallk,
+ lua_pop,
+ lua_pushboolean,
+ lua_pushcclosure,
+ lua_pushcfunction,
+ lua_pushfstring,
+ lua_pushglobaltable,
+ lua_pushinteger,
+ lua_pushlightuserdata,
+ lua_pushliteral,
+ lua_pushlstring,
+ lua_pushnil,
+ lua_pushnumber,
+ lua_pushstring,
+ lua_pushthread,
+ lua_pushvalue,
+ // omitted: lua_pushvfstring
+ lua_rawequal,
+ lua_rawget,
+ lua_rawgeti,
+ lua_rawgetp,
+ lua_rawlen,
+ lua_rawset,
+ lua_rawseti,
+ lua_rawsetp,
+ lua_register,
+ lua_remove,
+ lua_replace,
+ lua_resume,
+ lua_rotate,
+ lua_setallocf,
+ lua_setfield,
+ lua_setglobal,
+ lua_sethook,
+ lua_seti,
+ lua_setlocal,
+ lua_setmetatable,
+ lua_settable,
+ lua_settop,
+ lua_setupvalue,
+ lua_setuservalue,
+ lua_status,
+ lua_stringtonumber,
+ lua_toboolean,
+ lua_tocfunction,
+ lua_tointeger,
+ lua_tointegerx,
+ lua_tolstring,
+ lua_tonumber,
+ lua_tonumberx,
+ lua_topointer,
+ lua_tostring,
+ lua_tothread,
+ lua_touserdata,
+ lua_type,
+ lua_typename,
+ lua_upvalueid,
+ lua_upvalueindex,
+ lua_upvaluejoin,
+ lua_version,
+ lua_xmove,
+ lua_yield,
+ lua_yieldk
+};
+
+// auxiliary library types
+pub use self::lauxlib::{
+ luaL_Buffer,
+ luaL_Reg,
+ luaL_Stream
+};
+
+// 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_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
+};
+
+// lualib.h functions
+pub use self::lualib::{
+ luaopen_base,
+ luaopen_coroutine,
+ luaopen_table,
+ luaopen_io,
+ luaopen_os,
+ luaopen_string,
+ luaopen_utf8,
+ luaopen_bit32,
+ luaopen_math,
+ luaopen_debug,
+ luaopen_package,
+
+ luaL_openlibs
+};
+
+// constants from lua.h
+pub use self::lua::{
+ LUA_MULTRET,
+ LUA_REGISTRYINDEX,
+
+ LUA_RIDX_MAINTHREAD, LUA_RIDX_GLOBALS,
+
+ LUA_OPADD, LUA_OPSUB, LUA_OPMUL, LUA_OPDIV, LUA_OPIDIV,
+ LUA_OPMOD, LUA_OPPOW, LUA_OPUNM,
+ LUA_OPBNOT, LUA_OPBAND, LUA_OPBOR, LUA_OPBXOR, LUA_OPSHL, LUA_OPSHR,
+ LUA_OPEQ, LUA_OPLT, LUA_OPLE,
+
+ LUA_OK, LUA_YIELD, LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM, LUA_ERRGCMM, LUA_ERRERR,
+
+ LUA_TNONE, LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE,
+ LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA,
+
+ LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE, LUA_HOOKCOUNT,
+ LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, LUA_MASKCOUNT,
+
+ LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB,
+ LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING,
+
+ LUA_MINSTACK
+};
+
+// constants from lauxlib.h
+pub use self::lauxlib::{
+ LUA_REFNIL, LUA_NOREF,
+ LUA_ERRFILE,
+ LUA_FILEHANDLE
+};
+
+// constants from lualib.h
+pub use self::lualib::{
+ LUA_COLIBNAME, LUA_TABLIBNAME, LUA_IOLIBNAME, LUA_OSLIBNAME, LUA_STRLIBNAME,
+ LUA_UTF8LIBNAME, LUA_BITLIBNAME, LUA_MATHLIBNAME, LUA_DBLIBNAME, LUA_LOADLIBNAME
+};
+
+// Not actually defined in lua.h / luaconf.h
+pub const LUA_MAX_UPVALUES: c_int = 255;
+
+#[allow(unused_imports, dead_code, non_camel_case_types)]
+mod glue {
+ include!(concat!(env!("OUT_DIR"), "/glue.rs"));
+}
+
+mod luaconf;
+mod lua;
+mod lauxlib;
+mod lualib;