From e423a543d09e69a04115af7ceb50846853a97ee9 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Tue, 25 Aug 2015 05:16:30 -0400 Subject: Add incomplete FFI code --- diff --git a/src/local.mk b/src/local.mk index 2dd9ffe..cdbdc06 100644 --- a/src/local.mk +++ b/src/local.mk @@ -1,4 +1,5 @@ include $(top_srcdir)/src/resources/local.mk +include $(top_srcdir)/src/scripting/local.mk boukengine_SOURCES += \ src/area.c \ diff --git a/src/scripting/ffi.c b/src/scripting/ffi.c new file mode 100644 index 0000000..9632893 --- /dev/null +++ b/src/scripting/ffi.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2015 Patrick "P. J." McDermott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + */ + +#include +#include +#include +#include "../logging.h" +#include "../resources/script.h" +#include "ffi.h" + +/* LUA_OK is defined in Lua 5.2 but not 5.1. */ +#ifndef LUA_OK +#define LUA_OK 0 +#endif + +static struct script *ctx; +static struct ffi_namespace root = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; +static int call_arg_index; + +static void ffi_register_functions_in_namespace(lua_State *l, + struct ffi_namespace *parent); + +void +ffi_add_namespace(struct ffi_namespace *parent, const char *name) +{ + struct ffi_namespace *new_ns; + + if (parent == NULL) { + parent = &root; + } + + new_ns = malloc(sizeof(*new_ns)); + if (new_ns == NULL) { + err(1, "Failed to allocate FFI namespace \"%s\"", name); + return; + } + new_ns->name = strdup(name); + new_ns->ns_head = NULL; + new_ns->ns_tail = NULL; + new_ns->fn_head = NULL; + new_ns->fn_tail = NULL; + new_ns->next = NULL; + + if (parent->ns_head == NULL) { + parent->ns_head = new_ns; + } else { + parent->ns_tail->next = new_ns; + } + parent->ns_tail = new_ns; +} + +void +ffi_add_function(struct ffi_namespace *parent, const char *name, + void (*func)(void)) +{ + struct ffi_function *new_fn; + + new_fn = malloc(sizeof(*new_fn)); + if (new_fn == NULL) { + err(1, "Failed to allocate FFI function \"%s\"", name); + return; + } + new_fn->name = strdup(name); + new_fn->func = func; + new_fn->next = NULL; + + if (parent->fn_head == NULL) { + parent->fn_head = new_fn; + } else { + parent->fn_tail->next = new_fn; + } + parent->fn_tail = new_fn; +} + +void +ffi_register_functions(struct script *script) +{ + ffi_register_functions_in_namespace(script->lua_state, &root); +} + +static void +ffi_register_functions_in_namespace(lua_State *l, struct ffi_namespace *parent) +{ + struct ffi_namespace *ns; + struct ffi_function *fn; + + for (ns = parent->ns_head; ns != NULL; ns = ns->next) { + } + for (fn = ns->fn_head; fn != NULL; fn = fn->next) { + } + l = l; +} + +void ffi_context_switch(struct script *script) +{ + ctx = script; +} + +int +ffi_stack_get_bool(void) +{ + if (lua_gettop(ctx->lua_state) < ++call_arg_index) { + warn("Bad argument #%d to %s (no value)"); + return 0; + } + if (!lua_isboolean(ctx->lua_state, call_arg_index)) { + warn("Bad argument #%d to %s (boolean expected)"); + return 0; + } + return lua_toboolean(ctx->lua_state, call_arg_index); +} + +int +ffi_stack_get_int(void) +{ +#if LUA_VERSION_NUM <= 501 + if (lua_gettop(ctx->lua_state) < ++call_arg_index) { + warn("Bad argument #%d to %s (no value)"); + return 0; + } + return lua_tointeger(ctx->lua_state, call_arg_index); +#elif LUA_VERSION_NUM == 502 + int v; + int is_int; + + if (lua_gettop(ctx->lua_state) < ++call_arg_index) { + warn("Bad argument #%d to %s (no value)"); + return 0; + } + v = lua_tointegerx(ctx->lua_state, call_arg_index, &is_int); + if (!is_int) { + warn("Bad argument #%d to %s (integer expected)"); + return 0; + } + return v; +#elif LUA_VERSION_NUM >= 503 + if (lua_gettop(ctx->lua_state) < ++call_arg_index) { + warn("Bad argument #%d to %s (no value)"); + return 0; + } + if (!lua_isinteger(ctx->lua_state, call_arg_index)) { + warn("Bad argument #%d to %s (integer expected)"); + return 0; + } + return lua_tointeger(ctx->lua_state, call_arg_index); +#endif +} + +double +ffi_stack_get_float(void) +{ + if (lua_gettop(ctx->lua_state) < ++call_arg_index) { + warn("Bad argument #%d to %s (no value)"); + return 0; + } + if (!lua_isnumber(ctx->lua_state, call_arg_index)) { + warn("Bad argument #%d to %s (number expected)"); + return 0; + } + return lua_tonumber(ctx->lua_state, call_arg_index); +} + +const char * +ffi_stack_get_string(void) +{ + if (lua_gettop(ctx->lua_state) < ++call_arg_index) { + warn("Bad argument #%d to %s (no value)"); + return 0; + } + if (!lua_isstring(ctx->lua_state, call_arg_index)) { + warn("Bad argument #%d to %s (string expected)"); + return 0; + } + return lua_tostring(ctx->lua_state, call_arg_index); +} + +void +ffi_prepare_call(const char *func) +{ + lua_getglobal(ctx->lua_state, func); + call_arg_index = 0; +} + +void +ffi_stack_set_bool(int v) +{ + lua_pushboolean(ctx->lua_state, v); +} + +void +ffi_stack_set_int(int v) +{ + lua_pushinteger(ctx->lua_state, v); +} + +void +ffi_stack_set_float(double v) +{ + lua_pushnumber(ctx->lua_state, v); +} + +void +ffi_stack_set_string(const char *v) +{ + lua_pushstring(ctx->lua_state, v); +} + +void +ffi_call(void) +{ + if (lua_pcall(ctx->lua_state, call_arg_index, 0, 0) != LUA_OK) { + err(1, "Error calling function: %s\n", + lua_tostring(ctx->lua_state, -1)); + } +} diff --git a/src/scripting/ffi.h b/src/scripting/ffi.h new file mode 100644 index 0000000..b635d6f --- /dev/null +++ b/src/scripting/ffi.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 Patrick "P. J." McDermott + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + */ + +#ifndef _SCRIPTING_FFI_H_ +#define _SCRIPTING_FFI_H_ + +#include "../resources/script.h" + +struct ffi_function { + const char *name; + void (*func)(void); + struct ffi_function *next; +}; +struct ffi_namespace { + const char *name; + struct ffi_namespace *ns_head; + struct ffi_namespace *ns_tail; + struct ffi_function *fn_head; + struct ffi_function *fn_tail; + struct ffi_namespace *next; +}; + +void ffi_add_namespace(struct ffi_namespace *parent, const char *name); +void ffi_add_function(struct ffi_namespace *parent, const char *name, + void (*func)(void)); +void ffi_register_functions(struct script *script); +void ffi_context_switch(struct script *script); +int ffi_stack_get_bool(void); +int ffi_stack_get_int(void); +double ffi_stack_get_float(void); +const char *ffi_stack_get_string(void); +void ffi_prepare_call(const char *func); +void ffi_stack_set_bool(int v); +void ffi_stack_set_int(int v); +void ffi_stack_set_float(double v); +void ffi_stack_set_string(const char *v); +void ffi_call(void); + +#endif diff --git a/src/scripting/local.mk b/src/scripting/local.mk new file mode 100644 index 0000000..b709af3 --- /dev/null +++ b/src/scripting/local.mk @@ -0,0 +1,3 @@ +boukengine_SOURCES += \ + src/scripting/ffi.c \ + src/scripting/ffi.h -- cgit v0.9.1