2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 typedef struct prstack_s
30 #define MAX_STACK_DEPTH 256
31 // stacktrace writes into pr_stack[MAX_STACK_DEPTH]
32 // thus increase the array, so depth wont be overwritten
33 prstack_t pr_stack[MAX_STACK_DEPTH+1];
36 #define LOCALSTACK_SIZE 2048
37 int localstack[LOCALSTACK_SIZE];
42 mfunction_t *pr_xfunction;
137 char *PR_GlobalString (int ofs);
138 char *PR_GlobalStringNoContents (int ofs);
141 //=============================================================================
148 void PR_PrintStatement (dstatement_t *s)
152 if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
154 Con_Printf("%s ", pr_opnames[s->op]);
155 i = strlen(pr_opnames[s->op]);
160 if (s->op == OP_IF || s->op == OP_IFNOT)
161 Con_Printf("%sbranch %i",PR_GlobalString((unsigned short) s->a),s->b);
162 else if (s->op == OP_GOTO)
164 Con_Printf("branch %i",s->a);
166 else if ( (unsigned)(s->op - OP_STORE_F) < 6)
168 Con_Print(PR_GlobalString((unsigned short) s->a));
169 Con_Print(PR_GlobalStringNoContents((unsigned short) s->b));
174 Con_Print(PR_GlobalString((unsigned short) s->a));
176 Con_Print(PR_GlobalString((unsigned short) s->b));
178 Con_Print(PR_GlobalStringNoContents((unsigned short) s->c));
188 void PR_StackTrace (void)
193 pr_stack[pr_depth].s = pr_xstatement;
194 pr_stack[pr_depth].f = pr_xfunction;
195 for (i = pr_depth;i > 0;i--)
200 Con_Print("<NULL FUNCTION>\n");
202 Con_Printf("%12s : %s : statement %i\n", PRVM_GetString(f->s_file), PRVM_GetString(f->s_name), pr_stack[i].s - f->first_statement);
213 void PR_Profile_f (void)
215 mfunction_t *f, *best;
216 int i, num, max/*, howmany*/;
220 Con_Printf("no server running, can't profile\n");
224 Con_Print( "Server Profile:\n[Profile] [BuiltinProfile] [CallCount]\n" );
227 //if (Cmd_Argc() == 2)
228 // howmany = atoi(Cmd_Argv(1));
234 for (i=0 ; i<progs->numfunctions ; i++)
236 f = &prog->functions[i];
237 if (f->profile > max)
246 Con_Printf("%7i %7i %7i %s\n", best->profile, best->builtinsprofile, best->callcount, PRVM_GetString(best->s_name));
249 best->builtinsprofile = 0;
254 void PR_PrintState(void)
259 for (i = -7;i <= 0;i++)
260 if (pr_xstatement + i >= pr_xfunction->first_statement)
261 PR_PrintStatement (pr_statements + pr_xstatement + i);
264 Con_Print("null function executing??\n");
272 Con_Print("QuakeC crash report:\n");
276 // dump the stack so host_error can shutdown functions
282 ============================================================================
285 The interpretation main loop
286 ============================================================================
293 Returns the new program statement counter
296 int PR_EnterFunction (mfunction_t *f)
301 Host_Error ("PR_EnterFunction: NULL function\n");
303 pr_stack[pr_depth].s = pr_xstatement;
304 pr_stack[pr_depth].f = pr_xfunction;
306 if (pr_depth >= MAX_STACK_DEPTH)
307 Host_Error ("stack overflow");
309 // save off any locals that the new function steps on
311 if (localstack_used + c > LOCALSTACK_SIZE)
312 Host_Error ("PRVM_ExecuteProgram: locals stack overflow\n");
314 for (i=0 ; i < c ; i++)
315 localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
316 localstack_used += c;
320 for (i=0 ; i<f->numparms ; i++)
322 for (j=0 ; j<f->parm_size[i] ; j++)
324 ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
330 return f->first_statement - 1; // offset the s++
338 int PR_LeaveFunction (void)
343 Host_Error ("prog stack underflow");
346 Host_Error ("PR_LeaveFunction: NULL function\n");
347 // restore locals from the stack
348 c = pr_xfunction->locals;
349 localstack_used -= c;
350 if (localstack_used < 0)
351 Host_Error ("PRVM_ExecuteProgram: locals stack underflow\n");
353 for (i=0 ; i < c ; i++)
354 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
358 pr_xfunction = pr_stack[pr_depth].f;
359 return pr_stack[pr_depth].s;
362 void PR_ReInitStrings (void);
363 void PR_Execute_ProgsLoaded(void)
368 // reset the string table
377 // LordHavoc: optimized
378 #define OPA ((prvm_eval_t *)&pr_globals[(unsigned short) st->a])
379 #define OPB ((prvm_eval_t *)&pr_globals[(unsigned short) st->b])
380 #define OPC ((prvm_eval_t *)&pr_globals[(unsigned short) st->c])
381 extern cvar_t pr_boundscheck;
382 extern cvar_t pr_traceqc;
383 void PRVM_ExecuteProgram (func_t fnum, const char *errormessage)
386 mfunction_t *f, *newf;
389 int profile, startprofile, cachedpr_trace, exitdepth;
391 if (!fnum || fnum >= (unsigned) progs->numfunctions)
393 if (prog->globals.server->self)
394 ED_Print(PRVM_PROG_TO_EDICT(prog->globals.server->self));
395 Host_Error ("PRVM_ExecuteProgram: %s", errormessage);
398 f = &prog->functions[fnum];
400 pr_trace = pr_traceqc.integer;
402 // we know we're done when pr_depth drops to this
403 exitdepth = pr_depth;
405 // make a stack frame
406 st = &pr_statements[PR_EnterFunction (f)];
407 startprofile = profile = 0;
410 cachedpr_trace = pr_trace;
411 if (pr_boundscheck.integer)
413 #define PRBOUNDSCHECK 1
417 #include "pr_execprogram.h"
422 #include "pr_execprogram.h"
431 #include "pr_execprogram.h"
436 #include "pr_execprogram.h"
441 void PR_ReInitStrings (void)