#include "quakedef.h"
#include "progsvm.h"
-const char *prvm_opnames[] =
+static const char *prvm_opnames[] =
{
"^5DONE",
"^2OR",
"BITAND",
-"BITOR"
+"BITOR",
+
+
+
+
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+
+"STORE_I",
+
+NULL,
+NULL,
+
+"ADD_I",
+"ADD_FI",
+"ADD_IF",
+
+"SUB_I",
+"SUB_FI",
+"SUB_IF",
+"CONV_IF",
+"CONV_FI",
+
+NULL,
+NULL,
+
+"LOAD_I",
+"STOREP_I",
+
+NULL,
+NULL,
+
+"BITAND_I",
+"BITOR_I",
+
+"MUL_I",
+"DIV_I",
+"EQ_I",
+"NE_I",
+
+NULL,
+NULL,
+
+"NOT_I",
+
+"DIV_VF",
+
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+
+"STORE_P",
+
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+NULL,
+
+"LE_I",
+"GE_I",
+"LT_I",
+"GT_I",
+
+"LE_IF",
+"GE_IF",
+"LT_IF",
+"GT_IF",
+
+"LE_FI",
+"GE_FI",
+"LT_FI",
+"GT_FI",
+
+"EQ_IF",
+"EQ_FI",
+
+NULL,
+NULL,
+NULL,
+NULL,
+
+"MUL_IF",
+"MUL_FI",
+"MUL_VI",
+
+NULL,
+
+"DIV_IF",
+"DIV_FI",
+"BITAND_IF",
+"BITOR_IF",
+"BITAND_FI",
+"BITOR_FI",
+"AND_I",
+"OR_I",
+"AND_IF",
+"OR_IF",
+"AND_FI",
+"OR_FI",
+"NE_IF",
+"NE_FI",
+
+"GSTOREP_I",
+"GSTOREP_F",
+"GSTOREP_ENT",
+"GSTOREP_FLD",
+"GSTOREP_S",
+"GSTOREP_FNC",
+"GSTOREP_V",
+"GADDRESS",
+"GLOAD_I",
+"GLOAD_F",
+"GLOAD_FLD",
+"GLOAD_ENT",
+"GLOAD_S",
+"GLOAD_FNC",
+"BOUNDCHECK",
+NULL,
+NULL,
+NULL,
+NULL,
+"GLOAD_V",
};
size_t i;
int opnum = (int)(s - prog->statements);
char valuebuf[MAX_INPUTLINE];
+ const char *opname;
Con_Printf("s%i: ", opnum);
if( prog->statement_linenums )
if (prvm_statementprofiling.integer)
Con_Printf("%7.0f ", prog->statement_profile[s - prog->statements]);
- if ( (unsigned)s->op < sizeof(prvm_opnames)/sizeof(prvm_opnames[0]))
- {
- Con_Printf("%s ", prvm_opnames[s->op]);
- i = strlen(prvm_opnames[s->op]);
- // don't count a preceding color tag when padding the name
- if (prvm_opnames[s->op][0] == STRING_COLOR_TAG)
- i -= 2;
- for ( ; i<10 ; i++)
- Con_Print(" ");
- }
+ if ( (unsigned)s->op < sizeof(prvm_opnames)/sizeof(prvm_opnames[0]) && prvm_opnames[s->op])
+ opname = prvm_opnames[s->op];
+ else
+ opname = valuebuf, dpsnprintf(valuebuf, sizeof(valuebuf), "OPCODE_%u", (unsigned)s->op);
+ Con_Printf("%s ", opname);
+ i = strlen(opname);
+ // don't count a preceding color tag when padding the name
+ if (opname[0] == STRING_COLOR_TAG)
+ i -= 2;
+ for ( ; i<10 ; i++)
+ Con_Print(" ");
+
if (s->operand[0] >= 0) Con_Printf( "%s", PRVM_GlobalString(prog, s->operand[0], valuebuf, sizeof(valuebuf)));
if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[1], valuebuf, sizeof(valuebuf)));
if (s->operand[2] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[2], valuebuf, sizeof(valuebuf)));
void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize)
{
- mfunction_t *f;
- int i;
+ mfunction_t *f;
+ int i;
char vabuf[1024];
+ char *p;
if(prog)
{
- dpsnprintf(buf, bufsize, "(%s) ", prog->name);
+ i = dpsnprintf(buf, bufsize, "(%s) ", prog->name);
+ p = buf + max(0, i);
}
else
{
- strlcpy(buf, "<NO PROG>", bufsize);
+ dp_strlcpy(buf, "<NO PROG>", bufsize);
return;
}
for (i = prog->depth;i > 0;i--)
{
f = prog->stack[i].f;
-
- if(strlcat(buf,
+ p = dp_stpecpy(
+ p,
+ buf + bufsize,
f
? va(vabuf, sizeof(vabuf), "%s:%s(%i) ", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement)
- : "<NULL> ",
- bufsize
- ) >= bufsize)
+ : "<NULL> "
+ );
+ if (p == buf + bufsize)
break;
}
}
}
extern cvar_t prvm_errordump;
-void PRVM_Crash(prvm_prog_t *prog)
+void PRVM_Crash(void)
{
+ prvm_prog_t *prog;
char vabuf[1024];
- if (prog == NULL)
- return;
- if (!prog->loaded)
- return;
+ int i;
- PRVM_serverfunction(SV_Shutdown) = 0; // don't call SV_Shutdown on crash
+ // determine which program crashed
+ for (i = 0; i < PRVM_PROG_MAX; ++i)
+ if (PRVM_GetProg(i)->loaded && PRVM_GetProg(i)->depth > 0)
+ break;
+ if (i >= PRVM_PROG_MAX)
+ return; // none of them crashed
+ prog = PRVM_GetProg(i);
- if( prog->depth > 0 )
- {
- Con_Printf("QuakeC crash report for %s:\n", prog->name);
- PRVM_PrintState(prog, 0);
- }
+ Con_Printf("QuakeC crash report for %s:\n", prog->name);
+ PRVM_PrintState(prog, 0);
- if(prvm_errordump.integer)
+ // don't call graceful shutdown on crash
+ if (prog == SVVM_prog)
+ PRVM_serverfunction(SV_Shutdown) = 0;
+ else if (prog == CLVM_prog)
+ PRVM_clientfunction(CSQC_Shutdown) = 0;
+
+ if(prvm_errordump.integer && (prog == SVVM_prog || prog == CLVM_prog))
{
// make a savegame
SV_Savegame_to(prog, va(vabuf, sizeof(vabuf), "crash-%s.dmp", prog->name));
// dump the stack so host_error can shutdown functions
prog->depth = 0;
prog->localstack_used = 0;
-
- // delete all tempstrings (FIXME: is this safe in VM->engine->VM recursion?)
- prog->tempstringsbuf.cursize = 0;
-
- // reset the prog pointer
- prog = NULL;
}
/*
Con_Printf("prvm_coverage: %s just executed a statement at %s for the first time. Coverage: %.2f%%.\n", prog->name, PRVM_WhereAmI(vabuf, sizeof(vabuf), prog, func, statement), prog->statements_covered * 100.0 / prog->numstatements);
}
-#if defined (__GNUC__) || (__clang__)
+#if defined (__GNUC__) || (__clang__) || (__TINYC__)
# ifndef CONFIG_PEDANTIC
# define HAVE_COMPUTED_GOTOS 1
# endif
#define OPC ((prvm_eval_t *)&globals[st->operand[2]])
extern cvar_t prvm_traceqc;
extern cvar_t prvm_statementprofiling;
-extern qboolean prvm_runawaycheck;
+extern qbool prvm_runawaycheck;
#ifdef PROFILING
#ifdef CONFIG_MENU
unsigned int cached_max_edicts = prog->max_edicts;
// these do not change
mstatement_t *cached_statements = prog->statements;
- qboolean cached_allowworldwrites = prog->allowworldwrites;
+ qbool cached_allowworldwrites = prog->allowworldwrites;
unsigned int cached_flag = prog->flag;
prvm_vec_t *globals = prog->globals.fp;
if (prog == SVVM_prog)
SV_FlushBroadcastMessages();
}
-#endif
+#endif // CONFIG_MENU
/*
====================
unsigned int cached_max_edicts = prog->max_edicts;
// these do not change
mstatement_t *cached_statements = prog->statements;
- qboolean cached_allowworldwrites = prog->allowworldwrites;
+ qbool cached_allowworldwrites = prog->allowworldwrites;
unsigned int cached_flag = prog->flag;
prvm_vec_t *globals = prog->globals.fp;
if (prog == SVVM_prog)
SV_FlushBroadcastMessages();
}
-#endif
+#endif // PROFILING
/*
====================
unsigned int cached_max_edicts = prog->max_edicts;
// these do not change
mstatement_t *cached_statements = prog->statements;
- qboolean cached_allowworldwrites = prog->allowworldwrites;
+ qbool cached_allowworldwrites = prog->allowworldwrites;
unsigned int cached_flag = prog->flag;
prvm_vec_t *globals = prog->globals.fp;