Merge branch 'master' into vulkan

This commit is contained in:
Bill Currie 2020-03-20 13:04:41 +09:00
commit 1a7add3f6d
309 changed files with 13119 additions and 4152 deletions

View file

@ -75,8 +75,6 @@
tools/qfvis/Makefile
tools/qfvis/include/Makefile
tools/qfvis/source/Makefile
tools/qwaq/Makefile
tools/qwaq/progs.src
tools/wad/Makefile
tools/wav/Makefile
@ -88,6 +86,7 @@
ruamoko/gui/Makefile
ruamoko/cl_menu/Makefile
ruamoko/scheme/Makefile
ruamoko/qwaq/Makefile
pkg-config/Makefile
pkg-config/qfcc.pc

View file

@ -235,7 +235,11 @@ if test "x$ENABLE_tools_qfvis" = xyes; then
QF_NEED(libs,[util])
fi
if test "x$ENABLE_tools_qwaq" = xyes; then
QF_NEED(tools,[qwaq])
if test "x$HAVE_PANEL" = xyes -a "x$HAVE_PTHREAD" = xyes; then
QWAQ_TARGETS="$QWAQ_TARGETS qwaq-curses\$(EXEEXT)"
fi
QF_NEED(tools,[qfcc])
QF_NEED(ruamoko,[qwaq])
QF_NEED(libs,[ruamoko gamecode util])
fi
if test "x$ENABLE_tools_wad" = xyes; then
@ -249,14 +253,24 @@ fi
QF_NEED(top, [libs hw nq qtv qw])
QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis qwaq wad wav])
QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis qwaq wad wav], QF_NEED(top,tools))
QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav])
QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav], QF_NEED(top,tools))
QF_PROCESS_NEED_DIRS(libs,[util gamecode ruamoko gib audio image models video console net qw client])
QF_PROCESS_NEED_DIRS(ruamoko,[qwaq])
if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then
QF_NEED(top, [ruamoko])
qfcc_include_qf="\$(qfcc_include_qf)"
fi
QF_SUBST(qfcc_include_qf)
if test x"${top_need_libs}" = xyes; then
include_qf="\$(include_qf)"
fi
QF_SUBST(include_qf)
progs_gz=
if test "$HAVE_ZLIB" = "yes"; then
progs_gz=".gz"
@ -380,6 +394,7 @@ QF_DEPS(QFCC,
QF_DEPS(QFCC_TEST,
[],
[$(top_builddir)/libs/ruamoko/libQFruamoko.la
$(top_builddir)/libs/gamecode/libQFgamecode.la
$(top_builddir)/libs/util/libQFutil.la],
[$(WIN32_LIBS)],
)
@ -414,6 +429,7 @@ QF_DEPS(QFVIS,
QF_DEPS(QWAQ,
[],
[$(top_builddir)/libs/ruamoko/libQFruamoko.la
$(top_builddir)/libs/gamecode/libQFgamecode.la
$(top_builddir)/libs/util/libQFutil.la],
[$(WIN32_LIBS)],
)
@ -421,6 +437,7 @@ QF_DEPS(CARNE,
[],
[$(top_builddir)/libs/gib/libQFgib.la
$(top_builddir)/libs/ruamoko/libQFruamoko.la
$(top_builddir)/libs/gamecode/libQFgamecode.la
$(top_builddir)/libs/util/libQFutil.la],
[$(WIN32_LIBS)],
)

View file

@ -2,7 +2,7 @@ AC_ARG_ENABLE(curses,
[ --disable-curses disable curses support]
)
if test "x$enable_curses" != "xno"; then
AC_CHECK_HEADERS(curses.h)
AC_CHECK_HEADER(curses.h)
AC_CHECK_LIB(ncurses, initscr,
CURSES_LIBS=-lncurses,
AC_CHECK_LIB(pdcurses, initscr,
@ -13,7 +13,32 @@ if test "x$enable_curses" != "xno"; then
)
)
)
if test "x$CURSES_LIBS" != "x"; then
AC_DEFINE(HAVE_CURSES, 1, [Define if you have the ncurses library])
HAVE_CURSES=yes
else
HAVE_CURSES=no
fi
else
HAVE_CURSES=no
CURSES_LIBS=
fi
AC_SUBST(CURSES_LIBS)
if test "x$HAVE_CURSES" == "xyes"; then
AC_CHECK_HEADER(panel.h,
[AC_CHECK_LIB(panel, new_panel,
[AC_DEFINE(HAVE_PANEL, 1,
[Define if you have the ncurses panel library])
PANEL_LIBS=-lpanel
HAVE_PANEL=yes],
[HAVE_PANEL=no],
$CURSES_LIBS
)],
HAVE_PANEL=no,
[]
)
else
PANEL_LIBS=
fi
AC_SUBST(PANEL_LIBS)

View file

@ -23,6 +23,7 @@ call_progs_main (progs_t *pr, int argc, const char **argv)
PR_RESET_PARAMS (pr);
P_INT (pr, 0) = argc;
P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv);
pr->pr_argc = 2;
PR_ExecuteProgram (pr, progs_main);
PR_PopFrame (pr);
PR_Zone_Free (pr, pr_argv);

View file

@ -1566,7 +1566,7 @@ FORMULA_TRANSPARENT = YES
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
USE_MATHJAX = YES
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:

View file

@ -1,15 +1,19 @@
AUTOMAKE_OPTIONS = foreign
pkgincludedir = $(includedir)/QF
nobase_pkginclude_HEADERS = \
#for header files that qfcc (ruamoko) will use
pkgdatadir = $(datarootdir)/qfcc/include/QF
include_qf= \
alloc.h bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \
console.h crc.h csqc.h cvar.h darray.h dstring.h draw.h gib.h hash.h hl.h \
console.h crc.h csqc.h cvar.h darray.h dstring.h draw.h gib.h hash.h \
idparse.h image.h in_event.h info.h input.h iqm.h joystick.h keys.h \
link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \
msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \
pr_obj.h pr_type.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h \
quakefs.h \
quakeio.h render.h riff.h ruamoko.h screen.h script.h segtext.h set.h \
sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.h \
quakeio.h render.h riff.h ringbuffer.h ruamoko.h \
screen.h script.h segtext.h set.h \
sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h va.h \
ver_check.h vid.h vrect.h view.h wad.h wadfile.h winding.h zone.h \
\
GL/ati.h GL/defines.h GL/extensions.h GL/funcs.h GL/qf_draw.h \
@ -26,3 +30,9 @@ nobase_pkginclude_HEADERS = \
\
plugin/cd.h plugin/console.h plugin/general.h plugin/input.h \
plugin/snd_output.h plugin/snd_render.h plugin/vid_render.h
qfcc_include_qf=keys.h
nobase_pkginclude_HEADERS = @include_qf@
pkgdata_DATA=@qfcc_include_qf@
EXTRA_HEADERS = $(include_qf) $(qfcc_include_qf)

View file

@ -24,8 +24,8 @@
Boston, MA 02111-1307, USA
*/
#ifndef __bspfile_h_
#define __bspfile_h_
#ifndef __QF_bspfile_h
#define __QF_bspfile_h
#include "QF/qtypes.h"
#include "QF/quakeio.h"
@ -310,4 +310,4 @@ void BSP_AddVisibility (bsp_t *bsp, const byte *visdata, size_t visdatasize);
void BSP_AddEntities (bsp_t *bsp, const char *entdata, size_t entdatasize);
void BSP_AddTextures (bsp_t *bsp, const byte *texdata, size_t texdatasize);
#endif//__bspfile_h_
#endif//__QF_bspfile_h

View file

@ -25,8 +25,8 @@
*/
#ifndef _CDAUDIO_H
#define _CDAUDIO_H
#ifndef __QF_cdaudio_h
#define __QF_cdaudio_h
#include "QF/qtypes.h"
@ -37,4 +37,4 @@ void CDAudio_Pause(void);
void CDAudio_Resume(void);
void CDAudio_Update(void);
#endif // _CDAUDIO_H
#endif//__QF_cdaudio_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __checksum_h
#define __checksum_h
#ifndef __QF_checksum_h
#define __QF_checksum_h
/** \addtogroup crc
*/
@ -40,4 +40,4 @@ byte COM_BlockSequenceCRCByte (const byte *base, int length, int sequence);
///@}
#endif // __checksum_h
#endif//__QF_checksum_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __console_h
#define __console_h
#ifndef __QF_console_h
#define __QF_console_h
#include <stdarg.h>
@ -150,4 +150,4 @@ void Menu_Leave_f (void);
void Menu_Prev_f (void);
void Menu_Next_f (void);
#endif // __console_h
#endif//__QF_console_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __crc_h
#define __crc_h
#ifndef __QF_crc_h
#define __QF_crc_h
/** \defgroup crc Checksum generation.
\ingroup utils
@ -43,4 +43,4 @@ unsigned short CRC_Block (const byte *start, int count) __attribute__((pure));
///@}
#endif // __crc_h
#endif//__QF_crc_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __cvar_h
#define __cvar_h
#ifndef __QF_cvar_h
#define __QF_cvar_h
/** \defgroup cvar Configuration variables
\ingroup utils
@ -140,4 +140,4 @@ extern cvar_t *cvar_vars;
///@}
#endif // __cvar_h
#endif//__QF_cvar_h

View file

@ -25,8 +25,8 @@
*/
#ifndef _DRAW_H
#define _DRAW_H
#ifndef __QF_draw_h
#define __QF_draw_h
/** \defgroup video Video Sub-sytem */
@ -234,4 +234,4 @@ void Draw_Picf (float x, float y, qpic_t *pic);
void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
///@}
#endif // _DRAW_H
#endif//__QF_draw_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __dstring_h
#define __dstring_h
#ifndef __QF_dstring_h
#define __QF_dstring_h
/** \defgroup dstring Dynamic Strings
\ingroup utils
@ -164,17 +164,17 @@ void dstring_clearstr (dstring_t *dstr);
/** Formatted printing to dstrings. Existing data is replaced by the formatted
string.
*/
int dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0)));
int dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3)));
char *dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0)));
char *dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3)));
///@}
///@{
/** Formatted printing to dstrings. Formatted string is appened to the dstring.
Embedded nulls in the dstring are ignored.
*/
int davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0)));
int dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3)));
char *davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0)));
char *dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3)));
///@}
///@}
#endif // __dstring_h
#endif//__QF_dstring_h

View file

@ -28,8 +28,8 @@
*/
#ifndef __gib_h
#define __gib_h
#ifndef __QF_gib_h
#define __QF_gib_h
// Dependencies
@ -216,4 +216,4 @@ unsigned long int GIB_Handle_New (gib_object_t *data);
void GIB_Handle_Free (unsigned long int num);
gib_object_t *GIB_Handle_Get (unsigned long int num) __attribute__((pure));
#endif
#endif//__QF_gib_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __hash_h
#define __hash_h
#ifndef __QF_hash_h
#define __QF_hash_h
#include <stdint.h>
#include <stdlib.h>
@ -211,4 +211,4 @@ void Hash_Stats (hashtab_t *tab);
///@}
#endif // __hash_h
#endif//__QF_hash_h

View file

@ -1,40 +0,0 @@
/*
hl_bsp.h
Half Life file definitions
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
*/
#ifndef _HL_BSP_H
#define _HL_BSP_H
#include "QF/qtypes.h"
extern void CL_ParseEntityLump(const char *entdata);
extern void HL_Mod_LoadLighting (lump_t *l);
extern void HL_Mod_LoadTextures (lump_t *l);
extern byte *W_GetTexture(const char *name, int matchwidth, int matchheight);
extern void W_LoadTextureWadFile (const char *filename, int complain);
#endif // _HL_BSP_H

View file

