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