X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=exec.c;h=0b275c90ff8976ad387a28a612106839032fe61e;hb=e6cebc3ea35b3e96282e88f2792b8a2df68a868d;hp=9aef5f2b923b4148d988d54754b411e034b7ea3b;hpb=e761f1f7b757ab4771cb4163b6fffb3c786acf5d;p=xonotic%2Fgmqcc.git diff --git a/exec.c b/exec.c index 9aef5f2..0b275c9 100644 --- a/exec.c +++ b/exec.c @@ -1,26 +1,72 @@ +#include +#include +#include +#include + #include "gmqcc.h" -#include "exec.h" +MEM_VEC_FUNCTIONS(qc_program, prog_section_statement, code) +MEM_VEC_FUNCTIONS(qc_program, prog_section_def, defs) +MEM_VEC_FUNCTIONS(qc_program, prog_section_def, fields) +MEM_VEC_FUNCTIONS(qc_program, prog_section_function, functions) +MEM_VEC_FUNCTIONS(qc_program, char, strings) +MEM_VEC_FUN_APPEND(qc_program, char, strings) +MEM_VEC_FUN_RESIZE(qc_program, char, strings) +MEM_VEC_FUNCTIONS(qc_program, qcint, globals) +MEM_VEC_FUNCTIONS(qc_program, qcint, entitydata) +MEM_VEC_FUNCTIONS(qc_program, bool, entitypool) + +MEM_VEC_FUNCTIONS(qc_program, qcint, localstack) +MEM_VEC_FUN_APPEND(qc_program, qcint, localstack) +MEM_VEC_FUN_RESIZE(qc_program, qcint, localstack) +MEM_VEC_FUNCTIONS(qc_program, qc_exec_stack, stack) + +MEM_VEC_FUNCTIONS(qc_program, size_t, profile) +MEM_VEC_FUN_RESIZE(qc_program, size_t, profile) + +MEM_VEC_FUNCTIONS(qc_program, prog_builtin, builtins) + +static void loaderror(const char *fmt, ...) +{ + int err = errno; + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf(": %s\n", strerror(err)); +} + +static void qcvmerror(qc_program *prog, const char *fmt, ...) +{ + va_list ap; + + prog->vmerror++; + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + putchar('\n'); +} qc_program* prog_load(const char *filename) { qc_program *prog; prog_header header; + size_t i; FILE *file; - file = fopen(filename, "rb"); + file = util_fopen(filename, "rb"); if (!file) return NULL; if (fread(&header, sizeof(header), 1, file) != 1) { - perror("read"); + loaderror("failed to read header from '%s'", filename); fclose(file); return NULL; } if (header.version != 6) { - printf("header says this is a version %i progs, we need version 6\n", - header.version); + loaderror("header says this is a version %i progs, we need version 6\n", header.version); fclose(file); return NULL; } @@ -34,13 +80,17 @@ qc_program* prog_load(const char *filename) memset(prog, 0, sizeof(*prog)); prog->entityfields = header.entfield; + prog->crc16 = header.crc16; prog->filename = util_strdup(filename); - if (!prog->filename) + if (!prog->filename) { + loaderror("failed to store program name"); goto error; + } + #define read_data(hdrvar, progvar, type) \ if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ - perror("fseek"); \ + loaderror("seek failed"); \ goto error; \ } \ prog->progvar##_alloc = header.hdrvar.length; \ @@ -50,15 +100,15 @@ qc_program* prog_load(const char *filename) goto error; \ if (fread(prog->progvar, sizeof(*prog->progvar), header.hdrvar.length, file) \ != header.hdrvar.length) { \ - perror("read"); \ + loaderror("read failed"); \ goto error; \ } #define read_data1(x, y) read_data(x, x, y) - read_data (statements, code, prog_statement); - read_data1(defs, prog_def); - read_data1(fields, prog_def); - read_data1(functions, prog_function); + read_data (statements, code, prog_section_statement); + read_data1(defs, prog_section_def); + read_data1(fields, prog_section_def); + read_data1(functions, prog_section_function); read_data1(strings, char); read_data1(globals, qcint); @@ -74,6 +124,19 @@ qc_program* prog_load(const char *filename) if (!qc_program_strings_resize(prog, prog->strings_count + 16*1024)) goto error; + /* spawn the world entity */ + if (!qc_program_entitypool_add(prog, true)) { + loaderror("failed to allocate world entity\n"); + goto error; + } + for (i = 0; i < prog->entityfields; ++i) { + if (!qc_program_entitydata_add(prog, 0)) { + loaderror("failed to allocate world data\n"); + goto error; + } + } + prog->entities = 1; + return prog; error: @@ -85,6 +148,7 @@ error: if (prog->strings) mem_d(prog->strings); if (prog->globals) mem_d(prog->globals); if (prog->entitydata) mem_d(prog->entitydata); + if (prog->entitypool) mem_d(prog->entitypool); mem_d(prog); return NULL; } @@ -99,9 +163,15 @@ void prog_delete(qc_program *prog) MEM_VECTOR_CLEAR(prog, strings); MEM_VECTOR_CLEAR(prog, globals); MEM_VECTOR_CLEAR(prog, entitydata); + MEM_VECTOR_CLEAR(prog, entitypool); MEM_VECTOR_CLEAR(prog, localstack); MEM_VECTOR_CLEAR(prog, stack); MEM_VECTOR_CLEAR(prog, profile); + + if (prog->builtins_alloc) { + MEM_VECTOR_CLEAR(prog, builtins); + } + /* otherwise the builtins were statically allocated */ mem_d(prog); } @@ -116,7 +186,7 @@ char* prog_getstring(qc_program *prog, qcint str) return prog->strings + str; } -prog_def* prog_entfield(qc_program *prog, qcint off) +prog_section_def* prog_entfield(qc_program *prog, qcint off) { size_t i; for (i = 0; i < prog->fields_count; ++i) { @@ -126,7 +196,7 @@ prog_def* prog_entfield(qc_program *prog, qcint off) return NULL; } -prog_def* prog_getdef(qc_program *prog, qcint off) +prog_section_def* prog_getdef(qc_program *prog, qcint off) { size_t i; for (i = 0; i < prog->defs_count; ++i) { @@ -138,7 +208,61 @@ prog_def* prog_getdef(qc_program *prog, qcint off) qcany* prog_getedict(qc_program *prog, qcint e) { - return (qcany*)(prog->entitydata + (prog->entityfields + e)); + if (e >= prog->entitypool_count) { + prog->vmerror++; + printf("Accessing out of bounds edict %i\n", (int)e); + e = 0; + } + return (qcany*)(prog->entitydata + (prog->entityfields * e)); +} + +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]) { + data = (char*)(prog->entitydata + (prog->entityfields * e)); + memset(data, 0, prog->entityfields * sizeof(qcint)); + return e; + } + } + if (!qc_program_entitypool_add(prog, true)) { + prog->vmerror++; + printf("Failed to allocate entity\n"); + return 0; + } + prog->entities++; + for (i = 0; i < prog->entityfields; ++i) { + if (!qc_program_entitydata_add(prog, 0)) { + printf("Failed to allocate entity\n"); + return 0; + } + } + data = (char*)(prog->entitydata + (prog->entityfields * e)); + memset(data, 0, prog->entityfields * sizeof(qcint)); + return e; +} + +void prog_free_entity(qc_program *prog, qcint e) +{ + if (!e) { + prog->vmerror++; + printf("Trying to free world entity\n"); + return; + } + if (e >= prog->entitypool_count) { + prog->vmerror++; + printf("Trying to free out of bounds entity\n"); + return; + } + if (!prog->entitypool[e]) { + prog->vmerror++; + printf("Double free on entity\n"); + return; + } + prog->entitypool[e] = false; } qcint prog_tempstring(qc_program *prog, const char *_str) @@ -172,25 +296,65 @@ qcint prog_tempstring(qc_program *prog, const char *_str) return at; } +static int print_escaped_string(const char *str, size_t maxlen) +{ + int len = 2; + putchar('"'); + --maxlen; /* because we're lazy and have escape sequences */ + while (*str) { + if (len >= maxlen) { + putchar('.'); + putchar('.'); + putchar('.'); + len += 3; + break; + } + switch (*str) { + case '\a': len += 2; putchar('\\'); putchar('a'); break; + case '\b': len += 2; putchar('\\'); putchar('b'); break; + case '\r': len += 2; putchar('\\'); putchar('r'); break; + case '\n': len += 2; putchar('\\'); putchar('n'); break; + case '\t': len += 2; putchar('\\'); putchar('t'); break; + case '\f': len += 2; putchar('\\'); putchar('f'); break; + case '\v': len += 2; putchar('\\'); putchar('v'); break; + case '\\': len += 2; putchar('\\'); putchar('\\'); break; + case '"': len += 2; putchar('\\'); putchar('"'); break; + default: + ++len; + putchar(*str); + break; + } + ++str; + } + putchar('"'); + return len; +} + static void trace_print_global(qc_program *prog, unsigned int glob, int vtype) { - static char spaces[16+1] = " "; - prog_def *def; + static char spaces[28+1] = " "; + prog_section_def *def; qcany *value; int len; - if (!glob) - return; + if (!glob) { + len = printf(","); + 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 - len = printf("[#%u] ", glob); + len = printf("[@%u] ", glob); switch (vtype) { case TYPE_VOID: @@ -198,7 +362,7 @@ static void trace_print_global(qc_program *prog, unsigned int glob, int vtype) 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], @@ -206,27 +370,30 @@ static void trace_print_global(qc_program *prog, unsigned int glob, int vtype) value->vector[2]); break; case TYPE_STRING: - len += printf("\"%s\",", prog_getstring(prog, value->string)); + len += print_escaped_string(prog_getstring(prog, value->string), sizeof(spaces)-len-5); + len += printf(","); + /* len += printf("\"%s\",", prog_getstring(prog, value->string)); */ break; case TYPE_FLOAT: default: 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] = ' '; } } -static void prog_print_statement(qc_program *prog, prog_statement *st) +static void prog_print_statement(qc_program *prog, prog_section_statement *st) { if (st->opcode >= (sizeof(asm_instr)/sizeof(asm_instr[0]))) { printf("\n", st->opcode); return; } - printf("%-12s", asm_instr[st->opcode].m); + printf(" <> %-12s", asm_instr[st->opcode].m); if (st->opcode >= INSTR_IF && st->opcode <= INSTR_IFNOT) { @@ -266,42 +433,98 @@ static void prog_print_statement(qc_program *prog, prog_statement *st) 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_function *func) +static qcint prog_enterfunction(qc_program *prog, prog_section_function *func) { qc_exec_stack st; - prog_function *cur = NULL; - - if (prog->stack_count) - cur = prog->stack[prog->stack_count-1].function; + size_t p, parampos; /* back up locals */ st.localsp = prog->localstack_count; st.stmt = prog->statement; st.function = func; - if (cur) +#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS + if (prog->stack_count) + { + prog_section_function *cur; + cur = prog->stack[prog->stack_count-1].function; + if (cur) + { + qcint *globals = prog->globals + cur->firstlocal; + if (!qc_program_localstack_append(prog, globals, cur->locals)) + { + printf("out of memory\n"); + exit(1); + } + } + } +#else { - qcint *globals = prog->globals + cur->firstlocal; - if (!qc_program_localstack_append(prog, globals, cur->locals)) + qcint *globals = prog->globals + func->firstlocal; + if (!qc_program_localstack_append(prog, globals, func->locals)) { printf("out of memory\n"); exit(1); } } +#endif + + /* copy parameters */ + parampos = func->firstlocal; + for (p = 0; p < func->nargs; ++p) + { + size_t s; + for (s = 0; s < func->argsize[p]; ++s) { + prog->globals[parampos] = prog->globals[OFS_PARM0 + 3*p + s]; + ++parampos; + } + } if (!qc_program_stack_add(prog, st)) { printf("out of memory\n"); @@ -313,26 +536,45 @@ static qcint prog_enterfunction(qc_program *prog, prog_function *func) static qcint prog_leavefunction(qc_program *prog) { + prog_section_function *prev = NULL; + size_t oldsp; + qc_exec_stack st = prog->stack[prog->stack_count-1]; - if (!qc_program_stack_remove(prog, prog->stack_count-1)) { - printf("out of memory\n"); - exit(1); - } - if (st.localsp != prog->localstack_count) { - if (!qc_program_localstack_resize(prog, st.localsp)) { +#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS + if (prog->stack_count > 1) { + prev = prog->stack[prog->stack_count-2].function; + oldsp = prog->stack[prog->stack_count-2].localsp; + } +#else + prev = prog->stack[prog->stack_count-1].function; + oldsp = prog->stack[prog->stack_count-1].localsp; +#endif + if (prev) { + qcint *globals = prog->globals + prev->firstlocal; + memcpy(globals, prog->localstack + oldsp, prev->locals); + if (!qc_program_localstack_resize(prog, oldsp)) { printf("out of memory\n"); exit(1); } } - return st.stmt; + if (!qc_program_stack_remove(prog, prog->stack_count-1)) { + printf("out of memory\n"); + exit(1); + } + + return st.stmt - 1; /* offset the ++st */ } -bool prog_exec(qc_program *prog, prog_function *func, size_t flags, long maxjumps) +bool prog_exec(qc_program *prog, prog_section_function *func, size_t flags, long maxjumps) { long jumpcount = 0; - prog_statement *st; + size_t oldxflags = prog->xflags; + prog_section_statement *st; + + prog->vmerror = 0; + prog->xflags = flags; st = prog->code + prog_enterfunction(prog, func); --st; @@ -343,35 +585,38 @@ bool prog_exec(qc_program *prog, prog_function *func, size_t flags, long maxjump { #define QCVM_PROFILE 0 #define QCVM_TRACE 0 -# include "qcvm_execprogram.h" +# include "execloop.h" break; } case (VMXF_TRACE): { #define QCVM_PROFILE 0 #define QCVM_TRACE 1 -# include "qcvm_execprogram.h" +# include "execloop.h" break; } case (VMXF_PROFILE): { #define QCVM_PROFILE 1 #define QCVM_TRACE 0 -# include "qcvm_execprogram.h" +# include "execloop.h" break; } case (VMXF_TRACE|VMXF_PROFILE): { #define QCVM_PROFILE 1 #define QCVM_TRACE 1 -# include "qcvm_execprogram.h" +# include "execloop.h" break; } }; cleanup: + prog->xflags = oldxflags; prog->localstack_count = 0; prog->stack_count = 0; + if (prog->vmerror) + return false; return true; } @@ -380,35 +625,321 @@ cleanup: */ #if defined(QCVM_EXECUTOR) +#include + +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; + +typedef struct { + int vtype; + const char *value; +} qcvm_parameter; + +VECTOR_MAKE(qcvm_parameter, main_params); + +#define CheckArgs(num) do { \ + if (prog->argc != (num)) { \ + prog->vmerror++; \ + printf("ERROR: invalid number of arguments for %s: %i, expected %i\n", \ + __FUNCTION__, prog->argc, (num)); \ + return -1; \ + } \ +} while (0) + +#define GetGlobal(idx) ((qcany*)(prog->globals + (idx))) +#define GetArg(num) GetGlobal(OFS_PARM0 + 3*(num)) +#define Return(any) *(GetGlobal(OFS_RETURN)) = (any) + +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", (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]; + qcany *num; + qcany str; + CheckArgs(1); + num = GetArg(0); + snprintf(buffer, sizeof(buffer), "%g", num->_float); + str.string = prog_tempstring(prog, buffer); + Return(str); + 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_etos(qc_program *prog) +{ + char buffer[512]; + qcany *num; + qcany str; + CheckArgs(1); + num = GetArg(0); + snprintf(buffer, sizeof(buffer), "%i", num->_int); + str.string = prog_tempstring(prog, buffer); + Return(str); + return 0; +} + +static int qc_spawn(qc_program *prog) +{ + qcany ent; + CheckArgs(0); + ent.edict = prog_spawn_entity(prog); + Return(ent); + return (ent.edict ? 0 : -1); +} + +static int qc_kill(qc_program *prog) +{ + qcany *ent; + CheckArgs(1); + ent = GetArg(0); + prog_free_entity(prog, ent->edict); + 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, /* 1 */ + &qc_ftos, /* 2 */ + &qc_spawn, /* 3 */ + &qc_kill, /* 4 */ + &qc_vtos, /* 5 */ + &qc_error, /* 6 */ + &qc_vlen, /* 7 */ + &qc_etos /* 8 */ +}; +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); +} + +static void prog_main_setparams(qc_program *prog) +{ + size_t i; + qcany *arg; + + for (i = 0; i < main_params_elements; ++i) { + arg = GetGlobal(OFS_PARM0 + 3*i); + arg->vector[0] = 0; + arg->vector[1] = 0; + arg->vector[2] = 0; + switch (main_params_data[i].vtype) { + case TYPE_VECTOR: +#ifdef WIN32 + (void)sscanf_s(main_params_data[i].value, " %f %f %f ", + &arg->vector[0], + &arg->vector[1], + &arg->vector[2]); +#else + (void)sscanf(main_params_data[i].value, " %f %f %f ", + &arg->vector[0], + &arg->vector[1], + &arg->vector[2]); +#endif + break; + case TYPE_FLOAT: + arg->_float = atof(main_params_data[i].value); + break; + case TYPE_STRING: + arg->string = prog_tempstring(prog, main_params_data[i].value); + break; + default: + printf("error: unhandled parameter type: %i\n", main_params_data[i].vtype); + break; + } + } +} + 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 if (!strcmp(argv[1], "-vector") || + !strcmp(argv[1], "-string") || + !strcmp(argv[1], "-float") ) + { + qcvm_parameter p; + if (argv[1][1] == 'f') + p.vtype = TYPE_FLOAT; + else if (argv[1][1] == 's') + p.vtype = TYPE_STRING; + else if (argv[1][1] == 'v') + p.vtype = TYPE_VECTOR; + + --argc; + ++argv; + if (argc < 3) + usage(); + p.value = argv[1]; + + if (main_params_add(p) < 0) { + if (main_params_data) + mem_d(main_params_data); + printf("cannot add parameter\n"); + exit(1); + } + --argc; + ++argv; + } + else + usage(); } + prog = prog_load(argv[1]); if (!prog) { printf("failed to load program '%s'\n", argv[1]); exit(1); } + prog->builtins = qc_builtins; + prog->builtins_count = qc_builtins_count; + prog->builtins_alloc = 0; + + if (opts_info) { + printf("Program's system-checksum = 0x%04x\n", (int)prog->crc16); + printf("Entity field space: %i\n", (int)prog->entityfields); + } + 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; } - if (fnmain > 0) - { - prog_exec(prog, &prog->functions[fnmain], VMXF_TRACE, 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 & DEF_TYPEMASK], + 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_main_setparams(prog); + prog_exec(prog, &prog->functions[fnmain], xflags, VM_JUMPS_DEFAULT); + } + else + printf("No main function found\n"); + } prog_delete(prog); return 0;