X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=exec.c;h=b8f74ac72c61f4152f19d5dd9e1f1bb9330ddebe;hb=dd6f415a0456b7f09afebe6b008060bdb7fecb91;hp=f50eac1b40098794d00a223f05ddfff505dbce81;hpb=61fa54318c3aa1ce0c2099f9793d830e5896c016;p=xonotic%2Fgmqcc.git diff --git a/exec.c b/exec.c index f50eac1..b8f74ac 100644 --- a/exec.c +++ b/exec.c @@ -184,7 +184,7 @@ void prog_delete(qc_program *prog) char* prog_getstring(qc_program *prog, qcint str) { - if (str < 0 || str >= vec_size(prog->strings)) + if (str < 0 || str >= (qcint)vec_size(prog->strings)) return "<<>>"; return prog->strings + str; } @@ -211,7 +211,7 @@ prog_section_def* prog_getdef(qc_program *prog, qcint off) qcany* prog_getedict(qc_program *prog, qcint e) { - if (e >= vec_size(prog->entitypool)) { + if (e >= (qcint)vec_size(prog->entitypool)) { prog->vmerror++; printf("Accessing out of bounds edict %i\n", (int)e); e = 0; @@ -244,7 +244,7 @@ void prog_free_entity(qc_program *prog, qcint e) printf("Trying to free world entity\n"); return; } - if (e >= vec_size(prog->entitypool)) { + if (e >= (qcint)vec_size(prog->entitypool)) { prog->vmerror++; printf("Trying to free out of bounds entity\n"); return; @@ -285,9 +285,9 @@ qcint prog_tempstring(qc_program *prog, const char *_str) return at; } -static int print_escaped_string(const char *str, size_t maxlen) +static size_t print_escaped_string(const char *str, size_t maxlen) { - int len = 2; + size_t len = 2; putchar('"'); --maxlen; /* because we're lazy and have escape sequences */ while (*str) { @@ -368,7 +368,7 @@ static void trace_print_global(qc_program *prog, unsigned int glob, int vtype) break; } done: - if (len < sizeof(spaces)-1) { + if (len < (int)sizeof(spaces)-1) { spaces[sizeof(spaces)-1-len] = 0; printf(spaces); spaces[sizeof(spaces)-1-len] = ' '; @@ -477,7 +477,8 @@ static void prog_print_statement(qc_program *prog, prog_section_statement *st) static qcint prog_enterfunction(qc_program *prog, prog_section_function *func) { qc_exec_stack st; - size_t p, parampos; + size_t parampos; + int32_t p; /* back up locals */ st.localsp = vec_size(prog->localstack); @@ -616,6 +617,8 @@ cleanup: #if defined(QCVM_EXECUTOR) #include +opts_cmd_t opts; + const char *type_name[TYPE_COUNT] = { "void", "string", @@ -631,9 +634,6 @@ const char *type_name[TYPE_COUNT] = { "variant" }; -bool opts_debug = false; -bool opts_memchk = false; - typedef struct { int vtype; const char *value; @@ -658,7 +658,7 @@ static int qc_print(qc_program *prog) { size_t i; const char *laststr = NULL; - for (i = 0; i < prog->argc; ++i) { + for (i = 0; i < (size_t)prog->argc; ++i) { qcany *str = (qcany*)(prog->globals + OFS_PARM0 + 3*i); printf("%s", (laststr = prog_getstring(prog, str->string))); } @@ -691,6 +691,17 @@ static int qc_ftos(qc_program *prog) return 0; } +static int qc_stof(qc_program *prog) +{ + qcany *str; + qcany num; + CheckArgs(1); + str = GetArg(0); + num._float = strtof(prog_getstring(prog, str->string), NULL); + Return(num); + return 0; +} + static int qc_vtos(qc_program *prog) { char buffer[512]; @@ -740,7 +751,7 @@ static int qc_vlen(qc_program *prog) qcany *vec, len; CheckArgs(1); vec = GetArg(0); - len._float = sqrt(vec->vector[0] * vec->vector[0] + + len._float = sqrt(vec->vector[0] * vec->vector[0] + vec->vector[1] * vec->vector[1] + vec->vector[2] * vec->vector[2]); Return(len); @@ -756,16 +767,39 @@ static prog_builtin qc_builtins[] = { &qc_vtos, /* 5 */ &qc_error, /* 6 */ &qc_vlen, /* 7 */ - &qc_etos /* 8 */ + &qc_etos, /* 8 */ + &qc_stof /* 9 */ }; static size_t qc_builtins_count = sizeof(qc_builtins) / sizeof(qc_builtins[0]); static const char *arg0 = NULL; -void usage() +static void version() { + printf("GMQCC-QCVM %d.%d.%d Built %s %s\n", + GMQCC_VERSION_MAJOR, + GMQCC_VERSION_MINOR, + GMQCC_VERSION_PATCH, + __DATE__, + __TIME__ + ); +} + +static void usage() { - printf("usage: [-debug] %s file\n", arg0); - exit(1); + printf("usage: %s [options] [parameters] file\n", arg0); + printf("options:\n"); + printf(" -h, --help print this message\n" + " -trace trace the execution\n" + " -profile perform profiling during execution\n" + " -info print information from the prog's header\n" + " -disasm disassemble and exit\n" + " -printdefs list the defs section\n" + " -printfields list the field section\n" + " -printfuns list functions information\n"); + printf("parameters:\n"); + printf(" -vector pass a vector parameter to main()\n" + " -float pass a float parameter to main()\n" + " -string pass a string parameter to main() \n"); } static void prog_main_setparams(qc_program *prog) @@ -814,16 +848,35 @@ int main(int argc, char **argv) size_t xflags = VMXF_DEFAULT; bool opts_printfields = false; bool opts_printdefs = false; + bool opts_printfuns = false; bool opts_disasm = false; - bool opts_info = false; + bool opts_info = false; + bool noexec = false; + const char *progsfile = NULL; arg0 = argv[0]; - if (argc < 2) + if (argc < 2) { usage(); + exit(1); + } - while (argc > 2) { - if (!strcmp(argv[1], "-trace")) { + while (argc > 1) { + if (!strcmp(argv[1], "-h") || + !strcmp(argv[1], "-help") || + !strcmp(argv[1], "--help")) + { + usage(); + exit(0); + } + else if (!strcmp(argv[1], "-v") || + !strcmp(argv[1], "-version") || + !strcmp(argv[1], "--version")) + { + version(); + exit(0); + } + else if (!strcmp(argv[1], "-trace")) { --argc; ++argv; xflags |= VMXF_TRACE; @@ -837,21 +890,31 @@ int main(int argc, char **argv) --argc; ++argv; opts_info = true; + noexec = true; } else if (!strcmp(argv[1], "-disasm")) { --argc; ++argv; opts_disasm = true; + noexec = true; } else if (!strcmp(argv[1], "-printdefs")) { --argc; ++argv; opts_printdefs = true; + noexec = true; + } + else if (!strcmp(argv[1], "-printfuns")) { + --argc; + ++argv; + opts_printfuns = true; + noexec = true; } else if (!strcmp(argv[1], "-printfields")) { --argc; ++argv; opts_printfields = true; + noexec = true; } else if (!strcmp(argv[1], "-vector") || !strcmp(argv[1], "-string") || @@ -867,22 +930,61 @@ int main(int argc, char **argv) --argc; ++argv; - if (argc < 3) + if (argc < 3) { usage(); + exit(1); + } p.value = argv[1]; vec_push(main_params, p); --argc; ++argv; } + else if (!strcmp(argv[1], "--")) { + --argc; + ++argv; + break; + } + else if (argv[1][0] != '-') { + if (progsfile) { + printf("only 1 program file may be specified\n"); + usage(); + exit(1); + } + progsfile = argv[1]; + --argc; + ++argv; + } else + { + usage(); + exit(1); + } + } + + if (argc > 2) { + usage(); + exit(1); + } + if (argc > 1) { + if (progsfile) { + printf("only 1 program file may be specified\n"); usage(); + exit(1); + } + progsfile = argv[1]; + --argc; + ++argv; } + if (!progsfile) { + usage(); + exit(1); + } - prog = prog_load(argv[1]); + prog = prog_load(progsfile); if (!prog) { - printf("failed to load program '%s'\n", argv[1]); + printf("failed to load program '%s'\n", progsfile); exit(1); } @@ -890,16 +992,11 @@ int main(int argc, char **argv) prog->builtins_count = qc_builtins_count; if (opts_info) { - printf("Program's system-checksum = 0x%04x\n", (int)prog->crc16); - printf("Entity field space: %i\n", (int)prog->entityfields); + printf("Program's system-checksum = 0x%04x\n", (unsigned int)prog->crc16); + printf("Entity field space: %u\n", (unsigned int)prog->entityfields); + printf("Globals: %u\n", (unsigned int)vec_size(prog->globals)); } - for (i = 1; i < vec_size(prog->functions); ++i) { - const char *name = prog_getstring(prog, prog->functions[i].name); - /* printf("Found function: %s\n", name); */ - if (!strcmp(name, "main")) - fnmain = (qcint)i; - } if (opts_info) { prog_delete(prog); return 0; @@ -911,22 +1008,42 @@ int main(int argc, char **argv) } if (opts_printdefs) { for (i = 0; i < vec_size(prog->defs); ++i) { - printf("Global: %8s %-16s at %u\n", + printf("Global: %8s %-16s at %u%s\n", type_name[prog->defs[i].type & DEF_TYPEMASK], prog_getstring(prog, prog->defs[i].name), - (unsigned int)prog->defs[i].offset); + (unsigned int)prog->defs[i].offset, + ((prog->defs[i].type & DEF_SAVEGLOBAL) ? " [SAVE]" : "")); } } - else if (opts_printfields) { + if (opts_printfields) { for (i = 0; i < vec_size(prog->fields); ++i) { - printf("Field: %8s %-16s at %u\n", + printf("Field: %8s %-16s at %u%s\n", type_name[prog->fields[i].type], prog_getstring(prog, prog->fields[i].name), - (unsigned int)prog->fields[i].offset); + (unsigned int)prog->fields[i].offset, + ((prog->fields[i].type & DEF_SAVEGLOBAL) ? " [SAVE]" : "")); } } - else - { + if (opts_printfuns) { + for (i = 0; i < vec_size(prog->functions); ++i) { + int32_t a; + printf("Function: %-16s taking %i parameters:(", + prog_getstring(prog, prog->functions[i].name), + (unsigned int)prog->functions[i].nargs); + for (a = 0; a < prog->functions[i].nargs; ++a) { + printf(" %i", prog->functions[i].argsize[a]); + } + printf(") locals: %i + %i\n", + prog->functions[i].firstlocal, + prog->functions[i].locals); + } + } + if (!noexec) { + for (i = 1; i < vec_size(prog->functions); ++i) { + const char *name = prog_getstring(prog, prog->functions[i].name); + if (!strcmp(name, "main")) + fnmain = (qcint)i; + } if (fnmain > 0) { prog_main_setparams(prog); @@ -953,7 +1070,7 @@ void prog_disasm_function(qc_program *prog, size_t id) printf("FUNCTION \"%s\"\n", prog_getstring(prog, fdef->name)); st = prog->code + fdef->entry; - while (st->opcode != AINSTR_END) { + while (st->opcode != INSTR_DONE) { prog_print_statement(prog, st); ++st; } @@ -1128,7 +1245,7 @@ while (1) { qcvmerror(prog, "progs `%s` attempted to read an out of bounds entity", prog->filename); goto cleanup; } - if (OPB->_int < 0 || OPB->_int + 3 > prog->entityfields) + if (OPB->_int < 0 || OPB->_int + 3 > (qcint)prog->entityfields) { qcvmerror(prog, "prog `%s` attempted to read an invalid field from entity (%i)", prog->filename, @@ -1176,11 +1293,11 @@ while (1) { case INSTR_STOREP_ENT: case INSTR_STOREP_FLD: case INSTR_STOREP_FNC: - if (OPB->_int < 0 || OPB->_int >= vec_size(prog->entitydata)) { + if (OPB->_int < 0 || OPB->_int >= (qcint)vec_size(prog->entitydata)) { qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int); goto cleanup; } - if (OPB->_int < prog->entityfields && !prog->allowworldwrites) + if (OPB->_int < (qcint)prog->entityfields && !prog->allowworldwrites) qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n", prog->filename, prog_getstring(prog, prog_entfield(prog, OPB->_int)->name), @@ -1189,11 +1306,11 @@ while (1) { ptr->_int = OPA->_int; break; case INSTR_STOREP_V: - if (OPB->_int < 0 || OPB->_int + 2 >= vec_size(prog->entitydata)) { + if (OPB->_int < 0 || OPB->_int + 2 >= (qcint)vec_size(prog->entitydata)) { qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int); goto cleanup; } - if (OPB->_int < prog->entityfields && !prog->allowworldwrites) + if (OPB->_int < (qcint)prog->entityfields && !prog->allowworldwrites) qcvmerror(prog, "`%s` tried to assign to world.%s (field %i)\n", prog->filename, prog_getstring(prog, prog_entfield(prog, OPB->_int)->name), @@ -1254,7 +1371,7 @@ while (1) { if (!OPA->function) qcvmerror(prog, "NULL function in `%s`", prog->filename); - if(!OPA->function || OPA->function >= (unsigned int)vec_size(prog->functions)) + if(!OPA->function || OPA->function >= (qcint)vec_size(prog->functions)) { qcvmerror(prog, "CALL outside the program in `%s`", prog->filename); goto cleanup; @@ -1268,8 +1385,8 @@ while (1) { if (newf->entry < 0) { /* negative statements are built in functions */ - int builtinnumber = -newf->entry; - if (builtinnumber < prog->builtins_count && prog->builtins[builtinnumber]) + qcint builtinnumber = -newf->entry; + if (builtinnumber < (qcint)prog->builtins_count && prog->builtins[builtinnumber]) prog->builtins[builtinnumber](prog); else qcvmerror(prog, "No such builtin #%i in %s! Try updating your gmqcc sources",