@ -49,4 +49,4 @@ typedef struct tex_s {
tex_t *LoadImage (const char *imageFile);
#endif //__QF_image_h
#endif//__QF_image_h

View file

@ -25,8 +25,8 @@
*/
#ifndef _INFO_H
#define _INFO_H
#ifndef __QF_info_h
#define __QF_info_h
/** \defgroup info Info Keys
\ingroup utils
@ -65,4 +65,4 @@ void Info_AddKeys (info_t *info, info_t *keys);
///@}
#endif // _INFO_H
#endif//__QF_info_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __QF_input_h_
#define __QF_input_h_
#ifndef __QF_input_h
#define __QF_input_h
#include "QF/keys.h"
@ -73,4 +73,4 @@ void IN_LL_Grab_Input (int grab);
extern kbutton_t in_strafe, in_klook, in_speed, in_mlook;
#endif // __QF_input_h_
#endif//__QF_input_h

View file

@ -1,5 +1,5 @@
#ifndef __QF_iqm_h__
#define __QF_iqm_h__
#ifndef __QF_iqm_h
#define __QF_iqm_h
#include "QF/qtypes.h"
@ -149,4 +149,4 @@ typedef struct {
void *extra_data;
} iqm_t;
#endif//__QF_iqm_h__
#endif//__QF_iqm_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __QF_joystick_h_
#define __QF_joystick_h_
#ifndef __QF_joystick_h
#define __QF_joystick_h
#include <QF/qtypes.h>
#include "QF/quakeio.h"
@ -154,4 +154,4 @@ int JOY_GetAxis_i (int dest, const char *c);
void Joy_WriteBindings (QFile *f);
#endif // __QF_joystick_h_
#endif//__QF_joystick_h

View file

@ -26,8 +26,8 @@
*/
#ifndef _KEYS_H
#define _KEYS_H
#ifndef __QF_keys_h
#define __QF_keys_h
#ifndef __QFCC__
# include "QF/qtypes.h"
@ -661,4 +661,4 @@ void Key_Progs_Init (struct progs_s *pr);
///@}
#endif // _KEYS_H
#endif//__QF_keys_h

View file

@ -25,8 +25,8 @@
*/
#ifndef _LINK_H
#define _LINK_H
#ifndef __QF_link_h
#define __QF_link_h
// (type *)STRUCT_FROM_LINK(link_t *link, type, member)
// ent = STRUCT_FROM_LINK(link,entity_t,order)
@ -43,4 +43,4 @@ void RemoveLink (link_t *l);
void InsertLinkBefore (link_t *l, link_t *before);
void InsertLinkAfter (link_t *l, link_t *after);
#endif // _LINK_H
#endif//__QF_link_h

View file

@ -25,8 +25,8 @@
*/
#ifndef _LLIST_H
#define _LLIST_H
#ifndef __QF_llist_h
#define __QF_llist_h
#include "QF/qtypes.h"
@ -112,4 +112,4 @@ void *llist_createarray (llist_t *list, size_t esize);
//@}
#endif
#endif//__QF_llist_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __locs_h
#define __locs_h
#ifndef __QF_locs_h
#define __QF_locs_h
#include "QF/qtypes.h"
@ -47,4 +47,4 @@ void locs_reset (void);
void locs_save (const char *filename, qboolean gz);
void map_to_loc (const char *mapname, char *filename);
#endif // __locs_h
#endif//__QF_locs_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __mathlib_h
#define __mathlib_h
#ifndef __QF_mathlib_h
#define __QF_mathlib_h
/** \defgroup mathlib Vector and matrix functions
\ingroup utils
@ -220,4 +220,4 @@ void BarycentricCoords (const vec_t **points, int num_points, const vec3_t p,
///@}
#endif // __mathlib_h
#endif//__QF_mathlib_h

View file

@ -26,20 +26,20 @@
*/
#ifndef __mdfour_h
#define __mdfour_h
#ifndef __QF_mdfour_h
#define __QF_mdfour_h
#include "QF/qtypes.h"
/** \addtogroup crc
*/
///@{
#include "QF/uint32.h"
#define MDFOUR_DIGEST_BYTES 16
struct mdfour {
uint32 A, B, C, D;
uint32 totalN;
uint32_t A, B, C, D;
uint32_t totalN;
};
void mdfour_begin(struct mdfour *md); // old: MD4Init
@ -49,4 +49,4 @@ void mdfour(unsigned char *out, const unsigned char *in, int n);
///@}
#endif // __mdfour_h
#endif//__QF_mdfour_h

View file

@ -25,8 +25,8 @@
*/
#ifndef _MODEL_H
#define _MODEL_H
#ifndef __QF_model_h
#define __QF_model_h
#include "QF/qtypes.h"
#include "QF/bspfile.h"
@ -468,4 +468,4 @@ extern byte *mod_base;
extern byte mod_novis[MAX_MAP_LEAFS / 8];
extern int mod_lightmap_bytes;
#endif // _MODEL_H
#endif//__QF_model_h

View file

@ -31,8 +31,8 @@
// * pass data from one to the other via model files. *
// *********************************************************
#ifndef _MODELGEN_H
#define _MODELGEN_H
#ifndef __QF_modelgen_h
#define __QF_modelgen_h
#include "QF/mathlib.h"
@ -142,4 +142,4 @@ typedef struct {
// little-endian "IDP2"
#define IDHEADER_MD2 (('2'<<24)+('P'<<16)+('D'<<8)+'I')
#endif // _MODELGEN_H
#endif//__QF_modelgen_h

View file

@ -24,8 +24,8 @@
Boston, MA 02111-1307, USA
*/
#ifndef _MSG_H
#define _MSG_H
#ifndef __QF_msg_h
#define __QF_msg_h
/** \defgroup msg Message reading and writing
\ingroup utils
@ -251,4 +251,4 @@ int MSG_ReadUTF8 (qmsg_t *msg);
///@}
#endif
#endif//__QF_msg_h

View file

@ -32,8 +32,8 @@
*/
#ifndef __object_h
#define __object_h
#ifndef __QF_object_h
#define __QF_object_h
#include "QF/qtypes.h"
@ -115,4 +115,4 @@ void Object_Garbage_Collect (void);
#include "QF/classes/String.h"
#endif
#endif//__QF_object_h

View file

@ -28,8 +28,8 @@
*/
#ifndef __qf_pak_h
#define __qf_pak_h
#ifndef __QF_pak_h
#define __QF_pak_h
/** \addtogroup pak
*/
@ -53,4 +53,4 @@ typedef struct {
///@}
#endif//__qf_pak_h
#endif//__QF_pak_h

View file

@ -24,8 +24,8 @@
Boston, MA 02111-1307, USA
*/
#ifndef __pcx_h
#define __pcx_h
#ifndef __QF_pcx_h
#define __QF_pcx_h
#include "QF/qtypes.h"
#include "QF/quakeio.h"
@ -77,4 +77,4 @@ pcx_t *EncodePCX (byte *data, int width, int height, int rowbytes,
*/
struct tex_s *LoadPCX (QFile *f, qboolean convert, byte *pal);
#endif // __pcx_h
#endif//__QF_pcx_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __QF_plugin_h_
#define __QF_plugin_h_
#ifndef __QF_plugin_h
#define __QF_plugin_h
/** \defgroup plugin Plugins
\ingroup utils
@ -113,4 +113,4 @@ void PI_Shutdown (void);
///@}
#endif // __QF_plugin_h_
#endif//__QF_plugin_h

View file

@ -18,8 +18,8 @@
*/
// this file is shared by QuakeForge and qfcc
#ifndef __pr_comp_h
#define __pr_comp_h
#ifndef __QF_pr_comp_h
#define __QF_pr_comp_h
#include "QF/qtypes.h"
@ -27,7 +27,7 @@ typedef int16_t pr_short_t;
typedef uint16_t pr_ushort_t;
typedef int32_t pr_int_t;
typedef uint32_t pr_uint_t;
typedef pr_int_t func_t;
typedef pr_uint_t func_t;
typedef pr_int_t string_t;
typedef pr_uint_t pointer_t;
@ -50,8 +50,8 @@ typedef enum {
ev_type_count // not a type, gives number of types
} etype_t;
extern int pr_type_size[ev_type_count];
extern const char *pr_type_name[ev_type_count];
extern const pr_ushort_t pr_type_size[ev_type_count];
extern const char * const pr_type_name[ev_type_count];
#define OFS_NULL 0
#define OFS_RETURN 1
@ -395,7 +395,12 @@ typedef enum {
OP_MOD_I,
OP_MOD_F,
OP_MOD_D,
OP_MEMSETI,
OP_MEMSETP,
OP_MEMSETPI,
} pr_opcode_e;
#define OP_BREAK 0x8000
typedef struct opcode_s {
const char *name;
@ -407,9 +412,9 @@ typedef struct opcode_s {
const char *fmt;
} opcode_t;
extern opcode_t pr_opcodes[];
extern const opcode_t pr_opcodes[];
opcode_t *PR_Opcode (pr_short_t opcode);
void PR_Opcode_Init (void);
void PR_Opcode_Init (void); // idempotent
typedef struct dstatement_s {
pr_opcode_e op:16;
@ -417,12 +422,30 @@ typedef struct dstatement_s {
} GCC_STRUCT dstatement_t;
typedef struct ddef_s {
pr_ushort_t type; // if DEF_SAVEGLOBGAL bit is set
pr_ushort_t type; // if DEF_SAVEGLOBAL bit is set
// the variable needs to be saved in savegames
pr_ushort_t ofs;
pr_int_t s_name;
string_t s_name;
} ddef_t;
typedef struct xdef_s {
pointer_t type; ///< pointer to type definition
pointer_t ofs; ///< 32-bit version of ddef_t.ofs
} xdef_t;
typedef struct pr_xdefs_s {
pointer_t xdefs;
pr_int_t num_xdefs;
} pr_xdefs_t;
typedef struct pr_def_s {
pr_ushort_t type;
pr_ushort_t size; ///< may not be correct
pointer_t ofs;
string_t name;
pointer_t type_encoding;
} pr_def_t;
typedef struct dparmsize_s {
uint8_t size:5;
uint8_t alignment:3;
@ -435,11 +458,11 @@ typedef struct dparmsize_s {
typedef struct dfunction_s {
pr_int_t first_statement; // negative numbers are builtins
pr_int_t parm_start;
pr_int_t locals; // total ints of parms + locals
pr_uint_t locals; // total ints of parms + locals
pr_int_t profile; // runtime
pr_uint_t profile; // runtime
pr_int_t s_name;
string_t s_name;
pr_int_t s_file; // source file defined in
pr_int_t numparms;
@ -484,10 +507,10 @@ typedef struct dprograms_s {
pr_uint_t numfielddefs;
pr_uint_t ofs_functions;
pr_int_t numfunctions; // function 0 is an empty
pr_uint_t numfunctions; // function 0 is an empty
pr_uint_t ofs_strings;
pr_int_t numstrings; // first string is a null string
pr_uint_t numstrings; // first string is a null string
pr_uint_t ofs_globals;
pr_uint_t numglobals;
@ -495,4 +518,4 @@ typedef struct dprograms_s {
pr_uint_t entityfields;
} dprograms_t;
#endif // __pr_comp_h
#endif//__QF_pr_comp_h

View file

@ -28,8 +28,8 @@
*/
#ifndef __pr_debug_h
#define __pr_debug_h
#ifndef __QF_pr_debug_h
#define __QF_pr_debug_h
#include "QF/pr_comp.h"
@ -39,8 +39,7 @@ typedef struct pr_auxfunction_s {
pr_uint_t line_info; // index to first lineno entry
pr_uint_t local_defs; // index to the first local def
pr_uint_t num_locals; // number of local defs
pr_short_t return_type; // return type of this function
pr_short_t reserved;
pr_uint_t return_type; // return type of this function
} pr_auxfunction_t;
typedef struct pr_lineno_s {
@ -51,7 +50,7 @@ typedef struct pr_lineno_s {
pr_uint_t line;
} pr_lineno_t;
#define PROG_DEBUG_VERSION 0x00001002 // MMmmmRRR 0.001.002 (hex)
#define PROG_DEBUG_VERSION 0x00001003 // MMmmmRRR 0.001.002 (hex)
typedef struct pr_debug_header_s {
pr_int_t version;
@ -65,4 +64,4 @@ typedef struct pr_debug_header_s {
pr_uint_t num_locals;
} pr_debug_header_t;
#endif//__pr_debug_h
#endif//__QF_pr_debug_h

View file

@ -28,8 +28,8 @@
*/
#ifndef __pr_obj_h
#define __pr_obj_h
#ifndef __QF_pr_obj_h
#define __QF_pr_obj_h
#include "QF/pr_comp.h"
@ -94,7 +94,7 @@ typedef struct pr_class_s {
pr_int_t instance_size;
pointer_t ivars; // pr_ivar_list_t
pointer_t methods; // pr_method_list_t
pointer_t dtable;
pointer_t dtable; // resource index
pointer_t subclass_list; // pr_class_t
pointer_t sibling_class; // pr_class_t
pointer_t protocols; // pr_protocol_list_t
@ -185,4 +185,4 @@ typedef struct pr_super_s {
pointer_t class;
} pr_super_t;
#endif//__pr_obj_h
#endif//__QF_pr_obj_h

View file

@ -28,8 +28,8 @@
*/
#ifndef __pr_type_h
#define __pr_type_h
#ifndef __QF_pr_type_h
#define __QF_pr_type_h
/** \defgroup qfcc_qfo_type Object file type encoding
\ingroup progs
@ -40,6 +40,16 @@
#include "QF/pr_comp.h"
typedef enum {
ty_basic, ///< VM type (float, int, pointer, field, etc)
ty_struct,
ty_union,
ty_enum,
ty_array,
ty_class,
} ty_meta_e;
typedef struct qfot_fldptr_s {
pr_int_t type; ///< ev_field or ev_pointer
pointer_t aux_type; ///< referenced type
@ -88,20 +98,20 @@ typedef struct qfot_type_s {
pr_int_t size; ///< total word size of this encoding
string_t encoding; ///< Objective-QC encoding
union {
pr_int_t type; ///< basic type: etype_t
qfot_fldptr_t fldptr; ///< ty_none, ev_pointer/ev_field
qfot_func_t func; ///< ty_none, ev_func
pr_int_t type; ///< ty_basic: etype_t
qfot_fldptr_t fldptr; ///< ty_basic, ev_pointer/ev_field
qfot_func_t func; ///< ty_basic, ev_func
qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum
qfot_array_t array; ///< ty_array
pointer_t class; ///< ty_class
string_t class; ///< ty_class
} t;
} qfot_type_t;
typedef struct qfot_type_encodings_s {
pointer_t types;
pr_int_t size;
pr_uint_t size;
} qfot_type_encodings_t;
///@}
#endif//__pr_type_h
#endif//__QF_pr_type_h

View file

@ -53,8 +53,12 @@ typedef struct edict_s edict_t;
///@{
/** Initialize the progs engine.
The first call will initialize subsystems common to all progs instances.
\param pr The progs engine instance to initialize.
*/
void PR_Init (void);
void PR_Init (progs_t *pr);
/** Initialize the Cvars for the progs engine. Call before calling PR_Init().
*/
@ -87,15 +91,63 @@ void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(pri
(pr)->pr_params[1] = (pr)->pr_real_params[1]; \
} while (0)
/** Save the current parameters.
\param pr pointer to ::progs_t VM struct
/** \name Detouring Function Calls
These functions allow a builtin function that uses PR_CallFunction() to
safely insert a call to another VM function. The +initialize diversion
required by Objective-QuakeC uses this.
PR_PushFrame (pr);
__auto_type params = PR_SaveParams (pr);
... set up parameters to detour_function
PR_ExecuteProgram (pr, detour_function)
PR_RestoreParams (pr, params);
PR_PopFrame (pr);
*/
void PR_SaveParams (progs_t *pr);
///@{
typedef struct pr_stashed_params_s {
pr_type_t *param_ptrs[2];
int argc;
pr_type_t params[1];
} pr_stashed_params_t;
/** Save the current parameters to the provided stash.
\warning The memory for the parameter stash is allocated using
alloca().
\param pr pointer to ::progs_t VM struct
\return Pointer to a newly allocated and initialized parameter
stash that has the current parameters saved to it.
\hideinitializer
*/
#define PR_SaveParams(pr) \
_PR_SaveParams((pr), \
alloca (field_offset (pr_stashed_params_t, \
params[(pr)->pr_argc \
* (pr)->pr_param_size])))
/** [INTERNAL] Save the current parameters to the provided stash.
\warning Requires \a params to be correctly allocated. Use
PR_SaveParams instead as it will create a suitable stash for
saving the parameters.
\param pr pointer to ::progs_t VM struct
\param params location to save the parameters, must be of adequade size
to hold \a pr_argc * \a pr_param_size words in \a params
\return \a params Allows the likes of:
__auto_type params = PR_SaveParams (pr);
*/
pr_stashed_params_t *_PR_SaveParams (progs_t *pr, pr_stashed_params_t *params);
/** Restore the parameters saved by PR_SaveParams().
\param pr pointer to ::progs_t VM struct
\param params pointer to stash created by PR_SaveParams()
*/
void PR_RestoreParams (progs_t *pr);
void PR_RestoreParams (progs_t *pr, pr_stashed_params_t *params);
///@}
/** Push an execution frame onto the VM stack. Saves current execution state.
\param pr pointer to ::progs_t VM struct
@ -236,7 +288,7 @@ void ED_PrintNum (progs_t *pr, pr_int_t ent);
// pr_parse.c
struct script_s;
struct plitem_s;
qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key,
qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key,
const char *s);
struct plitem_s *ED_EntityDict (progs_t *pr, edict_t *ed);
struct plitem_s *ED_GlobalsDict (progs_t *pr);
@ -269,11 +321,13 @@ void ED_EntityParseFunction (progs_t *pr);
*/
///@{
ddef_t *PR_FieldAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure));
ddef_t *PR_GlobalAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure));
pr_def_t *PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset)
__attribute__((pure));
pr_def_t *PR_FieldAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure));
pr_def_t *PR_GlobalAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure));
ddef_t *PR_FindField (progs_t *pr, const char *name);
ddef_t *PR_FindGlobal (progs_t *pr, const char *name);
pr_def_t *PR_FindField (progs_t *pr, const char *name);
pr_def_t *PR_FindGlobal (progs_t *pr, const char *name);
dfunction_t *PR_FindFunction (progs_t *pr, const char *name);
int PR_ResolveGlobals (progs_t *pr);
@ -510,6 +564,20 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
*/
#define P_var(p,n,t) ((p)->pr_params[n]->t##_var)
/** Access a parameter as an arbitray type.
\par QC type:
\c struct etc small enough to fit in a single parameter
\param p pointer to ::progs_t VM struct
\param t C type of the structure
\param n parameter number (0-7)
\return structure lvalue. use & to make a pointer of the
appropriate type.
\hideinitializer
*/
#define P_PACKED(p,t,n) (*(t *) (p)->pr_params[n])
/** Access a float parameter. Can be assigned to.
\par QC type:
@ -532,7 +600,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
\hideinitializer
*/
#define P_DOUBLE(p,n) (*(double *) ((p)->pr_params[n]))
#define P_DOUBLE(p,n) P_PACKED(p, double, n)
/** Access an integer parameter. Can be assigned to.
@ -618,7 +686,6 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
*/
#define P_POINTER(p,n) P_var (p, n, pointer)
/** Access an entity parameter.
\par QC type:
@ -715,6 +782,19 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
*/
#define R_var(p,t) ((p)->pr_return->t##_var)
/** Access the VM function return value parameter as an arbitray type.
\par QC type:
\c struct etc small enough to fit in the return slot
\param p pointer to ::progs_t VM struct
\param t C type of the structure
\return structure lvalue. use & to make a pointer of the
appropriate type.
\hideinitializer
*/
#define R_PACKED(p,t) (*(t *) (p)->pr_return)
/** Access the VM function return value as a \c float
\par QC type:
@ -735,7 +815,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_
\hideinitializer
*/
#define R_DOUBLE(p) (*(double *) ((p)->pr_return))
#define R_DOUBLE(p) R_PACKED (p, double)
/** Access the VM function return value as a \c ::pr_int_t (AKA int32_t)
@ -1142,12 +1222,12 @@ int PR_RelocateBuiltins (progs_t *pr);
*/
///@{
/** Initialize the string tables using the strings supplied by the progs.
Called automatically during progs load.
\param pr pointer to ::progs_t VM struct
\return true for success, false for failure
/** Initialize the string management subsystem.
\param pr The VM of which the string management subsystem will be
initialized;
*/
int PR_LoadStrings (progs_t *pr);
void PR_Strings_Init (progs_t *pr);
/** Check the validity of a string index.
\param pr pointer to ::progs_t VM struct
@ -1196,6 +1276,29 @@ string_t PR_SetReturnString(progs_t *pr, const char *s);
*/
string_t PR_SetTempString(progs_t *pr, const char *s);
/** Make a temporary memory block that will be freed when the current progs
stack frame is exited. The contents may be anything and a new block is
returned every time, and the block is in VM addressible space. To access
the contents of the block (for reading, writing, etc), use PR_GetString()
and cast the pointer as necessary.
\param pr pointer to ::progs_t VM struct
\param size size of block in bytes
\return string index of the block
*/
string_t PR_AllocTempBlock (progs_t *pr, size_t size);
/** Push a temporary string to the callee stack frame
This is for when the temp string needs to be freed when the called function
returns rather than the calling function. It is an error to push a non-temp
string.
\param pr pointer to ::progs_t VM struct
\param num string index of the temp string
*/
void PR_PushTempString (progs_t *pr, string_t num);
/** Make a temporary progs string that is the concatenation of two C strings.
\param pr pointer to ::progs_t VM struct
\param a C string
@ -1226,11 +1329,6 @@ string_t PR_NewMutableString (progs_t *pr);
*/
string_t PR_SetDynamicString (progs_t *pr, const char *s);
/** Clear all of the return string slots. Called at progs load.
\param pr pointer to ::progs_t VM struct
*/
void PR_ClearReturnStrings (progs_t *pr);
/** Destroy a mutable, dynamic or temporary string.
\param pr pointer to ::progs_t VM struct
\param str string index of the string to be destroyed
@ -1418,6 +1516,8 @@ void *PR_Resources_Find (progs_t *pr, const char *name);
Any memory allocated to the resource must be freed before freeing the
resource.
A reset resource map is guaranteed to allocate elements sequentially.
\param type The type of the resource. Must match the \c type parameter
used for PR_RESMAP.
\param map The resource map.
@ -1432,6 +1532,8 @@ void *PR_Resources_Find (progs_t *pr, const char *name);
*(type **) &map._free[j] = &map._free[j + 1]; \
if (i < map._size - 1) \
*(type **) &map._free[j] = &map._map[i + 1][0]; \
else \
*(type **) &map._free[j] = 0; \
} \
map._free = map._map[0];
@ -1488,19 +1590,66 @@ void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size);
/// \addtogroup debug
///@{
void PR_Debug_Init (void);
struct qfot_type_s;
/** Callback for viewing progs data
\param type C pointer to the type definition by which to view the
data.
\param value C pointer to the data to be viewed.
\param data User data.
*/
typedef void (*type_view_func) (struct qfot_type_s *type, pr_type_t *value,
void *data);
/** Set of callbacks for viewing progs data
Each possible type has its own callback. Basic types (those for which the
VM has specific instructions) all have separate callbacks, one for each
type, but the callbacks for compound types are expected to some
interpretation on their own, such as displaying a simple identifier or
the entire contents of the data.
*/
typedef struct type_view_s {
type_view_func void_view;
type_view_func string_view;
type_view_func float_view;
type_view_func vector_view;
type_view_func entity_view;
type_view_func field_view;
type_view_func func_view;
type_view_func pointer_view;
type_view_func quat_view;
type_view_func integer_view;
type_view_func uinteger_view;
type_view_func short_view;
type_view_func double_view;
type_view_func struct_view;
type_view_func union_view;
type_view_func enum_view;
type_view_func array_view;
type_view_func class_view;
} type_view_t;
void PR_Debug_Init (progs_t *pr);
void PR_Debug_Init_Cvars (void);
int PR_LoadDebug (progs_t *pr);
void PR_Debug_Watch (progs_t *pr, const char *expr);
void PR_Debug_Print (progs_t *pr, const char *expr);
pr_auxfunction_t *PR_Debug_AuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure));
pr_auxfunction_t *PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure));
pr_def_t *PR_Debug_LocalDefs (progs_t *pr, pr_auxfunction_t *aux_function) __attribute__((pure));
pr_lineno_t *PR_Debug_Linenos (progs_t *pr, pr_auxfunction_t *aux_function,
pr_uint_t *num_linenos);
pr_auxfunction_t *PR_Get_Lineno_Func (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure));
pr_uint_t PR_Get_Lineno_Addr (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure));
pr_uint_t PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure));
pr_lineno_t *PR_Find_Lineno (progs_t *pr, pr_uint_t addr) __attribute__((pure));
const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure));
const char *PR_Get_Source_Line (progs_t *pr, pr_uint_t addr);
ddef_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure));
ddef_t *PR_Get_Local_Def (progs_t *pr, pr_int_t offs) __attribute__((pure));
pr_def_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure));
pr_def_t *PR_Get_Local_Def (progs_t *pr, pointer_t *offs) __attribute__((pure));
void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents);
void PR_DumpState (progs_t *pr);
void PR_StackTrace (progs_t *pr);
@ -1541,8 +1690,6 @@ typedef struct {
strref_t *tstr; ///< Linked list of temporary strings.
} prstack_t;
struct obj_list_s;
struct progs_s {
int (*parse_field) (progs_t *pr, const char *key, const char *value);
@ -1550,7 +1697,7 @@ struct progs_s {
int no_exec_limit;
void (*file_error) (progs_t *pr, const char *path);
void *(*load_file) (progs_t *pr, const char *path);
void *(*load_file) (progs_t *pr, const char *path, off_t *size);
void *(*allocate_progs_mem) (progs_t *pr, int size);
void (*free_progs_mem) (progs_t *pr, void *mem);
@ -1597,16 +1744,9 @@ struct progs_s {
/// \name string management
///@{
struct dstring_mem_s *ds_mem;
strref_t *free_string_refs;
strref_t *static_strings;
strref_t **string_map;
strref_t *return_strings[PR_RS_SLOTS];
int rs_slot;
unsigned dyn_str_size;
struct hashtab_s *strref_hash;
int num_strings;
struct prstr_resources_s *pr_string_resources;
strref_t *pr_xtstr;
strref_t *pr_pushtstr;
int float_promoted; ///< for PR_Sprintf
///@}
@ -1616,8 +1756,8 @@ struct progs_s {
bfunction_t *function_table;
char *pr_strings;
int pr_stringsize;
ddef_t *pr_globaldefs;
ddef_t *pr_fielddefs;
pr_def_t *pr_globaldefs;
pr_def_t *pr_fielddefs;
dstatement_t *pr_statements;
pr_type_t *pr_globals;
unsigned globals_size;
@ -1628,14 +1768,12 @@ struct progs_s {
pr_type_t *pr_return;
pr_type_t *pr_params[MAX_PARMS];
pr_type_t *pr_real_params[MAX_PARMS];
pr_type_t *pr_param_ptrs[2];
pr_type_t *pr_saved_params;
int pr_saved_argc;
int pr_param_size; ///< covers both params and return
int pr_param_alignment; ///< covers both params and return
///@}
/// \name edicts
/// \todo FIXME should this be outside the VM?
///@{
edict_t **edicts;
int max_edicts; ///< set by user
@ -1652,7 +1790,7 @@ struct progs_s {
/// \name execution state
///@{
int pr_argc;
int pr_argc; //FIXME need a good way to ensure it is correct
qboolean pr_trace;
int pr_trace_depth;
@ -1687,28 +1825,13 @@ struct progs_s {
/// \name obj info
///@{
unsigned selector_index;
unsigned selector_index_max;
struct obj_list_s **selector_sels;
string_t *selector_names;
struct hashtab_s *selector_hash;
struct hashtab_s *classes;
struct hashtab_s *load_methods;
struct obj_list_s *unresolved_classes;
struct obj_list_s *unclaimed_categories;
struct obj_list_s *unclaimed_proto_list;
struct obj_list_s *module_list;
struct obj_list_s *class_tree_list;
struct probj_resources_s *pr_objective_resources;
///@}
/// \name debug info
/// \name debugging
///@{
const char *debugfile;
struct pr_debug_header_s *debug;
struct pr_auxfunction_s *auxfunctions;
struct pr_auxfunction_s **auxfunction_map;
struct pr_lineno_s *linenos;
ddef_t *local_defs;
struct prdeb_resources_s *pr_debug_resources;
void (*breakpoint_handler) (progs_t *pr);
pr_type_t *watch;
int wp_conditional;
pr_type_t wp_val;
@ -1740,7 +1863,7 @@ struct progs_s {
\return C pointer represented by the parameter. 0 offset -> NULL
*/
static inline pr_type_t *
PR_GetPointer (progs_t *pr, pointer_t o)
PR_GetPointer (const progs_t *pr, pointer_t o)
{
return o ? pr->pr_globals + o : 0;
}
@ -1751,9 +1874,9 @@ PR_GetPointer (progs_t *pr, pointer_t o)
\return Progs offset/pointer represented by \c p. NULL -> 0 offset
*/
static inline pointer_t
PR_SetPointer (progs_t *pr, void *p)
PR_SetPointer (const progs_t *pr, const void *p)
{
return p ? (pr_type_t *) p - pr->pr_globals : 0;
return p ? (const pr_type_t *) p - pr->pr_globals : 0;
}
///@}

View file

@ -27,8 +27,8 @@
*/
#ifndef __qargs_h
#define __qargs_h
#ifndef __QF_qargs_h
#define __QF_qargs_h
/** \addtogroup misc
*/
@ -52,4 +52,4 @@ void COM_ParseConfig (void);
///@}
#endif // __qargs_h
#endif//__QF_qargs_h

View file

@ -27,8 +27,8 @@
*/
#ifndef __qdefs_h
#define __qdefs_h
#ifndef __QF_qdefs_h
#define __QF_qdefs_h
#define MAX_QPATH 64
#define MAX_CL_STATS 32
@ -40,4 +40,4 @@
#define clc_stringcmd 4
#endif // __qdefs_h
#endif//__QF_qdefs_h

View file

@ -27,8 +27,8 @@
*/
#ifndef __qendian_h
#define __qendian_h
#ifndef __QF_qendian_h
#define __QF_qendian_h
/** \defgroup qendian Endian handling functions
\ingroup utils
@ -120,4 +120,4 @@ unsigned int ReadLong (struct QFile_s *file);
///@}
#endif // __qendian_h
#endif//__QF_qendian_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __QF_qfplist_h_
#define __QF_qfplist_h_
#ifndef __QF_qfplist_h
#define __QF_qfplist_h
/** \defgroup qfplist Property lists
\ingroup utils
@ -228,4 +228,4 @@ void PL_Free (plitem_t *item);
///@}
#endif // __QF_qfplist_h_
#endif//__QF_qfplist_h

View file

@ -27,8 +27,8 @@
*/
#ifndef __qtypes_h
#define __qtypes_h
#ifndef __QF_qtypes_h
#define __QF_qtypes_h
#include <stdio.h>
#include <stdint.h>
@ -115,4 +115,4 @@ typedef struct sphere_s {
vec_t radius;
} sphere_t;
#endif // __qtypes_h
#endif//__QF_qtypes_h

View file

@ -27,8 +27,8 @@
*/
#ifndef __quakefs_h
#define __quakefs_h
#ifndef __QF_quakefs_h
#define __QF_quakefs_h
/** \defgroup quakefs Quake Filesystem
\ingroup utils
@ -420,4 +420,4 @@ void QFS_FilelistFree (filelist_t *list);
///@}
#endif // __quakefs_h
#endif//__QF_quakefs_h

View file

@ -26,8 +26,8 @@
Boston, MA 02111-1307, USA
*/
#ifndef __quakeio_h
#define __quakeio_h
#ifndef __QF_quakeio_h
#define __QF_quakeio_h
#include <stdio.h>
@ -62,4 +62,4 @@ const char *Qgetline(QFile *file);
///@}
#endif /*__quakeio_h*/
#endif//__QF_quakeio_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __render_h
#define __render_h
#ifndef __QF_render_h
#define __QF_render_h
#include "QF/mathlib.h"
#include "QF/model.h"
@ -177,4 +177,4 @@ void R_LoadModule (struct vid_internal_s *vid_internal);
struct progs_s;
void R_Progs_Init (struct progs_s *pr);
#endif // __render_h
#endif//__QF_render_h

103
include/QF/ringbuffer.h Normal file
View file

@ -0,0 +1,103 @@
/*
ringbuffer.h
ring buffer
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
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
*/
#ifndef __QF_ringbuffer_h
#define __QF_ringbuffer_h
#define RING_BUFFER(type, size) \
struct { \
type buffer[size]; \
unsigned head; \
unsigned tail; \
}
#define RB_buffer_size(ring_buffer) \
({ __auto_type rb = (ring_buffer); \
sizeof (rb->buffer) / sizeof (rb->buffer[0]); \
})
#define RB_SPACE_AVAILABLE(ring_buffer) \
({ __auto_type rb = &(ring_buffer); \
(rb->tail + RB_buffer_size(rb) - rb->head - 1) % RB_buffer_size(rb);\
})
#define RB_DATA_AVAILABLE(ring_buffer) \
({ __auto_type rb = &(ring_buffer); \
(rb->head + RB_buffer_size (rb) - rb->tail) % RB_buffer_size (rb); \
})
#define RB_WRITE_DATA(ring_buffer, data, count) \
({ __auto_type rb = &(ring_buffer); \
const typeof (rb->buffer[0]) *d = (data); \
unsigned c = (count); \
unsigned h = rb->head; \
rb->head = (h + c) % RB_buffer_size (rb); \
if (c > RB_buffer_size (rb) - h) { \
memcpy (rb->buffer + h, d, \
(RB_buffer_size (rb) - h) * sizeof (rb->buffer[0])); \
c -= RB_buffer_size (rb) - h; \
d += RB_buffer_size (rb) - h; \
h = 0; \
} \
memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \
})
#define RB_READ_DATA(ring_buffer, data, count) \
({ __auto_type rb = &(ring_buffer); \
typeof (&rb->buffer[0]) d = (data); \
unsigned c = (count); \
unsigned oc = c; \
unsigned t = rb->tail; \
if (c > RB_buffer_size (rb) - t) { \
memcpy (d, rb->buffer + t, \
(RB_buffer_size (rb) - t) * sizeof (rb->buffer[0])); \
c -= RB_buffer_size (rb) - t; \
d += RB_buffer_size (rb) - t; \
t = 0; \
} \
memcpy (d, rb->buffer + t, c * sizeof (rb->buffer[0])); \
rb->tail = (t + oc) % RB_buffer_size (rb); \
})
#define RB_DROP_DATA(ring_buffer, count) \
({ __auto_type rb = &(ring_buffer); \
unsigned c = (count); \
unsigned t = rb->tail; \
rb->tail = (t + c) % RB_buffer_size (rb); \
})
#define RB_PEEK_DATA(ring_buffer, ahead) \
({ __auto_type rb = &(ring_buffer); \
rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \
})
#define RB_POKE_DATA(ring_buffer, ahead, data) \
({ __auto_type rb = &(ring_buffer); \
rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)] = (data); \
})
#endif//__QF_ringbuffer_h

View file

@ -26,8 +26,8 @@
*/
// screen.h
#ifndef __screen_h
#define __screen_h
#ifndef __QF_screen_h
#define __QF_screen_h
#include "QF/qtypes.h"
@ -67,4 +67,4 @@ extern struct qpic_s *scr_turtle;
extern struct cvar_s *hud_fps, *hud_time;
#endif // __screen_h
#endif//__QF_screen_h

View file

@ -41,8 +41,9 @@ typedef struct script_s {
/// line number of the file being processed. used only for error reporting
/// but updated internally.
int line;
/// if set, will be called instead of the internal error handler
void (*error)(struct script_s *script, const char *msg);
/// contains last error message or null if no error
/// if set, no tokens will be parsed.
const char *error;
/// if set, multi line quoted tokens will be treated as errors
int no_quote_lines;
/// if set, characters in this string will always be lexed as single
@ -65,6 +66,7 @@ void Script_Delete (script_t *script);
/** Prepare a script_t object for parsing.
The caller is responsible for freeing the memory associated with file and
data when parsing is complete.
Resets \a script->error
\param script The script_t object being parsed
\param file Name of the file being parsed. used only for error reporting
\param data The script to be parsed

View file

@ -24,8 +24,8 @@
Boston, MA 02111-1307, USA
*/
#ifndef __sizebuf_h
#define __sizebuf_h
#ifndef __QF_sizebuf_h
#define __QF_sizebuf_h
/** \defgroup sizebuf Fixed Size Buffers
\ingroup utils
@ -53,4 +53,4 @@ void SZ_Print (sizebuf_t *buf, const char *data); // strcats onto the sizebuf
///@}
#endif // __sizebuf_h
#endif//__QF_sizebuf_h

View file

@ -25,8 +25,8 @@
*/
#ifndef _SKIN_H
#define _SKIN_H
#ifndef __QF_skin_h
#define __QF_skin_h
#include "QF/qtypes.h"
#include "QF/vid.h"
@ -57,4 +57,4 @@ typedef struct skin_s {
int auxtex;
} skin_t;
#endif
#endif//__QF_skin_h

View file

@ -26,8 +26,8 @@
*/
// sound.h -- client sound i/o functions
#ifndef _SOUND_H
#define _SOUND_H
#ifndef __QF_sound_h
#define __QF_sound_h
/** \defgroup sound QuakeForge sound engine
*/
@ -195,4 +195,4 @@ void S_Progs_Init (struct progs_s *pr);
///@}
#endif // _SOUND_H
#endif//__QF_sound_h

View file

@ -45,8 +45,8 @@
// <endrepeat>
//-------------------------------------------------------
#ifndef _SPRITEGN_H
#define _SPRITEGN_H
#ifndef __QF_sprintgn_h
#define __QF_sprintgn_h
#define SPR_VERSION 1
#define SP2_VERSION 2
@ -102,4 +102,4 @@ typedef struct {
// little-endian "IDS2"
#define IDHEADER_SP2 (('2'<<24)+('S'<<16)+('D'<<8)+'I')
#endif // _SPRITEGN_H
#endif//__QF_sprintgn_h

View file

@ -25,10 +25,10 @@
*/
#ifndef __sys_h
#define __sys_h
#ifndef __QF_sys_h
#define __QF_sys_h
/** \defgroup sys Portability
/** \defgroup sys System Portability
\ingroup utils
Non-portable functions
*/
@ -65,8 +65,8 @@ int Sys_mkdir (const char *path);
typedef void (*sys_printf_t) (const char *fmt, va_list args) __attribute__((format(printf, 1, 0)));
typedef void (*sys_error_t) (void *data);
void Sys_SetStdPrintf (sys_printf_t func);
void Sys_SetErrPrintf (sys_printf_t func);
sys_printf_t Sys_SetStdPrintf (sys_printf_t func);
sys_printf_t Sys_SetErrPrintf (sys_printf_t func);
void Sys_PushErrorHandler (sys_error_t func, void *data);
void Sys_PopErrorHandler (void);
@ -161,4 +161,4 @@ char *Sys_ExpandSquiggle (const char *path);
///@}
#endif // __sys_h
#endif//__QF_sys_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __teamplay_h
#define __teamplay_h
#ifndef __QF_teamplay_h
#define __QF_teamplay_h
extern struct cvar_s *cl_parsesay;
extern struct cvar_s *cl_nofake;
@ -47,4 +47,4 @@ const char *Team_ParseSay (struct dstring_s *buf, const char *);
void Locs_Init (void);
void Team_ParseChat (const char *string);
void Team_ResetTimers (void);
#endif // __teamplay_h
#endif//__QF_teamplay_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __tga_h
#define __tga_h
#ifndef __QF_tga_h
#define __QF_tga_h
#include "QF/qtypes.h"
#include "QF/quakeio.h"
@ -70,4 +70,4 @@ typedef struct _TargaHeader {
struct tex_s *LoadTGA (QFile *fin);
void WriteTGAfile (const char *tganame, byte *data, int width, int height);
#endif // __tga_h
#endif//__QF_tga_h

98
include/QF/txtbuffer.h Normal file
View file

@ -0,0 +1,98 @@
/*
txtbuffer.h
Text buffer for edit or scrollback
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
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
*/
#ifndef __QF_txtbuffer_h
#define __QF_txtbuffer_h
#include <stdint.h>
#include <stdlib.h>
/** \defgroup txtbuffer Text buffers
\ingroup utils
*/
///@{
/// must be a power of 2
#define TXTBUFFER_GROW 0x4000
/** Text buffer implementing efficient editing.
*/
typedef struct txtbuffer_s {
struct txtbuffer_s *next;
char *text;
size_t textSize; ///< amount of text in the buffer
size_t bufferSize; ///< current capacity of the buffer
size_t gapOffset; ///< beginning of the gap
size_t gapSize; ///< size of gap. gapSize + textSize == bufferSize
} txtbuffer_t;
/** Create a new, empty buffer.
*/
txtbuffer_t *TextBuffer_Create (void);
/** Destroy a buffer, freeing all resources connected to it.
\param buffer The buffer to destroy.
*/
void TextBuffer_Destroy (txtbuffer_t *buffer);
/** Insert a block of text at the specified offset.
Text after the offset is moved to be after the inserted block of text.
The buffer is resized as necessary.
nul characters are not significant in that they do not mark the end of
the text to be inserted.
\param buffer The buffer to be updated
\param offset The offset in the buffer at which to insert the text block
\param text The text block to be inserted. May contain nul ('\0')
characters.
\param text_len The number of characters to insert.
\return 1 for success, 0 for failure (offset not valid or out
of memory)
*/
int TextBuffer_InsertAt (txtbuffer_t *buffer, size_t offset,
const char *text, size_t text_len);
/** Delete a block of text from the buffer.
The buffer is not resized. Rather, its capacity before resizing is require
is increased.
\param buffer The buffer to be updated
\param offset The offset of the beginning of the text block to be deleted
\param len The amount of characters to be deleted. Values larger than
the amount of text in the buffer beyond the beginning of
block are truncated to the amount of remaining text. Thus
using excessivly large values sets the offset to be the
end of the buffer.
\return 1 for success, 0 for failure (offset not valid)
*/
int TextBuffer_DeleteAt (txtbuffer_t *buffer, size_t offset, size_t len);
///@}
#endif//__QF_txtbuffer_h

View file

@ -1,52 +0,0 @@
/*
uint32.h
Definitions for portable (?) unsigned int
Copyright (C) 2000 Jeff Teunissen <d2deek@pmail.net>
Author: Jeff Teunissen <d2deek@pmail.net>
Date: 01 Jan 2000
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
*/
#ifndef __uint32_h
#define __uint32_h
#ifndef int32
# if (SIZEOF_INT == 4)
# define int32 int
# elif (SIZEOF_LONG == 4)
# define int32 long
# elif (SIZEOF_SHORT == 4)
# define int32 short
# else
/* I hope this works */
# define int32 int
# define LARGE_INT32
# endif
#endif
#ifndef uint32
# define uint32 unsigned int32
#endif
#endif // __uint32_h

View file

@ -26,8 +26,8 @@
*/
#ifndef __va_h
#define __va_h
#ifndef __QF_va_h
#define __QF_va_h
/** \addtogroup misc
Formatted printing.
@ -41,4 +41,4 @@ char *nva(const char *format, ...) __attribute__((format(printf,1,2)));
///@}
#endif // __va_h
#endif//__QF_va_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __ver_check_h_
#define __ver_check_h_
#ifndef __QF_ver_check_h
#define __QF_ver_check_h
/** \defgroup utils Utils
*/
@ -47,4 +47,4 @@ int ver_compare (const char *, const char *);
///@}
#endif // __ver_check_h_
#endif//__QF_ver_check_h

View file

@ -25,8 +25,8 @@
*/
#ifndef __vid_h_
#define __vid_h_
#ifndef __QF_vid_h
#define __QF_vid_h
#include "QF/qtypes.h"
#include "QF/vrect.h"
@ -79,4 +79,4 @@ void VID_Init (byte *palette, byte *colormap);
void VID_SetCaption (const char *text);
void VID_ClearMemory (void);
#endif // __vid_h_
#endif//__QF_vid_h

View file

@ -28,8 +28,8 @@
*/
#ifndef __qf_view_h
#define __qf_view_h
#ifndef __QF_view_h
#define __QF_view_h
/** \defgroup console_view Console View Objects
\ingroup console
@ -217,4 +217,4 @@ void view_move (view_t *view, int xp, int yp);
///@}
#endif//__qf_view_h
#endif//__QF_view_h

View file

@ -26,8 +26,8 @@
*/
// wad.h
#ifndef _WAD_H
#define _WAD_H
#ifndef __QF_wad_h
#define __QF_wad_h
/** \addtogroup wad
Wad Files
@ -48,4 +48,4 @@ void SwapPic (qpic_t *pic);
///@}
#endif // _WAD_H
#endif//__QF_wad_h

View file

@ -24,8 +24,8 @@
Boston, MA 02111-1307, USA
*/
#ifndef __zone_h
#define __zone_h
#ifndef __QF_zone_h
#define __QF_zone_h
/** \defgroup zone Memory Management
\ingroup utils
@ -142,4 +142,4 @@ int Cache_ReadLock (cache_user_t *c) __attribute__((pure));
///@}
#endif // __zone_h
#endif//__QF_zone_h

View file

@ -39,8 +39,6 @@ void RUA_Cmd_Init (struct progs_s *pr, int secure);
void RUA_Cvar_Init (struct progs_s *pr, int secure);
void RUA_File_Init (struct progs_s *pr, int secure);
void RUA_Hash_Init (struct progs_s *pr, int secure);
void RUA_Math_Init (struct progs_s *pr, int secure);

View file

@ -130,9 +130,11 @@ bi_inputline_enter (inputline_t *il)
P_POINTER (pr, 0) = data->data[0];
P_POINTER (pr, 1) = data->data[1];
P_STRING (pr, 2) = PR_SetTempString (pr, line);
pr->pr_argc = 3;
} else {
P_STRING (pr, 0) = PR_SetTempString (pr, line);
P_POINTER (pr, 1) = data->data[0];
pr->pr_argc = 2;
}
PR_ExecuteProgram (pr, data->enter);
PR_PopFrame (pr);

View file

@ -92,7 +92,7 @@ Con_BufferAddText (con_buffer_t *buf, const char *text)
}
while (len--) {
byte c = *pos++ = *text++;
if ((size_t) (pos - buf->buffer) >= buf->buffer_size)
if (pos >= buf->buffer + buf->buffer_size)
pos = buf->buffer;
cur_line->len++;
if (pos == tail_line->text) {

View file

@ -117,7 +117,7 @@ static int
menu_resolve_globals (progs_t *pr)
{
const char *sym;
ddef_t *def;
pr_def_t *def;
dfunction_t *f;
size_t i;
@ -439,6 +439,7 @@ bi_Menu_Enter (progs_t *pr)
P_STRING (&menu_pr_state, 0) =
PR_SetTempString (&menu_pr_state, item->text);
P_INT (&menu_pr_state, 1) = 0;
pr->pr_argc = 2;
PR_ExecuteProgram (&menu_pr_state, item->func);
PR_PopFrame (&menu_pr_state);
run_menu_post ();
@ -510,9 +511,11 @@ menu_free_progs_mem (progs_t *pr, void *mem)
}
static void *
menu_load_file (progs_t *pr, const char *path)
menu_load_file (progs_t *pr, const char *path, off_t *size)
{
return QFS_LoadFile (QFS_FOpenFile (path), 0);
void *data = QFS_LoadFile (QFS_FOpenFile (path), 0);
*size = qfs_filesize;
return data;
}
static builtin_t builtins[] = {
@ -581,6 +584,8 @@ Menu_Init (void)
menu_pr_state.max_edicts = 0;
menu_pr_state.zone_size = 1024 * 1024;
PR_Init (&menu_pr_state);
menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0);
PR_RegisterBuiltins (&menu_pr_state, builtins);
@ -668,6 +673,7 @@ Menu_Draw (view_t *view)
PR_RESET_PARAMS (&menu_pr_state);
P_INT (&menu_pr_state, 0) = x;
P_INT (&menu_pr_state, 1) = y;
menu_pr_state.pr_argc = 2;
PR_ExecuteProgram (&menu_pr_state, menu->draw);
ret = R_INT (&menu_pr_state);
run_menu_post ();
@ -702,6 +708,7 @@ Menu_Draw (view_t *view)
PR_RESET_PARAMS (&menu_pr_state);
P_INT (&menu_pr_state, 0) = x + item->x;
P_INT (&menu_pr_state, 1) = y + item->y;
menu_pr_state.pr_argc = 2;
PR_ExecuteProgram (&menu_pr_state, menu->cursor);
run_menu_post ();
} else {
@ -734,6 +741,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down)
P_INT (&menu_pr_state, 0) = key;
P_INT (&menu_pr_state, 1) = unicode;
P_INT (&menu_pr_state, 2) = down;
menu_pr_state.pr_argc = 3;
PR_ExecuteProgram (&menu_pr_state, menu->keyevent);
ret = R_INT (&menu_pr_state);
run_menu_post ();
@ -748,6 +756,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down)
P_STRING (&menu_pr_state, 0) = PR_SetTempString (&menu_pr_state,
item->text);
P_INT (&menu_pr_state, 1) = key;
menu_pr_state.pr_argc = 2;
PR_ExecuteProgram (&menu_pr_state, item->func);
PR_PopFrame (&menu_pr_state);
ret = R_INT (&menu_pr_state);

View file

@ -47,7 +47,6 @@
#include "QF/quakefs.h"
#include "QF/sys.h"
#include "QF/zone.h"
#include "QF/va.h"
#include "compat.h"
@ -158,7 +157,8 @@ bi_no_function (progs_t *pr)
VISIBLE int
PR_RelocateBuiltins (progs_t *pr)
{
pr_int_t i, ind;
pr_uint_t i;
pr_int_t ind;
int bad = 0;
dfunction_t *desc;
bfunction_t *func;

File diff suppressed because it is too large Load diff

View file

@ -34,22 +34,10 @@
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include "QF/cbuf.h"
#include "QF/crc.h"
#include "QF/cvar.h"
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/idparse.h"
#include "QF/progs.h"
#include "QF/qdefs.h"
#include "QF/qendian.h"
#include "QF/quakefs.h"
#include "QF/sys.h"
#include "QF/zone.h"
#include "QF/va.h"
#include "compat.h"
@ -63,7 +51,7 @@ ED_ClearEdict (progs_t *pr, edict_t *e, int val)
{
pr_uint_t i;
if (NUM_FOR_EDICT (pr, e) < *pr->reserved_edicts)
if (pr->reserved_edicts && NUM_FOR_EDICT (pr, e) < *pr->reserved_edicts)
Sys_Printf ("clearing reserved edict %d\n", NUM_FOR_EDICT (pr, e));
for (i=0; i < pr->progs->entityfields; i++)
e->v[i].integer_var = val;
@ -86,6 +74,9 @@ ED_Alloc (progs_t *pr)
edict_t *e;
int start = pr->reserved_edicts ? *pr->reserved_edicts : 0;
if (!pr->num_edicts) {
PR_RunError (pr, "Edicts not supported in this VM\n");
}
for (i = start + 1; i < *pr->num_edicts; i++) {
e = EDICT_NUM (pr, i);
// the first couple seconds of server time can involve a lot of
@ -145,6 +136,10 @@ ED_Free (progs_t *pr, edict_t *ed)
VISIBLE void
ED_PrintNum (progs_t *pr, pr_int_t ent)
{
if (!pr->num_edicts) {
Sys_Printf ("Edicts not supported in this VM\n");
return;
}
ED_Print (pr, EDICT_NUM (pr, ent));
}
@ -158,13 +153,17 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval)
{
pr_int_t i;
int count;
ddef_t *def;
pr_def_t *def;
def = PR_FindField(pr, "classname");
if (!pr->num_edicts) {
Sys_Printf ("Edicts not supported in this VM\n");
return;
}
if (fieldval && fieldval[0] && def) {
count = 0;
for (i = 0; i < *(pr)->num_edicts; i++)
for (i = 0; i < *pr->num_edicts; i++)
if (strequal(fieldval,
E_GSTRING (pr, EDICT_NUM(pr, i), def->ofs))) {
ED_PrintNum (pr, i);
@ -172,9 +171,9 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval)
}
Sys_Printf ("%i entities\n", count);
} else {
for (i = 0; i < *(pr)->num_edicts; i++)
for (i = 0; i < *pr->num_edicts; i++)
ED_PrintNum (pr, i);
Sys_Printf ("%i entities\n", *(pr)->num_edicts);
Sys_Printf ("%i entities\n", *pr->num_edicts);
}
}
@ -188,14 +187,18 @@ ED_Count (progs_t *pr)
{
pr_int_t i;
int active, models, solid, step, zombie;
ddef_t *solid_def;
ddef_t *model_def;
pr_def_t *solid_def;
pr_def_t *model_def;
edict_t *ent;
if (!pr->num_edicts) {
Sys_Printf ("Edicts not supported in this VM\n");
return;
}
solid_def = PR_FindField (pr, "solid");
model_def = PR_FindField (pr, "model");
active = models = solid = step = zombie = 0;
for (i = 0; i < *(pr)->num_edicts; i++) {
for (i = 0; i < *pr->num_edicts; i++) {
ent = EDICT_NUM (pr, i);
if (ent->free) {
if (pr->globals.time && *pr->globals.time - ent->freetime <= 0.5)
@ -209,7 +212,7 @@ ED_Count (progs_t *pr)
models++;
}
Sys_Printf ("num_edicts:%3i\n", *(pr)->num_edicts);
Sys_Printf ("num_edicts:%3i\n", *pr->num_edicts);
Sys_Printf ("active :%3i\n", active);
Sys_Printf ("view :%3i\n", models);
Sys_Printf ("touch :%3i\n", solid);
@ -234,7 +237,7 @@ ED_NumForEdict (progs_t *pr, edict_t *e)
b = NUM_FOR_BAD_EDICT (pr, e);
if (b && (b < 0 || b >= *(pr)->num_edicts))
if (b && (b < 0 || b >= *pr->num_edicts))
PR_RunError (pr, "NUM_FOR_EDICT: bad pointer %d %p %p", b, e,
*(pr)->edicts);
@ -244,6 +247,9 @@ ED_NumForEdict (progs_t *pr, edict_t *e)
qboolean
PR_EdictValid (progs_t *pr, pr_int_t e)
{
if (!pr->num_edicts) {
return false;
}
if (e < 0 || e >= pr->pr_edictareasize)
return false;
if (e % pr->pr_edict_size)

View file

@ -68,41 +68,45 @@ PR_RunError (progs_t * pr, const char *error, ...)
// dump the stack so PR_Error can shutdown functions
pr->pr_depth = 0;
pr->localstack_used = 0;
PR_Error (pr, "Program error: %s", string->str);
}
VISIBLE void
PR_SaveParams (progs_t *pr)
VISIBLE pr_stashed_params_t *
_PR_SaveParams (progs_t *pr, pr_stashed_params_t *params)
{
int i;
int size = pr->pr_param_size * sizeof (pr_type_t);
pr->pr_param_ptrs[0] = pr->pr_params[0];
pr->pr_param_ptrs[1] = pr->pr_params[1];
params->param_ptrs[0] = pr->pr_params[0];
params->param_ptrs[1] = pr->pr_params[1];
pr->pr_params[0] = pr->pr_real_params[0];
pr->pr_params[1] = pr->pr_real_params[1];
for (i = 0; i < pr->pr_argc; i++) {
memcpy (pr->pr_saved_params + i * pr->pr_param_size,
memcpy (params->params + i * pr->pr_param_size,
pr->pr_real_params[i], size);
if (i < 2)
memcpy (pr->pr_real_params[i], pr->pr_param_ptrs[0], size);
if (i < 2) { //XXX FIXME what the what?!?
memcpy (pr->pr_real_params[i], params->param_ptrs[0], size);
}
}
pr->pr_saved_argc = pr->pr_argc;
params->argc = pr->pr_argc;
return params;
}
VISIBLE void
PR_RestoreParams (progs_t *pr)
PR_RestoreParams (progs_t *pr, pr_stashed_params_t *params)
{
int i;
int size = pr->pr_param_size * sizeof (pr_type_t);
pr->pr_params[0] = pr->pr_param_ptrs[0];
pr->pr_params[1] = pr->pr_param_ptrs[1];
pr->pr_argc = pr->pr_saved_argc;
for (i = 0; i < pr->pr_argc; i++)
pr->pr_params[0] = params->param_ptrs[0];
pr->pr_params[1] = params->param_ptrs[1];
pr->pr_argc = params->argc;
for (i = 0; i < pr->pr_argc; i++) {
memcpy (pr->pr_real_params[i],
pr->pr_saved_params + i * pr->pr_param_size, size);
params->params + i * pr->pr_param_size, size);
}
}
VISIBLE inline void
@ -119,7 +123,8 @@ PR_PushFrame (progs_t *pr)
frame->f = pr->pr_xfunction;
frame->tstr = pr->pr_xtstr;
pr->pr_xtstr = 0;
pr->pr_xtstr = pr->pr_pushtstr;
pr->pr_pushtstr = 0;
pr->pr_xfunction = 0;
}
@ -133,6 +138,17 @@ PR_PopFrame (progs_t *pr)
if (pr->pr_xtstr)
PR_FreeTempStrings (pr);
// normally, this won't happen, but if a builtin pushed a temp string
// when calling a function and the callee was another builtin that
// did not call a progs function, then the push strings will still be
// valid because PR_EnterFunction was never called
// however, not if a temp string survived: better to hold on to the push
// strings a little longer than lose one erroneously
if (!pr->pr_xtstr && pr->pr_pushtstr) {
pr->pr_xtstr = pr->pr_pushtstr;
pr->pr_pushtstr = 0;
PR_FreeTempStrings (pr);
}
// up stack
frame = pr->pr_stack + --pr->pr_depth;
@ -183,6 +199,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
if (pr->pr_params[i] != pr->pr_real_params[i]) {
copy_param (pr->pr_real_params[i], pr->pr_params[i],
f->parm_size[i].size);
pr->pr_params[i] = pr->pr_real_params[i];
}
}
} else if (f->numparms < 0) {
@ -194,6 +211,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
if (pr->pr_params[i] != pr->pr_real_params[i]) {
copy_param (pr->pr_real_params[i], pr->pr_params[i],
f->parm_size[i].size);
pr->pr_params[i] = pr->pr_real_params[i];
}
}
dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment };
@ -205,6 +223,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f)
if (pr->pr_params[i] != pr->pr_real_params[i]) {
copy_param (pr->pr_real_params[i], pr->pr_params[i],
parmsize.size);
pr->pr_params[i] = pr->pr_real_params[i];
}
}
}
@ -385,6 +404,14 @@ check_stack_pointer (progs_t *pr, pointer_t stack, int size)
}
}
static inline void
pr_memset (pr_type_t *dst, int val, int count)
{
while (count-- > 0) {
(*dst++).integer_var = val;
}
}
/*
PR_ExecuteProgram
@ -436,7 +463,16 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
if (pr->pr_trace)
PR_PrintStatement (pr, st, 1);
switch (st->op) {
if (st->op & OP_BREAK) {
if (pr->breakpoint_handler) {
pr->breakpoint_handler (pr);
} else {
PR_RunError (pr, "breakpoint hit");
}
}
pr_opcode_e op = st->op & ~OP_BREAK;
switch (op) {
case OP_ADD_D:
OPC_double_var = OPA_double_var + OPB_double_var;
break;
@ -1580,7 +1616,23 @@ op_call:
pr->pr_globals + OPA.integer_var,
st->b * 4);
break;
case OP_MEMSETI:
pr_memset (&OPC, OPA.integer_var, st->b);
break;
case OP_MEMSETP:
if (pr_boundscheck->int_val) {
PR_BoundsCheckSize (pr, OPC.pointer_var, OPB.integer_var);
}
pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var,
OPB.integer_var);
break;
case OP_MEMSETPI:
if (pr_boundscheck->int_val) {
PR_BoundsCheckSize (pr, OPC.pointer_var, st->b);
}
pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var,
st->b);
break;
case OP_GE_D:
OPC.float_var = OPA_double_var >= OPB_double_var;
break;
@ -1636,6 +1688,7 @@ op_call:
watch->integer_var);
}
exit_program:
pr->pr_argc = 0;
Sys_PopErrorHandler ();
Sys_PopSignalHook ();
}

View file

@ -34,22 +34,17 @@
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include "QF/cmd.h"
#include "QF/crc.h"
#include "QF/cvar.h"
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/mathlib.h"
#include "QF/progs.h"
#include "QF/qdefs.h"
#include "QF/qendian.h"
#include "QF/quakefs.h"
#include "QF/sys.h"
#include "QF/zone.h"
#include "QF/va.h"
#include "compat.h"
@ -70,8 +65,8 @@ static const char *
var_get_key (const void *d, void *_pr)
{
progs_t *pr = (progs_t*)_pr;
ddef_t *def = (ddef_t*)d;
return PR_GetString (pr, def->s_name);
pr_def_t *def = (pr_def_t*)d;
return PR_GetString (pr, def->name);
}
static void
@ -81,9 +76,11 @@ file_error (progs_t *pr, const char *path)
}
static void *
load_file (progs_t *pr, const char *path)
load_file (progs_t *pr, const char *path, off_t *size)
{
return QFS_LoadHunkFile (QFS_FOpenFile (path));
void *data = QFS_LoadHunkFile (QFS_FOpenFile (path));
*size = qfs_filesize;
return data;
}
static void *
@ -117,6 +114,9 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
dprograms_t progs;
byte *base;
byte *heap;
pr_def_t *xdefs_def = 0;
ddef_t *global_ddefs;
ddef_t *field_ddefs;
if (!pr->file_error)
pr->file_error = file_error;
@ -128,7 +128,6 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
pr->free_progs_mem = free_progs_mem;
PR_Resources_Clear (pr);
PR_ClearReturnStrings (pr);
if (pr->progs)
pr->free_progs_mem (pr, pr->progs);
pr->progs = 0;
@ -184,6 +183,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
pr->pr_edict_size = align_size (pr->pr_edict_size);
pr->pr_edictareasize = pr->max_edicts * pr->pr_edict_size;
pr->edict_parse = 0;
mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize
+ pr->stack_size;
@ -202,12 +202,11 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
base -= sizeof (progs); // offsets are from file start
heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize);
pr->float_promoted = progs.version == PROG_VERSION;
if (pr->edicts) {
*pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size);
}
pr->zone = 0;
if (pr->zone_size) {
//FIXME zone_size needs to be at least as big as memzone_t, but
//memzone_t is opaque so its size is unknown
@ -218,8 +217,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
(dfunction_t *) (base + pr->progs->ofs_functions);
pr->pr_strings = (char *) base + pr->progs->ofs_strings;
pr->pr_stringsize = (char *) heap + pr->zone_size - (char *) base;
pr->pr_globaldefs = (ddef_t *) (base + pr->progs->ofs_globaldefs);
pr->pr_fielddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs);
global_ddefs = (ddef_t *) (base + pr->progs->ofs_globaldefs);
field_ddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs);
pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements);
pr->pr_globals = (pr_type_t *) (base + pr->progs->ofs_globals);
@ -270,24 +269,67 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size)
Hash_Add (pr->function_hash, &pr->pr_functions[i]);
}
if (pr->pr_globaldefs) {
free (pr->pr_globaldefs);
}
pr->pr_globaldefs = calloc (pr->progs->numglobaldefs, sizeof (pr_def_t));
for (i = 0; i < pr->progs->numglobaldefs; i++) {
pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type);
pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs);
pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name);
pr_ushort_t safe_type = global_ddefs[i].type & ~DEF_SAVEGLOBAL;
global_ddefs[i].type = LittleShort (global_ddefs[i].type);
global_ddefs[i].ofs = LittleShort (global_ddefs[i].ofs);
global_ddefs[i].s_name = LittleLong (global_ddefs[i].s_name);
pr->pr_globaldefs[i].type = global_ddefs[i].type;
pr->pr_globaldefs[i].size = pr_type_size[safe_type];
pr->pr_globaldefs[i].ofs = global_ddefs[i].ofs;
pr->pr_globaldefs[i].name = global_ddefs[i].s_name;
Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]);
}
if (pr->pr_fielddefs) {
free (pr->pr_fielddefs);
}
pr->pr_fielddefs = calloc (pr->progs->numfielddefs, sizeof (pr_def_t));
for (i = 0; i < pr->progs->numfielddefs; i++) {
pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type);
if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL)
PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs);
pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name);
field_ddefs[i].type = LittleShort (field_ddefs[i].type);
if (field_ddefs[i].type & DEF_SAVEGLOBAL)
PR_Error (pr, "PR_LoadProgs: DEF_SAVEGLOBAL on field def %zd", i);
field_ddefs[i].ofs = LittleShort (field_ddefs[i].ofs);
field_ddefs[i].s_name = LittleLong (field_ddefs[i].s_name);
pr->pr_fielddefs[i].type = field_ddefs[i].type;
pr->pr_fielddefs[i].ofs = field_ddefs[i].ofs;
pr->pr_fielddefs[i].name = field_ddefs[i].s_name;
Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]);
}
for (i = 0; i < pr->progs->numglobals; i++)
((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]);
xdefs_def = PR_FindGlobal (pr, ".xdefs");
if (xdefs_def) {
pr_xdefs_t *xdefs = &G_STRUCT (pr, pr_xdefs_t, xdefs_def->ofs);
xdef_t *xdef = &G_STRUCT (pr, xdef_t, xdefs->xdefs);
pr_def_t *def;
for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs;
i++, xdef++, def++) {
def->ofs = xdef->ofs;
def->type_encoding = xdef->type;
}
for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs;
i++, xdef++, def++) {
def->ofs = xdef->ofs;
def->type_encoding = xdef->type;
}
}
pr->pr_trace = 0;
pr->pr_trace_depth = 0;
pr->pr_xfunction = 0;
pr->pr_xstatement = 0;
pr->pr_depth = 0;
pr->localstack_used = 0;
pr->pr_argc = 0;
}
VISIBLE void
@ -321,7 +363,7 @@ PR_AddLoadFinishFunc (progs_t *pr, int (*func)(progs_t *))
static int
pr_run_ctors (progs_t *pr)
{
pr_int_t fnum;
pr_uint_t fnum;
dfunction_t *func;
for (fnum = 0; fnum < pr->progs->numfunctions; fnum++) {
@ -333,9 +375,7 @@ pr_run_ctors (progs_t *pr)
}
static int (*load_funcs_1[])(progs_t *) = {
PR_LoadStrings,
PR_RelocateBuiltins,
PR_LoadDebug,
0,
};
@ -427,10 +467,12 @@ PR_Init_Cvars (void)
}
VISIBLE void
PR_Init (void)
PR_Init (progs_t *pr)
{
PR_Opcode_Init ();
PR_Debug_Init ();
PR_Opcode_Init (); // idempotent
PR_Resources_Init (pr);
PR_Strings_Init (pr);
PR_Debug_Init (pr);
}
VISIBLE void

View file

@ -46,9 +46,9 @@
#include "compat.h"
hashtab_t *opcode_table;
static hashtab_t *opcode_table;
VISIBLE int pr_type_size[ev_type_count] = {
VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = {
1, // ev_void
1, // ev_string
1, // ev_float
@ -62,9 +62,10 @@ VISIBLE int pr_type_size[ev_type_count] = {
1, // ev_uinteger
0, // ev_short value in opcode
2, // ev_double
0, // ev_invalid not a valid/simple type
};
VISIBLE const char *pr_type_name[ev_type_count] = {
VISIBLE const char * const pr_type_name[ev_type_count] = {
"void",
"string",
"float",
@ -97,7 +98,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = {
// c operand c
// x place holder for P (padding)
// 0-7 parameter index (for P)
VISIBLE opcode_t pr_opcodes[] = {
VISIBLE const opcode_t pr_opcodes[] = {
{"<DONE>", "done", OP_DONE, false, // OP_DONE is actually the same as
ev_entity, ev_field, ev_void, // OP_RETURN, the types are bogus
PROG_ID_VERSION,
@ -543,12 +544,12 @@ VISIBLE opcode_t pr_opcodes[] = {
{"&", "lea", OP_LEA, false,
ev_pointer, ev_integer, ev_pointer,
PROG_VERSION,
"%Ga, %Gb, %gc",
"(%Ga + %Gb), %gc",
},
{"&", "leai", OP_LEAI, false,
ev_pointer, ev_short, ev_pointer,
PROG_VERSION,
"%Ga, %sb, %gc",
"(%Ga + %sb), %gc",
},
{"<CONV>", "conv.if", OP_CONV_IF, false,
@ -1180,8 +1181,23 @@ VISIBLE opcode_t pr_opcodes[] = {
{"<MOVEP>", "movepi", OP_MOVEPI, true,
ev_pointer, ev_short, ev_pointer,
PROG_VERSION,
"%Ga, %sb, %Gc",
},
{"<MEMSET>", "memseti", OP_MEMSETI, true,
ev_integer, ev_short, ev_void,
PROG_VERSION,
"%Ga, %sb, %gc",
},
{"<MEMSETP>", "memsetp", OP_MEMSETP, true,
ev_integer, ev_integer, ev_pointer,
PROG_VERSION,
"%Ga, %Gb, %Gc",
},
{"<MEMSETP>", "memsetpi", OP_MEMSETPI, true,
ev_integer, ev_short, ev_pointer,
PROG_VERSION,
"%Ga, %sb, %Gc",
},
{"<PUSH>", "push.s", OP_PUSH_S, false,
ev_string, ev_invalid, ev_invalid,
@ -1491,13 +1507,17 @@ PR_Opcode (pr_short_t opcode)
VISIBLE void
PR_Opcode_Init (void)
{
opcode_t *op;
const opcode_t *op;
if (opcode_table) {
// already initialized
return;
}
opcode_table = Hash_NewTable (1021, 0, 0, 0);
Hash_SetHashCompare (opcode_table, opcode_get_hash, opcode_compare);
for (op = pr_opcodes; op->name; op++) {
Hash_AddElement (opcode_table, op);
Hash_AddElement (opcode_table, (void *) op);
}
}
@ -1535,7 +1555,7 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
unsigned short operand, int check_denorm)
{
const char *msg;
ddef_t *def;
pr_def_t *def;
switch (type) {
case ev_short:
@ -1695,6 +1715,9 @@ PR_Check_Opcodes (progs_t *pr)
check_global_size (pr, st, op, st->b, st->a);
check_global_size (pr, st, op, st->b, st->c);
break;
case OP_MEMSETI:
check_global_size (pr, st, op, st->b, st->c);
break;
case OP_PUSHB_F:
case OP_PUSHB_S:
case OP_PUSHB_ENT:

View file

@ -43,21 +43,12 @@
#include <malloc.h>
#endif
#include "QF/cbuf.h"
#include "QF/crc.h"
#include "QF/cvar.h"
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/mathlib.h"
#include "QF/progs.h"
#include "QF/qdefs.h"
#include "QF/qfplist.h"
#include "QF/qendian.h"
#include "QF/quakefs.h"
#include "QF/script.h"
#include "QF/sys.h"
#include "QF/zone.h"
#include "QF/va.h"
#include "compat.h"
@ -68,15 +59,11 @@
Easier to parse than PR_ValueString
*/
static const char *
PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val)
PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line)
{
static dstring_t *line = 0;
ddef_t *def;
pr_def_t *def;
dfunction_t *f;
if (!line)
line = dstring_new ();
type &= ~DEF_SAVEGLOBAL;
switch (type) {
@ -93,7 +80,7 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val)
break;
case ev_field:
def = PR_FieldAtOfs (pr, val->integer_var);
dsprintf (line, "%s", PR_GetString (pr, def->s_name));
dsprintf (line, "%s", PR_GetString (pr, def->name));
break;
case ev_void:
dstring_copystr (line, "void");
@ -121,6 +108,7 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val)
VISIBLE plitem_t *
ED_EntityDict (progs_t *pr, edict_t *ed)
{
dstring_t *dstr = dstring_newstr ();
plitem_t *entity = PL_NewDictionary ();
pr_uint_t i;
int j;
@ -131,9 +119,9 @@ ED_EntityDict (progs_t *pr, edict_t *ed)
if (!ed->free) {
for (i = 0; i < pr->progs->numfielddefs; i++) {
ddef_t *d = &pr->pr_fielddefs[i];
pr_def_t *d = &pr->pr_fielddefs[i];
name = PR_GetString (pr, d->s_name);
name = PR_GetString (pr, d->name);
if (!name[0])
continue; // skip unnamed fields
if (name[strlen (name) - 2] == '_')
@ -149,10 +137,11 @@ ED_EntityDict (progs_t *pr, edict_t *ed)
if (j == pr_type_size[type])
continue;
value = PR_UglyValueString (pr, type, v);
value = PR_UglyValueString (pr, type, v, dstr);
PL_D_AddObject (entity, name, PL_NewString (value));
}
}
dstring_delete (dstr);
return entity;
}
@ -165,11 +154,12 @@ ED_EntityDict (progs_t *pr, edict_t *ed)
VISIBLE plitem_t *
ED_GlobalsDict (progs_t *pr)
{
dstring_t *dstr = dstring_newstr ();
plitem_t *globals = PL_NewDictionary ();
pr_uint_t i;
const char *name;
const char *value;
ddef_t *def;
pr_def_t *def;
int type;
for (i = 0; i < pr->progs->numglobaldefs; i++) {
@ -182,10 +172,11 @@ ED_GlobalsDict (progs_t *pr)
if (type != ev_string && type != ev_float && type != ev_entity)
continue;
name = PR_GetString (pr, def->s_name);
value = PR_UglyValueString (pr, type, &pr->pr_globals[def->ofs]);
name = PR_GetString (pr, def->name);
value = PR_UglyValueString (pr, type, &pr->pr_globals[def->ofs], dstr);
PL_D_AddObject (globals, name, PL_NewString (value));
}
dstring_delete (dstr);
return globals;
}
@ -222,11 +213,11 @@ ED_NewString (progs_t *pr, const char *string)
returns false if error
*/
VISIBLE qboolean
ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s)
ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s)
{
int i;
char *string;
ddef_t *def;
pr_def_t *def;
char *v, *w;
pr_type_t *d;
dfunction_t *func;
@ -301,6 +292,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s)
VISIBLE plitem_t *
ED_ConvertToPlist (script_t *script, int nohack)
{
dstring_t *dstr = dstring_newstr ();
plitem_t *plist = PL_NewArray ();
plitem_t *ent;
plitem_t *key;
@ -341,15 +333,18 @@ ED_ConvertToPlist (script_t *script, int nohack)
token = script->token->str;
if (strequal (token, "}"))
Sys_Error ("ED_ConvertToPlist: closing brace without data");
if (anglehack)
value = PL_NewString (va ("0 %s 0", token));
else
if (anglehack) {
dsprintf (dstr, "0 %s 0", token);
value = PL_NewString (dstr->str);
} else {
value = PL_NewString (token);
}
PL_D_AddObject (ent, PL_String (key), value);
PL_Free (key);
}
PL_A_AddObject (plist, ent);
}
dstring_delete (dstr);
return plist;
}
@ -357,8 +352,8 @@ ED_ConvertToPlist (script_t *script, int nohack)
VISIBLE void
ED_InitGlobals (progs_t *pr, plitem_t *globals)
{
ddef_t vector_def;
ddef_t *global;
pr_def_t vector_def;
pr_def_t *global;
plitem_t *keys;
int count;
const char *global_name;
@ -405,7 +400,7 @@ ED_InitGlobals (progs_t *pr, plitem_t *globals)
VISIBLE void
ED_InitEntity (progs_t *pr, plitem_t *entity, edict_t *ent)
{
ddef_t *field;
pr_def_t *field;
plitem_t *keys;
const char *field_name;
const char *value;
@ -524,6 +519,7 @@ ED_LoadFromFile (progs_t *pr, const char *data)
PR_PushFrame (pr);
PR_RESET_PARAMS (pr);
P_INT (pr, 0) = PR_SetTempString (pr, data);
pr->pr_argc = 1;
PR_ExecuteProgram (pr, pr->edict_parse);
PR_PopFrame (pr);
return;

View file

@ -34,59 +34,59 @@
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include "QF/cmd.h"
#include "QF/crc.h"
#include "QF/cvar.h"
#include "QF/hash.h"
#include "QF/progs.h"
#include "QF/qdefs.h"
#include "QF/qendian.h"
#include "QF/quakefs.h"
#include "QF/sys.h"
#include "QF/zone.h"
#include "QF/va.h"
#include "compat.h"
static const char param_str[] = ".param_0";
ddef_t *
PR_GlobalAtOfs (progs_t * pr, pr_int_t ofs)
pr_def_t *
PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset)
{
ddef_t *def;
pr_uint_t i;
// fuzzy bsearh
unsigned left = 0;
unsigned right = num_defs - 1;
unsigned mid;
for (i = 0; i < pr->progs->numglobaldefs; i++) {
def = &pr->pr_globaldefs[i];
if (def->ofs == ofs)
return def;
if (!num_defs) {
return 0;
}
return NULL;
while (left != right) {
mid = (left + right + 1) / 2;
if (defs[mid].ofs > offset) {
right = mid - 1;
} else {
left = mid;
}
}
if (defs[left].ofs <= offset) {
return defs + left;
}
return 0;
}
VISIBLE ddef_t *
PR_FieldAtOfs (progs_t * pr, pr_int_t ofs)
pr_def_t *
PR_GlobalAtOfs (progs_t * pr, pointer_t ofs)
{
ddef_t *def;
pr_uint_t i;
for (i = 0; i < pr->progs->numfielddefs; i++) {
def = &pr->pr_fielddefs[i];
if (def->ofs == ofs)
return def;
}
return NULL;
return PR_SearchDefs (pr->pr_globaldefs, pr->progs->numglobaldefs, ofs);
}
VISIBLE ddef_t *
VISIBLE pr_def_t *
PR_FieldAtOfs (progs_t * pr, pointer_t ofs)
{
return PR_SearchDefs (pr->pr_fielddefs, pr->progs->numfielddefs, ofs);
}
VISIBLE pr_def_t *
PR_FindField (progs_t * pr, const char *name)
{
return Hash_Find (pr->field_hash, name);
}
VISIBLE ddef_t *
VISIBLE pr_def_t *
PR_FindGlobal (progs_t * pr, const char *name)
{
return Hash_Find (pr->global_hash, name);
@ -108,7 +108,7 @@ VISIBLE int
PR_ResolveGlobals (progs_t *pr)
{
const char *sym;
ddef_t *def;
pr_def_t *def;
int i;
if (pr->progs->version == PROG_ID_VERSION) {
@ -124,11 +124,14 @@ PR_ResolveGlobals (progs_t *pr)
pr->pr_param_size = OFS_PARM1 - OFS_PARM0;
pr->pr_param_alignment = 0; // log2
} else {
char *param_n = alloca (sizeof (param_str));
strcpy (param_n, param_str);
if (!(def = PR_FindGlobal (pr, sym = ".return")))
goto error;
pr->pr_return = &pr->pr_globals[def->ofs];
for (i = 0; i < MAX_PARMS; i++) {
if (!(def = PR_FindGlobal (pr, sym = va(".param_%d", i))))
param_n[sizeof (param_str) - 2] = i + '0';
if (!(def = PR_FindGlobal (pr, sym = param_n)))
goto error;
pr->pr_params[i] = &pr->pr_globals[def->ofs];
}
@ -139,10 +142,6 @@ PR_ResolveGlobals (progs_t *pr)
goto error;
pr->pr_param_alignment = G_INT (pr, def->ofs);
}
if (pr->pr_saved_params)
free (pr->pr_saved_params);
pr->pr_saved_params = calloc (pr->pr_param_size * MAX_PARMS,
sizeof (pr_type_t));
memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params));
if (!pr->globals.time) {
if ((def = PR_FindGlobal (pr, "time")))
@ -180,7 +179,7 @@ int
PR_AccessField (progs_t *pr, const char *name, etype_t type,
const char *file, int line)
{
ddef_t *def = PR_FindField (pr, name);
pr_def_t *def = PR_FindField (pr, name);
if (!def)
PR_Error (pr, "undefined field %s accessed at %s:%d", name, file, line);

View file

@ -42,26 +42,6 @@
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/progs.h"
#include "QF/va.h"
typedef enum {
str_free,
str_static,
str_dynamic,
str_mutable,
str_temp,
str_return,
} str_e;
struct strref_s {
strref_t *next;
strref_t **prev;
str_e type;
union {
char *string;
dstring_t *dstring;
} s;
};
// format adjustments
#define FMT_ALTFORM (1<<0)
@ -87,7 +67,45 @@ typedef struct fmt_item_s {
struct fmt_item_s *next;
} fmt_item_t;
static fmt_item_t *free_fmt_items;
typedef struct strref_slot_s {
struct strref_slot_s *next;
struct strref_slot_s **prev;
strref_t *strref;
} strref_slot_t;
typedef struct prstr_resources_s {
progs_t *pr;
dstring_mem_t ds_mem;
strref_t *free_string_refs;
strref_t *static_strings;
strref_t **string_map;
strref_slot_t return_strings[PR_RS_SLOTS];
strref_slot_t *rs_slot;
unsigned dyn_str_size;
struct hashtab_s *strref_hash;
int num_strings;
fmt_item_t *free_fmt_items;
dstring_t *print_str;
} prstr_resources_t;
typedef enum {
str_free,
str_static,
str_dynamic,
str_mutable,
str_temp,
str_return,
} str_e;
struct strref_s {
strref_t *next;
strref_slot_t *rs_slot;
str_e type;
union {
char *string;
dstring_t *dstring;
} s;
};
static void *
pr_strings_alloc (void *_pr, size_t size)
@ -111,51 +129,50 @@ pr_strings_realloc (void *_pr, void *ptr, size_t size)
}
static strref_t *
new_string_ref (progs_t *pr)
new_string_ref (prstr_resources_t *res)
{
strref_t *sr;
if (!pr->free_string_refs) {
if (!res->free_string_refs) {
int i;
size_t size;
pr->dyn_str_size++;
size = pr->dyn_str_size * sizeof (strref_t *);
pr->string_map = realloc (pr->string_map, size);
if (!pr->string_map)
PR_Error (pr, "out of memory");
if (!(pr->free_string_refs = calloc (1024, sizeof (strref_t))))
PR_Error (pr, "out of memory");
pr->string_map[pr->dyn_str_size - 1] = pr->free_string_refs;
for (i = 0, sr = pr->free_string_refs; i < 1023; i++, sr++)
res->dyn_str_size++;
size = res->dyn_str_size * sizeof (strref_t *);
res->string_map = realloc (res->string_map, size);
if (!res->string_map)
PR_Error (res->pr, "out of memory");
if (!(res->free_string_refs = calloc (1024, sizeof (strref_t))))
PR_Error (res->pr, "out of memory");
res->string_map[res->dyn_str_size - 1] = res->free_string_refs;
for (i = 0, sr = res->free_string_refs; i < 1023; i++, sr++)
sr->next = sr + 1;
sr->next = 0;
}
sr = pr->free_string_refs;
pr->free_string_refs = sr->next;
sr = res->free_string_refs;
res->free_string_refs = sr->next;
sr->next = 0;
sr->rs_slot = 0;
return sr;
}
static void
free_string_ref (progs_t *pr, strref_t *sr)
free_string_ref (prstr_resources_t *res, strref_t *sr)
{
sr->type = str_free;
if (sr->prev)
*sr->prev = sr->next;
sr->next = pr->free_string_refs;
pr->free_string_refs = sr;
sr->next = res->free_string_refs;
res->free_string_refs = sr;
}
static __attribute__((pure)) string_t
string_index (progs_t *pr, strref_t *sr)
string_index (prstr_resources_t *res, strref_t *sr)
{
long o = (long) (sr - pr->static_strings);
long o = (long) (sr - res->static_strings);
unsigned i;
if (o >= 0 && o < pr->num_strings)
return sr->s.string - pr->pr_strings;
for (i = 0; i < pr->dyn_str_size; i++) {
int d = sr - pr->string_map[i];
if (o >= 0 && o < res->num_strings)
return sr->s.string - res->pr->pr_strings;
for (i = 0; i < res->dyn_str_size; i++) {
int d = sr - res->string_map[i];
if (d >= 0 && d < 1024)
return ~(i * 1024 + d);
}
@ -172,70 +189,124 @@ strref_get_key (const void *_sr, void *notused)
}
static void
strref_free (void *_sr, void *_pr)
strref_free (void *_sr, void *_res)
{
progs_t *pr = (progs_t*)_pr;
strref_t *sr = (strref_t*)_sr;
__auto_type res = (prstr_resources_t *) _res;
__auto_type sr = (strref_t *) _sr;
// Since this is called only by Hash_FlushTable, the memory pointed
// to by sr->string or sr->dstring has already been lost in the progs
// load/reload and thus there's no need to free it.
// free the string and ref only if it's not a static string
if (sr < pr->static_strings || sr >= pr->static_strings + pr->num_strings) {
free_string_ref (pr, sr);
if (sr < res->static_strings
|| sr >= res->static_strings + res->num_strings) {
free_string_ref (res, sr);
}
}
VISIBLE int
static void
pr_strings_clear (progs_t *pr, void *data)
{
__auto_type res = (prstr_resources_t *) data;
int i;
for (i = 0; i < PR_RS_SLOTS; i++) {
if (res->return_strings[i].strref)
free_string_ref (res, res->return_strings[i].strref);
res->return_strings[i].strref = 0;
}
if (!res->rs_slot) {
strref_slot_t * const rs = res->return_strings;
for (i = 0; i < PR_RS_SLOTS; i++) {
rs[i].next = &rs[(i + 1) % PR_RS_SLOTS];
rs[i].prev = &rs[(i - 1 + PR_RS_SLOTS) % PR_RS_SLOTS].next;
}
res->rs_slot = rs;
}
pr->pr_string_resources = res;
pr->pr_xtstr = 0;
}
static int
PR_LoadStrings (progs_t *pr)
{
prstr_resources_t *res = PR_Resources_Find (pr, "Strings");
char *end = pr->pr_strings + pr->progs->numstrings;
char *str = pr->pr_strings;
int count = 0;
pr->float_promoted = 0;
while (str < end) {
count++;
if (*str == '@' && pr->progs->version == PROG_VERSION) {
if (!strcmp (str, "@float_promoted@")) {
pr->float_promoted = 1;
}
}
str += strlen (str) + 1;
}
if (!pr->ds_mem) {
pr->ds_mem = malloc (sizeof (dstring_mem_t));
pr->ds_mem->alloc = pr_strings_alloc;
pr->ds_mem->free = pr_strings_free;
pr->ds_mem->realloc = pr_strings_realloc;
pr->ds_mem->data = pr;
}
if (pr->strref_hash) {
Hash_FlushTable (pr->strref_hash);
res->ds_mem.alloc = pr_strings_alloc;
res->ds_mem.free = pr_strings_free;
res->ds_mem.realloc = pr_strings_realloc;
res->ds_mem.data = pr;
if (res->strref_hash) {
Hash_FlushTable (res->strref_hash);
} else {
pr->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free,
pr);
pr->string_map = 0;
pr->free_string_refs = 0;
pr->dyn_str_size = 0;
res->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free,
res);
res->string_map = 0;
res->free_string_refs = 0;
res->dyn_str_size = 0;
}
if (pr->static_strings)
free (pr->static_strings);
pr->static_strings = malloc (count * sizeof (strref_t));
if (res->static_strings)
free (res->static_strings);
res->static_strings = calloc (count, sizeof (strref_t));
count = 0;
str = pr->pr_strings;
while (str < end) {
if (!Hash_Find (pr->strref_hash, str)) {
pr->static_strings[count].type = str_static;
pr->static_strings[count].s.string = str;
Hash_Add (pr->strref_hash, &pr->static_strings[count]);
if (!Hash_Find (res->strref_hash, str)) {
res->static_strings[count].type = str_static;
res->static_strings[count].s.string = str;
Hash_Add (res->strref_hash, &res->static_strings[count]);
count++;
}
str += strlen (str) + 1;
}
pr->num_strings = count;
res->num_strings = count;
return 1;
}
static void
requeue_strref (prstr_resources_t *res, strref_t *sr)
{
strref_slot_t *rs_slot = sr->rs_slot;
if (rs_slot->next != res->rs_slot) {
// this is the oldest slot, so advance res->rs_slot to the
// next oldest slot so this slot does not get reused just yet
if (res->rs_slot == rs_slot) {
res->rs_slot = rs_slot->next;
}
// unlink this slot from the chain
rs_slot->next->prev = rs_slot->prev;
*rs_slot->prev = rs_slot->next;
// link this slot just before the oldest slot: all the slots
// form a doubly linked circular list
rs_slot->prev = res->rs_slot->prev;
rs_slot->next = res->rs_slot;
*res->rs_slot->prev = rs_slot;
res->rs_slot->prev = &rs_slot->next;
}
}
static inline strref_t *
get_strref (progs_t *pr, string_t num)
get_strref (prstr_resources_t *res, string_t num)
{
if (num < 0) {
strref_t *ref;
@ -243,9 +314,9 @@ get_strref (progs_t *pr, string_t num)
num = ~num % 1024;
if (row >= pr->dyn_str_size)
if (row >= res->dyn_str_size)
return 0;
ref = &pr->string_map[row][num];
ref = &res->string_map[row][num];
if (ref->type == str_free)
return 0;
return ref;
@ -256,22 +327,24 @@ get_strref (progs_t *pr, string_t num)
static inline __attribute__((pure)) const char *
get_string (progs_t *pr, string_t num)
{
__auto_type res = pr->pr_string_resources;
if (num < 0) {
strref_t *ref = get_strref (pr, num);
strref_t *ref = get_strref (res, num);
if (!ref)
return 0;
switch (ref->type) {
case str_return:
requeue_strref (res, ref);
case str_static:
case str_temp:
case str_dynamic:
case str_return:
return ref->s.string;
case str_mutable:
return ref->s.dstring->str;
case str_free:
break;
}
PR_Error (pr, "internal string error");
PR_Error (pr, "internal string error: %d", __LINE__);
} else {
if (num >= pr->pr_stringsize)
return 0;
@ -282,7 +355,10 @@ get_string (progs_t *pr, string_t num)
VISIBLE qboolean
PR_StringValid (progs_t *pr, string_t num)
{
return get_string (pr, num) != 0;
if (num >= 0) {
return num < pr->pr_stringsize;
}
return get_strref (pr->pr_string_resources, num) != 0;
}
VISIBLE const char *
@ -299,7 +375,7 @@ PR_GetString (progs_t *pr, string_t num)
VISIBLE dstring_t *
PR_GetMutableString (progs_t *pr, string_t num)
{
strref_t *ref = get_strref (pr, num);
strref_t *ref = get_strref (pr->pr_string_resources, num);
if (ref) {
if (ref->type == str_mutable)
return ref->s.dstring;
@ -308,10 +384,16 @@ PR_GetMutableString (progs_t *pr, string_t num)
PR_RunError (pr, "Invalid string offset: %d", num);
}
static inline void *
pr_strmalloc (progs_t *pr, size_t size)
{
return PR_Zone_Malloc (pr, size);
}
static inline char *
pr_stralloc (progs_t *pr, size_t len)
{
return PR_Zone_Malloc (pr, len + 1);
return pr_strmalloc (pr, len + 1);
}
static inline void
@ -331,70 +413,72 @@ pr_strdup (progs_t *pr, const char *s)
VISIBLE string_t
PR_SetString (progs_t *pr, const char *s)
{
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr;
if (!s)
s = "";
sr = Hash_Find (pr->strref_hash, s);
sr = Hash_Find (res->strref_hash, s);
if (__builtin_expect (!sr, 1)) {
sr = new_string_ref (pr);
sr = new_string_ref (res);
sr->type = str_static;
sr->s.string = pr_strdup(pr, s);
Hash_Add (pr->strref_hash, sr);
}
return string_index (pr, sr);
}
void
PR_ClearReturnStrings (progs_t *pr)
{
int i;
for (i = 0; i < PR_RS_SLOTS; i++) {
if (pr->return_strings[i])
free_string_ref (pr, pr->return_strings[i]);
pr->return_strings[i] = 0;
Hash_Add (res->strref_hash, sr);
}
return string_index (res, sr);
}
VISIBLE string_t
PR_SetReturnString (progs_t *pr, const char *s)
{
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr;
if (!s)
s = "";
if ((sr = Hash_Find (pr->strref_hash, s))) {
return string_index (pr, sr);
if ((sr = Hash_Find (res->strref_hash, s))) {
if (sr->type == str_return && sr->rs_slot) {
requeue_strref (res, sr);
} else if ((sr->type == str_return && !sr->rs_slot)
|| (sr->type != str_return && sr->rs_slot)) {
PR_Error (pr, "internal string error: %d %d %p", __LINE__,
sr->type, sr->rs_slot);
}
return string_index (res, sr);
}
if ((sr = pr->return_strings[pr->rs_slot])) {
if (sr->type != str_return)
PR_Error (pr, "internal string error");
// grab the string ref from the oldest slot, or make a new one if the
// slot is empty
if ((sr = res->rs_slot->strref)) {
if (sr->type != str_return || sr->rs_slot != res->rs_slot) {
PR_Error (pr, "internal string error: %d", __LINE__);
}
pr_strfree (pr, sr->s.string);
} else {
sr = new_string_ref (pr);
sr = new_string_ref (res);
}
sr->type = str_return;
sr->rs_slot = res->rs_slot;
sr->s.string = pr_strdup(pr, s);
pr->return_strings[pr->rs_slot++] = sr;
pr->rs_slot %= PR_RS_SLOTS;
return string_index (pr, sr);
// the oldest slot just became the newest, so advance to the next oldest
res->rs_slot = res->rs_slot->next;
return string_index (res, sr);
}
static inline string_t
pr_settempstring (progs_t *pr, char *s)
pr_settempstring (progs_t *pr, prstr_resources_t *res, char *s)
{
strref_t *sr;
sr = new_string_ref (pr);
sr = new_string_ref (res);
sr->type = str_temp;
sr->s.string = s;
sr->next = pr->pr_xtstr;
pr->pr_xtstr = sr;
return string_index (pr, sr);
return string_index (res, sr);
}
VISIBLE string_t
@ -410,46 +494,77 @@ PR_CatStrings (progs_t *pr, const char *a, const char *b)
strcpy (c, a);
strcpy (c + lena, b);
return pr_settempstring (pr, c);
return pr_settempstring (pr, pr->pr_string_resources, c);
}
VISIBLE string_t
PR_SetTempString (progs_t *pr, const char *s)
{
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr;
if (!s)
return PR_SetString (pr, "");
if ((sr = Hash_Find (pr->strref_hash, s))) {
return string_index (pr, sr);
if ((sr = Hash_Find (res->strref_hash, s))) {
return string_index (res, sr);
}
return pr_settempstring (pr, pr_strdup (pr, s));
return pr_settempstring (pr, res, pr_strdup (pr, s));
}
VISIBLE string_t
PR_AllocTempBlock (progs_t *pr, size_t size)
{
prstr_resources_t *res = pr->pr_string_resources;
return pr_settempstring (pr, res, pr_strmalloc (pr, size));
}
VISIBLE void
PR_PushTempString (progs_t *pr, string_t num)
{
prstr_resources_t *res = pr->pr_string_resources;
strref_t *ref = get_strref (res, num);
strref_t **temp_ref;
if (!ref || ref->type != str_temp) {
PR_Error (pr, "attempt to push a non-temp string");
}
for (temp_ref = &pr->pr_xtstr; *temp_ref; temp_ref = &(*temp_ref)->next) {
if (*temp_ref == ref) {
*temp_ref = ref->next;
ref->next = pr->pr_pushtstr;
pr->pr_pushtstr = ref;
return;
}
}
PR_Error (pr, "attempt to push stale temp string");
}
VISIBLE string_t
PR_SetDynamicString (progs_t *pr, const char *s)
{
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr;
if (!s)
return PR_SetString (pr, "");
if ((sr = Hash_Find (pr->strref_hash, s))) {
return string_index (pr, sr);
if ((sr = Hash_Find (res->strref_hash, s))) {
return string_index (res, sr);
}
sr = new_string_ref (pr);
sr = new_string_ref (res);
sr->type = str_dynamic;
sr->s.string = pr_strdup (pr, s);
return string_index (pr, sr);
return string_index (res, sr);
}
void
PR_MakeTempString (progs_t *pr, string_t str)
{
strref_t *sr = get_strref (pr, str);
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr = get_strref (res, str);
if (!sr)
PR_RunError (pr, "invalid string %d", str);
@ -470,16 +585,18 @@ PR_MakeTempString (progs_t *pr, string_t str)
VISIBLE string_t
PR_NewMutableString (progs_t *pr)
{
strref_t *sr = new_string_ref (pr);
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr = new_string_ref (res);
sr->type = str_mutable;
sr->s.dstring = _dstring_newstr (pr->ds_mem);
return string_index (pr, sr);
sr->s.dstring = _dstring_newstr (&res->ds_mem);
return string_index (res, sr);
}
VISIBLE void
PR_FreeString (progs_t *pr, string_t str)
{
strref_t *sr = get_strref (pr, str);
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr = get_strref (res, str);
if (sr) {
switch (sr->type) {
@ -494,32 +611,32 @@ PR_FreeString (progs_t *pr, string_t str)
break;
case str_return:
default:
PR_Error (pr, "internal string error");
PR_Error (pr, "internal string error: %d", __LINE__);
}
free_string_ref (pr, sr);
free_string_ref (res, sr);
return;
}
if (!get_string (pr, str))
PR_RunError (pr, "attempt to free invalid string %d", str);
PR_RunError (pr, "attempt to free invalid string %d", str);
}
void
PR_FreeTempStrings (progs_t *pr)
{
prstr_resources_t *res = pr->pr_string_resources;
strref_t *sr, *t;
for (sr = pr->pr_xtstr; sr; sr = t) {
t = sr->next;
if (sr->type != str_temp)
PR_Error (pr, "internal string error");
if (R_STRING (pr) < 0 && string_index (pr, sr) == R_STRING (pr)
PR_Error (pr, "internal string error: %d", __LINE__);
if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr)
&& pr->pr_depth) {
prstack_t *frame = pr->pr_stack + pr->pr_depth - 1;
sr->next = frame->tstr;
frame->tstr = sr;
} else {
pr_strfree (pr, sr->s.string);
free_string_ref (pr, sr);
free_string_ref (res, sr);
}
}
pr->pr_xtstr = 0;
@ -551,10 +668,9 @@ PR_FreeTempStrings (progs_t *pr)
list item.
*/
static void
I_DoPrint (dstring_t *result, fmt_item_t *formatting)
I_DoPrint (dstring_t *tmp, dstring_t *result, fmt_item_t *formatting)
{
fmt_item_t *current = formatting;
dstring_t *tmp = dstring_new ();
while (current) {
qboolean doPrecision, doWidth;
@ -617,34 +733,33 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting)
}
current = current->next;
}
dstring_delete (tmp);
}
static fmt_item_t *
new_fmt_item (void)
new_fmt_item (prstr_resources_t *res)
{
int i;
fmt_item_t *fi;
if (!free_fmt_items) {
free_fmt_items = malloc (16 * sizeof (fmt_item_t));
if (!res->free_fmt_items) {
res->free_fmt_items = malloc (16 * sizeof (fmt_item_t));
for (i = 0; i < 15; i++)
free_fmt_items[i].next = free_fmt_items + i + 1;
free_fmt_items[i].next = 0;
res->free_fmt_items[i].next = res->free_fmt_items + i + 1;
res->free_fmt_items[i].next = 0;
}
fi = free_fmt_items;
free_fmt_items = fi->next;
fi = res->free_fmt_items;
res->free_fmt_items = fi->next;
memset (fi, 0, sizeof (*fi));
fi->precision = -1;
return fi;
}
static void
free_fmt_item (fmt_item_t *fi)
free_fmt_item (prstr_resources_t *res, fmt_item_t *fi)
{
fi->next = free_fmt_items;
free_fmt_items = fi;
fi->next = res->free_fmt_items;
res->free_fmt_items = fi;
}
#undef P_var
@ -655,6 +770,7 @@ VISIBLE void
PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
const char *format, int count, pr_type_t **args)
{
prstr_resources_t *res = pr->pr_string_resources;
const char *c, *l;
const char *msg = "";
fmt_item_t *fmt_items = 0;
@ -664,7 +780,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
if (!name)
name = "PR_Sprintf";
*fi = new_fmt_item ();
*fi = new_fmt_item (res);
c = l = format;
while (*c) {
if (*c++ == '%') {
@ -674,14 +790,14 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->type = 's';
(*fi)->data.string_var = l;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
}
if (*c == '%') {
(*fi)->type = 's';
(*fi)->data.string_var = "%";
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
} else {
do {
@ -729,7 +845,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
case '@':
// object
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
case 'e':
@ -739,7 +855,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
P_EDICTNUM (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
case 'i':
@ -750,7 +866,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->data.integer_var = P_INT (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
case 'f':
@ -769,7 +885,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
}
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
case 'p':
@ -779,7 +895,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->data.uinteger_var = P_UINT (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
case 's':
@ -788,7 +904,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->data.string_var = P_GSTRING (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
case 'v':
@ -815,7 +931,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->type = 's';
(*fi)->data.string_var = " ";
}
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
(*fi)->flags = flags;
@ -825,7 +941,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->data.float_var =
P_VECTOR (pr, fmt_count)[i];
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
}
}
@ -834,7 +950,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->data.string_var = "'";
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
case 'x':
@ -843,7 +959,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->data.uinteger_var = P_UINT (pr, fmt_count);
fmt_count++;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
fi = &(*fi)->next;
break;
}
@ -859,7 +975,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
(*fi)->type = 's';
(*fi)->data.string_var = l;
(*fi)->next = new_fmt_item ();
(*fi)->next = new_fmt_item (res);
}
if (fmt_count != count) {
@ -867,17 +983,30 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name,
msg = "Not enough arguments for format string.";
else
msg = "Too many arguments for format string.";
msg = va ("%s: %d %d", msg, fmt_count, count);
dsprintf (res->print_str, "%s: %d %d", msg, fmt_count, count);
msg = res->print_str->str;
goto error;
}
I_DoPrint (result, fmt_items);
dstring_clear (res->print_str);
I_DoPrint (res->print_str, result, fmt_items);
while (fmt_items) {
fmt_item_t *t = fmt_items->next;
free_fmt_item (fmt_items);
free_fmt_item (res, fmt_items);
fmt_items = t;
}
return;
error:
PR_RunError (pr, "%s: %s", name, msg);
}
void
PR_Strings_Init (progs_t *pr)
{
prstr_resources_t *res = calloc (1, sizeof (*res));
res->pr = pr;
res->print_str = dstring_new ();
PR_Resources_Register (pr, "Strings", res, pr_strings_clear);
PR_AddLoadFunc (pr, PR_LoadStrings);
}

View file

@ -91,6 +91,7 @@ bi_gib_builtin_f (void)
PR_RESET_PARAMS (builtin->pr);
P_INT (builtin->pr, 0) = GIB_Argc();
P_INT (builtin->pr, 1) = PR_SetPointer (builtin->pr, pr_list);
builtin->pr->pr_argc = 2;
PR_ExecuteProgram (builtin->pr, builtin->func);
PR_PopFrame (builtin->pr);
PR_Zone_Free (builtin->pr, pr_list);

View file

@ -16,6 +16,6 @@ libQFruamoko_la_LIBADD= $(rua_libs)
libQFruamoko_la_DEPENDENCIES= $(rua_libs)
libQFruamoko_la_SOURCES= \
pr_cmds.c \
rua_cbuf.c rua_cmd.c rua_cvar.c rua_file.c rua_hash.c rua_init.c \
rua_cbuf.c rua_cmd.c rua_cvar.c rua_hash.c rua_init.c \
rua_math.c rua_msgbuf.c rua_obj.c rua_plist.c rua_qfile.c rua_qfs.c \
rua_script.c rua_set.c rua_string.c

View file

@ -255,7 +255,7 @@ PF_Find (progs_t *pr)
int i; // ev_vector
int e, f;
etype_t type;
ddef_t *field_def;
pr_def_t *field_def;
edict_t *ed;
e = P_EDICTNUM (pr, 0);
@ -583,6 +583,25 @@ PF_sprintf (progs_t *pr)
dstring_delete (dstr);
}
static void
PF_vsprintf (progs_t *pr)
{
const char *fmt = P_GSTRING (pr, 0);
__auto_type args = &P_PACKED (pr, pr_va_list_t, 1);
pr_type_t *list_start = PR_GetPointer (pr, args->list);
pr_type_t **list = alloca (args->count * sizeof (*list));
dstring_t *dstr;
for (int i = 0; i < args->count; i++) {
list[i] = list_start + i * pr->pr_param_size;
}
dstr = dstring_newstr ();
PR_Sprintf (pr, dstr, "PF_vsprintf", fmt, args->count, list);
RETURN_STRING (pr, dstr->str);
dstring_delete (dstr);
}
/*
string () gametype
*/
@ -596,7 +615,7 @@ static void
PF_PR_SetField (progs_t *pr)
{
edict_t *ent = P_EDICT (pr, 0);
ddef_t *field = PR_FindField (pr, P_GSTRING (pr, 1));
pr_def_t *field = PR_FindField (pr, P_GSTRING (pr, 1));
const char *value = P_GSTRING (pr, 2);
R_INT (pr) = 0;
@ -643,6 +662,7 @@ static builtin_t builtins[] = {
{"strlen", PF_strlen, QF 100},
{"charcount", PF_charcount, QF 101},
{"sprintf", PF_sprintf, QF 109},
{"vsprintf", PF_vsprintf, -1},
{"ftoi", PF_ftoi, QF 110},
{"itof", PF_itof, QF 111},
{"itos", PF_itos, QF 112},

View file

@ -1,184 +0,0 @@
/*
bi_file.c
CSQC file 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>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_FNMATCH_H
# define model_t sunmodel_t
# include <fnmatch.h>
# undef model_t
#else
# ifdef _WIN32
# include "fnmatch.h"
# endif
#endif
#ifndef HAVE_FNMATCH_PROTO
int fnmatch (const char *__pattern, const char *__string, int __flags);
#endif
#include "QF/cvar.h"
#include "QF/progs.h"
#include "QF/quakefs.h"
#include "QF/va.h"
#include "QF/zone.h"
#include "rua_internal.h"
static const char *file_ban_list[] = {
"default.cfg{,.gz}",
"demo1.dem{,.gz}",
"demo2.dem{,.gz}",
"demo3.dem{,.gz}",
"end1.bin{,.gz}",
"end2.bin{,.gz}",
"gfx.wad{,.gz}",
"progs.dat{,.gz}",
"quake.rc{,.gz}",
0,
};
static const char *dir_ban_list[] = {
"gfx",
"maps",
"progs",
"skins",
"sound",
0,
};
static int
file_readable (char *path)
{
char t;
char *p = strchr (path, '/');
const char **match;
if (p) {
t = *p;
*p = 0;
for (match = dir_ban_list; *match; match++) {
if (fnmatch (*match, path, FNM_PATHNAME) == 0) {
*p = t;
return 0;
}
}
} else {
for (match = file_ban_list; *match; match++) {
if (fnmatch (*match, path, FNM_PATHNAME) == 0) {
return 0;
}
}
}
return 1;
}
static int
file_writeable (char *path)
{
return file_readable (path);
}
static void
bi_File_Open (progs_t *pr)
{
QFile *file;
const char *pth = P_GSTRING (pr, 0);
const char *mode = P_GSTRING (pr, 1);
char *path;
char *p;
int do_write = 0;
int do_read = 0;
p = strchr (mode, 'r');
if (p) {
do_read |= 1;
if (p[1] == '+')
do_write |= 1;
}
p = strchr (mode, 'w');
if (p) {
do_write |= 1;
if (p[1] == '+')
do_read |= 1;
}
p = strchr (mode, 'a');
if (p) {
do_write |= 1;
if (p[1] == '+')
do_read |= 1;
}
path = QFS_CompressPath (pth);
//printf ("'%s' '%s'\n", P_GSTRING (pr, 0), path);
if (!path[0])
goto error;
if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || path [2] == 0))
goto error;
if (path[strlen (path) - 1] =='/')
goto error;
if (!do_read && !do_write)
goto error;
if (do_read && !file_readable (path))
goto error;
if (do_write && !file_writeable (path))
goto error;
file = QFS_Open (va ("%s/%s", qfs_gamedir->dir.def, path), mode);
if (!file)
goto error;
free (path);
if ((R_INT (pr) = QFile_AllocHandle (pr, file)))
return;
Qclose (file);
return;
error:
free (path);
R_INT (pr) = 0;
}
static builtin_t builtins[] = {
{"File_Open", bi_File_Open, -1},
{0}
};
void
RUA_File_Init (progs_t *pr, int secure)
{
PR_RegisterBuiltins (pr, builtins);
}

View file

@ -98,6 +98,7 @@ bi_get_key (const void *key, void *_ht)
PR_RESET_PARAMS (ht->pr);
P_INT (ht->pr, 0) = (intptr_t) (key);
P_INT (ht->pr, 1) = ht->ud;
ht->pr->pr_argc = 2;
PR_ExecuteProgram (ht->pr, ht->gk);
return PR_GetString (ht->pr, R_STRING (ht->pr));
}
@ -109,6 +110,7 @@ bi_get_hash (const void *key, void *_ht)
PR_RESET_PARAMS (ht->pr);
P_INT (ht->pr, 0) = (intptr_t) (key);
P_INT (ht->pr, 1) = ht->ud;
ht->pr->pr_argc = 2;
PR_ExecuteProgram (ht->pr, ht->gh);
return R_INT (ht->pr);
}
@ -121,6 +123,7 @@ bi_compare (const void *key1, const void *key2, void *_ht)
P_INT (ht->pr, 0) = (intptr_t) (key1);
P_INT (ht->pr, 1) = (intptr_t) (key2);
P_INT (ht->pr, 2) = ht->ud;
ht->pr->pr_argc = 3;
PR_ExecuteProgram (ht->pr, ht->cmp);
return R_INT (ht->pr);
}
@ -132,6 +135,7 @@ bi_free (void *key, void *_ht)
PR_RESET_PARAMS (ht->pr);
P_INT (ht->pr, 0) = (intptr_t) (key);
P_INT (ht->pr, 1) = ht->ud;
ht->pr->pr_argc = 2;
PR_ExecuteProgram (ht->pr, ht->f);
}

View file

@ -39,7 +39,6 @@ static void (*init_funcs[])(progs_t *, int) = {
RUA_Cbuf_Init,
RUA_Cmd_Init,
RUA_Cvar_Init,
RUA_File_Init,
RUA_Hash_Init,
RUA_Math_Init,
RUA_MsgBuf_Init,
@ -56,7 +55,6 @@ RUA_Init (progs_t *pr, int secure)
{
size_t i;
PR_Resources_Init (pr);
for (i = 0; i < sizeof (init_funcs) / sizeof (init_funcs[0]); i++)
init_funcs[i] (pr, secure);
}

File diff suppressed because it is too large Load diff

View file

@ -38,9 +38,7 @@
#include "QF/dstring.h"
#include "QF/progs.h"
#include "QF/quakefs.h"
#include "QF/va.h"
#include "QF/zone.h"
#include "QF/quakeio.h"
#include "rua_internal.h"

View file

@ -181,6 +181,12 @@ bi_QFS_FilelistFree (progs_t *pr)
PR_Zone_Free (pr, list);
}
static void
bi_QFS_GetDirectory (progs_t *pr)
{
RETURN_STRING (pr, qfs_gamedir->dir.def);
}
static builtin_t builtins[] = {
{"QFS_Open", bi_QFS_Open, -1},
{"QFS_WOpen", bi_QFS_WOpen, -1},
@ -190,6 +196,7 @@ static builtin_t builtins[] = {
{"QFS_WriteFile", bi_QFS_WriteFile, -1},
{"QFS_Filelist", bi_QFS_Filelist, -1},
{"QFS_FilelistFree", bi_QFS_FilelistFree, -1},
{"QFS_GetDirectory", bi_QFS_GetDirectory, -1},
{0}
};

View file

@ -48,7 +48,6 @@ typedef struct {
script_t script;
string_t dstr;
progs_t *pr;
string_t err_msg;
} rua_script_t;
typedef struct {
@ -92,13 +91,6 @@ bi_script_clear (progs_t *pr, void *data)
script_reset (res);
}
static void
bi_script_error (script_t *_script, const char *msg)
{
rua_script_t *script = (rua_script_t *)_script;
script->err_msg = PR_SetString (script->pr, msg);
}
static void
bi_Script_New (progs_t *pr)
{
@ -110,7 +102,6 @@ bi_Script_New (progs_t *pr)
script->dstr = PR_NewMutableString (pr);
script->script.token = PR_GetMutableString (pr, script->dstr);
script->script.error = bi_script_error;
script->pr = pr;
R_INT (pr) = script_index (res, script);
}
@ -180,8 +171,8 @@ bi_Script_Error (progs_t *pr)
if (!script)
PR_RunError (pr, "invalid script handle");
R_STRING (pr) = script->err_msg;
script->err_msg = 0;
R_STRING (pr) = PR_SetString (pr, script->script.error);
script->script.error = 0;
}
static void

View file

@ -112,6 +112,10 @@ bi_str_mid (progs_t *pr)
end = size;
if (pos < 0 || pos >= size || end <= pos)
return;
if (end == size) {
R_STRING (pr) = str + pos - pr->pr_strings;
return;
}
temp = alloca (end - pos + 1);
strncpy (temp, str + pos, end - pos);
temp[end - pos] = 0;
@ -130,6 +134,18 @@ bi_str_str (progs_t *pr)
R_STRING (pr) = res - pr->pr_strings;
}
static void
bi_str_char (progs_t *pr)
{
const char *str = P_GSTRING (pr, 0);
int ind = P_INT (pr, 1);
if (ind < 0) {
PR_RunError (pr, "negative index to str_char");
}
R_INT (pr) = str[ind];
}
static builtin_t builtins[] = {
{"str_new", bi_str_new, -1},
{"str_free", bi_str_free, -1},
@ -139,6 +155,7 @@ static builtin_t builtins[] = {
{"str_mid|*i", bi_str_mid, -1},
{"str_mid|*ii", bi_str_mid, -1},
{"str_str", bi_str_str, -1},
{"str_char", bi_str_char, -1},
{0}
};

View file

@ -53,7 +53,8 @@ libQFutil_la_SOURCES= \
fendian.c hash.c idparse.c info.c link.c llist.c \
mathlib.c mdfour.c mersenne.c msg.c pakfile.c plugin.c qargs.c qendian.c \
qfplist.c quakefs.c quakeio.c riff.c script.c segtext.c set.c sizebuf.c \
string.c sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \
string.c sys.c txtbuffer.c va.c ver_check.c vrect.c wad.c wadfile.c \
zone.c \
$(dirent) $(fnmatch) $(getopt)
EXTRA_DIST= $(fnmatch_src) $(getopt_src)

View file

@ -299,7 +299,7 @@ dstring_clearstr (dstring_t *dstr)
dstr->str[0] = 0;
}
static __attribute__((format(printf, 3, 0))) int
static __attribute__((format(printf, 3, 0))) char *
_dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args)
{
int size;
@ -325,20 +325,20 @@ _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args)
}
dstr->size = size + offs + 1;
dstr->str[dstr->size - 1] = 0;
return size;
return dstr->str;
}
VISIBLE int
VISIBLE char *
dvsprintf (dstring_t *dstr, const char *fmt, va_list args)
{
return _dvsprintf (dstr, 0, fmt, args);
}
VISIBLE int
VISIBLE char *
dsprintf (dstring_t *dstr, const char *fmt, ...)
{
va_list args;
int ret;
char *ret;
va_start (args, fmt);
ret = _dvsprintf (dstr, 0, fmt, args);
@ -347,7 +347,7 @@ dsprintf (dstring_t *dstr, const char *fmt, ...)
return ret;
}
VISIBLE int
VISIBLE char *
davsprintf (dstring_t *dstr, const char *fmt, va_list args)
{
int offs = 0;
@ -357,11 +357,11 @@ davsprintf (dstring_t *dstr, const char *fmt, va_list args)
return _dvsprintf (dstr, offs, fmt, args);
}
VISIBLE int
VISIBLE char *
dasprintf (dstring_t *dstr, const char *fmt, ...)
{
va_list args;
int ret;
char *ret;
int offs = 0;
if (dstr->size)

View file

@ -37,7 +37,6 @@
#endif
#include "QF/mdfour.h"
#include "QF/uint32.h"
/* NOTE: This code makes no attempt to be fast!
It assumes that a int is at least 32 bits long
@ -62,12 +61,12 @@ static struct mdfour *m;
/* this applies md4 to 64 byte chunks */
static void
mdfour64 (uint32 * M)
mdfour64 (uint32_t * M)
{
int j;
uint32 AA, BB, CC, DD;
uint32 X[16];
uint32 A, B, C, D;
uint32_t AA, BB, CC, DD;
uint32_t X[16];
uint32_t A, B, C, D;
for (j = 0; j < 16; j++)
X[j] = M[j];
@ -154,7 +153,7 @@ mdfour64 (uint32 * M)
}
static void
copy64 (uint32 * M, const unsigned char *in)
copy64 (uint32_t * M, const unsigned char *in)
{
int i;
@ -164,7 +163,7 @@ copy64 (uint32 * M, const unsigned char *in)
}
static void
copy4 (unsigned char *out, uint32 x)
copy4 (unsigned char *out, uint32_t x)
{
out[0] = x & 0xFF;
out[1] = (x >> 8) & 0xFF;
@ -186,8 +185,8 @@ static void
mdfour_tail (const unsigned char *in, int n)
{
unsigned char buf[128];
uint32 M[16];
uint32 b;
uint32_t M[16];
uint32_t b;
m->totalN += n;
@ -214,7 +213,7 @@ mdfour_tail (const unsigned char *in, int n)
VISIBLE void
mdfour_update (struct mdfour *md, const unsigned char *in, int n)
{
uint32 M[16];
uint32_t M[16];
if (n == 0)
mdfour_tail (in, n);

View file

@ -34,19 +34,6 @@
#include "QF/dstring.h"
#include "QF/script.h"
static void __attribute__ ((format (printf, 2, 3), noreturn))
script_error (script_t *script, const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
fprintf (stderr, "%s:%d: ", script->file, script->line);
vfprintf (stderr, fmt, args);
fprintf (stderr, "\n");
va_end (args);
exit (1);
}
VISIBLE script_t *
Script_New (void)
{
@ -69,11 +56,16 @@ Script_Start (script_t *script, const char *file, const char *data)
script->file = file;
script->p = data;
script->unget = false;
script->error = 0;
}
VISIBLE qboolean
Script_TokenAvailable (script_t *script, qboolean crossline)
{
if (script->error) {
return false;
}
if (script->unget)
return true;
skipspace:
@ -111,6 +103,10 @@ Script_GetToken (script_t *script, qboolean crossline)
{
const char *token_p;
if (script->error) {
return false;
}
if (script->unget) { // is a token allready waiting?
script->unget = false;
return true;
@ -118,10 +114,7 @@ Script_GetToken (script_t *script, qboolean crossline)
if (!Script_TokenAvailable (script, crossline)) {
if (!crossline) {
if (script->error)
script->error (script, "line is incomplete");
else
script_error (script, "line is incomplete");
script->error = "line is incomplete";
}
return false;
}
@ -134,18 +127,13 @@ Script_GetToken (script_t *script, qboolean crossline)
while (*script->p != '"') {
if (!*script->p) {
script->line = start_line;
if (script->error)
script->error (script, "EOF inside quoted token");
else
script_error (script, "EOF inside quoted token");
script->error = "EOF inside quoted token";
return false;
}
if (*script->p == '\n') {
if (script->no_quote_lines) {
if (script->error)
script->error (script, "EOL inside quoted token");
else
script_error (script, "EOL inside quoted token");
script->error = "EOL inside quoted token";
return false;
}
script->line++;
}
@ -175,11 +163,16 @@ Script_GetToken (script_t *script, qboolean crossline)
VISIBLE void
Script_UngetToken (script_t *script)
{
script->unget = true;
if (!script->error) {
script->unget = true;
}
}
VISIBLE const char *
Script_Token (script_t *script)
{
if (script->error) {
return 0;
}
return script->token->str;
}

View file

@ -126,18 +126,18 @@ qboolean stdin_ready;
/* The translation table between the graphical font and plain ASCII --KB */
VISIBLE const char sys_char_map[256] = {
'\0', '#', '#', '#', '#', '.', '#', '#',
'#', 9, 10, '#', ' ', 13, '.', '.',
0, '#', '#', '#', '#', '.', '#', '#',
'#', 9, 10, '#', ' ', 13, '.', '.',
'[', ']', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '.', '<', '=', '>',
' ', '!', '"', '#', '$', '%', '&', '\'',
' ', '!', '"', '#', '$', '%', '&','\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'X', 'Y', 'Z', '[','\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
@ -147,14 +147,14 @@ VISIBLE const char sys_char_map[256] = {
'#', '#', ' ', '#', ' ', '>', '.', '.',
'[', ']', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '.', '<', '=', '>',
' ', '!', '"', '#', '$', '%', '&', '\'',
' ', '!', '"', '#', '$', '%', '&','\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'X', 'Y', 'Z', '[','\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
@ -240,16 +240,20 @@ Sys_FileExists (const char *path)
for want of a better name, but it sets the function pointer for the
actual implementation of Sys_Printf.
*/
VISIBLE void
VISIBLE sys_printf_t
Sys_SetStdPrintf (sys_printf_t func)
{
sys_printf_t prev = sys_std_printf_function;
sys_std_printf_function = func;
return prev;
}
VISIBLE void
VISIBLE sys_printf_t
Sys_SetErrPrintf (sys_printf_t func)
{
sys_printf_t prev = sys_err_printf_function;
sys_err_printf_function = func;
return prev;
}
void

View file

@ -4,7 +4,8 @@ AM_CPPFLAGS= -I$(top_srcdir)/include
check_PROGRAMS= \
test-bary test-cs test-darray test-dq test-half test-mat3 test-mat4 \
test-plist test-qfs test-quat test-seb test-seg test-set test-vrect
test-plist test-qfs test-quat test-seb test-seg test-set test-txtbuffer \
test-vrect
test_bary_SOURCES=test-bary.c
test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la
@ -58,6 +59,10 @@ test_set_SOURCES=test-set.c
test_set_LDADD=$(top_builddir)/libs/util/libQFutil.la
test_set_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
test_txtbuffer_SOURCES=test-txtbuffer.c
test_txtbuffer_LDADD=$(top_builddir)/libs/util/libQFutil.la
test_txtbuffer_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
test_vrect_SOURCES=test-vrect.c
test_vrect_LDADD=$(top_builddir)/libs/util/libQFutil.la
test_vrect_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la

View file

@ -0,0 +1,240 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include "QF/txtbuffer.h"
static size_t
check_text_ptr (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
return buffer->text != 0;
}
static size_t
get_textSize (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
return buffer->textSize;
}
static size_t
get_bufferSize (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
return buffer->bufferSize;
}
static size_t
get_gapOffset (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
return buffer->gapOffset;
}
static size_t
get_gapSize (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
return buffer->gapSize;
}
static size_t
insert_text (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
if (TextBuffer_InsertAt (buffer, offset, txt, length)) {
memset (buffer->text + buffer->gapOffset, 0xff, buffer->gapSize);
return 1;
}
return 0;
}
static size_t
delete_text (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
if (TextBuffer_DeleteAt (buffer, offset, length)) {
memset (buffer->text + buffer->gapOffset, 0xff, buffer->gapSize);
return 1;
}
return 0;
}
static size_t
destroy_buffer (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
TextBuffer_Destroy (buffer);
return 0;
}
typedef size_t (*test_func) (txtbuffer_t *buffer, size_t offset,
const char *text, size_t length);
static const char test_text[] = {
"Guarding the entrance to the Grendal\n"
"Gorge is the Shadow Gate, a small keep\n"
"and monastary which was once the home\n"
"of the Shadow cult.\n\n"
"For years the Shadow Gate existed in\n"
"obscurity but after the cult discovered\n"
"the \3023\354\341\343\353\240\307\341\364\345 in the caves below\n"
"the empire took notice.\n"
"A batallion of Imperial Knights were\n"
"sent to the gate to destroy the cult\n"
"and claim the artifact for the King.",
};
static const char empty[TXTBUFFER_GROW] = { };
static size_t
compare_text (txtbuffer_t *buffer, size_t offset, const char *txt,
size_t length)
{
//printf("%zd %ld %zd\n", offset, txt - test_text, length);
size_t res = memcmp (buffer->text + offset, txt, length) == 0;
if (!res) {
for (size_t i = 0; i < length; i++) {
//printf ("%02x %02x\n", txt[i] & 0xff, buffer->text[offset + i] & 0xff);
}
}
return res;
}
#define txtsize (sizeof (test_text) - 1)
#define txtsize0 txtsize
#define bufsize0 (TXTBUFFER_GROW)
#define gapoffs0 txtsize0
#define gapsize0 (bufsize0 - txtsize0)
#define subtxtlen 200
#define suboffs 200
#define txtsize1 (txtsize0 + subtxtlen)
#define bufsize1 (TXTBUFFER_GROW)
#define gapoffs1 (suboffs + subtxtlen)
#define gapsize1 (bufsize1 - txtsize1)
#define deltxtlen 350
#define deloffs 150
#define txtsize2 (txtsize + subtxtlen - deltxtlen)
#define bufsize2 (TXTBUFFER_GROW)
#define gapoffs2 (deloffs)
#define gapsize2 (bufsize2 - txtsize2)
#define deltxtrem (txtsize2 - gapoffs2)
#define emptyoffs 370
#define txtsize3 (txtsize + sizeof (empty))
#define bufsize3 (2 * TXTBUFFER_GROW)
#define gapoffs3 (emptyoffs + sizeof (empty))
#define gapsize3 (bufsize3 - txtsize3)
#define txtsize4 (txtsize + 2 * sizeof (empty))
#define bufsize4 (3 * TXTBUFFER_GROW)
#define gapoffs4 (emptyoffs + sizeof (empty))
#define gapsize4 (bufsize4 - txtsize4)
struct {
test_func test;
size_t offset_param;
const char *text_param;
size_t length_param;
int test_expect;
} tests[] = {
{ check_text_ptr, 0, 0, 0, 0 },
{ get_textSize, 0, 0, 0, 0 },
{ get_bufferSize, 0, 0, 0, 0 },
{ get_gapOffset, 0, 0, 0, 0 },
{ get_gapSize, 0, 0, 0, 0 },
{ insert_text, 0, test_text, txtsize, 1 },
{ get_textSize, 0, 0, 0, txtsize0 },
{ get_bufferSize, 0, 0, 0, bufsize0 },
{ get_gapOffset, 0, 0, 0, gapoffs0 },
{ get_gapSize, 0, 0, 0, gapsize0 },
{ compare_text, 0, test_text, txtsize, 1 },
{ insert_text, suboffs, test_text, subtxtlen, 1 },
{ get_textSize, 0, 0, 0, txtsize1 },
{ get_bufferSize, 0, 0, 0, bufsize1 },
{ get_gapOffset, 0, 0, 0, gapoffs1 },
{ get_gapSize, 0, 0, 0, gapsize1 },
{ compare_text, 0, test_text, txtsize, 0 },
{ compare_text, 0, test_text, suboffs, 1 },
{ compare_text, suboffs, test_text, subtxtlen, 1 },
{ compare_text, gapoffs1 + gapsize1, test_text + subtxtlen, txtsize - subtxtlen, 1 },
{ delete_text, deloffs, 0, deltxtlen, 1 },
{ get_textSize, 0, 0, 0, txtsize2 },
{ get_bufferSize, 0, 0, 0, bufsize2 },
{ get_gapOffset, 0, 0, 0, gapoffs2 },
{ get_gapSize, 0, 0, 0, gapsize2 },
{ compare_text, 0, test_text, suboffs, 0 },
{ compare_text, suboffs, test_text, subtxtlen, 0 },
{ compare_text, gapoffs1 + gapsize1, test_text + subtxtlen, txtsize - subtxtlen, 0 },
{ compare_text, 0, test_text, deloffs, 1 },
{ compare_text, gapoffs2 + gapsize2, test_text + txtsize - deltxtrem, deltxtrem, 1 },
{ compare_text, gapoffs2 + gapsize2 - 1, test_text + txtsize - deltxtrem - 1, 1, 0 },
{ delete_text, 0, 0, -1, 1 },
{ check_text_ptr, 0, 0, 0, 1 },
{ get_textSize, 0, 0, 0, 0 },
{ get_bufferSize, 0, 0, 0, bufsize2 },
{ get_gapOffset, 0, 0, 0, 0 },
{ get_gapSize, 0, 0, 0, bufsize2 },
{ insert_text, 1, test_text, txtsize, 0 },
{ get_textSize, 0, 0, 0, 0 },
{ get_bufferSize, 0, 0, 0, bufsize2 },
{ get_gapOffset, 0, 0, 0, 0 },
{ get_gapSize, 0, 0, 0, bufsize2 },
{ insert_text, 0, test_text, txtsize, 1 },
{ insert_text, 300, 0, 0, 1 },
{ get_textSize, 0, 0, 0, txtsize0 },
{ get_bufferSize, 0, 0, 0, bufsize2 },
{ get_gapOffset, 0, 0, 0, 300 },
{ get_gapSize, 0, 0, 0, gapsize0 },
{ compare_text, 0, test_text, 300, 1 },
{ compare_text, 300, test_text + 300, 1, 0 },
{ compare_text, 300 + gapsize0, test_text + 300, txtsize - 300, 1 },
{ compare_text, 300 + gapsize0 - 1, test_text + 300 - 1, 1, 0 },
{ insert_text, 350, 0, 0, 1 },
{ compare_text, (emptyoffs - 20) + gapsize0, test_text + (emptyoffs - 20), txtsize - (emptyoffs - 20), 1 },
{ get_textSize, 0, 0, 0, txtsize0 },
{ get_bufferSize, 0, 0, 0, bufsize2 },
{ get_gapOffset, 0, 0, 0, (emptyoffs - 20) },
{ get_gapSize, 0, 0, 0, gapsize0 },
{ insert_text, emptyoffs, empty, sizeof (empty), 1 },
{ get_textSize, 0, 0, 0, txtsize3 },
{ get_bufferSize, 0, 0, 0, bufsize3 },
{ get_gapOffset, 0, 0, 0, gapoffs3 },
{ get_gapSize, 0, 0, 0, gapsize3 },
{ insert_text, emptyoffs, empty, sizeof (empty), 1 },
{ get_textSize, 0, 0, 0, txtsize4 },
{ get_bufferSize, 0, 0, 0, bufsize4 },
{ get_gapOffset, 0, 0, 0, gapoffs4 },
{ get_gapSize, 0, 0, 0, gapsize4 },
{ destroy_buffer, 0, 0, 0, 0 },
};
#define num_tests (sizeof (tests) / sizeof (tests[0]))
int test_start_line = __LINE__ - num_tests - 2;
int
main (int argc, const char **argv)
{
size_t i;
int res = 0;
txtbuffer_t *buffer = TextBuffer_Create ();
for (i = 0; i < num_tests; i++) {
if (tests[i].test) {
int test_res;
test_res = tests[i].test (buffer,
tests[i].offset_param,
tests[i].text_param,
tests[i].length_param);
if (test_res != tests[i].test_expect) {
res |= 1;
printf ("test %d (line %d) failed\n", (int) i,
(int) i + test_start_line);
printf ("expect: %d\n", tests[i].test_expect);
printf ("got : %d\n", test_res);
continue;
}
}
}
return res;
}

194
libs/util/txtbuffer.c Normal file
View file

@ -0,0 +1,194 @@
/*
txtbuffer.c
Text buffer
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
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
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/alloc.h"
#include "QF/qtypes.h"
#include "QF/sys.h"
#include "QF/txtbuffer.h"
#include "compat.h"
static txtbuffer_t *txtbuffers_freelist;
static char *
txtbuffer_open_gap (txtbuffer_t *buffer, size_t offset, size_t length)
{
size_t len;
char *dst;
char *src;
if (offset == buffer->gapOffset && length <= buffer->gapSize) {
return buffer->text + buffer->gapOffset;
}
if (length <= buffer->gapSize) {
// no resize needed
if (offset < buffer->gapOffset) {
len = buffer->gapOffset - offset;
dst = buffer->text + buffer->gapOffset + buffer->gapSize - len;
src = buffer->text + offset;
} else {
len = offset - buffer->gapOffset;
dst = buffer->text + buffer->gapOffset;
src = buffer->text + buffer->gapOffset + buffer->gapSize;
}
memmove (dst, src, len);
} else {
// need to resize the buffer
// grow the buffer by the difference in lengths rounded up to the
// next multiple of TXTBUFFER_GROW
size_t new_size = buffer->bufferSize + length - buffer->gapSize;
new_size = (new_size + TXTBUFFER_GROW - 1) & ~(TXTBUFFER_GROW - 1);
char *new_text = realloc (buffer->text, new_size);
if (!new_text) {
return 0;
}
buffer->text = new_text;
if (offset < buffer->gapOffset) {
// move the old post-gap to the end of the new buffer
len = buffer->bufferSize - (buffer->gapOffset + buffer->gapSize);
dst = buffer->text + new_size - len;
src = buffer->text + buffer->gapOffset + buffer->gapSize;
memmove (dst, src, len);
// move the remaining chunk to after the end of the new gap or
// just before the location of the previous move
len = buffer->gapOffset - offset;
dst -= len;
src = buffer->text + offset;
memmove (dst, src, len);
} else if (offset > buffer->gapOffset) {
// move the old post-offset to the end of the new buffer
len = buffer->bufferSize - (offset + buffer->gapSize);
dst = buffer->text + new_size - len;
src = buffer->text + offset + buffer->gapSize;
memmove (dst, src, len);
// move the old post-gap to offset block to before the new gap
len = offset - buffer->gapOffset;
dst = buffer->text + buffer->gapOffset;
src = buffer->text + buffer->gapOffset + buffer->gapSize;
memmove (dst, src, len);
} else {
// the gap only grew, did not move
len = buffer->bufferSize - (offset + buffer->gapSize);
dst = buffer->text + new_size - len;
src = buffer->text + buffer->gapOffset + buffer->gapSize;
memmove (dst, src, len);
}
buffer->gapSize += new_size - buffer->bufferSize;
buffer->bufferSize = new_size;
}
buffer->gapOffset = offset;
return buffer->text + buffer->gapOffset;
}
static char *
txtbuffer_delete_text (txtbuffer_t *buffer, size_t offset, size_t length)
{
size_t len;
char *dst;
char *src;
if (offset > buffer->gapOffset) {
len = offset - buffer->gapOffset;
dst = buffer->text + buffer->gapOffset;
src = buffer->text + buffer->gapOffset + buffer->gapSize;
memmove (dst, src, len);
} else if (offset + length < buffer->gapOffset) {
len = buffer->gapOffset - (offset + length);
dst = buffer->text + buffer->gapSize + (offset + length);
src = buffer->text + (offset + length);
memmove (dst, src, len);
}
// don't need to do any copying when offset <= gapOffset &&
// offset + length >= offset
buffer->gapOffset = offset;
buffer->gapSize += length;
buffer->textSize -= length;
return buffer->text + buffer->gapOffset;
}
VISIBLE txtbuffer_t *
TextBuffer_Create (void)
{
txtbuffer_t *buffer;
ALLOC (16, txtbuffer_t, txtbuffers, buffer);
return buffer;
}
VISIBLE void
TextBuffer_Destroy (txtbuffer_t *buffer)
{
if (buffer->text) {
free (buffer->text);
}
FREE (txtbuffers, buffer);
}
VISIBLE int
TextBuffer_InsertAt (txtbuffer_t *buffer, size_t offset,
const char *text, size_t text_len)
{
char *dst;
if (offset > buffer->textSize) {
return 0;
}
dst = txtbuffer_open_gap (buffer, offset, text_len);
if (!dst) {
return 0;
}
memcpy (dst, text, text_len);
buffer->textSize += text_len;
buffer->gapOffset += text_len;
buffer->gapSize -= text_len;
return 1;
}
VISIBLE int
TextBuffer_DeleteAt (txtbuffer_t *buffer, size_t offset, size_t len)
{
if (offset > buffer->textSize) {
return 0;
}
// clamp len to the amount of text beyond offset
if (len > buffer->textSize - offset) {
len = buffer->textSize - offset;
}
txtbuffer_delete_text (buffer, offset, len);
return 1;
}

View file

@ -51,16 +51,23 @@ VISIBLE char *
va (const char *fmt, ...)
{
va_list args;
static dstring_t *string;
static dstring_t *string[4];
#define NUM_STRINGS (sizeof (string) / sizeof (string[0]))
static int str_index;
dstring_t *dstr;
if (!string)
string = dstring_new ();
if (!string[0]) {
for (size_t i = 0; i < NUM_STRINGS; i++) {
string[i] = dstring_new ();
}
}
dstr = string[str_index++ % NUM_STRINGS];
va_start (args, fmt);
dvsprintf (string, fmt, args);
dvsprintf (dstr, fmt, args);
va_end (args);
return string->str;
return dstr->str;
}
VISIBLE char *

View file

@ -672,7 +672,7 @@ event_focusin (XEvent *event)
static void
center_pointer (void)
{
XEvent event;
XEvent event = {};
event.type = MotionNotify;
event.xmotion.display = x_disp;

Some files were not shown because too many files have changed in this diff Show more