src/nexus_lua.c
author Tero Marttila <terom@fixme.fi>
Thu, 21 May 2009 16:23:50 +0300
branchlua-threads
changeset 207 3fa22abb5421
parent 202 210c43e6c088
child 217 7728d6ec3abf
permissions -rw-r--r--
fix lua_nexus_sleep to use EV_TIMEOUT + misc
#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, struct error_info *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, struct error_info *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, struct error_info *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);
    };
}