• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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