1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19*/
20
21#include "quakedef.h"
22
23
24/*
25
26*/
27
28typedef struct
29{
30	int				s;
31	dfunction_t		*f;
32} prstack_t;
33
34#define	MAX_STACK_DEPTH		32
35prstack_t	pr_stack[MAX_STACK_DEPTH];
36int			pr_depth;
37
38#define	LOCALSTACK_SIZE		2048
39int			localstack[LOCALSTACK_SIZE];
40int			localstack_used;
41
42
43qboolean	pr_trace;
44dfunction_t	*pr_xfunction;
45int			pr_xstatement;
46
47
48int		pr_argc;
49
50const 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
139char *PR_GlobalString (int ofs);
140char *PR_GlobalStringNoContents (int ofs);
141
142
143//=============================================================================
144
145/*
146=================
147PR_PrintStatement
148=================
149*/
150void 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============
187PR_StackTrace
188============
189*/
190void 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_strings + f->s_file, pr_strings + f->s_name);
212	}
213}
214
215
216/*
217============
218PR_Profile_f
219
220============
221*/
222void 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_strings+best->s_name);
247			num++;
248			best->profile = 0;
249		}
250	} while (best);
251}
252
253
254/*
255============
256PR_RunError
257
258Aborts the currently executing function
259============
260*/
261void PR_RunError (const 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 host_error can shutdown functions
275
276	Host_Error ("Program error");
277}
278
279/*
280============================================================================
281PR_ExecuteProgram
282
283The interpretation main loop
284============================================================================
285*/
286
287/*
288====================
289PR_EnterFunction
290
291Returns the new program statement counter
292====================
293*/
294int 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====================
330PR_LeaveFunction
331====================
332*/
333int PR_LeaveFunction (void)
334{
335	int		i, c;
336
337	if (pr_depth <= 0)
338		Sys_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====================
358PR_ExecuteProgram
359====================
360*/
361void 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		Host_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
390while (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)
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_strings[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_strings+a->string,pr_strings+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_strings+a->string,pr_strings+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 *)(ed->u.i + 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 *)(ed->u.i + 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 *)(ed->u.i + 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#ifdef FPS_20
652		ed->u.v.nextthink = pr_global_struct->time + 0.05;
653#else
654		ed->u.v.nextthink = pr_global_struct->time + 0.1;
655#endif
656		if (a->_float != ed->u.v.frame)
657		{
658			ed->u.v.frame = a->_float;
659		}
660		ed->u.v.think = b->function;
661		break;
662
663	default:
664		PR_RunError ("Bad opcode %i", st->op);
665	}
666}
667
668}
669