src/lua_console.c
author Tero Marttila <terom@fixme.fi>
Thu, 21 May 2009 16:57:56 +0300
changeset 213 f0e52e026197
parent 205 c13d2fc7b480
child 217 7728d6ec3abf
permissions -rw-r--r--
implement lua_console_on_interrupt to abort any executing thread
#include "lua_console.h"
#include "lua_objs.h"
#include "log.h"

#include <stdlib.h>

#include <lua5.1/lauxlib.h>

struct lua_console {
    /** The lowlevel line-based console */
    struct console *console;

    /** Our lua state */
    struct nexus_lua *lua;

    /** Coroutine state */
    struct lua_thread thread;
};

/**
 * Line finished execution
 */
static void lua_console_on_thread (const error_t *err, void *arg)
{
    struct lua_console *lc = arg;

    if (err)
        // display error message
        console_print(lc->console, error_msg(err));

    // XXX: display return value?
    
    // un-wait console
    console_continue(lc->console);
}

/**
 * Got a line to exec from the console
 */
static enum console_line_status lua_console_on_line (const char *line, void *arg)
{
    struct lua_console *lc = arg;
    error_t err;
    int ret;

    // ignore empty lines and EOF
    if (!line || !(*line))
        return CONSOLE_CONTINUE;
    
    // exec it in our thread
    if ((ret = lua_thread_start(&lc->thread, line, &err)) < 0) {
        // display error message
        console_print(lc->console, error_msg(&err));

        return CONSOLE_CONTINUE;
    }

    // waiting?
    if (ret)
        return CONSOLE_WAIT;

    else
        return CONSOLE_CONTINUE;
}

static void lua_console_on_eof (void *arg)
{
    struct lua_console *lc = arg;

    // exit the process
    nexus_shutdown(lc->lua->nexus);
}

static void lua_console_on_interrupt (void *arg)
{
    struct lua_console *lc = arg;

    // abort thread so we can _start again
    lua_thread_abort(&lc->thread);

    // inform user
    console_print(lc->console, "Execution aborted.");
    
    // accept input
    console_continue(lc->console);
}

static struct console_callbacks _console_callbacks = {
    .on_line        = lua_console_on_line,
    .on_eof         = lua_console_on_eof,
    .on_interrupt   = lua_console_on_interrupt,
};

err_t lua_console_create (struct lua_console **lc_ptr, struct console *console, struct nexus_lua *lua, struct error_info *err)
{
    struct lua_console *lc;

    // allocate
    if ((lc = calloc(1, sizeof(*lc))) == NULL)
        return SET_ERROR(err, ERR_CALLOC);

    // store
    lc->console = console;
    lc->lua = lua;

    // set our console callbacks
    console_set_callbacks(console, &_console_callbacks, lc);

    // init thread
    lua_thread_init(&lc->thread, lua, lua_console_on_thread, lc);

    // ok
    *lc_ptr = lc;

    return SUCCESS;
}

void lua_console_destroy (struct lua_console *lc)
{
    // the console
    console_destroy(lc->console);

    free(lc);
}