o all progs strings are now stored in progs memory

o  temporary strings automaticly get freed when the function they're
    created in (results of str + str and most strings returned from
	builtins). a way to keep temp strings will be provided later
 o	fix up qwaq to test the temp strings
This commit is contained in:
Bill Currie 2004-01-03 08:43:57 +00:00
parent 40b8974c33
commit bd561fafc3
6 changed files with 169 additions and 33 deletions

View file

@ -156,7 +156,7 @@ qboolean PR_EdictValid (progs_t *pr, int e);
#define R_FUNCTION(p) R_var (p, func)
#define R_POINTER(p) R_var (p, pointer)
#define RETURN_STRING(p, s) (R_STRING (p) = PR_SetString((p), s))
#define RETURN_STRING(p, s) (R_STRING (p) = PR_SetTempString((p), s))
#define RETURN_EDICT(p, e) (R_STRING (p) = EDICT_TO_PROG(p, e))
#define RETURN_POINTER(pr,p) (R_POINTER (pr) = POINTER_TO_PROG (pr, p))
#define RETURN_VECTOR(p, v) (VectorCopy (v, R_VECTOR (p)))
@ -221,7 +221,12 @@ int PR_InitRuntime (progs_t *pr);
qboolean PR_StringValid (progs_t *pr, int num);
const char *PR_GetString(progs_t *pr, int num);
struct dstring_s *PR_GetDString(progs_t *pr, int num);
int PR_SetString(progs_t *pr, const char *s);
int PR_SetTempString(progs_t *pr, const char *s);
int PR_NewString (progs_t *pr);
void PR_FreeString (progs_t *pr, int str);
void PR_FreeTempStrings (progs_t *pr);
void PR_GarbageCollect (progs_t *pr);
//
@ -282,14 +287,9 @@ void PR_Cmds_Init (progs_t *pr);
typedef struct {
int s;
dfunction_t *f;
struct strref_s *tstr;
} prstack_t;
typedef struct strref_s {
struct strref_s *next;
char *string;
int count;
} strref_t;
struct progs_s {
const char *progs_name;
dprograms_t *progs;
@ -308,12 +308,14 @@ struct progs_s {
pr_load_func_t **load_funcs;
// garbage collected strings
strref_t *static_strings;
strref_t **dynamic_strings;
strref_t *free_string_refs;
struct dstring_mem_s *ds_mem;
struct strref_s *static_strings;
struct strref_s **dynamic_strings;
struct strref_s *free_string_refs;
unsigned dyn_str_size;
struct hashtab_s *strref_hash;
int num_strings;
struct strref_s *pr_xtstr;
dfunction_t *pr_functions;
char *pr_strings;

View file

@ -137,6 +137,7 @@ PR_EnterFunction (progs_t * pr, dfunction_t *f)
pr->pr_xfunction = f;
pr->pr_xstatement = f->first_statement - 1; // offset the st++
pr->pr_xtstr = 0;
return;
}
@ -158,10 +159,14 @@ PR_LeaveFunction (progs_t * pr)
&pr->localstack[pr->localstack_used],
sizeof (pr_type_t) * c);
if (pr->pr_xtstr)
PR_FreeTempStrings (pr);
// up stack
pr->pr_depth--;
pr->pr_xfunction = pr->pr_stack[pr->pr_depth].f;
pr->pr_xstatement = pr->pr_stack[pr->pr_depth].s;
pr->pr_xtstr = pr->pr_stack[pr->pr_depth].tstr;
}
#define OPA (*op_a)
@ -280,7 +285,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
char *c = Hunk_TempAlloc (size);
strcpy (c, a);
strcpy (c + lena, b);
OPC.string_var = PR_SetString (pr, c);
OPC.string_var = PR_SetTempString (pr, c);
}
break;
case OP_SUB_F:

View file

