]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - misc/mediasource/extra/fteqcc-src/pr_exec.c
Rename the compiled fteqcc to fteqcc-win32 (as that's what it is)
[voretournament/voretournament.git] / misc / mediasource / extra / fteqcc-src / pr_exec.c
1 #define PROGSUSED
2 #include "progsint.h"
3 //#include "editor.h"
4
5 #define HunkAlloc BADGDFG sdfhhsf FHS
6
7
8 #define Host_Error Sys_Error
9
10
11 //=============================================================================
12
13 /*
14 =================
15 PR_PrintStatement
16 =================
17 */
18 /*
19 void PR_PrintStatement (progfuncs_t *progfuncs, dstatement16_t *s)
20 {
21         int             i;
22 printf("PR_PrintStatement is unsupported\n");
23 return;
24         if ( (unsigned)s->op < OP_NUMOPS)
25         {
26                 printf ("%s ",  pr_opcodes[s->op].name);
27                 i = strlen(pr_opcodes[s->op].name);
28                 for ( ; i<10 ; i++)
29                         printf (" ");
30         }
31                 
32         if (s->op == OP_IF || s->op == OP_IFNOT)
33                 printf ("%sbranch %i",PR_GlobalString(progfuncs, s->a),s->b);
34         else if (s->op == OP_GOTO)
35         {
36                 printf ("branch %i",s->a);
37         }
38         else if ( (unsigned)(s->op - OP_STORE_F) < 6)
39         {
40                 printf ("%s",PR_GlobalString(progfuncs, s->a));
41                 printf ("%s", PR_GlobalStringNoContents(progfuncs, s->b));
42         }
43         else
44         {
45                 if (s->a)
46                         printf ("%s",PR_GlobalString(progfuncs, s->a));
47                 if (s->b)
48                         printf ("%s",PR_GlobalString(progfuncs, s->b));
49                 if (s->c)
50                         printf ("%s", PR_GlobalStringNoContents(progfuncs, s->c));
51         }
52         printf ("\n");
53 }
54 */
55
56 /*
57 ============
58 PR_StackTrace
59 ============
60 */
61 char *QC_ucase(char *str)
62 {
63         static char s[1024];
64         strcpy(s, str);
65         str = s;
66
67         while(*str)
68         {
69                 if (*str >= 'a' && *str <= 'z')
70                         *str = *str - 'a' + 'A';
71                 str++;
72         }
73         return s;
74 }
75
76 void PR_StackTrace (progfuncs_t *progfuncs)
77 {
78         dfunction_t     *f;
79         int                     i;
80         int progs;
81
82 #ifdef STACKTRACE
83         int arg;
84         int *globalbase;
85 #endif
86         progs = -1;
87         
88         if (pr_depth == 0)
89         {
90                 printf ("<NO STACK>\n");
91                 return;
92         }
93         
94 #ifdef STACKTRACE
95         globalbase = (int *)pr_globals + pr_xfunction->parm_start - pr_xfunction->locals;
96 #endif
97
98         pr_stack[pr_depth].f = pr_xfunction;
99         pr_stack[pr_depth].s = pr_xstatement;
100         for (i=pr_depth ; i>0 ; i--)
101         {
102                 f = pr_stack[i].f;
103                 
104                 if (!f)
105                 {
106                         printf ("<NO FUNCTION>\n");
107                 }
108                 else
109                 {
110                         if (pr_stack[i].progsnum != progs)
111                         {
112                                 progs = pr_stack[i].progsnum;
113
114                                 printf ("<%s>\n", pr_progstate[progs].filename);
115                         }
116                         if (!f->s_file)
117                                 printf ("stripped     : %s\n", f->s_name+progfuncs->stringtable);
118                         else
119                         {
120                                 if (pr_progstate[progs].linenums)
121                                         printf ("%12s %i : %s\n", f->s_file+progfuncs->stringtable, pr_progstate[progs].linenums[pr_stack[i].s], f->s_name+progfuncs->stringtable);
122                                 else
123                                         printf ("%12s : %s\n", f->s_file+progfuncs->stringtable, f->s_name+progfuncs->stringtable);
124                         }
125
126 #ifdef STACKTRACE
127
128                         for (arg = 0; arg < f->locals; arg++)
129                         {
130                                 ddef16_t *local;
131                                 local = ED_GlobalAtOfs16(progfuncs, f->parm_start+arg);
132                                 if (!local)
133                                 {
134                                         printf("    ofs %i: %f : %i\n", f->parm_start+arg, *(float *)(globalbase - f->locals+arg), *(int *)(globalbase - f->locals+arg) );
135                                 }
136                                 else
137                                 {
138                                         printf("    %s: %s\n", local->s_name+progfuncs->stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg)));
139                                         if (local->type == ev_vector)
140                                                 arg+=2;
141                                 }
142                         }
143
144                         if (i == pr_depth)
145                                 globalbase = localstack + localstack_used;
146                         else
147                                 globalbase -= f->locals;
148 #endif
149                 }
150         }
151 }
152
153 /*
154 ============
155 PR_Profile_f
156
157 ============
158 */
159 /*
160 void PR_Profile_f (void)
161 {
162         dfunction_t     *f, *best;
163         int                     max;
164         int                     num;
165         unsigned int                    i;
166
167         num = 0;
168         do
169         {
170                 max = 0;
171                 best = NULL;
172                 for (i=0 ; i<pr_progs->numfunctions ; i++)
173                 {
174                         f = &pr_functions[i];
175                         if (f->profile > max && f->first_statement >=0)
176                         {
177                                 max = f->profile;
178                                 best = f;
179                         }
180                 }
181                 if (best)
182                 {
183                         if (num < 10)
184                                 printf ("%7i %s\n", best->profile, best->s_name);
185                         num++;
186                         best->profile = 0;
187                 }
188         } while (best);
189 }
190 */
191
192
193 /*
194 ============
195 PR_RunError
196
197 Aborts the currently executing function
198 ============
199 */
200 void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...)
201 {
202         va_list         argptr;
203         char            string[1024];
204
205         va_start (argptr,error);
206         Q_vsnprintf (string,sizeof(string)-1, error,argptr);
207         va_end (argptr);
208
209 //      {
210 //              void SV_EndRedirect (void);
211 //              SV_EndRedirect();
212 //      }
213
214 //      PR_PrintStatement (pr_statements + pr_xstatement);
215         PR_StackTrace (progfuncs);
216         printf ("\n");
217
218 //editbadfile(pr_strings + pr_xfunction->s_file, -1);
219         
220 //      pr_depth = 0;           // dump the stack so host_error can shutdown functions  
221 //      prinst->exitdepth = 0;
222
223         Abort ("%s", string);
224 }
225
226 /*
227 ============================================================================
228 PR_ExecuteProgram
229
230 The interpretation main loop
231 ============================================================================
232 */
233
234 /*
235 ====================
236 PR_EnterFunction
237
238 Returns the new program statement counter
239 ====================
240 */
241 void    PR_AbortStack                   (progfuncs_t *progfuncs);
242 int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum)
243 {
244         int             i, j, c, o;
245
246         pr_stack[pr_depth].s = pr_xstatement;
247         pr_stack[pr_depth].f = pr_xfunction;    
248         pr_stack[pr_depth].progsnum = progsnum;
249         pr_stack[pr_depth].pushed = pr_spushed;
250         pr_depth++;
251         if (pr_depth == MAX_STACK_DEPTH)
252         {
253                 pr_depth--;
254                 PR_StackTrace (progfuncs);
255
256                 printf ("stack overflow on call to %s\n", progfuncs->stringtable+f->s_name);
257
258                 //comment this out if you want the progs to try to continue anyway (could cause infinate loops)
259                 PR_AbortStack(progfuncs);
260                 Abort("Stack Overflow in %s\n", progfuncs->stringtable+f->s_name);
261                 return pr_xstatement;
262         }
263
264         localstack_used += pr_spushed;  //make sure the call doesn't hurt pushed pointers
265
266 // save off any locals that the new function steps on (to a side place, fromwhere they are restored on exit)
267         c = f->locals;
268         if (localstack_used + c > LOCALSTACK_SIZE)
269         {
270                 localstack_used -= pr_spushed;
271                 pr_depth--;
272                 PR_RunError (progfuncs, "PR_ExecuteProgram: locals stack overflow\n");
273         }
274
275         for (i=0 ; i < c ; i++)
276                 localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
277         localstack_used += c;
278
279 // copy parameters (set initial values)
280         o = f->parm_start;
281         for (i=0 ; i<f->numparms ; i++)
282         {
283                 for (j=0 ; j<f->parm_size[i] ; j++)
284                 {
285                         ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
286                         o++;
287                 }
288         }
289
290         pr_xfunction = f;
291         return f->first_statement - 1;  // offset the s++
292 }
293
294 /*
295 ====================
296 PR_LeaveFunction
297 ====================
298 */
299 int PR_LeaveFunction (progfuncs_t *progfuncs)
300 {
301         int             i, c;
302
303         if (pr_depth <= 0)
304                 Sys_Error ("prog stack underflow");
305
306 // restore locals from the stack
307         c = pr_xfunction->locals;
308         localstack_used -= c;
309         if (localstack_used < 0)
310                 PR_RunError (progfuncs, "PR_ExecuteProgram: locals stack underflow\n");
311
312         for (i=0 ; i < c ; i++)
313                 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
314
315 // up stack
316         pr_depth--;
317         PR_MoveParms(progfuncs, pr_stack[pr_depth].progsnum, pr_typecurrent);
318         PR_SwitchProgs(progfuncs, pr_stack[pr_depth].progsnum);
319         pr_xfunction = pr_stack[pr_depth].f;
320         pr_spushed = pr_stack[pr_depth].pushed;
321
322         localstack_used -= pr_spushed;
323         return pr_stack[pr_depth].s;
324 }
325
326 ddef32_t *ED_FindLocalOrGlobal(progfuncs_t *progfuncs, char *name, eval_t **val)
327 {
328         static ddef32_t def;
329         ddef32_t *def32;
330         ddef16_t *def16;
331         int i;
332
333         switch (pr_progstate[pr_typecurrent].intsize)
334         {
335         case 16:
336         case 24:
337                 //this gets parms fine, but not locals
338                 if (pr_xfunction)
339                 for (i = 0; i < pr_xfunction->numparms; i++)
340                 {
341                         def16 = ED_GlobalAtOfs16(progfuncs, pr_xfunction->parm_start+i);
342                         if (!def16)
343                                 continue;
344                         if (!strcmp(def16->s_name+progfuncs->stringtable, name))
345                         {
346                                 *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[pr_xfunction->parm_start+i];
347
348                                 //we need something like this for functions that are not the top layer
349         //                      *val = (eval_t *)&localstack[localstack_used-pr_xfunction->numparms*4];
350                                 def.ofs = def16->ofs;
351                                 def.s_name = def16->s_name;
352                                 def.type = def16->type;
353                                 return &def;
354                         }
355                 }
356                 def16 = ED_FindGlobal16(progfuncs, name);
357                 if (!def16)
358                         return NULL;
359                 def.ofs = def16->ofs;
360                 def.type = def16->type;
361                 def.s_name = def16->s_name;
362                 def32 = &def;
363                 break;
364         case 32:
365                 //this gets parms fine, but not locals
366                 if (pr_xfunction)
367                 for (i = 0; i < pr_xfunction->numparms; i++)
368                 {
369                         def32 = ED_GlobalAtOfs32(progfuncs, pr_xfunction->parm_start+i);
370                         if (!def32)
371                                 continue;
372                         if (!strcmp(def32->s_name+progfuncs->stringtable, name))
373                         {
374                                 *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[pr_xfunction->parm_start+i];
375
376                                 //we need something like this for functions that are not the top layer
377         //                      *val = (eval_t *)&localstack[localstack_used-pr_xfunction->numparms*4];
378                                 return def32;
379                         }
380                 }
381                 def32 = ED_FindGlobal32(progfuncs, name);
382                 if (!def32)
383                         return NULL;
384                 break;
385         default:
386                 Sys_Error("Bad int size in ED_FindLocalOrGlobal");
387                 def32 = NULL;
388         }
389         
390         *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[def32->ofs];
391         return &def;
392 }
393
394 char *COM_TrimString(char *str)
395 {
396         int i;
397         static char buffer[256];
398         while (*str <= ' ' && *str>'\0')
399                 str++;
400
401         for (i = 0; i < 255; i++)
402         {
403                 if (*str <= ' ')
404                         break;
405                 buffer[i] = *str++;
406         }
407         buffer[i] = '\0';
408         return buffer;
409 }
410
411 char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
412 {
413         static char buf[256];
414         char *c, *c2;
415         ddef32_t *def;
416         fdef_t *fdef;
417         eval_t *val;
418         char *assignment;
419         int type;
420         ddef32_t fakedef;
421         eval_t fakeval;
422
423         assignment = strchr(key, '=');
424         if (assignment)
425                 *assignment = '\0';
426
427         c = strchr(key, '.');
428         if (c) *c = '\0';
429         def = ED_FindLocalOrGlobal(progfuncs, key, &val);       
430         if (!def)
431         {
432                 if (atoi(key))
433                 {
434                         def = &fakedef;
435                         def->ofs = 0;
436                         def->type = ev_entity;
437                         val = &fakeval;
438                         val->edict = atoi(key);
439                 }
440         }
441         if (c) *c = '.';
442         if (!def)
443         {               
444                 return "(Bad string)";
445         }       
446         type = def->type;
447
448         //go through ent vars
449         c = strchr(key, '.');   
450         while(c)
451         {
452                 c2 = c+1;
453                 c = strchr(c2, '.');
454                 type = type &~DEF_SAVEGLOBAL;
455                 if (current_progstate->types)
456                         type = current_progstate->types[type].type;
457                 if (type != ev_entity)
458                         return "'.' without entity";
459                 if (c)*c = '\0';
460                 fdef = ED_FindField(progfuncs, COM_TrimString(c2));
461                 if (c)*c = '.';
462                 if (!fdef)
463                         return "(Bad string)";
464                 val = (eval_t *) (((char *)PROG_TO_EDICT(progfuncs, val->_int)->fields) + fdef->ofs*4);         
465                 type = fdef->type;
466         }
467         
468         if (assignment)
469         {
470                 assignment++;
471                 switch (type&~DEF_SAVEGLOBAL)
472                 {
473                 case ev_string:
474                         *(string_t *)val = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, assignment, 0));
475                         break;
476                         
477                 case ev_float:
478                         *(float *)val = (float)atof (assignment);
479                         break;
480
481                 case ev_integer:
482                         *(int *)val = atoi (assignment);
483                         break;
484                         
485 /*              case ev_vector:
486                         strcpy (string, assignment);
487                         v = string;
488                         w = string;
489                         for (i=0 ; i<3 ; i++)
490                         {
491                                 while (*v && *v != ' ')
492                                         v++;
493                                 *v = 0;
494                                 ((float *)d)[i] = (float)atof (w);
495                                 w = v = v+1;
496                         }
497                         break;
498 */
499                 case ev_entity:
500                         *(int *)val = EDICT_TO_PROG(progfuncs, EDICT_NUM(progfuncs, atoi (assignment)));
501                         break;
502
503                 case ev_field:
504                         fdef = ED_FindField (progfuncs, assignment);
505                         if (!fdef)
506                         {
507                                 int l,nl = strlen(assignment);
508                                 strcpy(buf, "Can't find field ");
509                                 l = strlen(buf);
510                                 if (nl > sizeof(buf)-l-2)
511                                         nl = sizeof(buf)-l-2;
512                                 memcpy(buf+l, assignment, nl);
513                                 assignment[l+nl+0] = '\n';
514                                 assignment[l+nl+1] = 0;
515                                 return buf;
516                         }
517                         *(int *)val = G_INT(fdef->ofs);
518                         break;
519
520                 case ev_function:
521                         {
522                                 dfunction_t *func;
523                                 int i;
524                                 int progsnum = -1;
525                                 char *s = assignment;
526                                 if (s[0] && s[1] == ':')
527                                 {
528                                         progsnum = atoi(s);
529                                         s+=2;
530                                 }
531                                 else if (s[0] && s[1] && s[2] == ':')
532                                 {
533                                         progsnum = atoi(s);
534                                         s+=3;
535                                 }
536
537                                 func = ED_FindFunction (progfuncs, s, &i, progsnum);
538                                 if (!func)
539                                 {
540                                         int l,nl = strlen(s);
541
542                                         assignment[-1] = '=';
543
544                                         strcpy(buf, "Can't find field ");
545                                         l = strlen(buf);
546                                         if (nl > sizeof(buf)-l-2)
547                                                 nl = sizeof(buf)-l-2;
548                                         memcpy(buf+l, assignment, nl);
549                                         assignment[l+nl+0] = '\n';
550                                         assignment[l+nl+1] = 0;
551                                         return buf;
552                                 }
553                                 *(func_t *)val = (func - pr_progstate[i].functions) | (i<<24);
554                         }
555                         break;
556
557                 default:
558                         break;
559
560                 }
561                 assignment[-1] = '=';
562         }
563         strcpy(buf, PR_ValueString(progfuncs, type, val));
564
565         return buf;
566 }
567
568 int debugstatement;
569 //int EditorHighlightLine(window_t *wnd, int line);
570 void SetExecutionToLine(progfuncs_t *progfuncs, int linenum)
571 {
572         int pn = pr_typecurrent;
573         int snum;
574         dfunction_t *f = pr_xfunction;
575
576         switch(current_progstate->intsize)
577         {
578         case 16:
579                 for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++) 
580                 {
581                         if (pr_statements16[snum].op == OP_DONE)
582                                 return;
583                 }
584                 break;
585         case 24:
586         case 32:
587                 for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++) 
588                 {
589                         if (pr_statements32[snum].op == OP_DONE)
590                                 return;
591                 }
592                 break;
593         default:
594                 Sys_Error("Bad intsize");
595                 snum = 0;
596         }
597         debugstatement = snum;
598 //      EditorHighlightLine(editwnd, pr_progstate[pn].linenums[snum]);
599 }
600
601 //0 clear. 1 set, 2 toggle, 3 check
602 int PR_ToggleBreakpoint(progfuncs_t *progfuncs, char *filename, int linenum, int flag)  //write alternate route to work by function name.
603 {
604         int ret=0;
605         unsigned int fl;
606         unsigned int i;
607         int pn = pr_typecurrent;
608         dfunction_t *f;
609         int op;
610
611         for (pn = 0; (unsigned)pn < maxprogs; pn++)
612         {
613                 if (!pr_progstate || !pr_progstate[pn].progs)
614                         continue;
615
616                 if (linenum)    //linenum is set means to set the breakpoint on a file and line
617                 {
618                         if (!pr_progstate[pn].linenums)
619                                 continue;
620
621                         for (f = pr_progstate[pn].functions, fl = 0; fl < pr_progstate[pn].progs->numfunctions; f++, fl++)
622                         {
623                                 if (!stricmp(f->s_file+progfuncs->stringtable, filename))
624                                 {
625                                         for (i = f->first_statement; ; i++)
626                                         {
627                                                 if (pr_progstate[pn].linenums[i] >= linenum)
628                                                 {
629                                                         fl = pr_progstate[pn].linenums[i];
630                                                         for (; ; i++)
631                                                         {
632                                                                 if ((unsigned int)pr_progstate[pn].linenums[i] > fl)
633                                                                         break;
634
635                                                                 switch(pr_progstate[pn].intsize)
636                                                                 {
637                                                                 case 16:
638                                                                         op = ((dstatement16_t*)pr_progstate[pn].statements + i)->op;
639                                                                         break;
640                                                                 case 24:
641                                                                 case 32:
642                                                                         op = ((dstatement32_t*)pr_progstate[pn].statements + i)->op;
643                                                                         break;
644                                                                 default:
645                                                                         Sys_Error("Bad intsize");
646                                                                         op = 0;
647                                                                 }
648                                                                 switch (flag)
649                                                                 {
650                                                                 default:
651                                                                         if (op & 0x8000)
652                                                                         {
653                                                                                 op &= ~0x8000;
654                                                                                 ret = false;
655                                                                                 flag = 0;
656                                                                         }
657                                                                         else
658                                                                         {
659                                                                                 op |= 0x8000;
660                                                                                 ret = true;
661                                                                                 flag = 1;
662                                                                         }
663                                                                         break;
664                                                                 case 0:
665                                                                         op &= ~0x8000;
666                                                                         ret = false;
667                                                                         break;
668                                                                 case 1:
669                                                                         op |= 0x8000;
670                                                                         ret = true;
671                                                                         break;
672                                                                 case 3:
673                                                                         if (op & 0x8000)
674                                                                                 return true;
675                                                                 }
676                                                                 switch(pr_progstate[pn].intsize)
677                                                                 {
678                                                                 case 16:
679                                                                         ((dstatement16_t*)pr_progstate[pn].statements + i)->op = op;
680                                                                         break;
681                                                                 case 24:
682                                                                 case 32:
683                                                                         ((dstatement32_t*)pr_progstate[pn].statements + i)->op = op;
684                                                                         break;
685                                                                 default:
686                                                                         Sys_Error("Bad intsize");
687                                                                         op = 0;
688                                                                 }                                                       
689                                                         }
690                                                         goto cont;
691                                                 }
692                                         }
693                                 }
694                         }
695                 }
696                 else    //set the breakpoint on the first statement of the function specified.
697                 {
698                         for (f = pr_progstate[pn].functions, fl = 0; fl < pr_progstate[pn].progs->numfunctions; f++, fl++)
699                         {
700                                 if (!strcmp(f->s_name+progfuncs->stringtable, filename))
701                                 {
702                                         i = f->first_statement;
703                                         switch(pr_progstate[pn].intsize)
704                                         {
705                                         case 16:
706                                                 op = ((dstatement16_t*)pr_progstate[pn].statements + i)->op;
707                                                 break;
708                                         case 24:
709                                         case 32:
710                                                 op = ((dstatement32_t*)pr_progstate[pn].statements + i)->op;
711                                                 break;
712                                         default:
713                                                 Sys_Error("Bad intsize");
714                                         }
715                                         switch (flag)
716                                         {
717                                         default:
718                                                 if (op & 0x8000)
719                                                 {
720                                                         op &= ~0x8000;
721                                                         ret = false;
722                                                         flag = 0;
723                                                 }
724                                                 else
725                                                 {
726                                                         op |= 0x8000;
727                                                         ret = true;
728                                                         flag = 1;
729                                                 }
730                                                 break;
731                                         case 0:
732                                                 op &= ~0x8000;
733                                                 ret = false;
734                                                 break;
735                                         case 1:
736                                                 op |= 0x8000;
737                                                 ret = true;
738                                                 break;
739                                         case 3:
740                                                 if (op & 0x8000)
741                                                         return true;
742                                         }
743                                         switch(pr_progstate[pn].intsize)
744                                         {
745                                         case 16:
746                                                 ((dstatement16_t*)pr_progstate[pn].statements + i)->op = op;
747                                                 break;
748                                         case 24:
749                                         case 32:
750                                                 ((dstatement32_t*)pr_progstate[pn].statements + i)->op = op;
751                                                 break;
752                                         default:
753                                                 Sys_Error("Bad intsize");
754                                         }
755                                         break;
756                                 }
757                         }
758                 }
759 cont:
760                 continue;
761         }
762
763         return ret;
764 }
765
766 int ShowStep(progfuncs_t *progfuncs, int statement)
767 {
768 //      return statement;
769 //      texture realcursortex;
770 static int lastline = 0;
771 static char *lastfile = 0;
772
773         int pn = pr_typecurrent;
774         int i;
775         dfunction_t *f = pr_xfunction;  
776
777         if (f && pr_progstate[pn].linenums && externs->useeditor)
778         {
779                 if (lastline == pr_progstate[pn].linenums[statement] && lastfile == f->s_file+progfuncs->stringtable)
780                         return statement;       //no info/same line as last time
781
782                 lastline = pr_progstate[pn].linenums[statement];
783                 lastfile = f->s_file+progfuncs->stringtable;
784
785                 lastline = externs->useeditor(progfuncs, lastfile, lastline, 0, NULL);
786
787                 if (pr_progstate[pn].linenums[statement] != lastline)
788                 {
789                         for (i = f->first_statement; ; i++)
790                         {
791                                 if (lastline == pr_progstate[pn].linenums[i])
792                                 {
793                                         return i;
794                                 }
795                                 else if (lastline <= pr_progstate[pn].linenums[i])
796                                 {
797                                         return statement;
798                                 }
799                         }
800                 }
801         }
802         else if (f)     //annoying.
803         {
804                 if (*(f->s_file+progfuncs->stringtable))        //if we can't get the filename, then it was stripped, and debugging it like this is useless
805                         if (externs->useeditor)
806                                 externs->useeditor(progfuncs, f->s_file+progfuncs->stringtable, -1, 0, NULL);
807                 return statement;
808         }
809         
810
811         return statement;
812 }
813
814 //DMW: all pointer functions are modified to be absoloute pointers from NULL not sv_edicts
815 /*
816 ====================
817 PR_ExecuteProgram
818 ====================
819 */
820 void PR_ExecuteCode (progfuncs_t *progfuncs, int s)
821 {
822         eval_t  *t, *swtch=NULL;
823
824         int swtchtype;
825         dstatement16_t  *st16;
826         dstatement32_t  *st32;
827         dfunction_t     *newf;
828         int             runaway;
829         int             i;
830         int p;
831         edictrun_t      *ed;
832         eval_t  *ptr;
833
834         float *glob;
835
836         int fnum;
837
838         prinst->continuestatement = -1;
839 #ifdef QCJIT
840         if (prinst->usejit)
841         {
842                 PR_EnterJIT(progfuncs, s);
843                 return;
844         }
845 #endif
846         fnum = pr_xfunction - pr_functions;
847
848         runaway = 100000000;
849
850 #define PRBOUNDSCHECK
851 #define RUNAWAYCHECK()                                                  \
852         if (!--runaway)                                                         \
853         {                                                                                       \
854                 pr_xstatement = st-pr_statements;               \
855                 PR_StackTrace(progfuncs);                               \
856                 printf ("runaway loop error");                  \
857                 while(pr_depth > prinst->exitdepth)             \
858                         PR_LeaveFunction(progfuncs);            \
859                 pr_spushed = 0;                                                 \
860                 return;                                                                 \
861         }
862
863 #define OPA ((eval_t *)&glob[st->a])
864 #define OPB ((eval_t *)&glob[st->b])
865 #define OPC ((eval_t *)&glob[st->c])
866
867 restart:        //jumped to when the progs might have changed.
868         glob = pr_globals;
869         switch (current_progstate->intsize)
870         {
871         case 16:
872 #define INTSIZE 16
873                 st16 = &pr_statements16[s];
874                 while (pr_trace)
875                 {
876                         #define DEBUGABLE
877                         #ifdef SEPARATEINCLUDES
878                                 #include "execloop16d.h"
879                         #else
880                                 #include "execloop.h"
881                         #endif
882                         #undef DEBUGABLE
883                 }
884                 
885                 while(1)
886                 {
887                         #include "execloop.h"
888                 }       
889 #undef INTSIZE
890                 Sys_Error("PR_ExecuteProgram - should be unreachable");
891                 break;
892         case 24:
893         case 32:
894 #define INTSIZE 32
895                 st32 = &pr_statements32[s];
896                 while (pr_trace)
897                 {
898                         #define DEBUGABLE
899                         #ifdef SEPARATEINCLUDES
900                                 #include "execloop32d.h"
901                         #else
902                                 #include "execloop.h"
903                         #endif
904                         #undef DEBUGABLE
905                 }
906                 
907                 while(1)
908                 {
909                         #ifdef SEPARATEINCLUDES
910                                 #include "execloop32.h"
911                         #else
912                                 #include "execloop.h"
913                         #endif
914                 }
915 #undef INTSIZE  
916                 Sys_Error("PR_ExecuteProgram - should be unreachable");
917                 break;
918         default:
919                 Sys_Error("PR_ExecuteProgram - bad intsize");
920         }
921 }
922
923
924 void PR_ExecuteProgram (progfuncs_t *progfuncs, func_t fnum)
925 {
926         dfunction_t     *f;
927         int             i;
928         unsigned int initial_progs;
929         int             oldexitdepth;
930
931         int s;
932
933         int tempdepth;
934
935         unsigned int newprogs = (fnum & 0xff000000)>>24;
936
937         initial_progs = pr_typecurrent;
938         if (newprogs != initial_progs)
939         {
940                 if (newprogs >= maxprogs || !&pr_progstate[newprogs].globals)   //can happen with hexen2...
941                 {
942                         printf("PR_ExecuteProgram: tried branching into invalid progs\n");
943                         return;
944                 }
945                 PR_MoveParms(progfuncs, newprogs, pr_typecurrent);
946                 PR_SwitchProgs(progfuncs, newprogs);
947         }
948
949         if (!(fnum & ~0xff000000) || (signed)(fnum & ~0xff000000) >= pr_progs->numfunctions)
950         {
951 //              if (pr_global_struct->self)
952 //                      ED_Print (PROG_TO_EDICT(pr_global_struct->self));
953                 printf("PR_ExecuteProgram: NULL function from exe\n");
954 //              Host_Error ("PR_ExecuteProgram: NULL function from exe");
955
956 //              PR_MoveParms(0, pr_typecurrent);
957                 PR_SwitchProgs(progfuncs, initial_progs);
958                 return;
959         }
960
961         oldexitdepth = prinst->exitdepth;
962
963         f = &pr_functions[fnum & ~0xff000000];
964
965         if (f->first_statement < 0)
966         {       // negative statements are built in functions
967                 i = -f->first_statement;
968
969                 if (i < externs->numglobalbuiltins)
970                         (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals);
971                 else
972                 {
973                         i -= externs->numglobalbuiltins;
974                         if (i > current_progstate->numbuiltins)
975                         {
976                                 printf ("Bad builtin call number %i (from exe)\n", -f->first_statement);
977                         //      PR_MoveParms(p, pr_typecurrent);
978                                 PR_SwitchProgs(progfuncs, initial_progs);
979                                 return;
980                         }
981                         current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals);
982                 }
983                 PR_MoveParms(progfuncs, initial_progs, pr_typecurrent);
984                 PR_SwitchProgs(progfuncs, initial_progs);
985                 return;
986         }
987
988         if (pr_trace)
989                 pr_trace--;
990
991 // make a stack frame
992         prinst->exitdepth = pr_depth;
993
994
995         s = PR_EnterFunction (progfuncs, f, initial_progs);
996
997         tempdepth = prinst->numtempstringsstack;
998         PR_ExecuteCode(progfuncs, s);
999
1000
1001         PR_MoveParms(progfuncs, initial_progs, pr_typecurrent);
1002         PR_SwitchProgs(progfuncs, initial_progs);
1003
1004         PR_FreeTemps(progfuncs, tempdepth);
1005         prinst->numtempstringsstack = tempdepth;
1006
1007         prinst->exitdepth = oldexitdepth;
1008 }
1009
1010
1011
1012
1013
1014
1015 typedef struct {
1016         int fnum;
1017         int progsnum;
1018         int statement;
1019 } qcthreadstack_t;
1020 typedef struct qcthread_s {
1021         int fstackdepth;
1022         qcthreadstack_t fstack[MAX_STACK_DEPTH];
1023         int lstackused;
1024         int lstack[LOCALSTACK_SIZE];
1025         int xstatement;
1026         int xfunction;
1027         progsnum_t xprogs;
1028 } qcthread_t;
1029
1030 struct qcthread_s *PR_ForkStack(progfuncs_t *progfuncs)
1031 {       //QC code can call builtins that call qc code.
1032         //to get around the problems of restoring the builtins we simply don't save the thread over the builtin.
1033         int i, l;
1034         int ed = prinst->exitdepth;
1035         int localsoffset, baselocalsoffset;
1036         qcthread_t *thread = memalloc(sizeof(qcthread_t));
1037         dfunction_t *f;
1038         
1039         //copy out the functions stack.
1040         for (i = 0,localsoffset=0; i < ed; i++)
1041         {
1042                 if (i+1 == pr_depth)
1043                         f = pr_xfunction;
1044                 else
1045                         f = pr_stack[i+1].f;
1046                 localsoffset += f->locals;      //this is where it crashes
1047         }
1048         baselocalsoffset = localsoffset;
1049         for (i = ed; i < pr_depth; i++)
1050         {
1051                 thread->fstack[i-ed].fnum = pr_stack[i].f - pr_progstate[pr_stack[i].progsnum].functions; 
1052                 thread->fstack[i-ed].progsnum = pr_stack[i].progsnum;
1053                 thread->fstack[i-ed].statement = pr_stack[i].s;
1054
1055                 if (i+1 == pr_depth)
1056                         f = pr_xfunction;
1057                 else
1058                         f = pr_stack[i+1].f;
1059                 localsoffset += f->locals;
1060         }
1061         thread->fstackdepth = pr_depth - ed;
1062
1063         for (i = pr_depth - 1; i >= ed ; i--)
1064         {
1065                 if (i+1 == pr_depth)
1066                         f = pr_xfunction;
1067                 else
1068                         f = pr_stack[i+1].f;
1069                 localsoffset -= f->locals;
1070                 for (l = 0; l < f->locals; l++)
1071                 {
1072                         thread->lstack[localsoffset-baselocalsoffset + l ] = ((int *)pr_globals)[f->parm_start + l];
1073                         ((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.
1074                 }
1075         }
1076
1077         for (i = ed; i < pr_depth ; i++)        //we need to get the locals back to how they were.
1078         {
1079                 if (i+1 == pr_depth)
1080                         f = pr_xfunction;
1081                 else
1082                         f = pr_stack[i+1].f;
1083
1084                 for (l = 0; l < f->locals; l++)
1085                 {
1086                         ((int *)pr_globals)[f->parm_start + l] = thread->lstack[localsoffset-baselocalsoffset + l];
1087                 }
1088                 localsoffset += f->locals;
1089         }
1090         thread->lstackused = localsoffset - baselocalsoffset;
1091
1092         thread->xstatement = pr_xstatement;
1093         thread->xfunction = pr_xfunction - pr_progstate[pr_typecurrent].functions;
1094         thread->xprogs = pr_typecurrent;
1095
1096         return thread;
1097 }
1098
1099 void PR_ResumeThread (progfuncs_t *progfuncs, struct qcthread_s *thread)
1100 {
1101         dfunction_t     *f, *oldf;
1102         int             i,l,ls;
1103         progsnum_t initial_progs;
1104         int             oldexitdepth;
1105
1106         int s;
1107         int tempdepth;
1108
1109         progsnum_t prnum = thread->xprogs;
1110         int fnum = thread->xfunction;
1111
1112         if (localstack_used + thread->lstackused > LOCALSTACK_SIZE)
1113                 PR_RunError(progfuncs, "Too many locals on resumtion of QC thread\n");
1114
1115         if (pr_depth + thread->fstackdepth > MAX_STACK_DEPTH)
1116                 PR_RunError(progfuncs, "Too large stack on resumtion of QC thread\n");
1117
1118
1119         //do progs switching stuff as appropriate. (fteqw only)
1120         initial_progs = pr_typecurrent;
1121         PR_MoveParms(progfuncs, prnum, pr_typecurrent);
1122         PR_SwitchProgs(progfuncs, prnum);
1123
1124
1125         oldexitdepth = prinst->exitdepth;
1126         prinst->exitdepth = pr_depth;
1127
1128         ls = 0;
1129         //add on the callstack.
1130         for (i = 0; i < thread->fstackdepth; i++)
1131         {
1132                 if (pr_depth == prinst->exitdepth)
1133                 {
1134                         pr_stack[pr_depth].f = pr_xfunction;
1135                         pr_stack[pr_depth].s = pr_xstatement;
1136                         pr_stack[pr_depth].progsnum = initial_progs;
1137                 }
1138                 else
1139                 {
1140                         pr_stack[pr_depth].progsnum = thread->fstack[i].progsnum;
1141                         pr_stack[pr_depth].f = pr_progstate[thread->fstack[i].progsnum].functions + thread->fstack[i].fnum; 
1142                         pr_stack[pr_depth].s = thread->fstack[i].statement;
1143                 }
1144
1145                 if (i+1 == thread->fstackdepth)
1146                         f = &pr_functions[fnum];
1147                 else
1148                         f = pr_progstate[thread->fstack[i+1].progsnum].functions + thread->fstack[i+1].fnum;
1149                 for (l = 0; l < f->locals; l++)
1150                 {
1151                         localstack[localstack_used++] = ((int *)pr_globals)[f->parm_start + l];
1152                         ((int *)pr_globals)[f->parm_start + l] = thread->lstack[ls++];
1153                 }
1154
1155                 pr_depth++;
1156         }
1157
1158         if (ls != thread->lstackused)
1159                 PR_RunError(progfuncs, "Thread stores incorrect locals count\n");
1160
1161         
1162         f = &pr_functions[fnum];
1163
1164 //      thread->lstackused -= f->locals;        //the current function is the odd one out.
1165
1166         //add on the locals stack
1167         memcpy(localstack+localstack_used, thread->lstack, sizeof(int)*thread->lstackused);
1168         localstack_used += thread->lstackused;
1169
1170         //bung the locals of the current function on the stack.
1171 //      for (i=0 ; i < f->locals ; i++)
1172 //              ((int *)pr_globals)[f->parm_start + i] = 0xff00ff00;//thread->lstack[thread->lstackused+i];
1173
1174
1175 //      PR_EnterFunction (progfuncs, f, initial_progs);
1176         oldf = pr_xfunction;
1177         pr_xfunction = f;
1178         s = thread->xstatement;
1179
1180         tempdepth = prinst->numtempstringsstack;
1181         PR_ExecuteCode(progfuncs, s);
1182
1183
1184         PR_MoveParms(progfuncs, initial_progs, pr_typecurrent);
1185         PR_SwitchProgs(progfuncs, initial_progs);
1186         PR_FreeTemps(progfuncs, tempdepth);
1187         prinst->numtempstringsstack = tempdepth;
1188
1189         prinst->exitdepth = oldexitdepth;
1190         pr_xfunction = oldf;
1191 }
1192
1193 void    PR_AbortStack                   (progfuncs_t *progfuncs)
1194 {
1195         while(pr_depth > prinst->exitdepth+1)
1196                 PR_LeaveFunction(progfuncs);
1197         prinst->continuestatement = 0;
1198 }
1199