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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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