- struct stat chk;
- const char *ofile = NULL;
- const char *ifile = NULL;
- int i;
- if (argc <= 2)
- return usage(*argv);
-
- for (i=0; i<argc; i++) {
- if (argc != i + 1) {
- switch(argv[i][0]) {
- case '-':
- switch(argv[i][1]) {
- case 'f': ifile = argv[i+1]; break;
- case 'o': ofile = argv[i+1]; break;
- }
- break;
- }
- }
- }
-
- if (!ofile || !ifile)
- return usage(*argv);
-
- printf("ifile: %s\n", ifile);
- printf("ofile: %s\n", ofile);
-
- /* we check here for file existance, not in the lexer */
- if (stat(ifile, &chk) != 0)
- return error(ERROR_COMPILER, "source file `%s` not found\n", ifile);
-
- struct lex_file *lex = lex_open(ifile);
- 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;