memset(prog, 0, sizeof(*prog));
prog->entityfields = header.entfield;
+ prog->crc16 = header.crc16;
prog->filename = util_strdup(filename);
if (!prog->filename) {
qcint prog_spawn_entity(qc_program *prog)
{
+ char *data;
size_t i;
qcint e;
for (e = 0; e < (qcint)prog->entitypool_count; ++e) {
if (!prog->entitypool[e]) {
- char *data = (char*)(prog->entitydata + (prog->entityfields * e));
+ data = (char*)(prog->entitydata + (prog->entityfields * e));
memset(data, 0, prog->entityfields * sizeof(qcint));
return e;
}
return 0;
}
}
+ data = (char*)(prog->entitydata + (prog->entityfields * e));
+ memset(data, 0, prog->entityfields * sizeof(qcint));
return e;
}
static void trace_print_global(qc_program *prog, unsigned int glob, int vtype)
{
- static char spaces[16+1] = " ";
+ static char spaces[40+1] = " ";
prog_section_def *def;
qcany *value;
int len;
- if (!glob)
- return;
+ if (!glob) {
+ len = printf("<null>,");
+ goto done;
+ }
def = prog_getdef(prog, glob);
value = (qcany*)(&prog->globals[glob]);
if (def) {
- len = printf("[%s] ", prog_getstring(prog, def->name));
+ const char *name = prog_getstring(prog, def->name);
+ if (name[0] == '#')
+ len = printf("$");
+ else
+ len = printf("%s ", name);
vtype = def->type;
}
else
case TYPE_FIELD:
case TYPE_FUNCTION:
case TYPE_POINTER:
- len += printf("%i,", value->_int);
+ len += printf("(%i),", value->_int);
break;
case TYPE_VECTOR:
len += printf("'%g %g %g',", value->vector[0],
break;
case TYPE_STRING:
len += print_escaped_string(prog_getstring(prog, value->string));
+ len += printf(",");
/* len += printf("\"%s\",", prog_getstring(prog, value->string)); */
break;
case TYPE_FLOAT:
len += printf("%g,", value->_float);
break;
}
- if (len < 16) {
- spaces[16-len] = 0;
+done:
+ if (len < sizeof(spaces)-1) {
+ spaces[sizeof(spaces)-1-len] = 0;
printf(spaces);
- spaces[16-len] = ' ';
+ spaces[sizeof(spaces)-1-len] = ' ';
}
}
case INSTR_NE_S:
t[0] = t[1] = TYPE_STRING;
break;
+ case INSTR_STORE_F:
+ case INSTR_STOREP_F:
+ t[2] = -1;
+ break;
case INSTR_STORE_V:
t[0] = t[1] = TYPE_VECTOR; t[2] = -1;
break;
case INSTR_STORE_S:
t[0] = t[1] = TYPE_STRING; t[2] = -1;
break;
+ case INSTR_STORE_ENT:
+ t[0] = t[1] = TYPE_ENTITY; t[2] = -1;
+ break;
+ case INSTR_STORE_FLD:
+ t[0] = t[1] = TYPE_FIELD; t[2] = -1;
+ break;
+ case INSTR_STORE_FNC:
+ t[0] = t[1] = TYPE_FUNCTION; t[2] = -1;
+ break;
+ case INSTR_STOREP_V:
+ t[0] = TYPE_VECTOR; t[1] = TYPE_ENTITY; t[2] = -1;
+ break;
+ case INSTR_STOREP_S:
+ t[0] = TYPE_STRING; t[1] = TYPE_ENTITY; t[2] = -1;
+ break;
+ case INSTR_STOREP_ENT:
+ t[0] = TYPE_ENTITY; t[1] = TYPE_ENTITY; t[2] = -1;
+ break;
+ case INSTR_STOREP_FLD:
+ t[0] = TYPE_FIELD; t[1] = TYPE_ENTITY; t[2] = -1;
+ break;
+ case INSTR_STOREP_FNC:
+ t[0] = TYPE_FUNCTION; t[1] = TYPE_ENTITY; t[2] = -1;
+ break;
}
if (t[0] >= 0) trace_print_global(prog, st->o1.u1, t[0]);
+ else printf("(none), ");
if (t[1] >= 0) trace_print_global(prog, st->o2.u1, t[1]);
+ else printf("(none), ");
if (t[2] >= 0) trace_print_global(prog, st->o3.u1, t[2]);
+ else printf("(none)");
printf("\n");
}
+ fflush(stdout);
}
static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
exit(1);
}
- return st.stmt;
+ return st.stmt - 1; /* offset the ++st */
}
bool prog_exec(qc_program *prog, prog_section_function *func, size_t flags, long maxjumps)
{
long jumpcount = 0;
+ size_t oldxflags = prog->xflags;
prog_section_statement *st;
prog->vmerror = 0;
+ prog->xflags = flags;
st = prog->code + prog_enterfunction(prog, func);
--st;
};
cleanup:
+ prog->xflags = oldxflags;
prog->localstack_count = 0;
prog->stack_count = 0;
if (prog->vmerror)
*/
#if defined(QCVM_EXECUTOR)
+#include <math.h>
+
+const char *type_name[TYPE_COUNT] = {
+ "void",
+ "string",
+ "float",
+ "vector",
+ "entity",
+ "field",
+ "function",
+ "pointer",
+#if 0
+ "integer",
+#endif
+ "variant"
+};
+
bool opts_debug = false;
bool opts_memchk = false;
static int qc_print(qc_program *prog)
{
size_t i;
+ const char *laststr = NULL;
for (i = 0; i < prog->argc; ++i) {
qcany *str = (qcany*)(prog->globals + OFS_PARM0 + 3*i);
- printf("%s", prog_getstring(prog, str->string));
+ printf("%s", (laststr = prog_getstring(prog, str->string)));
+ }
+ if (laststr && (prog->xflags & VMXF_TRACE)) {
+ size_t len = strlen(laststr);
+ if (!len || laststr[len-1] != '\n')
+ printf("\n");
}
return 0;
}
+static int qc_error(qc_program *prog)
+{
+ printf("*** VM raised an error:\n");
+ qc_print(prog);
+ prog->vmerror++;
+ return -1;
+}
+
static int qc_ftos(qc_program *prog)
{
char buffer[512];
return 0;
}
+static int qc_vtos(qc_program *prog)
+{
+ char buffer[512];
+ qcany *num;
+ qcany str;
+ CheckArgs(1);
+ num = GetArg(0);
+ snprintf(buffer, sizeof(buffer), "`%g %g %g`", num->vector[0], num->vector[1], num->vector[2]);
+ str.string = prog_tempstring(prog, buffer);
+ Return(str);
+ return 0;
+}
+
static int qc_spawn(qc_program *prog)
{
qcany ent;
return 0;
}
+static int qc_vlen(qc_program *prog)
+{
+ qcany *vec, len;
+ CheckArgs(1);
+ vec = GetArg(0);
+ len._float = sqrt(vec->vector[0] * vec->vector[0] +
+ vec->vector[1] * vec->vector[1] +
+ vec->vector[2] * vec->vector[2]);
+ Return(len);
+ return 0;
+}
+
static prog_builtin qc_builtins[] = {
NULL,
- &qc_print,
- &qc_ftos,
- &qc_spawn,
- &qc_kill
+ &qc_print, /* 1 */
+ &qc_ftos, /* 2 */
+ &qc_spawn, /* 3 */
+ &qc_kill, /* 4 */
+ &qc_vtos, /* 5 */
+ &qc_error, /* 6 */
+ &qc_vlen /* 7 */
};
static size_t qc_builtins_count = sizeof(qc_builtins) / sizeof(qc_builtins[0]);
+static const char *arg0 = NULL;
+
+void usage()
+{
+ printf("usage: [-debug] %s file\n", arg0);
+ exit(1);
+}
+
int main(int argc, char **argv)
{
size_t i;
qcint fnmain = -1;
qc_program *prog;
+ size_t xflags = VMXF_DEFAULT;
+ bool opts_printfields = false;
+ bool opts_printdefs = false;
+ bool opts_info = false;
- if (argc != 2) {
- printf("usage: %s file\n", argv[0]);
- exit(1);
+ arg0 = argv[0];
+
+ if (argc < 2)
+ usage();
+
+ while (argc > 2) {
+ if (!strcmp(argv[1], "-trace")) {
+ --argc;
+ ++argv;
+ xflags |= VMXF_TRACE;
+ }
+ else if (!strcmp(argv[1], "-profile")) {
+ --argc;
+ ++argv;
+ xflags |= VMXF_PROFILE;
+ }
+ else if (!strcmp(argv[1], "-info")) {
+ --argc;
+ ++argv;
+ opts_info = true;
+ }
+ else if (!strcmp(argv[1], "-printdefs")) {
+ --argc;
+ ++argv;
+ opts_printdefs = true;
+ }
+ else if (!strcmp(argv[1], "-printfields")) {
+ --argc;
+ ++argv;
+ opts_printfields = true;
+ }
+ else
+ usage();
}
+
prog = prog_load(argv[1]);
if (!prog) {
printf("failed to load program '%s'\n", argv[1]);
prog->builtins_count = qc_builtins_count;
prog->builtins_alloc = 0;
+ printf("Program's system-checksum = 0x%04x\n", (int)prog->crc16);
+
for (i = 1; i < prog->functions_count; ++i) {
const char *name = prog_getstring(prog, prog->functions[i].name);
- printf("Found function: %s\n", name);
+ /* printf("Found function: %s\n", name); */
if (!strcmp(name, "main"))
fnmain = (qcint)i;
}
printf("Entity field space: %i\n", (int)prog->entityfields);
- if (fnmain > 0)
- {
- prog_exec(prog, &prog->functions[fnmain], VMXF_TRACE, VM_JUMPS_DEFAULT);
+ if (opts_info) {
+ prog_delete(prog);
+ return 0;
+ }
+ if (opts_printdefs) {
+ for (i = 0; i < prog->defs_count; ++i) {
+ printf("Global: %8s %-16s at %u\n",
+ type_name[prog->defs[i].type],
+ prog_getstring(prog, prog->defs[i].name),
+ (unsigned int)prog->defs[i].offset);
+ }
+ }
+ else if (opts_printfields) {
+ for (i = 0; i < prog->fields_count; ++i) {
+ printf("Field: %8s %-16s at %u\n",
+ type_name[prog->fields[i].type],
+ prog_getstring(prog, prog->fields[i].name),
+ (unsigned int)prog->fields[i].offset);
+ }
}
else
- printf("No main function found\n");
+ {
+ if (fnmain > 0)
+ {
+ prog_exec(prog, &prog->functions[fnmain], xflags, VM_JUMPS_DEFAULT);
+ }
+ else
+ printf("No main function found\n");
+ }
prog_delete(prog);
return 0;