[ruamoko] Add support for cbuf handling

I'm not sure how this will turn out, but the idea is ruamoko code will
be able to create its own scripting "language".
This commit is contained in:
Bill Currie 2023-06-14 20:25:50 +09:00
parent 140fe93a9c
commit 6f04c555a4
7 changed files with 337 additions and 31 deletions

View file

@ -64,22 +64,22 @@ typedef struct cbuf_s {
CBUF_STATE_JUNK // Buffer can be freed or reused
} state;
int (*unknown_command)(void); // handle unkown commands. !0 = handled
bool strict; // Should we tolerate unknown commands?
int (*unknown_command)(void); // handle unkown commands. !0 = handled
double resumetime; // Time when stack can be executed again
void *data; // Pointer to interpreter data
} cbuf_t;
typedef struct cbuf_interpreter_s {
void (*construct) (struct cbuf_s *cbuf);
void (*destruct) (struct cbuf_s *cbuf);
void (*reset) (struct cbuf_s *cbuf);
void (*add) (struct cbuf_s *cbuf, const char *str);
void (*insert) (struct cbuf_s *cbuf, const char *str);
void (*execute) (struct cbuf_s *cbuf);
void (*execute_sets) (struct cbuf_s *cbuf);
const char** (*complete) (struct cbuf_s *cbuf, const char *str);
void (*construct) (cbuf_t *cbuf);
void (*destruct) (cbuf_t *cbuf);
void (*reset) (cbuf_t *cbuf);
void (*add) (cbuf_t *cbuf, const char *str);
void (*insert) (cbuf_t *cbuf, const char *str);
void (*execute) (cbuf_t *cbuf);
void (*execute_sets) (cbuf_t *cbuf);
const char** (*complete) (cbuf_t *cbuf, const char *str);
} cbuf_interpreter_t;
extern cbuf_t *cbuf_active;
@ -88,7 +88,8 @@ cbuf_args_t *Cbuf_ArgsNew (void);
void Cbuf_ArgsDelete (cbuf_args_t *);
void Cbuf_ArgsAdd (cbuf_args_t *args, const char *arg);
cbuf_t * Cbuf_New (cbuf_interpreter_t *interp);
cbuf_t *_Cbuf_New (cbuf_interpreter_t *interp, void *data);
cbuf_t *Cbuf_New (cbuf_interpreter_t *interp);
void Cbuf_Delete (cbuf_t *cbuf);
void Cbuf_DeleteStack (cbuf_t *stack);

View file

