]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_exec.c
Removed some warnings in MSVC6
[divverent/darkplaces.git] / pr_exec.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.  
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20
21 #include "quakedef.h"
22
23
24 typedef struct
25 {
26         int                             s;
27         dfunction_t             *f;
28 } prstack_t;
29
30 #define MAX_STACK_DEPTH         256
31 prstack_t       pr_stack[MAX_STACK_DEPTH];
32 int                     pr_depth = 0;
33
34 #define LOCALSTACK_SIZE         2048
35 int                     localstack[LOCALSTACK_SIZE];
36 int                     localstack_used;
37
38
39 int                     pr_trace;
40 dfunction_t     *pr_xfunction;
41 int                     pr_xstatement;
42
43
44 int             pr_argc;
45
46 char *pr_opnames[] =
47 {
48 "DONE",
49
50 "MUL_F",
51 "MUL_V", 
52 "MUL_FV",
53 "MUL_VF",
54  
55 "DIV",
56
57 "ADD_F",
58 "ADD_V", 
59   
60 "SUB_F",
61 "SUB_V",
62
63 "EQ_F",
64 "EQ_V",
65 "EQ_S", 
66 "EQ_E",
67 "EQ_FNC",
68  
69 "NE_F",
70 "NE_V", 
71 "NE_S",
72 "NE_E", 
73 "NE_FNC",
74  
75 "LE",
76 "GE",
77 "LT",
78 "GT", 
79
80 "INDIRECT",
81 "INDIRECT",
82 "INDIRECT", 
83 "INDIRECT", 
84 "INDIRECT",
85 "INDIRECT", 
86
87 "ADDRESS", 
88
89 "STORE_F",
90 "STORE_V",
91 "STORE_S",
92 "STORE_ENT",
93 "STORE_FLD",
94 "STORE_FNC",
95
96 "STOREP_F",
97 "STOREP_V",
98 "STOREP_S",
99 "STOREP_ENT",
100 "STOREP_FLD",
101 "STOREP_FNC",
102
103 "RETURN",
104   
105 "NOT_F",
106 "NOT_V",
107 "NOT_S", 
108 "NOT_ENT", 
109 "NOT_FNC", 
110   
111 "IF",
112 "IFNOT",
113   
114 "CALL0",
115 "CALL1",
116 "CALL2",
117 "CALL3",
118 "CALL4",
119 "CALL5",
120 "CALL6",
121 "CALL7",
122 "CALL8",
123   
124 "STATE",
125
126 "GOTO", 
127   
128 "AND",
129 "OR", 
130
131 "BITAND",
132 "BITOR"
133 };
134
135 char *PR_GlobalString (int ofs);
136 char *PR_GlobalStringNoContents (int ofs);
137
138
139 //=============================================================================
140
141 /*
142 =================
143 PR_PrintStatement
144 =================
145 */
146 void PR_PrintStatement (dstatement_t *s)
147 {
148         int             i;
149
150         if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
151         {
152                 Con_Printf ("%s ",  pr_opnames[s->op]);
153                 i = strlen(pr_opnames[s->op]);
154                 for ( ; i<10 ; i++)
155                         Con_Printf (" ");
156         }
157
158         if (s->op == OP_IF || s->op == OP_IFNOT)
159                 Con_Printf ("%sbranch %i",PR_GlobalString((unsigned short) s->a),s->b);
160         else if (s->op == OP_GOTO)
161         {
162                 Con_Printf ("branch %i",s->a);
163         }
164         else if ( (unsigned)(s->op - OP_STORE_F) < 6)
165         {
166                 Con_Printf ("%s", PR_GlobalString((unsigned short) s->a));
167                 Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) s->b));
168         }
169         else
170         {
171                 if (s->a)
172                         Con_Printf ("%s", PR_GlobalString((unsigned short) s->a));
173                 if (s->b)
174                         Con_Printf ("%s", PR_GlobalString((unsigned short) s->b));
175                 if (s->c)
176                         Con_Printf ("%s", PR_GlobalStringNoContents((unsigned short) s->c));
177         }
178         Con_Printf ("\n");
179 }
180
181 /*
182 ============
183 PR_StackTrace
184 ============
185 */
186 void PR_StackTrace (void)
187 {
188         dfunction_t     *f;
189         int                     i;
190
191         pr_stack[pr_depth].s = pr_xstatement;
192         pr_stack[pr_depth].f = pr_xfunction;
193         for (i = pr_depth;i > 0;i--)
194         {
195                 f = pr_stack[i].f;
196
197                 if (!f)
198                         Con_Printf ("<NULL FUNCTION>\n");
199                 else
200                         Con_Printf ("%12s : %s : statement %i\n", PR_GetString(f->s_file), PR_GetString(f->s_name), pr_stack[i].s - f->first_statement);
201         }
202 }
203
204
205 /*
206 ============
207 PR_Profile_f
208
209 ============
210 */
211 void PR_Profile_f (void)
212 {
213         dfunction_t     *f, *best;
214         int                     max;
215         int                     num;
216         int                     i;
217
218         num = 0;
219         do
220         {
221                 max = 0;
222                 best = NULL;
223                 for (i=0 ; i<progs->numfunctions ; i++)
224                 {
225                         f = &pr_functions[i];
226                         if (f->profile > max)
227                         {
228                                 max = f->profile;
229                                 best = f;
230                         }
231                 }
232                 if (best)
233                 {
234                         if (num < 10)
235                                 Con_Printf ("%7i %s\n", best->profile, PR_GetString(best->s_name));
236                         num++;
237                         best->profile = 0;
238                 }
239         } while (best);
240 }
241
242
243 void PR_Crash(void)
244 {
245         int i;
246         if (pr_depth < 1)
247         {
248                 // kill the stack just to be sure
249                 pr_depth = 0;
250                 localstack_used = 0;
251                 return;
252         }
253
254         Con_Printf("QuakeC crash report:\n");
255         if (pr_xfunction)
256         {
257                 for (i = -4;i <= 0;i++)
258                         if (pr_xstatement + i >= pr_xfunction->first_statement)
259                                 PR_PrintStatement (pr_statements + pr_xstatement + i);
260         }
261         else
262                 Con_Printf("null function executing??\n");
263         PR_StackTrace ();
264
265         // dump the stack so host_error can shutdown functions
266         pr_depth = 0;
267         localstack_used = 0;
268 }
269
270 /*
271 ============================================================================
272 PR_ExecuteProgram
273
274 The interpretation main loop
275 ============================================================================
276 */
277
278 /*
279 ====================
280 PR_EnterFunction
281
282 Returns the new program statement counter
283 ====================
284 */
285 int PR_EnterFunction (dfunction_t *f)
286 {
287         int             i, j, c, o;
288
289         if (!f)
290                 Host_Error ("PR_EnterFunction: NULL function\n");
291
292         pr_stack[pr_depth].s = pr_xstatement;
293         pr_stack[pr_depth].f = pr_xfunction;
294         pr_depth++;
295         if (pr_depth >= MAX_STACK_DEPTH)
296                 Host_Error ("stack overflow");
297
298 // save off any locals that the new function steps on
299         c = f->locals;
300         if (localstack_used + c > LOCALSTACK_SIZE)
301                 Host_Error ("PR_ExecuteProgram: locals stack overflow\n");
302
303         for (i=0 ; i < c ; i++)
304                 localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
305         localstack_used += c;
306
307 // copy parameters
308         o = f->parm_start;
309         for (i=0 ; i<f->numparms ; i++)
310         {
311                 for (j=0 ; j<f->parm_size[i] ; j++)
312                 {
313                         ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
314                         o++;
315                 }
316         }
317
318         pr_xfunction = f;
319         return f->first_statement - 1;  // offset the s++
320 }
321
322 /*
323 ====================
324 PR_LeaveFunction
325 ====================
326 */
327 int PR_LeaveFunction (void)
328 {
329         int             i, c;
330
331         if (pr_depth <= 0)
332                 Host_Error ("prog stack underflow");
333
334         if (!pr_xfunction)
335                 Host_Error ("PR_LeaveFunction: NULL function\n");
336 // restore locals from the stack
337         c = pr_xfunction->locals;
338         localstack_used -= c;
339         if (localstack_used < 0)
340                 Host_Error ("PR_ExecuteProgram: locals stack underflow\n");
341
342         for (i=0 ; i < c ; i++)
343                 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
344
345 // up stack
346         pr_depth--;
347         pr_xfunction = pr_stack[pr_depth].f;
348         return pr_stack[pr_depth].s;
349 }
350
351 void PR_ReInitStrings (void);
352 void PR_Execute_ProgsLoaded(void)
353 {
354         // dump the stack
355         pr_depth = 0;
356         localstack_used = 0;
357         // reset the string table
358         PR_ReInitStrings();
359 }
360
361 /*
362 ====================
363 PR_ExecuteProgram
364 ====================
365 */
366 // LordHavoc: optimized
367 #define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
368 #define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
369 #define OPC ((eval_t *)&pr_globals[(unsigned short) st->c])
370 extern cvar_t pr_boundscheck;
371 extern cvar_t pr_traceqc;
372 void PR_ExecuteProgram (func_t fnum, const char *errormessage)
373 {
374         dstatement_t    *st;
375         dfunction_t     *f, *newf;
376         edict_t *ed;
377         eval_t  *ptr;
378         int             profile, startprofile, cachedpr_trace, exitdepth;
379
380         if (!fnum || fnum >= progs->numfunctions)
381         {
382                 if (pr_global_struct->self)
383                         ED_Print (PROG_TO_EDICT(pr_global_struct->self));
384                 Host_Error ("PR_ExecuteProgram: %s", errormessage);
385         }
386
387         f = &pr_functions[fnum];
388
389         pr_trace = pr_traceqc.integer;
390
391         // we know we're done when pr_depth drops to this
392         exitdepth = pr_depth;
393
394 // make a stack frame
395         st = &pr_statements[PR_EnterFunction (f)];
396         startprofile = profile = 0;
397
398 chooseexecprogram:
399         cachedpr_trace = pr_trace;
400         if (pr_boundscheck.integer)
401         {
402 #define PRBOUNDSCHECK 1
403                 if (pr_trace)
404                 {
405 #define PRTRACE 1
406 #include "pr_execprogram.h"
407                 }
408                 else
409                 {
410 #undef PRTRACE
411 #include "pr_execprogram.h"
412                 }
413         }
414         else
415         {
416 #undef PRBOUNDSCHECK
417                 if (pr_trace)
418                 {
419 #define PRTRACE 1
420 #include "pr_execprogram.h"
421                 }
422                 else
423                 {
424 #undef PRTRACE
425 #include "pr_execprogram.h"
426                 }
427         }
428 }
429
430 // LordHavoc: grabbed these from QWSV, works around a gcc 2.95.3 compiler bug
431 #define MAX_PRSTR 1024
432 static char *pr_strtbl[MAX_PRSTR];
433 static int num_prstr;
434
435 char *PR_GetString (int num)
436 {
437         return num >= 0 ? pr_strings + num : pr_strtbl[-num];
438 }
439
440 int PR_SetString (char *s)
441 {
442         if (s >= pr_strings)
443                 return (int) (s - pr_strings);
444         else
445         {
446                 int i;
447                 for (i = 0; i <= num_prstr; i++)
448                         if (pr_strtbl[i] == s)
449                                 return -i;
450                 if (num_prstr >= (MAX_PRSTR - 1))
451                         Host_Error ("PR_Setstring: ran out of string table slots");
452                 pr_strtbl[++num_prstr] = s;
453                 return -num_prstr;
454         }
455 }
456
457 void PR_ReInitStrings (void)
458 {
459         num_prstr = 0;
460 }