src/spbot/nexus_lua.c
author Tero Marttila <terom@fixme.fi>
Thu, 28 May 2009 01:17:36 +0300
branchnew-lib-errors
changeset 219 cefec18b8268
parent 218 5229a5d098b2
permissions -rw-r--r--
some of the lib/transport stuff compiles
#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_MEM(err);

    // store
    lua->nexus = nexus;

    // create the lua state
    if ((lua->st = luaL_newstate()) == NULL)
        JUMP_SET_ERROR(err, &lua_errors, 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;

    error_reset(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 SUCCESS;
        case LUA_ERRSYNTAX:     return SET_ERROR_STR(err, &lua_errors, ERR_LUA_SYNTAX, error);
        case LUA_ERRRUN:        return SET_ERROR_STR(err, &lua_errors, ERR_LUA_RUN, error);
        case LUA_ERRMEM:        return SET_ERROR_STR(err, &lua_errors, ERR_LUA_MEM, error);
        case LUA_ERRERR:        return SET_ERROR_STR(err, &lua_errors, ERR_LUA_ERR, error);
        case LUA_ERRFILE:       return SET_ERROR_STR(err, &lua_errors, ERR_LUA_FILE, error);
        default:                return SET_ERROR(err, &general_errors, ERR_UNKNOWN);
    };
}