@ -29,6 +29,7 @@
#endif
#include <stdlib.h>
#include <string.h>
#include "QF/cbuf.h"
#include "QF/idparse.h" // For now, use the id console parser
@ -37,12 +38,70 @@
#include "rua_internal.h"
typedef struct {
typedef struct bi_cbuf_interpreter_s {
pr_func_t construct;
pr_func_t destruct;
pr_func_t reset;
pr_func_t add;
pr_func_t insert;
pr_func_t execute;
pr_func_t complete;
} bi_cbuf_interpreter_t;
typedef struct biinterp_s {
struct cbuf_resources_s *res;
pr_ptr_t interp; // bi_cbuf_interpreter_t in progs memory
pr_ptr_t obj;
} biinterp_t;
typedef struct bicbuf_s {
struct bicbuf_s *next;
struct bicbuf_s **prev;
pr_ptr_t interp; // bi_cbuf_interpreter_t in progs memory
pr_ptr_t obj;
cbuf_t *cbuf;
struct cbuf_resources_s *res;
} bicbuf_t;
typedef struct cbuf_resources_s {
progs_t *pr;
cbuf_t *default_cbuf;
PR_RESMAP (bicbuf_t) cbuf_map;
PR_RESMAP (biinterp_t) interp_map;
bicbuf_t *cbufs;
} cbuf_resources_t;
static cbuf_t * __attribute__((pure))
static bicbuf_t *
cbuf_new (cbuf_resources_t *res)
{
return PR_RESNEW (res->cbuf_map);
}
static void
cbuf_free (cbuf_resources_t *res, bicbuf_t *cbuf)
{
PR_RESFREE (res->cbuf_map, cbuf);
}
static void
cbuf_reset (cbuf_resources_t *res)
{
PR_RESRESET (res->cbuf_map);
}
static bicbuf_t *
cbuf_get (cbuf_resources_t *res, int index)
{
return PR_RESGET (res->cbuf_map, index);
}
static int __attribute__ ((pure))
cbuf_index (cbuf_resources_t *res, bicbuf_t *cbuf)
{
return PR_RESINDEX (res->cbuf_map, cbuf);
}
static cbuf_t * __attribute__ ((pure))
_get_cbuf (progs_t *pr, cbuf_resources_t *res, int arg, const char *func)
{
qfZoneScoped (true);
@ -52,6 +111,10 @@ _get_cbuf (progs_t *pr, cbuf_resources_t *res, int arg, const char *func)
// a nil cbuf is valid only if the default cbuf has been set
cbuf = res->default_cbuf;
} else {
bicbuf_t *bicbuf = cbuf_get (res, arg);
if (bicbuf) {
cbuf = bicbuf->cbuf;
}
}
if (!cbuf) {
PR_RunError (pr, "%s: Invalid cbuf_t: %d", func, arg);
@ -63,6 +126,201 @@ _get_cbuf (progs_t *pr, cbuf_resources_t *res, int arg, const char *func)
#define bi(n) static void bi_##n (progs_t *pr, void *data)
static void
bi_cbi_construct (cbuf_t *cbuf)
{
cbuf_resources_t *res = cbuf->data;
bicbuf_t *bicbuf = cbuf_new (res);
*bicbuf = (bicbuf_t) {
.next = res->cbufs,
.prev = &res->cbufs,
.cbuf = cbuf,
.res = res,
};
if (res->cbufs) {
res->cbufs->prev = &bicbuf->next;
}
res->cbufs = bicbuf;
cbuf->data = bicbuf;
}
static void
bi__call_cbuf (progs_t *pr, pr_func_t func, pr_int_t cbuf)
{
PR_PushFrame (pr);
auto params = PR_SaveParams (pr);
pr->pr_argc = 1;
PR_SetupParams (pr, pr->pr_argc, 1);
P_INT (pr, 0) = cbuf;
PR_ExecuteProgram (pr, func);
PR_RestoreParams (pr, params);
PR_PopFrame (pr);
}
static void
bi__call_cbuf_string (progs_t *pr, pr_func_t func, pr_int_t cbuf,
const char *str)
{
PR_PushFrame (pr);
auto params = PR_SaveParams (pr);
pr->pr_argc = 2;
PR_SetupParams (pr, pr->pr_argc, 1);
P_INT (pr, 0) = cbuf;
P_STRING (pr, 1) = PR_SetTempString (pr, str);
PR_ExecuteProgram (pr, func);
PR_RestoreParams (pr, params);
PR_PopFrame (pr);
}
static void
bi_cbi_destruct (cbuf_t *cbuf)
{
bicbuf_t *bicbuf = cbuf->data;
auto res = bicbuf->res;
auto pr = res->pr;
int handle = cbuf_index (res, bicbuf);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->destruct) {
bi__call_cbuf (pr, interp->destruct, handle);
}
}
static void
bi_cbi_reset (cbuf_t *cbuf)
{
bicbuf_t *bicbuf = cbuf->data;
auto res = bicbuf->res;
auto pr = res->pr;
int handle = cbuf_index (res, bicbuf);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->reset) {
bi__call_cbuf (pr, interp->reset, handle);
}
}
static void
bi_cbi_add (cbuf_t *cbuf, const char *str)
{
bicbuf_t *bicbuf = cbuf->data;
auto res = bicbuf->res;
auto pr = res->pr;
int handle = cbuf_index (res, bicbuf);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->add) {
bi__call_cbuf_string (pr, interp->add, handle, str);
}
}
static void
bi_cbi_insert (cbuf_t *cbuf, const char *str)
{
bicbuf_t *bicbuf = cbuf->data;
auto res = bicbuf->res;
auto pr = res->pr;
int handle = cbuf_index (res, bicbuf);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->insert) {
bi__call_cbuf_string (pr, interp->insert, handle, str);
}
}
static void
bi_cbi_execute (cbuf_t *cbuf)
{
bicbuf_t *bicbuf = cbuf->data;
auto res = bicbuf->res;
auto pr = res->pr;
int handle = cbuf_index (res, bicbuf);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->execute) {
bi__call_cbuf (pr, interp->execute, handle);
}
}
static void
bi_cbi_execute_sets (cbuf_t *cbuf)
{
bicbuf_t *bicbuf = cbuf->data;
auto res = bicbuf->res;
auto pr = res->pr;
int handle = cbuf_index (res, bicbuf);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->execute) {
bi__call_cbuf (pr, interp->execute, handle);
}
}
static const char**
bi_cbi_complete (cbuf_t *cbuf, const char *str)
{
bicbuf_t *bicbuf = cbuf->data;
auto res = bicbuf->res;
auto pr = res->pr;
int handle = cbuf_index (res, bicbuf);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->complete) {
bi__call_cbuf_string (pr, interp->complete, handle, str);
}
return 0;
}
static cbuf_interpreter_t bi_cbuf_interp = {
.construct = bi_cbi_construct,
.destruct = bi_cbi_destruct,
.reset = bi_cbi_reset,
.add = bi_cbi_add,
.insert = bi_cbi_insert,
.execute = bi_cbi_execute,
.execute_sets = bi_cbi_execute_sets,
.complete = bi_cbi_complete,
};
bi(Cbuf_New)
{
cbuf_resources_t *res = data;
cbuf_t *cbuf = _Cbuf_New (&bi_cbuf_interp, res);
// bi_cbi_construct sets cbuf->data to the bicbuf_t object
bicbuf_t *bicbuf = cbuf->data;
int handle = cbuf_index (res, bicbuf);
bicbuf->interp = P_POINTER (pr, 0);
bicbuf->obj = P_POINTER (pr, 1);
auto interp = &G_PACKED (pr, bi_cbuf_interpreter_t, bicbuf->interp);
if (interp->construct) {
bi__call_cbuf (pr, interp->construct, handle);
}
R_INT (pr) = handle;
}
bi(Cbuf_Delete)
{
cbuf_resources_t *res = data;
bicbuf_t *cbuf = PR_RESGET (res->cbuf_map, P_INT (pr, 0));
if (!cbuf) {
PR_RunError (pr, "%s: Invalid cbuf_t", __FUNCTION__);
}
Cbuf_Delete (cbuf->cbuf);
if (cbuf->next) {
cbuf->next->prev = cbuf->prev;
}
*cbuf->prev = cbuf->next;
cbuf_free (res, cbuf);
}
bi(Cbuf_Reset)
{
cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0));
Cbuf_Reset (cbuf);
}
bi(Cbuf_AddText)
{
qfZoneScoped (true);
@ -86,6 +344,12 @@ bi(Cbuf_Execute)
Cbuf_Execute (cbuf);
}
bi(Cbuf_Execute_Stack)
{
cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0));
Cbuf_Execute_Stack (cbuf);
}
bi(Cbuf_Execute_Sets)
{
qfZoneScoped (true);
@ -93,10 +357,32 @@ bi(Cbuf_Execute_Sets)
Cbuf_Execute_Sets (cbuf);
}
#undef bi
#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}}
#define p(type) PR_PARAM(type)
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
static builtin_t builtins[] = {
bi(Cbuf_New, 2, p(ptr), p(ptr)),
bi(Cbuf_Delete, 1, p(ptr)),
bi(Cbuf_Reset, 1, p(ptr)),
bi(Cbuf_AddText, 2, p(ptr), p(string)),
bi(Cbuf_InsertText, 2, p(ptr), p(string)),
bi(Cbuf_Execute, 1, p(ptr)),
bi(Cbuf_Execute_Stack, 1, p(ptr)),
bi(Cbuf_Execute_Sets, 1, p(ptr)),
{0}
};
static void
bi_cbuf_clear (progs_t *pr, void *data)
{
qfZoneScoped (true);
cbuf_resources_t *res = data;
for (bicbuf_t *cbuf = res->cbufs; cbuf; cbuf = cbuf->next) {
Cbuf_Delete (cbuf->cbuf);
}
res->cbufs = 0;
cbuf_reset (res);
}
static void
@ -106,18 +392,6 @@ bi_cbuf_destroy (progs_t *pr, void *data)
free (data);
}
#undef bi
#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}}
#define p(type) PR_PARAM(type)
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
static builtin_t builtins[] = {
bi(Cbuf_AddText, 2, p(ptr), p(string)),
bi(Cbuf_InsertText, 2, p(ptr), p(string)),
bi(Cbuf_Execute, 1, p(ptr)),
bi(Cbuf_Execute_Sets, 1, p(ptr)),
{0}
};
void
RUA_Cbuf_Init (progs_t *pr, int secure)
{

View file

@ -499,6 +499,11 @@ bi_IMT_SetContext (progs_t *pr, void *_res)
IMT_SetContext (P_INT (pr, 0));
}
static void
bi_IMT_SetContextCbuf (progs_t *pr, void *_res)
{
}
static void
bi_IN_Binding_HandleEvent (progs_t *pr, void *_res)
{
@ -568,6 +573,7 @@ static builtin_t builtins[] = {
bi(IMT_CreateContext, 1, p(string)),
bi(IMT_GetContext, 0),
bi(IMT_SetContext, 1, p(int)),
bi(IMT_SetContextCbuf, 2, p(int), p(int)),
bi(IN_Binding_HandleEvent, 1, p(ptr)),

View file

@ -89,17 +89,27 @@ Cbuf_ArgsAdd (cbuf_args_t *args, const char *arg)
args->argc++;
}
VISIBLE cbuf_t *
_Cbuf_New (cbuf_interpreter_t *interp, void *data)
{
cbuf_t *cbuf = malloc (sizeof (cbuf_t));
*cbuf = (cbuf_t) {
.args = Cbuf_ArgsNew (),
.interpreter = interp,
.data = data,
};
if (interp->construct) {
interp->construct (cbuf);
}
return cbuf;
}
VISIBLE cbuf_t *
Cbuf_New (cbuf_interpreter_t *interp)
{
qfZoneScoped (true);
cbuf_t *cbuf = calloc (1, sizeof (cbuf_t));
cbuf->args = Cbuf_ArgsNew ();
cbuf->interpreter = interp;
if (interp->construct)
interp->construct (cbuf);
return cbuf;
return _Cbuf_New (interp, nullptr);
}
VISIBLE void

View file

@ -2,10 +2,23 @@
#define __ruamoko_cbuf_h
typedef @handle cbuf_h cbuf_t;
typedef struct cbuf_interpreter_s {
void (*construct) (cbuf_t cbuf);
void (*destruct) (cbuf_t cbuf);
void (*reset) (cbuf_t cbuf);
void (*add) (cbuf_t cbuf, string str);
void (*insert) (cbuf_t cbuf, string str);
void (*execute) (cbuf_t cbuf);
string *(*complete) (cbuf_t cbuf, string str);
} cbuf_interpreter_t;
@extern cbuf_t Cbuf_New (cbuf_interpreter_t *interpreter, void *obj);
@extern void Cbuf_Delete (cbuf_t cbuf);
@extern void Cbuf_Reset (cbuf_t cbuf);
@extern void Cbuf_AddText (cbuf_t cbuf, string text);
@extern void Cbuf_InsertText (cbuf_t cbuf, string text);
@extern void Cbuf_Execute (cbuf_t cbuf);
@extern void Cbuf_Execute_Stack (cbuf_t cbuf);
@extern void Cbuf_Execute_Sets (cbuf_t cbuf);
#endif//__ruamoko_cbuf_h

View file

@ -44,6 +44,7 @@ typedef void (*axis_listener_t) (void *data, in_axis_t *axis);//FIXME const
int IMT_CreateContext (string name);
int IMT_GetContext (void);
void IMT_SetContext (int ctx);
void IMT_SetContextCbuf (int ctx, @handle cbuf_h cbuf);
/*bool*/int IN_Binding_HandleEvent (/*const*/ struct IE_event_s *ie_event);
#endif//__ruamoko_input_h

View file

@ -42,6 +42,7 @@ void IN_AxisRemoveListener (in_axis_t *axis, IMP listener, id obj) = #0;
int IMT_CreateContext (string name) = #0;
int IMT_GetContext (void) = #0;
void IMT_SetContext (int ctx) = #0;
void IMT_SetContextCbuf (int ctx, @handle cbuf_h cbuf) = #0;
/*bool*/int IN_Binding_HandleEvent (/*const*/ struct IE_event_s *ie_event) = #0;