shithub: qk1

Download patch

ref: 6c484cc08d3b071c6441adc61c87db32c2d471b1
parent: 1bf25dcef002723ee963d081cb90f57b4ae77e16
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Oct 11 20:58:06 EDT 2023

pr: better string and temp string handling

--- a/host_cmd.c
+++ b/host_cmd.c
@@ -384,7 +384,7 @@
 		if(strcmp(host_client->name, newName) != 0)
 			Con_Printf ("%s renamed to %s\n", host_client->name, newName);
 	strcpy(host_client->name, newName);
-	host_client->edict->v.netname = host_client->name - pr_strings;
+	host_client->edict->v.netname = PR_SetStr(host_client->name);
 	
 // send notification to all clients
 	
@@ -704,7 +704,7 @@
 		memset (&ent->v, 0, progs->entityfields * 4);
 		ent->v.colormap = NUM_FOR_EDICT(ent);
 		ent->v.team = (host_client->colors & 15) + 1;
-		ent->v.netname = host_client->name - pr_strings;
+		ent->v.netname = PR_SetStr(host_client->name);
 
 		// copy spawn parms out of the client_t
 
--- a/model.c
+++ b/model.c
@@ -46,9 +46,11 @@
 		return r;
 
 	Mod_LoadModel (mod, true);
-	
-	if (!mod->cache.data)
+
+	if (!mod->cache.data){
+		assert(0);
 		fatal ("Mod_Extradata: caching failed: %s", mod->name);
+	}
 	return mod->cache.data;
 }
 
@@ -269,7 +271,6 @@
 	if(buf == nil){
 		if(crash)
 			fatal("Mod_LoadModel: %r");
-		fprint(2, "loadstklmp failed: %s\n", mod->name);
 		return nil;
 	}
 
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -232,17 +232,15 @@
 			
 	if (!*check)
 		PR_RunError ("no precache: %s\n", m);
-		
-
-	e->v.model = m - pr_strings;
+	e->v.model = PR_SetStr(m);
 	e->v.modelindex = i; //SV_ModelIndex (m);
 
 	mod = sv.models[ (int)e->v.modelindex];  // Mod_ForName (m, true);
-	
-	if (mod)
-		SetMinMaxSize (e, mod->mins, mod->maxs, true);
-	else
+
+	if(!mod)
 		SetMinMaxSize (e, vec3_origin, vec3_origin, true);
+	else
+		SetMinMaxSize (e, mod->mins, mod->maxs, true);
 }
 
 /*
@@ -876,18 +874,18 @@
 	fprint(2, "%s", PF_VarString(0));
 }
 
-char	pr_string_temp[128];
-
 void PF_ftos (void)
 {
 	float	v;
+	char *s;
+
 	v = G_FLOAT(OFS_PARM0);
-	
+	s = PR_StrTmp();
 	if (v == (int)v)
-		sprint (pr_string_temp, "%d",(int)v);
+		sprint (s, "%d",(int)v);
 	else
-		sprint (pr_string_temp, "%5.1f",v);
-	G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
+		sprint (s, "%5.1f",v);
+	G_INT(OFS_RETURN) = PR_SetStr(s);
 }
 
 void PF_fabs (void)
@@ -899,8 +897,10 @@
 
 void PF_vtos (void)
 {
-	sprint (pr_string_temp, "'%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_string_temp - pr_strings;
+	char *s;
+	s = PR_StrTmp();
+	sprint (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_SetStr(s);
 }
 
 void PF_Spawn (void)
--- a/pr_edict.c
+++ b/pr_edict.c
@@ -42,14 +42,65 @@
 
 static gefv_cache	gefvCache[GEFV_CACHESIZE] = {{nil, ""}, {nil, ""}};
 
-/* amd64: kludge for assumed 32bit pointer arithmetic */
-char *PR_Str (int ofs)
+#define MAX_PRSTR 1024
+char **prstr;
+int num_prstr;
+int max_prstr;
+
+#define MAX_PRTEMPSTR 1024
+#define PRTEMPSTR_SIZE 1024
+char *prtempstr;
+int num_prtempstr;
+
+char *
+PR_StrTmp(void)
 {
-	if (((uintptr)pr_strings&0xffffffff)+ofs>>32)
-		return (char *)((uintptr)pr_strings+ofs&0xffffffff);
-	return pr_strings+ofs;
+	return &prtempstr[PRTEMPSTR_SIZE * (num_prtempstr++ & MAX_PRTEMPSTR)];
 }
 
+int
+PR_CopyStrTmp(char *s)
+{
+	char *t = PR_StrTmp();
+	snprint(t, PRTEMPSTR_SIZE, "%s", s);
+	return PR_SetStr(t);
+}
+
+int
+PR_StrSlot(void)
+{
+	if(num_prstr >= max_prstr){
+		max_prstr *= 2;
+		prstr = realloc(prstr, max_prstr*sizeof(*prstr));
+	}
+	return num_prstr++;
+}
+
+int
+PR_SetStr(char *s)
+{
+	int i;
+
+	for(i = 0; i < num_prstr; i++){
+		if(s == prstr[i])
+			return -1-i;
+	}
+	i = PR_StrSlot();
+	prstr[i] = s;
+	return -1-i;
+}
+
+char *
+PR_Str(int i)
+{
+	if(i >= 0)
+		return pr_strings+i;
+	if(i < 0 && i >= -num_prstr)
+		return prstr[-1-i];
+	Host_Error("PR_Str: invalid offset %d", i);
+	return "";
+}
+
 /*
 =================
 ED_ClearEdict
@@ -600,14 +651,15 @@
 ED_NewString
 =============
 */
