X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=main.c;h=54c64b639ca4ae0103ad60ce52e2cd01f5122d1b;hb=ae12583ada0c94310052b64e71240499a05b9417;hp=7c4ae875a7e6f662aaad043896927343ceab2a6a;hpb=33b1995fa55632c864909c89a8652facdd252718;p=xonotic%2Fgmqcc.git diff --git a/main.c b/main.c index 7c4ae87..54c64b6 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 + * Copyright (C) 2012 * Dale Weiler * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -21,140 +21,86 @@ * SOFTWARE. */ #include "gmqcc.h" -// todo CLEANUP this argitem thing -typedef struct { char *name, type; } argitem; -VECTOR_MAKE(argitem, items); -/* global options */ -bool opts_debug = false; -bool opts_memchk = false; -bool opts_darkplaces_stringtablebug = false; -bool opts_omit_nullcode = false; -int opts_compiler = COMPILER_GMQCC; +static const char *output = "progs.dat"; +static const char *input = NULL; -static const int usage(const char *const app) { - printf("usage:\n" - " %s -c -oprog.dat -- compile file\n" - " %s -a -oprog.dat -- assemble file\n" - " %s -c -i -oprog.dat -- compile together (allowed multiple -i)\n" - " %s -a -i -oprog.dat -- assemble together(allowed multiple -i)\n" - " example:\n" - " %s -cfoo.qc -ibar.qc -oqc.dat -afoo.qs -ibar.qs -oqs.dat\n" - " additional flags:\n" - " -debug -- turns on compiler debug messages\n" - " -memchk -- turns on compiler memory leak check\n" - " -help -- prints this help/usage text\n" - " -std -- select the QuakeC compile type (types below):\n" - " -std=qcc -- original QuakeC\n" - " -std=ftqecc -- fteqcc QuakeC\n" - " -std=qccx -- qccx QuakeC\n" - " -std=gmqcc -- this compiler QuakeC (default selection)\n" - " codegen flags:\n" - " -fdarkplaces-string-table-bug -- patches the string table to work with bugged versions of darkplaces\n" - " -fomit-nullcode -- omits the generation of null code (will break everywhere see propsal.txt)\n", - app,app,app,app,app - ); - return -1; -} +#define OptReq(opt, body) \ + case opt: \ + if (argv[0][2]) argarg = argv[0]+2; \ + else { \ + if (argc < 2) { \ + printf("option -%c requires an argument\n", opt); \ + exit(1); \ + } \ + argarg = argv[1]; \ + --argc; \ + ++argv; \ + } \ + do { body } while (0); \ + break; -int main(int argc, char **argv) { - size_t itr = 0; - char *app = &argv[0][0]; - FILE *fpp = NULL; +#define LongReq(opt, body) \ + if (!strcmp(argv[0], opt)) { \ + if (argc < 2) { \ + printf("option " opt " requires an argument\n"); \ + exit(1); \ + } \ + argarg = argv[1]; \ + --argc; \ + ++argv; \ + do { body } while (0); \ + break; \ + } else if (!strncmp(argv[0], opt "=", sizeof(opt "="))) \ + { \ + argarg = argv[0] + sizeof(opt "="); \ + do { body } while (0); \ + break; \ + } - /* - * Parse all command line arguments. This is rather annoying to do - * because of all tiny corner cases. - */ - if (argc <= 1 || (argv[1][0] != '-')) - return usage(app); +bool parser_compile(const char *filename, const char *datfile); +int main(int argc, char **argv) { + const char *argarg; + char opt; - while ((argc > 1) && argv[1][0] == '-') { - switch (argv[1][1]) { - case 'v': { - printf("GMQCC:\n" - " version: %d.%d.%d (0x%08X)\n" - " build date: %s\n" - " build time: %s\n", - (GMQCC_VERSION >> 16) & 0xFF, - (GMQCC_VERSION >> 8) & 0xFF, - (GMQCC_VERSION >> 0) & 0xFF, - (GMQCC_VERSION), - __DATE__, - __TIME__ - ); - return 0; - } - case 'c': items_add((argitem){util_strdup(&argv[1][2]), 0}); break; /* compile */ - case 'a': items_add((argitem){util_strdup(&argv[1][2]), 1}); break; /* assemble */ - case 'i': items_add((argitem){util_strdup(&argv[1][2]), 2}); break; /* includes */ - default: - if (!strncmp(&argv[1][1], "debug" , 5)) { opts_debug = true; break; } - if (!strncmp(&argv[1][1], "memchk", 6)) { opts_memchk = true; break; } - if (!strncmp(&argv[1][1], "help", 4)) { - return usage(app); - break; - } - /* compiler type selection */ - if (!strncmp(&argv[1][1], "std=qcc" , 7 )) { opts_compiler = COMPILER_QCC; break; } - if (!strncmp(&argv[1][1], "std=fteqcc", 10)) { opts_compiler = COMPILER_FTEQCC; break; } - if (!strncmp(&argv[1][1], "std=qccx", 8 )) { opts_compiler = COMPILER_QCCX; break; } - if (!strncmp(&argv[1][1], "std=gmqcc", 9 )) { opts_compiler = COMPILER_GMQCC; break; } - if (!strncmp(&argv[1][1], "std=", 4 )) { - printf("invalid std selection, supported types:\n" - " -std=qcc -- original QuakeC\n" - " -std=ftqecc -- fteqcc QuakeC\n" - " -std=qccx -- qccx QuakeC\n" - " -std=gmqcc -- this compiler QuakeC (default selection)\n"); - return 0; - } + util_debug("COM", "starting ...\n"); - /* code specific switches */ - if (!strcmp(&argv[1][1], "fdarkplaces-stringtablebug")) { - opts_darkplaces_stringtablebug = true; - break; - } - if (!strcmp(&argv[1][1], "fomit-nullcode")) { - opts_omit_nullcode = true; + --argc; + ++argv; + while (argc > 0) { + if (argv[0][0] == '-') { + opt = argv[0][1]; + switch (opt) + { + OptReq('o', output = argarg; ); + case '-': + LongReq("--output", output = argarg; ); + default: + printf("Unrecognized option: %s\n", argv[0]); break; - } - return usage(app); - + } + } + else + { + if (input) { + printf("Onlyh 1 input file allowed\n"); + exit(1); + } + input = argv[0]; } - ++argv; --argc; + ++argv; } - /* - * options could depend on another option, this is where option - * validity checking like that would take place. - */ - if (opts_memchk && !opts_debug) - printf("Warning: cannot enable -memchk, without -debug.\n"); + if (!input) { + printf("must specify an input file\n"); + } - util_debug("COM", "starting ...\n"); - /* multi file multi path compilation system */ - for (; itr < items_elements; itr++) { - switch (items_data[itr].type) { - case 0: - fpp = fopen(items_data[itr].name, "r"); - lex_file *lex = lex_open(fpp); - parse_gen(lex); - lex_close(lex); - break; - case 1: - asm_init (items_data[itr].name, &fpp); - asm_parse(fpp); - asm_close(fpp); - break; - } + if (!parser_compile(input, output)) { + printf("There were compile errors\n"); } - util_debug("COM", "cleaning ...\n"); - /* clean list */ - for (itr = 0; itr < items_elements; itr++) - mem_d(items_data[itr].name); - mem_d(items_data); + util_debug("COM", "cleaning ...\n"); util_meminfo(); return 0;