int main(int argc, char **argv) { size_t i; qcint_t fnmain = -1; qc_program_t *prog; 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 noexec = false; const char *progsfile = nullptr; const char **dis_list = nullptr; int opts_v = 0; arg0 = argv[0]; if (argc < 2) { usage(); exit(EXIT_FAILURE); } while (argc > 1) { if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-help") || !strcmp(argv[1], "--help")) { usage(); exit(EXIT_SUCCESS); } else if (!strcmp(argv[1], "-v")) { ++opts_v; --argc; ++argv; } else if (!strncmp(argv[1], "-vv", 3)) { const char *av = argv[1]+1; for (; *av; ++av) { if (*av == 'v') ++opts_v; else { usage(); exit(EXIT_FAILURE); } } --argc; ++argv; } else if (!strcmp(argv[1], "-version") || !strcmp(argv[1], "--version")) { version(); exit(EXIT_SUCCESS); } else 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; noexec = true; } else if (!strcmp(argv[1], "-disasm")) { --argc; ++argv; opts_disasm = true; noexec = true; } else if (!strcmp(argv[1], "-disasm-func")) { --argc; ++argv; if (argc <= 1) { usage(); exit(EXIT_FAILURE); } vec_push(dis_list, argv[1]); --argc; ++argv; 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") || !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; else p.vtype = TYPE_VOID; --argc; ++argv; if (argc < 2) { usage(); exit(EXIT_FAILURE); } 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) { fprintf(stderr, "only 1 program file may be specified\n"); usage(); exit(EXIT_FAILURE); } progsfile = argv[1]; --argc; ++argv; } else { fprintf(stderr, "unknown parameter: %s\n", argv[1]); usage(); exit(EXIT_FAILURE); } } if (argc == 2 && !progsfile) { progsfile = argv[1]; --argc; ++argv; } if (!progsfile) { fprintf(stderr, "must specify a program to execute\n"); usage(); exit(EXIT_FAILURE); } prog = prog_load(progsfile, noexec); if (!prog) { fprintf(stderr, "failed to load program '%s'\n", progsfile); exit(EXIT_FAILURE); } prog->builtins = qc_builtins; prog->builtins_count = GMQCC_ARRAY_COUNT(qc_builtins); if (opts_info) { printf("Program's system-checksum = 0x%04x\n", (unsigned int)prog->crc16); printf("Entity field space: %u\n", (unsigned int)prog->entityfields); printf("Globals: %zu\n", prog->globals.size()); printf("Counts:\n" " code: %zu\n" " defs: %zu\n" " fields: %zu\n" " functions: %zu\n" " strings: %zu\n", prog->code.size(), prog->defs.size(), prog->fields.size(), prog->functions.size(), prog->strings.size()); } if (opts_info) { prog_delete(prog); return 0; } for (i = 0; i < vec_size(dis_list); ++i) { size_t k; printf("Looking for `%s`\n", dis_list[i]); for (k = 1; k < prog->functions.size(); ++k) { const char *name = prog_getstring(prog, prog->functions[k].name); if (!strcmp(name, dis_list[i])) { prog_disasm_function(prog, k); break; } } } if (opts_disasm) { for (i = 1; i < prog->functions.size(); ++i) prog_disasm_function(prog, i); return 0; } if (opts_printdefs) { const char *getstring = nullptr; for (auto &it : prog->defs) { printf("Global: %8s %-16s at %u%s", type_name[it.type & DEF_TYPEMASK], prog_getstring(prog, it.name), (unsigned int)it.offset, ((it.type & DEF_SAVEGLOBAL) ? " [SAVE]" : "")); if (opts_v) { switch (it.type & DEF_TYPEMASK) { case TYPE_FLOAT: printf(" [init: %g]", ((qcany_t*)(&prog->globals[0] + it.offset))->_float); break; case TYPE_INTEGER: printf(" [init: %i]", (int)( ((qcany_t*)(&prog->globals[0] + it.offset))->_int )); break; case TYPE_ENTITY: case TYPE_FUNCTION: case TYPE_FIELD: case TYPE_POINTER: printf(" [init: %u]", (unsigned)( ((qcany_t*)(&prog->globals[0] + it.offset))->_int )); break; case TYPE_STRING: getstring = prog_getstring(prog, ((qcany_t*)(&prog->globals[0] + it.offset))->string); printf(" [init: `"); print_escaped_string(getstring, strlen(getstring)); printf("`]\n"); break; default: break; } } printf("\n"); } } if (opts_printfields) { for (auto &it : prog->fields) { printf("Field: %8s %-16s at %d%s\n", type_name[it.type], prog_getstring(prog, it.name), it.offset, ((it.type & DEF_SAVEGLOBAL) ? " [SAVE]" : "")); } } if (opts_printfuns) { for (auto &it : prog->functions) { int32_t a; printf("Function: %-16s taking %u parameters:(", prog_getstring(prog, it.name), (unsigned int)it.nargs); for (a = 0; a < it.nargs; ++a) { printf(" %i", it.argsize[a]); } if (opts_v > 1) { int32_t start = it.entry; if (start < 0) printf(") builtin %i\n", (int)-start); else { size_t funsize = 0; prog_section_statement_t *st = &prog->code[0] + start; for (;st->opcode != INSTR_DONE; ++st) ++funsize; printf(") - %zu instructions", funsize); if (opts_v > 2) { printf(" - locals: %i + %i\n", it.firstlocal, it.locals); } else printf("\n"); } } else if (opts_v) { printf(") locals: %i + %i\n", it.firstlocal, it.locals); } else printf(")\n"); } } if (!noexec) { for (i = 1; i < prog->functions.size(); ++i) { const char *name = prog_getstring(prog, prog->functions[i].name); if (!strcmp(name, "main")) fnmain = (qcint_t)i; } if (fnmain > 0) { prog_main_setparams(prog); prog_exec(prog, &prog->functions[fnmain], xflags, VM_JUMPS_DEFAULT); } else fprintf(stderr, "No main function found\n"); } prog_delete(prog); return 0; }
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_printfuns = false; bool opts_disasm = false; bool opts_info = false; bool noexec = false; const char *progsfile = NULL; arg0 = argv[0]; if (argc < 2) { usage(); exit(1); } 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; } else if (!strcmp(argv[1], "-profile")) { --argc; ++argv; xflags |= VMXF_PROFILE; } else if (!strcmp(argv[1], "-info")) { --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") || !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(); 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(progsfile); if (!prog) { printf("failed to load program '%s'\n", progsfile); exit(1); } prog->builtins = qc_builtins; prog->builtins_count = qc_builtins_count; if (opts_info) { 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)); } if (opts_info) { prog_delete(prog); return 0; } if (opts_disasm) { for (i = 1; i < vec_size(prog->functions); ++i) prog_disasm_function(prog, i); return 0; } if (opts_printdefs) { for (i = 0; i < vec_size(prog->defs); ++i) { 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, ((prog->defs[i].type & DEF_SAVEGLOBAL) ? " [SAVE]" : "")); } } if (opts_printfields) { for (i = 0; i < vec_size(prog->fields); ++i) { 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, ((prog->fields[i].type & DEF_SAVEGLOBAL) ? " [SAVE]" : "")); } } 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); prog_exec(prog, &prog->functions[fnmain], xflags, VM_JUMPS_DEFAULT); } else printf("No main function found\n"); } prog_delete(prog); return 0; }