-char *ED_NewString (char *string)
+string_t ED_NewString (char *string)
 {
 	char	*new, *new_p;
-	int		i,l;
+	int		i,l, slot;
 	
 	l = strlen(string) + 1;
 	new = Hunk_Alloc (l);
 	new_p = new;
+	slot = PR_StrSlot();
 
 	for (i=0 ; i< l ; i++)
 	{
@@ -622,8 +674,9 @@
 		else
 			*new_p++ = string[i];
 	}
+	prstr[slot] = new;
 	
-	return new;
+	return -1-slot;
 }
 
 
@@ -649,7 +702,7 @@
 	switch (key->type & ~DEF_SAVEGLOBAL)
 	{
 	case ev_string:
-		*(string_t *)d = ED_NewString (s) - pr_strings;
+		*(string_t *)d = ED_NewString (s);
 		break;
 		
 	case ev_float:
@@ -821,7 +874,6 @@
 	ent = nil;
 	inhibit = 0;
 	pr_global_struct->time = sv.time;
-	
 // parse ents
 	while (1)
 	{
@@ -870,7 +922,6 @@
 
 	// look for the spawn function
 		func = ED_FindFunction ( PR_Str(ent->v.classname) );
-
 		if (!func)
 		{
 			Con_Printf ("No spawn function for:\n");
@@ -899,6 +950,19 @@
 // flush the non-C variable lookup cache
 	for (i=0 ; i<GEFV_CACHESIZE ; i++)
 		gefvCache[i].field[0] = 0;
+
+	if(prstr == nil){
+		max_prstr = MAX_PRSTR;
+		prstr = malloc(max_prstr*sizeof(*prstr));
+	}
+	if(prtempstr == nil)
+		prtempstr = malloc(MAX_PRTEMPSTR*PRTEMPSTR_SIZE);
+
+	memset(prstr, 0, MAX_PRSTR*sizeof(*prstr));
+	memset(prtempstr, 0, MAX_PRTEMPSTR*PRTEMPSTR_SIZE);
+	num_prstr = 0;
+	num_prtempstr = 0;
+	PR_SetStr("");
 
 	initcrc();
 
--- a/progs.h
+++ b/progs.h
@@ -48,7 +48,10 @@
 void PR_ExecuteProgram (func_t fnum);
 void PR_LoadProgs (void);
 
-char	*PR_Str (int ofs);
+char *PR_StrTmp(void);
+int PR_CopyStrTmp(char *s);
+int PR_SetStr(char *s);
+char *PR_Str (int ofs);
 char *PR_UglyValueString (etype_t, eval_t *);
 
 void PR_Profile_f (void);
@@ -56,7 +59,7 @@
 edict_t *ED_Alloc (void);
 void ED_Free (edict_t *ed);
 
-char	*ED_NewString (char *string);
+string_t ED_NewString (char *string);
 // returns a copy of the string allocated from the server's string heap
 
 void ED_Print (edict_t *ed);
--- a/sv_main.c
+++ b/sv_main.c
@@ -1016,6 +1016,7 @@
 void SV_SpawnServer (char *server)
 {
 	edict_t		*ent;
+	static char dummy[8] = {0};
 	int			i;
 
 	// let's not have any servers with no name
@@ -1105,9 +1106,8 @@
 //
 	SV_ClearWorld ();
 	
-	sv.sound_precache[0] = pr_strings;
-
-	sv.model_precache[0] = pr_strings;
+	sv.sound_precache[0] = dummy;
+	sv.model_precache[0] = dummy;
 	sv.model_precache[1] = sv.modelname;
 	for (i=1 ; i<sv.worldmodel->numsubmodels ; i++)
 	{
@@ -1121,7 +1121,7 @@
 	ent = EDICT_NUM(0);
 	memset(&ent->v, 0, progs->entityfields * 4);
 	ent->free = false;
-	ent->v.model = sv.worldmodel->name - pr_strings;
+	ent->v.model = PR_SetStr(sv.worldmodel->name);
 	ent->v.modelindex = 1;		// world model
 	ent->v.solid = SOLID_BSP;
 	ent->v.movetype = MOVETYPE_PUSH;
@@ -1131,7 +1131,7 @@
 	else
 		pr_global_struct->deathmatch = deathmatch.value;
 
-	pr_global_struct->mapname = sv.name - pr_strings;
+	pr_global_struct->mapname = PR_SetStr(sv.name);
 
 // serverflags are for cross level information (sigils)
 	pr_global_struct->serverflags = svs.serverflags;