src/spbot/nexus_lua.c
branchnew-lib-errors
changeset 218 5229a5d098b2
parent 217 7728d6ec3abf
child 219 cefec18b8268
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/spbot/nexus_lua.c	Thu May 28 00:35:02 2009 +0300
@@ -0,0 +1,117 @@
+#include "nexus_lua.h"
+#include "../lua_objs.h"
+#include "../lua_irc.h"
+
+#include <stdlib.h>
+
+#include <lua5.1/lualib.h>
+#include <lua5.1/lauxlib.h>
+
+/**
+ * Initialize the lua state, in protected mode
+ */
+int nexus_lua_init (lua_State *L)
+{
+    struct nexus_lua *lua;
+   
+    // read the nexus_lua off the stack
+    if ((lua = lua_touserdata(L, 1)) == NULL)
+        luaL_error(L, "lua_touserdata: NULL");
+
+    // open the standard libraries
+    luaL_openlibs(L);
+ 
+    // open our core lua api
+    lua_objs_init(lua);
+
+    // and the irc_* stuff
+    lua_irc_init(lua);
+
+    // ok
+    return 0;
+}
+
+err_t nexus_lua_create (struct nexus_lua **lua_ptr, struct nexus *nexus, error_t *err)
+{
+    struct nexus_lua *lua;
+
+    // alloc
+    if ((lua = calloc(1, sizeof(*lua))) == NULL)
+        return SET_ERROR(err, ERR_CALLOC);
+
+    // store
+    lua->nexus = nexus;
+
+    // create the lua state
+    if ((lua->st = luaL_newstate()) == NULL)
+        JUMP_SET_ERROR(err, ERR_LUA_MEM);
+    
+    // init in protected mode
+    if (nexus_lua_error(lua->st, lua_cpcall(lua->st, &nexus_lua_init, lua), err))
+        goto error;
+
+    // ok
+    *lua_ptr = lua;
+
+    return SUCCESS;
+
+error:
+    nexus_lua_destroy(lua);
+
+    return ERROR_CODE(err);
+}
+
+void nexus_lua_destroy (struct nexus_lua *lua)
+{
+    // close the lua stuff
+    lua_close(lua->st);
+
+    free(lua);
+}
+
+err_t nexus_lua_eval (struct nexus_lua *lua, const char *chunk, error_t *err)
+{
+    int ret;
+    bool loaded = false;
+
+    RESET_ERROR(err);
+
+    // load the line as a lua function
+    if ((ret = luaL_loadstring(lua->st, chunk)))
+        goto error;
+    
+    loaded = true;
+
+    // execute it
+    if ((ret = lua_pcall(lua->st, 0, 0, 0)))
+        goto error;
+
+error:
+    if (ret) {
+        // build the error_info
+        nexus_lua_error(lua->st, ret, err);
+
+        // pop the error message
+        // XXX: err points at GC:able memory
+        lua_pop(lua->st, 1);
+    }
+
+    return ERROR_CODE(err);
+}
+
+err_t nexus_lua_error (lua_State *L, int ret, error_t *err)
+{
+    // XXX: this can raise an erorr itself
+    const char *error = lua_tostring(L, -1);
+
+    switch (ret) {
+        case 0:                 RETURN_SET_ERROR(err, SUCCESS);
+        case LUA_ERRSYNTAX:     RETURN_SET_ERROR_STR(err, ERR_LUA_SYNTAX, error);
+        case LUA_ERRRUN:        RETURN_SET_ERROR_STR(err, ERR_LUA_RUN, error);
+        case LUA_ERRMEM:        RETURN_SET_ERROR_STR(err, ERR_LUA_MEM, error);
+        case LUA_ERRERR:        RETURN_SET_ERROR_STR(err, ERR_LUA_ERR, error);
+        case LUA_ERRFILE:       RETURN_SET_ERROR_STR(err, ERR_LUA_FILE, error);
+        default:                RETURN_SET_ERROR_EXTRA(err, ERR_UNKNOWN, ret);
+    };
+}
+