mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-12-11 21:31:30 +00:00
70aa970c32
It should have been this way all along, and it seems I thought they were when I did rua_gui.c as it already freed its resource block, which would have been a double free (oops). Fixes an invalid write when shutting down progs in qwaq-cmd (relevant change not committed).
493 lines
13 KiB
C
493 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)
|
|
{
|
|
free (_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);
|
|
}
|