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 "qwsvdef.h"
22
23
24 /*
25
26 */
27
28 typedef struct
29 {
30 int s;
31 dfunction_t *f;
32 } prstack_t;
33
34 #define MAX_STACK_DEPTH 32
35 prstack_t pr_stack[MAX_STACK_DEPTH];
36 int pr_depth;
37
38 #define LOCALSTACK_SIZE 2048
39 int localstack[LOCALSTACK_SIZE];
40 int localstack_used;
41
42
43 qboolean pr_trace;
44 dfunction_t *pr_xfunction;
45 int pr_xstatement;
46
47
48 int pr_argc;
49
50 char *pr_opnames[] =
51 {
52 "DONE",
53
54 "MUL_F",
55 "MUL_V",
56 "MUL_FV",
57 "MUL_VF",
58
59 "DIV",
60
61 "ADD_F",
62 "ADD_V",
63
64 "SUB_F",
65 "SUB_V",
66
67 "EQ_F",
68 "EQ_V",
69 "EQ_S",
70 "EQ_E",
71 "EQ_FNC",
72
73 "NE_F",
74 "NE_V",
75 "NE_S",
76 "NE_E",
77 "NE_FNC",
78
79 "LE",
80 "GE",
81 "LT",
82 "GT",
83
84 "INDIRECT",
85 "INDIRECT",
86 "INDIRECT",
87 "INDIRECT",
88 "INDIRECT",
89 "INDIRECT",
90
91 "ADDRESS",
92
93 "STORE_F",
94 "STORE_V",
95 "STORE_S",
96 "STORE_ENT",
97 "STORE_FLD",
98 "STORE_FNC",
99
100 "STOREP_F",
101 "STOREP_V",
102 "STOREP_S",
103 "STOREP_ENT",
104 "STOREP_FLD",
105 "STOREP_FNC",
106
107 "RETURN",
108
109 "NOT_F",
110 "NOT_V",
111 "NOT_S",
112 "NOT_ENT",
113 "NOT_FNC",
114
115 "IF",
116 "IFNOT",
117
118 "CALL0",
119 "CALL1",
120 "CALL2",
121 "CALL3",
122 "CALL4",
123 "CALL5",
124 "CALL6",
125 "CALL7",
126 "CALL8",
127
128 "STATE",
129
130 "GOTO",
131
132 "AND",
133 "OR",
134
135 "BITAND",
136 "BITOR"
137 };
138
139 char *PR_GlobalString (int ofs);
140 char *PR_GlobalStringNoContents (int ofs);
141
142
143 //=============================================================================
144
145 /*
146 =================
147 PR_PrintStatement
148 =================
149 */
PR_PrintStatement(dstatement_t * s)150 void PR_PrintStatement (dstatement_t *s)
151 {
152 int i;
153
154 if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
155 {
156 Con_Printf ("%s ", pr_opnames[s->op]);
157 i = strlen(pr_opnames[s->op]);
158 for ( ; i<10 ; i++)
159 Con_Printf (" ");
160 }
161
162 if (s->op == OP_IF || s->op == OP_IFNOT)
163 Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
164 else if (s->op == OP_GOTO)
165 {
166 Con_Printf ("branch %i",s->a);
167 }
168 else if ( (unsigned)(s->op - OP_STORE_F) < 6)
169 {
170 Con_Printf ("%s",PR_GlobalString(s->a));
171 Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
172 }
173 else
174 {
175 if (s->a)
176 Con_Printf ("%s",PR_GlobalString(s->a));
177 if (s->b)
178 Con_Printf ("%s",PR_GlobalString(s->b));
179 if (s->c)
180 Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
181 }
182 Con_Printf ("\n");
183 }
184
185 /*
186 ============
187 PR_StackTrace
188 ============
189 */
PR_StackTrace(void)190 void PR_StackTrace (void)
191 {
192 dfunction_t *f;
193 int i;
194
195 if (pr_depth == 0)
196 {
197 Con_Printf ("<NO STACK>\n");
198 return;
199 }
200
201 pr_stack[pr_depth].f = pr_xfunction;
202 for (i=pr_depth ; i>=0 ; i--)
203 {
204 f = pr_stack[i].f;
205
206 if (!f)
207 {
208 Con_Printf ("<NO FUNCTION>\n");
209 }
210 else
211 Con_Printf ("%12s : %s\n", PR_GetString(f->s_file), PR_GetString(f->s_name));
212 }
213 }
214
215
216 /*
217 ============
218 PR_Profile_f
219
220 ============
221 */
PR_Profile_f(void)222 void PR_Profile_f (void)
223 {
224 dfunction_t *f, *best;
225 int max;
226 int num;
227 int i;
228
229 num = 0;
230 do
231 {
232 max = 0;
233 best = NULL;
234 for (i=0 ; i<progs->numfunctions ; i++)
235 {
236 f = &pr_functions[i];
237 if (f->profile > max)
238 {
239 max = f->profile;
240 best = f;
241 }
242 }
243 if (best)
244 {
245 if (num < 10)
246 Con_Printf ("%7i %s\n", best->profile, PR_GetString(best->s_name));
247 num++;
248 best->profile = 0;
249 }
250 } while (best);
251 }
252
253
254 /*
255 ============
256 PR_RunError
257
258 Aborts the currently executing function
259 ============
260 */
PR_RunError(char * error,...)261 void PR_RunError (char *error, ...)
262 {
263 va_list argptr;
264 char string[1024];
265
266 va_start (argptr,error);
267 vsprintf (string,error,argptr);
268 va_end (argptr);
269
270 PR_PrintStatement (pr_statements + pr_xstatement);
271 PR_StackTrace ();
272 Con_Printf ("%s\n", string);
273
274 pr_depth = 0; // dump the stack so SV_Error can shutdown functions
275
276 SV_Error ("Program error");
277 }
278
279 /*
280 ============================================================================
281 PR_ExecuteProgram
282
283 The interpretation main loop
284 ============================================================================
285 */
286
287 /*
288 ====================
289 PR_EnterFunction
290
291 Returns the new program statement counter
292 ====================
293 */
PR_EnterFunction(dfunction_t * f)294 int PR_EnterFunction (dfunction_t *f)
295 {
296 int i, j, c, o;
297
298 pr_stack[pr_depth].s = pr_xstatement;
299 pr_stack[pr_depth].f = pr_xfunction;
300 pr_depth++;
301 if (pr_depth >= MAX_STACK_DEPTH)
302 PR_RunError ("stack overflow");
303
304 // save off any locals that the new function steps on
305 c = f->locals;
306 if (localstack_used + c > LOCALSTACK_SIZE)
307 PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
308
309 for (i=0 ; i < c ; i++)
310 localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
311 localstack_used += c;
312
313 // copy parameters
314 o = f->parm_start;
315 for (i=0 ; i<f->numparms ; i++)
316 {
317 for (j=0 ; j<f->parm_size[i] ; j++)
318 {
319 ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
320 o++;
321 }
322 }
323
324 pr_xfunction = f;
325 return f->first_statement - 1; // offset the s++
326 }
327
328 /*
329 ====================
330 PR_LeaveFunction
331 ====================
332 */
PR_LeaveFunction(void)333 int PR_LeaveFunction (void)
334 {
335 int i, c;
336
337 if (pr_depth <= 0)
338 SV_Error ("prog stack underflow");
339
340 // restore locals from the stack
341 c = pr_xfunction->locals;
342 localstack_used -= c;
343 if (localstack_used < 0)
344 PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
345
346 for (i=0 ; i < c ; i++)
347 ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
348
349 // up stack
350 pr_depth--;
351 pr_xfunction = pr_stack[pr_depth].f;
352 return pr_stack[pr_depth].s;
353 }
354
355
356 /*
357 ====================
358 PR_ExecuteProgram
359 ====================
360 */
PR_ExecuteProgram(func_t fnum)361 void PR_ExecuteProgram (func_t fnum)
362 {
363 eval_t *a, *b, *c;
364 int s;
365 dstatement_t *st;
366 dfunction_t *f, *newf;
367 int runaway;
368 int i;
369 edict_t *ed;
370 int exitdepth;
371 eval_t *ptr;
372
373 if (!fnum || fnum >= progs->numfunctions)
374 {
375 if (pr_global_struct->self)
376 ED_Print (PROG_TO_EDICT(pr_global_struct->self));
377 SV_Error ("PR_ExecuteProgram: NULL function");
378 }
379
380 f = &pr_functions[fnum];
381
382 runaway = 100000;
383 pr_trace = false;
384
385 // make a stack frame
386 exitdepth = pr_depth;
387
388 s = PR_EnterFunction (f);
389
390 while (1)
391 {
392 s++; // next statement
393
394 st = &pr_statements[s];
395 a = (eval_t *)&pr_globals[st->a];
396 b = (eval_t *)&pr_globals[st->b];
397 c = (eval_t *)&pr_globals[st->c];
398
399 if (--runaway == 0)
400 PR_RunError ("runaway loop error");
401
402 pr_xfunction->profile++;
403 pr_xstatement = s;
404
405 if (pr_trace)
406 PR_PrintStatement (st);
407
408 switch (st->op)
409 {
410 case OP_ADD_F:
411 c->_float = a->_float + b->_float;
412 break;
413 case OP_ADD_V:
414 c->vector[0] = a->vector[0] + b->vector[0];
415 c->vector[1] = a->vector[1] + b->vector[1];
416 c->vector[2] = a->vector[2] + b->vector[2];
417 break;
418
419 case OP_SUB_F:
420 c->_float = a->_float - b->_float;
421 break;
422 case OP_SUB_V:
423 c->vector[0] = a->vector[0] - b->vector[0];
424 c->vector[1] = a->vector[1] - b->vector[1];
425 c->vector[2] = a->vector[2] - b->vector[2];
426 break;
427
428 case OP_MUL_F:
429 c->_float = a->_float * b->_float;
430 break;
431 case OP_MUL_V:
432 c->_float = a->vector[0]*b->vector[0]
433 + a->vector[1]*b->vector[1]
434 + a->vector[2]*b->vector[2];
435 break;
436 case OP_MUL_FV:
437 c->vector[0] = a->_float * b->vector[0];
438 c->vector[1] = a->_float * b->vector[1];
439 c->vector[2] = a->_float * b->vector[2];
440 break;
441 case OP_MUL_VF:
442 c->vector[0] = b->_float * a->vector[0];
443 c->vector[1] = b->_float * a->vector[1];
444 c->vector[2] = b->_float * a->vector[2];
445 break;
446
447 case OP_DIV_F:
448 c->_float = a->_float / b->_float;
449 break;
450
451 case OP_BITAND:
452 c->_float = (int)a->_float & (int)b->_float;
453 break;
454
455 case OP_BITOR:
456 c->_float = (int)a->_float | (int)b->_float;
457 break;
458
459
460 case OP_GE:
461 c->_float = a->_float >= b->_float;
462 break;
463 case OP_LE:
464 c->_float = a->_float <= b->_float;
465 break;
466 case OP_GT:
467 c->_float = a->_float > b->_float;
468 break;
469 case OP_LT:
470 c->_float = a->_float < b->_float;
471 break;
472 case OP_AND:
473 c->_float = a->_float && b->_float;
474 break;
475 case OP_OR:
476 c->_float = a->_float || b->_float;
477 break;
478
479 case OP_NOT_F:
480 c->_float = !a->_float;
481 break;
482 case OP_NOT_V:
483 c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
484 break;
485 case OP_NOT_S:
486 c->_float = !a->string || !*PR_GetString(a->string);
487 break;
488 case OP_NOT_FNC:
489 c->_float = !a->function;
490 break;
491 case OP_NOT_ENT:
492 c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
493 break;
494
495 case OP_EQ_F:
496 c->_float = a->_float == b->_float;
497 break;
498 case OP_EQ_V:
499 c->_float = (a->vector[0] == b->vector[0]) &&
500 (a->vector[1] == b->vector[1]) &&
501 (a->vector[2] == b->vector[2]);
502 break;
503 case OP_EQ_S:
504 c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string));
505 break;
506 case OP_EQ_E:
507 c->_float = a->_int == b->_int;
508 break;
509 case OP_EQ_FNC:
510 c->_float = a->function == b->function;
511 break;
512
513
514 case OP_NE_F:
515 c->_float = a->_float != b->_float;
516 break;
517 case OP_NE_V:
518 c->_float = (a->vector[0] != b->vector[0]) ||
519 (a->vector[1] != b->vector[1]) ||
520 (a->vector[2] != b->vector[2]);
521 break;
522 case OP_NE_S:
523 c->_float = strcmp(PR_GetString(a->string), PR_GetString(b->string));
524 break;
525 case OP_NE_E:
526 c->_float = a->_int != b->_int;
527 break;
528 case OP_NE_FNC:
529 c->_float = a->function != b->function;
530 break;
531
532 //==================
533 case OP_STORE_F:
534 case OP_STORE_ENT:
535 case OP_STORE_FLD: // integers
536 case OP_STORE_S:
537 case OP_STORE_FNC: // pointers
538 b->_int = a->_int;
539 break;
540 case OP_STORE_V:
541 b->vector[0] = a->vector[0];
542 b->vector[1] = a->vector[1];
543 b->vector[2] = a->vector[2];
544 break;
545
546 case OP_STOREP_F:
547 case OP_STOREP_ENT:
548 case OP_STOREP_FLD: // integers
549 case OP_STOREP_S:
550 case OP_STOREP_FNC: // pointers
551 ptr = (eval_t *)((byte *)sv.edicts + b->_int);
552 ptr->_int = a->_int;
553 break;
554 case OP_STOREP_V:
555 ptr = (eval_t *)((byte *)sv.edicts + b->_int);
556 ptr->vector[0] = a->vector[0];
557 ptr->vector[1] = a->vector[1];
558 ptr->vector[2] = a->vector[2];
559 break;
560
561 case OP_ADDRESS:
562 ed = PROG_TO_EDICT(a->edict);
563 #ifdef PARANOID
564 NUM_FOR_EDICT(ed); // make sure it's in range
565 #endif
566 if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
567 PR_RunError ("assignment to world entity");
568 c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
569 break;
570
571 case OP_LOAD_F:
572 case OP_LOAD_FLD:
573 case OP_LOAD_ENT:
574 case OP_LOAD_S:
575 case OP_LOAD_FNC:
576 ed = PROG_TO_EDICT(a->edict);
577 #ifdef PARANOID
578 NUM_FOR_EDICT(ed); // make sure it's in range
579 #endif
580 a = (eval_t *)((int *)&ed->v + b->_int);
581 c->_int = a->_int;
582 break;
583
584 case OP_LOAD_V:
585 ed = PROG_TO_EDICT(a->edict);
586 #ifdef PARANOID
587 NUM_FOR_EDICT(ed); // make sure it's in range
588 #endif
589 a = (eval_t *)((int *)&ed->v + b->_int);
590 c->vector[0] = a->vector[0];
591 c->vector[1] = a->vector[1];
592 c->vector[2] = a->vector[2];
593 break;
594
595 //==================
596
597 case OP_IFNOT:
598 if (!a->_int)
599 s += st->b - 1; // offset the s++
600 break;
601
602 case OP_IF:
603 if (a->_int)
604 s += st->b - 1; // offset the s++
605 break;
606
607 case OP_GOTO:
608 s += st->a - 1; // offset the s++
609 break;
610
611 case OP_CALL0:
612 case OP_CALL1:
613 case OP_CALL2:
614 case OP_CALL3:
615 case OP_CALL4:
616 case OP_CALL5:
617 case OP_CALL6:
618 case OP_CALL7:
619 case OP_CALL8:
620 pr_argc = st->op - OP_CALL0;
621 if (!a->function)
622 PR_RunError ("NULL function");
623
624 newf = &pr_functions[a->function];
625
626 if (newf->first_statement < 0)
627 { // negative statements are built in functions
628 i = -newf->first_statement;
629 if (i >= pr_numbuiltins)
630 PR_RunError ("Bad builtin call number");
631 pr_builtins[i] ();
632 break;
633 }
634
635 s = PR_EnterFunction (newf);
636 break;
637
638 case OP_DONE:
639 case OP_RETURN:
640 pr_globals[OFS_RETURN] = pr_globals[st->a];
641 pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
642 pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
643
644 s = PR_LeaveFunction ();
645 if (pr_depth == exitdepth)
646 return; // all done
647 break;
648
649 case OP_STATE:
650 ed = PROG_TO_EDICT(pr_global_struct->self);
651 ed->v.nextthink = pr_global_struct->time + 0.1;
652 if (a->_float != ed->v.frame)
653 {
654 ed->v.frame = a->_float;
655 }
656 ed->v.think = b->function;
657 break;
658
659 default:
660 PR_RunError ("Bad opcode %i", st->op);
661 }
662 }
663
664 }
665
666 /*----------------------*/
667
668 char *pr_strtbl[MAX_PRSTR];
669 int num_prstr;
670
PR_GetString(int num)671 char *PR_GetString(int num)
672 {
673 if (num < 0) {
674 //Con_DPrintf("GET:%d == %s\n", num, pr_strtbl[-num]);
675 return pr_strtbl[-num];
676 }
677 return pr_strings + num;
678 }
679
PR_SetString(char * s)680 int PR_SetString(char *s)
681 {
682 int i;
683
684 if (s - pr_strings < 0) {
685 for (i = 0; i <= num_prstr; i++)
686 if (pr_strtbl[i] == s)
687 break;
688 if (i < num_prstr)
689 return -i;
690 if (num_prstr == MAX_PRSTR - 1)
691 Sys_Error("MAX_PRSTR");
692 num_prstr++;
693 pr_strtbl[num_prstr] = s;
694 //Con_DPrintf("SET:%d == %s\n", -num_prstr, s);
695 return -num_prstr;
696 }
697 return (int)(s - pr_strings);
698 }
699
700