+
+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])
+ PRVM_ERROR("PRVM_GetString: attempt to get string that is already freed\n");
+ return prog->knownstrings[num];
+ }
+ else
+ {
+ PRVM_ERROR("PRVM_GetString: invalid string offset %i\n", num);
+ return "";
+ }
+}
+
+int PRVM_SetEngineString(const char *s)
+{
+ int i;
+ if (!s)
+ return 0;
+ if (s >= prog->strings && s <= prog->strings + prog->stringssize)
+ PRVM_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 = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
+ if (!prog->knownstrings[i])
+ break;
+ if (i >= prog->numknownstrings)
+ {
+ if (i >= prog->maxknownstrings)
+ {
+ const char **oldstrings = prog->knownstrings;
+ const qbyte *oldstrings_freeable = prog->knownstrings_freeable;
+ prog->maxknownstrings += 128;
+ prog->knownstrings = PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
+ prog->knownstrings_freeable = PRVM_Alloc(prog->maxknownstrings * sizeof(qbyte));
+ if (prog->numknownstrings)
+ {
+ memcpy((char **)prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
+ memcpy((char **)prog->knownstrings_freeable, oldstrings_freeable, prog->numknownstrings * sizeof(qbyte));
+ }
+ }
+ prog->numknownstrings++;
+ }
+ prog->firstfreeknownstring = i + 1;
+ prog->knownstrings[i] = s;
+ return -1 - i;
+}
+
+int PRVM_AllocString(size_t bufferlength, char **pointer)
+{
+ int i;
+ if (!bufferlength)
+ return 0;
+ for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++)
+ if (!prog->knownstrings[i])
+ break;
+ if (i >= prog->numknownstrings)
+ {
+ if (i >= prog->maxknownstrings)
+ {
+ const char **oldstrings = prog->knownstrings;
+ const qbyte *oldstrings_freeable = prog->knownstrings_freeable;
+ prog->maxknownstrings += 128;
+ prog->knownstrings = PRVM_Alloc(prog->maxknownstrings * sizeof(char *));
+ prog->knownstrings_freeable = PRVM_Alloc(prog->maxknownstrings * sizeof(qbyte));
+ if (prog->numknownstrings)
+ {
+ memcpy((char **)prog->knownstrings, oldstrings, prog->numknownstrings * sizeof(char *));
+ memcpy((char **)prog->knownstrings_freeable, oldstrings_freeable, prog->numknownstrings * sizeof(qbyte));
+ }
+ }
+ prog->numknownstrings++;
+ }
+ prog->firstfreeknownstring = i + 1;
+ prog->knownstrings[i] = PRVM_Alloc(bufferlength);
+ prog->knownstrings_freeable[i] = true;
+ if (pointer)
+ *pointer = (char *)(prog->knownstrings[i]);
+ return -1 - i;
+}
+
+void PRVM_FreeString(int num)
+{
+ if (num == 0)
+ PRVM_ERROR("PRVM_FreeString: attempt to free a NULL string\n");
+ else if (num >= 0 && num < prog->stringssize)
+ PRVM_ERROR("PRVM_FreeString: attempt to free a constant string\n");
+ else if (num < 0 && num >= -prog->numknownstrings)
+ {
+ num = -1 - num;
+ if (!prog->knownstrings[num])
+ PRVM_ERROR("PRVM_FreeString: attempt to free a non-existent or already freed string\n");
+ if (!prog->knownstrings[num])
+ PRVM_ERROR("PRVM_FreeString: attempt to free a string owned by the engine\n");
+ PRVM_Free((char *)prog->knownstrings[num]);
+ prog->knownstrings[num] = NULL;
+ prog->knownstrings_freeable[num] = false;
+ prog->firstfreeknownstring = min(prog->firstfreeknownstring, num);
+ }
+ else
+ PRVM_ERROR("PRVM_FreeString: invalid string offset %i\n", num);
+}
+