mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-27 06:02:22 +00:00
Cleanups of compiler option configuration. Added ini/cfg parser system as well.
This commit is contained in:
parent
0befe5da1c
commit
4b3e2571af
6 changed files with 418 additions and 164 deletions
3
Makefile
3
Makefile
|
@ -27,7 +27,8 @@ OBJ = \
|
|||
ast.o \
|
||||
ir.o \
|
||||
con.o \
|
||||
ftepp.o
|
||||
ftepp.o \
|
||||
opts.o
|
||||
|
||||
OBJ_T = test.o util.o con.o
|
||||
OBJ_C = main.o lexer.o parser.o
|
||||
|
|
8
ast.c
8
ast.c
|
@ -1417,14 +1417,14 @@ bool ast_generate_accessors(ast_value *self, ir_builder *ir)
|
|||
}
|
||||
}
|
||||
|
||||
options_set(opts.warn, WARN_USED_UNINITIALIZED, false);
|
||||
opts_set(opts.warn, WARN_USED_UNINITIALIZED, false);
|
||||
if (self->setter) {
|
||||
if (!ast_global_codegen (self->setter, ir, false) ||
|
||||
!ast_function_codegen(self->setter->constval.vfunc, ir) ||
|
||||
!ir_function_finalize(self->setter->constval.vfunc->ir_func))
|
||||
{
|
||||
compile_error(ast_ctx(self), "internal error: failed to generate setter for `%s`", self->name);
|
||||
options_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
|
||||
opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1434,14 +1434,14 @@ bool ast_generate_accessors(ast_value *self, ir_builder *ir)
|
|||
!ir_function_finalize(self->getter->constval.vfunc->ir_func))
|
||||
{
|
||||
compile_error(ast_ctx(self), "internal error: failed to generate getter for `%s`", self->name);
|
||||
options_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
|
||||
opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < self->expression.count; ++i) {
|
||||
vec_free(self->ir_values[i]->life);
|
||||
}
|
||||
options_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
|
||||
opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
36
gmqcc.h
36
gmqcc.h
|
@ -623,10 +623,10 @@ int con_out (const char *, ...);
|
|||
extern size_t compile_errors;
|
||||
extern size_t compile_warnings;
|
||||
|
||||
void /********/ compile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, ...);
|
||||
bool GMQCC_WARN compile_warning(lex_ctx ctx, int warntype, const char *fmt, ...);
|
||||
void /********/ vcompile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, va_list);
|
||||
bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_list);
|
||||
void /********/ compile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, ...);
|
||||
void /********/ vcompile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, va_list ap);
|
||||
bool GMQCC_WARN compile_warning (lex_ctx ctx, int warntype, const char *fmt, ...);
|
||||
bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_list ap);
|
||||
|
||||
/*===================================================================*/
|
||||
/*========================= assembler.c =============================*/
|
||||
|
@ -867,14 +867,22 @@ typedef uint32_t longbit;
|
|||
#define LONGBIT(bit) (bit)
|
||||
#endif
|
||||
|
||||
/* Used to store the list of flags with names */
|
||||
/*===================================================================*/
|
||||
/*============================= opts.c ==============================*/
|
||||
/*===================================================================*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
longbit bit;
|
||||
} opts_flag_def;
|
||||
|
||||
/*===================================================================*/
|
||||
/* list of -f flags, like -fdarkplaces-string-table-bug */
|
||||
bool opts_setflag (const char *, bool);
|
||||
bool opts_setwarn (const char *, bool);
|
||||
bool opts_setoptim(const char *, bool);
|
||||
|
||||
void opts_init (const char *, int, size_t);
|
||||
void opts_set (uint32_t *, size_t, bool);
|
||||
void opts_setoptimlevel(unsigned int);
|
||||
|
||||
enum {
|
||||
# define GMQCC_TYPE_FLAGS
|
||||
# define GMQCC_DEFINE_FLAG(X) X,
|
||||
|
@ -919,21 +927,21 @@ static const unsigned int opts_opt_oflag[] = {
|
|||
# include "opts.def"
|
||||
0
|
||||
};
|
||||
extern unsigned int optimization_count[COUNT_OPTIMIZATIONS];
|
||||
extern unsigned int opts_optimizationcount[COUNT_OPTIMIZATIONS];
|
||||
|
||||
/* other options: */
|
||||
enum {
|
||||
typedef enum {
|
||||
COMPILER_QCC, /* circa QuakeC */
|
||||
COMPILER_FTEQCC, /* fteqcc QuakeC */
|
||||
COMPILER_QCCX, /* qccx QuakeC */
|
||||
COMPILER_GMQCC /* this QuakeC */
|
||||
};
|
||||
} opts_std_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t O; /* -Ox */
|
||||
const char *output; /* -o file */
|
||||
bool g; /* -g */
|
||||
int standard; /* -std= */
|
||||
opts_std_t standard; /* -std= */
|
||||
bool debug; /* -debug */
|
||||
bool memchk; /* -memchk */
|
||||
bool dumpfin; /* -dumpfin */
|
||||
|
@ -947,15 +955,13 @@ typedef struct {
|
|||
uint32_t flags [1 + (COUNT_FLAGS / 32)];
|
||||
uint32_t warn [1 + (COUNT_WARNINGS / 32)];
|
||||
uint32_t optimization[1 + (COUNT_OPTIMIZATIONS / 32)];
|
||||
} cmd_options;
|
||||
} opts_cmd_t;
|
||||
|
||||
extern cmd_options opts;
|
||||
extern opts_cmd_t opts;
|
||||
|
||||
/*===================================================================*/
|
||||
#define OPTS_FLAG(i) (!! (opts.flags [(i)/32] & (1<< ((i)%32))))
|
||||
#define OPTS_WARN(i) (!! (opts.warn [(i)/32] & (1<< ((i)%32))))
|
||||
#define OPTS_OPTIMIZATION(i) (!! (opts.optimization[(i)/32] & (1<< ((i)%32))))
|
||||
|
||||
void options_set(uint32_t *flags, size_t idx, bool on);
|
||||
|
||||
#endif
|
||||
|
|
20
ir.c
20
ir.c
|
@ -209,11 +209,11 @@ static void irerror(lex_ctx ctx, const char *msg, ...)
|
|||
static bool irwarning(lex_ctx ctx, int warntype, const char *fmt, ...)
|
||||
{
|
||||
bool r;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
r = vcompile_warning(ctx, warntype, fmt, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
r = vcompile_warning(ctx, warntype, fmt, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -575,7 +575,7 @@ bool ir_function_pass_peephole(ir_function *self)
|
|||
if (store->_ops[1] != value)
|
||||
continue;
|
||||
|
||||
++optimization_count[OPTIM_PEEPHOLE];
|
||||
++opts_optimizationcount[OPTIM_PEEPHOLE];
|
||||
(void)!ir_instr_op(oper, 0, store->_ops[0], true);
|
||||
|
||||
vec_remove(block->instr, i, 1);
|
||||
|
@ -610,7 +610,7 @@ bool ir_function_pass_peephole(ir_function *self)
|
|||
}
|
||||
|
||||
/* count */
|
||||
++optimization_count[OPTIM_PEEPHOLE];
|
||||
++opts_optimizationcount[OPTIM_PEEPHOLE];
|
||||
/* change operand */
|
||||
(void)!ir_instr_op(inst, 0, inot->_ops[1], false);
|
||||
/* remove NOT */
|
||||
|
@ -678,7 +678,7 @@ bool ir_function_pass_tailcall(ir_function *self)
|
|||
ret->_ops[0] == store->_ops[0] &&
|
||||
store->_ops[1] == call->_ops[0])
|
||||
{
|
||||
++optimization_count[OPTIM_PEEPHOLE];
|
||||
++opts_optimizationcount[OPTIM_PEEPHOLE];
|
||||
call->_ops[0] = store->_ops[0];
|
||||
vec_remove(block->instr, vec_size(block->instr) - 2, 1);
|
||||
ir_instr_delete(store);
|
||||
|
@ -700,7 +700,7 @@ bool ir_function_pass_tailcall(ir_function *self)
|
|||
if (ret->_ops[0] && call->_ops[0] != ret->_ops[0])
|
||||
continue;
|
||||
|
||||
++optimization_count[OPTIM_TAIL_RECURSION];
|
||||
++opts_optimizationcount[OPTIM_TAIL_RECURSION];
|
||||
vec_shrinkby(block->instr, 2);
|
||||
|
||||
block->final = false; /* open it back up */
|
||||
|
@ -2897,7 +2897,7 @@ tailcall:
|
|||
if (stmt.o2.u1 == stmt.o1.u1 &&
|
||||
OPTS_OPTIMIZATION(OPTIM_PEEPHOLE))
|
||||
{
|
||||
++optimization_count[OPTIM_PEEPHOLE];
|
||||
++opts_optimizationcount[OPTIM_PEEPHOLE];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
186
main.c
186
main.c
|
@ -24,15 +24,12 @@
|
|||
#include "gmqcc.h"
|
||||
#include "lexer.h"
|
||||
|
||||
/* counter increased in ir.c */
|
||||
unsigned int optimization_count[COUNT_OPTIMIZATIONS];
|
||||
static bool opts_output_wasset = false;
|
||||
|
||||
cmd_options opts;
|
||||
/* 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 *name; char *value; } ppitem;
|
||||
|
@ -84,38 +81,7 @@ static int usage() {
|
|||
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<<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_setoptim(const char *name, bool on) {
|
||||
return options_setflag_all(name, on, opts.optimization, opts_opt_list, COUNT_OPTIMIZATIONS);
|
||||
}
|
||||
|
||||
/* command line parsing */
|
||||
static bool options_witharg(int *argc_, char ***argv_, char **out) {
|
||||
int argc = *argc_;
|
||||
char **argv = *argv_;
|
||||
|
@ -166,29 +132,6 @@ static bool options_long_gcc(const char *optname, int *argc_, char ***argv_, cha
|
|||
return options_long_witharg_all(optname, argc_, argv_, out, 1, false);
|
||||
}
|
||||
|
||||
void options_set(uint32_t *flags, size_t idx, bool on)
|
||||
{
|
||||
longbit lb = LONGBIT(idx);
|
||||
#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
|
||||
}
|
||||
|
||||
static void set_optimizations(unsigned int level)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < COUNT_OPTIMIZATIONS; ++i)
|
||||
options_set(opts.optimization, i, level >= opts_opt_oflag[i]);
|
||||
}
|
||||
|
||||
static bool options_parse(int argc, char **argv) {
|
||||
bool argend = false;
|
||||
size_t itr;
|
||||
|
@ -205,26 +148,34 @@ static bool options_parse(int argc, char **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);
|
||||
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_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_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_set(opts.flags, ADJUST_VECTOR_FIELDS, false);
|
||||
opts.standard = COMPILER_QCCX;
|
||||
|
||||
} else {
|
||||
con_out("Unknown standard: %s\n", argarg);
|
||||
return false;
|
||||
|
@ -232,7 +183,7 @@ static bool options_parse(int argc, char **argv) {
|
|||
continue;
|
||||
}
|
||||
if (options_long_gcc("force-crc", &argc, &argv, &argarg)) {
|
||||
opts.forcecrc = true;
|
||||
opts.forcecrc = true;
|
||||
opts.forced_crc = strtol(argarg, NULL, 0);
|
||||
continue;
|
||||
}
|
||||
|
@ -308,7 +259,7 @@ static bool options_parse(int argc, char **argv) {
|
|||
|
||||
/* debug turns on -flno */
|
||||
case 'g':
|
||||
options_setflag("LNO", true);
|
||||
opts_setflag("LNO", true);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
|
@ -340,12 +291,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;
|
||||
}
|
||||
|
@ -379,12 +330,12 @@ static bool options_parse(int argc, char **argv) {
|
|||
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;
|
||||
}
|
||||
|
@ -397,7 +348,7 @@ static bool options_parse(int argc, char **argv) {
|
|||
}
|
||||
if (isdigit(argarg[0])) {
|
||||
opts.O = atoi(argarg);
|
||||
set_optimizations(opts.O);
|
||||
opts_setoptimlevel(opts.O);
|
||||
} else {
|
||||
util_strtocmd(argarg, argarg, strlen(argarg)+1);
|
||||
if (!strcmp(argarg, "HELP")) {
|
||||
|
@ -409,15 +360,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;
|
||||
}
|
||||
|
@ -517,46 +468,15 @@ 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;
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.output = "progs.dat";
|
||||
opts.standard = COMPILER_GMQCC;
|
||||
opts.max_array_size = (1024<<3);
|
||||
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.warn, WARN_UNKNOWN_PRAGMAS, 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();
|
||||
|
@ -564,13 +484,13 @@ int main(int argc, char **argv) {
|
|||
|
||||
/* the standard decides which set of operators to use */
|
||||
if (opts.standard == COMPILER_GMQCC) {
|
||||
operators = c_operators;
|
||||
operators = c_operators;
|
||||
operator_count = c_operator_count;
|
||||
} else if (opts.standard == COMPILER_FTEQCC) {
|
||||
operators = fte_operators;
|
||||
operators = fte_operators;
|
||||
operator_count = fte_operator_count;
|
||||
} else {
|
||||
operators = qcc_operators;
|
||||
operators = qcc_operators;
|
||||
operator_count = qcc_operator_count;
|
||||
}
|
||||
|
||||
|
@ -595,15 +515,14 @@ 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) {
|
||||
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) {
|
||||
|
@ -758,11 +677,10 @@ srcdone:
|
|||
}
|
||||
|
||||
/* stuff */
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
329
opts.c
Normal file
329
opts.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright (C) 2012
|
||||
* Wolfgang Bumiller
|
||||
* 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
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "gmqcc.h"
|
||||
unsigned int opts_optimizationcount[COUNT_OPTIMIZATIONS];
|
||||
opts_cmd_t opts; /* command lien options */
|
||||
|
||||
static void opts_ini_init();
|
||||
static void opts_setdefault() {
|
||||
memset(&opts, 0, sizeof(opts_cmd_t));
|
||||
|
||||
/* warnings */
|
||||
opts_set(opts.warn, WARN_UNKNOWN_CONTROL_SEQUENCE, true);
|
||||
opts_set(opts.warn, WARN_EXTENSIONS, true);
|
||||
opts_set(opts.warn, WARN_FIELD_REDECLARED, true);
|
||||
opts_set(opts.warn, WARN_TOO_FEW_PARAMETERS, true);
|
||||
opts_set(opts.warn, WARN_MISSING_RETURN_VALUES, true);
|
||||
opts_set(opts.warn, WARN_USED_UNINITIALIZED, true);
|
||||
opts_set(opts.warn, WARN_LOCAL_CONSTANTS, true);
|
||||
opts_set(opts.warn, WARN_VOID_VARIABLES, true);
|
||||
opts_set(opts.warn, WARN_IMPLICIT_FUNCTION_POINTER, true);
|
||||
opts_set(opts.warn, WARN_VARIADIC_FUNCTION, true);
|
||||
opts_set(opts.warn, WARN_FRAME_MACROS, true);
|
||||
opts_set(opts.warn, WARN_UNUSED_VARIABLE, true);
|
||||
opts_set(opts.warn, WARN_EFFECTLESS_STATEMENT, true);
|
||||
opts_set(opts.warn, WARN_END_SYS_FIELDS, true);
|
||||
opts_set(opts.warn, WARN_ASSIGN_FUNCTION_TYPES, true);
|
||||
opts_set(opts.warn, WARN_PREPROCESSOR, true);
|
||||
opts_set(opts.warn, WARN_MULTIFILE_IF, true);
|
||||
opts_set(opts.warn, WARN_DOUBLE_DECLARATION, true);
|
||||
opts_set(opts.warn, WARN_CONST_VAR, true);
|
||||
opts_set(opts.warn, WARN_MULTIBYTE_CHARACTER, true);
|
||||
opts_set(opts.warn, WARN_UNKNOWN_PRAGMAS, true);
|
||||
/* flags */
|
||||
opts_set(opts.flags, ADJUST_VECTOR_FIELDS, true);
|
||||
opts_set(opts.flags, FTEPP, false);
|
||||
opts_set(opts.flags, CORRECT_TERNARY, true);
|
||||
}
|
||||
|
||||
void opts_init(const char *output, int standard, size_t arraysize) {
|
||||
opts_setdefault();
|
||||
|
||||
opts.output = output;
|
||||
opts.standard = standard;
|
||||
opts.max_array_size = arraysize;
|
||||
|
||||
opts_ini_init();
|
||||
}
|
||||
|
||||
static bool opts_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;
|
||||
}
|
||||
bool opts_setflag (const char *name, bool on) {
|
||||
return opts_setflag_all(name, on, opts.flags, opts_flag_list, COUNT_FLAGS);
|
||||
}
|
||||
bool opts_setwarn (const char *name, bool on) {
|
||||
return opts_setflag_all(name, on, opts.warn, opts_warn_list, COUNT_WARNINGS);
|
||||
}
|
||||
bool opts_setoptim(const char *name, bool on) {
|
||||
return opts_setflag_all(name, on, opts.optimization, opts_opt_list, COUNT_OPTIMIZATIONS);
|
||||
}
|
||||
|
||||
void opts_set(uint32_t *flags, size_t idx, bool on) {
|
||||
longbit lb = LONGBIT(idx);
|
||||
#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
|
||||
}
|
||||
|
||||
void opts_setoptimlevel(unsigned int level) {
|
||||
size_t i;
|
||||
for (i = 0; i < COUNT_OPTIMIZATIONS; ++i)
|
||||
opts_set(opts.optimization, i, level >= opts_opt_oflag[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard configuration parser and subsystem. Yes, optionally you may
|
||||
* create ini files or cfg (the driver accepts both) for a project opposed
|
||||
* to supplying just a progs.src (since you also may need to supply command
|
||||
* line arguments or set the options of the compiler) [which cannot be done
|
||||
* from a progs.src.
|
||||
*/
|
||||
static char *opts_ini_rstrip(char *s) {
|
||||
char *p = s + strlen(s);
|
||||
while(p > s && isspace(*--p))
|
||||
*p = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
static char *opts_ini_lskip(const char *s) {
|
||||
while (*s && isspace(*s))
|
||||
s++;
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
static char *opts_ini_next(const char *s, char c) {
|
||||
bool last = false;
|
||||
while (*s && *s != c && !(last && *s == ';'))
|
||||
last = !!isspace(*s), s++;
|
||||
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
static size_t opts_ini_parse (
|
||||
FILE *filehandle,
|
||||
char *(*loadhandle)(const char *, const char *, const char *),
|
||||
char **errorhandle
|
||||
) {
|
||||
size_t linesize;
|
||||
size_t lineno = 1;
|
||||
size_t error = 0;
|
||||
char *line = NULL;
|
||||
char section_data[2048] = "";
|
||||
char oldname_data[2048] = "";
|
||||
|
||||
/* parsing and reading variables */
|
||||
char *parse_beg;
|
||||
char *parse_end;
|
||||
char *read_name;
|
||||
char *read_value;
|
||||
|
||||
while (util_getline(&line, &linesize, filehandle) != EOF) {
|
||||
parse_beg = line;
|
||||
|
||||
/* handle BOM */
|
||||
if (lineno == 1 && (
|
||||
(unsigned char)parse_beg[0] == 0xEF &&
|
||||
(unsigned char)parse_beg[1] == 0xBB &&
|
||||
(unsigned char)parse_beg[2] == 0xBF
|
||||
)
|
||||
) {
|
||||
parse_beg ++; /* 0xEF */
|
||||
parse_beg ++; /* 0xBB */
|
||||
parse_beg ++; /* 0xBF */
|
||||
}
|
||||
|
||||
if (*(parse_beg = opts_ini_lskip(opts_ini_rstrip(parse_beg))) == ';' || *parse_beg == '#') {
|
||||
/* ignore '#' is a perl extension */
|
||||
} else if (*parse_beg == '[') {
|
||||
/* section found */
|
||||
if (*(parse_end = opts_ini_next(parse_beg + 1, ']')) == ']') {
|
||||
* parse_end = '\0'; /* terminate bro */
|
||||
strncpy(section_data, parse_beg + 1, sizeof(section_data));
|
||||
section_data[sizeof(section_data) - 1] = '\0';
|
||||
*oldname_data = '\0';
|
||||
} else if (!error) {
|
||||
/* otherwise set error to the current line number */
|
||||
error = lineno;
|
||||
}
|
||||
} else if (*parse_beg && *parse_beg != ';') {
|
||||
/* not a comment, must be a name value pair :) */
|
||||
if (*(parse_end = opts_ini_next(parse_beg, '=')) != '=')
|
||||
parse_end = opts_ini_next(parse_beg, ':');
|
||||
|
||||
if (*parse_end == '=' || *parse_end == ':') {
|
||||
*parse_end = '\0'; /* terminate bro */
|
||||
read_name = opts_ini_rstrip(parse_beg);
|
||||
read_value = opts_ini_lskip(parse_end + 1);
|
||||
if (*(parse_end = opts_ini_next(read_value, '\0')) == ';')
|
||||
* parse_end = '\0';
|
||||
opts_ini_rstrip(read_value);
|
||||
|
||||
/* valid name value pair, lets call down to handler */
|
||||
strncpy(oldname_data, read_name, sizeof(oldname_data));
|
||||
oldname_data[sizeof(oldname_data) - 1] ='\0';
|
||||
|
||||
if ((*errorhandle = loadhandle(section_data, read_name, read_value)) && !error)
|
||||
error = lineno;
|
||||
} else if (!error) {
|
||||
/* otherwise set error to the current line number */
|
||||
error = lineno;
|
||||
}
|
||||
}
|
||||
lineno++;
|
||||
}
|
||||
mem_d(line);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns true/false for a char that contains ("true" or "false" or numeric 0/1)
|
||||
*/
|
||||
static bool opts_ini_bool(const char *value) {
|
||||
if (!strcmp(value, "true")) return true;
|
||||
if (!strcmp(value, "false")) return false;
|
||||
return !!atoi(value);
|
||||
}
|
||||
|
||||
static char *opts_ini_load(const char *section, const char *name, const char *value) {
|
||||
char *error = NULL;
|
||||
bool found = false;
|
||||
|
||||
/*
|
||||
* undef all of these because they may still be defined like in my
|
||||
* case they where.
|
||||
*/
|
||||
#undef GMQCC_TYPE_FLAGS
|
||||
#undef GMQCC_TYPE_OPTIMIZATIONS
|
||||
#undef GMQCC_TYPE_WARNS
|
||||
|
||||
/* flags */
|
||||
#define GMQCC_TYPE_FLAGS
|
||||
#define GMQCC_DEFINE_FLAG(X) \
|
||||
if (!strcmp(section, "flags") && !strcmp(name, #X)) { \
|
||||
opts_set(opts.flags, X, opts_ini_bool(value)); \
|
||||
found = true; \
|
||||
}
|
||||
#include "opts.def"
|
||||
|
||||
/* warnings */
|
||||
#define GMQCC_TYPE_WARNS
|
||||
#define GMQCC_DEFINE_FLAG(X) \
|
||||
if (!strcmp(section, "warnings") && !strcmp(name, #X)) { \
|
||||
opts_set(opts.warn, WARN_##X, opts_ini_bool(value)); \
|
||||
found = true; \
|
||||
}
|
||||
#include "opts.def"
|
||||
|
||||
/* optimizations */
|
||||
#define GMQCC_TYPE_OPTIMIZATIONS
|
||||
#define GMQCC_DEFINE_FLAG(X,Y) \
|
||||
if (!strcmp(section, "optimizations") && !strcmp(name, #X)) { \
|
||||
opts_set(opts.optimization, OPTIM_##X, opts_ini_bool(value)); \
|
||||
found = true; \
|
||||
}
|
||||
#include "opts.def"
|
||||
|
||||
/* nothing was found ever! */
|
||||
if (!found) {
|
||||
if (strcmp(section, "flags") &&
|
||||
strcmp(section, "warnings") &&
|
||||
strcmp(section, "optimizations"))
|
||||
{
|
||||
vec_upload(error, "invalid section `", 17);
|
||||
vec_upload(error, section, strlen(section));
|
||||
vec_push (error, '`');
|
||||
vec_push (error, '\0');
|
||||
} else {
|
||||
vec_upload(error, "invalid variable `", 18);
|
||||
vec_upload(error, name, strlen(name));
|
||||
vec_push (error, '`');
|
||||
vec_upload(error, " in section: `", 14);
|
||||
vec_upload(error, section, strlen(section));
|
||||
vec_push (error, '`');
|
||||
vec_push (error, '\0');
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Actual loading subsystem, this finds the ini or cfg file, and properly
|
||||
* loads it and executes it to set compiler options.
|
||||
*/
|
||||
static void opts_ini_init() {
|
||||
/*
|
||||
* Possible matches are:
|
||||
* gmqcc.ini
|
||||
* gmqcc.cfg
|
||||
*/
|
||||
|
||||
char *file;
|
||||
char *error;
|
||||
size_t line;
|
||||
FILE *ini;
|
||||
|
||||
/* try ini */
|
||||
if (!(ini = fopen((file = "gmqcc.ini"), "r")))
|
||||
/* try cfg */
|
||||
if (!(ini = fopen((file = "gmqcc.cfg"), "r")))
|
||||
return;
|
||||
|
||||
con_out("found ini file `%s`\n", file);
|
||||
|
||||
if ((line = opts_ini_parse(ini, &opts_ini_load, &error)) != 0) {
|
||||
/* there was a parse error with the ini file */
|
||||
con_printmsg(LVL_ERROR, file, line, "error", error);
|
||||
vec_free(error);
|
||||
}
|
||||
|
||||
fclose(ini);
|
||||
}
|
Loading…
Reference in a new issue