-int main(int argc, char **argv) {
- size_t itr = 0;
- char *app = &argv[0][0];
- FILE *fpp = NULL;
- lex_file *lex = 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;
- }
- #define param_argument(argtype) do { \
- argitem item; \
- if (argv[1][2]) { \
- item.name = util_strdup(&argv[1][2]); \
- item.type = argtype; \
- items_add(item); \
- } else { \
- ++argv; \
- --argc; \
- if (argc <= 1) \
- goto clean_params_usage; \
- item.name = util_strdup(argv[1]); \
- item.type = argtype; \
- items_add(item); \
- } \
- } while (0)
-
- case 'c': { param_argument(0); break; } /* compile */
- case 'a': { param_argument(1); break; } /* assemble */
- case 'i': { param_argument(2); break; } /* includes */
- #undef parm_argument
- default:
- if (util_strncmpexact(&argv[1][1], "debug" , 5)) { opts_debug = true; break; }
- if (util_strncmpexact(&argv[1][1], "memchk", 6)) { opts_memchk = true; break; }
- if (util_strncmpexact(&argv[1][1], "help", 4)) {
- return usage(app);
- }
- /* compiler type selection */
- if (util_strncmpexact(&argv[1][1], "std=qcc" , 7 )) { opts_compiler = COMPILER_QCC; break; }
- if (util_strncmpexact(&argv[1][1], "std=fteqcc", 10)) { opts_compiler = COMPILER_FTEQCC; break; }
- if (util_strncmpexact(&argv[1][1], "std=qccx", 8 )) { opts_compiler = COMPILER_QCCX; break; }
- if (util_strncmpexact(&argv[1][1], "std=gmqcc", 9 )) { opts_compiler = COMPILER_GMQCC; break; }
- if (util_strncmpexact(&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;
+static bool options_setflag_all(const char *name, bool on, uint32_t *flags, const opts_flag_def *list, size_t listsize) {
+ size_t i;
+
+ for (i = 0; i < listsize; ++i) {
+ if (!strcmp(name, list[i].name)) {
+ longbit lb = list[i].bit;
+#if 0
+ if (on)
+ flags[lb.idx] |= (1<<(lb.bit));
+ else
+ flags[lb.idx] &= ~(1<<(lb.bit));
+#else
+ if (on)
+ flags[0] |= (1<<lb);
+ else
+ flags[0] &= ~(1<<(lb));
+#endif
+ return true;
+ }
+ }
+ return false;
+}
+static bool options_setflag(const char *name, bool on) {
+ return options_setflag_all(name, on, opts_flags, opts_flag_list, COUNT_FLAGS);
+}
+static bool options_setwarn(const char *name, bool on) {
+ return options_setflag_all(name, on, opts_warn, opts_warn_list, COUNT_WARNINGS);
+}
+
+static bool options_witharg(int *argc_, char ***argv_, char **out) {
+ int argc = *argc_;
+ char **argv = *argv_;
+
+ if (argv[0][2]) {
+ *out = argv[0]+2;
+ return true;
+ }
+ /* eat up the next */
+ if (argc < 2) /* no parameter was provided */
+ return false;
+
+ *out = argv[1];
+ --*argc_;
+ ++*argv_;
+ return true;
+}
+
+static bool options_long_witharg_all(const char *optname, int *argc_, char ***argv_, char **out, int ds, bool split) {
+ int argc = *argc_;
+ char **argv = *argv_;
+
+ size_t len = strlen(optname);
+
+ if (strncmp(argv[0]+ds, optname, len))
+ return false;
+
+ /* it's --optname, check how the parameter is supplied */
+ if (argv[0][ds+len] == '=') {
+ /* using --opt=param */
+ *out = argv[0]+ds+len+1;
+ return true;
+ }
+
+ if (!split || argc < ds) /* no parameter was provided, or only single-arg form accepted */
+ return false;
+
+ /* using --opt param */
+ *out = argv[1];
+ --*argc_;
+ ++*argv_;
+ return true;
+}
+static bool options_long_witharg(const char *optname, int *argc_, char ***argv_, char **out) {
+ return options_long_witharg_all(optname, argc_, argv_, out, 2, true);
+}
+static bool options_long_gcc(const char *optname, int *argc_, char ***argv_, char **out) {
+ return options_long_witharg_all(optname, argc_, argv_, out, 1, false);
+}
+
+static bool options_parse(int argc, char **argv) {
+ bool argend = false;
+ size_t itr;
+ char buffer[1024];
+ while (!argend && argc > 1) {
+ char *argarg;
+ argitem item;
+
+ ++argv;
+ --argc;
+
+ if (argv[0][0] == '-') {
+ /* All gcc-type long options */
+ if (options_long_gcc("std", &argc, &argv, &argarg)) {
+ if (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default"))
+ opts_standard = COMPILER_GMQCC;
+ else if (!strcmp(argarg, "qcc"))
+ opts_standard = COMPILER_QCC;
+ else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc"))
+ opts_standard = COMPILER_FTEQCC;
+ else if (!strcmp(argarg, "qccx"))
+ opts_standard = COMPILER_QCCX;
+ else {
+ printf("Unknown standard: %s\n", argarg);
+ return false;