Example #1
0
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;
}
Example #2
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;
}