Replace ffi module with implementation from "jcmoyer/rust-lua53" crate

This commit is contained in:
Alex Orlenko 2019-09-27 00:31:27 +01:00
parent 14a68dd6d2
commit 53b352466e
10 changed files with 1412 additions and 332 deletions

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
target/
**/*.rs.bk
Cargo.lock
.vscode/
.DS_Store

View file

@ -19,7 +19,8 @@ num-traits = { version = "0.2.6" }
compiletest_rs = { version = "0.3", optional = true }
[build-dependencies]
pkg-config = "0.3"
cc = "1.0"
pkg-config = "0.3.11"
[dev-dependencies]
rustyline = "2.0.0"

View file

@ -1,8 +1,56 @@
extern crate pkg_config;
use std::io;
use std::env;
use std::path::PathBuf;
use std::process::Command;
trait CommandExt {
fn execute(&mut self) -> io::Result<()>;
}
impl CommandExt for Command {
/// Execute the command and return an error if it exited with a failure status.
fn execute(&mut self) -> io::Result<()> {
self.status()
.map(|_| ())
.map_err(|_| {
io::Error::new(io::ErrorKind::Other, format!("The command\n\
\t{:?}\n\
did not run successfully.", self))
})
}
}
fn main() {
pkg_config::Config::new()
.atleast_version("5.3")
let lua = pkg_config::Config::new()
.atleast_version("5.1")
.probe("lua")
.unwrap();
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
// Ensure the presence of glue.rs
if !build_dir.join("glue.rs").exists() {
let mut config = cc::Build::new();
for path in lua.include_paths {
config.include(path);
}
for (k, v) in lua.defines {
config.define(&k, v.as_ref().map(|x| x.as_str()));
}
// Compile and run glue.c
let glue = build_dir.join("glue");
config.get_compiler().to_command()
.arg("src/ffi/glue/glue.c")
.arg("-o").arg(&glue)
.execute()
.unwrap();
Command::new(glue)
.arg(build_dir.join("glue.rs"))
.execute()
.unwrap();
}
}

View file

@ -1,328 +0,0 @@
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
use std::mem;
use std::os::raw::{c_char, c_double, c_int, c_longlong, c_uchar, c_void};
use std::ptr;
pub type lua_Integer = c_longlong;
pub type lua_Number = c_double;
pub enum lua_State {}
pub type lua_Alloc =
unsafe extern "C" fn(ud: *mut c_void, ptr: *mut c_void, osize: usize, nsize: usize)
-> *mut c_void;
pub type lua_KContext = *mut c_void;
pub type lua_KFunction =
unsafe extern "C" fn(state: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int;
pub type lua_CFunction = unsafe extern "C" fn(state: *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; LUA_IDSIZE as usize],
i_ci: *mut c_void,
}
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 const LUA_NOREF: c_int = -2;
pub const LUA_REFNIL: c_int = -1;
pub const LUA_MULTRET: c_int = -1;
pub const LUAI_MAXSTACK: c_int = 1_000_000;
pub const LUA_REGISTRYINDEX: c_int = -LUAI_MAXSTACK - 1000;
pub const LUA_RIDX_MAINTHREAD: lua_Integer = 1;
pub const LUA_RIDX_GLOBALS: lua_Integer = 2;
pub const LUA_IDSIZE: c_int = 60;
pub const LUA_MINSTACK: c_int = 20;
// Not actually defined in lua.h / luaconf.h
pub const LUA_MAX_UPVALUES: c_int = 255;
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_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 "C" {
pub fn lua_newstate(alloc: lua_Alloc, ud: *mut c_void) -> *mut lua_State;
pub fn lua_close(state: *mut lua_State);
pub fn lua_callk(
state: *mut lua_State,
nargs: c_int,
nresults: c_int,
ctx: lua_KContext,
k: Option<lua_KFunction>,
);
pub fn lua_pcallk(
state: *mut lua_State,
nargs: c_int,
nresults: c_int,
msgh: c_int,
ctx: lua_KContext,
k: Option<lua_KFunction>,
) -> c_int;
pub fn lua_resume(state: *mut lua_State, from: *mut lua_State, nargs: c_int) -> c_int;
pub fn lua_status(state: *mut lua_State) -> c_int;
pub fn lua_pushnil(state: *mut lua_State);
pub fn lua_pushvalue(state: *mut lua_State, index: c_int);
pub fn lua_pushboolean(state: *mut lua_State, b: c_int);
pub fn lua_pushinteger(state: *mut lua_State, n: lua_Integer);
pub fn lua_pushnumber(state: *mut lua_State, n: lua_Number);
pub fn lua_pushlstring(state: *mut lua_State, s: *const c_char, len: usize) -> *const c_char;
pub fn lua_pushstring(state: *mut lua_State, s: *const c_char) -> *const c_char;
pub fn lua_pushlightuserdata(state: *mut lua_State, data: *mut c_void);
pub fn lua_pushcclosure(state: *mut lua_State, function: lua_CFunction, n: c_int);
pub fn lua_tointegerx(state: *mut lua_State, index: c_int, isnum: *mut c_int) -> lua_Integer;
pub fn lua_tolstring(state: *mut lua_State, index: c_int, len: *mut usize) -> *const c_char;
pub fn lua_toboolean(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_tonumberx(state: *mut lua_State, index: c_int, isnum: *mut c_int) -> lua_Number;
pub fn lua_touserdata(state: *mut lua_State, index: c_int) -> *mut c_void;
pub fn lua_tothread(state: *mut lua_State, index: c_int) -> *mut lua_State;
pub fn lua_gettop(state: *const lua_State) -> c_int;
pub fn lua_settop(state: *mut lua_State, n: c_int);
pub fn lua_checkstack(state: *mut lua_State, n: c_int) -> c_int;
pub fn lua_rotate(state: *mut lua_State, index: c_int, n: c_int);
pub fn lua_copy(state: *mut lua_State, from: c_int, to: c_int);
pub fn lua_absindex(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_xmove(from: *mut lua_State, to: *mut lua_State, n: c_int);
pub fn lua_isinteger(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_isnumber(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_isstring(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_iscfunction(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_isuserdata(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_type(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_gettable(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_geti(state: *mut lua_State, index: c_int, i: lua_Integer) -> c_int;
pub fn lua_rawget(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_rawgeti(state: *mut lua_State, index: c_int, n: lua_Integer) -> c_int;
pub fn lua_rawseti(state: *mut lua_State, index: c_int, n: lua_Integer);
pub fn lua_getmetatable(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_createtable(state: *mut lua_State, narr: c_int, nrec: c_int);
pub fn lua_newuserdata(state: *mut lua_State, size: usize) -> *mut c_void;
pub fn lua_newthread(state: *mut lua_State) -> *mut lua_State;
pub fn lua_setuservalue(state: *mut lua_State, index: c_int);
pub fn lua_getuservalue(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_getupvalue(state: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char;
pub fn lua_setupvalue(state: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char;
pub fn lua_settable(state: *mut lua_State, index: c_int);
pub fn lua_rawset(state: *mut lua_State, index: c_int);
pub fn lua_setmetatable(state: *mut lua_State, index: c_int);
pub fn lua_len(state: *mut lua_State, index: c_int);
pub fn lua_rawlen(state: *mut lua_State, index: c_int) -> usize;
pub fn lua_next(state: *mut lua_State, index: c_int) -> c_int;
pub fn lua_rawequal(state: *mut lua_State, index1: c_int, index2: c_int) -> c_int;
pub fn lua_error(state: *mut lua_State) -> !;
pub fn lua_atpanic(state: *mut lua_State, panic: lua_CFunction) -> lua_CFunction;
pub fn lua_gc(state: *mut lua_State, what: c_int, data: c_int) -> c_int;
pub fn lua_getinfo(state: *mut lua_State, what: *const c_char, ar: *mut lua_Debug) -> c_int;
pub fn luaopen_base(state: *mut lua_State) -> c_int;
pub fn luaopen_coroutine(state: *mut lua_State) -> c_int;
pub fn luaopen_table(state: *mut lua_State) -> c_int;
pub fn luaopen_io(state: *mut lua_State) -> c_int;
pub fn luaopen_os(state: *mut lua_State) -> c_int;
pub fn luaopen_string(state: *mut lua_State) -> c_int;
pub fn luaopen_utf8(state: *mut lua_State) -> c_int;
pub fn luaopen_math(state: *mut lua_State) -> c_int;
pub fn luaopen_debug(state: *mut lua_State) -> c_int;
pub fn luaopen_package(state: *mut lua_State) -> c_int;
pub fn luaL_openlibs(state: *mut lua_State);
pub fn luaL_requiref(
state: *mut lua_State,
modname: *const c_char,
openf: lua_CFunction,
glb: c_int,
);
pub fn luaL_loadbufferx(
state: *mut lua_State,
buf: *const c_char,
size: usize,
name: *const c_char,
mode: *const c_char,
) -> c_int;
pub fn luaL_ref(state: *mut lua_State, table: c_int) -> c_int;
pub fn luaL_unref(state: *mut lua_State, table: c_int, lref: c_int);
pub fn luaL_checkstack(state: *mut lua_State, size: c_int, msg: *const c_char);
pub fn luaL_traceback(
push_state: *mut lua_State,
state: *mut lua_State,
msg: *const c_char,
level: c_int,
);
pub fn luaL_len(push_state: *mut lua_State, index: c_int) -> lua_Integer;
}
// The following are re-implementations of what are macros in the Lua C API
pub unsafe fn lua_getextraspace(state: *mut lua_State) -> *mut c_void {
(state as *mut c_void).offset(-(mem::size_of::<*mut c_void>() as isize))
}
pub unsafe fn lua_pop(state: *mut lua_State, n: c_int) {
lua_settop(state, -n - 1);
}
pub unsafe fn lua_newtable(state: *mut lua_State) {
lua_createtable(state, 0, 0);
}
pub fn lua_upvalueindex(i: c_int) -> c_int {
LUA_REGISTRYINDEX - i
}
pub unsafe fn lua_pushcfunction(state: *mut lua_State, function: lua_CFunction) {
lua_pushcclosure(state, function, 0);
}
pub unsafe fn lua_tonumber(state: *mut lua_State, index: c_int) -> lua_Number {
lua_tonumberx(state, index, ptr::null_mut())
}
pub unsafe fn lua_tointeger(state: *mut lua_State, index: c_int) -> lua_Integer {
lua_tointegerx(state, index, ptr::null_mut())
}
pub unsafe fn lua_tostring(state: *mut lua_State, index: c_int) -> *const c_char {
lua_tolstring(state, index, ptr::null_mut())
}
pub unsafe fn lua_isfunction(state: *mut lua_State, index: c_int) -> c_int {
if lua_type(state, index) == LUA_TFUNCTION {
1
} else {
0
}
}
pub unsafe fn lua_istable(state: *mut lua_State, index: c_int) -> c_int {
if lua_type(state, index) == LUA_TTABLE {
1
} else {
0
}
}
pub unsafe fn lua_islightuserdata(state: *mut lua_State, index: c_int) -> c_int {
if lua_type(state, index) == LUA_TLIGHTUSERDATA {
1
} else {
0
}
}
pub unsafe fn lua_isnil(state: *mut lua_State, index: c_int) -> c_int {
if lua_type(state, index) == LUA_TNIL {
1
} else {
0
}
}
pub unsafe fn lua_isboolean(state: *mut lua_State, index: c_int) -> c_int {
if lua_type(state, index) == LUA_TBOOLEAN {
1
} else {
0
}
}
pub unsafe fn lua_isthread(state: *mut lua_State, index: c_int) -> c_int {
if lua_type(state, index) == LUA_TTHREAD {
1
} else {
0
}
}
pub unsafe fn lua_isnone(state: *mut lua_State, index: c_int) -> c_int {
if lua_type(state, index) == LUA_TNONE {
1
} else {
0
}
}
pub unsafe fn lua_insert(state: *mut lua_State, index: c_int) {
lua_rotate(state, index, 1);
}
pub unsafe fn lua_remove(state: *mut lua_State, index: c_int) {
lua_rotate(state, index, -1);
lua_pop(state, 1);
}
pub unsafe fn lua_call(state: *mut lua_State, nargs: c_int, nresults: c_int) {
lua_callk(state, nargs, nresults, ptr::null_mut(), None)
}
pub unsafe fn lua_pcall(
state: *mut lua_State,
nargs: c_int,
nresults: c_int,
msgh: c_int,
) -> c_int {
lua_pcallk(state, nargs, nresults, msgh, ptr::null_mut(), None)
}
pub unsafe fn lua_replace(state: *mut lua_State, index: c_int) {
lua_copy(state, -1, index);
lua_pop(state, 1);
}
pub unsafe fn luaL_loadbuffer(
state: *mut lua_State,
buf: *const c_char,
size: usize,
name: *const c_char,
) -> c_int {
luaL_loadbufferx(state, buf, size, name, ptr::null())
}

247
src/ffi/glue/glue.c Normal file
View file

@ -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;
}

264
src/ffi/lauxlib.rs Normal file
View file

@ -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

439
src/ffi/lua.rs Normal file
View file

@ -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,
}

49
src/ffi/luaconf.rs Normal file
View file

@ -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
}
}

47
src/ffi/lualib.rs Normal file
View file

@ -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);
}

310
src/ffi/mod.rs Normal file
View file

@ -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;