|
|
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.