]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/mediasource/extra/fteqcc-src/pr_exec.c
fteqcc source
[voretournament/voretournament.git] / misc / mediasource / extra / fteqcc-src / pr_exec.c
diff --git a/misc/mediasource/extra/fteqcc-src/pr_exec.c b/misc/mediasource/extra/fteqcc-src/pr_exec.c
new file mode 100644 (file)
index 0000000..bdd2af9
--- /dev/null
@@ -0,0 +1,1199 @@
+#define PROGSUSED
+#include "progsint.h"
+//#include "editor.h"
+
+#define HunkAlloc BADGDFG sdfhhsf FHS
+
+
+#define Host_Error Sys_Error
+
+
+//=============================================================================
+
+/*
+=================
+PR_PrintStatement
+=================
+*/
+/*
+void PR_PrintStatement (progfuncs_t *progfuncs, dstatement16_t *s)
+{
+       int             i;
+printf("PR_PrintStatement is unsupported\n");
+return;
+       if ( (unsigned)s->op < OP_NUMOPS)
+       {
+               printf ("%s ",  pr_opcodes[s->op].name);
+               i = strlen(pr_opcodes[s->op].name);
+               for ( ; i<10 ; i++)
+                       printf (" ");
+       }
+               
+       if (s->op == OP_IF || s->op == OP_IFNOT)
+               printf ("%sbranch %i",PR_GlobalString(progfuncs, s->a),s->b);
+       else if (s->op == OP_GOTO)
+       {
+               printf ("branch %i",s->a);
+       }
+       else if ( (unsigned)(s->op - OP_STORE_F) < 6)
+       {
+               printf ("%s",PR_GlobalString(progfuncs, s->a));
+               printf ("%s", PR_GlobalStringNoContents(progfuncs, s->b));
+       }
+       else
+       {
+               if (s->a)
+                       printf ("%s",PR_GlobalString(progfuncs, s->a));
+               if (s->b)
+                       printf ("%s",PR_GlobalString(progfuncs, s->b));
+               if (s->c)
+                       printf ("%s", PR_GlobalStringNoContents(progfuncs, s->c));
+       }
+       printf ("\n");
+}
+*/
+
+/*
+============
+PR_StackTrace
+============
+*/
+char *QC_ucase(char *str)
+{
+       static char s[1024];
+       strcpy(s, str);
+       str = s;
+
+       while(*str)
+       {
+               if (*str >= 'a' && *str <= 'z')
+                       *str = *str - 'a' + 'A';
+               str++;
+       }
+       return s;
+}
+
+void PR_StackTrace (progfuncs_t *progfuncs)
+{
+       dfunction_t     *f;
+       int                     i;
+       int progs;
+
+#ifdef STACKTRACE
+       int arg;
+       int *globalbase;
+#endif
+       progs = -1;
+       
+       if (pr_depth == 0)
+       {
+               printf ("<NO STACK>\n");
+               return;
+       }
+       
+#ifdef STACKTRACE
+       globalbase = (int *)pr_globals + pr_xfunction->parm_start - pr_xfunction->locals;
+#endif
+
+       pr_stack[pr_depth].f = pr_xfunction;
+       pr_stack[pr_depth].s = pr_xstatement;
+       for (i=pr_depth ; i>0 ; i--)
+       {
+               f = pr_stack[i].f;
+               
+               if (!f)
+               {
+                       printf ("<NO FUNCTION>\n");
+               }
+               else
+               {
+                       if (pr_stack[i].progsnum != progs)
+                       {
+                               progs = pr_stack[i].progsnum;
+
+                               printf ("<%s>\n", pr_progstate[progs].filename);
+                       }
+                       if (!f->s_file)
+                               printf ("stripped     : %s\n", f->s_name+progfuncs->stringtable);
+                       else
+                       {
+                               if (pr_progstate[progs].linenums)
+                                       printf ("%12s %i : %s\n", f->s_file+progfuncs->stringtable, pr_progstate[progs].linenums[pr_stack[i].s], f->s_name+progfuncs->stringtable);
+                               else
+                                       printf ("%12s : %s\n", f->s_file+progfuncs->stringtable, f->s_name+progfuncs->stringtable);
+                       }
+
+#ifdef STACKTRACE
+
+                       for (arg = 0; arg < f->locals; arg++)
+                       {
+                               ddef16_t *local;
+                               local = ED_GlobalAtOfs16(progfuncs, f->parm_start+arg);
+                               if (!local)
+                               {
+                                       printf("    ofs %i: %f : %i\n", f->parm_start+arg, *(float *)(globalbase - f->locals+arg), *(int *)(globalbase - f->locals+arg) );
+                               }
+                               else
+                               {
+                                       printf("    %s: %s\n", local->s_name+progfuncs->stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg)));
+                                       if (local->type == ev_vector)
+                                               arg+=2;
+                               }
+                       }
+
+                       if (i == pr_depth)
+                               globalbase = localstack + localstack_used;
+                       else
+                               globalbase -= f->locals;
+#endif
+               }
+       }
+}
+
+/*
+============
+PR_Profile_f
+
+============
+*/
+/*
+void PR_Profile_f (void)
+{
+       dfunction_t     *f, *best;
+       int                     max;
+       int                     num;
+       unsigned int                    i;
+
+       num = 0;
+       do
+       {
+               max = 0;
+               best = NULL;
+               for (i=0 ; i<pr_progs->numfunctions ; i++)
+               {
+                       f = &pr_functions[i];
+                       if (f->profile > max && f->first_statement >=0)
+                       {
+                               max = f->profile;
+                               best = f;
+                       }
+               }
+               if (best)
+               {
+                       if (num < 10)
+                               printf ("%7i %s\n", best->profile, best->s_name);
+                       num++;
+                       best->profile = 0;
+               }
+       } while (best);
+}
+*/
+
+
+/*
+============
+PR_RunError
+
+Aborts the currently executing function
+============
+*/
+void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...)
+{
+       va_list         argptr;
+       char            string[1024];
+
+       va_start (argptr,error);
+       Q_vsnprintf (string,sizeof(string)-1, error,argptr);
+       va_end (argptr);
+
+//     {
+//             void SV_EndRedirect (void);
+//             SV_EndRedirect();
+//     }
+
+//     PR_PrintStatement (pr_statements + pr_xstatement);
+       PR_StackTrace (progfuncs);
+       printf ("\n");
+
+//editbadfile(pr_strings + pr_xfunction->s_file, -1);
+       
+//     pr_depth = 0;           // dump the stack so host_error can shutdown functions  
+//     prinst->exitdepth = 0;
+
+       Abort ("%s", string);
+}
+
+/*
+============================================================================
+PR_ExecuteProgram
+
+The interpretation main loop
+============================================================================
+*/
+
+/*
+====================
+PR_EnterFunction
+
+Returns the new program statement counter
+====================
+*/
+void   PR_AbortStack                   (progfuncs_t *progfuncs);
+int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum)
+{
+       int             i, j, c, o;
+
+       pr_stack[pr_depth].s = pr_xstatement;
+       pr_stack[pr_depth].f = pr_xfunction;    
+       pr_stack[pr_depth].progsnum = progsnum;
+       pr_stack[pr_depth].pushed = pr_spushed;
+       pr_depth++;
+       if (pr_depth == MAX_STACK_DEPTH)
+       {
+               pr_depth--;
+               PR_StackTrace (progfuncs);
+
+               printf ("stack overflow on call to %s\n", progfuncs->stringtable+f->s_name);
+
+               //comment this out if you want the progs to try to continue anyway (could cause infinate loops)
+               PR_AbortStack(progfuncs);
+               Abort("Stack Overflow in %s\n", progfuncs->stringtable+f->s_name);
+               return pr_xstatement;
+       }
+
+       localstack_used += pr_spushed;  //make sure the call doesn't hurt pushed pointers
+
+// save off any locals that the new function steps on (to a side place, fromwhere they are restored on exit)
+       c = f->locals;
+       if (localstack_used + c > LOCALSTACK_SIZE)
+       {
+               localstack_used -= pr_spushed;
+               pr_depth--;
+               PR_RunError (progfuncs, "PR_ExecuteProgram: locals stack overflow\n");
+       }
+
+       for (i=0 ; i < c ; i++)
+               localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
+       localstack_used += c;
+
+// copy parameters (set initial values)
+       o = f->parm_start;
+       for (i=0 ; i<f->numparms ; i++)
+       {
+               for (j=0 ; j<f->parm_size[i] ; j++)
+               {
+                       ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
+                       o++;
+               }
+       }
+
+       pr_xfunction = f;
+       return f->first_statement - 1;  // offset the s++
+}
+
+/*
+====================
+PR_LeaveFunction
+====================
+*/
+int PR_LeaveFunction (progfuncs_t *progfuncs)
+{
+       int             i, c;
+
+       if (pr_depth <= 0)
+               Sys_Error ("prog stack underflow");
+
+// restore locals from the stack
+       c = pr_xfunction->locals;
+       localstack_used -= c;
+       if (localstack_used < 0)
+               PR_RunError (progfuncs, "PR_ExecuteProgram: locals stack underflow\n");
+
+       for (i=0 ; i < c ; i++)
+               ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
+
+// up stack
+       pr_depth--;
+       PR_MoveParms(progfuncs, pr_stack[pr_depth].progsnum, pr_typecurrent);
+       PR_SwitchProgs(progfuncs, pr_stack[pr_depth].progsnum);
+       pr_xfunction = pr_stack[pr_depth].f;
+       pr_spushed = pr_stack[pr_depth].pushed;
+
+       localstack_used -= pr_spushed;
+       return pr_stack[pr_depth].s;
+}
+
+ddef32_t *ED_FindLocalOrGlobal(progfuncs_t *progfuncs, char *name, eval_t **val)
+{
+       static ddef32_t def;
+       ddef32_t *def32;
+       ddef16_t *def16;
+       int i;
+
+       switch (pr_progstate[pr_typecurrent].intsize)
+       {
+       case 16:
+       case 24:
+               //this gets parms fine, but not locals
+               if (pr_xfunction)
+               for (i = 0; i < pr_xfunction->numparms; i++)
+               {
+                       def16 = ED_GlobalAtOfs16(progfuncs, pr_xfunction->parm_start+i);
+                       if (!def16)
+                               continue;
+                       if (!strcmp(def16->s_name+progfuncs->stringtable, name))
+                       {
+                               *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[pr_xfunction->parm_start+i];
+
+                               //we need something like this for functions that are not the top layer
+       //                      *val = (eval_t *)&localstack[localstack_used-pr_xfunction->numparms*4];
+                               def.ofs = def16->ofs;
+                               def.s_name = def16->s_name;
+                               def.type = def16->type;
+                               return &def;
+                       }
+               }
+               def16 = ED_FindGlobal16(progfuncs, name);
+               if (!def16)
+                       return NULL;
+               def.ofs = def16->ofs;
+               def.type = def16->type;
+               def.s_name = def16->s_name;
+               def32 = &def;
+               break;
+       case 32:
+               //this gets parms fine, but not locals
+               if (pr_xfunction)
+               for (i = 0; i < pr_xfunction->numparms; i++)
+               {
+                       def32 = ED_GlobalAtOfs32(progfuncs, pr_xfunction->parm_start+i);
+                       if (!def32)
+                               continue;
+                       if (!strcmp(def32->s_name+progfuncs->stringtable, name))
+                       {
+                               *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[pr_xfunction->parm_start+i];
+
+                               //we need something like this for functions that are not the top layer
+       //                      *val = (eval_t *)&localstack[localstack_used-pr_xfunction->numparms*4];
+                               return def32;
+                       }
+               }
+               def32 = ED_FindGlobal32(progfuncs, name);
+               if (!def32)
+                       return NULL;
+               break;
+       default:
+               Sys_Error("Bad int size in ED_FindLocalOrGlobal");
+               def32 = NULL;
+       }
+       
+       *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[def32->ofs];
+       return &def;
+}
+
+char *COM_TrimString(char *str)
+{
+       int i;
+       static char buffer[256];
+       while (*str <= ' ' && *str>'\0')
+               str++;
+
+       for (i = 0; i < 255; i++)
+       {
+               if (*str <= ' ')
+                       break;
+               buffer[i] = *str++;
+       }
+       buffer[i] = '\0';
+       return buffer;
+}
+
+char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
+{
+       static char buf[256];
+       char *c, *c2;
+       ddef32_t *def;
+       fdef_t *fdef;
+       eval_t *val;
+       char *assignment;
+       int type;
+       ddef32_t fakedef;
+       eval_t fakeval;
+
+       assignment = strchr(key, '=');
+       if (assignment)
+               *assignment = '\0';
+
+       c = strchr(key, '.');
+       if (c) *c = '\0';
+       def = ED_FindLocalOrGlobal(progfuncs, key, &val);       
+       if (!def)
+       {
+               if (atoi(key))
+               {
+                       def = &fakedef;
+                       def->ofs = 0;
+                       def->type = ev_entity;
+                       val = &fakeval;
+                       val->edict = atoi(key);
+               }
+       }
+       if (c) *c = '.';
+       if (!def)
+       {               
+               return "(Bad string)";
+       }       
+       type = def->type;
+
+       //go through ent vars
+       c = strchr(key, '.');   
+       while(c)
+       {
+               c2 = c+1;
+               c = strchr(c2, '.');
+               type = type &~DEF_SAVEGLOBAL;
+               if (current_progstate->types)
+                       type = current_progstate->types[type].type;
+               if (type != ev_entity)
+                       return "'.' without entity";
+               if (c)*c = '\0';
+               fdef = ED_FindField(progfuncs, COM_TrimString(c2));
+               if (c)*c = '.';
+               if (!fdef)
+                       return "(Bad string)";
+               val = (eval_t *) (((char *)PROG_TO_EDICT(progfuncs, val->_int)->fields) + fdef->ofs*4);         
+               type = fdef->type;
+       }
+       
+       if (assignment)
+       {
+               assignment++;
+               switch (type&~DEF_SAVEGLOBAL)
+               {
+               case ev_string:
+                       *(string_t *)val = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, assignment, 0));
+                       break;
+                       
+               case ev_float:
+                       *(float *)val = (float)atof (assignment);
+                       break;
+
+               case ev_integer:
+                       *(int *)val = atoi (assignment);
+                       break;
+                       
+/*             case ev_vector:
+                       strcpy (string, assignment);
+                       v = string;
+                       w = string;
+                       for (i=0 ; i<3 ; i++)
+                       {
+                               while (*v && *v != ' ')
+                                       v++;
+                               *v = 0;
+                               ((float *)d)[i] = (float)atof (w);
+                               w = v = v+1;
+                       }
+                       break;
+*/
+               case ev_entity:
+                       *(int *)val = EDICT_TO_PROG(progfuncs, EDICT_NUM(progfuncs, atoi (assignment)));
+                       break;
+
+               case ev_field:
+                       fdef = ED_FindField (progfuncs, assignment);
+                       if (!fdef)
+                       {
+                               int l,nl = strlen(assignment);
+                               strcpy(buf, "Can't find field ");
+                               l = strlen(buf);
+                               if (nl > sizeof(buf)-l-2)
+                                       nl = sizeof(buf)-l-2;
+                               memcpy(buf+l, assignment, nl);
+                               assignment[l+nl+0] = '\n';
+                               assignment[l+nl+1] = 0;
+                               return buf;
+                       }
+                       *(int *)val = G_INT(fdef->ofs);
+                       break;
+
+               case ev_function:
+                       {
+                               dfunction_t *func;
+                               int i;
+                               int progsnum = -1;
+                               char *s = assignment;
+                               if (s[0] && s[1] == ':')
+                               {
+                                       progsnum = atoi(s);
+                                       s+=2;
+                               }
+                               else if (s[0] && s[1] && s[2] == ':')
+                               {
+                                       progsnum = atoi(s);
+                                       s+=3;
+                               }
+
+                               func = ED_FindFunction (progfuncs, s, &i, progsnum);
+                               if (!func)
+                               {
+                                       int l,nl = strlen(s);
+
+                                       assignment[-1] = '=';
+
+                                       strcpy(buf, "Can't find field ");
+                                       l = strlen(buf);
+                                       if (nl > sizeof(buf)-l-2)
+                                               nl = sizeof(buf)-l-2;
+                                       memcpy(buf+l, assignment, nl);
+                                       assignment[l+nl+0] = '\n';
+                                       assignment[l+nl+1] = 0;
+                                       return buf;
+                               }
+                               *(func_t *)val = (func - pr_progstate[i].functions) | (i<<24);
+                       }
+                       break;
+
+               default:
+                       break;
+
+               }
+               assignment[-1] = '=';
+       }
+       strcpy(buf, PR_ValueString(progfuncs, type, val));
+
+       return buf;
+}
+
+int debugstatement;
+//int EditorHighlightLine(window_t *wnd, int line);
+void SetExecutionToLine(progfuncs_t *progfuncs, int linenum)
+{
+       int pn = pr_typecurrent;
+       int snum;
+       dfunction_t *f = pr_xfunction;
+
+       switch(current_progstate->intsize)
+       {
+       case 16:
+               for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++) 
+               {
+                       if (pr_statements16[snum].op == OP_DONE)
+                               return;
+               }
+               break;
+       case 24:
+       case 32:
+               for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++) 
+               {
+                       if (pr_statements32[snum].op == OP_DONE)
+                               return;
+               }
+               break;
+       default:
+               Sys_Error("Bad intsize");
+               snum = 0;
+       }
+       debugstatement = snum;
+//     EditorHighlightLine(editwnd, pr_progstate[pn].linenums[snum]);
+}
+
+//0 clear. 1 set, 2 toggle, 3 check
+int PR_ToggleBreakpoint(progfuncs_t *progfuncs, char *filename, int linenum, int flag) //write alternate route to work by function name.
+{
+       int ret=0;
+       unsigned int fl;
+       unsigned int i;
+       int pn = pr_typecurrent;
+       dfunction_t *f;
+       int op;
+
+       for (pn = 0; (unsigned)pn < maxprogs; pn++)
+       {
+               if (!pr_progstate || !pr_progstate[pn].progs)
+                       continue;
+
+               if (linenum)    //linenum is set means to set the breakpoint on a file and line
+               {
+                       if (!pr_progstate[pn].linenums)
+                               continue;
+
+                       for (f = pr_progstate[pn].functions, fl = 0; fl < pr_progstate[pn].progs->numfunctions; f++, fl++)
+                       {
+                               if (!stricmp(f->s_file+progfuncs->stringtable, filename))
+                               {
+                                       for (i = f->first_statement; ; i++)
+                                       {
+                                               if (pr_progstate[pn].linenums[i] >= linenum)
+                                               {
+                                                       fl = pr_progstate[pn].linenums[i];
+                                                       for (; ; i++)
+                                                       {
+                                                               if ((unsigned int)pr_progstate[pn].linenums[i] > fl)
+                                                                       break;
+
+                                                               switch(pr_progstate[pn].intsize)
+                                                               {
+                                                               case 16:
+                                                                       op = ((dstatement16_t*)pr_progstate[pn].statements + i)->op;
+                                                                       break;
+                                                               case 24:
+                                                               case 32:
+                                                                       op = ((dstatement32_t*)pr_progstate[pn].statements + i)->op;
+                                                                       break;
+                                                               default:
+                                                                       Sys_Error("Bad intsize");
+                                                                       op = 0;
+                                                               }
+                                                               switch (flag)
+                                                               {
+                                                               default:
+                                                                       if (op & 0x8000)
+                                                                       {
+                                                                               op &= ~0x8000;
+                                                                               ret = false;
+                                                                               flag = 0;
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               op |= 0x8000;
+                                                                               ret = true;
+                                                                               flag = 1;
+                                                                       }
+                                                                       break;
+                                                               case 0:
+                                                                       op &= ~0x8000;
+                                                                       ret = false;
+                                                                       break;
+                                                               case 1:
+                                                                       op |= 0x8000;
+                                                                       ret = true;
+                                                                       break;
+                                                               case 3:
+                                                                       if (op & 0x8000)
+                                                                               return true;
+                                                               }
+                                                               switch(pr_progstate[pn].intsize)
+                                                               {
+                                                               case 16:
+                                                                       ((dstatement16_t*)pr_progstate[pn].statements + i)->op = op;
+                                                                       break;
+                                                               case 24:
+                                                               case 32:
+                                                                       ((dstatement32_t*)pr_progstate[pn].statements + i)->op = op;
+                                                                       break;
+                                                               default:
+                                                                       Sys_Error("Bad intsize");
+                                                                       op = 0;
+                                                               }                                                       
+                                                       }
+                                                       goto cont;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else    //set the breakpoint on the first statement of the function specified.
+               {
+                       for (f = pr_progstate[pn].functions, fl = 0; fl < pr_progstate[pn].progs->numfunctions; f++, fl++)
+                       {
+                               if (!strcmp(f->s_name+progfuncs->stringtable, filename))
+                               {
+                                       i = f->first_statement;
+                                       switch(pr_progstate[pn].intsize)
+                                       {
+                                       case 16:
+                                               op = ((dstatement16_t*)pr_progstate[pn].statements + i)->op;
+                                               break;
+                                       case 24:
+                                       case 32:
+                                               op = ((dstatement32_t*)pr_progstate[pn].statements + i)->op;
+                                               break;
+                                       default:
+                                               Sys_Error("Bad intsize");
+                                       }
+                                       switch (flag)
+                                       {
+                                       default:
+                                               if (op & 0x8000)
+                                               {
+                                                       op &= ~0x8000;
+                                                       ret = false;
+                                                       flag = 0;
+                                               }
+                                               else
+                                               {
+                                                       op |= 0x8000;
+                                                       ret = true;
+                                                       flag = 1;
+                                               }
+                                               break;
+                                       case 0:
+                                               op &= ~0x8000;
+                                               ret = false;
+                                               break;
+                                       case 1:
+                                               op |= 0x8000;
+                                               ret = true;
+                                               break;
+                                       case 3:
+                                               if (op & 0x8000)
+                                                       return true;
+                                       }
+                                       switch(pr_progstate[pn].intsize)
+                                       {
+                                       case 16:
+                                               ((dstatement16_t*)pr_progstate[pn].statements + i)->op = op;
+                                               break;
+                                       case 24:
+                                       case 32:
+                                               ((dstatement32_t*)pr_progstate[pn].statements + i)->op = op;
+                                               break;
+                                       default:
+                                               Sys_Error("Bad intsize");
+                                       }
+                                       break;
+                               }
+                       }
+               }
+cont:
+               continue;
+       }
+
+       return ret;
+}
+
+int ShowStep(progfuncs_t *progfuncs, int statement)
+{
+//     return statement;
+//     texture realcursortex;
+static int lastline = 0;
+static char *lastfile = 0;
+
+       int pn = pr_typecurrent;
+       int i;
+       dfunction_t *f = pr_xfunction;  
+
+       if (f && pr_progstate[pn].linenums && externs->useeditor)
+       {
+               if (lastline == pr_progstate[pn].linenums[statement] && lastfile == f->s_file+progfuncs->stringtable)
+                       return statement;       //no info/same line as last time
+
+               lastline = pr_progstate[pn].linenums[statement];
+               lastfile = f->s_file+progfuncs->stringtable;
+
+               lastline = externs->useeditor(progfuncs, lastfile, lastline, 0, NULL);
+
+               if (pr_progstate[pn].linenums[statement] != lastline)
+               {
+                       for (i = f->first_statement; ; i++)
+                       {
+                               if (lastline == pr_progstate[pn].linenums[i])
+                               {
+                                       return i;
+                               }
+                               else if (lastline <= pr_progstate[pn].linenums[i])
+                               {
+                                       return statement;
+                               }
+                       }
+               }
+       }
+       else if (f)     //annoying.
+       {
+               if (*(f->s_file+progfuncs->stringtable))        //if we can't get the filename, then it was stripped, and debugging it like this is useless
+                       if (externs->useeditor)
+                               externs->useeditor(progfuncs, f->s_file+progfuncs->stringtable, -1, 0, NULL);
+               return statement;
+       }
+       
+
+       return statement;
+}
+
+//DMW: all pointer functions are modified to be absoloute pointers from NULL not sv_edicts
+/*
+====================
+PR_ExecuteProgram
+====================
+*/
+void PR_ExecuteCode (progfuncs_t *progfuncs, int s)
+{
+       eval_t  *t, *swtch=NULL;
+
+       int swtchtype;
+       dstatement16_t  *st16;
+       dstatement32_t  *st32;
+       dfunction_t     *newf;
+       int             runaway;
+       int             i;
+       int p;
+       edictrun_t      *ed;
+       eval_t  *ptr;
+
+       float *glob;
+
+       int fnum;
+
+       prinst->continuestatement = -1;
+#ifdef QCJIT
+       if (prinst->usejit)
+       {
+               PR_EnterJIT(progfuncs, s);
+               return;
+       }
+#endif
+       fnum = pr_xfunction - pr_functions;
+
+       runaway = 100000000;
+
+#define PRBOUNDSCHECK
+#define RUNAWAYCHECK()                                                 \
+       if (!--runaway)                                                         \
+       {                                                                                       \
+               pr_xstatement = st-pr_statements;               \
+               PR_StackTrace(progfuncs);                               \
+               printf ("runaway loop error");                  \
+               while(pr_depth > prinst->exitdepth)             \
+                       PR_LeaveFunction(progfuncs);            \
+               pr_spushed = 0;                                                 \
+               return;                                                                 \
+       }
+
+#define OPA ((eval_t *)&glob[st->a])
+#define OPB ((eval_t *)&glob[st->b])
+#define OPC ((eval_t *)&glob[st->c])
+
+restart:       //jumped to when the progs might have changed.
+       glob = pr_globals;
+       switch (current_progstate->intsize)
+       {
+       case 16:
+#define INTSIZE 16
+               st16 = &pr_statements16[s];
+               while (pr_trace)
+               {
+                       #define DEBUGABLE
+                       #ifdef SEPARATEINCLUDES
+                               #include "execloop16d.h"
+                       #else
+                               #include "execloop.h"
+                       #endif
+                       #undef DEBUGABLE
+               }
+               
+               while(1)
+               {
+                       #include "execloop.h"
+               }       
+#undef INTSIZE
+               Sys_Error("PR_ExecuteProgram - should be unreachable");
+               break;
+       case 24:
+       case 32:
+#define INTSIZE 32
+               st32 = &pr_statements32[s];
+               while (pr_trace)
+               {
+                       #define DEBUGABLE
+                       #ifdef SEPARATEINCLUDES
+                               #include "execloop32d.h"
+                       #else
+                               #include "execloop.h"
+                       #endif
+                       #undef DEBUGABLE
+               }
+               
+               while(1)
+               {
+                       #ifdef SEPARATEINCLUDES
+                               #include "execloop32.h"
+                       #else
+                               #include "execloop.h"
+                       #endif
+               }
+#undef INTSIZE 
+               Sys_Error("PR_ExecuteProgram - should be unreachable");
+               break;
+       default:
+               Sys_Error("PR_ExecuteProgram - bad intsize");
+       }
+}
+
+
+void PR_ExecuteProgram (progfuncs_t *progfuncs, func_t fnum)
+{
+       dfunction_t     *f;
+       int             i;
+       unsigned int initial_progs;
+       int             oldexitdepth;
+
+       int s;
+
+       int tempdepth;
+
+       unsigned int newprogs = (fnum & 0xff000000)>>24;
+
+       initial_progs = pr_typecurrent;
+       if (newprogs != initial_progs)
+       {
+               if (newprogs >= maxprogs || !&pr_progstate[newprogs].globals)   //can happen with hexen2...
+               {
+                       printf("PR_ExecuteProgram: tried branching into invalid progs\n");
+                       return;
+               }
+               PR_MoveParms(progfuncs, newprogs, pr_typecurrent);
+               PR_SwitchProgs(progfuncs, newprogs);
+       }
+
+       if (!(fnum & ~0xff000000) || (signed)(fnum & ~0xff000000) >= pr_progs->numfunctions)
+       {
+//             if (pr_global_struct->self)
+//                     ED_Print (PROG_TO_EDICT(pr_global_struct->self));
+               printf("PR_ExecuteProgram: NULL function from exe\n");
+//             Host_Error ("PR_ExecuteProgram: NULL function from exe");
+
+//             PR_MoveParms(0, pr_typecurrent);
+               PR_SwitchProgs(progfuncs, initial_progs);
+               return;
+       }
+
+       oldexitdepth = prinst->exitdepth;
+
+       f = &pr_functions[fnum & ~0xff000000];
+
+       if (f->first_statement < 0)
+       {       // negative statements are built in functions
+               i = -f->first_statement;
+
+               if (i < externs->numglobalbuiltins)
+                       (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals);
+               else
+               {
+                       i -= externs->numglobalbuiltins;
+                       if (i > current_progstate->numbuiltins)
+                       {
+                               printf ("Bad builtin call number %i (from exe)\n", -f->first_statement);
+                       //      PR_MoveParms(p, pr_typecurrent);
+                               PR_SwitchProgs(progfuncs, initial_progs);
+                               return;
+                       }
+                       current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals);
+               }
+               PR_MoveParms(progfuncs, initial_progs, pr_typecurrent);
+               PR_SwitchProgs(progfuncs, initial_progs);
+               return;
+       }
+
+       if (pr_trace)
+               pr_trace--;
+
+// 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;
+}
+
+
+
+
+
+
+typedef struct {
+       int fnum;
+       int progsnum;
+       int statement;
+} qcthreadstack_t;
+typedef struct qcthread_s {
+       int fstackdepth;
+       qcthreadstack_t fstack[MAX_STACK_DEPTH];
+       int lstackused;
+       int lstack[LOCALSTACK_SIZE];
+       int xstatement;
+       int xfunction;
+       progsnum_t xprogs;
+} qcthread_t;
+
+struct qcthread_s *PR_ForkStack(progfuncs_t *progfuncs)
+{      //QC code can call builtins that call qc code.
+       //to get around the problems of restoring the builtins we simply don't save the thread over the builtin.
+       int i, l;
+       int ed = prinst->exitdepth;
+       int localsoffset, baselocalsoffset;
+       qcthread_t *thread = memalloc(sizeof(qcthread_t));
+       dfunction_t *f;
+       
+       //copy out the functions stack.
+       for (i = 0,localsoffset=0; i < ed; i++)
+       {
+               if (i+1 == pr_depth)
+                       f = pr_xfunction;
+               else
+                       f = pr_stack[i+1].f;
+               localsoffset += f->locals;      //this is where it crashes
+       }
+       baselocalsoffset = localsoffset;
+       for (i = ed; i < pr_depth; i++)
+       {
+               thread->fstack[i-ed].fnum = pr_stack[i].f - pr_progstate[pr_stack[i].progsnum].functions; 
+               thread->fstack[i-ed].progsnum = pr_stack[i].progsnum;
+               thread->fstack[i-ed].statement = pr_stack[i].s;
+
+               if (i+1 == pr_depth)
+                       f = pr_xfunction;
+               else
+                       f = pr_stack[i+1].f;
+               localsoffset += f->locals;
+       }
+       thread->fstackdepth = pr_depth - ed;
+
+       for (i = pr_depth - 1; i >= ed ; i--)
+       {
+               if (i+1 == pr_depth)
+                       f = pr_xfunction;
+               else
+                       f = pr_stack[i+1].f;
+               localsoffset -= f->locals;
+               for (l = 0; l < f->locals; l++)
+               {
+                       thread->lstack[localsoffset-baselocalsoffset + l ] = ((int *)pr_globals)[f->parm_start + l];
+                       ((int *)pr_globals)[f->parm_start + l] = localstack[localsoffset+l];    //copy the old value into the globals (so the older functions have the correct locals.
+               }
+       }
+
+       for (i = ed; i < pr_depth ; i++)        //we need to get the locals back to how they were.
+       {
+               if (i+1 == pr_depth)
+                       f = pr_xfunction;
+               else
+                       f = pr_stack[i+1].f;
+
+               for (l = 0; l < f->locals; l++)
+               {
+                       ((int *)pr_globals)[f->parm_start + l] = thread->lstack[localsoffset-baselocalsoffset + l];
+               }
+               localsoffset += f->locals;
+       }
+       thread->lstackused = localsoffset - baselocalsoffset;
+
+       thread->xstatement = pr_xstatement;
+       thread->xfunction = pr_xfunction - pr_progstate[pr_typecurrent].functions;
+       thread->xprogs = pr_typecurrent;
+
+       return thread;
+}
+
+void PR_ResumeThread (progfuncs_t *progfuncs, struct qcthread_s *thread)
+{
+       dfunction_t     *f, *oldf;
+       int             i,l,ls;
+       progsnum_t initial_progs;
+       int             oldexitdepth;
+
+       int s;
+       int tempdepth;
+
+       progsnum_t prnum = thread->xprogs;
+       int fnum = thread->xfunction;
+
+       if (localstack_used + thread->lstackused > LOCALSTACK_SIZE)
+               PR_RunError(progfuncs, "Too many locals on resumtion of QC thread\n");
+
+       if (pr_depth + thread->fstackdepth > MAX_STACK_DEPTH)
+               PR_RunError(progfuncs, "Too large stack on resumtion of QC thread\n");
+
+
+       //do progs switching stuff as appropriate. (fteqw only)
+       initial_progs = pr_typecurrent;
+       PR_MoveParms(progfuncs, prnum, pr_typecurrent);
+       PR_SwitchProgs(progfuncs, prnum);
+
+
+       oldexitdepth = prinst->exitdepth;
+       prinst->exitdepth = pr_depth;
+
+       ls = 0;
+       //add on the callstack.
+       for (i = 0; i < thread->fstackdepth; i++)
+       {
+               if (pr_depth == prinst->exitdepth)
+               {
+                       pr_stack[pr_depth].f = pr_xfunction;
+                       pr_stack[pr_depth].s = pr_xstatement;
+                       pr_stack[pr_depth].progsnum = initial_progs;
+               }
+               else
+               {
+                       pr_stack[pr_depth].progsnum = thread->fstack[i].progsnum;
+                       pr_stack[pr_depth].f = pr_progstate[thread->fstack[i].progsnum].functions + thread->fstack[i].fnum; 
+                       pr_stack[pr_depth].s = thread->fstack[i].statement;
+               }
+
+               if (i+1 == thread->fstackdepth)
+                       f = &pr_functions[fnum];
+               else
+                       f = pr_progstate[thread->fstack[i+1].progsnum].functions + thread->fstack[i+1].fnum;
+               for (l = 0; l < f->locals; l++)
+               {
+                       localstack[localstack_used++] = ((int *)pr_globals)[f->parm_start + l];
+                       ((int *)pr_globals)[f->parm_start + l] = thread->lstack[ls++];
+               }
+
+               pr_depth++;
+       }
+
+       if (ls != thread->lstackused)
+               PR_RunError(progfuncs, "Thread stores incorrect locals count\n");
+
+       
+       f = &pr_functions[fnum];
+
+//     thread->lstackused -= f->locals;        //the current function is the odd one out.
+
+       //add on the locals stack
+       memcpy(localstack+localstack_used, thread->lstack, sizeof(int)*thread->lstackused);
+       localstack_used += thread->lstackused;
+
+       //bung the locals of the current function on the stack.
+//     for (i=0 ; i < f->locals ; i++)
+//             ((int *)pr_globals)[f->parm_start + i] = 0xff00ff00;//thread->lstack[thread->lstackused+i];
+
+
+//     PR_EnterFunction (progfuncs, f, initial_progs);
+       oldf = pr_xfunction;
+       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;
+}
+
+void   PR_AbortStack                   (progfuncs_t *progfuncs)
+{
+       while(pr_depth > prinst->exitdepth+1)
+               PR_LeaveFunction(progfuncs);
+       prinst->continuestatement = 0;
+}
+