diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 64265b2c..50aa95e2 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -1176,9 +1176,7 @@ static void PF_cs_getstati(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void PF_cs_getstats(progfuncs_t *prinst, struct globalvars_s *pr_globals) { int stnum = G_FLOAT(OFS_PARM0); - char *out; - - out = PF_TempStr(prinst); + char out[8]; //the network protocol byteswaps @@ -1188,7 +1186,7 @@ static void PF_cs_getstats(progfuncs_t *prinst, struct globalvars_s *pr_globals) ((unsigned int*)out)[3] = LittleLong(cl.stats[0][stnum+3]); ((unsigned int*)out)[4] = 0; //make sure it's null terminated - RETURN_SSTRING(out); + RETURN_TSTRING(out); } static void PF_cs_SetOrigin(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1555,10 +1553,9 @@ static void PF_ReadFloat(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void PF_ReadString(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *str = PF_TempStr(prinst); char *read = MSG_ReadString(); - Q_strncpyz(str, read, MAXTEMPBUFFERLEN); + RETURN_TSTRING(read); } static void PF_ReadAngle(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1854,7 +1851,7 @@ static void PF_cs_serverkey (progfuncs_t *prinst, struct globalvars_s *pr_global } if (*ret) - RETURN_SSTRING(ret); + RETURN_TSTRING(ret); else G_INT(OFS_RETURN) = 0; } @@ -1862,6 +1859,7 @@ static void PF_cs_serverkey (progfuncs_t *prinst, struct globalvars_s *pr_global //string(float pnum, string keyname) static void PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars_s *pr_globals) { + char buffer[64]; char *ret; int pnum = G_FLOAT(OFS_PARM0); char *keyname = PR_GetStringOfs(prinst, OFS_PARM1); @@ -1886,24 +1884,24 @@ static void PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars_s *pr_glo { CheckSendPings(); - ret = PF_TempStr(prinst); + ret = buffer; sprintf(ret, "%i", cl.players[pnum].ping); } else if (!strcmp(keyname, "frags")) { - ret = PF_TempStr(prinst); + ret = buffer; sprintf(ret, "%i", cl.players[pnum].frags); } else if (!strcmp(keyname, "pl")) //packet loss { CheckSendPings(); - ret = PF_TempStr(prinst); + ret = buffer; sprintf(ret, "%i", cl.players[pnum].pl); } else if (!strcmp(keyname, "entertime")) //packet loss { - ret = PF_TempStr(prinst); + ret = buffer; sprintf(ret, "%i", (int)cl.players[pnum].entertime); } else @@ -1911,7 +1909,7 @@ static void PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars_s *pr_glo ret = Info_ValueForKey(cl.players[pnum].userinfo, keyname); } if (*ret) - RETURN_SSTRING(ret); + RETURN_TSTRING(ret); else G_INT(OFS_RETURN) = 0; } @@ -3770,15 +3768,11 @@ qboolean CSQC_MouseMove(float xdelta, float ydelta) qboolean CSQC_ConsoleCommand(char *cmd) { void *pr_globals; - char *str; if (!csqcprogs || !csqcg.console_command) return false; - str = PF_TempStr(csqcprogs); - Q_strncpyz(str, cmd, MAXTEMPBUFFERLEN); - pr_globals = PR_globals(csqcprogs, PR_CURRENT); - (((string_t *)pr_globals)[OFS_PARM0] = PR_SetString(csqcprogs, str)); + (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd)); PR_ExecuteProgram (csqcprogs, csqcg.console_command); return G_FLOAT(OFS_RETURN); @@ -3787,15 +3781,11 @@ qboolean CSQC_ConsoleCommand(char *cmd) qboolean CSQC_StuffCmd(char *cmd) { void *pr_globals; - char *str; if (!csqcprogs || !csqcg.parse_stuffcmd) return false; - str = PF_TempStr(csqcprogs); - Q_strncpyz(str, cmd, MAXTEMPBUFFERLEN); - pr_globals = PR_globals(csqcprogs, PR_CURRENT); - (((string_t *)pr_globals)[OFS_PARM0] = PR_SetString(csqcprogs, str)); + (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd)); PR_ExecuteProgram (csqcprogs, csqcg.parse_stuffcmd); return true; @@ -3803,15 +3793,11 @@ qboolean CSQC_StuffCmd(char *cmd) qboolean CSQC_CenterPrint(char *cmd) { void *pr_globals; - char *str; if (!csqcprogs || !csqcg.parse_centerprint) return false; - str = PF_TempStr(csqcprogs); - Q_strncpyz(str, cmd, MAXTEMPBUFFERLEN); - pr_globals = PR_globals(csqcprogs, PR_CURRENT); - (((string_t *)pr_globals)[OFS_PARM0] = PR_SetString(csqcprogs, str)); + (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd)); PR_ExecuteProgram (csqcprogs, csqcg.parse_centerprint); return G_FLOAT(OFS_RETURN); @@ -3823,7 +3809,6 @@ qboolean CSQC_CenterPrint(char *cmd) int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation) { void *pr_globals; - char *str; csqcedict_t *ent; if (!csqcprogs || !csqcg.serversound) @@ -3840,12 +3825,9 @@ int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float pr_globals = PR_globals(csqcprogs, PR_CURRENT); - str = PF_TempStr(csqcprogs); - Q_strncpyz(str, soundname, MAXTEMPBUFFERLEN); - *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent); G_FLOAT(OFS_PARM0) = channel; - G_INT(OFS_PARM1) = PR_SetString(csqcprogs, str); + G_INT(OFS_PARM1) = PR_TempString(csqcprogs, soundname); VectorCopy(pos, G_VECTOR(OFS_PARM2)); G_FLOAT(OFS_PARM3) = vol; G_FLOAT(OFS_PARM4) = attenuation; @@ -3960,7 +3942,7 @@ void CSQC_ParseEntities(void) #ifndef CLIENTONLY if (sv.state) { - Con_Printf("Server classname: \"%s\"\n", svprogfuncs->stringtable+EDICT_NUM(svprogfuncs, entnum)->v->classname); + Con_Printf("Server classname: \"%s\"\n", PR_GetString(svprogfuncs, EDICT_NUM(svprogfuncs, entnum)->v->classname)); } #endif } diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index f66cbb97..464ea7c3 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -633,22 +633,16 @@ int MP_TranslateDPtoFTECodes(int code); void PF_cl_keynumtostring (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int code = G_FLOAT(OFS_PARM0); - char *keyname = PF_TempStr(prinst); code = MP_TranslateDPtoFTECodes (code); - strcpy(keyname, Key_KeynumToString(code)); - RETURN_SSTRING(keyname); + RETURN_TSTRING(Key_KeynumToString(code)); } void PF_cl_getkeybind (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *binding = Key_GetBinding(G_FLOAT(OFS_PARM0)); - char *result = PF_TempStr(prinst); - if (!binding) - binding = ""; - Q_strncpyz(result, binding, MAXTEMPBUFFERLEN); - RETURN_SSTRING(result); + RETURN_TSTRING(binding); } int MP_TranslateDPtoFTECodes(int code); @@ -657,16 +651,16 @@ void PF_cl_findkeysforcommand (progfuncs_t *prinst, struct globalvars_s *pr_glob { char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0); int keynums[2]; - char *keyname = PF_TempStr(prinst); + char keyname[512]; M_FindKeysForCommand(cmdname, keynums); keyname[0] = '\0'; - Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[0])), MAXTEMPBUFFERLEN); - Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[1])), MAXTEMPBUFFERLEN); + Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[0])), sizeof(keyname)); + Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoDPCodes(keynums[1])), sizeof(keyname)); - RETURN_SSTRING(keyname); + RETURN_TSTRING(keyname); } //vector getmousepos(void) = #66; @@ -813,17 +807,15 @@ void PF_M_gethostcachenumber(progfuncs_t *prinst, struct globalvars_s *pr_global } void PF_M_gethostcachestring (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *keyname = PF_TempStr(prinst); - char *ret = ""; + char *ret; int keynum = G_FLOAT(OFS_PARM0); int svnum = G_FLOAT(OFS_PARM1); serverinfo_t *sv; - sv = Master_SortedServer(svnum); + sv = Master_SortedServer(svnum); ret = Master_ReadKeyString(sv, keynum); - Q_strncpyz(keyname, ret, MAXTEMPBUFFERLEN); - RETURN_SSTRING(keyname); + RETURN_TSTRING(ret); } //float gethostcacheindexforkey(string key) = #622; @@ -1010,7 +1002,7 @@ void PF_altstr_count(progfuncs_t *prinst, struct globalvars_s *pr_globals) //string altstr_prepare(string str) = #83; void PF_altstr_prepare(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *outstr, *out; + char outstr[8192], *out; char *instr, *in; int size; @@ -1018,23 +1010,26 @@ void PF_altstr_prepare(progfuncs_t *prinst, struct globalvars_s *pr_globals) instr = PR_GetStringOfs(prinst, OFS_PARM0 ); //VM_CheckEmptyString( instr ); - outstr = PF_TempStr(prinst); - for( out = outstr, in = instr, size = MAXTEMPBUFFERLEN - 1 ; size && *in ; size--, in++, out++ ) - if( *in == '\'' ) { + for( out = outstr, in = instr, size = sizeof(outstr) - 1 ; size && *in ; size--, in++, out++ ) + { + if( *in == '\'' ) + { *out++ = '\\'; *out = '\''; size--; - } else + } + else *out = *in; + } *out = 0; - G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, outstr ); + G_INT( OFS_RETURN ) = (int)PR_TempString( prinst, outstr ); } //string altstr_get(string str, float num) = #84; void PF_altstr_get(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *altstr, *pos, *outstr, *out; + char *altstr, *pos, outstr[8192], *out; int count, size; // VM_SAFEPARMCOUNT( 2, VM_altstr_get ); @@ -1046,27 +1041,33 @@ void PF_altstr_get(progfuncs_t *prinst, struct globalvars_s *pr_globals) count = count * 2 + 1; for( pos = altstr ; *pos && count ; pos++ ) + { if( *pos == '\\' && !*++pos ) break; else if( *pos == '\'' ) count--; + } - if( !*pos ) { + if( !*pos ) + { G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, "" ); return; } - outstr = PF_TempStr(prinst); - for( out = outstr, size = MAXTEMPBUFFERLEN - 1 ; size && *pos ; size--, pos++, out++ ) - if( *pos == '\\' ) { + for( out = outstr, size = sizeof(outstr) - 1 ; size && *pos ; size--, pos++, out++ ) + { + if( *pos == '\\' ) + { if( !*++pos ) break; *out = *pos; size--; - } else if( *pos == '\'' ) + } + else if( *pos == '\'' ) break; else *out = *pos; + } *out = 0; G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, outstr ); @@ -1077,7 +1078,7 @@ void PF_altstr_set(progfuncs_t *prinst, struct globalvars_s *pr_globals) int num; char *altstr, *str; char *in; - char *outstr, *out; + char outstr[8192], *out; // VM_SAFEPARMCOUNT( 3, VM_altstr_set ); @@ -1089,23 +1090,29 @@ void PF_altstr_set(progfuncs_t *prinst, struct globalvars_s *pr_globals) str = PR_GetStringOfs(prinst, OFS_PARM2 ); //VM_CheckEmptyString( str ); - outstr = out = PF_TempStr(prinst); + out = outstr; for( num = num * 2 + 1, in = altstr; *in && num; *out++ = *in++ ) + { if( *in == '\\' && !*++in ) break; else if( *in == '\'' ) num--; + } - if( !in ) { + if( !in ) + { G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, "" ); return; } // copy set in - for( ; *str; *out++ = *str++ ); + for( ; *str; *out++ = *str++ ) + ; // now jump over the old contents for( ; *in ; in++ ) + { if( *in == '\'' || (*in == '\\' && !*++in) ) break; + } if( !in ) { G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, "" ); @@ -1113,7 +1120,7 @@ void PF_altstr_set(progfuncs_t *prinst, struct globalvars_s *pr_globals) } strcpy( out, in ); - G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, outstr ); + G_INT( OFS_RETURN ) = (int)PR_TempString( prinst, outstr ); } diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 80ef6588..e02f7349 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -1629,7 +1629,7 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n")); } ent = sv.edicts; - ent->v->model = PR_SetString(svprogfuncs, sv.worldmodel->name); //FIXME: is this a problem for normal ents? +// ent->v->model = PR_NewString(svprogfuncs, sv.worldmodel->name); //FIXME: is this a problem for normal ents? for (i=0 ; i_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]); break; case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*(OPA->string+progfuncs->stringtable)); + OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string)); break; case OP_NOT_FNC: OPC->_float = (float)(!(OPA->function & ~0xff000000)); @@ -206,20 +206,20 @@ reeval: OPC->_float = true; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string)) OPC->_float = true; else OPC->_float = false; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = true; else OPC->_float = false; } else - OPC->_float = (float)(!strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_EQ_E: OPC->_float = (float)(OPA->_int == OPB->_int); @@ -242,20 +242,20 @@ reeval: OPC->_float = false; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string))) OPC->_float = false; else OPC->_float = true; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = false; else OPC->_float = true; } else - OPC->_float = (float)(strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_NE_E: OPC->_float = (float)(OPA->_int != OPB->_int); @@ -443,7 +443,7 @@ reeval: case OP_IFNOTS: RUNAWAYCHECK(); - if (!OPA->string || !OPA->string[progfuncs->stringtable]) + if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -455,7 +455,7 @@ reeval: case OP_IFS: RUNAWAYCHECK(); - if (OPA->string && OPA->string[progfuncs->stringtable]) + if (OPA->string && PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -542,6 +542,7 @@ if (pr_typecurrent != 0) progfuncs->lastcalledbuiltinnumber = i; if (i < externs->numglobalbuiltins) { + prinst->numtempstringsstack = prinst->numtempstrings; (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); if (prinst->continuestatement!=-1) { @@ -868,9 +869,9 @@ if (pr_typecurrent != 0) RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ } - if ((!swtch->_int && progfuncs->stringtable[OPA->string]) || (!OPA->_int && progfuncs->stringtable[swtch->string])) //one is null (cannot be not both). + if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both). break; - if (!strcmp(progfuncs->stringtable+swtch->string, progfuncs->stringtable+OPA->string)) + if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string))) { RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ diff --git a/engine/qclib/execloop16d.h b/engine/qclib/execloop16d.h index d4fc02e4..fa511ece 100644 --- a/engine/qclib/execloop16d.h +++ b/engine/qclib/execloop16d.h @@ -176,7 +176,7 @@ reeval: OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]); break; case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*(OPA->string+progfuncs->stringtable)); + OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string)); break; case OP_NOT_FNC: OPC->_float = (float)(!(OPA->function & ~0xff000000)); @@ -206,20 +206,20 @@ reeval: OPC->_float = true; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string)) OPC->_float = true; else OPC->_float = false; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = true; else OPC->_float = false; } else - OPC->_float = (float)(!strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_EQ_E: OPC->_float = (float)(OPA->_int == OPB->_int); @@ -242,20 +242,20 @@ reeval: OPC->_float = false; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string))) OPC->_float = false; else OPC->_float = true; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = false; else OPC->_float = true; } else - OPC->_float = (float)(strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_NE_E: OPC->_float = (float)(OPA->_int != OPB->_int); @@ -394,11 +394,18 @@ reeval: #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif - if (ed->readonly) + if (!ed || ed->readonly) { pr_xstatement = st-pr_statements; PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } + +//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods. +// if (ed->isfree) +// { +// pr_xstatement = st-pr_statements; +// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); +// } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; @@ -436,7 +443,7 @@ reeval: case OP_IFNOTS: RUNAWAYCHECK(); - if (!OPA->string || !OPA->string[progfuncs->stringtable]) + if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -448,7 +455,7 @@ reeval: case OP_IFS: RUNAWAYCHECK(); - if (OPA->string && OPA->string[progfuncs->stringtable]) + if (OPA->string && PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -535,6 +542,7 @@ if (pr_typecurrent != 0) progfuncs->lastcalledbuiltinnumber = i; if (i < externs->numglobalbuiltins) { + prinst->numtempstringsstack = prinst->numtempstrings; (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); if (prinst->continuestatement!=-1) { @@ -734,7 +742,7 @@ if (pr_typecurrent != 0) case OP_FETCH_GBL_E: case OP_FETCH_GBL_FNC: i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) + if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) { PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); } @@ -743,7 +751,7 @@ if (pr_typecurrent != 0) break; case OP_FETCH_GBL_V: i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) + if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) { PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); } @@ -861,9 +869,9 @@ if (pr_typecurrent != 0) RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ } - if ((!swtch->_int && progfuncs->stringtable[OPA->string]) || (!OPA->_int && progfuncs->stringtable[swtch->string])) //one is null (cannot be not both). + if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both). break; - if (!strcmp(progfuncs->stringtable+swtch->string, progfuncs->stringtable+OPA->string)) + if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string))) { RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ diff --git a/engine/qclib/execloop32.h b/engine/qclib/execloop32.h index d4fc02e4..fa511ece 100644 --- a/engine/qclib/execloop32.h +++ b/engine/qclib/execloop32.h @@ -176,7 +176,7 @@ reeval: OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]); break; case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*(OPA->string+progfuncs->stringtable)); + OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string)); break; case OP_NOT_FNC: OPC->_float = (float)(!(OPA->function & ~0xff000000)); @@ -206,20 +206,20 @@ reeval: OPC->_float = true; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string)) OPC->_float = true; else OPC->_float = false; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = true; else OPC->_float = false; } else - OPC->_float = (float)(!strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_EQ_E: OPC->_float = (float)(OPA->_int == OPB->_int); @@ -242,20 +242,20 @@ reeval: OPC->_float = false; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string))) OPC->_float = false; else OPC->_float = true; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = false; else OPC->_float = true; } else - OPC->_float = (float)(strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_NE_E: OPC->_float = (float)(OPA->_int != OPB->_int); @@ -394,11 +394,18 @@ reeval: #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif - if (ed->readonly) + if (!ed || ed->readonly) { pr_xstatement = st-pr_statements; PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } + +//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods. +// if (ed->isfree) +// { +// pr_xstatement = st-pr_statements; +// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); +// } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; @@ -436,7 +443,7 @@ reeval: case OP_IFNOTS: RUNAWAYCHECK(); - if (!OPA->string || !OPA->string[progfuncs->stringtable]) + if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -448,7 +455,7 @@ reeval: case OP_IFS: RUNAWAYCHECK(); - if (OPA->string && OPA->string[progfuncs->stringtable]) + if (OPA->string && PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -535,6 +542,7 @@ if (pr_typecurrent != 0) progfuncs->lastcalledbuiltinnumber = i; if (i < externs->numglobalbuiltins) { + prinst->numtempstringsstack = prinst->numtempstrings; (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); if (prinst->continuestatement!=-1) { @@ -734,7 +742,7 @@ if (pr_typecurrent != 0) case OP_FETCH_GBL_E: case OP_FETCH_GBL_FNC: i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) + if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) { PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); } @@ -743,7 +751,7 @@ if (pr_typecurrent != 0) break; case OP_FETCH_GBL_V: i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) + if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) { PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); } @@ -861,9 +869,9 @@ if (pr_typecurrent != 0) RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ } - if ((!swtch->_int && progfuncs->stringtable[OPA->string]) || (!OPA->_int && progfuncs->stringtable[swtch->string])) //one is null (cannot be not both). + if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both). break; - if (!strcmp(progfuncs->stringtable+swtch->string, progfuncs->stringtable+OPA->string)) + if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string))) { RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ diff --git a/engine/qclib/execloop32d.h b/engine/qclib/execloop32d.h index d4fc02e4..fa511ece 100644 --- a/engine/qclib/execloop32d.h +++ b/engine/qclib/execloop32d.h @@ -176,7 +176,7 @@ reeval: OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]); break; case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*(OPA->string+progfuncs->stringtable)); + OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string)); break; case OP_NOT_FNC: OPC->_float = (float)(!(OPA->function & ~0xff000000)); @@ -206,20 +206,20 @@ reeval: OPC->_float = true; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string)) OPC->_float = true; else OPC->_float = false; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = true; else OPC->_float = false; } else - OPC->_float = (float)(!strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_EQ_E: OPC->_float = (float)(OPA->_int == OPB->_int); @@ -242,20 +242,20 @@ reeval: OPC->_float = false; else if (!OPA->string) { - if (!OPB->string || !*(OPB->string+progfuncs->stringtable)) + if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string))) OPC->_float = false; else OPC->_float = true; } else if (!OPB->string) { - if (!OPA->string || !*(OPA->string+progfuncs->stringtable)) + if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) OPC->_float = false; else OPC->_float = true; } else - OPC->_float = (float)(strcmp(OPA->string+progfuncs->stringtable,OPB->string+progfuncs->stringtable)); + OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); break; case OP_NE_E: OPC->_float = (float)(OPA->_int != OPB->_int); @@ -394,11 +394,18 @@ reeval: #ifdef PARANOID NUM_FOR_EDICT(ed); // make sure it's in range #endif - if (ed->readonly) + if (!ed || ed->readonly) { pr_xstatement = st-pr_statements; PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } + +//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods. +// if (ed->isfree) +// { +// pr_xstatement = st-pr_statements; +// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); +// } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break; @@ -436,7 +443,7 @@ reeval: case OP_IFNOTS: RUNAWAYCHECK(); - if (!OPA->string || !OPA->string[progfuncs->stringtable]) + if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -448,7 +455,7 @@ reeval: case OP_IFS: RUNAWAYCHECK(); - if (OPA->string && OPA->string[progfuncs->stringtable]) + if (OPA->string && PR_StringToNative(progfuncs, OPA->string)) st += (sofs)st->b - 1; // offset the s++ break; @@ -535,6 +542,7 @@ if (pr_typecurrent != 0) progfuncs->lastcalledbuiltinnumber = i; if (i < externs->numglobalbuiltins) { + prinst->numtempstringsstack = prinst->numtempstrings; (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); if (prinst->continuestatement!=-1) { @@ -734,7 +742,7 @@ if (pr_typecurrent != 0) case OP_FETCH_GBL_E: case OP_FETCH_GBL_FNC: i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) + if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) { PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); } @@ -743,7 +751,7 @@ if (pr_typecurrent != 0) break; case OP_FETCH_GBL_V: i = (int)OPB->_float; - if(i < 0 || i > G_INT((uofs)st->a - 1)) + if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) { PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); } @@ -861,9 +869,9 @@ if (pr_typecurrent != 0) RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ } - if ((!swtch->_int && progfuncs->stringtable[OPA->string]) || (!OPA->_int && progfuncs->stringtable[swtch->string])) //one is null (cannot be not both). + if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both). break; - if (!strcmp(progfuncs->stringtable+swtch->string, progfuncs->stringtable+OPA->string)) + if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string))) { RUNAWAYCHECK(); st += (sofs)st->b-1; // -1 to offset the s++ diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index a122ab13..d169ea2a 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -330,6 +330,130 @@ int EdictToProgs (progfuncs_t *progfuncs, struct edict_s *ed) return EDICT_TO_PROG(progfuncs, ed); } +string_t PR_StringToProgs (progfuncs_t *progfuncs, char *str) +{ + char **ntable; + int i, free=-1; + + if (!str) + return 0; + +// if (str-progfuncs->stringtable < progfuncs->stringtablesize) +// return str - progfuncs->stringtable; + + for (i = prinst->numallocedstrings-1; i >= 0; i--) + { + if (prinst->allocedstrings[i] == str) + return (string_t)((unsigned int)i | 0x80000000); + if (!prinst->allocedstrings[i]) + free = i; + } + + if (free != -1) + { + i = free; + prinst->allocedstrings[i] = str; + return (string_t)((unsigned int)i | 0x80000000); + } + + prinst->maxallocedstrings += 1024; + ntable = memalloc(sizeof(char*) * prinst->maxallocedstrings); + memcpy(ntable, prinst->allocedstrings, sizeof(char*) * prinst->numallocedstrings); + prinst->numallocedstrings = prinst->maxallocedstrings; + if (prinst->allocedstrings) + memfree(prinst->allocedstrings); + prinst->allocedstrings = ntable; + + for (i = prinst->numallocedstrings-1; i >= 0; i--) + { + if (!prinst->allocedstrings[i]) + { + prinst->allocedstrings[i] = str; + return (string_t)((unsigned int)i | 0x80000000); + } + } + + return 0; +} + +char *PR_StringToNative (progfuncs_t *progfuncs, string_t str) +{ + if ((unsigned int)str & 0xc0000000) + { + if ((unsigned int)str & 0x80000000) + { + int i = str & ~0x80000000; + if (i >= prinst->numallocedstrings) + return ""; + if (prinst->allocedstrings[i]) + return prinst->allocedstrings[i]; + else + return ""; //urm, was freed... + } + if ((unsigned int)str & 0x40000000) + { + int i = str & ~0x40000000; + if (i >= prinst->numtempstrings) + return ""; + return prinst->tempstrings[i]; + } + } + + if (str >= progfuncs->stringtablesize) + return ""; + return progfuncs->stringtable + str; +} + + +string_t PR_AllocTempString (progfuncs_t *progfuncs, char *str) +{ + char **ntable; + int newmax; + int i; + + if (!str) + return 0; + + if (prinst->numtempstrings == prinst->maxtempstrings) + { + newmax = prinst->maxtempstrings += 1024; + prinst->maxtempstrings += 1024; + ntable = memalloc(sizeof(char*) * newmax); + memcpy(ntable, prinst->tempstrings, sizeof(char*) * prinst->numtempstrings); + prinst->maxtempstrings = newmax; + if (prinst->tempstrings) + memfree(prinst->tempstrings); + prinst->tempstrings = ntable; + } + + i = prinst->numtempstrings; + if (i == 0x10000000) + return 0; + + prinst->numtempstrings++; + + prinst->tempstrings[i] = memalloc(strlen(str)+1); + strcpy(prinst->tempstrings[i], str); + + return (string_t)((unsigned int)i | 0x40000000); +} + +void PR_FreeTemps (progfuncs_t *progfuncs, int depth) +{ + int i; + if (depth > prinst->numtempstrings) + { + Sys_Error("QC Temp stack inverted\n"); + return; + } + for (i = depth; i < prinst->numtempstrings; i++) + { + memfree(prinst->tempstrings[i]); + } + + prinst->numtempstrings = depth; +} + struct qcthread_s *PR_ForkStack (progfuncs_t *progfuncs); void PR_ResumeThread (progfuncs_t *progfuncs, struct qcthread_s *thread); @@ -416,7 +540,12 @@ progfuncs_t deffuncs = { QC_RegisterFieldVar, 0, - 0 + 0, + + PR_AllocTempString, + + PR_StringToProgs, + PR_StringToNative }; #undef printf diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index ff7af9ed..b7d460a5 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -508,7 +508,7 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) sprintf (line, "union"); break; case ev_string: - sprintf (line, "%s", val->string+progfuncs->stringtable); + sprintf (line, "%s", PR_StringToNative(progfuncs, val->string)); break; case ev_entity: sprintf (line, "entity %i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict)) ); @@ -609,7 +609,7 @@ char *PR_UglyValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) if ((unsigned)val->_int > (unsigned)addressableused) _snprintf (line, sizeof(line), "CORRUPT STRING"); else - _snprintf (line, sizeof(line), "%s", val->string+progfuncs->stringtable); + _snprintf (line, sizeof(line), "%s", PR_StringToNative(progfuncs, val->string)); break; case ev_entity: sprintf (line, "%i", val->_int); @@ -683,7 +683,7 @@ char *PR_UglyOldValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) sprintf (line, "unions cannot yet be saved"); break; case ev_string: - sprintf (line, "%s", val->string+progfuncs->stringtable); + sprintf (line, "%s", PR_StringToNative(progfuncs, val->string)); break; case ev_entity: sprintf (line, "%i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict))); @@ -1051,7 +1051,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, switch (type) { case ev_string: - st = ED_NewString (progfuncs, s, 0)-progfuncs->stringtable; + st = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, s, 0)); *(string_t *)d = st; break; @@ -2018,7 +2018,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) CheckSpawn = PR_FindFunc(progfuncs, "CheckSpawn", -2); var = GetEdictFieldValue (progfuncs, (struct edict_s *)ed, "classname", NULL); - if (!var || !var->string || !*(var->string+progfuncs->stringtable)) + if (!var || !var->string || !*PR_StringToNative(progfuncs, var->string)) { printf("No classname\n"); ED_Free(progfuncs, (struct edict_s *)ed); @@ -2044,7 +2044,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) selfvar = (eval_t *)((int *)pr_globals + ED_FindGlobalOfs(progfuncs, "self")); selfvar->edict = EDICT_TO_PROG(progfuncs, ed); - f = PR_FindFunc(progfuncs, var->string+progfuncs->stringtable, PR_ANYBACK); + f = PR_FindFunc(progfuncs, PR_StringToNative(progfuncs, var->string), PR_ANYBACK); if (f) { if (CheckSpawn) @@ -2064,7 +2064,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) } else { - printf("Couldn't find spawn function %s\n", var->string+progfuncs->stringtable); + printf("Couldn't find spawn function %s\n", PR_StringToNative(progfuncs, var->string)); ED_Free(progfuncs, (struct edict_s *)ed); } } @@ -2977,6 +2977,9 @@ retry: if (!progfuncs->stringtable) progfuncs->stringtable = pr_strings; + if (progfuncs->stringtablesize + progfuncs->stringtable < pr_strings + pr_progs->numstrings) + progfuncs->stringtablesize = (pr_strings + pr_progs->numstrings) - progfuncs->stringtable; + eval = PR_FindGlobal(progfuncs, "thisprogs", progstype); if (eval) eval->prog = progstype; diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index 061e3b21..1da6911e 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -894,6 +894,8 @@ void PR_ExecuteProgram (progfuncs_t *progfuncs, func_t fnum) int s; + int tempdepth; + unsigned int newprogs = (fnum & 0xff000000)>>24; initial_progs = pr_typecurrent; @@ -953,14 +955,19 @@ void PR_ExecuteProgram (progfuncs_t *progfuncs, func_t fnum) // make a stack frame prinst->exitdepth = pr_depth; + s = PR_EnterFunction (progfuncs, f, initial_progs); + tempdepth = prinst->numtempstringsstack; PR_ExecuteCode(progfuncs, s); PR_MoveParms(progfuncs, initial_progs, pr_typecurrent); PR_SwitchProgs(progfuncs, initial_progs); + PR_FreeTemps(progfuncs, tempdepth); + prinst->numtempstringsstack = tempdepth; + prinst->exitdepth = oldexitdepth; } @@ -1061,6 +1068,7 @@ void PR_ResumeThread (progfuncs_t *progfuncs, struct qcthread_s *thread) int oldexitdepth; int s; + int tempdepth; progsnum_t prnum = thread->xprogs; int fnum = thread->xfunction; @@ -1133,11 +1141,14 @@ void PR_ResumeThread (progfuncs_t *progfuncs, struct qcthread_s *thread) pr_xfunction = f; s = thread->xstatement; + tempdepth = prinst->numtempstringsstack; PR_ExecuteCode(progfuncs, s); PR_MoveParms(progfuncs, initial_progs, pr_typecurrent); PR_SwitchProgs(progfuncs, initial_progs); + PR_FreeTemps(progfuncs, tempdepth); + prinst->numtempstringsstack = tempdepth; prinst->exitdepth = oldexitdepth; pr_xfunction = oldf; diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 07bfe326..c9439750 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -328,6 +328,16 @@ void PR_SetBuiltins(int type); #define vars(type, name, size) type name[size] typedef struct prinst_s { + + char **tempstrings; + int maxtempstrings; + int numtempstrings; + int numtempstringsstack; + + char **allocedstrings; + int maxallocedstrings; + int numallocedstrings; + var(progstate_t *, pr_progstate); #define pr_progstate prinst->pr_progstate @@ -440,6 +450,11 @@ ddef16_t *ED_FindGlobal16 (progfuncs_t *progfuncs, char *name); ddef32_t *ED_FindGlobal32 (progfuncs_t *progfuncs, char *name); ddef32_t *ED_GlobalAtOfs32 (progfuncs_t *progfuncs, unsigned int ofs); +string_t PR_StringToProgs (progfuncs_t *inst, char *str); +char *PR_StringToNative (progfuncs_t *inst, string_t str); + +void PR_FreeTemps (progfuncs_t *progfuncs, int depth); + char *PR_GlobalString (progfuncs_t *progfuncs, int ofs); char *PR_GlobalStringNoContents (progfuncs_t *progfuncs, int ofs); diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 300cde1c..6b5ec959 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -127,6 +127,12 @@ struct progfuncs_s { char *tempstringbase; //for engine's use. Store your base tempstring pointer here. int tempstringnum; //for engine's use. + + string_t (*TempString) (progfuncs_t *prinst, char *str); + + string_t (*StringToProgs) (progfuncs_t *prinst, char *str); + char *(*StringToNative) (progfuncs_t *prinst, string_t str); + int stringtablesize; }; typedef struct progexterns_s { @@ -244,6 +250,10 @@ typedef union eval_s #define PR_RegisterBuiltin(pf, name, func) (*pf->RegisterBuiltin) (pf, name, func) +#define PR_GetString(pf,s) (*pf->StringToNative) (pf, s) +#define PR_GetStringOfs(pf,o) (*pf->StringToNative) (pf, G_INT(o)) +#define PR_SetString(pf, s) (*pf->StringToProgs) (pf, s) + #define NEXT_EDICT(pf,o) EDICT_NUM(pf, NUM_FOR_EDICT(pf, o)+1) #define RETURN_EDICT(pf, e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(pf, e)) @@ -258,11 +268,14 @@ typedef union eval_s #define G_VECTOR(o) (&((float *)pr_globals)[o]) #define G_FUNCTION(o) (*(func_t *)&((float *)pr_globals)[o]) +/* #define PR_GetString(p,s) (s?s + p->stringtable:"") #define PR_GetStringOfs(p,o) (G_INT(o)?G_INT(o) + p->stringtable:"") #define PR_SetStringOfs(p,o,s) (G_INT(o) = s - p->stringtable) -#define PR_SetString(p, s) ((s&&*s)?(s - p->stringtable):0) -#define PR_NewString(p, s, l) (PR_AddString(p, s, l) - p->stringtable) +*/ +//#define PR_SetString(p, s) ((s&&*s)?(s - p->stringtable):0) +#define PR_NewString(p, s, l) PR_SetString(p, PR_AddString(p, s, l)) +/**/ #define ev_prog ev_integer diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 3ba4e57b..97ebaa20 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -262,7 +262,12 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); - if (cl) + if (!cl) + { + Con_Printf("msg_entity: not a client\n"); + return; + } + else { if (cl->protocol == SCP_BAD) // is a bot return; @@ -571,12 +576,22 @@ void NPP_NQWriteAngle(int dest, float in) //replacement write func (nq to qw) if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); - if (cl && !ISQWCLIENT(cl)) + if (!cl) { - ClientReliableCheckBlock(cl, sizeof(char)); - ClientReliableWrite_Angle(cl, in); + Con_Printf("msg_entity: not a client\n"); return; } + else + { + if (cl->protocol == SCP_BAD) + return; + else if (!ISQWCLIENT(cl)) + { + ClientReliableCheckBlock(cl, sizeof(char)); + ClientReliableWrite_Angle(cl, in); + return; + } + } } else MSG_WriteAngle (NQWriteDest(dest), in); @@ -594,15 +609,27 @@ void NPP_NQWriteCoord(int dest, float in) //replacement write func (nq to qw) Con_Printf("NQWriteCoord: Messages should start with WriteByte\n"); #ifdef NQPROT - if (dest == MSG_ONE) { + if (dest == MSG_ONE) + { client_t *cl = Write_GetClient(); - if (cl && !ISQWCLIENT(cl)) + if (!cl) { - ClientReliableCheckBlock(cl, sizeof(float)); - ClientReliableWrite_Coord(cl, in); + Con_Printf("msg_entity: not a client\n"); return; } - } else + else + { + if (cl->protocol == SCP_BAD) + return; + else if (!ISQWCLIENT(cl)) + { + ClientReliableCheckBlock(cl, sizeof(float)); + ClientReliableWrite_Coord(cl, in); + return; + } + } + } + else MSG_WriteCoord (NQWriteDest(dest), in); #endif @@ -627,15 +654,27 @@ void NPP_NQWriteString(int dest, char *data) //replacement write func (nq to qw) } #ifdef NQPROT - if (dest == MSG_ONE) { + if (dest == MSG_ONE) + { client_t *cl = Write_GetClient(); - if (cl && !ISQWCLIENT(cl)) + if (!cl) { - ClientReliableCheckBlock(cl, strlen(data)+1); - ClientReliableWrite_String(cl, data); + Con_Printf("msg_entity: not a client\n"); return; } - } else + else + { + if (cl->protocol == SCP_BAD) + return; + else if (!ISQWCLIENT(cl)) + { + ClientReliableCheckBlock(cl, strlen(data)+1); + ClientReliableWrite_String(cl, data); + return; + } + } + } + else MSG_WriteString (NQWriteDest(dest), data); #endif @@ -668,15 +707,27 @@ void NPP_NQWriteEntity(int dest, short data) //replacement write func (nq to qw) data = svs.clients[data-1].viewent; #ifdef NQPROT - if (dest == MSG_ONE) { + if (dest == MSG_ONE) + { client_t *cl = Write_GetClient(); - if (cl && !ISQWCLIENT(cl)) + if (!cl) { - ClientReliableCheckBlock(cl, sizeof(short)); - ClientReliableWrite_Short(cl, data); + Con_Printf("msg_entity: not a client\n"); return; } - } else + else + { + if (cl->protocol == SCP_BAD) + return; + else if (!ISQWCLIENT(cl)) + { + ClientReliableCheckBlock(cl, sizeof(short)); + ClientReliableWrite_Short(cl, data); + return; + } + } + } + else MSG_WriteShort (NQWriteDest(dest), data); #endif @@ -961,6 +1012,7 @@ void NPP_QWCheckDest(int dest) } cldest = cl; */ + cldest = NULL; } else { @@ -985,16 +1037,21 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) if (dest == MSG_ONE) { client_t *cl = Write_GetClient(); - if (cl) + if (!cl) { - if (ISQWCLIENT(cl)) + Con_Printf("msg_entity: not a client\n"); + return; + } + else + { + if (cl->protocol == SCP_BAD) // is a bot + return; + else if (ISQWCLIENT(cl)) { ClientReliableCheckBlock(cl, sizeof(qbyte)); ClientReliableWrite_Byte(cl, data); return; } - else if (cl->protocol == SCP_BAD) // is a bot - return; } } else @@ -1218,15 +1275,27 @@ void NPP_QWWriteString(int dest, char *data) //replacement write func (nq to qw) NPP_QWCheckDest(dest); #ifdef NQPROT - if (dest == MSG_ONE) { + if (dest == MSG_ONE) + { client_t *cl = Write_GetClient(); - if (cl && ISQWCLIENT(cl)) + if (!cl) { - ClientReliableCheckBlock(cl, strlen(data)+1); - ClientReliableWrite_String(cl, data); + Con_Printf("msg_entity: not a client\n"); return; } - } else + else + { + if (cl->protocol == SCP_BAD) + return; + else if (ISQWCLIENT(cl)) + { + ClientReliableCheckBlock(cl, strlen(data)+1); + ClientReliableWrite_String(cl, data); + return; + } + } + } + else MSG_WriteString (QWWriteDest(dest), data); #endif diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 9c1bbbbe..2c793070 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -61,7 +61,7 @@ cvar_t pr_compatabilitytest = SCVARF("pr_compatabilitytest", "0", CVAR_LATCH); cvar_t pr_ssqc_coreonerror = SCVAR("pr_coreonerror", "1"); -cvar_t pr_tempstringcount = SCVAR("pr_tempstringcount", "16"); +cvar_t pr_tempstringcount = SCVAR("pr_tempstringcount", "");//"16"); cvar_t pr_tempstringsize = SCVAR("pr_tempstringsize", "4096"); cvar_t pr_droptofloorunits = SCVAR("pr_droptofloorunits", ""); @@ -1611,7 +1611,7 @@ char *PF_VarString (progfuncs_t *prinst, int first, globalvars_t *pr_globals) //#define RETURN_EDICT(pf, e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(pf, e)) #define RETURN_SSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it. -#define RETURN_TSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //temp (static but cycle buffers?) +#define RETURN_TSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_TempString(prinst, s)) //temp (static but cycle buffers) #define RETURN_CSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //semi-permanant. (hash tables?) #define RETURN_PSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_NewString(prinst, s, 0)) //permanant @@ -3510,40 +3510,43 @@ void PF_printv (progfuncs_t *prinst, struct globalvars_s *pr_globals) #define MAX_TEMPSTRS ((int)pr_tempstringcount.value) #define MAXTEMPBUFFERLEN ((int)pr_tempstringsize.value) -char *PF_TempStr(progfuncs_t *prinst) -{ - if (prinst->tempstringnum == MAX_TEMPSTRS) - prinst->tempstringnum = 0; - return prinst->tempstringbase + (prinst->tempstringnum++)*MAXTEMPBUFFERLEN; -} - string_t PR_TempString(progfuncs_t *prinst, char *str) { char *tmp; + if (!prinst->tempstringbase) + return prinst->TempString(prinst, str); + if (!str || !*str) return 0; - tmp = PF_TempStr(prinst); + + if (prinst->tempstringnum == MAX_TEMPSTRS) + prinst->tempstringnum = 0; + tmp = prinst->tempstringbase + (prinst->tempstringnum++)*MAXTEMPBUFFERLEN; + Q_strncpyz(tmp, str, MAXTEMPBUFFERLEN); return tmp - prinst->stringtable; } void PF_InitTempStrings(progfuncs_t *prinst) { - if (pr_tempstringcount.value < 2) + if (pr_tempstringcount.value > 0 && pr_tempstringcount.value < 2) pr_tempstringcount.value = 2; if (pr_tempstringsize.value < 256) pr_tempstringsize.value = 256; pr_tempstringcount.flags |= CVAR_NOSET; pr_tempstringsize.flags |= CVAR_NOSET; - prinst->tempstringbase = prinst->AddString(prinst, "", MAXTEMPBUFFERLEN*MAX_TEMPSTRS); + if (pr_tempstringcount.value >= 2) + prinst->tempstringbase = prinst->AddString(prinst, "", MAXTEMPBUFFERLEN*MAX_TEMPSTRS); + else + prinst->tempstringbase = 0; prinst->tempstringnum = 0; } void PF_ftos (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float v; - char *pr_string_temp = PF_TempStr(prinst); + char pr_string_temp[64]; v = G_FLOAT(OFS_PARM0); if (v == (int)v) @@ -3564,8 +3567,9 @@ void PF_fabs (progfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_vtos (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *pr_string_temp = PF_TempStr(prinst); + char pr_string_temp[64]; sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); + PR_TempString(prinst, pr_string_temp); RETURN_TSTRING(pr_string_temp); } @@ -3630,7 +3634,7 @@ void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals) t = ((string_t *)ed->v)[f]; if (!t) continue; - if (!strcmp(t+prinst->stringtable,s)) + if (!strcmp(PR_GetString(prinst, t),s)) { RETURN_EDICT(prinst, ed); return; @@ -5190,7 +5194,6 @@ void PF_infokey (progfuncs_t *prinst, struct globalvars_s *pr_globals) char *value; char *key; char ov[256]; - char *dest; e = G_EDICT(prinst, OFS_PARM0); e1 = NUM_FOR_EDICT(prinst, e); @@ -5236,9 +5239,7 @@ void PF_infokey (progfuncs_t *prinst, struct globalvars_s *pr_globals) } else value = ""; - dest = PF_TempStr(prinst); - strcpy(dest, value); - RETURN_CSTRING(dest); + G_INT(OFS_RETURN) = PR_TempString(prinst, value); } /* @@ -5486,7 +5487,7 @@ void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int i, start, length; char *s; - char *string = PF_TempStr(prinst); + char string[4096]; s = PR_GetStringOfs(prinst, OFS_PARM0); start = G_FLOAT(OFS_PARM1); @@ -5513,7 +5514,7 @@ void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals) string[i] = *s; string[i] = 0; - RETURN_SSTRING(string); + RETURN_TSTRING(string); } @@ -5592,11 +5593,11 @@ void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int i; - char *string = PF_TempStr(prinst); + char string[16]; for (i = 0; i < *prinst->callargc; i++) string[i] = G_FLOAT(OFS_PARM0 + i*3); string[i] = '\0'; - RETURN_SSTRING(string); + RETURN_TSTRING(string); } static int chrconv_number(int i, int base, int conv) { @@ -5688,13 +5689,13 @@ void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) unsigned char *string = PF_VarString(prinst, 3, pr_globals); int len = strlen(string); int i; - unsigned char *result = PF_TempStr(prinst); - unsigned char *resbuf = result; + unsigned char resbuf[8192]; + unsigned char *result = resbuf; if (len >= MAXTEMPBUFFERLEN) len = MAXTEMPBUFFERLEN-1; - for (i = 0; i < len; i++, string++, result++) //do this backwards + for (i = 0; i < len; i++, string++, result++) //should this be done backwards? { if (*string >= '0' && *string <= '9') //normal numbers... *result = chrconv_number(*string, '0', redchars); @@ -5764,14 +5765,13 @@ void PF_infoadd (progfuncs_t *prinst, struct globalvars_s *pr_globals) char *info = PR_GetStringOfs(prinst, OFS_PARM0); char *key = PR_GetStringOfs(prinst, OFS_PARM1); char *value = PF_VarString(prinst, 2, pr_globals); - char *temp; + char temp[8192]; - temp = PF_TempStr(prinst); Q_strncpyz(temp, info, MAXTEMPBUFFERLEN); Info_SetValueForStarKey(temp, key, value, MAXTEMPBUFFERLEN); - RETURN_SSTRING(temp); + RETURN_TSTRING(temp); } //uses qw style \key\value strings @@ -5779,13 +5779,10 @@ void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *info = PR_GetStringOfs(prinst, OFS_PARM0); char *key = PR_GetStringOfs(prinst, OFS_PARM1); - char *temp; key = Info_ValueForKey(info, key); - temp = PF_TempStr(prinst); - strcpy(temp, key); - RETURN_SSTRING(temp); + RETURN_TSTRING(key); } //back to frik_file support. @@ -5919,10 +5916,10 @@ void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char c, *s, *o, *max; int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; - char *pr_string_temp = PF_TempStr(prinst); + char pr_string_temp[4096]; *pr_string_temp = '\0'; - RETURN_SSTRING(pr_string_temp); + G_INT(OFS_RETURN) = 0; //EOF if (fnum < 0 || fnum >= MAX_QC_FILES) { PR_BIError(prinst, "PF_fgets: File out of range\n"); @@ -5964,7 +5961,7 @@ void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (!pr_string_temp[0] && !*s) G_INT(OFS_RETURN) = 0; //EOF else - G_INT(OFS_RETURN) = pr_string_temp - prinst->stringtable; + RETURN_TSTRING(pr_string_temp); } void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -6194,7 +6191,7 @@ void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals if (num < 0 || num >= s->entries) return; - G_INT(OFS_RETURN) = (int)(s->names[num] - prinst->stringtable); + RETURN_TSTRING(s->names[num]); return; } } @@ -6578,7 +6575,6 @@ void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals) //84 } void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals) //86 //string(float num) argv; { - char *dest = PF_TempStr(prinst); int i = G_FLOAT(OFS_PARM0); if (i < 0) { @@ -6586,8 +6582,7 @@ void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals) //86 / G_INT(OFS_RETURN) = 0; return; } - strcpy(dest, Cmd_Argv(i)); - RETURN_CSTRING(dest); + RETURN_TSTRING(Cmd_Argv(i)); } /* @@ -6613,7 +6608,7 @@ string substr(string str, float start, float len) void PF_substr (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *dest; + char dest[4096]; char *s; int start, len, l; @@ -6627,7 +6622,6 @@ void PF_substr (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_TSTRING(""); return; } - dest = PF_TempStr(prinst); s += start; l -= start; @@ -6635,6 +6629,9 @@ void PF_substr (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (len > l + 1) len = l + 1; + if (len > sizeof(dest)-1) + len = sizeof(dest)-1; + Q_strncpyz(dest, s, len + 1); RETURN_TSTRING(dest); @@ -6650,7 +6647,7 @@ string strcat(string str1, string str2) void PF_strcat (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *dest = PF_TempStr(prinst); + char dest[4096]; char *src = PF_VarString(prinst, 0, pr_globals); Q_strncpyz(dest, src, MAXTEMPBUFFERLEN); RETURN_TSTRING(dest); @@ -6666,12 +6663,11 @@ string strcat(float pad, string str1, ...) void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *dest = PF_TempStr(prinst); + char destbuf[4096]; + char *dest = destbuf; int pad = G_FLOAT(OFS_PARM0); char *src = PF_VarString(prinst, 1, pr_globals); - RETURN_TSTRING(dest); - if (pad < 0) { //pad left pad = -pad - strlen(src); @@ -6702,6 +6698,8 @@ void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals) *dest++ = ' '; *dest = '\0'; } + + RETURN_TSTRING(destbuf); } /* @@ -6804,7 +6802,6 @@ void PF_calltimeofday (progfuncs_t *prinst, struct globalvars_s *pr_globals) { date_t date; func_t f; - char *ret = PF_TempStr(prinst); f = PR_FindFunction(svprogfuncs, "timeofday", PR_ANY); if (f) @@ -6817,8 +6814,7 @@ void PF_calltimeofday (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_PARM3) = (float)date.day; G_FLOAT(OFS_PARM4) = (float)date.mon; G_FLOAT(OFS_PARM5) = (float)date.year; - strcpy(ret, date.str); - G_INT(OFS_PARM6) = (int)PR_SetString(prinst, ret); + G_INT(OFS_PARM6) = (int)PR_TempString(prinst, date.str); PR_ExecuteProgram(prinst, f); } @@ -7033,10 +7029,9 @@ static void PF_copyentity (progfuncs_t *prinst, struct globalvars_s *pr_globals) //string(entity ent) etos = #65 void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *s; - s = PF_TempStr(prinst); - sprintf (s, "entity %i", G_EDICTNUM(prinst, OFS_PARM0)); - G_INT(OFS_RETURN) = (int)PR_SetString(prinst, s); + char s[64]; + snprintf (s, sizeof(s), "entity %i", G_EDICTNUM(prinst, OFS_PARM0)); + RETURN_TSTRING(s); }