quakeforge/libs/ruamoko/rua_msgbuf.c
Bill Currie 973ae0ad54 [gamecode] Add PR_Shutdown for tearing down a VM
This is meant for a "permanent" tear-down before freeing the memory
holding the VM state or at program shutdown. As a consequence, builtin
sub-systems registering resources are now required to pass a "destroy"
function pointer that will be called just before the memory holding
those resources is freed by the VM resource manager (ie, the manager
owns the resource memory block, but each subsystem is responsible for
cleaning up any resources held within that block).

This even enhances thread-safety in rua_obj (there are some problems
with cmd, cvar, and gib).
2022-05-12 19:58:18 +09:00

492 lines
13 KiB
C

/*
bi_msgbuf.c
CSQC message buffer builtins
Copyright (C) 2012 Bill Currie <bill:taniwha.org>
Author: Bill Currie <bill:taniwha.org>
Date: 2012/2/6
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>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/msg.h"
#include "QF/progs.h"
#include "rua_internal.h"
typedef struct msgbuf_s {
struct msgbuf_s *next;
struct msgbuf_s **prev;
qmsg_t msg;
sizebuf_t sizebuf;
} msgbuf_t;
typedef struct {
PR_RESMAP (msgbuf_t) msgbuf_map;
} msgbuf_resources_t;
static msgbuf_t *
msgbuf_new (msgbuf_resources_t *res)
{
return PR_RESNEW (res->msgbuf_map);
}
static void
msgbuf_free (progs_t *pr, msgbuf_resources_t *res, msgbuf_t *msgbuf)
{
PR_Zone_Free (pr, msgbuf->sizebuf.data);
PR_RESFREE (res->msgbuf_map, msgbuf);
}
static void
msgbuf_reset (msgbuf_resources_t *res)
{
PR_RESRESET (res->msgbuf_map);
}
static inline msgbuf_t *
msgbuf_get (msgbuf_resources_t *res, int index)
{
return PR_RESGET(res->msgbuf_map, index);
}
static inline int __attribute__((pure))
msgbuf_index (msgbuf_resources_t *res, msgbuf_t *msgbuf)
{
return PR_RESINDEX(res->msgbuf_map, msgbuf);
}
static void
bi_msgbuf_clear (progs_t *pr, void *data)
{
msgbuf_resources_t *res = (msgbuf_resources_t *) data;
msgbuf_reset (res);
}
static void
bi_msgbuf_destroy (progs_t *pr, void *_res)
{
}
static int
alloc_msgbuf (msgbuf_resources_t *res, byte *buf, int size)
{
msgbuf_t *msgbuf = msgbuf_new (res);
if (!msgbuf)
return 0;
memset (&msgbuf->msg, 0, sizeof (msgbuf->msg));
msgbuf->msg.message = &msgbuf->sizebuf;
memset (&msgbuf->sizebuf, 0, sizeof (msgbuf->sizebuf));
msgbuf->sizebuf.data = buf;
msgbuf->sizebuf.maxsize = size;
return msgbuf_index (res, msgbuf);
}
static msgbuf_t * __attribute__((pure))
get_msgbuf (progs_t *pr, msgbuf_resources_t *res, const char *name, int msgbuf)
{
msgbuf_t *mb = msgbuf_get (res, msgbuf);
if (!mb)
PR_RunError (pr, "invalid msgbuf handle passed to %s", name + 3);
return mb;
}
static void
bi_MsgBuf_New (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf");
int size = P_INT (pr, 0);
byte *buf;
buf = PR_Zone_Malloc (pr, size);
R_INT (pr) = alloc_msgbuf (res, buf, size);
}
static void
bi_MsgBuf_Delete (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf");
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
msgbuf_free (pr, res, mb);
}
static void
bi_MsgBuf_FromFile (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
QFile *file = QFile_GetFile (pr, P_INT (pr, 1));
int bytes;
SZ_Clear (&mb->sizebuf);
bytes = Qread (file, mb->sizebuf.data, mb->sizebuf.maxsize);
mb->sizebuf.cursize = bytes;
MSG_BeginReading (&mb->msg);
}
static void
bi_MsgBuf_MaxSize (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_INT (pr) = mb->sizebuf.maxsize;
}
static void
bi_MsgBuf_CurSize (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_INT (pr) = mb->sizebuf.cursize;
}
static void
bi_MsgBuf_ReadCount (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_INT (pr) = mb->msg.readcount;
}
static void
bi_MsgBuf_DataPtr (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
byte *ptr = mb->sizebuf.data + mb->msg.readcount;
R_INT (pr) = ptr - (byte *) pr->pr_strings;
}
static void
bi_MsgBuf_Clear (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
SZ_Clear (&mb->sizebuf);
}
static void
bi_MsgBuf_WriteByte (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteByte (&mb->sizebuf, P_INT (pr, 1));
}
static void
bi_MsgBuf_WriteShort (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteShort (&mb->sizebuf, P_INT (pr, 1));
}
static void
bi_MsgBuf_WriteLong (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteLong (&mb->sizebuf, P_INT (pr, 1));
}
static void
bi_MsgBuf_WriteFloat (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteFloat (&mb->sizebuf, P_FLOAT (pr, 1));
}
static void
bi_MsgBuf_WriteString (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteString (&mb->sizebuf, P_GSTRING (pr, 1));
}
#if 0
static void
bi_MsgBuf_WriteBytes (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteBytes (&mb->sizebuf, P_INT (pr, 1));
}
#endif
static void
bi_MsgBuf_WriteCoord (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteCoord (&mb->sizebuf, P_FLOAT (pr, 1));
}
static void
bi_MsgBuf_WriteCoordV (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteCoordV (&mb->sizebuf, P_VECTOR (pr, 1));
}
static void
bi_MsgBuf_WriteCoordAngleV (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteCoordAngleV (&mb->sizebuf,
P_VECTOR (pr, 1), P_VECTOR (pr, 2));
}
static void
bi_MsgBuf_WriteAngle (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteAngle (&mb->sizebuf, P_FLOAT (pr, 1));
}
static void
bi_MsgBuf_WriteAngleV (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteAngleV (&mb->sizebuf, P_VECTOR (pr, 1));
}
static void
bi_MsgBuf_WriteAngle16 (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteAngle16 (&mb->sizebuf, P_FLOAT (pr, 1));
}
static void
bi_MsgBuf_WriteAngle16V (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteAngle16V (&mb->sizebuf, P_VECTOR (pr, 1));
}
static void
bi_MsgBuf_WriteUTF8 (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_WriteUTF8 (&mb->sizebuf, P_INT (pr, 1));
}
static void
bi_MsgBuf_BeginReading (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_BeginReading (&mb->msg);
}
static void
bi_MsgBuf_ReadByte (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_INT (pr) = MSG_ReadByte (&mb->msg);
}
static void
bi_MsgBuf_ReadShort (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_INT (pr) = MSG_ReadShort (&mb->msg);
}
static void
bi_MsgBuf_ReadLong (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_INT (pr) = MSG_ReadLong (&mb->msg);
}
static void
bi_MsgBuf_ReadFloat (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_FLOAT (pr) = MSG_ReadFloat (&mb->msg);
}
static void
bi_MsgBuf_ReadString (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
const char *str;
str = MSG_ReadString (&mb->msg);
RETURN_STRING (pr, str);
}
#if 0
static void
bi_MsgBuf_ReadBytes (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_ReadBytes (&mb->msg);
}
#endif
static void
bi_MsgBuf_ReadCoord (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_FLOAT (pr) = MSG_ReadCoord (&mb->msg);
}
static void
bi_MsgBuf_ReadCoordV (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_ReadCoordV (&mb->msg, R_VECTOR (pr));
}
static void
bi_MsgBuf_ReadCoordAngleV (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_ReadCoordAngleV (&mb->msg, P_VECTOR (pr, 1), P_VECTOR (pr, 2));
}
static void
bi_MsgBuf_ReadAngle (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_FLOAT (pr) = MSG_ReadAngle (&mb->msg);
}
static void
bi_MsgBuf_ReadAngleV (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_ReadAngleV (&mb->msg, R_VECTOR (pr));
}
static void
bi_MsgBuf_ReadAngle16 (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_FLOAT (pr) = MSG_ReadAngle16 (&mb->msg);
}
static void
bi_MsgBuf_ReadAngle16V (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
MSG_ReadAngle16V (&mb->msg, R_VECTOR (pr));
}
static void
bi_MsgBuf_ReadUTF8 (progs_t *pr, void *_res)
{
msgbuf_resources_t *res = _res;
msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0));
R_INT (pr) = MSG_ReadUTF8 (&mb->msg);
}
#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(MsgBuf_New, 1, p(int)),
bi(MsgBuf_Delete, 1, p(ptr)),
bi(MsgBuf_FromFile, 2, p(ptr), p(ptr)),
bi(MsgBuf_MaxSize, 1, p(ptr)),
bi(MsgBuf_CurSize, 1, p(ptr)),
bi(MsgBuf_ReadCount, 1, p(ptr)),
bi(MsgBuf_DataPtr, 1, p(ptr)),
bi(MsgBuf_Clear, 1, p(ptr)),
bi(MsgBuf_WriteByte, 2, p(ptr), p(int)),
bi(MsgBuf_WriteShort, 2, p(ptr), p(int)),
bi(MsgBuf_WriteLong, 2, p(ptr), p(int)),
bi(MsgBuf_WriteFloat, 2, p(ptr), p(float)),
bi(MsgBuf_WriteString, 2, p(ptr), p(string)),
// bi(MsgBuf_WriteBytes, _, _),
bi(MsgBuf_WriteCoord, 2, p(ptr), p(float)),
bi(MsgBuf_WriteCoordV, 2, p(ptr), p(vector)),
bi(MsgBuf_WriteCoordAngleV, 2, p(ptr), p(vector)),
bi(MsgBuf_WriteAngle, 2, p(ptr), p(float)),
bi(MsgBuf_WriteAngleV, 2, p(ptr), p(vector)),
bi(MsgBuf_WriteAngle16, 2, p(ptr), p(float)),
bi(MsgBuf_WriteAngle16V, 2, p(ptr), p(vector)),
bi(MsgBuf_WriteUTF8, 2, p(ptr), p(int)),
bi(MsgBuf_BeginReading, 1, p(ptr)),
bi(MsgBuf_ReadByte, 1, p(ptr)),
bi(MsgBuf_ReadShort, 1, p(ptr)),
bi(MsgBuf_ReadLong, 1, p(ptr)),
bi(MsgBuf_ReadFloat, 1, p(ptr)),
bi(MsgBuf_ReadString, 1, p(ptr)),
// bi(MsgBuf_ReadBytes, _, _),
bi(MsgBuf_ReadCoord, 1, p(ptr)),
bi(MsgBuf_ReadCoordV, 1, p(ptr)),
bi(MsgBuf_ReadCoordAngleV, 2, p(ptr), p(ptr)),
bi(MsgBuf_ReadAngle, 1, p(ptr)),
bi(MsgBuf_ReadAngleV, 1, p(ptr)),
bi(MsgBuf_ReadAngle16, 1, p(ptr)),
bi(MsgBuf_ReadAngle16V, 1, p(ptr)),
bi(MsgBuf_ReadUTF8, 1, p(ptr)),
{0}
};
void
RUA_MsgBuf_Init (progs_t *pr, int secure)
{
msgbuf_resources_t *res = calloc (sizeof (msgbuf_resources_t), 1);
PR_Resources_Register (pr, "MsgBuf", res, bi_msgbuf_clear,
bi_msgbuf_destroy);
PR_RegisterBuiltins (pr, builtins, res);
}