fixed all the signed/unsigned mismatch warnings
[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_strings + f->s_file, pr_strings + 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_strings+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_Execute_ProgsLoaded(void)
352 {
353         // dump the stack
354         pr_depth = 0;
355         localstack_used = 0;
356 }
357
358 /*
359 ====================
360 PR_ExecuteProgram
361 ====================
362 */
363 // LordHavoc: optimized
364 #define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
365 #define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
366 #define OPC ((eval_t *)&pr_globals[(unsigned short) st->c])
367 extern cvar_t pr_boundscheck;
368 extern cvar_t pr_traceqc;
369 void PR_ExecuteProgram (func_t fnum, const char *errormessage)
370 {
371         dstatement_t    *st;
372         dfunction_t     *f, *newf;
373         edict_t *ed;
374         eval_t  *ptr;
375         int             profile, startprofile, cachedpr_trace, exitdepth;
376
377         if (!fnum || fnum >= progs->numfunctions)
378         {
379                 if (pr_global_struct->self)
380                         ED_Print (PROG_TO_EDICT(pr_global_struct->self));
381                 Host_Error ("PR_ExecuteProgram: %s", errormessage);
382         }
383
384         f = &pr_functions[fnum];
385
386         pr_trace = pr_traceqc.integer;
387
388         // we know we're done when pr_depth drops to this
389         exitdepth = pr_depth;
390
391 // make a stack frame
392         st = &pr_statements[PR_EnterFunction (f)];
393         startprofile = profile = 0;
394
395 chooseexecprogram:
396         cachedpr_trace = pr_trace;
397         if (pr_boundscheck.integer)
398         {
399 #define PRBOUNDSCHECK 1
400                 if (pr_trace)
401                 {
402 #define PRTRACE 1
403 #include "pr_execprogram.h"
404                 }
405                 else
406                 {
407 #undef PRTRACE
408 #include "pr_execprogram.h"
409                 }
410         }
411         else
412         {
413 #undef PRBOUNDSCHECK
414                 if (pr_trace)
415                 {
416 #define PRTRACE 1
417 #include "pr_execprogram.h"
418                 }
419                 else
420                 {
421 #undef PRTRACE
422 #include "pr_execprogram.h"
423                 }
424         }
425 }
426