/* vifm * Copyright (C) 2021 xaizek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "vlua_state.h" #include <assert.h> /* assert() */ #include <stddef.h> /* NULL size_t */ #include <stdlib.h> /* calloc() free() malloc() */ #include "../utils/darray.h" #include "../utils/string_array.h" #include "lua/lauxlib.h" #include "lua/lua.h" #include "lua/lualib.h" static void set_state(struct lua_State *lua, vlua_t *vlua); /* Address of this variable serves as a key in Lua table. */ static char vlua_state_key; vlua_t * vlua_state_alloc(void) { vlua_t *vlua = calloc(1, sizeof(*vlua)); if(vlua == NULL) { return NULL; } vlua->lua = luaL_newstate(); set_state(vlua->lua, vlua); luaL_requiref(vlua->lua, "base", &luaopen_base, 1); luaL_requiref(vlua->lua, LUA_TABLIBNAME, &luaopen_table, 1); luaL_requiref(vlua->lua, LUA_IOLIBNAME, &luaopen_io, 1); luaL_requiref(vlua->lua, LUA_STRLIBNAME, &luaopen_string, 1); luaL_requiref(vlua->lua, LUA_MATHLIBNAME, &luaopen_math, 1); luaL_requiref(vlua->lua, LUA_OSLIBNAME, &luaopen_os, 1); luaL_requiref(vlua->lua, LUA_LOADLIBNAME, &luaopen_package, 1); lua_pop(vlua->lua, 7); return vlua; } void vlua_state_free(vlua_t *vlua) { if(vlua != NULL) { size_t i; for(i = 0U; i < DA_SIZE(vlua->ptrs); ++i) { free(vlua->ptrs[i]); } DA_REMOVE_ALL(vlua->ptrs); free_string_array(vlua->strings.items, vlua->strings.nitems); lua_close(vlua->lua); free(vlua); } } state_ptr_t * vlua_state_store_pointer(vlua_t *vlua, void *ptr) { state_ptr_t **p = DA_EXTEND(vlua->ptrs); if(p == NULL) { return NULL; } *p = malloc(sizeof(**p)); if(*p == NULL) { return NULL; } (*p)->vlua = vlua; (*p)->ptr = ptr; DA_COMMIT(vlua->ptrs); return *p; } const char * vlua_state_store_string(vlua_t *vlua, const char str[]) { int n = add_to_string_array(&vlua->strings.items, vlua->strings.nitems, str); if(n == vlua->strings.nitems) { return ""; } vlua->strings.nitems = n; return vlua->strings.items[n - 1]; } /* Stores pointer to vlua inside Lua state. */ static void set_state(lua_State *lua, vlua_t *vlua) { lua_pushlightuserdata(lua, &vlua_state_key); lua_pushlightuserdata(lua, vlua); lua_settable(lua, LUA_REGISTRYINDEX); } vlua_t * vlua_state_get(lua_State *lua) { lua_pushlightuserdata(lua, &vlua_state_key); lua_gettable(lua, LUA_REGISTRYINDEX); vlua_t *vlua = lua_touserdata(lua, -1); lua_pop(lua, 1); assert(vlua != NULL && "Failed to obtain vlua state!"); return vlua; } void vlua_state_make_table(vlua_t *vlua, void *key) { lua_pushlightuserdata(vlua->lua, key); lua_newtable(vlua->lua); lua_settable(vlua->lua, LUA_REGISTRYINDEX); } void vlua_state_get_table(vlua_t *vlua, void *key) { lua_pushlightuserdata(vlua->lua, key); lua_gettable(vlua->lua, LUA_REGISTRYINDEX); } int vlua_state_safe_mode_on(lua_State *lua) { vlua_t *vlua = vlua_state_get(lua); return vlua->safe_mode_level++; } void vlua_state_safe_mode_off(lua_State *lua, int cookie) { vlua_t *vlua = vlua_state_get(lua); --vlua->safe_mode_level; assert(vlua->safe_mode_level == cookie && "Mismatched safe mode change!"); assert(vlua->safe_mode_level >= 0 && "Can't disabled disabled safe mode!"); } int vlua_state_proxy_call(lua_State *lua, int (*call)(lua_State *lua)) { if(vlua_state_get(lua)->safe_mode_level != 0) { return luaL_error(lua, "%s", "Unsafe functions can't be called in this environment!"); } return call(lua); } /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set cinoptions+=t0 : */