X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=main.c;h=006fdea863722c2d5b9c56666eb816c41b976c00;hb=de01d34925cb609607e76b3cb7e7a48312f2cc8e;hp=8718a72afb74b14051b9e2b1df0ed71a223cd4f3;hpb=48a95ec3c9a4a8601f97c8ac1adbd7d94ba15465;p=xonotic%2Fgmqcc.git diff --git a/main.c b/main.c index 8718a72..006fdea 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2012 - * Dale Weiler + * Dale Weiler * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -21,17 +21,141 @@ * 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 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; +} int main(int argc, char **argv) { - if (argc <= 1) { - printf("Usage: %s infile.qc outfile\n", *argv); - return -1; - } - - struct lex_file *lex = lex_open(argv[1]); - lex_debug(lex); - parse (lex); - lex_close(lex); - - return 0; + size_t itr = 0; + char *app = &argv[0][0]; + FILE *fpp = NULL; + + /* + * 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); + + 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; + } + + /* 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; + break; + } + return usage(app); + + } + ++argv; + --argc; + } + + /* + * 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"); + + 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"); + struct 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; + } + } + + 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_meminfo(); + return 0; }