capi4yaps/lua.c

443 lines
9.6 KiB
C

/* -*- mode: c; mode: fold -*- */
# include "config.h"
# ifdef SCRIPT_LUA
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <lua.h>
# include <lualib.h>
# include "pager.h"
# include "script.h"
# define STARTUP "Startup.lua"
/*{{{ statics & callable functions */
static Bool isinit = False;
static double lua_no_err = (double) NO_ERR,
lua_err_fail = (double) ERR_FAIL,
lua_err_fatal = (double) ERR_FATAL,
lua_err_abort = (double) ERR_ABORT;
static script *ls = NULL;
static char *lline = NULL;
static int lsiz = 0;
static char *lcb = NULL;
static void
lua_logger (void)
{
lua_Object obj;
char *sav, *str;
char typ;
if (((obj = lua_getparam (1)) != LUA_NOOBJECT) &&
(str = lua_getstring (obj)) &&
(sav = strdup (str))) {
typ = *sav;
if (((obj = lua_getparam (2)) == LUA_NOOBJECT) ||
(! (str = lua_getstring (obj)))) {
str = sav;
typ = LG_INF;
}
if (ls && ls -> logger)
(*ls -> logger) (typ, "%s\n", str);
free (sav);
}
}
static void
lua_callback (void *sp, string_t *s, char_t sep, void *data)
{
int len;
char *str;
lua_Object obj;
if (str = sextract (s)) {
len = strlen (str);
if (len + 2 >= lsiz) {
lsiz = len + 64;
if (! (lline = Realloc (lline, lsiz + 4)))
lsiz = 0;
}
if (lline) {
sprintf (lline, "%s%c", str, (char) sep);
if (lcb && (obj = lua_getglobal (lcb)) && lua_isfunction (obj)) {
lua_pushstring (lline);
lua_callfunction (obj);
}
}
free (str);
}
}
static void
lua_setcb (void)
{
lua_Object obj1, obj2;
char *sep, *func;
if ((obj1 = lua_getparam (1)) != LUA_NOOBJECT)
obj2 = lua_getparam (2);
else
obj2 = LUA_NOOBJECT;
if (lcb) {
free (lcb);
lcb = NULL;
}
if ((obj1 == LUA_NOOBJECT) || (! lua_isstring (obj1)) || (! (sep = lua_getstring (obj1)))) {
if (ls && ls -> sp)
tty_set_line_callback (ls -> sp, NULL, NULL, NULL);
} else {
if (ls && ls -> sp)
tty_set_line_callback (ls -> sp, lua_callback, sep, NULL);
if ((obj2 != LUA_NOOBJECT) && lua_isstring (obj2) && (func = lua_getstring (obj2)))
lcb = strdup (func);
}
}
static void
lua_get_line (void)
{
if (lline)
lua_pushstring (lline);
else
lua_pushnil ();
}
static void
lua_hangup (void)
{
lua_Object obj;
double sec;
int msec;
if (((obj = lua_getparam (1)) != LUA_NOOBJECT) &&
lua_isnumber (obj)) {
sec = lua_getnumber (obj);
msec = (int) (sec * 1000.0);
} else
msec = 500;
if (ls && ls -> sp)
tty_hangup (ls -> sp, msec);
}
static void
do_send (Bool dcv)
{
int ret;
lua_Object obj;
char *str;
ret = 0;
if (((obj = lua_getparam (1)) != LUA_NOOBJECT) &&
lua_isstring (obj) && (str = lua_getstring (obj)))
if (ls && ls -> sp) {
if (dcv)
str = scr_convert (ls, str);
if (str) {
if (tty_send_string (ls -> sp, str) != -1)
ret = 1;
if (dcv)
free (str);
}
}
if (ret)
lua_pushnumber (1.0);
else
lua_pushnil ();
}
static void
lua_send (void)
{
do_send (False);
}
static void
lua_csend (void)
{
do_send (True);
}
static void
lua_expect (void)
{
int ret;
lua_Object obj;
int tout;
char *str;
int cnt, siz;
char **ex;
int *len;
int start;
int n;
if (((obj = lua_getparam (1)) != LUA_NOOBJECT) && lua_isnumber (obj)) {
tout = (int) lua_getnumber (obj);
start = 2;
} else {
tout = 5;
start = 1;
}
ex = NULL;
cnt = 0;
siz = 0;
while (((obj = lua_getparam (start)) != LUA_NOOBJECT) &&
lua_isstring (obj) && (str = lua_getstring (obj))) {
if (cnt >= siz) {
siz += 4;
if (! (ex = (char **) Realloc (ex, (siz + 2) * sizeof (char *))))
break;
}
if (ex[cnt] = strdup (str))
++cnt;
}
ret = -1;
if (ex) {
ex[cnt] = NULL;
if ((cnt > 0) && (len = (int *) malloc ((cnt + 1) * sizeof (int)))) {
for (n = 0; n < cnt; ++n)
len[n] = strlen (ex[n]);
len[cnt] = 0;
if (ls && ls -> sp)
ret = tty_expect_list (ls -> sp, tout, ex, len);
free (len);
for (n = 0; n < cnt; ++n)
free (ex[n]);
}
free (ex);
}
lua_pushnumber ((double) ret);
}
static void
lua_send_expect (void)
{
int ret;
lua_Object obj;
int tout;
char *str;
ret = 0;
if ((obj = lua_getparam (1)) != LUA_NOOBJECT) {
if (lua_isnumber (obj)) {
tout = (int) lua_getnumber (obj);
obj = lua_getparam (2);
}
if ((obj != LUA_NOOBJECT) && lua_isstring (obj) && (str = lua_getstring (obj)))
if (ls && ls -> sp && (tty_send_expect (ls -> sp, tout, str, NULL) != -1))
ret = 1;
}
if (ret)
lua_pushnumber (1.0);
else
lua_pushnil ();
}
static void
lua_drain (void)
{
lua_Object obj;
int sec;
if (((obj = lua_getparam (1)) != LUA_NOOBJECT) && lua_isnumber (obj))
sec = (int) lua_getnumber (obj);
else
sec = 1;
if (ls && ls -> sp)
tty_drain (ls -> sp, sec);
}
static void
lua_cvdef (void)
{
lua_Object obj1, obj2;
char *src, *dst;
int n;
if (ls) {
if (! ls -> ctab)
ls -> ctab = cv_new ();
if (ls -> ctab)
if (((obj1 = lua_getparam (1)) != LUA_NOOBJECT) && lua_isstring (obj1) && (src = lua_getstring (obj1))) {
if ((obj2 = lua_getparam (2)) == LUA_NOOBJECT)
cv_undefine (ls -> ctab, (char_t) *src);
else if (lua_isstring (obj2) && (dst = lua_getstring (obj2)))
cv_define (ls -> ctab, (char_t) *src, (char_t) *dst);
else if (lua_isnumber (obj2)) {
n = (int) lua_getnumber (obj2);
if (n < 0)
cv_invalid (ls -> ctab, (char_t) *src);
else
cv_define (ls -> ctab, (char_t) *src, (char_t) n);
}
}
}
}
static void
lua_conv (void)
{
char *ret;
lua_Object obj;
char *str;
ret = NULL;
if (((obj = lua_getparam (1)) != LUA_NOOBJECT) && lua_isstring (obj) && (str = lua_getstring (obj)))
if (ls)
ret = scr_convert (ls, str);
if (ret) {
lua_pushstring (ret);
free (ret);
} else
lua_pushnil ();
}
/*}}}*/
/*{{{ init/deinit */
static int
lua_init (script *s, char *libdir)
{
char *fname;
if (! isinit) {
iolib_open ();
strlib_open ();
mathlib_open ();
lua_pushnumber (lua_no_err); lua_storeglobal ("NO_ERR");
lua_pushnumber (lua_err_fail); lua_storeglobal ("ERR_FAIL");
lua_pushnumber (lua_err_fatal); lua_storeglobal ("ERR_FATAL");
lua_pushnumber (lua_err_abort); lua_storeglobal ("ERR_ABORT");
/* void logger (string str); */
lua_register ("logger", lua_logger);
/* void setcb ([string sep[, string|function func]]); */
lua_register ("setcb", lua_setcb);
/* string|nil get_line (void); */
lua_register ("get_line", lua_get_line);
/* void hangup ([num sec]); */
lua_register ("hangup", lua_hangup);
/* num|nil send (string line); */
lua_register ("send", lua_send);
/* num|nil csend (string line); */
lua_register ("csend", lua_csend);
/* num expect (num tout, string, s1, ..., string sn); */
lua_register ("expect", lua_expect);
/* num|nil send_expect (num tout, string str); */
lua_register ("send_expect", lua_send_expect);
/* void drain ([num sec]); */
lua_register ("drain", lua_drain);
/* void cvdef (string src[, string|num dst]); */
lua_register ("cvdef", lua_cvdef);
/* string|nil conv (string str); */
lua_register ("conv", lua_conv);
if (libdir && (fname = malloc (strlen (libdir) + sizeof (STARTUP) + 4))) {
sprintf (fname, "%s/%s", libdir, STARTUP);
if (access (fname, R_OK) != -1)
lua_dofile (fname);
free (fname);
}
lline = NULL;
lsiz = 0;
isinit = True;
}
return NO_ERR;
}
static void
lua_deinit (script *s)
{
if (lline) {
free (lline);
lline = NULL;
lsiz = 0;
}
}
/*}}}*/
/*{{{ execution */
static int
lua_execute (script *s, char *func, char *parm)
{
int err;
lua_Object obj;
double ret;
err = NO_ERR;
if ((obj = lua_getglobal (func)) && lua_isfunction (obj)) {
ls = s;
lua_beginblock ();
lua_pushnumber ((double) s -> delay.day); lua_storeglobal ("delay_day");
lua_pushnumber ((double) s -> delay.mon); lua_storeglobal ("delay_mon");
lua_pushnumber ((double) s -> delay.year); lua_storeglobal ("delay_year");
lua_pushnumber ((double) s -> delay.hour); lua_storeglobal ("delay_hour");
lua_pushnumber ((double) s -> delay.min); lua_storeglobal ("delay_min");
lua_pushnumber ((double) s -> delay.sec); lua_storeglobal ("delay_sec");
lua_pushnumber ((double) s -> expire.day); lua_storeglobal ("expire_day");
lua_pushnumber ((double) s -> expire.mon); lua_storeglobal ("expire_mon");
lua_pushnumber ((double) s -> expire.year); lua_storeglobal ("expire_year");
lua_pushnumber ((double) s -> expire.hour); lua_storeglobal ("expire_hour");
lua_pushnumber ((double) s -> expire.min); lua_storeglobal ("expire_min");
lua_pushnumber ((double) s -> expire.sec); lua_storeglobal ("expire_sec");
lua_pushnumber ((double) s -> rds); lua_storeglobal ("rds");
if (parm)
lua_pushstring (parm);
else
lua_pushnil ();
if (lua_callfunction (obj))
err = ERR_FATAL;
else if ((obj = lua_getresult (1)) && (obj != LUA_NOOBJECT)) {
ret = lua_getnumber (obj);
if (ret == lua_no_err)
err = NO_ERR;
else if (ret == lua_err_fail)
err = ERR_FAIL;
else if (ret == lua_err_fatal)
err = ERR_FATAL;
else if (ret == lua_err_abort)
err = ERR_ABORT;
}
lua_endblock ();
if (ls -> sp)
tty_set_line_callback (ls -> sp, NULL, NULL, NULL);
ls = NULL;
}
return err;
}
/*}}}*/
/*{{{ loading */
static int
lua_load_string (script *s, char *scr)
{
return lua_dostring (scr) ? ERR_FATAL : NO_ERR;
}
static int
lua_load_file (script *s, char *fname)
{
return lua_dofile (fname) ? ERR_FATAL : NO_ERR;
}
/*}}}*/
/*{{{ preinit/postdeinit/scriptentry */
static int
lua_preinit (char *libdir)
{
return lua_init (NULL, libdir);
}
static void
lua_postdeinit (void)
{
lua_deinit (NULL);
}
funcs flua = {
"Lua",
lua_init,
lua_deinit,
lua_execute,
lua_load_string,
lua_load_file,
lua_preinit,
lua_postdeinit
};
/*}}}*/
# endif /* SCRIPT_LUA */