M hlog/common/config.c +8 -5
@@ 120,6 120,7 @@ static int process_config(lua_State *L,
int load_config(int data_dir_fd, struct qso *template, const char *mode)
{
+ struct xlua_state *lua;
char error[128];
lua_State *L;
int ret;
@@ 128,13 129,15 @@ int load_config(int data_dir_fd, struct
qso_line_init_defaults();
/* load the config; it should return a table with desired settings */
- L = xlua_init_at(data_dir_fd, DATA_DIR_CONFIG_FNAME, 1, error,
- sizeof(error));
- if (IS_ERR(L)) {
+ lua = xlua_init_at(data_dir_fd, DATA_DIR_CONFIG_FNAME, 1, error,
+ sizeof(error));
+ if (IS_ERR(lua)) {
fprintf(stderr, "Error: failed to read config: %s\n", error);
- return PTR_ERR(L);
+ return PTR_ERR(lua);
}
+ L = xlua_get_state(lua);
+
switch (lua_type(L, -1)) {
case LUA_TTABLE:
/* got a table - process it */
@@ 156,7 159,7 @@ int load_config(int data_dir_fd, struct
ret = 0;
err_lua:
- lua_close(L);
+ xlua_put_and_close(lua, L);
if (ret)
fprintf(stderr, "Error: failed to load config: %s\n",
M hlog/contest.c +10 -10
@@ 176,8 176,8 @@ static void stop_listeners(const char *g
announce_stop();
}
-static int do_export(lua_State *L, const struct contest_params *params,
- const char *outdir)
+static int do_export(struct xlua_state *lua,
+ const struct contest_params *params, const char *outdir)
{
char error[128];
int ret;
@@ 185,7 185,7 @@ static int do_export(lua_State *L, const
printf("Exporting %s entries to %s...\n", str_cstr(params->name),
outdir);
- ret = script_event_export(L, outdir, error, sizeof(error));
+ ret = script_event_export(lua, outdir, error, sizeof(error));
if (ret)
fprintf(stderr, "Error: Failed to export log: %s\n",
error);
@@ 206,7 206,7 @@ int main(int argc, char **argv)
uint32_t rig_model;
uint16_t rig_port;
const char *gpsd_port;
- lua_State *L;
+ struct xlua_state *lua;
char *export;
int ret;
int opt;
@@ 383,18 383,18 @@ int main(int argc, char **argv)
goto err_listen;
}
- L = script_load(&wfields, &nwfields, &contest_params);
- if (IS_ERR(L)) {
- ret = PTR_ERR(L);
+ lua = script_load(&wfields, &nwfields, &contest_params);
+ if (IS_ERR(lua)) {
+ ret = PTR_ERR(lua);
goto err_free;
}
if (!export)
- ret = contest_run(L, wfields, nwfields);
+ ret = contest_run(lua, wfields, nwfields);
else
- ret = do_export(L, &contest_params, export);
+ ret = do_export(lua, &contest_params, export);
- lua_close(L);
+ xlua_close(lua);
err_free:
if (!export)
M hlog/contest/contest.h +5 -4
@@ 42,7 42,8 @@ struct contest_params {
};
extern int contest_init(struct contest_params *contest_params);
-extern int contest_run(lua_State *L, struct xfield_def *wfields, size_t nwfields);
+extern int contest_run(struct xlua_state *lua, struct xfield_def *wfields,
+ size_t nwfields);
extern void contest_cleanup(void);
/*
@@ 56,13 57,13 @@ extern struct recent recent_list; /* all
/*
* interactive form UI
*/
-extern void ui_work_dispatch(lua_State *L, int ch, struct qso **qso);
-extern void ui_current_dispatch(lua_State *L, int ch, struct qso **qso);
+extern void ui_work_dispatch(struct xlua_state *lua, int ch, struct qso **qso);
+extern void ui_current_dispatch(struct xlua_state *lua, int ch, struct qso **qso);
/*
* contact handling
*/
-extern int init_contact(lua_State *L, struct qso **qso, char *error,
+extern int init_contact(struct xlua_state *lua, struct qso **qso, char *error,
size_t errlen);
extern int save_qso_and_update_index(struct qso *qso, const char *source);
M hlog/contest/script.c +37 -14
@@ 313,9 313,10 @@ int script_exists(const struct contest_p
return xlua_script_find(file, NULL, NULL);
}
-lua_State *script_load(struct xfield_def **fields, size_t *nfields,
- const struct contest_params *params)
+struct xlua_state *script_load(struct xfield_def **fields, size_t *nfields,
+ const struct contest_params *params)
{
+ struct xlua_state *lua;
char error[128];
char file[128];
lua_State *L;
@@ 326,12 327,14 @@ lua_State *script_load(struct xfield_def
snprintf(file, sizeof(file), "contests/%s.lua", str_cstr(params->name));
- L = xlua_init_script(file, 1, error, sizeof(error));
- if (IS_ERR(L)) {
+ lua = xlua_init_script(file, 1, error, sizeof(error));
+ if (IS_ERR(lua)) {
printf("Error: failed to initialize lua: %s\n", error);
- return L;
+ return lua;
}
+ L = xlua_get_state(lua);
+
if (lua_type(L, -1) != LUA_TTABLE) {
fprintf(stderr, "Error: contest script init failed: "
"expected table, got %s\n",
@@ 382,10 385,12 @@ lua_State *script_load(struct xfield_def
ASSERT_LUA_STACK(L, 0);
- return L;
+ xlua_put_state(lua, L);
+
+ return lua;
err:
- lua_close(L);
+ xlua_put_and_close(lua, L);
return ERR_PTR(ret);
}
@@ 444,16 449,20 @@ static int script_event_startup(lua_Stat
return ret;
}
-int script_event_export(lua_State *L, const char *outdir, char *error,
+int script_event_export(struct xlua_state *lua, const char *outdir, char *error,
size_t errlen)
{
+ lua_State *L;
int type;
int ret;
+ L = xlua_get_state(lua);
+
type = lua_getfield(L, LUA_REGISTRYINDEX, EVENT_EXPORT);
if (type == LUA_TNIL) {
lua_pop(L, 1);
ASSERT_LUA_STACK(L, 0);
+ xlua_put_state(lua, L);
snprintf(error, errlen, "Contest doesn't define an export "
"function");
return -ENOTSUP;
@@ 465,10 474,12 @@ int script_event_export(lua_State *L, co
ASSERT_LUA_STACK(L, 0);
+ xlua_put_state(lua, L);
+
return ret;
}
-int script_event_field_change(lua_State *L, struct qso *qso,
+int script_event_field_change(struct xlua_state *lua, struct qso *qso,
struct xform *form,
char *error, size_t errlen,
void (*fcb)(struct xform *, const char *,
@@ 476,14 487,18 @@ int script_event_field_change(lua_State
void (*acb)(struct xform *, const char *,
const char *))
{
+ lua_State *L;
size_t i;
int type;
int ret;
+ L = xlua_get_state(lua);
+
type = lua_getfield(L, LUA_REGISTRYINDEX, EVENT_FIELD_CHANGED);
if (type == LUA_TNIL) {
lua_pop(L, 1);
ASSERT_LUA_STACK(L, 0);
+ xlua_put_state(lua, L);
return 0;
}
@@ 530,19 545,25 @@ int script_event_field_change(lua_State
out:
ASSERT_LUA_STACK(L, 0);
+ xlua_put_state(lua, L);
+
return ret;
}
-static int event_qso(lua_State *L, struct qso *qso, const char *event,
+static int event_qso(struct xlua_state *lua, struct qso *qso, const char *event,
char *error, size_t errlen)
{
+ lua_State *L;
int type;
int ret;
+ L = xlua_get_state(lua);
+
type = lua_getfield(L, LUA_REGISTRYINDEX, event);
if (type == LUA_TNIL) {
lua_pop(L, 1);
ASSERT_LUA_STACK(L, 0);
+ xlua_put_state(lua, L);
return 0;
}
@@ 550,17 571,19 @@ static int event_qso(lua_State *L, struc
ASSERT_LUA_STACK(L, 0);
+ xlua_put_state(lua, L);
+
return ret;
}
-int script_event_qso_init(lua_State *L, struct qso *qso,
+int script_event_qso_init(struct xlua_state *lua, struct qso *qso,
char *error, size_t errlen)
{
- return event_qso(L, qso, EVENT_QSO_INIT, error, errlen);
+ return event_qso(lua, qso, EVENT_QSO_INIT, error, errlen);
}
-int script_event_qso_done(lua_State *L, struct qso *qso,
+int script_event_qso_done(struct xlua_state *lua, struct qso *qso,
char *error, size_t errlen)
{
- return event_qso(L, qso, EVENT_QSO_DONE, error, errlen);
+ return event_qso(lua, qso, EVENT_QSO_DONE, error, errlen);
}
M hlog/contest/script.h +9 -8
@@ 1,5 1,5 @@
/*
- * Copyright (c) 2020-2022 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright (c) 2020-2022,2024 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ 28,22 28,23 @@
#include "../common/xform.h"
extern int script_exists(const struct contest_params *params);
-extern lua_State *script_load(struct xfield_def **fields, size_t *nfields,
- const struct contest_params *params);
+extern struct xlua_state *script_load(struct xfield_def **fields,
+ size_t *nfields,
+ const struct contest_params *params);
/* events */
-extern int script_event_field_change(lua_State *L, struct qso *qso,
+extern int script_event_field_change(struct xlua_state *lua, struct qso *qso,
struct xform *form, char *error,
size_t errlen,
void (*fcb)(struct xform *, const char *,
const char *),
void (*acb)(struct xform *, const char *,
const char *));
-extern int script_event_qso_init(lua_State *L, struct qso *qso,
+extern int script_event_qso_init(struct xlua_state *lua, struct qso *qso,
char *error, size_t errlen);
-extern int script_event_qso_done(lua_State *L, struct qso *qso,
+extern int script_event_qso_done(struct xlua_state *lua, struct qso *qso,
char *error, size_t errlen);
-extern int script_event_export(lua_State *L, const char *outdir, char *error,
- size_t errlen);
+extern int script_event_export(struct xlua_state *lua, const char *outdir,
+ char *error, size_t errlen);
#endif
M hlog/contest/ui-work.c +13 -13
@@ 65,7 65,7 @@ static void wrapped_set_annunciator_colo
}
}
-static void field_changed(lua_State *L, struct qso *qso)
+static void field_changed(struct xlua_state *lua, struct qso *qso)
{
struct xform *form = &work; /* for simplicity */
char error[128];
@@ 75,7 75,7 @@ static void field_changed(lua_State *L,
if (!qso->start.have)
ASSERT0(qso_set_datetime(qso, true, NULL));
- ret = script_event_field_change(L, qso, form,
+ ret = script_event_field_change(lua, qso, form,
error, sizeof(error),
wrapped_set_field_buffer,
wrapped_set_annunciator_color);
@@ 85,7 85,7 @@ static void field_changed(lua_State *L,
}
}
-static void abort_qso(lua_State *L, struct qso **_qso)
+static void abort_qso(struct xlua_state *lua, struct qso **_qso)
{
struct xform *form = &work; /* for simplicity */
char error[128];
@@ 102,14 102,14 @@ static void abort_qso(lua_State *L, stru
xform_driver(form, XFORM_REQ_FIRST_FIELD);
/* initialize the qso */
- ret = init_contact(L, _qso, error, sizeof(error));
+ ret = init_contact(lua, _qso, error, sizeof(error));
if (ret) {
msg_print(MSG_SCRIPT, CE_ERROR, "%s", error);
status_display_error("%s", error);
}
}
-static void end_qso(lua_State *L, struct qso **_qso)
+static void end_qso(struct xlua_state *lua, struct qso **_qso)
{
struct xform *form = &work; /* for simplicity */
struct qso *qso = *_qso;
@@ 117,7 117,7 @@ static void end_qso(lua_State *L, struct
size_t i;
int ret;
- ret = script_event_qso_done(L, qso, error, sizeof(error));
+ ret = script_event_qso_done(lua, qso, error, sizeof(error));
if (ret)
goto err;
@@ 153,7 153,7 @@ static void end_qso(lua_State *L, struct
xform_driver(form, XFORM_REQ_FIRST_FIELD);
/* start the next qso */
- ret = init_contact(L, _qso, error, sizeof(error));
+ ret = init_contact(lua, _qso, error, sizeof(error));
if (ret)
msg_print(MSG_SCRIPT, CE_ERROR, "%s", error);
@@ 164,7 164,7 @@ err:
status_display_error("%s", error);
}
-void ui_work_dispatch(lua_State *L, int ch, struct qso **qso)
+void ui_work_dispatch(struct xlua_state *lua, int ch, struct qso **qso)
{
struct xform *form = &work; /* for simplicity */
@@ 178,33 178,33 @@ void ui_work_dispatch(lua_State *L, int
case '\b':
case 127:
xform_driver(form, XFORM_REQ_DEL_PREV);
- field_changed(L, *qso); /* inform script */
+ field_changed(lua, *qso); /* inform script */
recent_invalidate(&recent_work_list);
break;
case KEY_DC:
xform_driver(form, XFORM_REQ_DEL_THIS);
- field_changed(L, *qso); /* inform script */
+ field_changed(lua, *qso); /* inform script */
recent_invalidate(&recent_work_list);
break;
/* navigate between forms */
case KEY_ENTER:
case '\n':
- end_qso(L, qso);
+ end_qso(lua, qso);
recent_invalidate(&recent_work_list);
recent_invalidate(&recent_list);
break;
case '\x1b': /* escape */
- abort_qso(L, qso);
+ abort_qso(lua, qso);
recent_invalidate(&recent_work_list);
break;
default:
if (!iscntrl(ch)) {
xform_driver(form, ch);
- field_changed(L, *qso); /* inform script */
+ field_changed(lua, *qso); /* inform script */
recent_invalidate(&recent_work_list);
} else {
beep();
M hlog/contest/ui.c +7 -5
@@ 323,7 323,8 @@ static struct xform_palette palette = {
/*
* contact setup
*/
-int init_contact(lua_State *L, struct qso **qso, char *error, size_t errlen)
+int init_contact(struct xlua_state *lua, struct qso **qso, char *error,
+ size_t errlen)
{
struct qso *tmp;
@@ 342,7 343,7 @@ int init_contact(lua_State *L, struct qs
xuuid_unparse(&tmp->uuid, tmp->uuid_str);
/* let the script finish up setup */
- return script_event_qso_init(L, tmp, error, errlen);
+ return script_event_qso_init(lua, tmp, error, errlen);
}
static void __get_qso_ts(const struct time *ts, size_t field)
@@ 941,7 942,8 @@ void contest_cleanup(void)
MXDESTROY(&location_lock);
}
-int contest_run(lua_State *L, struct xfield_def *_wfields, size_t _nwfields)
+int contest_run(struct xlua_state *lua, struct xfield_def *_wfields,
+ size_t _nwfields)
{
char error[128];
uint64_t gen;
@@ 954,7 956,7 @@ int contest_run(lua_State *L, struct xfi
tweak_script_colors();
/* set up the current contact struct qso */
- ret = init_contact(L, &contact, error, sizeof(error));
+ ret = init_contact(lua, &contact, error, sizeof(error));
if (ret) {
fprintf(stderr, "Error: Failed to initialize QSO: %s\n",
error);
@@ 996,7 998,7 @@ int contest_run(lua_State *L, struct xfi
if (ch != ERR) {
status_display_error(""); /* clear the error string */
- ui_work_dispatch(L, ch, &contact);
+ ui_work_dispatch(lua, ch, &contact);
}
draw_location();
M hlog/hlog.c +7 -4
@@ 1978,20 1978,23 @@ static int load_index(void)
static void print_stats(void)
{
struct index_iter_ctx ctx;
+ struct xlua_state *lua;
+ lua_State *L;
struct qso *qso;
char error[128];
- lua_State *L;
bool failed;
int ret;
printf("Global call statistics:\n");
- L = xlua_init_script("startup-stats.lua", 0, error, sizeof(error));
- if (IS_ERR(L)) {
+ lua = xlua_init_script("startup-stats.lua", 0, error, sizeof(error));
+ if (IS_ERR(lua)) {
printf("Error: failed to initialize lua: %s\n", error);
return;
}
+ L = xlua_get_state(lua);
+
/* iterate over all the QSOs */
for (qso = index_iter_history_start(&ctx, true), failed = false;
qso;
@@ 2012,7 2015,7 @@ static void print_stats(void)
if (ret)
printf("Error: %s\n", error);
- lua_close(L);
+ xlua_put_and_close(lua, L);
}
static void state_free(void)
M run-script/run-script.c +8 -5
@@ 1,5 1,5 @@
/*
- * Copyright (c) 2020-2021 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright (c) 2020-2021,2024 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ 37,21 37,24 @@ static int data_dir_fd;
static void process(const char *scriptname)
{
+ struct xlua_state *lua;
+ lua_State *L;
char error[128];
- lua_State *L;
int ret;
- L = xlua_init(scriptname, 0, error, sizeof(error));
- if (IS_ERR(L)) {
+ lua = xlua_init(scriptname, 0, error, sizeof(error));
+ if (IS_ERR(lua)) {
printf("Error: failed to initialize lua: %s\n", error);
return;
}
+ L = xlua_get_state(lua);
+
ret = xlua_call(L, "main", 0, 0, error, sizeof(error));
if (ret)
printf("Error: failed to execute lua: %s\n", error);
- lua_close(L);
+ xlua_put_and_close(lua, L);
}
static void usage(const char *prog)
M xlua/include/hlog-lua/xlua.h +21 -7
@@ 1,5 1,5 @@
/*
- * Copyright (c) 2020-2022 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * Copyright (c) 2020-2022,2024 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ 48,11 48,19 @@
#define COPY_ERROR(L, idx, err, errlen) \
strcpy_safe(err, lua_tostring((L), (idx)), (errlen))
+struct xlua_state;
+
extern int lua2errno(int e);
-extern lua_State *xlua_init_at(int dirfd, const char *script_fname, int nresults,
- char *error, size_t errlen);
-extern lua_State *xlua_init_script(const char *script_name, int nresults,
- char *error, size_t errlen);
+extern struct xlua_state *xlua_init_at(int dirfd, const char *script_fname,
+ int nresults, char *error,
+ size_t errlen);
+extern struct xlua_state *xlua_init_script(const char *script_name,
+ int nresults, char *error,
+ size_t errlen);
+extern void xlua_close(struct xlua_state *lua);
+
+extern lua_State *xlua_get_state(struct xlua_state *lua);
+extern void xlua_put_state(struct xlua_state *lua, lua_State *L);
/* return raw script data */
extern int xlua_script_find(const char *name, const uint8_t **data_r,
@@ 86,12 94,18 @@ extern int xlua_pushqso(lua_State *L, st
extern int xlua_pushtime(lua_State *L, struct time *time, bool ro,
char *error, size_t errlen);
-static inline lua_State *xlua_init(const char *script_fname, int nresults,
- char *error, size_t errlen)
+static inline struct xlua_state *xlua_init(const char *script_fname,
+ int nresults, char *error,
+ size_t errlen)
{
return xlua_init_at(AT_FDCWD, script_fname, nresults, error, errlen);
}
+static inline void xlua_put_and_close(struct xlua_state *lua, lua_State *L)
+{
+ xlua_close(lua);
+}
+
static inline bool xlua_isstringornil(lua_State *L, int idx)
{
return lua_isnil(L, idx) || lua_isstring(L, idx);
M xlua/xlua-impl.h +4 -0
@@ 28,6 28,10 @@
#include <hlog/qso.h>
#include <hlog-lua/xlua.h>
+struct xlua_state {
+ lua_State *L;
+};
+
extern int xlua_load_script_internal(lua_State *L, const char *scriptname,
char *error, size_t errlen);
extern void xlua_merge_lua_funcs(lua_State *L, const char *scriptname);
M xlua/xlua.c +49 -18
@@ 223,50 223,64 @@ void xlua_merge_lua_funcs(lua_State *L,
ASSERT_LUA_STACK(L, orig_top);
}
-static lua_State *__xlua_init(const char *name, const uint8_t *data,
- size_t size, int nresults, char *error,
- size_t errlen)
+static struct xlua_state *__xlua_init(const char *name, const uint8_t *data,
+ size_t size, int nresults, char *error,
+ size_t errlen)
{
+ struct xlua_state *lua;
struct buffer buf;
lua_State *L;
int ret;
buffer_init_static(&buf, data, size, size, false);
- L = luaL_newstate();
- if (!L) {
- strcpy_safe(error, "failed to allocate lua state", errlen);
+ lua = malloc(sizeof(struct xlua_state));
+ if (!lua) {
+ strcpy_safe(error, "failed to allocate xlua state", errlen);
return ERR_PTR(-ENOMEM);
}
+ lua->L = luaL_newstate();
+ if (!lua->L) {
+ strcpy_safe(error, "failed to allocate lua state", errlen);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ L = lua->L;
+
luaL_openlibs(L);
xlua_register(L);
ret = lua_load(L, xlua_init_reader, &buf, name, NULL);
if (ret != LUA_OK)
- goto err;
+ goto err_free;
ret = lua_pcall(L, 0, nresults, 0);
if (ret)
- goto err;
+ goto err_free;
ASSERT_LUA_STACK(L, nresults);
- return L;
-err:
+ return lua;
+
+err_free:
COPY_ERROR(L, -1, error, errlen);
lua_close(L);
+err:
+ free(lua);
+
return ERR_PTR(lua2errno(ret));
}
-lua_State *xlua_init_at(int dirfd, const char *fname, int nresults, char *error,
- size_t errlen)
+struct xlua_state *xlua_init_at(int dirfd, const char *fname, int nresults,
+ char *error, size_t errlen)
{
- lua_State *L;
+ struct xlua_state *lua;
char *raw;
size_t size;
@@ 281,16 295,16 @@ lua_State *xlua_init_at(int dirfd, const
return ERR_CAST(raw);
}
- L = __xlua_init(fname, (const uint8_t *) raw, size, nresults, error,
- errlen);
+ lua = __xlua_init(fname, (const uint8_t *) raw, size, nresults, error,
+ errlen);
free(raw);
- return L;
+ return lua;
}
-lua_State *xlua_init_script(const char *scriptname, int nresults, char *error,
- size_t errlen)
+struct xlua_state *xlua_init_script(const char *scriptname, int nresults,
+ char *error, size_t errlen)
{
const uint8_t *data;
size_t size;
@@ 310,6 324,23 @@ lua_State *xlua_init_script(const char *
return __xlua_init(scriptname, data, size, nresults, error, errlen);
}
+void xlua_close(struct xlua_state *lua)
+{
+ lua_close(lua->L);
+
+ free(lua);
+}
+
+lua_State *xlua_get_state(struct xlua_state *lua)
+{
+ return lua->L;
+}
+
+void xlua_put_state(struct xlua_state *lua, lua_State *L)
+{
+ ASSERT3P(lua->L, ==, L);
+}
+
int xlua_call(lua_State *L, const char *funcname, int nargs, int nresults,
char *error, size_t errlen)
{