quakeforge/libs/ruamoko/rua_cbuf.c

412 lines
9.2 KiB
C
Raw Normal View History

/*
bi_cbuf.c
CSQC cbuf builtins
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include "QF/cbuf.h"
#include "QF/idparse.h" // For now, use the id console parser
#include "QF/progs.h"
#include "QF/ruamoko.h"
#include "rua_internal.h"
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 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);
cbuf_t *cbuf = 0;
if (arg == 0) {
// 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);
}
return cbuf;
}
#define get_cbuf(pr, res, arg) _get_cbuf(pr, res, arg, __FUNCTION__)
#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);
cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0));
const char *text = P_GSTRING (pr, 1);
Cbuf_AddText (cbuf, text);
}
bi(Cbuf_InsertText)
{
qfZoneScoped (true);
cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0));
const char *text = P_GSTRING (pr, 1);
Cbuf_InsertText (cbuf, text);
}
bi(Cbuf_Execute)
{
qfZoneScoped (true);
cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0));
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);
cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0));
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
bi_cbuf_destroy (progs_t *pr, void *data)
{
qfZoneScoped (true);
free (data);
}
void
RUA_Cbuf_Init (progs_t *pr, int secure)
{
qfZoneScoped (true);
2002-08-26 00:30:31 +00:00
cbuf_resources_t *res = calloc (sizeof (cbuf_resources_t), 1);
res->pr = pr;
PR_Resources_Register (pr, "Cbuf", res, bi_cbuf_clear, bi_cbuf_destroy);
PR_RegisterBuiltins (pr, builtins, res);
}
VISIBLE void
RUA_Cbuf_SetCbuf (progs_t *pr, cbuf_t *cbuf)
{
qfZoneScoped (true);
cbuf_resources_t *res = PR_Resources_Find (pr, "Cbuf");
res->default_cbuf = cbuf;
}