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