@ -99,16 +99,14 @@ free_progs_mem (progs_t *pr, void *mem)
void
PR_LoadProgsFile (progs_t * pr, QFile *file, int size, int edicts, int zone)
{
unsigned int i;
unsigned i;
int mem_size;
dprograms_t progs;
pr->progs = 0;
if (Qread (file, &progs, sizeof (progs)) != sizeof (progs))
PR_Error (pr, "error reading header");
pr->progs_size = size;
Sys_DPrintf ("Programs occupy %iK.\n", size / 1024);
// store prog crc
pr->crc = CRC_Block ((byte*)&progs, sizeof (progs));
@ -137,6 +135,7 @@ PR_LoadProgsFile (progs_t * pr, QFile *file, int size, int edicts, int zone)
// size of progs themselves
pr->progs_size = size;
Sys_DPrintf ("Programs occupy %iK.\n", size / 1024);
// round off to next highest whole word address (esp for Alpha)
// this ensures that pointers in the engine data area are always
// properly aligned
@ -174,10 +173,11 @@ PR_LoadProgsFile (progs_t * pr, QFile *file, int size, int edicts, int zone)
PR_Resources_Clear (pr);
if (pr->progs)
pr->free_progs_mem (pr, pr->progs);
pr->progs = pr->allocate_progs_mem (pr, pr->progs_size + pr->zone_size
+ pr->pr_edictareasize);
mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize;
pr->progs = pr->allocate_progs_mem (pr, mem_size + 1);
if (!pr->progs)
return;
((byte *) pr->progs)[mem_size] = 0;
memcpy (pr->progs, &progs, sizeof (progs));
Qread (file, pr->progs + 1, size - sizeof (progs));
@ -194,7 +194,7 @@ PR_LoadProgsFile (progs_t * pr, QFile *file, int size, int edicts, int zone)
pr->pr_functions =
(dfunction_t *) ((byte *) pr->progs + pr->progs->ofs_functions);
pr->pr_strings = (char *) pr->progs + pr->progs->ofs_strings;
pr->pr_stringsize = pr->progs->numstrings;
pr->pr_stringsize = (char *) pr->zone + pr->zone_size - (char *) pr->progs;
pr->pr_globaldefs =
(ddef_t *) ((byte *) pr->progs + pr->progs->ofs_globaldefs);
pr->pr_fielddefs =

View file

@ -41,9 +41,37 @@ static __attribute__ ((unused)) const char rcsid[] =
#include <stdarg.h>
#include <stdlib.h>
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/progs.h"
typedef struct strref_s {
struct strref_s *next;
char *string;
dstring_t *dstring;
int count;
} strref_t;
static void *
pr_strings_alloc (void *_pr, size_t size)
{
progs_t *pr = (progs_t *) _pr;
return PR_Zone_Malloc (pr, size);
}
static void
pr_strings_free (void *_pr, void *ptr)
{
progs_t *pr = (progs_t *) _pr;
PR_Zone_Free (pr, ptr);
}
static void *
pr_strings_realloc (void *_pr, void *ptr, size_t size)
{
progs_t *pr = (progs_t *) _pr;
return PR_Zone_Realloc (pr, ptr, size);
}
static strref_t *
new_string_ref (progs_t *pr)
@ -74,6 +102,7 @@ static void
free_string_ref (progs_t *pr, strref_t *sr)
{
sr->string = 0;
sr->dstring = 0;
sr->next = pr->free_string_refs;
pr->free_string_refs = sr;
}
@ -110,7 +139,7 @@ strref_free (void *_sr, void *_pr)
// 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 (sr->string);
PR_Zone_Free (pr, sr->string);
free_string_ref (pr, sr);
}
}
@ -126,6 +155,14 @@ PR_LoadStrings (progs_t *pr)
count++;
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);
} else {
@ -138,7 +175,7 @@ PR_LoadStrings (progs_t *pr)
if (pr->static_strings)
free (pr->static_strings);
pr->static_strings = calloc (count, sizeof (strref_t));
pr->static_strings = malloc (count * sizeof (strref_t));
count = 0;
str = pr->pr_strings;
while (str < end) {
@ -198,8 +235,8 @@ PR_GarbageCollect (progs_t *pr)
}
}
static inline char *
get_string (progs_t *pr, int num)
static inline strref_t *
get_strref (progs_t *pr, int num)
{
if (num < 0) {
unsigned int row = ~num / 1024;
@ -208,7 +245,22 @@ get_string (progs_t *pr, int num)
if (row >= pr->dyn_str_size)
return 0;
return pr->dynamic_strings[row][num].string;
return &pr->dynamic_strings[row][num];
} else {
return 0;
}
}
static inline const char *
get_string (progs_t *pr, int num)
{
if (num < 0) {
strref_t *ref = get_strref (pr, num);
if (!ref)
return 0;
if (ref->dstring)
return ref->dstring->str;
return ref->string;
} else {
if (num >= pr->pr_stringsize)
return 0;
@ -225,12 +277,33 @@ PR_StringValid (progs_t *pr, int num)
const char *
PR_GetString (progs_t *pr, int num)
{
char *str;
const char *str;
str = get_string (pr, num);
if (str)
return str;
PR_RunError (pr, "Invalid string offset %u", num);
PR_RunError (pr, "Invalid string offset %d", num);
}
dstring_t *
PR_GetDString (progs_t *pr, int num)
{
strref_t *ref = get_strref (pr, num);
if (ref) {
if (ref->dstring)
return ref->dstring;
PR_RunError (pr, "not a dstring: %d", num);
}
PR_RunError (pr, "Invalid string offset: %d", num);
}
static inline char *
pr_strdup (progs_t *pr, const char *s)
{
size_t len = strlen (s) + 1;
char *new = PR_Zone_Malloc (pr, len);
strcpy (new, s);
return new;
}
int
@ -240,9 +313,59 @@ PR_SetString (progs_t *pr, const char *s)
if (!sr) {
sr = new_string_ref (pr);
sr->string = strdup(s);
sr->string = pr_strdup(pr, s);
sr->count = 0;
Hash_Add (pr->strref_hash, sr);
}
return string_index (pr, sr);
}
int
PR_SetTempString (progs_t *pr, const char *s)
{
strref_t *sr;
sr = new_string_ref (pr);
sr->string = pr_strdup(pr, s);
sr->count = 0;
sr->next = pr->pr_xtstr;
pr->pr_xtstr = sr;
return string_index (pr, sr);
}
int
PR_NewString (progs_t *pr)
{
strref_t *sr = new_string_ref (pr);
sr->dstring = _dstring_newstr (pr->ds_mem);
return string_index (pr, sr);
}
void
PR_FreeString (progs_t *pr, int str)
{
strref_t *sr = get_strref (pr, str);
if (sr) {
if (sr->dstring)
dstring_delete (sr->dstring);
else
PR_Zone_Free (pr, sr->string);
free_string_ref (pr, sr);
return;
}
PR_RunError (pr, "attempt to free invalid string %d", str);
}
void
PR_FreeTempStrings (progs_t *pr)
{
strref_t *sr, *t;
for (sr = pr->pr_xtstr; sr; sr = t) {
t = sr->next;
PR_Zone_Free (pr, sr->string);
free_string_ref (pr, sr);
}
pr->pr_xtstr = 0;
}

View file

@ -140,13 +140,8 @@ load_progs (const char *name)
pr.progs_name = name;
PR_LoadProgsFile (&pr, file, size, 1, 1024 * 1024);
Qclose (file);
if (!PR_ResolveGlobals (&pr))
if (!PR_RunLoadFuncs (&pr))
PR_Error (&pr, "unable to load %s", pr.progs_name);
PR_LoadStrings (&pr);
PR_LoadDebug (&pr);
PR_Check_Opcodes (&pr);
PR_RelocateBuiltins (&pr);
PR_InitRuntime (&pr);
return 1;
}

View file

@ -1,3 +1,13 @@
void () test_str =
{
local string a,b,c,d;
a = "testing ";
b = "temp ";
c = "strings ";
d = "\n";
print (a + b + c + d);
};
integer (integer argc, string []argv) main =
{
local integer i;
@ -35,5 +45,6 @@ integer (integer argc, string []argv) main =
print ("Object instances do not repond to `run:with:me:'\n");
} else
print ("did not find selector for `run:with:me:'\n");
test_str ();
return 0;
};