From 2a36c74120c4752582b1dc85a75f0a50a6e1ee85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Nov 2004 09:40:00 +0000 Subject: [PATCH] add dynamic (freeable but unchangeable) strings This is an imperfect revision of history. --- libs/gamecode/builtins/pr_cmds.c | 6 +- libs/gamecode/engine/pr_strings.c | 144 +++++++++++++++++++++--------- libs/ruamoko/rua_string.c | 44 ++++++++- qw/source/sv_pr_qwe.c | 9 +- 4 files changed, 150 insertions(+), 53 deletions(-) diff --git a/libs/gamecode/builtins/pr_cmds.c b/libs/gamecode/builtins/pr_cmds.c index 7e5524f5e..f44e4b570 100644 --- a/libs/gamecode/builtins/pr_cmds.c +++ b/libs/gamecode/builtins/pr_cmds.c @@ -583,9 +583,9 @@ PF_sprintf (progs_t *pr) dstring_t *dstr; int str; - str = PR_NewString (pr); - dstr = PR_GetDString (pr, str); - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); + str = PR_NewMutableString (pr); + dstr = PR_GetMutableString (pr, str); + PR_Sprintf (pr, dstr, "PF_sprintf", fmt, count, args); PR_MakeTempString (pr, str); R_STRING (pr) = str; } diff --git a/libs/gamecode/engine/pr_strings.c b/libs/gamecode/engine/pr_strings.c index 9b84b08cd..727512e69 100644 --- a/libs/gamecode/engine/pr_strings.c +++ b/libs/gamecode/engine/pr_strings.c @@ -46,11 +46,22 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/hash.h" #include "QF/progs.h" +typedef enum { + str_static, + str_dynamic, + str_mutable, + str_temp, + str_return, +} str_e; + struct strref_s { strref_t *next; - char *string; - dstring_t *dstring; - int count; + strref_t **prev; + str_e type; + union { + char *string; + dstring_t *dstring; + } s; }; // format adjustments @@ -126,8 +137,8 @@ new_string_ref (progs_t *pr) static void free_string_ref (progs_t *pr, strref_t *sr) { - sr->string = 0; - sr->dstring = 0; + if (sr->prev) + *sr->prev = sr->next; sr->next = pr->free_string_refs; pr->free_string_refs = sr; } @@ -139,9 +150,9 @@ string_index (progs_t *pr, strref_t *sr) unsigned int i; if (o >= 0 && o < pr->num_strings) - return sr->string - pr->pr_strings; + return sr->s.string - pr->pr_strings; for (i = 0; i < pr->dyn_str_size; i++) { - int d = sr - pr->dynamic_strings[i]; + int d = sr - pr->string_map[i]; if (d >= 0 && d < 1024) return ~(i * 1024 + d); } @@ -153,7 +164,8 @@ strref_get_key (void *_sr, void *notused) { strref_t *sr = (strref_t*)_sr; - return sr->string; + // only static strings will ever be in the hash table + return sr->s.string; } static void @@ -244,9 +256,16 @@ get_string (progs_t *pr, int num) strref_t *ref = get_strref (pr, num); if (!ref) return 0; - if (ref->dstring) - return ref->dstring->str; - return ref->string; + switch (ref->type) { + case str_static: + case str_temp: + case str_dynamic: + case str_return: + return ref->s.string; + case str_mutable: + return ref->s.dstring->str; + } + PR_Error (pr, "internal string error"); } else { if (num >= pr->pr_stringsize) return 0; @@ -272,12 +291,12 @@ PR_GetString (progs_t *pr, int num) } dstring_t * -PR_GetDString (progs_t *pr, int num) +PR_GetMutableString (progs_t *pr, int num) { strref_t *ref = get_strref (pr, num); if (ref) { - if (ref->dstring) - return ref->dstring; + if (ref->type == str_mutable) + return ref->s.dstring; PR_RunError (pr, "not a dstring: %d", num); } PR_RunError (pr, "Invalid string offset: %d", num); @@ -298,8 +317,7 @@ pr_strfree (progs_t *pr, char *s) static inline char * pr_strdup (progs_t *pr, const char *s) { - size_t len = strlen (s) + 1; - char *new = PR_Zone_Malloc (pr, len); + char *new = pr_stralloc (pr, strlen (s)); strcpy (new, s); return new; } @@ -315,8 +333,8 @@ PR_SetString (progs_t *pr, const char *s) if (!sr) { sr = new_string_ref (pr); - sr->string = pr_strdup(pr, s); - sr->count = 0; + sr->type = str_static; + sr->s.string = pr_strdup(pr, s); Hash_Add (pr->strref_hash, sr); } return string_index (pr, sr); @@ -346,13 +364,14 @@ PR_SetReturnString (progs_t *pr, const char *s) } if ((sr = pr->return_strings[pr->rs_slot])) { - if (sr->string) - PR_Zone_Free (pr, sr->string); + if (sr->type != str_return) + PR_Error (pr, "internal string error"); + pr_strfree (pr, sr->s.string); } else { sr = new_string_ref (pr); } - sr->string = pr_strdup(pr, s); - sr->count = 0; + sr->type = str_return; + sr->s.string = pr_strdup(pr, s); pr->return_strings[pr->rs_slot++] = sr; pr->rs_slot %= PR_RS_SLOTS; @@ -396,11 +415,28 @@ PR_SetTempString (progs_t *pr, const char *s) if (!s) return PR_SetString (pr, ""); + if ((sr = Hash_Find (pr->strref_hash, s))) { + return string_index (pr, sr); + } + + return pr_settempstring (pr, pr_strdup (pr, s)); +} + +int +PR_SetDynamicString (progs_t *pr, const char *s) +{ + strref_t *sr; + + if (!s) + return PR_SetString (pr, ""); + + if ((sr = Hash_Find (pr->strref_hash, s))) { + return string_index (pr, sr); + } + sr = new_string_ref (pr); - sr->string = pr_strdup(pr, s); - sr->count = 0; - sr->next = pr->pr_xtstr; - pr->pr_xtstr = sr; + sr->type = str_dynamic; + sr->s.string = pr_strdup (pr, s); return string_index (pr, sr); } @@ -411,23 +447,26 @@ PR_MakeTempString (progs_t *pr, int str) if (!sr) PR_RunError (pr, "invalid string %d", str); - if (sr->dstring) { - if (sr->dstring->str) - sr->string = sr->dstring->str; - PR_Zone_Free (pr, sr->dstring); + if (sr->type != str_mutable) + PR_RunError (pr, "not a dstring: %d", str); + if (sr->s.dstring->str) { + sr->s.string = dstring_freeze (sr->s.dstring); + } else { + dstring_delete (sr->s.dstring); } - if (!sr->string) - sr->string = pr_strdup (pr, ""); - sr->count = 0; + if (!sr->s.string) + sr->s.string = pr_strdup (pr, ""); + sr->type = str_temp; sr->next = pr->pr_xtstr; pr->pr_xtstr = sr; } int -PR_NewString (progs_t *pr) +PR_NewMutableString (progs_t *pr) { strref_t *sr = new_string_ref (pr); - sr->dstring = _dstring_newstr (pr->ds_mem); + sr->type = str_mutable; + sr->s.dstring = _dstring_newstr (pr->ds_mem); return string_index (pr, sr); } @@ -437,14 +476,25 @@ 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); + switch (sr->type) { + case str_static: + case str_temp: + return; + case str_mutable: + dstring_delete (sr->s.dstring); + break; + case str_dynamic: + pr_strfree (pr, sr->s.string); + break; + case str_return: + default: + PR_Error (pr, "internal string error"); + } free_string_ref (pr, sr); return; } - PR_RunError (pr, "attempt to free invalid string %d", str); + if (!get_string (pr, str)) + PR_RunError (pr, "attempt to free invalid string %d", str); } void @@ -454,7 +504,9 @@ PR_FreeTempStrings (progs_t *pr) for (sr = pr->pr_xtstr; sr; sr = t) { t = sr->next; - PR_Zone_Free (pr, sr->string); + if (sr->type != str_temp) + PR_Error (pr, "internal string error"); + pr_strfree (pr, sr->s.string); free_string_ref (pr, sr); } pr->pr_xtstr = 0; @@ -512,14 +564,18 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting) PRINT (string); break; case 'i': - dstring_appendstr (tmp, "ld"); + dstring_appendstr (tmp, "d"); + PRINT (integer); + break; + case 'x': + dstring_appendstr (tmp, "x"); PRINT (integer); break; case 'u': if (current->flags & FMT_HEX) - dstring_appendstr (tmp, "lx"); + dstring_appendstr (tmp, "x"); else - dstring_appendstr (tmp, "lu"); + dstring_appendstr (tmp, "u"); PRINT (uinteger); break; case 'f': diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index cdf585a06..1caa34ee4 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -50,7 +50,7 @@ static __attribute__ ((unused)) const char rcsid[] = static void bi_str_new (progs_t *pr) { - R_STRING (pr) = PR_NewString (pr); + R_STRING (pr) = PR_NewMutableString (pr); } static void @@ -78,11 +78,53 @@ bi_str_clear (progs_t *pr) R_STRING (pr) = P_STRING (pr, 0); } +static void +bi_str_mid (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + int pos = P_INT (pr, 1); + int end = P_INT (pr, 2); + int size = strlen (str); + char *temp; + + if (pr->pr_argc == 2) + end = size; + + R_STRING (pr) = 0; + if (pos < 0) + pos += size; + if (end < 0) + end += size; + if (end > size) + end = size; + if (pos < 0 || pos >= size || end <= pos) + return; + temp = alloca (end - pos + 1); + strncpy (temp, str + pos, end - pos); + temp[end - pos] = 0; + RETURN_STRING (pr, temp); +} + +static void +bi_str_str (progs_t *pr) +{ + const char *haystack = P_GSTRING (pr, 0); + const char *needle = P_GSTRING (pr, 1); + char *res = strstr (haystack, needle); + + R_STRING (pr) = 0; + if (res) + R_STRING (pr) = res - pr->pr_strings; +} + static builtin_t builtins[] = { {"str_new", bi_str_new, -1}, {"str_free", bi_str_free, -1}, {"str_copy", bi_str_copy, -1}, {"str_clear", bi_str_clear, -1}, + {"str_mid|*i", bi_str_mid, -1}, + {"str_mid|*ii", bi_str_mid, -1}, + {"str_str", bi_str_str, -1}, {0} }; diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index 174bcd4a8..b7ddaadf2 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -178,7 +178,7 @@ PF_substr (progs_t * pr) tmp = Hunk_TempAlloc (len); strncpy (tmp, s, len - 1); - tmp[len] = 0; + tmp[len - 1] = 0; RETURN_STRING (pr, tmp); } @@ -238,8 +238,7 @@ PF_str2short (progs_t * pr) PF_newstr string newstr (string str [, float size]) - - ignores size (there for compatability with qwe) + The new string will be at least as big as size, if given. */ static void PF_newstr (progs_t * pr) @@ -250,8 +249,8 @@ PF_newstr (progs_t * pr) s = P_GSTRING (pr, 0); - i = PR_NewString (pr); - dstr = PR_GetDString (pr, i); + i = PR_NewMutableString (pr); + dstr = PR_GetMutableString (pr, i); dstring_copystr (dstr, s);