upgraded both QuakeC VMs to use a table of negative string indices for all dynamic...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 13 May 2005 19:41:09 +0000 (19:41 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 13 May 2005 19:41:09 +0000 (19:41 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5278 d7cf8633-e32d-0410-b094-e92efae38249

22 files changed:
cl_screen.c
cl_screen.h
cl_video.c
cl_video.h
common.c
common.h
draw.h
gl_draw.c
host.c
host_cmd.c
menu.c
pr_cmds.c
pr_edict.c
progs.h
progsvm.h
prvm_cmds.c
prvm_edict.c
server.h
sv_main.c
sv_user.c
wad.c
wad.h

index 02632b2..505366f 100644 (file)
@@ -489,7 +489,7 @@ void DrawQ_Clear(void)
 }
 
 static int picelements[6] = {0, 1, 2, 0, 2, 3};
-void DrawQ_Pic(float x, float y, char *picname, float width, float height, float red, float green, float blue, float alpha, int flags)
+void DrawQ_Pic(float x, float y, const char *picname, float width, float height, float red, float green, float blue, float alpha, int flags)
 {
        DrawQ_SuperPic(x,y,picname,width,height,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
 }
@@ -546,7 +546,7 @@ void DrawQ_Fill (float x, float y, float w, float h, float red, float green, flo
        DrawQ_SuperPic(x,y,NULL,w,h,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
 }
 
-void DrawQ_SuperPic(float x, float y, char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
+void DrawQ_SuperPic(float x, float y, const char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
 {
        float floats[36];
        cachepic_t *pic;
index 7f705b6..d914bfa 100644 (file)
@@ -33,7 +33,7 @@ typedef struct drawqueuemesh_s
 }
 drawqueuemesh_t;
 
-enum drawqueue_drawflag_e { 
+enum drawqueue_drawflag_e {
 DRAWFLAG_NORMAL,
 DRAWFLAG_ADDITIVE,
 DRAWFLAG_MODULATE,
@@ -44,13 +44,13 @@ DRAWFLAG_NUMFLAGS
 // clear the draw queue
 void DrawQ_Clear(void);
 // draw an image
-void DrawQ_Pic(float x, float y, char *picname, float width, float height, float red, float green, float blue, float alpha, int flags);
+void DrawQ_Pic(float x, float y, const char *picname, float width, float height, float red, float green, float blue, float alpha, int flags);
 // draw a text string
 void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags);
 // draw a filled rectangle
 void DrawQ_Fill(float x, float y, float w, float h, float red, float green, float blue, float alpha, int flags);
 // draw a very fancy pic (per corner texcoord/color control), the order is tl, tr, bl, br
-void DrawQ_SuperPic(float x, float y, char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags);
+void DrawQ_SuperPic(float x, float y, const char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags);
 // draw a triangle mesh
 void DrawQ_Mesh(drawqueuemesh_t *mesh, int flags);
 // set the clipping area
index cac5af6..e7858ac 100644 (file)
@@ -69,7 +69,7 @@ static qboolean WakeVideo( clvideo_t * video )
        return true;
 }
 
-static clvideo_t* OpenVideo( clvideo_t *video, char *filename, char *name, int owner )
+static clvideo_t* OpenVideo( clvideo_t *video, const char *filename, const char *name, int owner )
 {
        strncpy( video->filename, filename, MAX_QPATH );
        video->ownertag = owner;
@@ -95,7 +95,7 @@ static clvideo_t* OpenVideo( clvideo_t *video, char *filename, char *name, int o
        return video;
 }
 
-clvideo_t* CL_OpenVideo( char *filename, char *name, int owner )
+clvideo_t* CL_OpenVideo( const char *filename, const char *name, int owner )
 {
        clvideo_t *video;
 
@@ -107,7 +107,7 @@ clvideo_t* CL_OpenVideo( char *filename, char *name, int owner )
        return OpenVideo( video, filename, name, owner );
 }
 
-clvideo_t* CL_GetVideo( char *name )
+clvideo_t* CL_GetVideo( const char *name )
 {
        int i;
        clvideo_t *video;
index bd706bc..8439e92 100644 (file)
@@ -36,17 +36,17 @@ typedef struct clvideo_s
        cachepic_t cpif;
 
        // if a video is suspended, it is automatically paused (else we'd still have to process the frames)
-       
+
        // used to determine whether the video's resources should be freed or not
-    double  lasttime; 
+    double  lasttime;
        // when lasttime - realtime > THRESHOLD, all but the stream is freed
-       qboolean suspended; 
+       qboolean suspended;
 
        char    filename[MAX_QPATH];
 } clvideo_t;
 
-clvideo_t*     CL_OpenVideo( char *filename, char *name, int owner );
-clvideo_t*     CL_GetVideo( char *name );
+clvideo_t*     CL_OpenVideo( const char *filename, const char *name, int owner );
+clvideo_t*     CL_GetVideo( const char *name );
 void           CL_SetVideoState( clvideo_t *video, clvideostate_t state );
 void           CL_RestartVideo( clvideo_t *video );
 
index f568a82..0c8dc3f 100644 (file)
--- a/common.c
+++ b/common.c
@@ -171,7 +171,7 @@ static unsigned short crctable[256] =
        0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
 };
 
-unsigned short CRC_Block(qbyte *data, int size)
+unsigned short CRC_Block(const qbyte *data, int size)
 {
        unsigned short crc = CRC_INIT_VALUE;
        while (size--)
index 3a73d7c..8994079 100644 (file)
--- a/common.h
+++ b/common.h
@@ -53,7 +53,7 @@ void SZ_HexDumpToConsole(const sizebuf_t *buf);
 
 void Com_HexDumpToConsole(const qbyte *data, int size);
 
-unsigned short CRC_Block(qbyte *data, int size);
+unsigned short CRC_Block(const qbyte *data, int size);
 
 
 //============================================================================
diff --git a/draw.h b/draw.h
index 4c50788..61d50af 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -39,11 +39,11 @@ typedef struct cachepic_s
 cachepic_t;
 
 void Draw_Init (void);
-cachepic_t *Draw_CachePic (char *path, qboolean persistent);
+cachepic_t *Draw_CachePic (const char *path, qboolean persistent);
 // create or update a pic's image
-cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels);
+cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, qbyte *pixels);
 // free the texture memory used by a pic
-void Draw_FreePic(char *picname);
+void Draw_FreePic(const char *picname);
 
 void R_DrawQueue(void);
 
index f0b1d40..7ae8700 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -262,7 +262,7 @@ Draw_CachePic
 ================
 */
 // FIXME: move this to client somehow
-cachepic_t     *Draw_CachePic (char *path, qboolean persistent)
+cachepic_t     *Draw_CachePic (const char *path, qboolean persistent)
 {
        int i, crc, hashkey;
        cachepic_t *pic;
@@ -350,7 +350,7 @@ cachepic_t  *Draw_CachePic (char *path, qboolean persistent)
        return pic;
 }
 
-cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels)
+cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, qbyte *pixels)
 {
        int crc, hashkey;
        cachepic_t *pic;
@@ -391,7 +391,7 @@ cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *
        return pic;
 }
 
-void Draw_FreePic(char *picname)
+void Draw_FreePic(const char *picname)
 {
        int crc;
        int hashkey;
diff --git a/host.c b/host.c
index 108db33..b81831a 100644 (file)
--- a/host.c
+++ b/host.c
@@ -424,7 +424,7 @@ void SV_DropClient(qboolean crash)
        }
 
        // remove leaving player from scoreboard
-       //host_client->edict->v->netname = PR_SetString(host_client->name);
+       //host_client->edict->v->netname = PR_SetEngineString(host_client->name);
        //if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_clientcolors)))
        //      val->_float = 0;
        //host_client->edict->v->frags = 0;
index 21ad53e..702d149 100644 (file)
@@ -519,7 +519,7 @@ void Host_Savegame_f (void)
        // write the light styles
        for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
        {
-               if (sv.lightstyles[i])
+               if (sv.lightstyles[i][0])
                        FS_Printf(f, "%s\n", sv.lightstyles[i]);
                else
                        FS_Print(f,"m\n");
@@ -627,8 +627,7 @@ void Host_Loadgame_f (void)
        {
                // light style
                COM_ParseToken(&t, false);
-               sv.lightstyles[i] = PR_Alloc(strlen(com_token)+1);
-               strcpy(sv.lightstyles[i], com_token);
+               strlcpy(sv.lightstyles[i], com_token, sizeof(sv.lightstyles[i]));
        }
 
 // load the edicts out of the savegame file
@@ -737,7 +736,7 @@ void Host_Name_f (void)
 
        // point the string back at updateclient->name to keep it safe
        strlcpy (host_client->name, newName, sizeof (host_client->name));
-       host_client->edict->v->netname = PR_SetString(host_client->name);
+       host_client->edict->v->netname = PR_SetEngineString(host_client->name);
        if (strcmp(host_client->old_name, host_client->name))
        {
                if (host_client->spawned)
@@ -799,7 +798,7 @@ void Host_Playermodel_f (void)
        // point the string back at updateclient->name to keep it safe
        strlcpy (host_client->playermodel, newPath, sizeof (host_client->playermodel));
        if( eval_playermodel )
-               GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(host_client->playermodel);
+               GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetEngineString(host_client->playermodel);
        if (strcmp(host_client->old_model, host_client->playermodel))
        {
                if (host_client->spawned)
@@ -860,7 +859,7 @@ void Host_Playerskin_f (void)
        // point the string back at updateclient->name to keep it safe
        strlcpy (host_client->playerskin, newPath, sizeof (host_client->playerskin));
        if( eval_playerskin )
-               GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(host_client->playerskin);
+               GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetEngineString(host_client->playerskin);
        if (strcmp(host_client->old_skin, host_client->playerskin))
        {
                if (host_client->spawned)
diff --git a/menu.c b/menu.c
index c09d888..a83f1a1 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -2506,7 +2506,7 @@ void M_Menu_Keys_f (void)
 
 #define NUMKEYS 5
 
-void M_FindKeysForCommand (char *command, int *keys)
+void M_FindKeysForCommand (const char *command, int *keys)
 {
        int             count;
        int             j;
index 19643ea..52555c9 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -175,7 +175,7 @@ char *ENGINE_EXTENSIONS =
 "NEXUIZ_PLAYERSKIN "
 ;
 
-qboolean checkextension(char *name)
+qboolean checkextension(const char *name)
 {
        int len;
        char *e, *start;
@@ -370,7 +370,7 @@ void PF_setmodel (void)
        if (e->e->free)
                PF_WARNING("setmodel: can not modify free entity\n");
        i = SV_ModelIndex(G_STRING(OFS_PARM1), 1);
-       e->v->model = PR_SetString(sv.model_precache[i]);
+       e->v->model = PR_SetEngineString(sv.model_precache[i]);
        e->v->modelindex = i;
 
        mod = sv.models[i];
@@ -627,7 +627,7 @@ PF_ambientsound
 */
 void PF_ambientsound (void)
 {
-       char            *samp;
+       const char      *samp;
        float           *pos;
        float           vol, attenuation;
        int                     soundnum, large;
@@ -682,7 +682,7 @@ Larger attenuations will drop off.
 */
 void PF_sound (void)
 {
-       char            *sample;
+       const char      *sample;
        int                     channel;
        edict_t         *entity;
        int             volume;
@@ -960,7 +960,7 @@ stuffcmd (clientent, value)
 void PF_stuffcmd (void)
 {
        int             entnum;
-       char    *str;
+       const char      *str;
        client_t        *old;
 
        entnum = G_EDICTNUM(OFS_PARM0);
@@ -1109,7 +1109,7 @@ void PF_ftos (void)
                sprintf(s, "%i", (int)v);
        else
                sprintf(s, "%f", v);
-       G_INT(OFS_RETURN) = PR_SetString(s);
+       G_INT(OFS_RETURN) = PR_SetEngineString(s);
 }
 
 void PF_fabs (void)
@@ -1124,7 +1124,7 @@ void PF_vtos (void)
        char *s;
        s = PR_GetTempString();
        sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
-       G_INT(OFS_RETURN) = PR_SetString(s);
+       G_INT(OFS_RETURN) = PR_SetEngineString(s);
 }
 
 void PF_etos (void)
@@ -1132,7 +1132,7 @@ void PF_etos (void)
        char *s;
        s = PR_GetTempString();
        sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
-       G_INT(OFS_RETURN) = PR_SetString(s);
+       G_INT(OFS_RETURN) = PR_SetEngineString(s);
 }
 
 void PF_Spawn (void)
@@ -1165,7 +1165,7 @@ void PF_Find (void)
 {
        int             e;
        int             f;
-       char    *s, *t;
+       const char      *s, *t;
        edict_t *ed;
 
        e = G_EDICTNUM(OFS_PARM0);
@@ -1230,7 +1230,7 @@ void PF_findchain (void)
 {
        int             i;
        int             f;
-       char    *s, *t;
+       const char      *s, *t;
        edict_t *ent, *chain;
 
        chain = (edict_t *)sv.edicts;
@@ -1349,12 +1349,6 @@ void PF_findchainflags (void)
        RETURN_EDICT(chain);
 }
 
-void PR_CheckEmptyString (char *s)
-{
-       if (s[0] <= ' ')
-               PF_ERROR("Bad string");
-}
-
 void PF_precache_file (void)
 {      // precache_file is only used to copy files with qcc, it does nothing
        G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
@@ -1490,7 +1484,7 @@ void(float style, string value) lightstyle
 void PF_lightstyle (void)
 {
        int             style;
-       char    *val;
+       const char      *val;
        client_t        *client;
        int                     j;
 
@@ -1498,7 +1492,7 @@ void PF_lightstyle (void)
        val = G_STRING(OFS_PARM1);
 
 // change the string in sv
-       sv.lightstyles[style] = val;
+       strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
 
 // send message to all clients on this server
        if (sv.state != ss_active)
@@ -1946,7 +1940,7 @@ PF_changelevel
 */
 void PF_changelevel (void)
 {
-       char    *s;
+       const char      *s;
 
 // make sure we don't issue two changelevels
        if (svs.changelevel_issued)
@@ -2021,7 +2015,7 @@ void PF_GetLight (void)
 
 void PF_registercvar (void)
 {
-       char *name, *value;
+       const char *name, *value;
        name = G_STRING(OFS_PARM0);
        value = G_STRING(OFS_PARM1);
        G_FLOAT(OFS_RETURN) = 0;
@@ -2207,7 +2201,7 @@ effect(origin, modelname, startframe, framecount, framerate)
 void PF_effect (void)
 {
        int i;
-       char *s;
+       const char *s;
        s = G_STRING(OFS_PARM1);
        if (!s || !s[0])
                PF_WARNING("effect: no model specified\n");
@@ -2718,7 +2712,7 @@ void PF_getsurfacetexture(void)
        G_INT(OFS_RETURN) = 0;
        if (!(surface = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
                return;
-       G_INT(OFS_RETURN) = PR_SetString(surface->texture->name);
+       G_INT(OFS_RETURN) = PR_SetEngineString(surface->texture->name);
 }
 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
 void PF_getsurfacenearpoint(void)
@@ -2822,7 +2816,7 @@ void PF_stof(void)
 void PF_fopen(void)
 {
        int filenum, mode;
-       char *modestring, *filename;
+       const char *modestring, *filename;
        for (filenum = 0;filenum < MAX_PRFILES;filenum++)
                if (pr_files[filenum] == NULL)
                        break;
@@ -2916,7 +2910,7 @@ void PF_fgets(void)
        if (developer.integer)
                Con_Printf("fgets: %s\n", string);
        if (c >= 0 || end)
-               G_INT(OFS_RETURN) = PR_SetString(string);
+               G_INT(OFS_RETURN) = PR_SetEngineString(string);
        else
                G_INT(OFS_RETURN) = 0;
 }
@@ -2947,7 +2941,7 @@ void PF_fputs(void)
 //float(string s) strlen = #114; // returns how many characters are in a string
 void PF_strlen(void)
 {
-       char *s;
+       const char *s;
        s = G_STRING(OFS_PARM0);
        if (s)
                G_FLOAT(OFS_RETURN) = strlen(s);
@@ -2960,14 +2954,15 @@ void PF_strcat(void)
 {
        char *s = PR_GetTempString();
        PF_VarString(0, s, STRINGTEMP_LENGTH);
-       G_INT(OFS_RETURN) = PR_SetString(s);
+       G_INT(OFS_RETURN) = PR_SetEngineString(s);
 }
 
 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
 void PF_substring(void)
 {
        int i, start, length;
-       char *s, *string = PR_GetTempString();
+       const char *s;
+       char *string = PR_GetTempString();
        s = G_STRING(OFS_PARM0);
        start = G_FLOAT(OFS_PARM1);
        length = G_FLOAT(OFS_PARM2);
@@ -2977,7 +2972,7 @@ void PF_substring(void)
        for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
                string[i] = *s;
        string[i] = 0;
-       G_INT(OFS_RETURN) = PR_SetString(string);
+       G_INT(OFS_RETURN) = PR_SetEngineString(string);
 }
 
 //vector(string s) stov = #117; // returns vector value from a string
@@ -2991,17 +2986,18 @@ void PF_stov(void)
 //string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
 void PF_strzone(void)
 {
-       char *in, *out;
+       const char *in;
+       char *out;
        in = G_STRING(OFS_PARM0);
-       out = PR_Alloc(strlen(in) + 1);
+       out = PR_AllocString(strlen(in) + 1);
        strcpy(out, in);
-       G_INT(OFS_RETURN) = PR_SetString(out);
+       G_INT(OFS_RETURN) = PR_SetQCString(out);
 }
 
 //void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
 void PF_strunzone(void)
 {
-       PR_Free(G_STRING(OFS_PARM0));
+       PR_FreeString((char *)G_STRING(OFS_PARM0));
 }
 
 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
@@ -3058,9 +3054,9 @@ void PF_argv (void)
 {
        int token_num = G_FLOAT(OFS_PARM0);
        if (token_num >= 0 && token_num < num_tokens)
-               G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
+               G_INT(OFS_RETURN) = PR_SetEngineString(tokens[token_num]);
        else
-               G_INT(OFS_RETURN) = PR_SetString("");
+               G_INT(OFS_RETURN) = PR_SetEngineString(NULL);
 }
 
 //void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
@@ -3068,7 +3064,7 @@ void PF_setattachment (void)
 {
        edict_t *e = G_EDICT(OFS_PARM0);
        edict_t *tagentity = G_EDICT(OFS_PARM1);
-       char *tagname = G_STRING(OFS_PARM2);
+       const char *tagname = G_STRING(OFS_PARM2);
        eval_t *v;
        int modelindex;
        model_t *model;
@@ -3105,7 +3101,7 @@ void PF_setattachment (void)
 /////////////////////////////////////////
 // DP_MD3_TAGINFO extension coded by VorteX
 
-int SV_GetTagIndex (edict_t *e, char *tagname)
+int SV_GetTagIndex (edict_t *e, const char *tagname)
 {
        int i;
        model_t *model;
@@ -3259,7 +3255,7 @@ int SV_GetTagMatrix (matrix4x4_t *out, edict_t *ent, int tagindex)
 void PF_gettagindex (void)
 {
        edict_t *ent = G_EDICT(OFS_PARM0);
-       char *tag_name = G_STRING(OFS_PARM1);
+       const char *tag_name = G_STRING(OFS_PARM1);
        int modelindex, tag_index;
 
        if (ent == sv.edicts)
@@ -3345,12 +3341,12 @@ float search_begin(string pattern, float caseinsensitive, float quiet)
 void PF_search_begin(void)
 {
        int handle;
-       char *pattern;
+       const char *pattern;
        int caseinsens, quiet;
 
        pattern = G_STRING(OFS_PARM0);
-
-       PR_CheckEmptyString(pattern);
+       if (!pattern || pattern[0] <= ' ')
+               PF_ERROR("PF_search_begin: Bad string");
 
        caseinsens = G_FLOAT(OFS_PARM1);
        quiet = G_FLOAT(OFS_PARM2);
@@ -3461,12 +3457,12 @@ void PF_search_getfilename(void)
        tmp = PR_GetTempString();
        strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
 
-       G_INT(OFS_RETURN) = PR_SetString(tmp);
+       G_INT(OFS_RETURN) = PR_SetEngineString(tmp);
 }
 
 void PF_cvar_string (void)
 {
-       char *str;
+       const char *str;
        cvar_t *var;
        char *tmp;
 
@@ -3478,8 +3474,8 @@ void PF_cvar_string (void)
                strcpy(tmp, var->string);
        }
        else
-               tmp = "";
-       G_INT(OFS_RETURN) = PR_SetString(tmp);
+               tmp = NULL;
+       G_INT(OFS_RETURN) = PR_SetEngineString(tmp);
 }
 
 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
index 985fc4d..8b1ef35 100644 (file)
@@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 dprograms_t            *progs;
 mfunction_t            *pr_functions;
 char                   *pr_strings;
+int                            pr_stringssize;
 ddef_t                 *pr_fielddefs;
 ddef_t                 *pr_globaldefs;
 dstatement_t   *pr_statements;
@@ -32,6 +33,10 @@ float                        *pr_globals;                    // same as pr_global_struct
 int                            pr_edict_size;                  // in bytes
 int                            pr_edictareasize;               // LordHavoc: in bytes
 
+int                            pr_maxknownstrings;
+int                            pr_numknownstrings;
+const char             **pr_knownstrings;
+
 unsigned short pr_crc;
 
 mempool_t              *serverprogs_mempool;
@@ -235,14 +240,14 @@ void ED_ClearEdict (edict_t *e)
                // set netname/clientcolors back to client values so that
                // DP_SV_CLIENTNAME and DPV_SV_CLIENTCOLORS will not immediately
                // reset them
-               e->v->netname = PR_SetString(svs.clients[num].name);
+               e->v->netname = PR_SetEngineString(svs.clients[num].name);
                if ((val = GETEDICTFIELDVALUE(e, eval_clientcolors)))
                        val->_float = svs.clients[num].colors;
                // NEXUIZ_PLAYERMODEL and NEXUIZ_PLAYERSKIN
                if( eval_playermodel )
-                       GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(svs.clients[num].playermodel);
+                       GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetEngineString(svs.clients[num].playermodel);
                if( eval_playerskin )
-                       GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(svs.clients[num].playerskin);
+                       GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetEngineString(svs.clients[num].playerskin);
        }
 }
 
@@ -484,7 +489,7 @@ char *PR_UglyValueString (etype_t type, eval_t *val)
 {
        static char line[4096];
        int i;
-       char *s;
+       const char *s;
        ddef_t *def;
        mfunction_t *f;
 
@@ -613,7 +618,7 @@ void ED_Print(edict_t *ed)
        ddef_t  *d;
        int             *v;
        int             i, j;
-       char    *name;
+       const char      *name;
        int             type;
        char    tempstring[8192], tempstring2[260]; // temporary string buffers
 
@@ -687,7 +692,7 @@ void ED_Write (qfile_t *f, edict_t *ed)
        ddef_t  *d;
        int             *v;
        int             i, j;
-       char    *name;
+       const char      *name;
        int             type;
 
        FS_Print(f, "{\n");
@@ -817,7 +822,7 @@ void ED_WriteGlobals (qfile_t *f)
 {
        ddef_t          *def;
        int                     i;
-       char            *name;
+       const char              *name;
        int                     type;
 
        FS_Print(f,"{\n");
@@ -909,40 +914,6 @@ void ED_ParseGlobals (const char *data)
 //============================================================================
 
 
-/*
-=============
-ED_NewString
-=============
-*/
-char *ED_NewString (const char *string)
-{
-       char *new, *new_p;
-       int i,l;
-
-       l = strlen(string) + 1;
-       new = PR_Alloc(l);
-       new_p = new;
-
-       for (i=0 ; i< l ; i++)
-       {
-               if (string[i] == '\\' && i < l-1)
-               {
-                       i++;
-                       if (string[i] == 'n')
-                               *new_p++ = '\n';
-                       else if (string[i] == 'r')
-                               *new_p++ = '\r';
-                       else
-                               *new_p++ = '\\';
-               }
-               else
-                       *new_p++ = string[i];
-       }
-
-       return new;
-}
-
-
 /*
 =============
 ED_ParseEval
@@ -953,7 +924,8 @@ returns false if error
 */
 qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
 {
-       int i;
+       int i, l;
+       char *new_p;
        ddef_t *def;
        eval_t *val;
        mfunction_t *func;
@@ -965,7 +937,24 @@ qboolean ED_ParseEpair(edict_t *ent, ddef_t *key, const char *s)
        switch (key->type & ~DEF_SAVEGLOBAL)
        {
        case ev_string:
-               val->string = PR_SetString(ED_NewString(s));
+               l = strlen(s) + 1;
+               new_p = PR_AllocString(l);
+               val->string = PR_SetQCString(new_p);
+               for (i = 0;i < l;i++)
+               {
+                       if (s[i] == '\\' && i < l-1)
+                       {
+                               i++;
+                               if (s[i] == 'n')
+                                       *new_p++ = '\n';
+                               else if (s[i] == 'r')
+                                       *new_p++ = '\r';
+                               else
+                                       *new_p++ = s[i];
+                       }
+                       else
+                               *new_p++ = s[i];
+               }
                break;
 
        case ev_float:
@@ -1327,7 +1316,19 @@ void PR_LoadProgs (const char *progsname)
 
        //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
        dfunctions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
+
        pr_strings = (char *)progs + progs->ofs_strings;
+       pr_stringssize = 0;
+       for (i = 0;i < progs->numstrings;i++)
+       {
+               if (progs->ofs_strings + pr_stringssize >= fs_filesize)
+                       Host_Error ("progs.dat strings go past end of file\n");
+               pr_stringssize += strlen (pr_strings + pr_stringssize) + 1;
+       }
+       pr_numknownstrings = 0;
+       pr_maxknownstrings = 0;
+       pr_knownstrings = NULL;
+
        pr_globaldefs = (ddef_t *)((qbyte *)progs + progs->ofs_globaldefs);
 
        // we need to expand the fielddefs list to include all the engine fields,
@@ -1385,7 +1386,7 @@ void PR_LoadProgs (const char *progsname)
        {
                pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
                pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
-               pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
+               pr_fielddefs[progs->numfielddefs].s_name = PR_SetEngineString(dpfields[i].string);
                if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
                        progs->entityfields += 3;
                else
@@ -1510,7 +1511,8 @@ void PR_Fields_f (void)
 {
        int i, j, ednum, used, usedamount;
        int *counts;
-       char tempstring[5000], tempstring2[260], *name;
+       const char *name;
+       char tempstring[5000], tempstring2[260];
        edict_t *ed;
        ddef_t *d;
        int *v;
@@ -1756,3 +1758,106 @@ edict_t *PROG_TO_EDICT(int n)
 }
 */
 
+const char *PR_GetString(int num)
+{
+       if (num >= 0 && num < pr_stringssize)
+               return pr_strings + num;
+       else if (num < 0 && num >= -pr_numknownstrings)
+       {
+               num = -1 - num;
+               if (!pr_knownstrings[num])
+                       Host_Error("PR_GetString: attempt to get string that is already freed\n");
+               return pr_knownstrings[num];
+       }
+       else
+       {
+               Host_Error("PR_GetString: invalid string offset %i\n", num);
+               return "";
+       }
+}
+
+int PR_SetQCString(const char *s)
+{
+       int i;
+       if (!s)
+               return 0;
+       if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+               return s - pr_strings;
+       for (i = 0;i < pr_numknownstrings;i++)
+               if (pr_knownstrings[i] == s)
+                       return -1 - i;
+       Host_Error("PR_SetQCString: unknown string\n");
+       return -1 - i;
+}
+
+int PR_SetEngineString(const char *s)
+{
+       int i;
+       if (!s)
+               return 0;
+       if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+               Host_Error("PR_SetEngineString: s in pr_strings area\n");
+       for (i = 0;i < pr_numknownstrings;i++)
+               if (pr_knownstrings[i] == s)
+                       return -1 - i;
+       // new unknown engine string
+       if (developer.integer >= 3)
+               Con_Printf("new engine string %p\n", s);
+       for (i = 0;i < pr_numknownstrings;i++)
+               if (!pr_knownstrings[i])
+                       break;
+       if (i >= pr_numknownstrings)
+       {
+               if (i >= pr_maxknownstrings)
+               {
+                       const char **oldstrings = pr_knownstrings;
+                       pr_maxknownstrings += 128;
+                       pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
+                       if (pr_numknownstrings)
+                               memcpy(pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
+               }
+               pr_numknownstrings++;
+       }
+       pr_knownstrings[i] = s;
+       return -1 - i;
+}
+
+char *PR_AllocString(int bufferlength)
+{
+       int i;
+       if (!bufferlength)
+               return 0;
+       for (i = 0;i < pr_numknownstrings;i++)
+               if (!pr_knownstrings[i])
+                       break;
+       if (i >= pr_numknownstrings)
+       {
+               if (i >= pr_maxknownstrings)
+               {
+                       const char **oldstrings = pr_knownstrings;
+                       pr_maxknownstrings += 128;
+                       pr_knownstrings = PR_Alloc(pr_maxknownstrings * sizeof(char *));
+                       if (pr_numknownstrings)
+                               memcpy(pr_knownstrings, oldstrings, pr_numknownstrings * sizeof(char *));
+               }
+               pr_numknownstrings++;
+       }
+       return (char *)(pr_knownstrings[i] = PR_Alloc(bufferlength));
+}
+
+void PR_FreeString(char *s)
+{
+       int i;
+       if (!s)
+               Host_Error("PR_FreeString: attempt to free a NULL string\n");
+       if (s >= pr_strings && s <= pr_strings + pr_stringssize)
+               Host_Error("PR_FreeString: attempt to free a constant string\n");
+       for (i = 0;i < pr_numknownstrings;i++)
+               if (pr_knownstrings[i] == s)
+                       break;
+       if (i == pr_numknownstrings)
+               Host_Error("PR_FreeString: attempt to free a non-existent or already freed string\n");
+       PR_Free((char *)pr_knownstrings[i]);
+       pr_knownstrings[i] = NULL;
+}
+
diff --git a/progs.h b/progs.h
index b39f355..e4ea141 100644 (file)
--- a/progs.h
+++ b/progs.h
@@ -147,6 +147,7 @@ extern mfunction_t *SV_ParseClientCommandQC;
 extern dprograms_t             *progs;
 extern mfunction_t             *pr_functions;
 extern char                    *pr_strings;
+extern int                             pr_stringssize;
 extern ddef_t                  *pr_globaldefs;
 extern ddef_t                  *pr_fielddefs;
 extern dstatement_t    *pr_statements;
@@ -156,6 +157,10 @@ extern     float                   *pr_globals;                    // same as pr_global_struct
 extern int                             pr_edict_size;  // in bytes
 extern int                             pr_edictareasize; // LordHavoc: for bounds checking
 
+extern int                             pr_maxknownstrings;
+extern int                             pr_numknownstrings;
+extern const char              **pr_knownstrings;
+
 //============================================================================
 
 void PR_Init (void);
@@ -182,9 +187,6 @@ edict_t *ED_Alloc (void);
 void ED_Free (edict_t *ed);
 void ED_ClearEdict (edict_t *e);
 
-char   *ED_NewString (const char *string);
-// returns a copy of the string allocated from the server's string heap
-
 void ED_Print(edict_t *ed);
 void ED_Write (qfile_t *f, edict_t *ed);
 const char *ED_ParseEdict (const char *data, edict_t *ent);
@@ -244,8 +246,11 @@ void PR_Execute_ProgsLoaded(void);
 void ED_PrintEdicts (void);
 void ED_PrintNum (int ent);
 
-#define PR_GetString(num) (pr_strings + num)
-#define PR_SetString(s)   ((s) != NULL ? (int) (s - pr_strings) : 0)
+const char *PR_GetString(int num);
+int PR_SetQCString(const char *s);
+int PR_SetEngineString(const char *s);
+char *PR_AllocString(int bufferlength);
+void PR_FreeString(char *s);
 
 #endif
 
index 744c8f5..0ea2072 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -242,6 +242,7 @@ typedef struct vm_prog_s
        dprograms_t                     *progs;
        mfunction_t                     *functions;
        char                            *strings;
+       int                                     stringssize;
        ddef_t                          *fielddefs;
        ddef_t                          *globaldefs;
        dstatement_t            *statements;
@@ -250,6 +251,10 @@ typedef struct vm_prog_s
        int                                     edict_size;                     // in bytes
        int                                     edictareasize;          // LordHavoc: in bytes (for bound checking)
 
+       int                                     maxknownstrings;
+       int                                     numknownstrings;
+       const char                      **knownstrings;
+
        // all memory allocations related to this vm_prog (code, edicts, strings)
        mempool_t                       *progs_mempool;
 
@@ -379,6 +384,13 @@ void PRVM_Init (void);
 void PRVM_ExecuteProgram (func_t fnum, const char *errormessage);
 void PRVM_LoadProgs (const char *filename, int numrequiredfunc, char **required_func);
 
+#define PRVM_Alloc(buffersize) _PRVM_Alloc(buffersize, __FILE__, __LINE__)
+#define PRVM_Free(buffer) _PRVM_Free(buffer, __FILE__, __LINE__)
+#define PRVM_FreeAll() _PRVM_FreeAll(__FILE__, __LINE__)
+void *_PRVM_Alloc (size_t buffersize, const char *filename, int fileline);
+void _PRVM_Free (void *buffer, const char *filename, int fileline);
+void _PRVM_FreeAll (const char *filename, int fileline);
+
 void PRVM_Profile_f (void);
 
 void PRVM_PrintState(void);
@@ -389,9 +401,6 @@ prvm_edict_t *PRVM_ED_Alloc (void);
 void PRVM_ED_Free (prvm_edict_t *ed);
 void PRVM_ED_ClearEdict (prvm_edict_t *e);
 
-char *PRVM_ED_NewString (const char *string);
-// returns a copy of the string allocated from the server's string heap
-
 void PRVM_ED_Print(prvm_edict_t *ed);
 void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed);
 const char *PRVM_ED_ParseEdict (const char *data, prvm_edict_t *ent);
@@ -439,8 +448,11 @@ void PRVM_Init_Exec(void);
 void PRVM_ED_PrintEdicts_f (void);
 void PRVM_ED_PrintNum (int ent);
 
-#define PRVM_GetString(num) (prog->strings + num)
-#define PRVM_SetString(s)   ((s) != NULL ? (int) (s - prog->strings) : 0)
+const char *PRVM_GetString(int num);
+int PRVM_SetQCString(const char *s);
+int PRVM_SetEngineString(const char *s);
+char *PRVM_AllocString(int bufferlength);
+void PRVM_FreeString(char *s);
 
 //============================================================================
 
index 4ebdc3b..b09b92a 100644 (file)
@@ -190,8 +190,6 @@ float       getserverlistindexforkey(string key)
 
 #define        VM_RETURN_EDICT(e)              (((int *)prog->globals)[OFS_RETURN] = PRVM_EDICT_TO_PROG(e))
 
-#define VM_STRINGS_MEMPOOL             vm_strings_mempool[PRVM_GetProgNr()]
-
 #define e10 0,0,0,0,0,0,0,0,0,0
 #define e100 e10,e10,e10,e10,e10,e10,e10,e10,e10,e10
 #define e1000 e100,e100,e100,e100,e100,e100,e100,e100,e100,e100
@@ -199,9 +197,6 @@ float       getserverlistindexforkey(string key)
 //============================================================================
 // Common
 
-// string zone mempool
-mempool_t *vm_strings_mempool[PRVM_MAXPROGS];
-
 // temp string handling
 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
 #define VM_STRINGTEMP_BUFFERS 16
@@ -231,7 +226,7 @@ static char *VM_GetTempString(void)
        return s;
 }
 
-void VM_CheckEmptyString (char *s)
+void VM_CheckEmptyString (const char *s)
 {
        if (s[0] <= ' ')
                PRVM_ERROR ("%s: Bad string", PRVM_NAME);
@@ -267,7 +262,7 @@ checkextension(extensionname)
 */
 
 // kind of helper function
-static qboolean checkextension(char *name)
+static qboolean checkextension(const char *name)
 {
        int len;
        char *e, *start;
@@ -641,7 +636,7 @@ localsound(string sample)
 */
 void VM_localsound(void)
 {
-       char *s;
+       const char *s;
 
        VM_SAFEPARMCOUNT(1,VM_localsound);
 
@@ -711,7 +706,8 @@ const string        str_cvar (string)
 */
 void VM_str_cvar(void)
 {
-       char *out, *name;
+       char *out;
+       const char *name;
        const char *cvar_string;
        VM_SAFEPARMCOUNT(1,VM_str_cvar);
 
@@ -728,7 +724,7 @@ void VM_str_cvar(void)
 
        strcpy(out, cvar_string);
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(out);
 }
 
 /*
@@ -784,7 +780,7 @@ void VM_ftos (void)
                sprintf(s, "%i", (int)v);
        else
                sprintf(s, "%f", v);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
 }
 
 /*
@@ -821,7 +817,7 @@ void VM_vtos (void)
 
        s = VM_GetTempString();
        sprintf (s, "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
 }
 
 /*
@@ -840,7 +836,7 @@ void VM_etos (void)
 
        s = VM_GetTempString();
        sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
 }
 
 /*
@@ -940,7 +936,7 @@ void VM_find (void)
 {
        int             e;
        int             f;
-       char    *s, *t;
+       const char      *s, *t;
        prvm_edict_t    *ed;
 
        VM_SAFEPARMCOUNT(3,VM_find);
@@ -1028,7 +1024,7 @@ void VM_findchain (void)
        int             i;
        int             f;
        int             chain_of;
-       char    *s, *t;
+       const char      *s, *t;
        prvm_edict_t    *ent, *chain;
 
        VM_SAFEPARMCOUNT(2,VM_findchain);
@@ -1150,7 +1146,7 @@ string    precache_sound (string sample)
 */
 void VM_precache_sound (void)
 {
-       char    *s;
+       const char      *s;
 
        VM_SAFEPARMCOUNT(1, VM_precache_sound);
 
@@ -1434,7 +1430,7 @@ changelevel(string map)
 */
 void VM_changelevel (void)
 {
-       char    *s;
+       const char      *s;
 
        VM_SAFEPARMCOUNT(1, VM_changelevel);
 
@@ -1449,7 +1445,7 @@ void VM_changelevel (void)
                return;
        svs.changelevel_issued = true;
 
-       s = G_STRING(OFS_PARM0);
+       s = PRVM_G_STRING(OFS_PARM0);
        Cbuf_AddText (va("changelevel %s\n",s));
 }
 
@@ -1538,7 +1534,7 @@ float     registercvar (string name, string value, float flags)
 */
 void VM_registercvar (void)
 {
-       char *name, *value;
+       const char *name, *value;
        int     flags;
 
        VM_SAFEPARMCOUNT(3,VM_registercvar);
@@ -1735,7 +1731,7 @@ float     fopen(string filename, float mode)
 void VM_fopen(void)
 {
        int filenum, mode;
-       char *modestring, *filename;
+       const char *modestring, *filename;
 
        VM_SAFEPARMCOUNT(2,VM_fopen);
 
@@ -1862,7 +1858,7 @@ void VM_fgets(void)
        if (developer.integer >= 3)
                Con_Printf("fgets: %s: %s\n", PRVM_NAME, string);
        if (c >= 0 || end)
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
        else
                PRVM_G_INT(OFS_RETURN) = 0;
 }
@@ -1911,7 +1907,7 @@ float     strlen(string s)
 //float(string s) strlen = #114; // returns how many characters are in a string
 void VM_strlen(void)
 {
-       char *s;
+       const char *s;
 
        VM_SAFEPARMCOUNT(1,VM_strlen);
 
@@ -1941,7 +1937,7 @@ void VM_strcat(void)
 
        s = VM_GetTempString();
        VM_VarString(0, s, VM_STRINGTEMP_LENGTH);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(s);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
 }
 
 /*
@@ -1956,7 +1952,8 @@ string    substring(string s, float start, float length)
 void VM_substring(void)
 {
        int i, start, length;
-       char *s, *string;
+       const char *s;
+       char *string;
 
        VM_SAFEPARMCOUNT(3,VM_substring);
 
@@ -1970,7 +1967,7 @@ void VM_substring(void)
        for (i = 0;i < VM_STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
                string[i] = *s;
        string[i] = 0;
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(string);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
 }
 
 /*
@@ -2001,14 +1998,15 @@ string  strzone(string s)
 //string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
 void VM_strzone(void)
 {
-       char *in, *out;
+       const char *in;
+       char *out;
 
        VM_SAFEPARMCOUNT(1,VM_strzone);
 
        in = PRVM_G_STRING(OFS_PARM0);
-       out = Mem_Alloc(VM_STRINGS_MEMPOOL, strlen(in) + 1);
+       out = PRVM_AllocString(strlen(in) + 1);
        strcpy(out, in);
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(out);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetQCString(out);
 }
 
 /*
@@ -2021,16 +2019,8 @@ strunzone(string s)
 //void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
 void VM_strunzone(void)
 {
-       char *str;
        VM_SAFEPARMCOUNT(1,VM_strunzone);
-
-       str = PRVM_G_STRING(OFS_PARM0);
-       if( !str )
-               PRVM_ERROR( "VM_strunzone: s%: Null string passed!", PRVM_NAME );
-       if( developer.integer && !Mem_IsAllocated( VM_STRINGS_MEMPOOL, str ) )
-               PRVM_ERROR( "VM_strunzone: Zone string already freed in %s!", PRVM_NAME );
-       else
-               Mem_Free( str );
+       PRVM_FreeString((char *)PRVM_G_STRING(OFS_PARM0));
 }
 
 /*
@@ -2077,8 +2067,7 @@ static char **tokens = NULL;
 static int    max_tokens, num_tokens = 0;
 void VM_tokenize (void)
 {
-       const char *p;
-       char *str;
+       const char *p, *str;
 
        VM_SAFEPARMCOUNT(1,VM_tokenize);
 
@@ -2123,9 +2112,9 @@ void VM_argv (void)
 
        token_num = PRVM_G_FLOAT(OFS_PARM0);
        if (token_num >= 0 && token_num < num_tokens)
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tokens[token_num]);
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]);
        else
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
 }
 
 /*
@@ -2322,7 +2311,7 @@ loadfromfile(string file)
 */
 void VM_loadfromfile(void)
 {
-       char *filename;
+       const char *filename;
        qbyte *data;
 
        VM_SAFEPARMCOUNT(1,VM_loadfromfile);
@@ -2394,7 +2383,7 @@ float search_begin(string pattern, float caseinsensitive, float quiet)
 void VM_search_begin(void)
 {
        int handle;
-       char *pattern;
+       const char *pattern;
        int caseinsens, quiet;
 
        VM_SAFEPARMCOUNT(3, VM_search_begin);
@@ -2515,7 +2504,7 @@ void VM_search_getfilename(void)
        tmp = VM_GetTempString();
        strcpy(tmp, VM_SEARCHLIST[handle]->filenames[filenum]);
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
 }
 
 /*
@@ -2534,7 +2523,7 @@ void VM_chr(void)
        tmp[0] = (unsigned char) PRVM_G_FLOAT(OFS_PARM0);
        tmp[1] = 0;
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
 }
 
 //=============================================================================
@@ -2564,7 +2553,7 @@ string    precache_pic(string pic)
 */
 void VM_precache_pic(void)
 {
-       char    *s;
+       const char      *s;
 
        VM_SAFEPARMCOUNT(1, VM_precache_pic);
 
@@ -2578,7 +2567,7 @@ void VM_precache_pic(void)
 
        // AK Draw_CachePic is supposed to always return a valid pointer
        if( Draw_CachePic(s, false)->tex == r_texture_notexture )
-               PRVM_G_INT(OFS_RETURN) = PRVM_SetString("");
+               PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
 }
 
 /*
@@ -2590,7 +2579,7 @@ freepic(string s)
 */
 void VM_freepic(void)
 {
-       char *s;
+       const char *s;
 
        VM_SAFEPARMCOUNT(1,VM_freepic);
 
@@ -2662,7 +2651,7 @@ float     drawstring(vector position, string text, vector scale, vector rgb, float a
 void VM_drawstring(void)
 {
        float *pos,*scale,*rgb;
-       char  *string;
+       const char  *string;
        int flag;
        VM_SAFEPARMCOUNT(6,VM_drawstring);
 
@@ -2710,7 +2699,7 @@ float     drawpic(vector position, string pic, vector size, vector rgb, float alpha,
 */
 void VM_drawpic(void)
 {
-       char *pic;
+       const char *pic;
        float *size, *pos, *rgb;
        int flag;
 
@@ -2831,7 +2820,7 @@ vector    getimagesize(string pic)
 */
 void VM_getimagesize(void)
 {
-       char *p;
+       const char *p;
        cachepic_t *pic;
 
        VM_SAFEPARMCOUNT(1,VM_getimagesize);
@@ -2861,8 +2850,8 @@ float cin_open(string file, string name)
 */
 void VM_cin_open( void )
 {
-       char *file;
-       char *name;
+       const char *file;
+       const char *name;
 
        VM_SAFEPARMCOUNT( 2, VM_cin_open );
 
@@ -2887,7 +2876,7 @@ void cin_close(string name)
 */
 void VM_cin_close( void )
 {
-       char *name;
+       const char *name;
 
        VM_SAFEPARMCOUNT( 1, VM_cin_close );
 
@@ -2905,7 +2894,7 @@ void cin_setstate(string name, float type)
 */
 void VM_cin_setstate( void )
 {
-       char *name;
+       const char *name;
        clvideostate_t  state;
        clvideo_t               *video;
 
@@ -2930,7 +2919,7 @@ float cin_getstate(string name)
 */
 void VM_cin_getstate( void )
 {
-       char *name;
+       const char *name;
        clvideo_t               *video;
 
        VM_SAFEPARMCOUNT( 1, VM_cin_getstate );
@@ -2954,7 +2943,7 @@ void cin_restart(string name)
 */
 void VM_cin_restart( void )
 {
-       char *name;
+       const char *name;
        clvideo_t               *video;
 
        VM_SAFEPARMCOUNT( 1, VM_cin_restart );
@@ -2980,7 +2969,7 @@ float altstr_count(string)
 */
 void VM_altstr_count( void )
 {
-       char *altstr, *pos;
+       const char *altstr, *pos;
        int     count;
 
        VM_SAFEPARMCOUNT( 1, VM_altstr_count );
@@ -3007,7 +2996,7 @@ string altstr_prepare(string)
 void VM_altstr_prepare( void )
 {
        char *outstr, *out;
-       char *instr, *in;
+       const char *instr, *in;
        int size;
 
        VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
@@ -3025,7 +3014,7 @@ void VM_altstr_prepare( void )
                        *out = *in;
        *out = 0;
 
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
 }
 
 /*
@@ -3037,7 +3026,8 @@ string altstr_get(string, float)
 */
 void VM_altstr_get( void )
 {
-       char *altstr, *pos, *outstr, *out;
+       const char *altstr, *pos;
+       char *outstr, *out;
        int count, size;
 
        VM_SAFEPARMCOUNT( 2, VM_altstr_get );
@@ -3055,7 +3045,7 @@ void VM_altstr_get( void )
                        count--;
 
        if( !*pos ) {
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+               PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
                return;
        }
 
@@ -3072,7 +3062,7 @@ void VM_altstr_get( void )
                        *out = *pos;
 
        *out = 0;
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
 }
 
 /*
@@ -3085,8 +3075,8 @@ string altstr_set(string altstr, float num, string set)
 void VM_altstr_set( void )
 {
     int num;
-       char *altstr, *str;
-       char *in;
+       const char *altstr, *str;
+       const char *in;
        char *outstr, *out;
 
        VM_SAFEPARMCOUNT( 3, VM_altstr_set );
@@ -3107,7 +3097,7 @@ void VM_altstr_set( void )
                        num--;
 
        if( !in ) {
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+               PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
                return;
        }
        // copy set in
@@ -3118,12 +3108,12 @@ void VM_altstr_set( void )
                        break;
 
        if( !in ) {
-               PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( "" );
+               PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( NULL );
                return;
        }
 
        strcpy( out, in );
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
 }
 
 /*
@@ -3136,10 +3126,10 @@ string  altstr_ins(string altstr, float num, string set)
 void VM_altstr_ins(void)
 {
        int num;
-       char *setstr;
-       char *set;
-       char *instr;
-       char *in;
+       const char *setstr;
+       const char *set;
+       const char *instr;
+       const char *in;
        char *outstr;
        char *out;
 
@@ -3157,29 +3147,18 @@ void VM_altstr_ins(void)
        for( ; *set ; *out++ = *set++ );
 
        strcpy( out, in );
-       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( outstr );
+       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( outstr );
 }
 
 void VM_Cmd_Init(void)
 {
        // only init the stuff for the current prog
-       VM_STRINGS_MEMPOOL = Mem_AllocPool(va("vm_stringsmempool[%s]",PRVM_NAME), 0, NULL);
        VM_Files_Init();
        VM_Search_Init();
 }
 
 void VM_Cmd_Reset(void)
 {
-       //Mem_EmptyPool(VM_STRINGS_MEMPOOL);
-       if( developer.integer >= 2 && VM_STRINGS_MEMPOOL ) {
-               memheader_t *header;
-               int     i;
-
-               for( i = 0, header = VM_STRINGS_MEMPOOL->chain ; header ; header = header->next, i++ )
-                       Con_DPrintf( "Leaked string %i (size: %i): %.*s\n", i, header->size, header->size, ((char*)header) + sizeof( memheader_t ) );
-       }
-
-       Mem_FreePool(&VM_STRINGS_MEMPOOL);
        CL_PurgeOwner( MENUOWNER );
        VM_Search_Reset();
        VM_Files_CloseAll();
@@ -3345,7 +3324,7 @@ mfunction_t *PRVM_ED_FindFunction (const char *name);
 void VM_M_callfunction(void)
 {
        mfunction_t *func;
-       char *s;
+       const char *s;
 
        if(prog->argc == 0)
                PRVM_ERROR("VM_M_callfunction: 1 parameter is required !\n");
@@ -3390,7 +3369,7 @@ mfunction_t *PRVM_ED_FindFunction (const char *name);
 void VM_M_isfunction(void)
 {
        mfunction_t *func;
-       char *s;
+       const char *s;
 
        VM_SAFEPARMCOUNT(1, VM_M_isfunction);
 
@@ -3485,7 +3464,7 @@ void VM_M_keynumtostring(void)
 
        strcpy(tmp, Key_KeynumToString(keynum));
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(tmp);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
 }
 
 /*
@@ -3497,7 +3476,7 @@ float stringtokeynum(string key)
 */
 void VM_M_stringtokeynum( void )
 {
-       char *str;
+       const char *str;
        VM_SAFEPARMCOUNT( 1, VM_M_keynumtostring );
 
        str = PRVM_G_STRING( OFS_PARM0 );
@@ -3516,10 +3495,11 @@ the returned string is an altstring
 */
 #define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
 
-void M_FindKeysForCommand(char *command, int *keys);
+void M_FindKeysForCommand(const char *command, int *keys);
 void VM_M_findkeysforcommand(void)
 {
-       char *cmd, *ret;
+       const char *cmd;
+       char *ret;
        int keys[NUMKEYS];
        int i;
 
@@ -3536,7 +3516,7 @@ void VM_M_findkeysforcommand(void)
        for(i = 0; i < NUMKEYS; i++)
                ret = strcat(ret, va(" \'%i\'", keys[i]));
 
-       PRVM_G_INT(OFS_RETURN) = PRVM_SetString(ret);
+       PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(ret);
 }
 
 /*
@@ -3619,7 +3599,7 @@ setserverlistmaskstring(float mask, float fld, string str, float op)
 */
 void VM_M_setserverlistmaskstring( void )
 {
-       char *str;
+       const char *str;
        int masknr;
        serverlist_mask_t *mask;
        int field;
@@ -3758,26 +3738,26 @@ void VM_M_getserverliststring(void)
        cache = serverlist_viewlist[hostnr];
        switch( (int) PRVM_G_FLOAT(OFS_PARM0) ) {
                case SLIF_CNAME:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.cname );
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.cname );
                        break;
                case SLIF_NAME:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.name );
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.name );
                        break;
                case SLIF_GAME:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.game );
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.game );
                        break;
                case SLIF_MOD:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.mod );
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.mod );
                        break;
                case SLIF_MAP:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->info.map );
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->info.map );
                        break;
                // TODO remove this again
                case 1024:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line1 );
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line1 );
                        break;
                case 1025:
-                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetString( cache->line2 );
+                       PRVM_G_INT( OFS_RETURN ) = PRVM_SetEngineString( cache->line2 );
                        break;
                default:
                        Con_Print("VM_M_getserverliststring: bad field number passed!\n");
@@ -3863,7 +3843,7 @@ float getserverlistindexforkey(string key)
 */
 void VM_M_getserverlistindexforkey( void )
 {
-       char *key;
+       const char *key;
        VM_SAFEPARMCOUNT( 1, VM_M_getserverlistindexforkey );
 
        key = PRVM_G_STRING( OFS_PARM0 );
index 3f54cbe..818dba6 100644 (file)
@@ -435,7 +435,7 @@ char *PRVM_UglyValueString (etype_t type, prvm_eval_t *val)
 {
        static char line[4096];
        int i;
-       char *s;
+       const char *s;
        ddef_t *def;
        mfunction_t *f;
 
@@ -564,7 +564,7 @@ void PRVM_ED_Print(prvm_edict_t *ed)
        ddef_t  *d;
        int             *v;
        int             i, j;
-       char    *name;
+       const char      *name;
        int             type;
        char    tempstring[8192], tempstring2[260]; // temporary string buffers
 
@@ -638,7 +638,7 @@ void PRVM_ED_Write (qfile_t *f, prvm_edict_t *ed)
        ddef_t  *d;
        int             *v;
        int             i, j;
-       char    *name;
+       const char      *name;
        int             type;
 
        FS_Print(f, "{\n");
@@ -802,7 +802,7 @@ void PRVM_ED_WriteGlobals (qfile_t *f)
 {
        ddef_t          *def;
        int                     i;
-       char            *name;
+       const char              *name;
        int                     type;
 
        FS_Print(f,"{\n");
@@ -866,37 +866,6 @@ void PRVM_ED_ParseGlobals (const char *data)
 //============================================================================
 
 
-/*
-=============
-PRVM_ED_NewString
-=============
-*/
-char *PRVM_ED_NewString (const char *string)
-{
-       char *new, *new_p;
-       int i,l;
-
-       l = strlen(string) + 1;
-       new = Mem_Alloc(prog->progs_mempool, l);
-       new_p = new;
-
-       for (i=0 ; i< l ; i++)
-       {
-               if (string[i] == '\\' && i < l-1)
-               {
-                       i++;
-                       if (string[i] == 'n')
-                               *new_p++ = '\n';
-                       else
-                               *new_p++ = '\\';
-               }
-               else
-                       *new_p++ = string[i];
-       }
-
-       return new;
-}
-
 /*
 =============
 PRVM_ED_ParseEval
@@ -907,7 +876,8 @@ returns false if error
 */
 qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
 {
-       int i;
+       int i, l;
+       char *new_p;
        ddef_t *def;
        prvm_eval_t *val;
        mfunction_t *func;
@@ -919,7 +889,24 @@ qboolean PRVM_ED_ParseEpair(prvm_edict_t *ent, ddef_t *key, const char *s)
        switch (key->type & ~DEF_SAVEGLOBAL)
        {
        case ev_string:
-               val->string = PRVM_SetString(PRVM_ED_NewString(s));
+               l = strlen(s) + 1;
+               new_p = PRVM_AllocString(l);
+               val->string = PRVM_SetQCString(new_p);
+               for (i = 0;i < l;i++)
+               {
+                       if (s[i] == '\\' && i < l-1)
+                       {
+                               i++;
+                               if (s[i] == 'n')
+                                       *new_p++ = '\n';
+                               else if (s[i] == 'r')
+                                       *new_p++ = '\r';
+                               else
+                                       *new_p++ = s[i];
+                       }
+                       else
+                               *new_p++ = s[i];
+               }
                break;
 
        case ev_float:
@@ -1233,19 +1220,8 @@ PRVM_ResetProg
 
 void PRVM_ResetProg()
 {
-       /*mempool_t *t1;
-
-       t1 = prog->progs_mempool;
-
-       Mem_EmptyPool(prog->progs_mempool);*/
        Mem_FreePool(&prog->progs_mempool);
-
        memset(prog,0,sizeof(prvm_prog_t));
-
-       /*prog->time = &prog->_time;
-
-       prog->progs_mempool = t1;*/
-
        PRVM_GCALL(reset_cmd)();
 }
 
@@ -1282,7 +1258,19 @@ void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required
 
        //pr_functions = (dfunction_t *)((qbyte *)progs + progs->ofs_functions);
        dfunctions = (dfunction_t *)((qbyte *)prog->progs + prog->progs->ofs_functions);
+
        prog->strings = (char *)prog->progs + prog->progs->ofs_strings;
+       prog->stringssize = 0;
+       for (i = 0;i < prog->progs->numstrings;i++)
+       {
+               if (prog->progs->ofs_strings + prog->stringssize >= fs_filesize)
+                       PRVM_ERROR ("%s: %s strings go past end of file\n", PRVM_NAME, filename);
+               prog->stringssize += strlen (prog->strings + prog->stringssize) + 1;
+       }
+       prog->numknownstrings = 0;
+       prog->maxknownstrings = 0;
+       prog->knownstrings = NULL;
+
        prog->globaldefs = (ddef_t *)((qbyte *)prog->progs + prog->progs->ofs_globaldefs);
 
        // we need to expand the fielddefs list to include all the engine fields,
@@ -1341,7 +1329,7 @@ void PRVM_LoadProgs (const char * filename, int numrequiredfunc, char **required
        {
                pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
                pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
-               pr_fielddefs[progs->numfielddefs].s_name = PR_SetString(dpfields[i].string);
+               pr_fielddefs[progs->numfielddefs].s_name = PR_SetEngineString(dpfields[i].string);
                if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
                        progs->entityfields += 3;
                else
@@ -1496,7 +1484,8 @@ void PRVM_Fields_f (void)
 {
        int i, j, ednum, used, usedamount;
        int *counts;
-       char tempstring[5000], tempstring2[260], *name;
+       char tempstring[5000], tempstring2[260];
+       const char *name;
        prvm_edict_t *ed;
        ddef_t *d;
        int *v;
@@ -1740,6 +1729,24 @@ int PRVM_GetProgNr()
        return prog - prog_list;
 }
 
+void *_PRVM_Alloc(size_t buffersize, const char *filename, int fileline)
+{
+       return _Mem_Alloc(prog->progs_mempool, buffersize, filename, fileline);
+}
+
+void _PRVM_Free(void *buffer, const char *filename, int fileline)
+{
+       _Mem_Free(buffer, filename, fileline);
+}
+
+void _PRVM_FreeAll(const char *filename, int fileline)
+{
+       prog->progs = NULL;
+       prog->fielddefs = NULL;
+       prog->functions = NULL;
+       _Mem_EmptyPool(prog->progs_mempool, filename, fileline);
+}
+
 // LordHavoc: turned PRVM_EDICT_NUM into a #define for speed reasons
 prvm_edict_t *PRVM_EDICT_NUM_ERROR(int n, char *filename, int fileline)
 {
@@ -1794,3 +1801,107 @@ edict_t *PROG_TO_EDICT(int n)
 }
 */
 
+
+const char *PRVM_GetString(int num)
+{
+       if (num >= 0 && num < prog->stringssize)
+               return prog->strings + num;
+       else if (num < 0 && num >= -prog->numknownstrings)
+       {
+               num = -1 - num;
+               if (!prog->knownstrings[num])
+                       Host_Error("PRVM_GetString: attempt to get string that is already freed\n");
+               return prog->knownstrings[num];
+       }
+       else
+       {
+               Host_Error("PRVM_GetString: invalid string offset %i\n", num);
+               return "";
+       }
+}
+
+int PRVM_SetQCString(const char *s)
+{
+       int i;
+       if (!s)
+               return 0;
+       if (s >= prog->strings && s <= prog->strings + prog->stringssize)
+               return s - prog->strings;
+       for (i = 0;i < prog->numknownstrings;i++)
+               if (prog->knownstrings[i] == s)
+                       return -1 - i;
+       Host_Error("PRVM_SetQCString: unknown string\n");
+       return -1 - i;
+}
+
+int PRVM_SetEngineString(const char *s)
+{
+       int i;
+       if (!s)
+               return 0;
+       if (s >= prog->strings && s <= prog->strings + prog->stringssize)
+               Host_Error("PRVM_SetEngineString: s in prog->strings area\n");
+       for (i = 0;i < prog->numknownstrings;i++)
+               if (prog->knownstrings[i] == s)
+                       return -1 - i;
+       // new unknown engine string
+       if (developer.integer >= 3)
+               Con_Printf("new engine string %p\n", s);
+       for (i = 0;i < prog->numknownstrings;i++)
+               if (!prog->knownstrings[i])
+                       break;
+       if (i >= prog->numknownstrings)
+       {
+               if (i >= prog->maxknownstrings)
+               {
+                       const char **oldstrings = prog->knownstrings;
+                       prog->maxknownstrings += 128;
+                       prog->knownstrings = PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
+                       if (prog->numknownstrings)
+                               memcpy(prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
+               }
+               prog->numknownstrings++;
+       }
+       prog->knownstrings[i] = s;
+       return -1 - i;
+}
+
+char *PRVM_AllocString(int bufferlength)
+{
+       int i;
+       if (!bufferlength)
+               return 0;
+       for (i = 0;i < prog->numknownstrings;i++)
+               if (!prog->knownstrings[i])
+                       break;
+       if (i >= prog->numknownstrings)
+       {
+               if (i >= prog->maxknownstrings)
+               {
+                       const char **oldstrings = prog->knownstrings;
+                       prog->maxknownstrings += 128;
+                       prog->knownstrings = PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
+                       if (prog->numknownstrings)
+                               memcpy(prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
+               }
+               prog->numknownstrings++;
+       }
+       return (char *)(prog->knownstrings[i] = PRVM_Alloc(bufferlength));
+}
+
+void PRVM_FreeString(char *s)
+{
+       int i;
+       if (!s)
+               Host_Error("PRVM_FreeString: attempt to free a NULL string\n");
+       if (s >= prog->strings && s <= prog->strings + prog->stringssize)
+               Host_Error("PRVM_FreeString: attempt to free a constant string\n");
+       for (i = 0;i < prog->numknownstrings;i++)
+               if (prog->knownstrings[i] == s)
+                       break;
+       if (i == prog->numknownstrings)
+               Host_Error("PRVM_FreeString: attempt to free a non-existent or already freed string\n");
+       PRVM_Free((char *)prog->knownstrings[i]);
+       prog->knownstrings[i] = NULL;
+}
+
index 770be3f..5439f50 100644 (file)
--- a/server.h
+++ b/server.h
@@ -77,7 +77,7 @@ typedef struct
        // LordHavoc: precaches are now MAX_QPATH rather than a pointer
        // updated by SV_SoundIndex
        char sound_precache[MAX_SOUNDS][MAX_QPATH];
-       char *lightstyles[MAX_LIGHTSTYLES];
+       char lightstyles[MAX_LIGHTSTYLES][64];
        int num_edicts;
        int max_edicts;
        // small edict_t structures which just contain pointers
@@ -297,7 +297,7 @@ void SV_Init (void);
 
 void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count);
 void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate);
-void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation);
+void SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, float attenuation);
 
 void SV_ConnectClient (int clientnum, netconn_t *netconnection);
 void SV_DropClient (qboolean crash);
@@ -311,8 +311,8 @@ void SV_ReadClientMessage(void);
 // 0 = fail if not precached,
 // 1 = warn if not found and precache if possible
 // 2 = precache
-int SV_ModelIndex(char *s, int precachemode);
-int SV_SoundIndex(char *s, int precachemode);
+int SV_ModelIndex(const char *s, int precachemode);
+int SV_SoundIndex(const char *s, int precachemode);
 
 void SV_SetIdealPitch (void);
 
index 2e2f18a..c330e94 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -201,7 +201,7 @@ Larger attenuations will drop off.  (max 4 attenuation)
 
 ==================
 */
-void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation)
+void SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, float attenuation)
 {
        int sound_num, field_mask, i, ent;
 
@@ -1136,9 +1136,9 @@ void SV_UpdateToReliableMessages (void)
        int i, j;
        client_t *client;
        eval_t *val;
-       char *name;
-       char *model;
-       char *skin;
+       const char *name;
+       const char *model;
+       const char *skin;
 
 // check for changes to be sent over the reliable streams
        for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
@@ -1152,7 +1152,7 @@ void SV_UpdateToReliableMessages (void)
                        name = "";
                // always point the string back at host_client->name to keep it safe
                strlcpy (host_client->name, name, sizeof (host_client->name));
-               host_client->edict->v->netname = PR_SetString(host_client->name);
+               host_client->edict->v->netname = PR_SetEngineString(host_client->name);
                if (strcmp(host_client->old_name, host_client->name))
                {
                        if (host_client->spawned)
@@ -1184,7 +1184,7 @@ void SV_UpdateToReliableMessages (void)
                                model = "";
                        // always point the string back at host_client->name to keep it safe
                        strlcpy (host_client->playermodel, model, sizeof (host_client->playermodel));
-                       GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetString(host_client->playermodel);
+                       GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PR_SetEngineString(host_client->playermodel);
                }
 
                // NEXUIZ_PLAYERSKIN
@@ -1194,7 +1194,7 @@ void SV_UpdateToReliableMessages (void)
                                skin = "";
                        // always point the string back at host_client->name to keep it safe
                        strlcpy (host_client->playerskin, skin, sizeof (host_client->playerskin));
-                       GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetString(host_client->playerskin);
+                       GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PR_SetEngineString(host_client->playerskin);
                }
 
                // frags
@@ -1333,7 +1333,7 @@ SV_ModelIndex
 
 ================
 */
-int SV_ModelIndex(char *s, int precachemode)
+int SV_ModelIndex(const char *s, int precachemode)
 {
        int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
        char filename[MAX_QPATH];
@@ -1382,7 +1382,7 @@ SV_SoundIndex
 
 ================
 */
-int SV_SoundIndex(char *s, int precachemode)
+int SV_SoundIndex(const char *s, int precachemode)
 {
        int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
        char filename[MAX_QPATH];
@@ -1762,7 +1762,7 @@ void SV_SpawnServer (const char *server)
        ent = EDICT_NUM(0);
        memset (ent->v, 0, progs->entityfields * 4);
        ent->e->free = false;
-       ent->v->model = PR_SetString(sv.modelname);
+       ent->v->model = PR_SetEngineString(sv.modelname);
        ent->v->modelindex = 1;         // world model
        ent->v->solid = SOLID_BSP;
        ent->v->movetype = MOVETYPE_PUSH;
@@ -1772,7 +1772,7 @@ void SV_SpawnServer (const char *server)
        else
                pr_global_struct->deathmatch = deathmatch.integer;
 
-       pr_global_struct->mapname = PR_SetString(sv.name);
+       pr_global_struct->mapname = PR_SetEngineString(sv.name);
 
 // serverflags are for cross level information (sigils)
        pr_global_struct->serverflags = svs.serverflags;
index 24cc9a7..ff18ccf 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -776,7 +776,7 @@ void SV_ReadClientMessage(void)
                                Cmd_ExecuteString (s, src_client);
                        else if (SV_ParseClientCommandQC)
                        {
-                               G_INT(OFS_PARM0) = PR_SetString(s);
+                               G_INT(OFS_PARM0) = PR_SetEngineString(s);
                                pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
                                PR_ExecuteProgram ((func_t)(SV_ParseClientCommandQC - pr_functions), "QC function SV_ParseClientCommand is missing");
                        }
diff --git a/wad.c b/wad.c
index 35671d6..333e619 100644 (file)
--- a/wad.c
+++ b/wad.c
@@ -38,7 +38,7 @@ Space padding is so names can be printed nicely in tables.
 Can safely be performed in place.
 ==================
 */
-static void W_CleanupName (char *in, char *out)
+static void W_CleanupName (const char *in, char *out)
 {
        int             i;
        int             c;
@@ -58,7 +58,7 @@ static void W_CleanupName (char *in, char *out)
                out[i] = 0;
 }
 
-void *W_GetLumpName(char *name)
+void *W_GetLumpName(const char *name)
 {
        int i;
        lumpinfo_t *lump;
diff --git a/wad.h b/wad.h
index edef176..87289a7 100644 (file)
--- a/wad.h
+++ b/wad.h
@@ -69,7 +69,7 @@ extern        int                     wad_numlumps;
 extern lumpinfo_t      *wad_lumps;
 extern qbyte           *wad_base;
 
-void   *W_GetLumpName (char *name);
+void   *W_GetLumpName (const char *name);
 
 
 // LordHavoc: added alternate texture WAD2/WAD3 system for easier loading of HalfLife texture wads