X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=main.c;h=6a0fe1667a60a740fd7db2cd23323edaaa0c787b;hb=4ef0e8c66e3373a5fd824864735185d1eb28a13d;hp=79b70febed22d1766a7ecc206c9652712635dbc1;hpb=16ae493a9a6df3baba3e160b0fefbc5143733423;p=xonotic%2Fgmqcc.git diff --git a/main.c b/main.c index 79b70fe..6a0fe16 100644 --- a/main.c +++ b/main.c @@ -24,33 +24,17 @@ #include "gmqcc.h" #include "lexer.h" -uint32_t opts_flags[1 + (COUNT_FLAGS / 32)]; -uint32_t opts_optimization[1 + (COUNT_OPTIMIZATIONS / 32)]; - -/* counter increased in ir.c */ -unsigned int optimization_count[COUNT_OPTIMIZATIONS]; - -uint32_t opts_O = 1; -const char *opts_output = "progs.dat"; -int opts_standard = COMPILER_GMQCC; -bool opts_debug = false; -bool opts_memchk = false; -bool opts_dumpfin = false; -bool opts_dump = false; -bool opts_forcecrc = false; -bool opts_pp_only = false; -size_t opts_max_array_size = (1024 << 3); - -uint16_t opts_forced_crc; - -static bool opts_output_wasset = false; +/* TODO: cleanup this whole file .. it's a fuckign mess */ /* set by the standard */ const oper_info *operators = NULL; size_t operator_count = 0; +static bool opts_output_wasset = false; -typedef struct { char *filename; int type; } argitem; +typedef struct { char *filename; int type; } argitem; +typedef struct { char *name; char *value; } ppitem; static argitem *items = NULL; +static ppitem *ppems = NULL; #define TYPE_QC 0 #define TYPE_ASM 1 @@ -58,6 +42,16 @@ static argitem *items = NULL; static const char *app_name; +static void version() { + con_out("GMQCC %d.%d.%d Built %s %s\n", + GMQCC_VERSION_MAJOR, + GMQCC_VERSION_MINOR, + GMQCC_VERSION_PATCH, + __DATE__, + __TIME__ + ); +} + static int usage() { con_out("usage: %s [options] [files...]", app_name); con_out("options:\n" @@ -65,60 +59,30 @@ static int usage() { " -debug turns on compiler debug messages\n" " -memchk turns on compiler memory leak check\n"); con_out(" -o, --output=file output file, defaults to progs.dat\n" - " -a filename add an asm file to be assembled\n" " -s filename add a progs.src file to be used\n"); con_out(" -E stop after preprocessing\n"); - con_out(" -f enable a flag\n" - " -fno- disable a flag\n" - " -std standard select one of the following standards\n" + con_out(" -config file use the specified ini file\n"); + con_out(" -std=standard select one of the following standards\n" " -std=qcc original QuakeC\n" " -std=fteqcc fteqcc QuakeC\n" " -std=gmqcc this compiler (default)\n"); + con_out(" -f enable a flag\n" + " -fno- disable a flag\n" + " -fhelp list possible flags\n"); con_out(" -W enable a warning\n" " -Wno- disable a warning\n" " -Wall enable all warnings\n" " -Werror treat warnings as errors\n"); + con_out(" -Whelp list possible warnings\n"); + con_out(" -O optimization level\n" + " -O enable specific optimization\n" + " -Ono- disable specific optimization\n" + " -Ohelp list optimizations\n"); con_out(" -force-crc=num force a specific checksum into the header\n"); - con_out("\n"); - con_out("flags:\n" - " -fadjust-vector-fields\n" - " when assigning a vector field, its _y and _z fields also get assigned\n" - ); return -1; } -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<= opts_opt_oflag[i]); -} - static bool options_parse(int argc, char **argv) { bool argend = false; size_t itr; char buffer[1024]; char *redirout = (char*)stdout; char *redirerr = (char*)stderr; + char *config = NULL; while (!argend && argc > 1) { char *argarg; argitem item; + ppitem macro; ++argv; --argc; if (argv[0][0] == '-') { - /* All gcc-type long options */ + /* All gcc-type long options */ if (options_long_gcc("std", &argc, &argv, &argarg)) { - if (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default")) { - options_set(opts_flags, ADJUST_VECTOR_FIELDS, true); - opts_standard = COMPILER_GMQCC; + if (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default")) { + + opts_set(opts.flags, ADJUST_VECTOR_FIELDS, true); + opts.standard = COMPILER_GMQCC; + } else if (!strcmp(argarg, "qcc")) { - options_set(opts_flags, ADJUST_VECTOR_FIELDS, false); - options_set(opts_flags, ASSIGN_FUNCTION_TYPES, true); - opts_standard = COMPILER_QCC; + + opts_set(opts.flags, ADJUST_VECTOR_FIELDS, false); + opts_set(opts.flags, ASSIGN_FUNCTION_TYPES, true); + opts.standard = COMPILER_QCC; + } else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc")) { - options_set(opts_flags, FTEPP, true); - options_set(opts_flags, TRANSLATABLE_STRINGS, true); - options_set(opts_flags, ADJUST_VECTOR_FIELDS, false); - options_set(opts_flags, ASSIGN_FUNCTION_TYPES, true); - options_set(opts_warn, WARN_TERNARY_PRECEDENCE, true); - options_set(opts_flags, CORRECT_TERNARY, false); - opts_standard = COMPILER_FTEQCC; + + opts_set(opts.flags, FTEPP, true); + opts_set(opts.flags, TRANSLATABLE_STRINGS, true); + opts_set(opts.flags, ADJUST_VECTOR_FIELDS, false); + opts_set(opts.flags, ASSIGN_FUNCTION_TYPES, true); + opts_set(opts.warn, WARN_TERNARY_PRECEDENCE, true); + opts_set(opts.flags, CORRECT_TERNARY, false); + opts.standard = COMPILER_FTEQCC; + } else if (!strcmp(argarg, "qccx")) { - options_set(opts_flags, ADJUST_VECTOR_FIELDS, false); - opts_standard = COMPILER_QCCX; + + opts_set(opts.flags, ADJUST_VECTOR_FIELDS, false); + opts.standard = COMPILER_QCCX; + } else { con_out("Unknown standard: %s\n", argarg); return false; @@ -234,8 +185,8 @@ static bool options_parse(int argc, char **argv) { continue; } if (options_long_gcc("force-crc", &argc, &argv, &argarg)) { - opts_forcecrc = true; - opts_forced_crc = strtol(argarg, NULL, 0); + opts.forcecrc = true; + opts.forced_crc = strtol(argarg, NULL, 0); continue; } if (options_long_gcc("redirout", &argc, &argv, &redirout)) { @@ -246,6 +197,10 @@ static bool options_parse(int argc, char **argv) { con_change(redirout, redirerr); continue; } + if (options_long_gcc("config", &argc, &argv, &argarg)) { + config = argarg; + continue; + } /* show defaults (like pathscale) */ if (!strcmp(argv[0]+1, "show-defaults")) { @@ -273,19 +228,19 @@ static bool options_parse(int argc, char **argv) { } if (!strcmp(argv[0]+1, "debug")) { - opts_debug = true; + opts.debug = true; continue; } if (!strcmp(argv[0]+1, "dump")) { - opts_dump = true; + opts.dump = true; continue; } if (!strcmp(argv[0]+1, "dumpfin")) { - opts_dumpfin = true; + opts.dumpfin = true; continue; } if (!strcmp(argv[0]+1, "memchk")) { - opts_memchk = true; + opts.memchk = true; continue; } if (!strcmp(argv[0]+1, "nocolor")) { @@ -300,13 +255,35 @@ static bool options_parse(int argc, char **argv) { exit(0); /* break; never reached because of exit(0) */ + case 'v': + version(); + exit(0); + case 'E': - opts_pp_only = true; + opts.pp_only = true; break; /* debug turns on -flno */ case 'g': - options_setflag("LNO", true); + opts_setflag("LNO", true); + opts.g = true; + break; + + case 'D': + if (!strlen(argv[0]+2)) { + con_err("expected name after -D\n"); + exit(0); + } + + if (!(argarg = strchr(argv[0] + 2, '='))) { + macro.name = util_strdup(argv[0]+2); + macro.value = NULL; + } else { + *argarg='\0'; /* terminate for name */ + macro.name = util_strdup(argv[0]+2); + macro.value = util_strdup(argarg+1); + } + vec_push(ppems, macro); break; /* handle all -fflags */ @@ -321,12 +298,12 @@ static bool options_parse(int argc, char **argv) { exit(0); } else if (!strncmp(argv[0]+2, "NO_", 3)) { - if (!options_setflag(argv[0]+5, false)) { + if (!opts_setflag(argv[0]+5, false)) { con_out("unknown flag: %s\n", argv[0]+2); return false; } } - else if (!options_setflag(argv[0]+2, true)) { + else if (!opts_setflag(argv[0]+2, true)) { con_out("unknown flag: %s\n", argv[0]+2); return false; } @@ -342,30 +319,30 @@ static bool options_parse(int argc, char **argv) { exit(0); } else if (!strcmp(argv[0]+2, "NO_ERROR")) { - opts_werror = false; + opts.werror = false; break; } else if (!strcmp(argv[0]+2, "ERROR")) { - opts_werror = true; + opts.werror = true; break; } else if (!strcmp(argv[0]+2, "NONE")) { - for (itr = 0; itr < sizeof(opts_warn)/sizeof(opts_warn[0]); ++itr) - opts_warn[itr] = 0; + for (itr = 0; itr < sizeof(opts.warn)/sizeof(opts.warn[0]); ++itr) + opts.warn[itr] = 0; break; } else if (!strcmp(argv[0]+2, "ALL")) { - for (itr = 0; itr < sizeof(opts_warn)/sizeof(opts_warn[0]); ++itr) - opts_warn[itr] = 0xFFFFFFFFL; + for (itr = 0; itr < sizeof(opts.warn)/sizeof(opts.warn[0]); ++itr) + opts.warn[itr] = 0xFFFFFFFFL; break; } if (!strncmp(argv[0]+2, "NO_", 3)) { - if (!options_setwarn(argv[0]+5, false)) { + if (!opts_setwarn(argv[0]+5, false)) { con_out("unknown warning: %s\n", argv[0]+2); return false; } } - else if (!options_setwarn(argv[0]+2, true)) { + else if (!opts_setwarn(argv[0]+2, true)) { con_out("unknown warning: %s\n", argv[0]+2); return false; } @@ -377,8 +354,8 @@ static bool options_parse(int argc, char **argv) { return false; } if (isdigit(argarg[0])) { - opts_O = atoi(argarg); - set_optimizations(opts_O); + opts.O = atoi(argarg); + opts_setoptimlevel(opts.O); } else { util_strtocmd(argarg, argarg, strlen(argarg)+1); if (!strcmp(argarg, "HELP")) { @@ -390,15 +367,15 @@ static bool options_parse(int argc, char **argv) { exit(0); } else if (!strcmp(argarg, "ALL")) - set_optimizations(opts_O = 9999); + opts_setoptimlevel(opts.O = 9999); else if (!strncmp(argarg, "NO_", 3)) { - if (!options_setoptim(argarg+3, false)) { + if (!opts_setoptim(argarg+3, false)) { con_out("unknown optimization: %s\n", argarg+3); return false; } } else { - if (!options_setoptim(argarg, true)) { + if (!opts_setoptim(argarg, true)) { con_out("unknown optimization: %s\n", argarg); return false; } @@ -411,7 +388,7 @@ static bool options_parse(int argc, char **argv) { con_out("option -o requires an argument: the output file name\n"); return false; } - opts_output = argarg; + opts.output = argarg; opts_output_wasset = true; break; @@ -438,10 +415,14 @@ static bool options_parse(int argc, char **argv) { usage(); exit(0); } + else if (!strcmp(argv[0]+2, "version")) { + version(); + exit(0); + } else { /* All long options with arguments */ if (options_long_witharg("output", &argc, &argv, &argarg)) { - opts_output = argarg; + opts.output = argarg; opts_output_wasset = true; } else { con_out("Unknown parameter: %s\n", argv[0]); @@ -463,6 +444,7 @@ static bool options_parse(int argc, char **argv) { vec_push(items, item); } } + opts_ini_init(config); return true; } @@ -494,54 +476,29 @@ static bool progs_nextline(char **out, size_t *alen,FILE *src) { int main(int argc, char **argv) { size_t itr; - int retval = 0; - bool opts_output_free = false; - bool operators_free = false; - bool progs_src = false; - FILE *outfile = NULL; + int retval = 0; + bool opts_output_free = false; + bool operators_free = false; + bool progs_src = false; + FILE *outfile = NULL; app_name = argv[0]; - con_init(); - - /* default options / warn flags */ - options_set(opts_warn, WARN_UNKNOWN_CONTROL_SEQUENCE, true); - options_set(opts_warn, WARN_EXTENSIONS, true); - options_set(opts_warn, WARN_FIELD_REDECLARED, true); - options_set(opts_warn, WARN_TOO_FEW_PARAMETERS, true); - options_set(opts_warn, WARN_MISSING_RETURN_VALUES, true); - options_set(opts_warn, WARN_USED_UNINITIALIZED, true); - options_set(opts_warn, WARN_LOCAL_CONSTANTS, true); - options_set(opts_warn, WARN_VOID_VARIABLES, true); - options_set(opts_warn, WARN_IMPLICIT_FUNCTION_POINTER, true); - options_set(opts_warn, WARN_VARIADIC_FUNCTION, true); - options_set(opts_warn, WARN_FRAME_MACROS, true); - options_set(opts_warn, WARN_UNUSED_VARIABLE, true); - options_set(opts_warn, WARN_EFFECTLESS_STATEMENT, true); - options_set(opts_warn, WARN_END_SYS_FIELDS, true); - options_set(opts_warn, WARN_ASSIGN_FUNCTION_TYPES, true); - options_set(opts_warn, WARN_PREPROCESSOR, true); - options_set(opts_warn, WARN_MULTIFILE_IF, true); - options_set(opts_warn, WARN_DOUBLE_DECLARATION, true); - options_set(opts_warn, WARN_CONST_VAR, true); - options_set(opts_warn, WARN_MULTIBYTE_CHARACTER, true); - - options_set(opts_flags, ADJUST_VECTOR_FIELDS, true); - options_set(opts_flags, FTEPP, false); - options_set(opts_flags, CORRECT_TERNARY, true); + con_init (); + opts_init("progs.dat", COMPILER_GMQCC, (1024 << 3)); if (!options_parse(argc, argv)) { return usage(); } /* the standard decides which set of operators to use */ - if (opts_standard == COMPILER_GMQCC) { - operators = c_operators; + if (opts.standard == COMPILER_GMQCC) { + operators = c_operators; operator_count = c_operator_count; - } else if (opts_standard == COMPILER_FTEQCC) { - operators = fte_operators; + } else if (opts.standard == COMPILER_FTEQCC) { + operators = fte_operators; operator_count = fte_operator_count; } else { - operators = qcc_operators; + operators = qcc_operators; operator_count = qcc_operator_count; } @@ -565,23 +522,22 @@ int main(int argc, char **argv) { } } - if (opts_dump) { - for (itr = 0; itr < COUNT_FLAGS; ++itr) { - con_out("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr)); - } - for (itr = 0; itr < COUNT_WARNINGS; ++itr) { + if (opts.dump) { + for (itr = 0; itr < COUNT_FLAGS; ++itr) + con_out("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr)); + for (itr = 0; itr < COUNT_WARNINGS; ++itr) con_out("Warning %s = %i\n", opts_warn_list[itr].name, OPTS_WARN(itr)); - } - con_out("output = %s\n", opts_output); - con_out("optimization level = %i\n", (int)opts_O); - con_out("standard = %i\n", opts_standard); + + con_out("output = %s\n", opts.output); + con_out("optimization level = %d\n", opts.O); + con_out("standard = %i\n", opts.standard); } - if (opts_pp_only) { + if (opts.pp_only) { if (opts_output_wasset) { - outfile = util_fopen(opts_output, "wb"); + outfile = util_fopen(opts.output, "wb"); if (!outfile) { - con_err("failed to open `%s` for writing\n", opts_output); + con_err("failed to open `%s` for writing\n", opts.output); retval = 1; goto cleanup; } @@ -590,14 +546,15 @@ int main(int argc, char **argv) { outfile = stdout; } - if (!opts_pp_only) { + if (!opts.pp_only) { if (!parser_init()) { con_err("failed to initialize parser\n"); retval = 1; goto cleanup; } } - if (opts_pp_only || OPTS_FLAG(FTEPP)) { + + if (opts.pp_only || OPTS_FLAG(FTEPP)) { if (!ftepp_init()) { con_err("failed to initialize parser\n"); retval = 1; @@ -607,6 +564,18 @@ int main(int argc, char **argv) { util_debug("COM", "starting ...\n"); + /* add macros */ + if (opts.pp_only || OPTS_FLAG(FTEPP)) { + for (itr = 0; itr < vec_size(ppems); itr++) { + ftepp_add_macro(ppems[itr].name, ppems[itr].value); + mem_d(ppems[itr].name); + + /* can be null */ + if (ppems[itr].value) + mem_d(ppems[itr].value); + } + } + if (!vec_size(items)) { FILE *src; char *line; @@ -629,7 +598,7 @@ int main(int argc, char **argv) { } if (!opts_output_wasset) { - opts_output = util_strdup(line); + opts.output = util_strdup(line); opts_output_free = true; } @@ -651,12 +620,12 @@ srcdone: goto cleanup; if (vec_size(items)) { - if (!opts_pp_only) { + if (!opts.pp_only) { con_out("Mode: %s\n", (progs_src ? "progs.src" : "manual")); con_out("There are %lu items to compile:\n", (unsigned long)vec_size(items)); } for (itr = 0; itr < vec_size(items); ++itr) { - if (!opts_pp_only) { + if (!opts.pp_only) { con_out(" item: %s (%s)\n", items[itr].filename, ( (items[itr].type == TYPE_QC ? "qc" : @@ -665,7 +634,7 @@ srcdone: ("unknown")))))); } - if (opts_pp_only) { + if (opts.pp_only) { const char *out; if (!ftepp_preprocess_file(items[itr].filename)) { retval = 1; @@ -707,8 +676,8 @@ srcdone: } ftepp_finish(); - if (!opts_pp_only) { - if (!parser_finish(opts_output)) { + if (!opts.pp_only) { + if (!parser_finish(opts.output)) { retval = 1; goto cleanup; } @@ -716,11 +685,10 @@ srcdone: } /* stuff */ - - if (!opts_pp_only) { + if (!opts.pp_only) { for (itr = 0; itr < COUNT_OPTIMIZATIONS; ++itr) { - if (optimization_count[itr]) { - con_out("%s: %u\n", opts_opt_list[itr].name, (unsigned int)optimization_count[itr]); + if (opts_optimizationcount[itr]) { + con_out("%s: %u\n", opts_opt_list[itr].name, (unsigned int)opts_optimizationcount[itr]); } } } @@ -730,11 +698,12 @@ cleanup: ftepp_finish(); con_close(); vec_free(items); + vec_free(ppems); - if (!opts_pp_only) + if (!opts.pp_only) parser_cleanup(); if (opts_output_free) - mem_d((char*)opts_output); + mem_d((char*)opts.output); if (operators_free) mem_d((void*)operators);