foxygit / doom Log in
commit 5914e16076339ef487094dba8be67eed21b0a811
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sat Oct 18 20:33:30 2014 -0400
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sat Oct 18 20:33:30 2014 -0400

    dehacked: Allow override of string replacements.

    If loading two dehacked patches and both replace the same string,
    the second replacement should override the first. Change the API
    function DEH_AddStringReplacement so that the from_text and to_text
    are implicitly duplicated, and we can free to_text and replace
    it later if we subsequently change it to something else.
---
 src/deh_str.c           | 65 +++++++++++++++++++++++++++++++++++++------------
 src/deh_text.c          | 25 ++++++++-----------
 src/doom/deh_bexstr.c   |  2 +-
 src/heretic/deh_htext.c | 10 +++-----
 4 files changed, 64 insertions(+), 38 deletions(-)

diff --git a/src/deh_str.c b/src/deh_str.c
index ecd00a6b..1422b759 100644
--- a/src/deh_str.c
+++ b/src/deh_str.c
@@ -52,17 +52,13 @@ static unsigned int strhash(char *s)
     return h;
 }

-// Look up a string to see if it has been replaced with something else
-// This will be used throughout the program to substitute text
-
-char *DEH_String(char *s)
+static deh_substitution_t *SubstitutionForString(char *s)
 {
     int entry;

     // Fallback if we have not initialized the hash table yet
-
     if (hash_table_length < 0)
-	return s;
+	return NULL;

     entry = strhash(s) % hash_table_length;

@@ -71,16 +67,33 @@ char *DEH_String(char *s)
         if (!strcmp(hash_table[entry]->from_text, s))
         {
             // substitution found!
-
-            return hash_table[entry]->to_text;
+            return hash_table[entry];
         }

         entry = (entry + 1) % hash_table_length;
     }

     // no substitution found
+    return NULL;
+}

-    return s;
+// Look up a string to see if it has been replaced with something else
+// This will be used throughout the program to substitute text
+
+char *DEH_String(char *s)
+{
+    deh_substitution_t *subst;
+
+    subst = SubstitutionForString(s);
+
+    if (subst != NULL)
+    {
+        return subst->to_text;
+    }
+    else
+    {
+        return s;
+    }
 }

 static void InitHashTable(void)
@@ -139,9 +152,8 @@ static void DEH_AddToHashtable(deh_substitution_t *sub)
     {
         IncreaseHashtable();
     }
-
+
     // find where to insert it
-
     entry = strhash(sub->from_text) % hash_table_length;

     while (hash_table[entry] != NULL)
@@ -156,20 +168,41 @@ static void DEH_AddToHashtable(deh_substitution_t *sub)
 void DEH_AddStringReplacement(char *from_text, char *to_text)
 {
     deh_substitution_t *sub;
+    size_t len;

     // Initialize the hash table if this is the first time
-
     if (hash_table_length < 0)
     {
         InitHashTable();
     }

-    sub = Z_Malloc(sizeof(*sub), PU_STATIC, 0);
+    // Check to see if there is an existing substitution already in place.
+    sub = SubstitutionForString(from_text);

-    sub->from_text = from_text;
-    sub->to_text = to_text;
+    if (sub != NULL)
+    {
+        Z_Free(sub->to_text);
+
+        len = strlen(to_text) + 1;
+        sub->to_text = Z_Malloc(len, PU_STATIC, NULL);
+        memcpy(sub->to_text, to_text, len);
+    }
+    else
+    {
+        // We need to allocate a new substitution.
+        sub = Z_Malloc(sizeof(*sub), PU_STATIC, 0);

-    DEH_AddToHashtable(sub);
+        // We need to create our own duplicates of the provided strings.
+        len = strlen(from_text) + 1;
+        sub->from_text = Z_Malloc(len, PU_STATIC, NULL);
+        memcpy(sub->from_text, from_text, len);
+
+        len = strlen(to_text) + 1;
+        sub->to_text = Z_Malloc(len, PU_STATIC, NULL);
+        memcpy(sub->to_text, to_text, len);
+
+        DEH_AddToHashtable(sub);
+    }
 }

 typedef enum
diff --git a/src/deh_text.c b/src/deh_text.c
index 1fc91185..9e621b43 100644
--- a/src/deh_text.c
+++ b/src/deh_text.c
@@ -16,6 +16,7 @@
 //

 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>

 #include "doomtype.h"
@@ -51,7 +52,7 @@ static void *DEH_TextStart(deh_context_t *context, char *line)
     char *from_text, *to_text;
     int fromlen, tolen;
     int i;
-
+
     if (sscanf(line, "Text %i %i", &fromlen, &tolen) != 2)
     {
         DEH_Warning(context, "Parse error on section start");
@@ -68,36 +69,30 @@ static void *DEH_TextStart(deh_context_t *context, char *line)
         return NULL;
     }

-    from_text = Z_Malloc(fromlen + 1, PU_STATIC, NULL);
-    to_text = Z_Malloc(tolen + 1, PU_STATIC, NULL);
+    from_text = malloc(fromlen + 1);
+    to_text = malloc(tolen + 1);

     // read in the "from" text

     for (i=0; i<fromlen; ++i)
     {
-        int c;
-
-        c = DEH_GetChar(context);
-
-        from_text[i] = c;
+        from_text[i] = DEH_GetChar(context);
     }
-
     from_text[fromlen] = '\0';

     // read in the "to" text

     for (i=0; i<tolen; ++i)
     {
-        int c;
-
-        c = DEH_GetChar(context);
-
-        to_text[i] = c;
+        to_text[i] = DEH_GetChar(context);
     }
     to_text[tolen] = '\0';

     DEH_AddStringReplacement(from_text, to_text);
-
+
+    free(from_text);
+    free(to_text);
+
     return NULL;
 }

diff --git a/src/doom/deh_bexstr.c b/src/doom/deh_bexstr.c
index e29b71dc..ac3ab651 100644
--- a/src/doom/deh_bexstr.c
+++ b/src/doom/deh_bexstr.c
@@ -360,7 +360,7 @@ static void DEH_BEXStrParseLine(deh_context_t *context, char *line, void *tag)
     {
 	if (!strcmp(bex_stringtable[i].macro, variable_name))
 	{
-	    DEH_AddStringReplacement(bex_stringtable[i].string, strdup(value));
+	    DEH_AddStringReplacement(bex_stringtable[i].string, value);
 	}
     }
 }
diff --git a/src/heretic/deh_htext.c b/src/heretic/deh_htext.c
index 55f32872..fe0dc663 100644
--- a/src/heretic/deh_htext.c
+++ b/src/heretic/deh_htext.c
@@ -16,6 +16,7 @@
 //

 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>

 #include "doomtype.h"
@@ -776,7 +777,7 @@ static void *DEH_TextStart(deh_context_t *context, char *line)
         return NULL;
     }

-    repl_text = Z_Malloc(repl_len + 1, PU_STATIC, NULL);
+    repl_text = malloc(repl_len + 1);

     // read in the "to" text

@@ -819,13 +820,10 @@ static void *DEH_TextStart(deh_context_t *context, char *line)
         // Success.

         DEH_AddStringReplacement(orig_text, repl_text);
-
-        return NULL;
     }

-    // Failure.
-
-    Z_Free(repl_text);
+    // We must always free the replacement text.
+    free(repl_text);

     return NULL;
 }