From 64f76bd7628c23341188fb1d02355809f3ab73e0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 09:16:55 +0900 Subject: [PATCH 0001/1519] Use the right value when getting a function's defref. Either I had gotten confused while writing the code and mixed up line and offset, or I had changed offset to line at one stage but missed a place. This fixes the segfault when compiling chewed-alias.r and return-ivar.r --- tools/qfcc/source/linker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 99c77a0f1..772f3fd35 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -876,7 +876,7 @@ process_funcs (qfo_t *qfo) func->file = linker_add_string (QFOSTR (qfo, func->file)); if (func->code > 0) func->code += work_base[qfo_code_space]; - func->def = qfo->defs[func->def].offset; // defref index + func->def = qfo->defs[func->def].line; // defref index func->locals_space = qfo->spaces[func->locals_space].id; if (func->line_info) func->line_info += work->num_lines - 1; //FIXME order dependent From 35bc9814020ab0b30dc163aef3753fa8ad6feda7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jun 2013 12:09:13 +0900 Subject: [PATCH 0002/1519] Allow use of a jump table when switching on an enum. --- tools/qfcc/source/switch.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index f74fe762d..a60b89d7b 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -401,7 +401,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, num_labels++; if (options.code.progsversion == PROG_ID_VERSION || (type != &type_string - && type != &type_float && type != &type_integer) + && type != &type_float && !is_integral (type)) || num_labels < 8) { for (l = labels; *l; l++) { expr_t *cmp = binary_expr (EQ, sw_val, (*l)->value); @@ -421,20 +421,10 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, temp = new_temp_def_expr (&type_integer); else temp = new_temp_def_expr (type); - case_tree = build_case_tree (labels, num_labels, type == &type_integer); - switch (type->type) { - case ev_string: - op = NE; - break; - case ev_float: - op = '-'; - break; - case ev_integer: - op = '-'; - break; - default: - internal_error (0, "in switch"); - } + case_tree = build_case_tree (labels, num_labels, is_integral (type)); + op = '-'; + if (type->type == ev_string) + op = NE; build_switch (sw, case_tree, op, sw_val, temp, default_label->label); } pr.source_line = saved_line; From 8ac2c3a04da0e91f27fdd960291fdbd85650405e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jun 2013 14:21:43 +0900 Subject: [PATCH 0003/1519] Check for unused enum values in switch statements. Unfortunately, it turns out the value lookup is broken (including for duplicate cases). --- tools/qfcc/source/switch.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index a60b89d7b..f2665b63d 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -368,6 +368,24 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, } } +static void +check_enum_switch (switch_block_t *switch_block) +{ + case_label_t cl; + symbol_t *enum_val; + type_t *type = get_type (switch_block->test); + + for (enum_val = type->t.symtab->symbols; enum_val; + enum_val = enum_val->next) { + cl.value = new_integer_expr (enum_val->s.value->v.integer_val); + if (!Hash_FindElement (switch_block->labels, &cl)) { + warning (switch_block->test, + "enumeration value `%s' not handled in switch", + enum_val->name); + } + } +} + struct expr_s * switch_expr (switch_block_t *switch_block, expr_t *break_label, expr_t *statements) @@ -393,6 +411,8 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, if (!default_label) { default_label = &_default_label; default_label->label = break_label; + if (is_enum (type)) + check_enum_switch (switch_block); } append_expr (sw, assign_expr (sw_val, switch_block->test)); From 29df4ac7eedfef00c1a03d293e66c67d4b37460c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jun 2013 08:40:25 +0900 Subject: [PATCH 0004/1519] Fix case label lookup. It looks like I had forgotten that the compare function is supposed to return true/false (unlike memcmp's sorting ability). Also, avoid the pointers in the value struct as they can change without notice. Using enums in switches now works nicely, including warnings for unused enum values. --- tools/qfcc/TODO | 2 +- tools/qfcc/source/switch.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index f9867c2b3..368ea6e77 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -6,13 +6,13 @@ I = in progress W = waiting on other work X fix object files +X fix enums in switch statements (use tables (treat as int), check missing) M arrays in structures M unnamed function parameters for prototypes/typdefs etc. I optimizations (esp CSE) I fix used/uninitialized warnings o id id; o vec = [x, y, z]; expressions (nice feature in fteqcc) -o fix enums in switch statements (use tables (treat as int), check missing) o arrays in entities o optional arguments for functions (alternative to overloading) vector(vector fwd, optional vector up) vectoangles = #51; diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index f2665b63d..dee8bac5f 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -68,6 +68,8 @@ get_value (expr_t *e) { if (e->type == ex_symbol) return e->e.symbol->s.value; + if (e->type != ex_value) + internal_error (e, "bogus case label"); return e->e.value; } @@ -80,7 +82,7 @@ get_hash (const void *_cl, void *unused) if (!cl->value) return 0; val = get_value (cl->value); - return Hash_Buffer (val, sizeof (*val)); + return Hash_Buffer (&val->v, sizeof (val->v)) + val->type; } static int @@ -99,8 +101,10 @@ compare (const void *_cla, const void *_clb, void *unused) if (extract_type (v1) != extract_type (v2)) return 0; val1 = get_value (v1); - val2 = get_value (v1); - return memcmp (val1, val2, sizeof (*val1)); + val2 = get_value (v2); + if (val1->type != val2->type) + return 0; + return memcmp (&val1->v, &val2->v, sizeof (val1->v)) == 0; } struct expr_s * From fd1ea9e00eb2e0cbd9f10afdb2d6e6d2f24af3cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jun 2013 09:08:51 +0900 Subject: [PATCH 0005/1519] Add an option to control the enum switch warning. --- tools/qfcc/doc/man/qfcc.1 | 7 +++++++ tools/qfcc/include/options.h | 1 + tools/qfcc/source/options.c | 7 +++++++ tools/qfcc/source/switch.c | 2 +- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index cf5c6372d..2857ffedd 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -314,6 +314,13 @@ Emit a warning when potentially ambiguous logic is used without parentheses. .B redeclared Emit a warning when a local variable is redeclared. .TP +.B switch +Emit a warning when an enum value is not handled in a switch statement that +tests an enum. +Using a default label will cause all otherwise unhandled enum values to be +handled (for good or evil). +.TP +.TP .B traditional Emit a warning when code that should be an error is allowed by traditional \fBqcc\fP. diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 131aec720..6be963699 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -61,6 +61,7 @@ typedef struct { qboolean initializer; // Warn on excessive initializer elements qboolean unimplemented; // Warn on unimplemented class methods qboolean redeclared; // Warn on redeclared local variables + qboolean enum_switch; // Warn on unhandled enum values in switch } warn_options_t; typedef struct { diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index e9f67ca0c..4209cbbec 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -232,6 +232,8 @@ warning_usage (void) " interface.\n" " none Turn off all warnings.\n" " [no-]precedence Warn about potentially ambiguous logic.\n" +" [no-]switch Warn about unhandled enum values in switch\n" +" statements.\n" " [no-]redeclared Warn about redeclared local variables.\n" " [no-]traditional Warn about bad code that qcc allowed.\n" " [no-]undef-function Warn about calling a yet to be defined\n" @@ -295,6 +297,7 @@ DecodeArgs (int argc, char **argv) options.warnings.initializer = true; options.warnings.unimplemented = true; options.warnings.redeclared = true; + options.warnings.enum_switch = true; options.single_cpp = true; options.save_temps = false; @@ -503,6 +506,7 @@ DecodeArgs (int argc, char **argv) options.warnings.initializer = true; options.warnings.unimplemented = true; options.warnings.redeclared = true; + options.warnings.enum_switch = true; } else if (!(strcasecmp (temp, "none"))) { options.warnings.cow = false; options.warnings.undefined_function = false; @@ -517,6 +521,7 @@ DecodeArgs (int argc, char **argv) options.warnings.initializer = false; options.warnings.unimplemented = false; options.warnings.redeclared = false; + options.warnings.enum_switch = false; } else { qboolean flag = true; @@ -542,6 +547,8 @@ DecodeArgs (int argc, char **argv) options.warnings.precedence = flag; } else if (!strcasecmp (temp, "redeclared")) { options.warnings.redeclared = flag; + } else if (!strcasecmp (temp, "switch")) { + options.warnings.enum_switch = flag; } else if (!strcasecmp (temp, "traditional")) { options.warnings.traditional = flag; } else if (!strcasecmp (temp, "undef-function")) { diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index dee8bac5f..f6b05547c 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -415,7 +415,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, if (!default_label) { default_label = &_default_label; default_label->label = break_label; - if (is_enum (type)) + if (options.warnings.enum_switch && is_enum (type)) check_enum_switch (switch_block); } From 99a8e8f22803521a7a6721ce2b0612bd70d7c736 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jun 2013 09:59:19 +0900 Subject: [PATCH 0006/1519] Fix the jump instruction. The offset to compensate for st++ was missing. Obviously, the code has never been tested. Found while looking at the jump code and thinking about using 32-bit addresses for the jump tables. --- libs/gamecode/pr_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 24778dd74..f67bc1856 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -893,7 +893,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) && (OPA.uinteger_var >= pr->progs->numstatements)) { PR_RunError (pr, "Invalid jump destination"); } - pr->pr_xstatement = OPA.uinteger_var; + pr->pr_xstatement = OPA.uinteger_var - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; break; case OP_JUMPB: From 77337e2402646a457a4c4b984ecb5dc599ff874c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Dec 2012 09:57:24 +0900 Subject: [PATCH 0007/1519] Separate "" and nil. It turns out this is required for compatibility with qcc (and C, really). Once string to boolean conversions are sorted out completely (not that simple as qcc is inconsistent with if (string) vs if (!string)), Qgets can be implemented :) --- tools/qfcc/source/strpool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index d22762a3c..8b32ae71e 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -103,7 +103,7 @@ strpool_addstr (strpool_t *strpool, const char *str) intptr_t s; int len; - if (!str || !*str) + if (!str) return 0; s = (intptr_t) Hash_Find (strpool->str_tab, str); if (s) From 8d34d3305544826972af57d2cf5246326201643d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Dec 2012 10:02:00 +0900 Subject: [PATCH 0008/1519] Implement "if not (foo)" syntax. It is syntactic sugar for if (!(foo)), but is useful for avoiding inconsistencies between such things as if (string) and if (!string), even though qcc can't parse if not (string). It also makes for easier to read code when the logic in the condition is complex. --- tools/qfcc/include/expr.h | 3 ++- tools/qfcc/source/expr.c | 11 ++++++++--- tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/qc-parse.y | 17 +++++++++++------ tools/qfcc/source/qp-parse.y | 4 ++-- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 713292fbf..a3348e9d7 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -598,7 +598,8 @@ expr_t *incop_expr (int op, expr_t *e, int postop); expr_t *array_expr (expr_t *array, expr_t *index); expr_t *pointer_expr (expr_t *pointer); expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); -expr_t *build_if_statement (expr_t *test, expr_t *s1, expr_t *els, expr_t *s2); +expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, + expr_t *s2); expr_t *build_while_statement (expr_t *test, expr_t *statement, expr_t *break_label, expr_t *continue_label); expr_t *build_do_while_statement (expr_t *statement, expr_t *test, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 8f72240cf..109d0a51f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2284,7 +2284,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) } expr_t * -build_if_statement (expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) +build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) { int line = pr.source_line; string_t file = pr.source_file; @@ -2299,8 +2299,13 @@ build_if_statement (expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) test = convert_bool (test, 1); if (test->type != ex_error) { - backpatch (test->e.bool.true_list, tl); - backpatch (test->e.bool.false_list, fl); + if (not) { + backpatch (test->e.bool.true_list, fl); + backpatch (test->e.bool.false_list, tl); + } else { + backpatch (test->e.bool.true_list, tl); + backpatch (test->e.bool.false_list, fl); + } append_expr (test->e.bool.e, tl); append_expr (if_expr, test); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index ff0f89e8a..7d190cb48 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -319,6 +319,7 @@ static keyword_t at_keywords[] = { {"static", STATIC }, {"sizeof", SIZEOF }, {"nosave", NOSAVE }, + {"not", NOT }, }; // These keywords require the QuakeForge VM to be of any use. ie, they cannot diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index ef7bd1cf6..7304f7f0e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -145,7 +145,7 @@ int yylex (void); %token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS %token NIL IFBE IFB IFAE IFA SWITCH CASE DEFAULT ENUM TYPEDEF -%token ARGS EXTERN STATIC SYSTEM NOSAVE OVERLOAD +%token ARGS EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT %token STRUCT %token TYPE %token OBJECT TYPE_NAME @@ -205,7 +205,7 @@ int yylex (void); %type protocol_name %type methodprotolist methodprotolist2 %type ivar_decl_list -%type ci +%type ci not %{ @@ -1149,13 +1149,13 @@ statement switch_block = $5; break_label = $2; } - | IF '(' texpr ')' statement %prec IFX + | IF not '(' texpr ')' statement %prec IFX { - $$ = build_if_statement ($3, $5, 0, 0); + $$ = build_if_statement ($2, $4, $6, 0, 0); } - | IF '(' texpr ')' statement else statement + | IF not '(' texpr ')' statement else statement { - $$ = build_if_statement ($3, $5, $6, $7); + $$ = build_if_statement ($2, $4, $6, $7, $8); } | FOR break_label continue_label '(' opt_expr ';' opt_expr ';' opt_expr ')' statement @@ -1184,6 +1184,11 @@ statement } ; +not + : NOT { $$ = 1; } + | /* empty */ { $$ = 0; } + ; + else : ELSE { diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index f8c870ed4..a2b94acea 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -354,11 +354,11 @@ statement | compound_statement | IF expression THEN statement else statement { - $$ = build_if_statement ($2, $4, $5, $6); + $$ = build_if_statement (0, $2, $4, $5, $6); } | IF expression THEN statement %prec IFX { - $$ = build_if_statement ($2, $4, 0, 0); + $$ = build_if_statement (0, $2, $4, 0, 0); } | WHILE expression DO statement { From 6fa63f6c54d2bf4bdee36838d3df4448151d255c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Dec 2012 10:05:17 +0900 Subject: [PATCH 0009/1519] Implement the basics of fteqcc's -Fifstring. It's -Cifstring in qfcc, but otherwise the intent is the same. More testing and investigation into what fteqcc does is required. --- tools/qfcc/include/options.h | 1 + tools/qfcc/source/expr.c | 5 ++++- tools/qfcc/source/options.c | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 6be963699..4377dab97 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -44,6 +44,7 @@ typedef struct { qboolean local_merging; // merge function locals into one block unsigned progsversion; // Progs version to generate code for qboolean vector_components; // add *_[xyz] symbols for vectors + qboolean ifstring; // expand if (str) to if (str != "") } code_options_t; typedef struct { diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 109d0a51f..ff1ebab3e 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1082,6 +1082,8 @@ test_expr (expr_t *e) } return error (e, "void has no value"); case ev_string: + if (!options.code.ifstring) + return new_alias_expr (type_default, e); new = new_string_expr (0); break; case ev_uinteger: @@ -1211,7 +1213,8 @@ convert_bool (expr_t *e, int block) return b; } - if (e->type == ex_uexpr && e->e.expr.op == '!') { + if (e->type == ex_uexpr && e->e.expr.op == '!' + && get_type (e->e.expr.e1) != &type_string) { e = convert_bool (e->e.expr.e1, 0); if (e->type == ex_error) return e; diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 4209cbbec..4edb03623 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -470,6 +470,8 @@ DecodeArgs (int argc, char **argv) options.code.optimize = flag; } else if (!(strcasecmp (temp, "short-circuit"))) { options.code.short_circuit = flag; + } else if (!(strcasecmp (temp, "ifstring"))) { + options.code.ifstring = flag; } else if (!(strcasecmp (temp, "single-cpp"))) { options.single_cpp = flag; } else if (!(strcasecmp (temp, "vector-calls"))) { @@ -645,6 +647,8 @@ DecodeArgs (int argc, char **argv) options.advanced = false; if (!options.code.progsversion) options.code.progsversion = PROG_ID_VERSION; + if (options.code.ifstring == (qboolean) -1) + options.code.ifstring = false; if (options.code.short_circuit == (qboolean) -1) options.code.short_circuit = false; if (options.code.local_merging == (qboolean) -1) @@ -658,6 +662,8 @@ DecodeArgs (int argc, char **argv) options.advanced = true; add_cpp_def ("-D__RUAMOKO__=1"); add_cpp_def ("-D__RAUMOKO__=1"); + if (options.code.ifstring == (qboolean) -1) + options.code.ifstring = false; if (options.code.short_circuit == (qboolean) -1) options.code.short_circuit = true; if (options.code.local_merging == (qboolean) -1) From 45a09e195ec63998974f7d38ed377855a33e26ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Dec 2012 10:08:27 +0900 Subject: [PATCH 0010/1519] Add more TODO items (strings stuff) --- tools/qfcc/TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index 368ea6e77..37c64d6d6 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -13,6 +13,8 @@ I optimizations (esp CSE) I fix used/uninitialized warnings o id id; o vec = [x, y, z]; expressions (nice feature in fteqcc) +o finish -Fifstring +o isset() intrinsic for more consistent string handling. o arrays in entities o optional arguments for functions (alternative to overloading) vector(vector fwd, optional vector up) vectoangles = #51; From cef213605061958bf1a9b0be8936efa2d3ba42f7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jun 2013 10:46:51 +0900 Subject: [PATCH 0011/1519] Implement "not" logic for while and do-while. This goes towards complementing the "if not" logic extension. I need to check if fteqcc supports "not" with "while" (the version I have access to at the moment does not), and also whether it would be good to support "not" with "for", and if so, what form the syntax should take. --- tools/qfcc/include/expr.h | 4 ++-- tools/qfcc/source/expr.c | 22 ++++++++++++++++------ tools/qfcc/source/qc-parse.y | 9 +++++---- tools/qfcc/source/qp-parse.y | 2 +- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index a3348e9d7..819969afc 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -600,9 +600,9 @@ expr_t *pointer_expr (expr_t *pointer); expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2); -expr_t *build_while_statement (expr_t *test, expr_t *statement, +expr_t *build_while_statement (int not, expr_t *test, expr_t *statement, expr_t *break_label, expr_t *continue_label); -expr_t *build_do_while_statement (expr_t *statement, expr_t *test, +expr_t *build_do_while_statement (expr_t *statement, int not, expr_t *test, expr_t *break_label, expr_t *continue_label); expr_t *build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t *statement, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ff1ebab3e..67307b0e2 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2337,7 +2337,7 @@ build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) } expr_t * -build_while_statement (expr_t *test, expr_t *statement, +build_while_statement (int not, expr_t *test, expr_t *statement, expr_t *break_label, expr_t *continue_label) { int line = pr.source_line; @@ -2358,8 +2358,13 @@ build_while_statement (expr_t *test, expr_t *statement, test = convert_bool (test, 1); if (test->type != ex_error) { - backpatch (test->e.bool.true_list, l1); - backpatch (test->e.bool.false_list, l2); + if (not) { + backpatch (test->e.bool.true_list, l2); + backpatch (test->e.bool.false_list, l1); + } else { + backpatch (test->e.bool.true_list, l1); + backpatch (test->e.bool.false_list, l2); + } append_expr (test->e.bool.e, l2); append_expr (while_expr, test); } @@ -2371,7 +2376,7 @@ build_while_statement (expr_t *test, expr_t *statement, } expr_t * -build_do_while_statement (expr_t *statement, expr_t *test, +build_do_while_statement (expr_t *statement, int not, expr_t *test, expr_t *break_label, expr_t *continue_label) { expr_t *l1 = new_label_expr (); @@ -2390,8 +2395,13 @@ build_do_while_statement (expr_t *statement, expr_t *test, test = convert_bool (test, 1); if (test->type != ex_error) { - backpatch (test->e.bool.true_list, l1); - backpatch (test->e.bool.false_list, break_label); + if (not) { + backpatch (test->e.bool.true_list, break_label); + backpatch (test->e.bool.false_list, l1); + } else { + backpatch (test->e.bool.true_list, l1); + backpatch (test->e.bool.false_list, break_label); + } append_expr (test->e.bool.e, break_label); append_expr (do_while_expr, test); } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 7304f7f0e..14937a811 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1165,15 +1165,16 @@ statement break_label = $2; continue_label = $3; } - | WHILE break_label continue_label '(' texpr ')' statement + | WHILE break_label continue_label not '(' texpr ')' statement { - $$ = build_while_statement ($5, $7, break_label, continue_label); + $$ = build_while_statement ($4, $6, $8, break_label, + continue_label); break_label = $2; continue_label = $3; } - | DO break_label continue_label statement WHILE '(' texpr ')' ';' + | DO break_label continue_label statement WHILE not '(' texpr ')' ';' { - $$ = build_do_while_statement ($4, $7, + $$ = build_do_while_statement ($4, $6, $8, break_label, continue_label); break_label = $2; continue_label = $3; diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index a2b94acea..9731402a5 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -362,7 +362,7 @@ statement } | WHILE expression DO statement { - $$ = build_while_statement ($2, $4, + $$ = build_while_statement (0, $2, $4, new_label_expr (), new_label_expr ()); } From 257597fd384f1d00a5b462ea096807194637bf2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jun 2013 11:03:25 +0900 Subject: [PATCH 0012/1519] Update ifstring in TODO It seems to be done, but... --- tools/qfcc/TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index 37c64d6d6..f44c2bf15 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -13,7 +13,7 @@ I optimizations (esp CSE) I fix used/uninitialized warnings o id id; o vec = [x, y, z]; expressions (nice feature in fteqcc) -o finish -Fifstring +M finish -Fifstring o isset() intrinsic for more consistent string handling. o arrays in entities o optional arguments for functions (alternative to overloading) From 16d899ace5df478e2b36778df9b264ede971bdac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jun 2013 11:23:02 +0900 Subject: [PATCH 0013/1519] Remove the string:string concatentation TODO item. I think it may have been for compatibility with a certain qcc variant (no idea which one, though). While the shift/reduce conflict is fixable using "%prec IFX" on the const:string rule, the colon breaks test?"a":"b". Putting parentheses around "a" allows such a construct, requiring them breaks comatibility with C. I think this feature just isn't worth that. --- tools/qfcc/TODO | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index f44c2bf15..ed68de57c 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -20,4 +20,3 @@ o optional arguments for functions (alternative to overloading) vector(vector fwd, optional vector up) vectoangles = #51; ? try to reduce memory consumption ?? embedded nul characters in strings (why?) -?? "":"" string concatenation (parser issues) (why?) From 03fb47d7ba5f56429817ea5ac6ed890fbab2aa4e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Sep 2013 17:45:30 +0900 Subject: [PATCH 0014/1519] Fix some sizeof goofs. Yay for continually improving gcc warnings :) --- qw/source/cl_chat.c | 2 +- tools/qfcc/source/type.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index 305c14f55..2b40e64dd 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -160,7 +160,7 @@ static qboolean cam_iterator (ignore_t *ig, llist_node_t *node) return true; } dsprintf (g_cam_test, "%s: ", Info_ValueForKey (cl.players[ig->slot].userinfo, "name")); - if (!strncmp (g_cam_test->str, g_cam_str, sizeof (g_cam_test->str))) { + if (!strncmp (g_cam_test->str, g_cam_str, g_cam_test->size - 1)) { return g_cam_allowed = false; } else return true; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 0077d36c7..92d63b11f 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -182,7 +182,7 @@ free_type (type_t *type) free_type (type->t.array.type); break; } - memset (type, 0, sizeof (type)); + memset (type, 0, sizeof (*type)); FREE (types, type); } From 6288684fa245005e7399c56955ff297fa4207d3d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Sep 2013 23:08:33 +0900 Subject: [PATCH 0015/1519] Fix more gcc 4.8 errors. More actual bugs found, too. --- libs/ruamoko/rua_plist.c | 4 +++- libs/video/renderer/gl/gl_dyn_part.c | 8 ++++++-- libs/video/renderer/glsl/glsl_particles.c | 8 +++++--- libs/video/renderer/sw/sw_rpart.c | 8 +++++--- libs/video/renderer/sw32/sw32_rpart.c | 8 +++++--- qw/source/sv_pr_cpqw.c | 6 +++--- 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 40a8b072f..0fdb1ff8d 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -45,6 +45,8 @@ #include "rua_internal.h" +#define always_inline inline __attribute__((__always_inline__)) + typedef struct bi_plist_s { struct bi_plist_s *next; struct bi_plist_s **prev; @@ -140,7 +142,7 @@ plist_free_handle (plist_resources_t *res, bi_plist_t *plist) plist_free (res, plist); } -static inline bi_plist_t * +static always_inline bi_plist_t * get_plist (progs_t *pr, const char *name, int handle) { plist_resources_t *res = PR_Resources_Find (pr, "plist"); diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 949e8b0a3..d3f50f015 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -1185,8 +1185,12 @@ R_EntityParticles_ID (const entity_t *ent) } if (!avelocities[0][0]) { - for (i = 0; i < NUMVERTEXNORMALS * 3; i++) - avelocities[0][i] = (mtwist_rand (&mt) & 255) * 0.01; + for (i = 0; i < NUMVERTEXNORMALS; i++) { + int k; + for (k = 0; k < 3; k++) { + avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + } + } } for (i = 0; i < j; i++) { diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 06ca3d000..8d4819fec 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -1271,9 +1271,11 @@ R_EntityParticles_ID (const entity_t *ent) j = r_maxparticles - numparticles; } - if (!avelocities[0][0]) { - for (i = 0; i < NUMVERTEXNORMALS * 3; i++) - avelocities[0][i] = (mtwist_rand (&mt) & 255) * 0.01; + for (i = 0; i < NUMVERTEXNORMALS; i++) { + int k; + for (k = 0; k < 3; k++) { + avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + } } for (i = 0; i < j; i++) { diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index b198624ee..de59f0ba1 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -435,9 +435,11 @@ R_EntityParticles_ID (const entity_t *ent) if (!r_particles->int_val) return; - if (!avelocities[0][0]) { - for (i = 0; i < NUMVERTEXNORMALS * 3; i++) - avelocities[0][i] = (mtwist_rand (&mt) & 255) * 0.01; + for (i = 0; i < NUMVERTEXNORMALS; i++) { + int k; + for (k = 0; k < 3; k++) { + avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + } } for (i = 0; i < NUMVERTEXNORMALS; i++) { diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 3ae503213..3affa45b1 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -377,9 +377,11 @@ R_EntityParticles_ID (const entity_t *ent) particle_t *p; vec3_t forward; - if (!avelocities[0][0]) { - for (i = 0; i < NUMVERTEXNORMALS * 3; i++) - avelocities[0][i] = (mtwist_rand (&mt) & 255) * 0.01; + for (i = 0; i < NUMVERTEXNORMALS; i++) { + int k; + for (k = 0; k < 3; k++) { + avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + } } for (i = 0; i < NUMVERTEXNORMALS; i++) { diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index 3037db482..07659f634 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -818,10 +818,10 @@ cpqw_user_cmd (void) PR_PushFrame (pr); P_FLOAT (pr, 0) = argc; - for (i = 0; i < argc; i++) - P_STRING (pr, i + 1) = PR_SetTempString (pr, Cmd_Argv (i)); + for (i = 1; i < argc; i++) + P_STRING (pr, i) = PR_SetTempString (pr, Cmd_Argv (i - 1)); for (; i < 7; i++) - P_STRING (pr, i + 1) = 0; + P_STRING (pr, i) = 0; PR_ExecuteProgram (pr, cpqw_funcs.ClientCommand); PR_PopFrame (pr); return (int) R_FLOAT (pr); From 35de42aeac9ce15f2f5e5374e17c1c35130ceba9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 11:34:38 +0900 Subject: [PATCH 0016/1519] Catch bogus comparison types. This fixes an ICE when trying to compare a function with a float. --- tools/qfcc/source/expr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 67307b0e2..f734710b2 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1539,6 +1539,10 @@ binary_expr (int op, expr_t *e1, expr_t *e2) type = t1; + if (is_compare (op)) { + if (!type_assignable (t1, t2)) + return error (e1, "type mismatch for %s", get_op_string (op)); + } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) type = &type_integer; From a6cdc8735a56aef602410edabfcc9cf821324fc2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 11:36:52 +0900 Subject: [PATCH 0017/1519] Start implementing vec = [x,y,z]. This is a nice feature found in fteqcc (also a bit of a challenge from Spike). Getting bison to accept the new expression required rewriting the state expression grammar, so this is mostly for the state expression. A test to ensure the state expression doesn't break is included. --- tools/qfcc/include/expr.h | 3 +- tools/qfcc/source/expr.c | 30 +++++++++++++++++-- tools/qfcc/source/qc-parse.y | 34 ++++++++++------------ tools/qfcc/test/Makefile.am | 8 +++++ tools/qfcc/test/state.r | 53 ++++++++++++++++++++++++++++++++++ tools/qfcc/test/test-bi.c | 18 ++++++++++++ tools/qfcc/test/test-harness.c | 2 +- tools/qfcc/test/test-harness.h | 6 ++++ 8 files changed, 131 insertions(+), 23 deletions(-) create mode 100644 tools/qfcc/test/state.r create mode 100644 tools/qfcc/test/test-harness.h diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 819969afc..f4dd2d716 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -571,6 +571,7 @@ void convert_name (expr_t *e); expr_t *append_expr (expr_t *block, expr_t *e); +expr_t *reverse_expr_list (expr_t *e); void print_expr (expr_t *e); void dump_dot_expr (void *e, const char *filename); @@ -607,7 +608,7 @@ expr_t *build_do_while_statement (expr_t *statement, int not, expr_t *test, expr_t *build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t *statement, expr_t *break_label, expr_t *continue_label); -expr_t *build_state_expr (expr_t *frame, expr_t *think, expr_t *step); +expr_t *build_state_expr (expr_t *e); expr_t *think_expr (struct symbol_s *think_sym); expr_t *assign_expr (expr_t *e1, expr_t *e2); expr_t *cast_expr (struct type_s *t, expr_t *e); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f734710b2..d87b17ac4 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2472,8 +2472,18 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next, } expr_t * -build_state_expr (expr_t *frame, expr_t *think, expr_t *step) +build_state_expr (expr_t *e) { + expr_t *frame = 0; + expr_t *think = 0; + expr_t *step = 0; + + e = reverse_expr_list (e); + frame = e; + think = frame->next; + step = think->next; + if (think->type == ex_symbol) + think = think_expr (think->e.symbol); if (is_integer_val (frame)) convert_int (frame); if (!type_assignable (&type_float, get_type (frame))) @@ -2481,10 +2491,12 @@ build_state_expr (expr_t *frame, expr_t *think, expr_t *step) if (extract_type (think) != ev_func) return error (think, "invalid type for think"); if (step) { + if (step->next) + return error (step->next, "too many state arguments"); if (is_integer_val (step)) convert_int (step); if (!type_assignable (&type_float, get_type (step))) - return error (step, "invalid type for frame number"); + return error (step, "invalid type for step"); } return new_state_expr (frame, think, step); } @@ -2951,3 +2963,17 @@ sizeof_expr (expr_t *expr, struct type_s *type) expr = new_integer_expr (type_size (type)); return expr; } + +expr_t * +reverse_expr_list (expr_t *e) +{ + expr_t *r = 0; + + while (e) { + expr_t *t = e->next; + e->next = r; + r = e; + e = t; + } + return r; +} diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 14937a811..a0be3c5d8 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -180,8 +180,8 @@ int yylex (void); %type methoddef %type opt_initializer var_initializer local_def -%type opt_expr fexpr expr element_list element -%type optional_state_expr think opt_step texpr +%type opt_expr fexpr expr element_list element vector_expr +%type optional_state_expr texpr %type statement statements compound_statement %type else label break_label continue_label %type unary_expr cast_expr opt_arg_list arg_list @@ -1026,23 +1026,7 @@ var_initializer optional_state_expr : /* emtpy */ { $$ = 0; } - | '[' fexpr ',' think opt_step ']' { $$ = build_state_expr ($2, $4, $5); } - ; - -think - : identifier - { - $$ = think_expr ($1); - } - | '(' fexpr ')' - { - $$ = $2; - } - ; - -opt_step - : ',' fexpr { $$ = $2; } - | /* empty */ { $$ = 0; } + | vector_expr { $$ = build_state_expr ($1); } ; element_list @@ -1261,9 +1245,21 @@ unary_expr { $$ = sizeof_expr (0, $3->type); } + | vector_expr { $$ = $1; } | obj_expr { $$ = $1; } ; +vector_expr + : '[' fexpr ',' arg_list ']' + { + expr_t *t = $4; + while (t->next) + t = t->next; + t->next = $2; + $$ = $4; + } + ; + cast_expr : '(' abstract_decl ')' cast_expr { diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index de5a7a078..eee7ba5be 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -28,6 +28,7 @@ test_progs_dat=\ paramret.dat \ return-ivar.dat \ sendv.dat \ + state.dat \ structlive.dat \ structptr.dat \ vecinit.dat \ @@ -109,6 +110,13 @@ sendv.dat: $(sendv_obj) $(QFCC_DEP) sendv.run: Makefile build-run $(srcdir)/build-run $@ +state_dat_SOURCES=state.r +state_obj=$(state_dat_SOURCES:.r=.qfo) +state.dat: $(state_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(state_obj) +state.run: Makefile build-run + $(srcdir)/build-run $@ + structlive_dat_SOURCES=structlive.r structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) structlive.dat: $(structlive_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/state.r b/tools/qfcc/test/state.r new file mode 100644 index 000000000..7fec3c2d0 --- /dev/null +++ b/tools/qfcc/test/state.r @@ -0,0 +1,53 @@ +#include "test-harness.h" + +.void() think; +.float nextthink; +.float frame; +entity self; +float time; + +$frame frame0 frame1 frame2 frame3 + +void +state0 (void) +[$frame1, state1] +{ + if (self.frame != $frame1 || self.think != state1 + || self.nextthink != 0.1) { + printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); + exit (1); + } +} + +void +state1 (void) +[$frame2, state2, 0.2] +{ + if (self.frame != $frame2 || self.think != state2 + || self.nextthink != 0.2) { + printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); + exit (1); + } +} + +void +state2 (void) +[$frame0, state0, 0.5] +{ + if (self.frame != $frame0 || self.think != state0 + || self.nextthink != 0.5) { + printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); + exit (1); + } +} + +int +main () +{ + self = spawn (); + state0(); + while (self.frame != $frame0) { + self.think(); + } + return 0; +} diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index a820aa9d8..bec2b247e 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -79,11 +79,29 @@ bi_exit (progs_t *pr) exit (P_INT (pr, 0)); } +static void +bi_spawn (progs_t *pr) +{ + edict_t *ed; + ed = ED_Alloc (pr); + RETURN_EDICT (pr, ed); +} + +static void +bi_remove (progs_t *pr) +{ + edict_t *ed; + ed = P_EDICT (pr, 0); + ED_Free (pr, ed); +} + static builtin_t builtins[] = { {"printf", bi_printf, -1}, {"errno", bi_errno, -1}, {"strerror", bi_strerror, -1}, {"exit", bi_exit, -1}, + {"spawn", bi_spawn, -1}, + {"remove", bi_remove, -1}, {0} }; diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index eff3ff9a4..87cd26c55 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -165,7 +165,7 @@ load_progs (const char *name) return 0; } pr.progs_name = name; - PR_LoadProgsFile (&pr, file, size, 1, 1024 * 1024); + PR_LoadProgsFile (&pr, file, size, 16, 1024 * 1024); Qclose (file); if (!PR_RunLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); diff --git a/tools/qfcc/test/test-harness.h b/tools/qfcc/test/test-harness.h new file mode 100644 index 000000000..959910534 --- /dev/null +++ b/tools/qfcc/test/test-harness.h @@ -0,0 +1,6 @@ +void printf (string fmt, ...) = #0; +int errno (void) = #0; +string strerror (int err) = #0; +void exit (int code) = #0; +entity spawn (void) = #0; +void remove (entity e) = #0; From c197d6a4f970821927f6af5b512226fee8997d95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 11:43:57 +0900 Subject: [PATCH 0018/1519] Ignore the new test-driver link. It seems to have come with automake 1.13. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5d6dd8c0a..b3bca858c 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ core /mkinstalldirs /quakeforge-config /quakeforge.lsm +/test-driver /ylwrap # /RPM/ From 2572811bf464755a3313daa54a033e8d3c8fde50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 15:33:21 +0900 Subject: [PATCH 0019/1519] Add support for quaternion.w/x/y/z. It's sometimes more useful to have direct access to each individual component of the imaginary part of the quaternion, and then for consistency, alias w and s. --- tools/qfcc/source/type.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 92d63b11f..51615e9d7 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -885,6 +885,21 @@ init_types (void) make_structure ("@quaternion", 's', quaternion_struct, &type_quaternion); type_quaternion.type = ev_quat; type_quaternion.meta = ty_none; + { + symbol_t *sym; + sym = new_symbol_type ("w", &type_float); + sym->s.offset = 0; + symtab_addsymbol (type_quaternion.t.symtab, sym); + sym = new_symbol_type ("x", &type_float); + sym->s.offset = 1; + symtab_addsymbol (type_quaternion.t.symtab, sym); + sym = new_symbol_type ("y", &type_float); + sym->s.offset = 2; + symtab_addsymbol (type_quaternion.t.symtab, sym); + sym = new_symbol_type ("z", &type_float); + sym->s.offset = 3; + symtab_addsymbol (type_quaternion.t.symtab, sym); + } } void From 7a7a68510542f29b597288889f5dbd7340a768fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 15:37:08 +0900 Subject: [PATCH 0020/1519] Add support for actual vector expressions. Currently, they can represent either vectors or quaternions, and the quaternions can be in either [s, v] form or [w, x, y, z] form. Many things will not actual work yet as the vector expression needs to be converted into the appropriate form for assigning the elements to the components of the "vector" type. --- tools/qfcc/include/expr.h | 8 +++++ tools/qfcc/source/dot_expr.c | 9 ++++++ tools/qfcc/source/expr.c | 57 ++++++++++++++++++++++++++++++++++ tools/qfcc/source/qc-parse.y | 2 +- tools/qfcc/source/statements.c | 2 ++ 5 files changed, 77 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f4dd2d716..5729e316e 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -51,6 +51,7 @@ typedef enum { ex_uexpr, ///< unary expression (::ex_expr_t) ex_symbol, ///< non-temporary variable (::symbol_t) ex_temp, ///< temporary variable (::ex_temp_t) + ex_vector, ///< "vector" expression (::ex_vector_t) ex_nil, ///< umm, nil, null. nuff said (0 of any type) ex_value, ///< constant value (::ex_value_t) @@ -96,6 +97,11 @@ typedef struct { struct type_s *type; ///< The type of the temporary variable. } ex_temp_t; +typedef struct { + struct type_s *type; ///< Type of vector (vector/quaternion) + struct expr_s *list; ///< Linked list of element expressions. +} ex_vector_t; + /** Pointer constant expression. Represent a pointer to an absolute address in data space. @@ -199,6 +205,7 @@ typedef struct expr_s { ex_expr_t expr; ///< binary or unary expression struct symbol_s *symbol; ///< symbol reference expression ex_temp_t temp; ///< temporary variable expression + ex_vector_t vector; ///< vector expression list ex_value_t *value; ///< constant value } e; } expr_t; @@ -396,6 +403,7 @@ float expr_float (expr_t *e); */ expr_t *new_vector_expr (const float *vector_val); const float *expr_vector (expr_t *e); +expr_t *new_vector_list (expr_t *e); /** Create a new entity constant expression node. diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index aaf5b8706..301086dba 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -361,6 +361,14 @@ print_temp (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->line); } +static void +print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"vector FIXME\"];\n", indent, "", e); +} + static void print_nil (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -455,6 +463,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) print_uexpr, print_symbol, print_temp, + print_vector, print_nil, print_value, }; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index d87b17ac4..2efa90cd3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -178,6 +178,8 @@ get_type (expr_t *e) convert_int (e); } return ev_types[e->e.value->type]; + case ex_vector: + return e->e.vector.type; } return 0; } @@ -355,6 +357,18 @@ copy_expr (expr_t *e) n->file = pr.source_file; n->e.temp.expr = copy_expr (e->e.temp.expr); return n; + case ex_vector: + n = new_expr (); + n->e.vector.type = e->e.vector.type; + n->e.vector.list = copy_expr (e->e.vector.list); + n = n->e.vector.list; + t = e->e.vector.list; + while (t->next) { + n->next = copy_expr (t->next); + n = n->next; + t = t->next; + } + return n; } internal_error (e, "invalid expression"); } @@ -546,6 +560,46 @@ new_vector_expr (const float *vector_val) return e; } +expr_t * +new_vector_list (expr_t *e) +{ + expr_t *t; + int count; + type_t *type = &type_vector; + expr_t *vec; + + e = reverse_expr_list (e); // put the elements in the right order + for (t = e, count = 0; t; t = t->next) + count++; + switch (count) { + case 4: + type = &type_quaternion; + case 3: + // quaternion or vector. all expressions must be compatible with + // a float + for (t = e; t; t = t->next) + if (!type_assignable (&type_float, get_type (t))) + return error (t, "invalid type for vector element"); + vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = type; + vec->e.vector.list = e; + break; + case 2: + // quaternion. first expression must be compatible with a float, + // the other must be a vector + if (!type_assignable (&type_float, get_type (e)) + || type_assignable (&type_vector, get_type(e->next))) { + return error (t, "invalid types for vector elements"); + } + // s, v + break; + default: + return error (e, "invalid number of elements in vector exprssion"); + } + return vec; +} + expr_t * new_entity_expr (int entity_val) { @@ -1669,6 +1723,7 @@ unary_expr (int op, expr_t *e) case ex_expr: case ex_bool: case ex_temp: + case ex_vector: { expr_t *n = new_unary_expr (op, e); @@ -1733,6 +1788,7 @@ unary_expr (int op, expr_t *e) case ex_expr: case ex_symbol: case ex_temp: + case ex_vector: { expr_t *n = new_unary_expr (op, e); @@ -1793,6 +1849,7 @@ unary_expr (int op, expr_t *e) case ex_bool: case ex_symbol: case ex_temp: + case ex_vector: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_integer_expr (-1); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a0be3c5d8..bf2ff86f4 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1245,7 +1245,7 @@ unary_expr { $$ = sizeof_expr (0, $3->type); } - | vector_expr { $$ = $1; } + | vector_expr { $$ = new_vector_list ($1); } | obj_expr { $$ = $1; } ; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index de425b0dd..ac4b140f1 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1005,6 +1005,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) expr_uexpr, expr_symbol, expr_temp, + 0, // ex_vector 0, // ex_nil expr_value, }; @@ -1287,6 +1288,7 @@ statement_slist (sblock_t *sblock, expr_t *e) statement_uexpr, statement_nonexec, // ex_symbol statement_nonexec, // ex_temp + statement_nonexec, // ex_vector statement_nonexec, // ex_nil statement_nonexec, // ex_value }; From 7f50333b2c089f4844d4f7ffe7fa9b004e9422aa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 15:42:11 +0900 Subject: [PATCH 0021/1519] Add support for constant [] vector expressions. --- tools/qfcc/include/expr.h | 2 ++ tools/qfcc/source/expr.c | 60 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5729e316e..cb84ac691 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -577,6 +577,8 @@ expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type, */ void convert_name (expr_t *e); +expr_t *convert_vector (expr_t *e); + expr_t *append_expr (expr_t *block, expr_t *e); expr_t *reverse_expr_list (expr_t *e); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 2efa90cd3..2b9bb58d3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -138,6 +138,65 @@ convert: e->e = new->e; } +expr_t * +convert_vector (expr_t *e) +{ + float val[4]; + + if (e->type != ex_vector) + return e; + if (e->e.vector.type == &type_vector) { + // guaranteed to have three elements + expr_t *x = e->e.vector.list; + expr_t *y = x->next; + expr_t *z = y->next; + x = fold_constants (cast_expr (&type_float, x)); + y = fold_constants (cast_expr (&type_float, y)); + z = fold_constants (cast_expr (&type_float, z)); + if (is_constant (x) && is_constant (y) && is_constant (z)) { + val[0] = expr_float(x); + val[1] = expr_float(y); + val[2] = expr_float(z); + return new_vector_expr (val); + } + } + if (e->e.vector.type == &type_quaternion) { + // guaranteed to have two or four elements + if (e->e.vector.list->next->next) { + // four vals: w, x, y, z + expr_t *w = e->e.vector.list; + expr_t *x = w->next; + expr_t *y = x->next; + expr_t *z = y->next; + w = fold_constants (cast_expr (&type_float, w)); + x = fold_constants (cast_expr (&type_float, x)); + y = fold_constants (cast_expr (&type_float, y)); + z = fold_constants (cast_expr (&type_float, z)); + if (is_constant (w) && is_constant (x) && is_constant (y) + && is_constant (z)) { + val[0] = expr_float(w); + val[1] = expr_float(x); + val[2] = expr_float(y); + val[3] = expr_float(z); + return new_quaternion_expr (val); + } + } else { + // s, v + expr_t *s = e->e.vector.list; + expr_t *v = s->next; + + s = fold_constants (cast_expr (&type_float, s)); + v = convert_vector (v); + if (is_constant (s) && is_constant (v)) { + val[0] = expr_float (s); + memcpy (val + 1, expr_vector (v), 3 * sizeof (float)); + return new_quaternion_expr (val); + } + } + } + internal_error (e, "bogus vector expression"); +} + type_t * get_type (expr_t *e) { @@ -2636,6 +2695,7 @@ assign_expr (expr_t *e1, expr_t *e2) convert_name (e1); convert_name (e2); + e2 = convert_vector (e2); if (e1->type == ex_error) return e1; From c13f2c2c233053098264327ca03e56c7c480656e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jun 2013 15:52:24 +0900 Subject: [PATCH 0022/1519] Fix the support for [s, v] for quaterions. --- tools/qfcc/source/expr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 2b9bb58d3..4d4f37e31 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -648,10 +648,14 @@ new_vector_list (expr_t *e) // quaternion. first expression must be compatible with a float, // the other must be a vector if (!type_assignable (&type_float, get_type (e)) - || type_assignable (&type_vector, get_type(e->next))) { + || !type_assignable (&type_vector, get_type(e->next))) { return error (t, "invalid types for vector elements"); } // s, v + vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = &type_quaternion; + vec->e.vector.list = e; break; default: return error (e, "invalid number of elements in vector exprssion"); From b66cbeeb57730f9f6be37814e7cbcde4e3751241 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jun 2013 09:24:56 +0900 Subject: [PATCH 0023/1519] Run fold_constants on comparison operands. This is a bit of a workaround to ensure the operands have their types setup correctly. Really, binary_expr needs to handle expression types properly. This fixes the bogus error for comparing the result of pointer subtraction with an integer. --- tools/qfcc/source/expr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 4d4f37e31..f44344084 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1626,6 +1626,10 @@ binary_expr (int op, expr_t *e1, expr_t *e2) e1 = test_expr (e1); e2 = test_expr (e2); } + if (is_compare (op)) { + e1 = fold_constants (e1); + e2 = fold_constants (e2); + } if (e1->type == ex_error) return e1; From ca9693d9cdff7269f353de4b298d0d06010033e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Sep 2013 17:41:20 +0900 Subject: [PATCH 0024/1519] Expose convert_from_bool(). --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index cb84ac691..3b991799b 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -593,6 +593,7 @@ void convert_nil (expr_t *e, struct type_s *t); expr_t *test_expr (expr_t *e); void backpatch (ex_list_t *list, expr_t *label); expr_t *convert_bool (expr_t *e, int block); +expr_t *convert_from_bool (expr_t *e, struct type_s *type); expr_t *bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2); expr_t *binary_expr (int op, expr_t *e1, expr_t *e2); expr_t *asx_expr (int op, expr_t *e1, expr_t *e2); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f44344084..d8111ead5 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1363,7 +1363,7 @@ convert_bool (expr_t *e, int block) return e; } -static expr_t * +expr_t * convert_from_bool (expr_t *e, type_t *type) { expr_t *zero; From 3295370328a7a5e53ffbcda51f82fc053dbe9bdb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Sep 2013 17:43:33 +0900 Subject: [PATCH 0025/1519] Expose and use field_expr(). This may cause problems later on, but it is needed for the binary_expr() cleanup. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/class.c | 4 ++-- tools/qfcc/source/def.c | 4 ++-- tools/qfcc/source/expr.c | 14 +++++++------- tools/qfcc/source/qc-parse.y | 2 +- tools/qfcc/source/statements.c | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 3b991799b..8973f810b 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -596,6 +596,7 @@ expr_t *convert_bool (expr_t *e, int block); expr_t *convert_from_bool (expr_t *e, struct type_s *type); expr_t *bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2); expr_t *binary_expr (int op, expr_t *e1, expr_t *e2); +expr_t *field_expr (expr_t *e1, expr_t *e2); expr_t *asx_expr (int op, expr_t *e1, expr_t *e2); expr_t *unary_expr (int op, expr_t *e); expr_t *build_function_call (expr_t *fexpr, struct type_s *ftype, diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 65517b356..a7898e5db 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1576,8 +1576,8 @@ class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope, if (sym->sy_type != sy_var) continue; sym->sy_type = sy_expr; - sym->s.expr = binary_expr ('.', copy_expr (self_expr), - new_symbol_expr (new_symbol (sym->name))); + sym->s.expr = field_expr (copy_expr (self_expr), + new_symbol_expr (new_symbol (sym->name))); } } diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index e26105f3d..c16aa9912 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -426,8 +426,8 @@ init_vector_components (symbol_t *vector_sym, int is_field) if (is_field) { expr = new_field_expr (i, &type_float, vector_sym->s.def); } else { - expr = binary_expr ('.', vector_expr, - new_symbol_expr (new_symbol (fields[i]))); + expr = field_expr (vector_expr, + new_symbol_expr (new_symbol (fields[i]))); } } sym->sy_type = sy_expr; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index d8111ead5..e85817d1e 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1075,7 +1075,7 @@ get_struct_field (type_t *t1, expr_t *e1, expr_t *e2) return field; } -static expr_t * +expr_t * field_expr (expr_t *e1, expr_t *e2) { type_t *t1, *t2; @@ -2756,10 +2756,10 @@ assign_expr (expr_t *e1, expr_t *e2) warning (e1, "assignment between disparate function types"); } else if (t1->type == ev_float && t2->type == ev_vector) { warning (e1, "assignment of vector to float"); - e2 = binary_expr ('.', e2, new_name_expr ("x")); + e2 = field_expr (e2, new_name_expr ("x")); } else if (t1->type == ev_vector && t2->type == ev_float) { warning (e1, "assignment of float to vector"); - e1 = binary_expr ('.', e1, new_name_expr ("x")); + e1 = field_expr (e1, new_name_expr ("x")); } else { return type_mismatch (e1, e2, op); } @@ -2972,13 +2972,13 @@ super_expr (class_type_t *class_type) super_block = new_block_expr (); - e = assign_expr (binary_expr ('.', super, new_name_expr ("self")), - new_name_expr ("self")); + e = assign_expr (field_expr (super, new_name_expr ("self")), + new_name_expr ("self")); append_expr (super_block, e); e = new_symbol_expr (class_pointer_symbol (class)); - e = assign_expr (binary_expr ('.', super, new_name_expr ("class")), - binary_expr ('.', e, new_name_expr ("super_class"))); + e = assign_expr (field_expr (super, new_name_expr ("class")), + field_expr (e, new_name_expr ("super_class"))); append_expr (super_block, e); e = address_expr (super, 0, 0); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index bf2ff86f4..2ab9d4144 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1231,7 +1231,7 @@ unary_expr | '(' expr ')' { $$ = $2; $$->paren = 1; } | unary_expr '(' opt_arg_list ')' { $$ = function_expr ($1, $3); } | unary_expr '[' expr ']' { $$ = array_expr ($1, $3); } - | unary_expr '.' unary_expr { $$ = binary_expr ('.', $1, $3); } + | unary_expr '.' unary_expr { $$ = field_expr ($1, $3); } | INCOP unary_expr { $$ = incop_expr ($1, $2, 0); } | unary_expr INCOP { $$ = incop_expr ($2, $1, 1); } | '+' cast_expr %prec UNARY { $$ = $2; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ac4b140f1..e1606705e 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -624,7 +624,7 @@ vector_call (sblock_t *sblock, expr_t *earg, expr_t *param, int ind, for (i = 0; i < 3; i++) { n = new_name_expr (names[i]); v = new_float_expr (earg->e.value->v.vector_val[i]); - a = assign_expr (binary_expr ('.', param, n), v); + a = assign_expr (field_expr (param, n), v); param = new_param_expr (get_type (earg), ind); a->line = earg->line; a->file = earg->file; From ec98954dfc6bcd666b3766cdac2276c985887c60 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Sep 2013 17:44:29 +0900 Subject: [PATCH 0026/1519] Remove the small struct optimization. It might cause trouble for the binary_expr() cleanup. --- tools/qfcc/source/type.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 51615e9d7..586a7b1a0 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -101,13 +101,8 @@ low_level_type (type_t *type) return type->type; if (is_enum (type)) return type_default->type; - if (is_struct (type)) { - //FIXME does this break anything? - //maybe the peephole optimizer should do this sort of thing. - if (type_size (type) == 1) - return ev_integer; + if (is_struct (type)) return ev_void; - } if (is_array (type)) return ev_void; internal_error (0, "invalid complex type"); From 4bc40b39171dc71dbf9a91c3f1577004425d0c1d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Sep 2013 17:48:06 +0900 Subject: [PATCH 0027/1519] Rewrite binary_expr(). It is now in its own file and uses table lookups to check for valid type and operator combinations, and also the resulting type of the expression. This probably breaks multiple function calls in the one expression. --- tools/qfcc/source/Makefile.am | 3 +- tools/qfcc/source/expr.c | 201 -------- tools/qfcc/source/expr_binary.c | 787 ++++++++++++++++++++++++++++++++ 3 files changed, 789 insertions(+), 202 deletions(-) create mode 100644 tools/qfcc/source/expr_binary.c diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index b2c5f0711..b5674b614 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -41,7 +41,8 @@ bin_SCRIPTS= qfpreqcc common_src=\ class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \ - expr.c flow.c function.c grab.c idstuff.c linker.c method.c obj_file.c \ + expr.c expr_binary.c flow.c function.c grab.c idstuff.c linker.c method.c \ + obj_file.c \ obj_type.c opcodes.c options.c pragma.c qfcc.c reloc.c shared.c \ statements.c strpool.c struct.c switch.c symtab.c type.c value.c diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index e85817d1e..bc5ba5a6e 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1488,91 +1488,6 @@ is_logic (int op) return 0; } -static expr_t * -check_precedence (int op, expr_t *e1, expr_t *e2) -{ - if (e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) { - if (options.traditional) { - if (op != AND && op != OR && op != '=') { - notice (e1, "precedence of `!' and `%s' inverted for " - "traditional code", get_op_string (op)); - e1->e.expr.e1->paren = 1; - return unary_expr ('!', binary_expr (op, e1->e.expr.e1, e2)); - } - } else if (op == '&' || op == '|') { - if (options.warnings.precedence) - warning (e1, "ambiguous logic. Suggest explicit parentheses " - "with expressions involving ! and %s", - get_op_string (op)); - } - } - if (options.traditional) { - if (e2->type == ex_expr && !e2->paren) { - if (((op == '&' || op == '|') - && (is_math_op (e2->e.expr.op) || is_compare (e2->e.expr.op))) - || (op == '=' - && (e2->e.expr.op == OR || e2->e.expr.op == AND))) { - notice (e1, "precedence of `%s' and `%s' inverted for " - "traditional code", get_op_string (op), - get_op_string (e2->e.expr.op)); - e1 = binary_expr (op, e1, e2->e.expr.e1); - e1->paren = 1; - return binary_expr (e2->e.expr.op, e1, e2->e.expr.e2); - } - if (((op == EQ || op == NE) && is_compare (e2->e.expr.op)) - || (op == OR && e2->e.expr.op == AND) - || (op == '|' && e2->e.expr.op == '&')) { - notice (e1, "precedence of `%s' raised to `%s' for " - "traditional code", get_op_string (op), - get_op_string (e2->e.expr.op)); - e1 = binary_expr (op, e1, e2->e.expr.e1); - e1->paren = 1; - return binary_expr (e2->e.expr.op, e1, e2->e.expr.e2); - } - } else if (e1->type == ex_expr && !e1->paren) { - if (((op == '&' || op == '|') - && (is_math_op (e1->e.expr.op) || is_compare (e1->e.expr.op))) - || (op == '=' - && (e1->e.expr.op == OR || e1->e.expr.op == AND))) { - notice (e1, "precedence of `%s' and `%s' inverted for " - "traditional code", get_op_string (op), - get_op_string (e1->e.expr.op)); - e2 = binary_expr (op, e1->e.expr.e2, e2); - e2->paren = 1; - return binary_expr (e1->e.expr.op, e1->e.expr.e1, e2); - } - } - } else { - if (e2->type == ex_expr && !e2->paren) { - if ((op == '&' || op == '|' || op == '^') - && (is_math_op (e2->e.expr.op) - || is_compare (e2->e.expr.op))) { - if (options.warnings.precedence) - warning (e2, "suggest parentheses around %s in " - "operand of %c", - is_compare (e2->e.expr.op) - ? "comparison" - : get_op_string (e2->e.expr.op), - op); - } - } - if (e1->type == ex_expr && !e1->paren) { - if ((op == '&' || op == '|' || op == '^') - && (is_math_op (e1->e.expr.op) - || is_compare (e1->e.expr.op))) { - if (options.warnings.precedence) - warning (e1, "suggest parentheses around %s in " - "operand of %c", - is_compare (e1->e.expr.op) - ? "comparison" - : get_op_string (e1->e.expr.op), - op); - } - } - } - return 0; -} - static int has_function_call (expr_t *e) { @@ -1599,122 +1514,6 @@ has_function_call (expr_t *e) } } -expr_t * -binary_expr (int op, expr_t *e1, expr_t *e2) -{ - type_t *t1, *t2; - type_t *type = 0; - expr_t *e; - - if (e1->type == ex_error) - return e1; - if (e2->type == ex_error) - return e2; - - convert_name (e1); - if (e1->type == ex_block && e1->e.block.is_call - && has_function_call (e2) && e1->e.block.result) { - e = new_temp_def_expr (get_type (e1->e.block.result)); - e1 = assign_expr (e, e1); - } - - if (op == '.') - return field_expr (e1, e2); - - convert_name (e2); - if (op == OR || op == AND) { - e1 = test_expr (e1); - e2 = test_expr (e2); - } - if (is_compare (op)) { - e1 = fold_constants (e1); - e2 = fold_constants (e2); - } - - if (e1->type == ex_error) - return e1; - if (e2->type == ex_error) - return e2; - t1 = get_type (e1); - t2 = get_type (e2); - if (!t1 || !t2) - internal_error (e1, 0); - if (op == EQ || op == NE) { - if (e1->type == ex_nil) { - t1 = t2; - convert_nil (e1, t1); - } else if (e2->type == ex_nil) { - t2 = t1; - convert_nil (e2, t2); - } - } - - if (e1->type == ex_bool) - e1 = convert_from_bool (e1, t2); - - if (e2->type == ex_bool) - e2 = convert_from_bool (e2, t1); - - if ((e = check_precedence (op, e1, e2))) - return e; - - type = t1; - - if (is_compare (op)) { - if (!type_assignable (t1, t2)) - return error (e1, "type mismatch for %s", get_op_string (op)); - } - if (is_compare (op) || is_logic (op)) { - if (options.code.progsversion > PROG_ID_VERSION) - type = &type_integer; - else - type = &type_float; - } else if (op == '*' && t1 == &type_vector && t2 == &type_vector) { - type = &type_float; - } - if (!type) - internal_error (e1, 0); - - if (options.code.progsversion == PROG_ID_VERSION) { - switch (op) { - case '%': - { - expr_t *tmp1, *tmp2, *tmp3, *tmp4, *t1, *t2; - e = new_block_expr (); - t1 = new_temp_def_expr (&type_float); - t2 = new_temp_def_expr (&type_float); - tmp1 = new_temp_def_expr (&type_float); - tmp2 = new_temp_def_expr (&type_float); - tmp3 = new_temp_def_expr (&type_float); - tmp4 = new_temp_def_expr (&type_float); - - append_expr (e, assign_expr (t1, e1)); - e1 = binary_expr ('&', t1, t1); - append_expr (e, assign_expr (tmp1, e1)); - - append_expr (e, assign_expr (t2, e2)); - e2 = binary_expr ('&', t2, t2); - append_expr (e, assign_expr (tmp2, e2)); - - e1 = binary_expr ('/', tmp1, tmp2); - append_expr (e, assign_expr (tmp3, e1)); - - e2 = binary_expr ('&', tmp3, tmp3); - append_expr (e, assign_expr (tmp4, e2)); - - e1 = binary_expr ('*', tmp2, tmp4); - e2 = binary_expr ('-', tmp1, e1); - e->e.block.result = e2; - return e; - } - break; - } - } - e = new_binary_expr (op, e1, e2); - e->e.expr.type = type; - return e; -} - expr_t * asx_expr (int op, expr_t *e1, expr_t *e2) { diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c new file mode 100644 index 000000000..d9f6f43b0 --- /dev/null +++ b/tools/qfcc/source/expr_binary.c @@ -0,0 +1,787 @@ +/* + exprtype.c + + Expression type manipulation + + Copyright (C) 2013 Bill Currie + + Author: Bill Currie + Date: 2013/06/27 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "diagnostic.h" +#include "expr.h" +#include "options.h" +#include "type.h" +#include "qc-parse.h" + +typedef struct { + int op; + type_t *type; + type_t *a_cast; + type_t *b_cast; +} expr_type_t; + +static expr_type_t string_string[] = { + {'+', &type_string}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t float_float[] = { + {'+', &type_float}, + {'-', &type_float}, + {'*', &type_float}, + {'/', &type_float}, + {'&', &type_float}, + {'|', &type_float}, + {'^', &type_float}, + {'%', &type_float}, + {SHL, &type_float}, + {SHR, &type_float}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t float_vector[] = { + {'*', &type_vector}, + {0, 0} +}; + +static expr_type_t float_quat[] = { + {'*', &type_quaternion}, + {'/', &type_quaternion}, + {0, 0} +}; + +static expr_type_t float_integer[] = { + {'+', &type_float, 0, &type_float}, + {'-', &type_float, 0, &type_float}, + {'*', &type_float, 0, &type_float}, + {'/', &type_float, 0, &type_float}, + {'&', &type_float, 0, &type_float}, + {'|', &type_float, 0, &type_float}, + {'^', &type_float, 0, &type_float}, + {'%', &type_float, 0, &type_float}, + {SHL, &type_float, 0, &type_float}, + {SHR, &type_float, 0, &type_float}, + {EQ, &type_integer, 0, &type_float}, + {NE, &type_integer, 0, &type_float}, + {LE, &type_integer, 0, &type_float}, + {GE, &type_integer, 0, &type_float}, + {LT, &type_integer, 0, &type_float}, + {GT, &type_integer, 0, &type_float}, + {0, 0} +}; +#define float_uinteger float_integer +#define float_short float_integer + +static expr_type_t vector_float[] = { + {'*', &type_vector}, + {'/', &type_vector}, + {0, 0} +}; + +static expr_type_t vector_vector[] = { + {'+', &type_vector}, + {'-', &type_vector}, + {'*', &type_float}, + {EQ, &type_integer}, + {NE, &type_integer}, + {0, 0} +}; + +#define vector_integer vector_float +#define vector_uinteger vector_float +#define vector_short vector_float + +static expr_type_t entity_entity[] = { + {EQ, &type_integer}, + {NE, &type_integer}, + {0, 0} +}; + +static expr_type_t field_field[] = { + {EQ, &type_integer}, + {NE, &type_integer}, + {0, 0} +}; + +static expr_type_t func_func[] = { + {EQ, &type_integer}, + {NE, &type_integer}, + {0, 0} +}; + +static expr_type_t pointer_pointer[] = { + {'-', &type_integer, &type_integer, &type_integer}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t pointer_integer[] = { + {'+', &type_pointer}, + {'-', &type_pointer}, + {0, 0} +}; +#define pointer_uinteger pointer_integer +#define pointer_short pointer_integer + +static expr_type_t quat_float[] = { + {'*', &type_quaternion}, + {'/', &type_quaternion}, + {0, 0} +}; + +static expr_type_t quat_vector[] = { + {'*', &type_vector}, + {0, 0} +}; + +static expr_type_t quat_quat[] = { + {'+', &type_quaternion}, + {'-', &type_quaternion}, + {'*', &type_quaternion}, + {EQ, &type_integer}, + {NE, &type_integer}, + {0, 0} +}; + +static expr_type_t quat_integer[] = { + {'*', &type_quaternion, 0, &type_float}, + {'/', &type_quaternion, 0, &type_float}, + {0, 0} +}; +#define quat_uinteger quat_integer +#define quat_short quat_integer + +static expr_type_t integer_float[] = { + {'+', &type_float, &type_float, 0}, + {'-', &type_float, &type_float, 0}, + {'*', &type_float, &type_float, 0}, + {'/', &type_float, &type_float, 0}, + {'&', &type_float, &type_float, 0}, + {'|', &type_float, &type_float, 0}, + {'^', &type_float, &type_float, 0}, + {'%', &type_float, &type_float, 0}, + {SHL, &type_integer, 0, &type_integer}, //FIXME? + {SHR, &type_integer, 0, &type_integer}, //FIXME? + {EQ, &type_integer, &type_float, 0}, + {NE, &type_integer, &type_float, 0}, + {LE, &type_integer, &type_float, 0}, + {GE, &type_integer, &type_float, 0}, + {LT, &type_integer, &type_float, 0}, + {GT, &type_integer, &type_float, 0}, + {0, 0} +}; + +static expr_type_t integer_vector[] = { + {'*', &type_vector, &type_float, 0}, + {0, 0} +}; + +static expr_type_t integer_pointer[] = { + {'+', &type_pointer}, + {0, 0} +}; + +static expr_type_t integer_quat[] = { + {'*', &type_quaternion, &type_float, 0}, + {'/', &type_quaternion, &type_float, 0}, + {0, 0} +}; + +static expr_type_t integer_integer[] = { + {'+', &type_integer}, + {'-', &type_integer}, + {'*', &type_integer}, + {'/', &type_integer}, + {'&', &type_integer}, + {'|', &type_integer}, + {'^', &type_integer}, + {'%', &type_integer}, + {SHL, &type_integer}, + {SHR, &type_integer}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t integer_uinteger[] = { + {'+', &type_integer}, + {'-', &type_integer}, + {'*', &type_integer}, + {'/', &type_integer}, + {'&', &type_integer}, + {'|', &type_integer}, + {'^', &type_integer}, + {'%', &type_integer}, + {SHL, &type_integer}, + {SHR, &type_integer}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t integer_short[] = { + {'+', &type_integer}, + {'-', &type_integer}, + {'*', &type_integer}, + {'/', &type_integer}, + {'&', &type_integer}, + {'|', &type_integer}, + {'^', &type_integer}, + {'%', &type_integer}, + {SHL, &type_integer}, + {SHR, &type_integer}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +#define uinteger_float integer_float +#define uinteger_vector integer_vector +#define uinteger_pointer integer_pointer +#define uinteger_quat integer_quat + +static expr_type_t uinteger_integer[] = { + {'+', &type_integer}, + {'-', &type_integer}, + {'*', &type_integer}, + {'/', &type_integer}, + {'&', &type_integer}, + {'|', &type_integer}, + {'^', &type_integer}, + {'%', &type_integer}, + {SHL, &type_uinteger}, + {SHR, &type_uinteger}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t uinteger_uinteger[] = { + {'+', &type_uinteger}, + {'-', &type_uinteger}, + {'*', &type_uinteger}, + {'/', &type_uinteger}, + {'&', &type_uinteger}, + {'|', &type_uinteger}, + {'^', &type_uinteger}, + {'%', &type_uinteger}, + {SHL, &type_uinteger}, + {SHR, &type_uinteger}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; +#define uinteger_short uinteger_integer + +#define short_float integer_float +#define short_vector integer_vector +#define short_pointer integer_pointer +#define short_quat integer_quat + +static expr_type_t short_integer[] = { + {'+', &type_integer}, + {'-', &type_integer}, + {'*', &type_integer}, + {'/', &type_integer}, + {'&', &type_integer}, + {'|', &type_integer}, + {'^', &type_integer}, + {'%', &type_integer}, + {SHL, &type_short}, + {SHR, &type_short}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t short_uinteger[] = { + {'+', &type_uinteger}, + {'-', &type_uinteger}, + {'*', &type_uinteger}, + {'/', &type_uinteger}, + {'&', &type_uinteger}, + {'|', &type_uinteger}, + {'^', &type_uinteger}, + {'%', &type_uinteger}, + {SHL, &type_short}, + {SHR, &type_short}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t short_short[] = { + {'+', &type_short}, + {'-', &type_short}, + {'*', &type_short}, + {'/', &type_short}, + {'&', &type_short}, + {'|', &type_short}, + {'^', &type_short}, + {'%', &type_short}, + {SHL, &type_short}, + {SHR, &type_short}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t *string_x[] = { + 0, // ev_void + string_string, + 0, // ev_float + 0, // ev_vector + 0, // ev_entity + 0, // ev_field + 0, // ev_func + 0, // ev_pointer + 0, // ev_quat + 0, // ev_integer + 0, // ev_uinteger + 0, // ev_short +}; + +static expr_type_t *float_x[] = { + 0, // ev_void + 0, // ev_string + float_float, + float_vector, + 0, // ev_entity + 0, // ev_field + 0, // ev_func + 0, // ev_pointer + float_quat, + float_integer, + float_uinteger, + float_short, +}; + +static expr_type_t *vector_x[] = { + 0, // ev_void + 0, // ev_string + vector_float, + vector_vector, + 0, // ev_entity + 0, // ev_field + 0, // ev_func + 0, // ev_pointer + 0, // ev_quaternion + vector_integer, + vector_uinteger, + vector_short, +}; + +static expr_type_t *entity_x[] = { + 0, // ev_void + 0, // ev_string + 0, // ev_float + 0, // ev_vector + entity_entity, // ev_entity + 0, // ev_field + 0, // ev_func + 0, // ev_pointer + 0, // ev_quaternion + 0, // ev_integer + 0, // ev_uinteger + 0, // ev_short +}; + +static expr_type_t *field_x[] = { + 0, // ev_void + 0, // ev_string + 0, // ev_float + 0, // ev_vector + 0, // ev_entity + field_field, // ev_field + 0, // ev_func + 0, // ev_pointer + 0, // ev_quaternion + 0, // ev_integer + 0, // ev_uinteger + 0, // ev_short +}; + +static expr_type_t *funcx[] = { + 0, // ev_void + 0, // ev_string + 0, // ev_float + 0, // ev_vector + 0, // ev_entity + 0, // ev_field + func_func, // ev_func + 0, // ev_pointer + 0, // ev_quaternion + 0, // ev_integer + 0, // ev_uinteger + 0, // ev_short +}; + +static expr_type_t *pointer_x[] = { + 0, // ev_void + 0, // ev_string + 0, // ev_float + 0, // ev_vector + 0, // ev_entity + 0, // ev_field + 0, // ev_func + pointer_pointer, + 0, // ev_quat + pointer_integer, + pointer_uinteger, + pointer_short, +}; + +static expr_type_t *quat_x[] = { + 0, // ev_void + 0, // ev_string + quat_float, + quat_vector, + 0, // ev_entity + 0, // ev_field + 0, // ev_func + 0, // ev_pointer + quat_quat, + quat_integer, + quat_uinteger, + quat_short, +}; + +static expr_type_t *integer_x[] = { + 0, // ev_void + 0, // ev_string + integer_float, + integer_vector, + 0, // ev_entity + 0, // ev_field + 0, // ev_func + integer_pointer, + integer_quat, + integer_integer, + integer_uinteger, + integer_short, +}; + +static expr_type_t *uinteger_x[] = { + 0, // ev_void + 0, // ev_string + uinteger_float, + uinteger_vector, + 0, // ev_entity + 0, // ev_field + 0, // ev_func + uinteger_pointer, + uinteger_quat, + uinteger_integer, + uinteger_uinteger, + uinteger_short, +}; + +static expr_type_t *short_x[] = { + 0, // ev_void + 0, // ev_string + short_float, + short_vector, + 0, // ev_entity + 0, // ev_field + 0, // ev_func + short_pointer, + short_quat, + short_integer, + short_uinteger, + short_short, +}; + +static expr_type_t **binary_expr_types[] = { + 0, // ev_void + string_x, + float_x, + vector_x, + entity_x, + field_x, + funcx, + pointer_x, + quat_x, + integer_x, + uinteger_x, + short_x, +}; + +static expr_t * +invalid_binary_expr (int op, expr_t *e1, expr_t *e2) +{ + etype_t t1, t2; + t1 = extract_type (e1); + t2 = extract_type (e2); + return error (e1, "invalid binary expression: %s %s %s", + pr_type_name[t1], get_op_string (op), pr_type_name[t2]); +} + +static expr_t * +reimplement_binary_expr (int op, expr_t *e1, expr_t *e2) +{ + expr_t *e; + + if (options.code.progsversion == PROG_ID_VERSION) { + switch (op) { + case '%': + { + expr_t *tmp1, *tmp2, *tmp3, *tmp4, *t1, *t2; + e = new_block_expr (); + t1 = new_temp_def_expr (&type_float); + t2 = new_temp_def_expr (&type_float); + tmp1 = new_temp_def_expr (&type_float); + tmp2 = new_temp_def_expr (&type_float); + tmp3 = new_temp_def_expr (&type_float); + tmp4 = new_temp_def_expr (&type_float); + + append_expr (e, assign_expr (t1, e1)); + e1 = binary_expr ('&', t1, t1); + append_expr (e, assign_expr (tmp1, e1)); + + append_expr (e, assign_expr (t2, e2)); + e2 = binary_expr ('&', t2, t2); + append_expr (e, assign_expr (tmp2, e2)); + + e1 = binary_expr ('/', tmp1, tmp2); + append_expr (e, assign_expr (tmp3, e1)); + + e2 = binary_expr ('&', tmp3, tmp3); + append_expr (e, assign_expr (tmp4, e2)); + + e1 = binary_expr ('*', tmp2, tmp4); + e2 = binary_expr ('-', tmp1, e1); + e->e.block.result = e2; + return e; + } + break; + } + } + return 0; +} + +static expr_t * +check_precedence (int op, expr_t *e1, expr_t *e2) +{ + if (e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) { + if (options.traditional) { + if (op != AND && op != OR && op != '=') { + notice (e1, "precedence of `!' and `%s' inverted for " + "traditional code", get_op_string (op)); + e1->e.expr.e1->paren = 1; + return unary_expr ('!', binary_expr (op, e1->e.expr.e1, e2)); + } + } else if (op == '&' || op == '|') { + if (options.warnings.precedence) + warning (e1, "ambiguous logic. Suggest explicit parentheses " + "with expressions involving ! and %s", + get_op_string (op)); + } + } + if (options.traditional) { + if (e2->type == ex_expr && !e2->paren) { + if (((op == '&' || op == '|') + && (is_math_op (e2->e.expr.op) || is_compare (e2->e.expr.op))) + || (op == '=' + && (e2->e.expr.op == OR || e2->e.expr.op == AND))) { + notice (e1, "precedence of `%s' and `%s' inverted for " + "traditional code", get_op_string (op), + get_op_string (e2->e.expr.op)); + e1 = binary_expr (op, e1, e2->e.expr.e1); + e1->paren = 1; + return binary_expr (e2->e.expr.op, e1, e2->e.expr.e2); + } + if (((op == EQ || op == NE) && is_compare (e2->e.expr.op)) + || (op == OR && e2->e.expr.op == AND) + || (op == '|' && e2->e.expr.op == '&')) { + notice (e1, "precedence of `%s' raised to `%s' for " + "traditional code", get_op_string (op), + get_op_string (e2->e.expr.op)); + e1 = binary_expr (op, e1, e2->e.expr.e1); + e1->paren = 1; + return binary_expr (e2->e.expr.op, e1, e2->e.expr.e2); + } + } else if (e1->type == ex_expr && !e1->paren) { + if (((op == '&' || op == '|') + && (is_math_op (e1->e.expr.op) || is_compare (e1->e.expr.op))) + || (op == '=' + && (e1->e.expr.op == OR || e1->e.expr.op == AND))) { + notice (e1, "precedence of `%s' and `%s' inverted for " + "traditional code", get_op_string (op), + get_op_string (e1->e.expr.op)); + e2 = binary_expr (op, e1->e.expr.e2, e2); + e2->paren = 1; + return binary_expr (e1->e.expr.op, e1->e.expr.e1, e2); + } + } + } else { + if (e2->type == ex_expr && !e2->paren) { + if ((op == '&' || op == '|' || op == '^') + && (is_math_op (e2->e.expr.op) + || is_compare (e2->e.expr.op))) { + if (options.warnings.precedence) + warning (e2, "suggest parentheses around %s in " + "operand of %c", + is_compare (e2->e.expr.op) + ? "comparison" + : get_op_string (e2->e.expr.op), + op); + } + } + if (e1->type == ex_expr && !e1->paren) { + if ((op == '&' || op == '|' || op == '^') + && (is_math_op (e1->e.expr.op) + || is_compare (e1->e.expr.op))) { + if (options.warnings.precedence) + warning (e1, "suggest parentheses around %s in " + "operand of %c", + is_compare (e1->e.expr.op) + ? "comparison" + : get_op_string (e1->e.expr.op), + op); + } + } + } + return 0; +} + +expr_t * +binary_expr (int op, expr_t *e1, expr_t *e2) +{ + type_t *t1, *t2; + etype_t et1, et2; + expr_t *e; + expr_type_t *expr_type; + + convert_name (e1); + if (e1->type == ex_error) + return e1; + + convert_name (e2); + if (e2->type == ex_error) + return e2; + + if (e1->type == ex_bool) + e1 = convert_from_bool (e1, get_type (e2)); + if (e2->type == ex_bool) + e2 = convert_from_bool (e2, get_type (e1)); + + if ((e = check_precedence (op, e1, e2))) + return e; + + t1 = get_type (e1); + t2 = get_type (e2); + if (!t1 || !t2) + internal_error (e1, "expr with no type"); + + if (op == EQ || op == NE) { + if (e1->type == ex_nil) { + t1 = t2; + convert_nil (e1, t1); + } else if (e2->type == ex_nil) { + t2 = t1; + convert_nil (e2, t2); + } + } + + et1 = low_level_type (t1); + et2 = low_level_type (t2); + + if (et1 > ev_short || !binary_expr_types[et1]) + return invalid_binary_expr(op, e1, e2); + if (et2 > ev_short || !binary_expr_types[et1][et2]) + return invalid_binary_expr(op, e1, e2); + expr_type = binary_expr_types[et1][et2]; + while (expr_type->op && expr_type->op != op) + expr_type++; + if (!expr_type->op) + return invalid_binary_expr(op, e1, e2); + + if (expr_type->a_cast) + e1 = cast_expr (expr_type->a_cast, e1); + if (expr_type->b_cast) + e2 = cast_expr (expr_type->b_cast, e2); + + if ((e = reimplement_binary_expr (op, e1, e2))) + return e; + + e = new_binary_expr (op, e1, e2); + e->e.expr.type = expr_type->type; + if (is_compare (op) || is_logic (op)) { + if (options.code.progsversion == PROG_ID_VERSION) + e->e.expr.type = &type_float; + } + return e; +} From 70d18ecfa13b493f9b4d5f17762a4fec7889ef75 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Sep 2013 18:21:15 +0900 Subject: [PATCH 0028/1519] Add a test for functions in binary expressions. As expected, the binary_expr() cleanup broke multiple function calls in a single expression. --- tools/qfcc/test/Makefile.am | 8 ++++++++ tools/qfcc/test/func-expr.r | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tools/qfcc/test/func-expr.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index eee7ba5be..1ca89205a 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -21,6 +21,7 @@ QFCC_TEST_INCS=@QFCC_TEST_INCS@ test_progs_dat=\ chewed-alias.dat \ chewed-return.dat \ + func-expr.dat \ func-static.dat \ deadbool.dat \ infloop.dat \ @@ -61,6 +62,13 @@ chewed-return.dat: $(chewed_return_obj) $(QFCC_DEP) chewed-return.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ +func_expr_dat_SOURCES=func-expr.r +func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) +func-expr.dat: $(func_expr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) +func-expr.run: Makefile build-run + $(srcdir)/build-run $@ + func_static_dat_SOURCES=func-static.r func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) func-static.dat: $(func_static_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/func-expr.r b/tools/qfcc/test/func-expr.r new file mode 100644 index 000000000..a6b43ca4b --- /dev/null +++ b/tools/qfcc/test/func-expr.r @@ -0,0 +1,18 @@ +int foo (int i) +{ + return i; +} + +int func (int a, int b) +{ + local int x; + + x = foo (a) + foo (b); + return x; +}; + +int +main () +{ + return func (1,3) != 1 + 3; +} From db460155e9df747cadb2265f4465ee0e5fd3cd11 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Sep 2013 23:07:38 +0900 Subject: [PATCH 0029/1519] Fix multiple function calls in expressions. --- tools/qfcc/include/expr.h | 2 ++ tools/qfcc/source/expr.c | 2 +- tools/qfcc/source/expr_binary.c | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 8973f810b..5b1c6d1e7 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -516,6 +516,8 @@ int is_math_op (int op); */ int is_logic (int op); +int has_function_call (expr_t *e); + int is_string_val (expr_t *e); int is_float_val (expr_t *e); int is_vector_val (expr_t *e); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index bc5ba5a6e..14ee4b528 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1488,7 +1488,7 @@ is_logic (int op) return 0; } -static int +int has_function_call (expr_t *e) { switch (e->type) { diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index d9f6f43b0..2aa963b3a 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -726,6 +726,11 @@ binary_expr (int op, expr_t *e1, expr_t *e2) expr_type_t *expr_type; convert_name (e1); + if (e1->type == ex_block && e1->e.block.is_call + && has_function_call (e2) && e1->e.block.result) { + e = new_temp_def_expr (get_type (e1->e.block.result)); + e1 = assign_expr (e, e1); + } if (e1->type == ex_error) return e1; From c88d1987a1585a8ead5a07dcaa79c88902df4bac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Sep 2013 18:09:04 +0900 Subject: [PATCH 0030/1519] Add warnings for empty blocks in if/else/do. Saw a discussion of such in #qc and that gcc implemented it. I realized it would be pretty easy to detect and very useful (I've made such mistakes at times). --- tools/qfcc/source/expr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 14ee4b528..a5a88ca37 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2222,6 +2222,14 @@ build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) expr_t *tl = new_label_expr (); expr_t *fl = new_label_expr (); + if (els && !s2) { + warning (els, + "suggest braces around empty body in an ‘else’ statement"); + } + if (!els && !s1) { + warning (test, + "suggest braces around empty body in an ‘if’ statement"); + } pr.source_line = test->line; pr.source_file = test->file; @@ -2311,6 +2319,11 @@ build_do_while_statement (expr_t *statement, int not, expr_t *test, string_t file = pr.source_file; expr_t *do_while_expr; + if (!statement) { + warning (break_label, + "suggest braces around empty body in a ‘do’ statement"); + } + pr.source_line = test->line; pr.source_file = test->file; From eeaf2bc43f695a6b6a97e9c63bc2bedf4f0375a2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Nov 2013 11:19:50 +0900 Subject: [PATCH 0031/1519] Return None instead of False from parse_entity. Don't remember how I found that one, but None makes much more sense. --- tools/io_qfmap/map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/io_qfmap/map.py b/tools/io_qfmap/map.py index b05c7392c..b0820de69 100644 --- a/tools/io_qfmap/map.py +++ b/tools/io_qfmap/map.py @@ -229,7 +229,7 @@ def parse_epair(script, mapent): def parse_entity(script): if script.getToken(True) == None: - return False + return None if script.token != "{": map_error(script, "Missing {") mapent = Entity() From 6996e7295a9d3fd0d9ade07fa81da13ec24c7b02 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Nov 2013 11:21:40 +0900 Subject: [PATCH 0032/1519] Add a getLine method to Script. It returns the rest of the line (minus // style comments) as the token. I needed it in another project but this is my central repository for script.py. --- tools/io_qfmap/script.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/io_qfmap/script.py b/tools/io_qfmap/script.py index 170f79f14..9e34934f9 100644 --- a/tools/io_qfmap/script.py +++ b/tools/io_qfmap/script.py @@ -61,6 +61,24 @@ class Script: continue return True return False + def getLine(self): + start = self.pos + end = start + while self.pos < len(self.text): + if self.text[self.pos] == "\n": + self.line += 1 + self.pos += 1 + break + if self.text[self.pos:self.pos + 2] == "//": + break + self.pos += 1 + end = self.pos + if self.unget: + self.unget = False + self.token = self.token + self.text[start:end] + else: + self.token = self.text[start:end] + return self.pos < len(self.text) def getToken(self, crossline=False): if self.unget: self.unget = False From f5501fbf241ce281b6cfa43f5cd3799ecd1fcc59 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Nov 2013 13:11:50 +0900 Subject: [PATCH 0033/1519] Fix a pile of automake deprecation warnings. s/INCLUDES/AM_CPPFLAGS/g I <3 sed :) --- hw/source/Makefile.am | 2 +- libs/audio/Makefile.am | 2 +- libs/audio/renderer/Makefile.am | 2 +- libs/audio/targets/Makefile.am | 2 +- libs/audio/test/Makefile.am | 2 +- libs/client/Makefile.am | 2 +- libs/console/Makefile.am | 2 +- libs/gamecode/Makefile.am | 2 +- libs/gib/Makefile.am | 2 +- libs/models/Makefile.am | 2 +- libs/models/alias/Makefile.am | 2 +- libs/models/brush/Makefile.am | 2 +- libs/models/iqm/Makefile.am | 2 +- libs/models/sprite/Makefile.am | 2 +- libs/models/test/Makefile.am | 2 +- libs/net/Makefile.am | 2 +- libs/net/nc/Makefile.am | 2 +- libs/net/nm/Makefile.am | 2 +- libs/qw/Makefile.am | 2 +- libs/ruamoko/Makefile.am | 2 +- libs/util/Makefile.am | 2 +- libs/util/test/Makefile.am | 2 +- libs/video/renderer/Makefile.am | 2 +- libs/video/renderer/gl/Makefile.am | 2 +- libs/video/renderer/glsl/Makefile.am | 2 +- libs/video/renderer/sw/Makefile.am | 2 +- libs/video/renderer/sw32/Makefile.am | 2 +- libs/video/targets/Makefile.am | 2 +- nq/source/Makefile.am | 2 +- qtv/source/Makefile.am | 2 +- qw/source/Makefile.am | 2 +- ruamoko/gui/Makefile.am | 4 ++-- ruamoko/lib/Makefile.am | 4 ++-- ruamoko/scheme/Makefile.am | 4 ++-- tools/bsp2img/Makefile.am | 2 +- tools/carne/Makefile.am | 2 +- tools/pak/Makefile.am | 2 +- tools/qfbsp/source/Makefile.am | 2 +- tools/qfcc/source/Makefile.am | 2 +- tools/qfcc/test/Makefile.am | 2 +- tools/qflight/source/Makefile.am | 2 +- tools/qflmp/Makefile.am | 2 +- tools/qfmodelgen/source/Makefile.am | 2 +- tools/qfspritegen/Makefile.am | 2 +- tools/qfvis/source/Makefile.am | 2 +- tools/qwaq/Makefile.am | 2 +- tools/wad/Makefile.am | 2 +- tools/wav/Makefile.am | 2 +- 48 files changed, 51 insertions(+), 51 deletions(-) diff --git a/hw/source/Makefile.am b/hw/source/Makefile.am index 25a0c90b3..d5ad0658e 100644 --- a/hw/source/Makefile.am +++ b/hw/source/Makefile.am @@ -30,7 +30,7 @@ AUTOMAKE_OPTIONS= foreign # Stuff that is common to both client and server -INCLUDES= -I$(top_srcdir)/include -I$(top_srcdir)/hw/include +AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/hw/include SDL_LIBS = @SDL_LIBS@ bin_PROGRAMS= @HW_TARGETS@ diff --git a/libs/audio/Makefile.am b/libs/audio/Makefile.am index bdff7edea..5521b3e2f 100644 --- a/libs/audio/Makefile.am +++ b/libs/audio/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign SUBDIRS= targets renderer . test AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include SDL_LIBS= @SDL_LIBS@ XMMS_LIBS= @XMMS_LIBS@ plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) diff --git a/libs/audio/renderer/Makefile.am b/libs/audio/renderer/Makefile.am index e0c86a009..0c3bcd719 100644 --- a/libs/audio/renderer/Makefile.am +++ b/libs/audio/renderer/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ \ $(VORBIS_CFLAGS) $(OGG_CFLAGS) $(SAMPLERATE_CFLAGS) $(JACK_CFLAGS) -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) plugin_libadd= @plugin_libadd@ EXEEXT= diff --git a/libs/audio/targets/Makefile.am b/libs/audio/targets/Makefile.am index 7b42f69d5..ff0411354 100644 --- a/libs/audio/targets/Makefile.am +++ b/libs/audio/targets/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include SDL_LIBS = @SDL_LIBS@ plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) plugin_libadd= @plugin_libadd@ diff --git a/libs/audio/test/Makefile.am b/libs/audio/test/Makefile.am index ebee1ef13..410be4f4e 100644 --- a/libs/audio/test/Makefile.am +++ b/libs/audio/test/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS= foreign -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_PROGRAMS= @AUDIO_TARGETS@ diff --git a/libs/client/Makefile.am b/libs/client/Makefile.am index af91b0b3b..d9fc98a77 100644 --- a/libs/client/Makefile.am +++ b/libs/client/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= libQFclient.la diff --git a/libs/console/Makefile.am b/libs/console/Makefile.am index 8c9fb156f..d7cce92e7 100644 --- a/libs/console/Makefile.am +++ b/libs/console/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include $(FNM_FLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS) plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) plugin_libadd= @plugin_libadd@ lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ diff --git a/libs/gamecode/Makefile.am b/libs/gamecode/Makefile.am index 3222ff473..6d31504a8 100644 --- a/libs/gamecode/Makefile.am +++ b/libs/gamecode/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include lib_ldflags= gc_deps=$(top_builddir)/libs/util/libQFutil.la diff --git a/libs/gib/Makefile.am b/libs/gib/Makefile.am index b8f2a7c93..80ea92067 100644 --- a/libs/gib/Makefile.am +++ b/libs/gib/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include $(FNM_FLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS) lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ -rpath $(libdir) -no-undefined diff --git a/libs/models/Makefile.am b/libs/models/Makefile.am index 425679829..2fa145649 100644 --- a/libs/models/Makefile.am +++ b/libs/models/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign SUBDIRS= alias brush iqm sprite . test AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include lib_LTLIBRARIES= libQFmodels.la noinst_LTLIBRARIES= @models_libs@ diff --git a/libs/models/alias/Makefile.am b/libs/models/alias/Makefile.am index e79dbd9e6..e74edfeda 100644 --- a/libs/models/alias/Makefile.am +++ b/libs/models/alias/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= @alias_libs@ EXTRA_LTLIBRARIES=libalias_gl.la libalias_glsl.la libalias_sw.la diff --git a/libs/models/brush/Makefile.am b/libs/models/brush/Makefile.am index 01cc76439..cd728baed 100644 --- a/libs/models/brush/Makefile.am +++ b/libs/models/brush/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= libbrush.la @brush_libs@ EXTRA_LTLIBRARIES=libbrush_gl.la libbrush_glsl.la libbrush_sw.la diff --git a/libs/models/iqm/Makefile.am b/libs/models/iqm/Makefile.am index 0603bdbbe..71f54f576 100644 --- a/libs/models/iqm/Makefile.am +++ b/libs/models/iqm/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= @iqm_libs@ EXTRA_LTLIBRARIES=libiqm_gl.la libiqm_glsl.la libiqm_sw.la diff --git a/libs/models/sprite/Makefile.am b/libs/models/sprite/Makefile.am index a4aa70858..3c6c023d1 100644 --- a/libs/models/sprite/Makefile.am +++ b/libs/models/sprite/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= @sprite_libs@ EXTRA_LTLIBRARIES=libsprite_gl.la libsprite_glsl.la libsprite_sw.la diff --git a/libs/models/test/Makefile.am b/libs/models/test/Makefile.am index 6c9f65c75..2718f5ddd 100644 --- a/libs/models/test/Makefile.am +++ b/libs/models/test/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS= foreign -INCLUDES= -I$(srcdir) -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(srcdir) -I$(top_srcdir)/include check_PROGRAMS=testclip testcontents testportals EXTRA_DIST= trace-id.c trace-qf-bad.c hulls.h main.c diff --git a/libs/net/Makefile.am b/libs/net/Makefile.am index 6d5e13fa9..69f2fbb6c 100644 --- a/libs/net/Makefile.am +++ b/libs/net/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign SUBDIRS= nc nm AM_CFLAGS= @PREFER_NON_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= libnet_chan.la libnet_main.la diff --git a/libs/net/nc/Makefile.am b/libs/net/nc/Makefile.am index 27a900987..08b0cb810 100644 --- a/libs/net/nc/Makefile.am +++ b/libs/net/nc/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_NON_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= libnc.la diff --git a/libs/net/nm/Makefile.am b/libs/net/nm/Makefile.am index ba7771470..cfdaae275 100644 --- a/libs/net/nm/Makefile.am +++ b/libs/net/nm/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_NON_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= libnm.la diff --git a/libs/qw/Makefile.am b/libs/qw/Makefile.am index 5af85f1a0..48a58fa72 100644 --- a/libs/qw/Makefile.am +++ b/libs/qw/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS= foreign -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LIBRARIES= libqw.a diff --git a/libs/ruamoko/Makefile.am b/libs/ruamoko/Makefile.am index 4a255a4c7..64c65e972 100644 --- a/libs/ruamoko/Makefile.am +++ b/libs/ruamoko/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include $(FNM_FLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS) lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ -rpath $(libdir) -no-undefined diff --git a/libs/util/Makefile.am b/libs/util/Makefile.am index 0a8ed680f..a54935e16 100644 --- a/libs/util/Makefile.am +++ b/libs/util/Makefile.am @@ -4,7 +4,7 @@ SUBDIRS= . test AM_CFLAGS= @PREFER_PIC@ CCASFLAGS+= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include $(Z_CFLAGS) $(FNM_FLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(Z_CFLAGS) $(FNM_FLAGS) lib_LTLIBRARIES= libQFutil.la diff --git a/libs/util/test/Makefile.am b/libs/util/test/Makefile.am index 17b64d3a7..b9b3b8f9a 100644 --- a/libs/util/test/Makefile.am +++ b/libs/util/test/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS= foreign -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include check_PROGRAMS= \ test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \ diff --git a/libs/video/renderer/Makefile.am b/libs/video/renderer/Makefile.am index aee55cfe9..2c234fe33 100644 --- a/libs/video/renderer/Makefile.am +++ b/libs/video/renderer/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign SUBDIRS= @vid_render_dirs@ DIST_SUBDIRS= gl glsl sw sw32 -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ -rpath $(libdir) -no-undefined diff --git a/libs/video/renderer/gl/Makefile.am b/libs/video/renderer/gl/Makefile.am index 087fa0e8e..041db8546 100644 --- a/libs/video/renderer/gl/Makefile.am +++ b/libs/video/renderer/gl/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include $(GLX_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) noinst_LTLIBRARIES= libgl.la diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 097e847a9..c85b7a6fe 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include $(GLX_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) shader_src= \ iqm.frag iqm.vert \ diff --git a/libs/video/renderer/sw/Makefile.am b/libs/video/renderer/sw/Makefile.am index 697315e25..62f64e689 100644 --- a/libs/video/renderer/sw/Makefile.am +++ b/libs/video/renderer/sw/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ CCASFLAGS+= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include asm = @swrend_libs@ diff --git a/libs/video/renderer/sw32/Makefile.am b/libs/video/renderer/sw32/Makefile.am index 5fa5f7e03..5d078e90c 100644 --- a/libs/video/renderer/sw32/Makefile.am +++ b/libs/video/renderer/sw32/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include noinst_LTLIBRARIES= libsw32.la diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am index 98faa6099..b883b676b 100644 --- a/libs/video/targets/Makefile.am +++ b/libs/video/targets/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS= foreign -INCLUDES= -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/include lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ -rpath $(libdir) -no-undefined diff --git a/nq/source/Makefile.am b/nq/source/Makefile.am index 415c603c0..71cb290e8 100644 --- a/nq/source/Makefile.am +++ b/nq/source/Makefile.am @@ -30,7 +30,7 @@ AUTOMAKE_OPTIONS= foreign # Stuff that is common to both client and server # -INCLUDES= -I$(top_srcdir)/include -I$(top_srcdir)/nq/include +AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/nq/include SDL_LIBS = @SDL_LIBS@ AM_CFLAGS= @PTHREAD_CFLAGS@ diff --git a/qtv/source/Makefile.am b/qtv/source/Makefile.am index b403f70e9..fa73f8de8 100644 --- a/qtv/source/Makefile.am +++ b/qtv/source/Makefile.am @@ -29,7 +29,7 @@ AUTOMAKE_OPTIONS= foreign -INCLUDES= -I$(top_srcdir)/include -I$(top_srcdir)/qtv/include +AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/qtv/include bin_PROGRAMS= @QTV_TARGETS@ diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am index 202f2a70d..9afe77ae1 100644 --- a/qw/source/Makefile.am +++ b/qw/source/Makefile.am @@ -30,7 +30,7 @@ AUTOMAKE_OPTIONS= foreign # Stuff that is common to both client and server -INCLUDES= -I$(top_srcdir)/include -I$(top_srcdir)/qw/include @LIBCURL_CFLAGS@ +AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/qw/include @LIBCURL_CFLAGS@ SDL_LIBS = @SDL_LIBS@ AM_CFLAGS= @PTHREAD_CFLAGS@ diff --git a/ruamoko/gui/Makefile.am b/ruamoko/gui/Makefile.am index 611819151..e4866e856 100644 --- a/ruamoko/gui/Makefile.am +++ b/ruamoko/gui/Makefile.am @@ -4,11 +4,11 @@ pkglibdir=$(datarootdir)/qfcc/lib QFCC=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide --no-default-paths -QCPPFLAGS=$(INCLUDES) +QCPPFLAGS=$(AM_CPPFLAGS) PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) RANLIB=touch -INCLUDES= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include gui_libs=libgui.a libs=$(gui_libs) diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index 112941dc4..53a20875b 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -4,11 +4,11 @@ pkglibdir=$(datarootdir)/qfcc/lib QFCC=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QCFLAGS=-qq -O -g -Wall -Wno-integer-divide -Werror --no-default-paths -QCPPFLAGS=$(INCLUDES) +QCPPFLAGS=$(AM_CPPFLAGS) PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) RANLIB=touch -INCLUDES= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include noinst_HEADERS= \ Array+Private.h diff --git a/ruamoko/scheme/Makefile.am b/ruamoko/scheme/Makefile.am index 0e9365d5c..75f784ef5 100644 --- a/ruamoko/scheme/Makefile.am +++ b/ruamoko/scheme/Makefile.am @@ -5,7 +5,7 @@ pkglibdir=$(datarootdir)/qfcc/lib QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(QFCC_DEP) QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide --no-default-paths -QCPPFLAGS=$(INCLUDES) +QCPPFLAGS=$(AM_CPPFLAGS) PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi GZ=@progs_gz@ @@ -15,7 +15,7 @@ STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` RANLIB=touch -INCLUDES= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +AM_CPPFLAGS= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include scheme_libs=libscheme.a libs=$(scheme_libs) diff --git a/tools/bsp2img/Makefile.am b/tools/bsp2img/Makefile.am index cef3784cf..ceaeca266 100644 --- a/tools/bsp2img/Makefile.am +++ b/tools/bsp2img/Makefile.am @@ -2,7 +2,7 @@ BSP2IMG_LIBS=@BSP2IMG_LIBS@ BSP2IMG_DEPS=@BSP2IMG_DEPS@ BSP2IMG_INCS=@BSP2IMG_INCS@ -INCLUDES= -I$(top_srcdir)/include $(BSP2IMG_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(BSP2IMG_INCS) bin_PROGRAMS=bsp2img diff --git a/tools/carne/Makefile.am b/tools/carne/Makefile.am index 6a966cbbc..bec57857d 100644 --- a/tools/carne/Makefile.am +++ b/tools/carne/Makefile.am @@ -4,7 +4,7 @@ CARNE_LIBS=@CARNE_LIBS@ CARNE_DEPS=@CARNE_DEPS@ PAK_INCS=@CARNE_INCS@ -INCLUDES= -I$(top_srcdir)/include $(CARNE_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(CARNE_INCS) noinst_PROGRAMS= carne diff --git a/tools/pak/Makefile.am b/tools/pak/Makefile.am index 95559f892..5461c399e 100644 --- a/tools/pak/Makefile.am +++ b/tools/pak/Makefile.am @@ -4,7 +4,7 @@ PAK_LIBS=@PAK_LIBS@ PAK_DEPS=@PAK_DEPS@ PAK_INCS=@PAK_INCS@ -INCLUDES= -I$(top_srcdir)/include $(PAK_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(PAK_INCS) bin_PROGRAMS= pak bin_SCRIPTS= zpak diff --git a/tools/qfbsp/source/Makefile.am b/tools/qfbsp/source/Makefile.am index dffb426ab..8fd7f660b 100644 --- a/tools/qfbsp/source/Makefile.am +++ b/tools/qfbsp/source/Makefile.am @@ -4,7 +4,7 @@ QFBSP_LIBS=@QFBSP_LIBS@ QFBSP_DEPS=@QFBSP_DEPS@ QFBSP_INCS=@QFBSP_INCS@ -INCLUDES= -I$(top_srcdir)/include $(QFBSP_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFBSP_INCS) bin_PROGRAMS= qfbsp diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index b5674b614..58011ea08 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -32,7 +32,7 @@ QFCC_LIBS=@QFCC_LIBS@ QFCC_DEPS=@QFCC_DEPS@ QFCC_INCS=@QFCC_INCS@ -INCLUDES= -I$(top_srcdir)/include $(QFCC_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFCC_INCS) YFLAGS = -v -d bin_PROGRAMS= qfcc qfprogs diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 1ca89205a..d447671a9 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -1,5 +1,5 @@ AUTOMAKE_OPTIONS= foreign -INCLUDES= -I$(top_srcdir)/include $(QFCC_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFCC_INCS) QFCC_DEP=$(builddir)/../source/qfcc$(EXEEXT) QFCC=$(QFCC_DEP) diff --git a/tools/qflight/source/Makefile.am b/tools/qflight/source/Makefile.am index 063521a8f..cdf5005fb 100644 --- a/tools/qflight/source/Makefile.am +++ b/tools/qflight/source/Makefile.am @@ -6,7 +6,7 @@ QFLIGHT_INCS=@QFLIGHT_INCS@ PTHREAD_LDFLAGS=@PTHREAD_LDFLAGS@ PTHREAD_CFLAGS=@PTHREAD_CFLAGS@ -INCLUDES= -I$(top_srcdir)/include $(QFLIGHT_INCS) $(PTHREAD_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFLIGHT_INCS) $(PTHREAD_CFLAGS) bin_PROGRAMS= qflight diff --git a/tools/qflmp/Makefile.am b/tools/qflmp/Makefile.am index e3c6fe5fd..b9436172c 100644 --- a/tools/qflmp/Makefile.am +++ b/tools/qflmp/Makefile.am @@ -4,7 +4,7 @@ QFLMP_LIBS=@QFLMP_LIBS@ QFLMP_DEPS=@QFLMP_DEPS@ QFLMP_INCS=@QFLMP_INCS@ -INCLUDES= -I$(top_srcdir)/include $(QFLMP_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFLMP_INCS) bin_PROGRAMS= qflmp diff --git a/tools/qfmodelgen/source/Makefile.am b/tools/qfmodelgen/source/Makefile.am index 6e95a7a3e..4bc3a0bda 100644 --- a/tools/qfmodelgen/source/Makefile.am +++ b/tools/qfmodelgen/source/Makefile.am @@ -4,7 +4,7 @@ QFMODELGEN_LIBS=@QFMODELGEN_LIBS@ QFMODELGEN_DEPS=@QFMODELGEN_DEPS@ QFMODELGEN_INCS=@QFMODELGEN_INCS@ -INCLUDES= -I$(top_srcdir)/include $(QFMODELGEN_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFMODELGEN_INCS) bin_PROGRAMS= qfmodelgen diff --git a/tools/qfspritegen/Makefile.am b/tools/qfspritegen/Makefile.am index 7f3735ee4..05f321022 100644 --- a/tools/qfspritegen/Makefile.am +++ b/tools/qfspritegen/Makefile.am @@ -4,7 +4,7 @@ QFSPRITEGEN_LIBS=@QFSPRITEGEN_LIBS@ QFSPRITEGEN_DEPS=@QFSPRITEGEN_DEPS@ QFSPRITEGEN_INCS=@QFSPRITEGEN_INCS@ -INCLUDES= -I$(top_srcdir)/include $(QFSPRITEGEN_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFSPRITEGEN_INCS) bin_PROGRAMS= qfspritegen diff --git a/tools/qfvis/source/Makefile.am b/tools/qfvis/source/Makefile.am index 1ddcf6404..e0a725ca0 100644 --- a/tools/qfvis/source/Makefile.am +++ b/tools/qfvis/source/Makefile.am @@ -6,7 +6,7 @@ QFVIS_INCS=@QFVIS_INCS@ PTHREAD_LDFLAGS=@PTHREAD_LDFLAGS@ PTHREAD_CFLAGS=@PTHREAD_CFLAGS@ -INCLUDES= -I$(top_srcdir)/include $(QFVIS_INCS) $(PTHREAD_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QFVIS_INCS) $(PTHREAD_CFLAGS) bin_PROGRAMS= qfvis diff --git a/tools/qwaq/Makefile.am b/tools/qwaq/Makefile.am index e80524ddc..dd34fd9c5 100644 --- a/tools/qwaq/Makefile.am +++ b/tools/qwaq/Makefile.am @@ -2,7 +2,7 @@ QWAQ_LIBS=@QWAQ_LIBS@ QWAQ_DEPS=@QWAQ_DEPS@ QWAQ_INCS=@QWAQ_INCS@ -INCLUDES= -I$(top_srcdir)/include $(QWAQ_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QWAQ_INCS) QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(top_builddir)/tools/qfcc/source/qfcc diff --git a/tools/wad/Makefile.am b/tools/wad/Makefile.am index a47a10047..7db82d273 100644 --- a/tools/wad/Makefile.am +++ b/tools/wad/Makefile.am @@ -4,7 +4,7 @@ WAD_LIBS=@WAD_LIBS@ WAD_DEPS=@WAD_DEPS@ WAD_INCS=@WAD_INCS@ -INCLUDES= -I$(top_srcdir)/include $(WAD_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(WAD_INCS) bin_PROGRAMS= wad diff --git a/tools/wav/Makefile.am b/tools/wav/Makefile.am index 555ae0fbb..7e17fe376 100644 --- a/tools/wav/Makefile.am +++ b/tools/wav/Makefile.am @@ -4,7 +4,7 @@ WAV_LIBS=@WAV_LIBS@ WAV_DEPS=@WAV_DEPS@ WAV_INCS=@WAV_INCS@ -INCLUDES= -I$(top_srcdir)/include $(WAV_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(WAV_INCS) bin_PROGRAMS= qfwavinfo From 6c0f2717839a1702a8a605243725b502a7929ba2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Nov 2013 13:26:12 +0900 Subject: [PATCH 0034/1519] Fix some more automake warnings. --- tools/qfcc/test/Makefile.am | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index d447671a9..c4302f32f 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -50,112 +50,112 @@ test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS) chewed_alias_dat_SOURCES=chewed-alias.r chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) -chewed-alias.dat: $(chewed_alias_obj) $(QFCC_DEP) +chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) chewed-alias.run: Makefile build-run $(srcdir)/build-run $@ chewed_return_dat_SOURCES=chewed-return.r chewed_return_obj=$(chewed_return_dat_SOURCES:.r=.qfo) -chewed-return.dat: $(chewed_return_obj) $(QFCC_DEP) +chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) chewed-return.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ func_expr_dat_SOURCES=func-expr.r func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) -func-expr.dat: $(func_expr_obj) $(QFCC_DEP) +func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) func-expr.run: Makefile build-run $(srcdir)/build-run $@ func_static_dat_SOURCES=func-static.r func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) -func-static.dat: $(func_static_obj) $(QFCC_DEP) +func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) func-static.run: Makefile build-run $(srcdir)/build-run $@ deadbool_dat_SOURCES=deadbool.r deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) -deadbool.dat: $(deadbool_obj) $(QFCC_DEP) +deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) deadbool.run: Makefile build-run $(srcdir)/build-run $@ infloop_dat_SOURCES=infloop.r infloop_obj=$(infloop_dat_SOURCES:.r=.qfo) -infloop.dat: $(infloop_obj) $(QFCC_DEP) +infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) infloop.run: Makefile build-run $(srcdir)/build-run $@ modulo_dat_SOURCES=modulo.r modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) -modulo.dat: $(modulo_obj) $(QFCC_DEP) +modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) modulo.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ paramret_dat_SOURCES=paramret.r paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) -paramret.dat: $(paramret_obj) $(QFCC_DEP) +paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) paramret.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ return_ivar_dat_SOURCES=return-ivar.r return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) -return-ivar.dat: $(return_ivar_obj) $(QFCC_DEP) +return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) return-ivar.run: Makefile build-run $(srcdir)/build-run $@ sendv_dat_SOURCES=sendv.r sendv_obj=$(sendv_dat_SOURCES:.r=.qfo) -sendv.dat: $(sendv_obj) $(QFCC_DEP) +sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) sendv.run: Makefile build-run $(srcdir)/build-run $@ state_dat_SOURCES=state.r state_obj=$(state_dat_SOURCES:.r=.qfo) -state.dat: $(state_obj) $(QFCC_DEP) +state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(state_obj) state.run: Makefile build-run $(srcdir)/build-run $@ structlive_dat_SOURCES=structlive.r structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) -structlive.dat: $(structlive_obj) $(QFCC_DEP) +structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) structlive.run: Makefile build-run $(srcdir)/build-run $@ structptr_dat_SOURCES=structptr.r structptr_obj=$(structptr_dat_SOURCES:.r=.qfo) -structptr.dat: $(structptr_obj) $(QFCC_DEP) +structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) structptr.run: Makefile build-run $(srcdir)/build-run $@ vecinit_dat_SOURCES=vecinit.r vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) -vecinit.dat: $(vecinit_obj) $(QFCC_DEP) +vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) vecinit.run: Makefile build-run $(srcdir)/build-run $@ while_dat_SOURCES=while.r while_obj=$(while_dat_SOURCES:.r=.qfo) -while.dat: $(while_obj) $(QFCC_DEP) +while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(while_obj) while.run: Makefile build-run $(srcdir)/build-run $@ voidfor_dat_SOURCES=voidfor.r voidfor_obj=$(voidfor_dat_SOURCES:.r=.qfo) -voidfor.dat: $(voidfor_obj) $(QFCC_DEP) +voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) voidfor.run: Makefile build-run $(srcdir)/build-run $@ From 4c6478c77f4fa334889aad46fca08f90de1602e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Nov 2013 14:27:49 +0900 Subject: [PATCH 0035/1519] Strip trailing spaces from field names. A certain mod (glare at rogue) has a space at the end of a field name in the bsp entity data causing a crash. Thanks to ccr for the report. --- libs/gamecode/pr_parse.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 758e2c4cc..a8259ee78 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -305,7 +305,7 @@ ED_ConvertToPlist (script_t *script, int nohack) plitem_t *ent; plitem_t *key; plitem_t *value; - const char *token; + char *token; int anglehack; while (Script_GetToken (script, 1)) { @@ -314,11 +314,18 @@ ED_ConvertToPlist (script_t *script, int nohack) Sys_Error ("ED_ConvertToPlist: EOF without closing brace"); ent = PL_NewDictionary (); while (1) { + int n; + if (!Script_GetToken (script, 1)) Sys_Error ("ED_ConvertToPlist: EOF without closing brace"); token = script->token->str; if (strequal (token, "}")) break; + // hack to take care of trailing spaces in field names + // (looking at you, Rogue) + for (n = strlen (token); n && token[n - 1] == ' '; n--) { + token[n - 1] = 0; + } anglehack = 0; if (!nohack && strequal (token, "angle")) { key = PL_NewString ("angles"); From 7de0317a22c76808f57ed55b6ae3b6108d03af8d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Nov 2013 16:08:30 +0900 Subject: [PATCH 0036/1519] Avoid a segfault at the end of hipnotic. This is based on ccr's patch, but a little more thorough (he missed some potential problems) and probably more readable (the original code wasn't the greatest (still isn't, but...)).. --- nq/source/cl_ents.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 87f25f1ed..b6bac93cd 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -294,6 +294,7 @@ CL_RelinkEntities (void) int i, j; int entvalid; vec3_t delta; + int model_flags; r_data->player_entity = &cl_entities[cl.viewentity]; @@ -365,13 +366,16 @@ CL_RelinkEntities (void) VectorCopy (ent_colormod[new->colormod], ent->colormod); ent->colormod[3] = ENTALPHA_DECODE (new->alpha); + model_flags = 0; + if (ent->model) + model_flags = ent->model->flags; if (cl_forcelink[i]) { // The entity was not updated in the last message so move to the // final spot ent->pose1 = ent->pose2 = -1; VectorCopy (new->origin, ent->origin); - if (!(ent->model->flags & EF_ROTATE)) + if (!(model_flags & EF_ROTATE)) CL_TransformEntity (ent, new->angles, true); if (i != cl.viewentity || chase_active->int_val) { if (ent->efrag) @@ -388,14 +392,14 @@ CL_RelinkEntities (void) || fabs (delta[2]) > 100) { // assume a teleportation, not a motion VectorCopy (new->origin, ent->origin); - if (!(ent->model->flags & EF_ROTATE)) + if (!(model_flags & EF_ROTATE)) CL_TransformEntity (ent, new->angles, true); ent->pose1 = ent->pose2 = -1; } else { vec3_t angles, d; // interpolate the origin and angles VectorMultAdd (old->origin, f, delta, ent->origin); - if (!(ent->model->flags & EF_ROTATE)) { + if (!(model_flags & EF_ROTATE)) { VectorSubtract (new->angles, old->angles, d); for (j = 0; j < 3; j++) { if (d[j] > 180) @@ -420,7 +424,7 @@ CL_RelinkEntities (void) } // rotate binary objects locally - if (ent->model->flags & EF_ROTATE) { + if (model_flags & EF_ROTATE) { vec3_t angles; VectorCopy (new->angles, angles); angles[YAW] = bobjrotate; @@ -431,7 +435,7 @@ CL_RelinkEntities (void) new->glow_color); if (VectorDistance_fast (old->origin, ent->origin) > (256 * 256)) VectorCopy (ent->origin, old->origin); - if (ent->model->flags & ~EF_ROTATE) + if (model_flags & ~EF_ROTATE) CL_ModelEffects (ent, i, new->glow_color); cl_forcelink[i] = false; From b133e9a092469eaeaf3c294d9c53cc02edb37529 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jan 2014 15:47:29 +0900 Subject: [PATCH 0037/1519] Remove a stray -e from bootstrap's error report. Not sure it was there, unless I had intended -n. --- bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap b/bootstrap index 7e7aa4789..4986a6ca4 100755 --- a/bootstrap +++ b/bootstrap @@ -100,7 +100,7 @@ else fi if test -n "$errors" ; then - echo -e $errors + echo "$errors" exit 1 fi From d912970cd340631138695e8fe4b584814e99b73d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Feb 2013 18:55:37 +0900 Subject: [PATCH 0038/1519] Add support for segmented text files. The idea comes from The OpenGL Shader Wrangler (http://prideout.net/blog/?p=11). Text files are broken up into chunks via lines beginning with -- (^-- in regex). The chunks are optionally named with tags of the form: [0-9A-Za-z._]+. Unnamed chunks cannot be found. Searching for chunks looks for the longest tag that matches the beginning of the search tag (eg, a chunk named "Vertex" will be found with a search tag of "Vertex.foo"). Note that '.' forms the units for the searc ("Vertex.foo" will not find "Vertex.f"). Unlike glsw, this implementation does not have the concept of effects keys as that will be separate. Also, this implementation takes strings rather than file names (thus is more generally useful). --- include/QF/Makefile.am | 4 +- include/QF/segtext.h | 58 ++++++++++ libs/util/Makefile.am | 4 +- libs/util/segtext.c | 214 +++++++++++++++++++++++++++++++++++++ libs/util/test/Makefile.am | 6 +- libs/util/test/test-seg.c | 65 +++++++++++ 6 files changed, 346 insertions(+), 5 deletions(-) create mode 100644 include/QF/segtext.h create mode 100644 libs/util/segtext.c create mode 100644 libs/util/test/test-seg.c diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index 1283043da..ffb0ff56b 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -7,8 +7,8 @@ nobase_pkginclude_HEADERS = \ link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \ msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \ pr_obj.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h quakefs.h \ - quakeio.h render.h riff.h ruamoko.h set.h screen.h script.h sizebuf.h \ - skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.h \ + quakeio.h render.h riff.h ruamoko.h screen.h script.h segtext.h set.h \ + sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.h \ ver_check.h vid.h vrect.h view.h wad.h wadfile.h winding.h zone.h \ \ GL/ati.h GL/defines.h GL/extensions.h GL/funcs.h GL/qf_draw.h \ diff --git a/include/QF/segtext.h b/include/QF/segtext.h new file mode 100644 index 000000000..1c781fcb9 --- /dev/null +++ b/include/QF/segtext.h @@ -0,0 +1,58 @@ +/* + segtext.h + + Segmented text file handling + + Copyright (C) 2013 Bill Currie + + Author: Bill Currie + Date: 2013/02/26 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_segtext_h +#define __QF_segtext_h + +/** \defgroup segtext Segmented text files. + \ingroup utils + + Based on The OpenGL Shader Wrangler: http://prideout.net/blog/?p=11 +*/ + +typedef struct segchunk_s { + struct segchunk_s *next; + const char *tag; + const char *text; + int start_line; +} segchunk_t; + +typedef struct segtext_s { + struct segtext_s *next; + segchunk_t *chunk_list; + struct hashtab_s *tab; +} segtext_t; + +segtext_t *Segtext_new (const char *src); +void Segtext_delete (segtext_t *st); +const segchunk_t *Segtext_FindChunk (const segtext_t *st, const char *tag); +const char *Segtext_Find (const segtext_t *st, const char *tag); + +#endif//__QF_segtext_h diff --git a/libs/util/Makefile.am b/libs/util/Makefile.am index a54935e16..0c6421450 100644 --- a/libs/util/Makefile.am +++ b/libs/util/Makefile.am @@ -52,8 +52,8 @@ libQFutil_la_SOURCES= \ bspfile.c buildnum.c cbuf.c checksum.c cmd.c crc.c cvar.c dstring.c \ fendian.c hash.c idparse.c info.c link.c llist.c \ mathlib.c mdfour.c mersenne.c msg.c pakfile.c plugin.c qargs.c qendian.c \ - qfplist.c quakefs.c quakeio.c riff.c script.c set.c sizebuf.c string.c \ - sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \ + qfplist.c quakefs.c quakeio.c riff.c script.c segtext.c set.c sizebuf.c \ + string.c sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \ $(dirent) $(fnmatch) $(getopt) EXTRA_DIST= $(fnmatch_src) $(getopt_src) diff --git a/libs/util/segtext.c b/libs/util/segtext.c new file mode 100644 index 000000000..01268a9f0 --- /dev/null +++ b/libs/util/segtext.c @@ -0,0 +1,214 @@ +/* + segtext.c + + Segmented text file handling + + Copyright (C) 2013 Bill Currie + + Author: Bill Currie + Date: 2013/02/26 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/alloc.h" +#include "QF/hash.h" +#include "QF/qtypes.h" +#include "QF/segtext.h" + +static segchunk_t *free_chunks; +static segtext_t *free_texts; + +static segchunk_t * +new_chunk (void) +{ + segchunk_t *chunk; + ALLOC (64, segchunk_t, chunks, chunk); + return chunk; +} + +static void +delete_chunk (segchunk_t *chunk) +{ + FREE (chunks, chunk); +} + +static segtext_t * +new_text (void) +{ + segtext_t *text; + ALLOC (64, segtext_t, texts, text); + return text; +} + +static void +delete_text (segtext_t *text) +{ + FREE (texts, text); +} + +static const char * +segtext_getkey (const void *sc, void *unused) +{ + segchunk_t *chunk = (segchunk_t *) sc; + if (!chunk->tag) + return ""; + return chunk->tag; +} + +static char * +next_line (char *src, int *line) +{ + while (*src && *src != '\n') + src++; + if (*src == '\n') { + *line += 1; + src++; + } + return src; +} + +static char * +next_chunk (char *src, int *line) +{ + while (*src) { + // chunks begin on a line that starts with -- + if (src[0] == '-' && src[1] == '-') + return src; + src = next_line (src, line); + } + // no next chunk + return 0; +} + +static int +is_tag_char (char ch) +{ + return isalnum ((byte) ch) || ch == '.' || ch == '_'; +} + +static char * +find_tag (const char *src) +{ + const char *end; + char *tag; + + while (*src && *src != '\n' && !is_tag_char (*src)) + src++; + + for (end = src; is_tag_char (*end); end++) + ; + if (end == src) + return 0; + + tag = malloc (end - src + 1); + strncpy (tag, src, end - src); + tag[end - src] = 0; + return tag; +} + +VISIBLE segtext_t * +Segtext_new (const char *source_string) +{ + segchunk_t **chunk; + segtext_t *text; + char *src; + int line = 1; + + if (!source_string) + return 0; + text = new_text (); + text->tab = Hash_NewTable (61, segtext_getkey, 0, 0); + + src = strdup (source_string); + // The first chunk is special in that it holds the pointer to the copied + // string data. The chunk itself has no name and may be empty. + chunk = &text->chunk_list; + *chunk = new_chunk (); + (*chunk)->tag = 0; + (*chunk)->text = src; + (*chunk)->start_line = line; + + chunk = &(*chunk)->next; + + while ((src = next_chunk (src, &line))) { + *src++ = 0; // terminate the previous chunk + *chunk = new_chunk (); + (*chunk)->tag = find_tag (src); + (*chunk)->text = next_line (src, &line); + (*chunk)->start_line = line; + // If tags are duplicated, the first one takes precedence + if ((*chunk)->tag && !Hash_Find (text->tab, (*chunk)->tag)) + Hash_Add (text->tab, *chunk); + } + return text; +} + +VISIBLE void +Segtext_delete (segtext_t *st) +{ + segchunk_t *chunk; + + // the first chunk holds the pointer to the block holding all chunk data; + free ((char *) st->chunk_list->text); + while (st->chunk_list) { + chunk = st->chunk_list; + st->chunk_list = chunk->next; + if (chunk->tag) + free ((char *) chunk->tag); + delete_chunk (chunk); + } + Hash_DelTable (st->tab); + delete_text (st); +} + +const segchunk_t * +Segtext_FindChunk (const segtext_t *st, const char *tag) +{ + char *sub; + char *dot; + segchunk_t *chunk; + + sub = alloca (strlen (tag) + 1); + strcpy (sub, tag); + do { + chunk = Hash_Find (st->tab, sub); + if (chunk) + return chunk; + dot = strrchr (sub, '.'); + if (dot) + *dot = 0; + } while (dot); + return 0; +} + +const char * +Segtext_Find (const segtext_t *st, const char *tag) +{ + const segchunk_t *chunk = Segtext_FindChunk (st, tag); + if (chunk) + return chunk->text; + return 0; +} diff --git a/libs/util/test/Makefile.am b/libs/util/test/Makefile.am index b9b3b8f9a..a7bdb5d4e 100644 --- a/libs/util/test/Makefile.am +++ b/libs/util/test/Makefile.am @@ -4,7 +4,7 @@ AM_CPPFLAGS= -I$(top_srcdir)/include check_PROGRAMS= \ test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \ - test-qfs test-quat test-seb test-set test-vrect + test-qfs test-quat test-seb test-seg test-set test-vrect test_bary_SOURCES=test-bary.c test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la @@ -46,6 +46,10 @@ test_seb_SOURCES=test-seb.c test_seb_LDADD=$(top_builddir)/libs/util/libQFutil.la test_seb_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la +test_seg_SOURCES=test-seg.c +test_seg_LDADD=$(top_builddir)/libs/util/libQFutil.la +test_seg_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la + test_set_SOURCES=test-set.c test_set_LDADD=$(top_builddir)/libs/util/libQFutil.la test_set_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la diff --git a/libs/util/test/test-seg.c b/libs/util/test/test-seg.c new file mode 100644 index 000000000..7c36cec17 --- /dev/null +++ b/libs/util/test/test-seg.c @@ -0,0 +1,65 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include + +#include "QF/segtext.h" + +static const char *test_string = + "blah\n" + "-- Vertex\n" + "FOO\n" + "-- Geometry\n" + "BAR\n" + "-- Fragment.Erosion\n" + "BAZ\n" + "-- Fragment.Grassfire\n" + "QUX\n" + "-- TessControl\n" + "QUUX\n" + "-- TessEvaluation\n" + "QUUUX"; + +struct { + const char *tag; + const char *expect; +} seg_tests[] = { + {"", 0}, // empty tags not findable + {"Vertex", "FOO\n"}, + {"Geometry", "BAR\n"}, + {"Fragment.Erosion", "BAZ\n"}, + {"Fragment.Grassfire", "QUX\n"}, + {"TessControl", "QUUX\n"}, + {"TessEvaluation", "QUUUX"}, // final chunk doesn't have \n + {"Vertex.Erosion", "FOO\n"}, + {"Geometry.Grasfire", "BAR\n"}, +}; +#define num_seg_tests (sizeof (seg_tests) / sizeof (seg_tests[0])) + +int +main (int argc, const char **argv) +{ + size_t i; + int res = 0; + segtext_t *st; + + st = Segtext_new (test_string); + for (i = 0; i < num_seg_tests; i++) { + const char *text = Segtext_Find (st, seg_tests[i].tag); + if ((!text != !seg_tests[i].expect) + && (!text || !seg_tests[i].expect + || strcmp (text, seg_tests[i].expect))) { + fprintf (stderr, "FAIL: (%zd) \"%s\" -> \"%s\", got \"%s\"\n", i, + seg_tests[i].tag, seg_tests[i].expect, text); + res = 1; + } + } + return res; +} From d1848a93c8e97d1a44cffe36a25b0d0160ea97fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Feb 2013 19:50:23 +0900 Subject: [PATCH 0039/1519] Add tests for chunk line numbers. Which happen to find errors :P --- libs/util/test/test-seg.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libs/util/test/test-seg.c b/libs/util/test/test-seg.c index 7c36cec17..d67001394 100644 --- a/libs/util/test/test-seg.c +++ b/libs/util/test/test-seg.c @@ -43,6 +43,19 @@ struct { }; #define num_seg_tests (sizeof (seg_tests) / sizeof (seg_tests[0])) +struct { + const char *tag; + int expect; +} line_tests[] = { + {"Vertex", 3}, + {"Geometry", 5}, + {"Fragment.Erosion", 7}, + {"Fragment.Grassfire", 9}, + {"TessControl", 11}, + {"TessEvaluation", 13}, // final chunk doesn't have \n +}; +#define num_line_tests (sizeof (line_tests) / sizeof (line_tests[0])) + int main (int argc, const char **argv) { @@ -61,5 +74,14 @@ main (int argc, const char **argv) res = 1; } } + for (i = 0; i < num_line_tests; i++) { + const segchunk_t *chunk = Segtext_FindChunk (st, line_tests[i].tag); + if (!chunk || chunk->start_line != line_tests[i].expect) { + fprintf (stderr, "FAIL: (%zd) \"%s\" -> %d, got %d\n", i, + line_tests[i].tag, line_tests[i].expect, + chunk->start_line); + res = 1; + } + } return res; } From 3b56f0e3bfb3555b58f85b9bc0830203357c14cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Feb 2013 19:51:26 +0900 Subject: [PATCH 0040/1519] Advance src with next_line. This fixes the double counting of the \n at the end of the chunk separator line. --- libs/util/segtext.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/util/segtext.c b/libs/util/segtext.c index 01268a9f0..9ae516b6f 100644 --- a/libs/util/segtext.c +++ b/libs/util/segtext.c @@ -157,7 +157,8 @@ Segtext_new (const char *source_string) *src++ = 0; // terminate the previous chunk *chunk = new_chunk (); (*chunk)->tag = find_tag (src); - (*chunk)->text = next_line (src, &line); + src = next_line (src, &line); + (*chunk)->text = src; (*chunk)->start_line = line; // If tags are duplicated, the first one takes precedence if ((*chunk)->tag && !Hash_Find (text->tab, (*chunk)->tag)) From 96c40cb9a1ac026985519100c5f8d3cc8273f3c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Feb 2013 21:52:35 +0900 Subject: [PATCH 0041/1519] Add basic support for shader "effects". Again, based on The OpenGL Shader Wrangler. The wrangling part is not used yet, but the shader compiler has been modified to take the built up shader. Just to keep things compiling, a wrapper has been temporarily created. --- include/QF/GLSL/qf_vid.h | 14 +- libs/video/renderer/glsl/Makefile.am | 4 +- libs/video/renderer/glsl/glsl_alias.c | 4 +- libs/video/renderer/glsl/glsl_bsp.c | 12 +- libs/video/renderer/glsl/glsl_draw.c | 4 +- libs/video/renderer/glsl/glsl_iqm.c | 4 +- libs/video/renderer/glsl/glsl_particles.c | 8 +- libs/video/renderer/glsl/glsl_shader.c | 161 +++++++++++++++++++++ libs/video/renderer/glsl/glsl_sprite.c | 4 +- libs/video/renderer/glsl/vid_common_glsl.c | 31 ++-- 10 files changed, 213 insertions(+), 33 deletions(-) create mode 100644 libs/video/renderer/glsl/glsl_shader.c diff --git a/include/QF/GLSL/qf_vid.h b/include/QF/GLSL/qf_vid.h index 8240db436..c08354037 100644 --- a/include/QF/GLSL/qf_vid.h +++ b/include/QF/GLSL/qf_vid.h @@ -30,6 +30,12 @@ #include "QF/qtypes.h" +typedef struct shader_s { + int num_strings; + const char **strings; + const char **src; +} shader_t; + typedef struct shaderparam_s { const char *name; qboolean uniform; @@ -40,9 +46,15 @@ extern int glsl_palette; extern int glsl_colormap; void GLSL_Init_Common (void); -int GLSL_CompileShader (const char *name, const char *shader_src, int type); + +int GLSL_CompileShader (const char *name, const shader_t *shader, int type); +int GLSL_CompileShaderS (const char *name, const char *src, int type); int GLSL_LinkProgram (const char *name, int vert, int frag); int GLSL_ResolveShaderParam (int program, shaderparam_t *param); void GLSL_DumpAttribArrays (void); +int GLSL_RegisterEffect (const char *name, const char *src); +shader_t *GLSL_BuildShader (const char **effect_keys); +void GLSL_FreeShader (shader_t *shader); + #endif // __QF_GLSL_vid_h diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index c85b7a6fe..1b8208769 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -17,8 +17,8 @@ shader_gen= \ glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ - glsl_main.c glsl_particles.c glsl_screen.c glsl_sprite.c glsl_textures.c \ - qfglsl.c vid_common_glsl.c + glsl_main.c glsl_particles.c glsl_screen.c glsl_shader.c glsl_sprite.c \ + glsl_textures.c qfglsl.c vid_common_glsl.c noinst_LTLIBRARIES= libglsl.la BUILT_SOURCES= $(shader_gen) diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index b8925ad0f..2a2a3560b 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -113,9 +113,9 @@ glsl_R_InitAlias (void) int vert; int frag; - vert = GLSL_CompileShader ("quakemdl.vert", quakemdl_vert, + vert = GLSL_CompileShaderS ("quakemdl.vert", quakemdl_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("quakemdl.frag", quakemdl_frag, + frag = GLSL_CompileShaderS ("quakemdl.frag", quakemdl_frag, GL_FRAGMENT_SHADER); quake_mdl.program = GLSL_LinkProgram ("quakemdl", vert, frag); GLSL_ResolveShaderParam (quake_mdl.program, &quake_mdl.mvp_matrix); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 13aad5a95..8de55a9bd 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1244,9 +1244,9 @@ glsl_R_InitBsp (void) int vert; int frag; - vert = GLSL_CompileShader ("quakebsp.vert", quakebsp_vert, + vert = GLSL_CompileShaderS ("quakebsp.vert", quakebsp_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("quakebsp.frag", quakebsp_frag, + frag = GLSL_CompileShaderS ("quakebsp.frag", quakebsp_frag, GL_FRAGMENT_SHADER); quake_bsp.program = GLSL_LinkProgram ("quakebsp", vert, frag); GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.mvp_matrix); @@ -1258,7 +1258,7 @@ glsl_R_InitBsp (void) GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.color); GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.fog); - frag = GLSL_CompileShader ("quaketrb.frag", quaketurb_frag, + frag = GLSL_CompileShaderS ("quaketrb.frag", quaketurb_frag, GL_FRAGMENT_SHADER); quake_turb.program = GLSL_LinkProgram ("quaketrb", vert, frag); GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.mvp_matrix); @@ -1270,9 +1270,9 @@ glsl_R_InitBsp (void) GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.color); GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.fog); - vert = GLSL_CompileShader ("quakesky.vert", quakesky_vert, + vert = GLSL_CompileShaderS ("quakesky.vert", quakesky_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("quakeski.frag", quakeskyid_frag, + frag = GLSL_CompileShaderS ("quakeski.frag", quakeskyid_frag, GL_FRAGMENT_SHADER); quake_skyid.program = GLSL_LinkProgram ("quakeskyid", vert, frag); GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.mvp_matrix); @@ -1284,7 +1284,7 @@ glsl_R_InitBsp (void) GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.realtime); GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.fog); - frag = GLSL_CompileShader ("quakeskb.frag", quakeskybox_frag, + frag = GLSL_CompileShaderS ("quakeskb.frag", quakeskybox_frag, GL_FRAGMENT_SHADER); quake_skybox.program = GLSL_LinkProgram ("quakeskybox", vert, frag); GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.mvp_matrix); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index e7209bd53..9be2635cc 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -381,9 +381,9 @@ glsl_Draw_Init (void) draw_queue = dstring_new (); - vert = GLSL_CompileShader ("quakeico.vert", quakeicon_vert, + vert = GLSL_CompileShaderS ("quakeico.vert", quakeicon_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("quake2d.frag", quake2d_frag, + frag = GLSL_CompileShaderS ("quake2d.frag", quake2d_frag, GL_FRAGMENT_SHADER); quake_2d.program = GLSL_LinkProgram ("quake2d", vert, frag); GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.texture); diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 17302d7aa..b8cae10bd 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -140,8 +140,8 @@ glsl_R_InitIQM (void) int frag; int i; - vert = GLSL_CompileShader ("iqm.vert", iqm_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("iqm.frag", iqm_frag, GL_FRAGMENT_SHADER); + vert = GLSL_CompileShaderS ("iqm.vert", iqm_vert, GL_VERTEX_SHADER); + frag = GLSL_CompileShaderS ("iqm.frag", iqm_frag, GL_FRAGMENT_SHADER); iqm_shader.program = GLSL_LinkProgram ("iqm", vert, frag); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.mvp_matrix); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.norm_matrix); diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 8d4819fec..4d870623f 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -223,9 +223,9 @@ glsl_R_InitParticles (void) qfeglGetFloatv (GL_ALIASED_POINT_SIZE_RANGE, v); Sys_MaskPrintf (SYS_GLSL, "point size: %g - %g\n", v[0], v[1]); - vert = GLSL_CompileShader ("quakepnt.vert", quakepoint_vert, + vert = GLSL_CompileShaderS ("quakepnt.vert", quakepoint_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("quakepnt.frag", quakepoint_frag, + frag = GLSL_CompileShaderS ("quakepnt.frag", quakepoint_frag, GL_FRAGMENT_SHADER); quake_point.program = GLSL_LinkProgram ("quakepoint", vert, frag); GLSL_ResolveShaderParam (quake_point.program, &quake_point.mvp_matrix); @@ -234,9 +234,9 @@ glsl_R_InitParticles (void) GLSL_ResolveShaderParam (quake_point.program, &quake_point.color); GLSL_ResolveShaderParam (quake_point.program, &quake_point.fog); - vert = GLSL_CompileShader ("quakepar.vert", quakepart_vert, + vert = GLSL_CompileShaderS ("quakepar.vert", quakepart_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("quakepar.frag", quakepart_frag, + frag = GLSL_CompileShaderS ("quakepar.frag", quakepart_frag, GL_FRAGMENT_SHADER); quake_part.program = GLSL_LinkProgram ("quakepart", vert, frag); GLSL_ResolveShaderParam (quake_part.program, &quake_part.mvp_matrix); diff --git a/libs/video/renderer/glsl/glsl_shader.c b/libs/video/renderer/glsl/glsl_shader.c new file mode 100644 index 000000000..4fb317b04 --- /dev/null +++ b/libs/video/renderer/glsl/glsl_shader.c @@ -0,0 +1,161 @@ +/* + glsl_shader.c + + Shader management based on The OpenGL Shader Wrangler + http://prideout.net/blog/?p=11 + + Copyright (C) 2013 Bill Currie + + Author: Bill Currie + Date: 2013/02/26 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/alloc.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/segtext.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "QF/GLSL/qf_vid.h" + +typedef struct glsl_effect_s { + struct glsl_effect_s *next; + const char *name; + segtext_t *text; +} glsl_effect_t; + +static hashtab_t *effect_tab; +static glsl_effect_t *free_effects; + +static glsl_effect_t * +new_effect (void) +{ + glsl_effect_t *effect; + ALLOC (64, glsl_effect_t, effects, effect); + return effect; +} + +static const char * +effect_get_key (const void *e, void *unused) +{ + glsl_effect_t *effect = (glsl_effect_t *) e; + return effect->name; +} + +int +GLSL_RegisterEffect (const char *name, const char *src) +{ + glsl_effect_t *effect; + segtext_t *text; + + if (!effect_tab) + effect_tab = Hash_NewTable (61, effect_get_key, 0, 0); + + if (Hash_Find (effect_tab, name)) { + Sys_Printf ("WARNING: ignoring duplicate '%s' effect\n", name); + return 0; + } + text = Segtext_new (src); + if (!text) { + Sys_Printf ("WARNING: %s: problem parsing effect source\n", name); + return 0; + } + effect = new_effect (); + effect->name = strdup (name); + effect->text = text; + Hash_Add (effect_tab, effect); + return 1; +} + +shader_t * +GLSL_BuildShader (const char **effect_keys) +{ + const char *dot; + const char **key; + int num_keys = 0; + shader_t *shader; + dstring_t *ekey; + glsl_effect_t *effect; + const segchunk_t *chunk; + + for (key = effect_keys; *key; key++) + num_keys++; + + shader = malloc (sizeof (shader_t)); + shader->num_strings = num_keys; + shader->strings = calloc (2, num_keys); + shader->src = shader->strings + num_keys; + + ekey = dstring_new (); + for (key = effect_keys; *key; key++) { + int num = key - effect_keys; + dot = strchr (*key, '.'); + if (!dot) { + Sys_Printf ("Invalid effect key: '%s'\n", *key); + goto error; + } + dstring_copysubstr (ekey, *key, dot - *key); + effect = Hash_Find (effect_tab, ekey->str); + if (!effect) { + Sys_Printf ("Unknown effect: '%s'\n", ekey->str); + goto error; + } + dot++; + chunk = Segtext_FindChunk (effect->text, dot); + if (!chunk) { + Sys_Printf ("Unknown shader key: '%s'\n", dot); + goto error; + } + shader->strings[num] = nva ("#line %d\n%s", chunk->start_line, + chunk->text); + shader->src[num] = strdup (ekey->str); + } + dstring_delete (ekey); + return shader; +error: + // there is guaranteed to be a null in the array if an error occurs. + for (key = shader->strings; *key; key++) { + free ((char *) *key); + free ((char *) shader->src[key - shader->strings]); + } + free (shader->strings); + free (shader); + dstring_delete (ekey); + return 0; +} + +void +GLSL_FreeShader (shader_t *shader) +{ + int i; + + for (i = 0; i < shader->num_strings; i++) { + free ((char *) shader->strings[i]); + free ((char *) shader->src[i]); + } + free (shader->strings); + free (shader); +} diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index a5b02b42a..ab96b137e 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -98,9 +98,9 @@ glsl_R_InitSprites (void) { int frag, vert; - vert = GLSL_CompileShader ("quakespr.vert", quakesprite_vert, + vert = GLSL_CompileShaderS ("quakespr.vert", quakesprite_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShader ("quakespr.frag", quakesprite_frag, + frag = GLSL_CompileShaderS ("quakespr.frag", quakesprite_frag, GL_FRAGMENT_SHADER); quake_sprite.program = GLSL_LinkProgram ("quakespr", vert, frag); GLSL_ResolveShaderParam (quake_sprite.program, &quake_sprite.spritea); diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 4c46a56d5..6664eb841 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -184,33 +184,40 @@ GLSL_Init_Common (void) } int -GLSL_CompileShader (const char *name, const char *shader_src, int type) +GLSL_CompileShader (const char *name, const shader_t *shader, int type) { - const char *src[1]; - int shader; + int sid; int compiled; - src[0] = shader_src; - shader = qfeglCreateShader (type); - qfeglShaderSource (shader, 1, src, 0); - qfeglCompileShader (shader); - qfeglGetShaderiv (shader, GL_COMPILE_STATUS, &compiled); + sid = qfeglCreateShader (type); + qfeglShaderSource (sid, shader->num_strings, shader->strings, 0); + qfeglCompileShader (sid); + qfeglGetShaderiv (sid, GL_COMPILE_STATUS, &compiled); if (!compiled || (developer->int_val & SYS_GLSL)) { dstring_t *log = dstring_new (); int size; - qfeglGetShaderiv (shader, GL_INFO_LOG_LENGTH, &size); + qfeglGetShaderiv (sid, GL_INFO_LOG_LENGTH, &size); log->size = size + 1; // for terminating null dstring_adjust (log); - qfeglGetShaderInfoLog (shader, log->size, 0, log->str); + qfeglGetShaderInfoLog (sid, log->size, 0, log->str); if (!compiled) - qfeglDeleteShader (shader); + qfeglDeleteShader (sid); Sys_Printf ("Shader (%s) compile log:\n----8<----\n%s----8<----\n", name, log->str); dstring_delete (log); if (!compiled) return 0; } - return shader; + return sid; +} + +int +GLSL_CompileShaderS (const char *name, const char *src, int type) +{ + const char *shader_src = src; + const char *shader_name = "wrapped"; + shader_t shader = {1, &shader_src, &shader_name}; + return GLSL_CompileShader (name, &shader, type); } static const char * From 550f1ae7889cb3137f08fff429c037e5683484bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 May 2013 13:11:26 +0900 Subject: [PATCH 0042/1519] Fix some bitrot. Just updating for the changes to the ALLOC/FREE macros. --- libs/util/segtext.c | 4 ++-- libs/video/renderer/glsl/glsl_shader.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/util/segtext.c b/libs/util/segtext.c index 9ae516b6f..742983be1 100644 --- a/libs/util/segtext.c +++ b/libs/util/segtext.c @@ -38,8 +38,8 @@ #include "QF/qtypes.h" #include "QF/segtext.h" -static segchunk_t *free_chunks; -static segtext_t *free_texts; +static segchunk_t *chunks_freelist; +static segtext_t *texts_freelist; static segchunk_t * new_chunk (void) diff --git a/libs/video/renderer/glsl/glsl_shader.c b/libs/video/renderer/glsl/glsl_shader.c index 4fb317b04..bc3a7c546 100644 --- a/libs/video/renderer/glsl/glsl_shader.c +++ b/libs/video/renderer/glsl/glsl_shader.c @@ -48,7 +48,7 @@ typedef struct glsl_effect_s { } glsl_effect_t; static hashtab_t *effect_tab; -static glsl_effect_t *free_effects; +static glsl_effect_t *effects_freelist; static glsl_effect_t * new_effect (void) From 323fbe192708242bebfce3980c263f791ea33837 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 May 2013 13:50:17 +0900 Subject: [PATCH 0043/1519] Fix an allocation oopsie. I must have been tired when I wrote that line. --- libs/video/renderer/glsl/glsl_shader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/glsl/glsl_shader.c b/libs/video/renderer/glsl/glsl_shader.c index bc3a7c546..d38bb2c29 100644 --- a/libs/video/renderer/glsl/glsl_shader.c +++ b/libs/video/renderer/glsl/glsl_shader.c @@ -106,7 +106,7 @@ GLSL_BuildShader (const char **effect_keys) shader = malloc (sizeof (shader_t)); shader->num_strings = num_keys; - shader->strings = calloc (2, num_keys); + shader->strings = calloc (2 * num_keys, sizeof (const char *)); shader->src = shader->strings + num_keys; ekey = dstring_new (); From 4bd82eb2b818676311d681f55d1cf9e8184187a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 May 2013 13:50:43 +0900 Subject: [PATCH 0044/1519] Add some documentation. Nowhere near adequate. --- include/QF/GLSL/qf_vid.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/QF/GLSL/qf_vid.h b/include/QF/GLSL/qf_vid.h index c08354037..1dd324f05 100644 --- a/include/QF/GLSL/qf_vid.h +++ b/include/QF/GLSL/qf_vid.h @@ -53,8 +53,36 @@ int GLSL_LinkProgram (const char *name, int vert, int frag); int GLSL_ResolveShaderParam (int program, shaderparam_t *param); void GLSL_DumpAttribArrays (void); +/* Register a shader effect "file". + + This is based on The OpenGL Shader Wrangler by the little grasshopper + (http://prideout.net/blog/?p=11). + + \param name The name of the effect in the effect key. + \param src The string holding the effect file. + \return 0 for failure, 1 for success. +*/ int GLSL_RegisterEffect (const char *name, const char *src); + +/* Build a shader program script from a list of effect keys. + + This is based on The OpenGL Shader Wrangler by the little grasshopper + (http://prideout.net/blog/?p=11). + + The returned shader program script is suitable for passing directly to + GLSL_CompileShader. + + \param effect_keys Null terminated list of effect keys. The shader will be + built from the specified segments in the given order. + \return A pointer to the built up shader program script, or null on + failure. +*/ shader_t *GLSL_BuildShader (const char **effect_keys); + +/* Free a shader program script built by GLSL_BuildShader. + + \param shader The shader program script to be freed. +*/ void GLSL_FreeShader (shader_t *shader); #endif // __QF_GLSL_vid_h From b269338947939cb8ad0f658a68acd92e53a0e648 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 May 2013 13:51:02 +0900 Subject: [PATCH 0045/1519] Start using the new shader system. So far, alias model rendering is the only victim, but things are working, even if only color map lookup and fog blending are broken out at this stage. I expect the effect naming scheme will go through some changes until I'm happy with it. --- libs/video/renderer/glsl/Makefile.am | 8 +- libs/video/renderer/glsl/glsl_alias.c | 25 ++-- libs/video/renderer/glsl/quakeforge.glsl | 152 +++++++++++++++++++++ libs/video/renderer/glsl/quakemdl.frag | 42 ------ libs/video/renderer/glsl/quakemdl.vert | 27 ---- libs/video/renderer/glsl/vid_common_glsl.c | 6 + 6 files changed, 180 insertions(+), 80 deletions(-) create mode 100644 libs/video/renderer/glsl/quakeforge.glsl delete mode 100644 libs/video/renderer/glsl/quakemdl.frag delete mode 100644 libs/video/renderer/glsl/quakemdl.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 1b8208769..dd65e2f0b 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -3,13 +3,13 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) -shader_src= \ +shader_src= quakeforge.glsl \ iqm.frag iqm.vert \ quake2d.frag quakebsp.frag quakebsp.vert quakeico.vert quakemdl.frag \ quakemdl.vert quakepar.frag quakepar.vert quakepnt.frag quakepnt.vert \ quakeskb.frag quakeski.frag quakesky.vert quakespr.frag quakespr.vert \ quaketrb.frag quaketxt.vert -shader_gen= \ +shader_gen= quakeforge.slc \ iqm.fc iqm.vc \ quake2d.fc quakebsp.fc quakebsp.vc quakeico.vc quakemdl.fc quakemdl.vc \ quakepar.fc quakepar.vc quakepnt.fc quakepnt.vc quakeskb.fc quakeski.fc \ @@ -23,7 +23,9 @@ glsl_src = \ noinst_LTLIBRARIES= libglsl.la BUILT_SOURCES= $(shader_gen) -SUFFICES=.frag .vert .fc .vc +SUFFICES=.frag .vert .fc .vc .slc .glsl +.glsl.slc: + sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ .frag.fc: sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ .vert.vc: diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 2a2a3560b..ddbec7b04 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -55,13 +55,17 @@ #include "r_internal.h" -static const char quakemdl_vert[] = -#include "quakemdl.vc" -; +static const char *alias_vert_effects[] = +{ + "QuakeForge.Vertex.mdl", +}; -static const char quakemdl_frag[] = -#include "quakemdl.fc" -; +static const char *alias_frag_effects[] = +{ + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.colormap", + "QuakeForge.Fragment.mdl", +}; static struct { int program; @@ -110,12 +114,15 @@ static mat4_t alias_vp; void glsl_R_InitAlias (void) { + shader_t *vert_shader, *frag_shader; int vert; int frag; - vert = GLSL_CompileShaderS ("quakemdl.vert", quakemdl_vert, + vert_shader = GLSL_BuildShader (alias_vert_effects); + frag_shader = GLSL_BuildShader (alias_frag_effects); + vert = GLSL_CompileShader ("quakemdl.vert", vert_shader, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("quakemdl.frag", quakemdl_frag, + frag = GLSL_CompileShader ("quakemdl.frag", frag_shader, GL_FRAGMENT_SHADER); quake_mdl.program = GLSL_LinkProgram ("quakemdl", vert, frag); GLSL_ResolveShaderParam (quake_mdl.program, &quake_mdl.mvp_matrix); @@ -136,6 +143,8 @@ glsl_R_InitAlias (void) GLSL_ResolveShaderParam (quake_mdl.program, &quake_mdl.shadelight); GLSL_ResolveShaderParam (quake_mdl.program, &quake_mdl.lightvec); GLSL_ResolveShaderParam (quake_mdl.program, &quake_mdl.fog); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); } static void diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl new file mode 100644 index 000000000..cfb296307 --- /dev/null +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -0,0 +1,152 @@ +-- Math.const + +const float PI = 3.14159265; +const float E = 2.71828183; + +-- Math.quaternion + +vec3 +qmult (vec4 q, vec3 v) +{ + float qc = q.w; + vec3 qv = q.xyz; + vec3 t = cross (qv, v); + return (qs * qs) * v + 2.0 * qs * t + dot (qv, v) * qv + cross (qv, t); +} + +vec3 +dqtrans (vec4 q0, vec4 qe) +{//2.0 * (q0.w * qe.xyz - qe.w * q0.xyz - cross (qe.xyz, q0.xyz)); + float qs = q0.w, Ts = qe.w; + vec3 qv = -q0.xyz, Tv = qe.xyz; + + return 2.0 * (Ts * qv + qs * Tv + cross (Tv, qv)); +} + +-- Fragment.fog + +uniform vec4 fog; + +vec4 +fogBlend (vec4 color) +{ + float fog_factor; + float az = fog.a * gl_FragCoord.z / gl_FragCoord.w; + vec4 fog_color = vec4 (fog.rgb, 1.0); + + fog_factor = exp (-az * az); + return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); +} + +-- Fragment.colormap + +uniform sampler2D colormap; + +vec4 +mappedColor (float pix, float light) +{ + return texture2D (colormap, vec2 (pix, light)); +} + +-- Fragment.turb + +const float SPEED = 20.0; +const float CYCLE = 128.0; +const float FACTOR = PI * 2.0 / CYCLE; +const vec2 BIAS = vec2 (1.0, 1.0) +const float SCALE = 8.0; + +vec2 +turb_st (vec2 st, float time) +{ + vec2 angle = st.ts * CYCLE / 2.0; + vec2 phase = vec2 (time, time) * SPEED; + return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; +} + +-- Fragment.skydome + +uniform sampler2D palette; +uniform sampler2D solid; +uniform sampler2D trans; +uniform float time +varying vec3 direction + +const float SCALE = 189.0 / 64.0; + +vec4 +skydome (dir, time) +{ + float len; + float pix; + vec2 flow = vec2 (1.0, 1.0); + vec2 st, base; + vec3 dir = direction; + + dir.z *= 3.0; + len = dot (dir, dir); + len = SCALE * inversesqrt (len); + + base = dir.yx * vec2(1.0, -1.0) * len; + st = base + flow * time / 8.0; + pix = texture2D (trans, st).r; + if (pix == 0.0) { + st = base + flow * realtime / 16.0; + pix = texture2D (solid, st).r; + } + return texture2D (palette, pix); +} + +-- Vertex.mdl +uniform mat4 mvp_mat; +uniform mat3 norm_mat; +uniform vec2 skin_size; +uniform float blend; + +attribute vec4 vcolora, vcolorb; +attribute vec2 vsta, vstb; +attribute vec3 vnormala, vnormalb; +attribute vec3 vertexa, vertexb; + +varying vec3 normal; +varying vec2 st; +varying vec4 color; + +void +main (void) +{ + vec3 vertex; + vec3 vnormal; + + vertex = mix (vertexa, vertexb, blend); + vnormal = mix (vnormala, vnormalb, blend); + gl_Position = mvp_mat * vec4 (vertex, 1.0); + st = mix (vsta, vstb, blend) / skin_size; + normal = norm_mat * vnormal; + color = mix (vcolora, vcolorb, blend); +} +-- Fragment.mdl +uniform sampler2D skin; +uniform float ambient; +uniform float shadelight; +uniform vec3 lightvec; + +varying vec3 normal; +varying vec2 st; +varying vec4 color; + +void +main (void) +{ + float pix = texture2D (skin, st).r; + float light = ambient; + float d, col; + vec4 lit; + + d = dot (normal, lightvec); + d = min (d, 0.0); + light = 255.0 - light; + light += d * shadelight; + lit = mappedColor (pix, light / 255.0); + gl_FragColor = fogBlend (lit * color); +} diff --git a/libs/video/renderer/glsl/quakemdl.frag b/libs/video/renderer/glsl/quakemdl.frag deleted file mode 100644 index cb7320931..000000000 --- a/libs/video/renderer/glsl/quakemdl.frag +++ /dev/null @@ -1,42 +0,0 @@ -uniform sampler2D colormap; -uniform sampler2D skin; -uniform float ambient; -uniform float shadelight; -uniform vec3 lightvec; -uniform vec4 fog; - -varying vec3 normal; -varying vec2 st; -varying vec4 color; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -void -main (void) -{ - float pix = texture2D (skin, st).r; - float light = ambient; - float d, col; - vec4 lit; - - d = dot (normal, lightvec); - d = min (d, 0.0); - light = 255.0 - light; - light += d * shadelight; - lit = texture2D (colormap, vec2 (pix, light / 255.0)); - gl_FragColor = fogBlend (lit * color); -} diff --git a/libs/video/renderer/glsl/quakemdl.vert b/libs/video/renderer/glsl/quakemdl.vert deleted file mode 100644 index b21e09b9f..000000000 --- a/libs/video/renderer/glsl/quakemdl.vert +++ /dev/null @@ -1,27 +0,0 @@ -uniform mat4 mvp_mat; -uniform mat3 norm_mat; -uniform vec2 skin_size; -uniform float blend; - -attribute vec4 vcolora, vcolorb; -attribute vec2 vsta, vstb; -attribute vec3 vnormala, vnormalb; -attribute vec3 vertexa, vertexb; - -varying vec3 normal; -varying vec2 st; -varying vec4 color; - -void -main (void) -{ - vec3 vertex; - vec3 vnormal; - - vertex = mix (vertexa, vertexb, blend); - vnormal = mix (vnormala, vnormalb, blend); - gl_Position = mvp_mat * vec4 (vertex, 1.0); - st = mix (vsta, vstb, blend) / skin_size; - normal = norm_mat * vnormal; - color = mix (vcolora, vcolorb, blend); -} diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 6664eb841..9f46fdc9c 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -56,6 +56,10 @@ #include "d_iface.h" #include "r_internal.h" +static const char quakeforge_effect[] = +#include "quakeforge.slc" +; + int glsl_palette; int glsl_colormap; @@ -181,6 +185,8 @@ GLSL_Init_Common (void) qfeglEnable (GL_BLEND); qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + GLSL_RegisterEffect ("QuakeForge", quakeforge_effect); } int From f43592589d8376d642e3125e643935374212ce9a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jun 2013 17:12:44 +0900 Subject: [PATCH 0046/1519] Use the new shader system in the bsp renderer. It mostly works. Skybox is untested, and water surfaces are broken. --- libs/video/renderer/glsl/Makefile.am | 12 +-- libs/video/renderer/glsl/glsl_alias.c | 2 + libs/video/renderer/glsl/glsl_bsp.c | 93 +++++++++++++++--------- libs/video/renderer/glsl/quakebsp.vert | 18 ----- libs/video/renderer/glsl/quakeforge.glsl | 82 +++++++++++++++++++-- libs/video/renderer/glsl/quakeskb.frag | 32 -------- libs/video/renderer/glsl/quakeski.frag | 48 ------------ libs/video/renderer/glsl/quakesky.vert | 14 ---- 8 files changed, 143 insertions(+), 158 deletions(-) delete mode 100644 libs/video/renderer/glsl/quakebsp.vert delete mode 100644 libs/video/renderer/glsl/quakeskb.frag delete mode 100644 libs/video/renderer/glsl/quakeski.frag delete mode 100644 libs/video/renderer/glsl/quakesky.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index dd65e2f0b..0a1b83725 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -5,15 +5,15 @@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) shader_src= quakeforge.glsl \ iqm.frag iqm.vert \ - quake2d.frag quakebsp.frag quakebsp.vert quakeico.vert quakemdl.frag \ - quakemdl.vert quakepar.frag quakepar.vert quakepnt.frag quakepnt.vert \ - quakeskb.frag quakeski.frag quakesky.vert quakespr.frag quakespr.vert \ + quake2d.frag quakeico.vert \ + quakepar.frag quakepar.vert quakepnt.frag quakepnt.vert \ + quakespr.frag quakespr.vert \ quaketrb.frag quaketxt.vert shader_gen= quakeforge.slc \ iqm.fc iqm.vc \ - quake2d.fc quakebsp.fc quakebsp.vc quakeico.vc quakemdl.fc quakemdl.vc \ - quakepar.fc quakepar.vc quakepnt.fc quakepnt.vc quakeskb.fc quakeski.fc \ - quakesky.vc quakespr.fc quakespr.vc quaketrb.fc quaketxt.vc + quake2d.fc quakeico.vc \ + quakepar.fc quakepar.vc quakepnt.fc quakepnt.vc \ + quakespr.fc quakespr.vc quaketrb.fc quaketxt.vc glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index ddbec7b04..3fdd50b66 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -58,6 +58,7 @@ static const char *alias_vert_effects[] = { "QuakeForge.Vertex.mdl", + 0 }; static const char *alias_frag_effects[] = @@ -65,6 +66,7 @@ static const char *alias_frag_effects[] = "QuakeForge.Fragment.fog", "QuakeForge.Fragment.colormap", "QuakeForge.Fragment.mdl", + 0 }; static struct { diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 8de55a9bd..4280964a5 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -106,29 +106,45 @@ static double sky_time; static quat_t default_color = { 1, 1, 1, 1 }; static quat_t last_color; -static const char quakebsp_vert[] = -#include "quakebsp.vc" -; +static const char *bsp_vert_effects[] = +{ + "QuakeForge.Vertex.bsp", + 0 +}; -static const char quakebsp_frag[] = -#include "quakebsp.fc" -; +static const char *bsp_lit_effects[] = +{ + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.colormap", + "QuakeForge.Fragment.bsp.lit", + 0 +}; -static const char quaketurb_frag[] = -#include "quaketrb.fc" -; +static const char *bsp_turb_effects[] = +{ + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.colormap", + "QuakeForge.Fragment.bsp.lit", + 0 +}; -static const char quakesky_vert[] = -#include "quakesky.vc" -; +static const char *bsp_sky_cube_effects[] = +{ + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.colormap", + "QuakeForge.env.sky.cube", + "QuakeForge.Fragment.bsp.sky", + 0 +}; -static const char quakeskyid_frag[] = -#include "quakeski.fc" -; - -static const char quakeskybox_frag[] = -#include "quakeskb.fc" -; +static const char *bsp_sky_id_effects[] = +{ + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.colormap", + "QuakeForge.env.sky.id", + "QuakeForge.Fragment.bsp.sky", + 0 +}; static struct { int program; @@ -159,7 +175,7 @@ static struct { shaderparam_t vertex; shaderparam_t palette; shaderparam_t texture; - shaderparam_t realtime; + shaderparam_t time; shaderparam_t color; shaderparam_t fog; } quake_turb = { @@ -169,7 +185,7 @@ static struct { {"vertex", 0}, {"palette", 1}, {"texture", 1}, - {"realtime", 1}, + {"time", 1}, {"vcolor", 0}, {"fog", 1}, }; @@ -182,7 +198,7 @@ static struct { shaderparam_t palette; shaderparam_t solid; shaderparam_t trans; - shaderparam_t realtime; + shaderparam_t time; shaderparam_t fog; } quake_skyid = { 0, @@ -192,7 +208,7 @@ static struct { {"palette", 1}, {"solid", 1}, {"trans", 1}, - {"realtime", 1}, + {"time", 1}, {"fog", 1}, }; @@ -917,7 +933,7 @@ turb_begin (void) qfeglEnable (GL_TEXTURE_2D); qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); - qfeglUniform1f (quake_turb.realtime.location, vr_data.realtime); + qfeglUniform1f (quake_turb.time.location, vr_data.realtime); qfeglUniform1i (quake_turb.texture.location, 0); qfeglActiveTexture (GL_TEXTURE0 + 0); @@ -1001,7 +1017,7 @@ sky_begin (void) qfeglEnable (GL_TEXTURE_2D); qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); - qfeglUniform1f (quake_skyid.realtime.location, vr_data.realtime); + qfeglUniform1f (quake_skyid.time.location, vr_data.realtime); qfeglUniform1i (quake_skyid.trans.location, 0); qfeglActiveTexture (GL_TEXTURE0 + 0); @@ -1241,12 +1257,15 @@ glsl_R_DrawSky (void) void glsl_R_InitBsp (void) { + shader_t *vert_shader, *frag_shader; int vert; int frag; - vert = GLSL_CompileShaderS ("quakebsp.vert", quakebsp_vert, + vert_shader = GLSL_BuildShader (bsp_vert_effects); + frag_shader = GLSL_BuildShader (bsp_lit_effects); + vert = GLSL_CompileShader ("quakebsp.vert", vert_shader, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("quakebsp.frag", quakebsp_frag, + frag = GLSL_CompileShader ("quakebsp.frag", frag_shader, GL_FRAGMENT_SHADER); quake_bsp.program = GLSL_LinkProgram ("quakebsp", vert, frag); GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.mvp_matrix); @@ -1257,8 +1276,11 @@ glsl_R_InitBsp (void) GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.lightmap); GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.color); GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.fog); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); - frag = GLSL_CompileShaderS ("quaketrb.frag", quaketurb_frag, + frag_shader = GLSL_BuildShader (bsp_turb_effects); + frag = GLSL_CompileShader ("quaketrb.frag", frag_shader, GL_FRAGMENT_SHADER); quake_turb.program = GLSL_LinkProgram ("quaketrb", vert, frag); GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.mvp_matrix); @@ -1266,13 +1288,13 @@ glsl_R_InitBsp (void) GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.vertex); GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.palette); GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.texture); - GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.realtime); + GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.time); GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.color); GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.fog); + GLSL_FreeShader (frag_shader); - vert = GLSL_CompileShaderS ("quakesky.vert", quakesky_vert, - GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("quakeski.frag", quakeskyid_frag, + frag_shader = GLSL_BuildShader (bsp_sky_id_effects); + frag = GLSL_CompileShader ("quakeski.frag", frag_shader, GL_FRAGMENT_SHADER); quake_skyid.program = GLSL_LinkProgram ("quakeskyid", vert, frag); GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.mvp_matrix); @@ -1281,10 +1303,12 @@ glsl_R_InitBsp (void) GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.palette); GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.solid); GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.trans); - GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.realtime); + GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.time); GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.fog); + GLSL_FreeShader (frag_shader); - frag = GLSL_CompileShaderS ("quakeskb.frag", quakeskybox_frag, + frag_shader = GLSL_BuildShader (bsp_sky_cube_effects); + frag = GLSL_CompileShader ("quakeskb.frag", frag_shader, GL_FRAGMENT_SHADER); quake_skybox.program = GLSL_LinkProgram ("quakeskybox", vert, frag); GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.mvp_matrix); @@ -1292,6 +1316,7 @@ glsl_R_InitBsp (void) GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.vertex); GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.sky); GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.fog); + GLSL_FreeShader (frag_shader); } static inline int diff --git a/libs/video/renderer/glsl/quakebsp.vert b/libs/video/renderer/glsl/quakebsp.vert deleted file mode 100644 index fc22d17e6..000000000 --- a/libs/video/renderer/glsl/quakebsp.vert +++ /dev/null @@ -1,18 +0,0 @@ -uniform mat4 mvp_mat; - -attribute vec4 vcolor; -attribute vec4 tlst; -attribute vec4 vertex; - -varying vec2 tst; -varying vec2 lst; -varying vec4 color; - -void -main (void) -{ - gl_Position = mvp_mat * vertex; - tst = tlst.st; - lst = tlst.pq; - color = vcolor; -} diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index cfb296307..7efd9db48 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -64,24 +64,36 @@ turb_st (vec2 st, float time) return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; } --- Fragment.skydome +-- env.sky.cube + +uniform samplerCube sky; + +vec4 +sky_color (vec3 dir) +{ + // NOTE: quake's world and GL's world are rotated relative to each other + // quake has x right, y in, z up. gl has x right, y up, z out + // The textures are loaded with GL's z (quake's y) already negated, so + // all that's needed here is to swizzle y and z. + return textureCube(sky, dir.xzy); +} + +-- env.sky.id uniform sampler2D palette; uniform sampler2D solid; uniform sampler2D trans; -uniform float time -varying vec3 direction +uniform float time; const float SCALE = 189.0 / 64.0; vec4 -skydome (dir, time) +sky_color (vec3 dir) { float len; float pix; vec2 flow = vec2 (1.0, 1.0); vec2 st, base; - vec3 dir = direction; dir.z *= 3.0; len = dot (dir, dir); @@ -91,13 +103,14 @@ skydome (dir, time) st = base + flow * time / 8.0; pix = texture2D (trans, st).r; if (pix == 0.0) { - st = base + flow * realtime / 16.0; + st = base + flow * time / 16.0; pix = texture2D (solid, st).r; } return texture2D (palette, pix); } -- Vertex.mdl + uniform mat4 mvp_mat; uniform mat3 norm_mat; uniform vec2 skin_size; @@ -125,7 +138,9 @@ main (void) normal = norm_mat * vnormal; color = mix (vcolora, vcolorb, blend); } + -- Fragment.mdl + uniform sampler2D skin; uniform float ambient; uniform float shadelight; @@ -150,3 +165,58 @@ main (void) lit = mappedColor (pix, light / 255.0); gl_FragColor = fogBlend (lit * color); } + +-- Vertex.bsp + +uniform mat4 mvp_mat; +uniform mat4 sky_mat; + +attribute vec4 vcolor; +attribute vec4 tlst; +attribute vec4 vertex; + +varying vec2 tst; +varying vec2 lst; +varying vec4 color; +varying vec3 direction; + +void +main (void) +{ + gl_Position = mvp_mat * vertex; + direction = (sky_mat * vertex).xyz; + tst = tlst.st; + lst = tlst.pq; + color = vcolor; +} + +-- Fragment.bsp.lit + +uniform sampler2D texture; +uniform sampler2D lightmap; + +varying vec2 tst; +varying vec2 lst; +varying vec4 color; + +void +main (void) +{ + float pix = texture2D (texture, tst).r; + float light = texture2D (lightmap, lst).r; + vec4 c; + + c = mappedColor (pix, light * 4.0) * color; + gl_FragColor = fogBlend (c); +} + +-- Fragment.bsp.sky + +varying vec3 direction; + +void +main (void) +{ + vec4 c = sky_color (direction); + gl_FragColor = fogBlend (c); +} diff --git a/libs/video/renderer/glsl/quakeskb.frag b/libs/video/renderer/glsl/quakeskb.frag deleted file mode 100644 index 3ffacd398..000000000 --- a/libs/video/renderer/glsl/quakeskb.frag +++ /dev/null @@ -1,32 +0,0 @@ -uniform samplerCube sky; -uniform vec4 fog; - -varying vec3 direction; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -void -main (void) -{ - vec3 dir = direction; - - // NOTE: quake's world and GL's world are rotated relative to each other - // quake has x right, y in, z up. gl has x right, y up, z out - // The textures are loaded with GL's z (quake's y) already negated, so - // all that's needed here is to swizzle y and z. - gl_FragColor = fogBlend (textureCube(sky, dir.xzy)); -} diff --git a/libs/video/renderer/glsl/quakeski.frag b/libs/video/renderer/glsl/quakeski.frag deleted file mode 100644 index 5c2bbb96c..000000000 --- a/libs/video/renderer/glsl/quakeski.frag +++ /dev/null @@ -1,48 +0,0 @@ -uniform sampler2D palette; -uniform sampler2D solid; -uniform sampler2D trans; -uniform float realtime; -uniform vec4 fog; - -varying vec3 direction; - -const float SCALE = 189.0 / 64.0; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -void -main (void) -{ - float len; - float pix; - vec2 flow = vec2 (1.0, 1.0); - vec2 st, base; - vec3 dir = direction; - - dir.z *= 3.0; - len = dot (dir, dir); - len = SCALE * inversesqrt (len); - - base = direction.yx * vec2(1.0, -1.0) * len; - st = base + flow * realtime / 8.0; - pix = texture2D (trans, st).r; - if (pix == 0.0) { - st = base + flow * realtime / 16.0; - pix = texture2D (solid, st).r; - } - gl_FragColor = fogBlend (texture2D (palette, vec2 (pix, 0.0))); -} diff --git a/libs/video/renderer/glsl/quakesky.vert b/libs/video/renderer/glsl/quakesky.vert deleted file mode 100644 index 98754de77..000000000 --- a/libs/video/renderer/glsl/quakesky.vert +++ /dev/null @@ -1,14 +0,0 @@ -uniform mat4 mvp_mat; -uniform mat4 sky_mat; - -attribute vec4 tlst; -attribute vec4 vertex; - -varying vec3 direction; - -void -main (void) -{ - gl_Position = mvp_mat * vertex; - direction = (sky_mat * vertex).xyz; -} From 26fc0b74e61dad055807a1fbf900b19b7a09aeda Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jun 2013 19:08:58 +0900 Subject: [PATCH 0047/1519] Fix bsp water surfaces. Everything seems to be working for the bsp renderer. --- libs/video/renderer/glsl/glsl_bsp.c | 5 ++- libs/video/renderer/glsl/quakeforge.glsl | 45 +++++++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 4280964a5..9f6d019ed 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -115,6 +115,7 @@ static const char *bsp_vert_effects[] = static const char *bsp_lit_effects[] = { "QuakeForge.Fragment.fog", + "QuakeForge.env.warp.nop", "QuakeForge.Fragment.colormap", "QuakeForge.Fragment.bsp.lit", 0 @@ -122,9 +123,11 @@ static const char *bsp_lit_effects[] = static const char *bsp_turb_effects[] = { + "QuakeForge.Math.const", "QuakeForge.Fragment.fog", + "QuakeForge.env.warp.turb", "QuakeForge.Fragment.colormap", - "QuakeForge.Fragment.bsp.lit", + "QuakeForge.Fragment.bsp.unlit", 0 }; diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 7efd9db48..a4bb5390d 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -48,16 +48,24 @@ mappedColor (float pix, float light) return texture2D (colormap, vec2 (pix, light)); } --- Fragment.turb +-- env.warp.nop + +vec2 +warp_st (vec2 st, float time) +{ + return st; +} + +-- env.warp.turb const float SPEED = 20.0; const float CYCLE = 128.0; const float FACTOR = PI * 2.0 / CYCLE; -const vec2 BIAS = vec2 (1.0, 1.0) +const vec2 BIAS = vec2 (1.0, 1.0); const float SCALE = 8.0; vec2 -turb_st (vec2 st, float time) +warp_st (vec2 st, float time) { vec2 angle = st.ts * CYCLE / 2.0; vec2 phase = vec2 (time, time) * SPEED; @@ -106,7 +114,7 @@ sky_color (vec3 dir) st = base + flow * time / 16.0; pix = texture2D (solid, st).r; } - return texture2D (palette, pix); + return texture2D (palette, vec2 (pix, 0)); } -- Vertex.mdl @@ -194,6 +202,7 @@ main (void) uniform sampler2D texture; uniform sampler2D lightmap; +uniform float time; varying vec2 tst; varying vec2 lst; @@ -202,14 +211,40 @@ varying vec4 color; void main (void) { - float pix = texture2D (texture, tst).r; + float pix; + vec2 st; float light = texture2D (lightmap, lst).r; vec4 c; + st = warp_st (tst, time); + pix = texture2D (texture, st).r; c = mappedColor (pix, light * 4.0) * color; gl_FragColor = fogBlend (c); } +-- Fragment.bsp.unlit + +uniform sampler2D texture; +uniform sampler2D palette; +uniform float time; + +varying vec2 tst; +varying vec4 color; + +void +main (void) +{ + float pix; + vec2 st; + vec4 c; + + st = warp_st (tst, time); + pix = texture2D (texture, st).r; + c = texture2D (palette, vec2(pix, 0)) * color; + gl_FragColor = fogBlend (c); +} + + -- Fragment.bsp.sky varying vec3 direction; From 042d6e57281ef3109639755ee8a92cc38bba5a23 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jun 2013 19:42:51 +0900 Subject: [PATCH 0048/1519] Remove a couple of stale files. Missed these in the bsp related commit. --- libs/video/renderer/glsl/quakebsp.frag | 36 ------------------- libs/video/renderer/glsl/quaketrb.frag | 49 -------------------------- 2 files changed, 85 deletions(-) delete mode 100644 libs/video/renderer/glsl/quakebsp.frag delete mode 100644 libs/video/renderer/glsl/quaketrb.frag diff --git a/libs/video/renderer/glsl/quakebsp.frag b/libs/video/renderer/glsl/quakebsp.frag deleted file mode 100644 index 4dd8a0c7e..000000000 --- a/libs/video/renderer/glsl/quakebsp.frag +++ /dev/null @@ -1,36 +0,0 @@ -uniform sampler2D colormap; -uniform sampler2D texture; -uniform sampler2D lightmap; -uniform vec4 fog; - -varying vec2 tst; -varying vec2 lst; -varying vec4 color; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -void -main (void) -{ - float pix = texture2D (texture, tst).r; - float light = texture2D (lightmap, lst).r; - float col; - vec4 c; - - c = texture2D (colormap, vec2 (pix, light * 4.0)) * color; - gl_FragColor = fogBlend (c); -} diff --git a/libs/video/renderer/glsl/quaketrb.frag b/libs/video/renderer/glsl/quaketrb.frag deleted file mode 100644 index e019c557e..000000000 --- a/libs/video/renderer/glsl/quaketrb.frag +++ /dev/null @@ -1,49 +0,0 @@ -uniform sampler2D palette; -uniform sampler2D texture; -uniform float realtime; -uniform vec4 fog; - -varying vec2 tst; -varying vec4 color; - -const float SPEED = 20.0; -const float CYCLE = 128.0; -const float PI = 3.14159; -const float FACTOR = PI * 2.0 / CYCLE; -const vec2 BIAS = vec2 (1.0, 1.0); -const float SCALE = 8.0; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -vec2 -turb_st (vec2 st, float time) -{ - vec2 angle = st.ts * CYCLE / 2.0; - vec2 phase = vec2 (time, time) * SPEED; - return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; -} - -void -main (void) -{ - float pix; - vec2 st; - - st = turb_st (tst, realtime); - pix = texture2D (texture, st).r; - gl_FragColor = fogBlend (texture2D (palette, vec2 (pix, 0.0)) * color); -} From a419fb2c92c2f4bf3b60bd01f7a7c76f271c6547 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 11:38:13 +0900 Subject: [PATCH 0049/1519] Ensure the vertex coord attribute is attribute 0. It seems mesa still has the bug where non-array attributes don't work when set as attribute 0, and that the allocation order changed sometime since I last tested with mesa. This fixes the black world and flickering alias models on my eeepc. --- libs/video/renderer/glsl/quakeforge.glsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index a4bb5390d..c8d0da2c2 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -124,10 +124,10 @@ uniform mat3 norm_mat; uniform vec2 skin_size; uniform float blend; -attribute vec4 vcolora, vcolorb; -attribute vec2 vsta, vstb; -attribute vec3 vnormala, vnormalb; attribute vec3 vertexa, vertexb; +attribute vec3 vnormala, vnormalb; +attribute vec2 vsta, vstb; +attribute vec4 vcolora, vcolorb; varying vec3 normal; varying vec2 st; @@ -179,9 +179,9 @@ main (void) uniform mat4 mvp_mat; uniform mat4 sky_mat; -attribute vec4 vcolor; -attribute vec4 tlst; attribute vec4 vertex; +attribute vec4 tlst; +attribute vec4 vcolor; varying vec2 tst; varying vec2 lst; From 3af6a640fedd4c6034660dfd44c84e89bbaac19c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 12:06:36 +0900 Subject: [PATCH 0050/1519] Missed the old turb frag shader. --- libs/video/renderer/glsl/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 0a1b83725..d28c62454 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -8,12 +8,12 @@ shader_src= quakeforge.glsl \ quake2d.frag quakeico.vert \ quakepar.frag quakepar.vert quakepnt.frag quakepnt.vert \ quakespr.frag quakespr.vert \ - quaketrb.frag quaketxt.vert + quaketxt.vert shader_gen= quakeforge.slc \ iqm.fc iqm.vc \ quake2d.fc quakeico.vc \ quakepar.fc quakepar.vc quakepnt.fc quakepnt.vc \ - quakespr.fc quakespr.vc quaketrb.fc quaketxt.vc + quakespr.fc quakespr.vc quaketxt.vc glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ From 1a7b532927e550fcec363b1246cd5d78ab76add6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 12:08:53 +0900 Subject: [PATCH 0051/1519] Use the new shader system for point particles. --- libs/video/renderer/glsl/Makefile.am | 4 +- libs/video/renderer/glsl/glsl_particles.c | 25 +++++++---- libs/video/renderer/glsl/quakeforge.glsl | 55 +++++++++++++++++++++++ libs/video/renderer/glsl/quakepnt.frag | 29 ------------ libs/video/renderer/glsl/quakepnt.vert | 19 -------- 5 files changed, 74 insertions(+), 58 deletions(-) delete mode 100644 libs/video/renderer/glsl/quakepnt.frag delete mode 100644 libs/video/renderer/glsl/quakepnt.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index d28c62454..7c1b1869c 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -6,13 +6,13 @@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) shader_src= quakeforge.glsl \ iqm.frag iqm.vert \ quake2d.frag quakeico.vert \ - quakepar.frag quakepar.vert quakepnt.frag quakepnt.vert \ + quakepar.frag quakepar.vert \ quakespr.frag quakespr.vert \ quaketxt.vert shader_gen= quakeforge.slc \ iqm.fc iqm.vc \ quake2d.fc quakeico.vc \ - quakepar.fc quakepar.vc quakepnt.fc quakepnt.vc \ + quakepar.fc quakepar.vc \ quakespr.fc quakespr.vc quaketxt.vc glsl_src = \ diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 4d870623f..902fef2c0 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -78,13 +78,17 @@ static partvert_t *particleVertexArray; static GLuint part_tex; -static const char quakepoint_vert[] = -#include "quakepnt.vc" -; +static const char *particle_point_vert_effects[] = +{ + "QuakeForge.Vertex.particle.point", + 0 +}; -static const char quakepoint_frag[] = -#include "quakepnt.fc" -; +static const char *particle_point_frag_effects[] = +{ + "QuakeForge.Fragment.particle.point", + 0 +}; static const char quakepart_vert[] = #include "quakepar.vc" @@ -210,6 +214,7 @@ glsl_R_ClearParticles (void) void glsl_R_InitParticles (void) { + shader_t *vert_shader, *frag_shader; unsigned i; int vert; int frag; @@ -223,9 +228,11 @@ glsl_R_InitParticles (void) qfeglGetFloatv (GL_ALIASED_POINT_SIZE_RANGE, v); Sys_MaskPrintf (SYS_GLSL, "point size: %g - %g\n", v[0], v[1]); - vert = GLSL_CompileShaderS ("quakepnt.vert", quakepoint_vert, + vert_shader = GLSL_BuildShader (particle_point_vert_effects); + frag_shader = GLSL_BuildShader (particle_point_frag_effects); + vert = GLSL_CompileShader ("quakepnt.vert", vert_shader, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("quakepnt.frag", quakepoint_frag, + frag = GLSL_CompileShader ("quakepnt.frag", frag_shader, GL_FRAGMENT_SHADER); quake_point.program = GLSL_LinkProgram ("quakepoint", vert, frag); GLSL_ResolveShaderParam (quake_point.program, &quake_point.mvp_matrix); @@ -233,6 +240,8 @@ glsl_R_InitParticles (void) GLSL_ResolveShaderParam (quake_point.program, &quake_point.palette); GLSL_ResolveShaderParam (quake_point.program, &quake_point.color); GLSL_ResolveShaderParam (quake_point.program, &quake_point.fog); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); vert = GLSL_CompileShaderS ("quakepar.vert", quakepart_vert, GL_VERTEX_SHADER); diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index c8d0da2c2..cbde9ac81 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -255,3 +255,58 @@ main (void) vec4 c = sky_color (direction); gl_FragColor = fogBlend (c); } + + +-- Vertex.particle.point + +uniform mat4 mvp_mat; +attribute float vcolor; +/** Vertex position. + + x, y, z, c + + c is the color of the point. +*/ +attribute vec3 vertex; + +varying float color; + +void +main (void) +{ + gl_Position = mvp_mat * vec4 (vertex, 1.0); + gl_PointSize = max (1.0, 1024.0 * abs (1.0 / gl_Position.z)); + color = vcolor; +} + +-- Fragment.particle.point + +//precision mediump float; +uniform sampler2D palette; +uniform vec4 fog; + +varying float color; + +float +sqr (float x) +{ + return x * x; +} + +vec4 +fogBlend (vec4 color) +{ + float f; + vec4 fog_color = vec4 (fog.rgb, 1.0); + + f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); + return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); +} + +void +main (void) +{ + if (color == 1.0) + discard; + gl_FragColor = fogBlend (texture2D (palette, vec2 (color, 0.0))); +} diff --git a/libs/video/renderer/glsl/quakepnt.frag b/libs/video/renderer/glsl/quakepnt.frag deleted file mode 100644 index 3ae6bebbc..000000000 --- a/libs/video/renderer/glsl/quakepnt.frag +++ /dev/null @@ -1,29 +0,0 @@ -//precision mediump float; -uniform sampler2D palette; -uniform vec4 fog; - -varying float color; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -void -main (void) -{ - if (color == 1.0) - discard; - gl_FragColor = fogBlend (texture2D (palette, vec2 (color, 0.0))); -} diff --git a/libs/video/renderer/glsl/quakepnt.vert b/libs/video/renderer/glsl/quakepnt.vert deleted file mode 100644 index 2a1ca43b6..000000000 --- a/libs/video/renderer/glsl/quakepnt.vert +++ /dev/null @@ -1,19 +0,0 @@ -uniform mat4 mvp_mat; -attribute float vcolor; -/** Vertex position. - - x, y, z, c - - c is the color of the point. -*/ -attribute vec3 vertex; - -varying float color; - -void -main (void) -{ - gl_Position = mvp_mat * vec4 (vertex, 1.0); - gl_PointSize = max (1.0, 1024.0 * abs (1.0 / gl_Position.z)); - color = vcolor; -} From 1d67f8f0c3dc362b43497bc2094cfbdf54e5785c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 12:16:52 +0900 Subject: [PATCH 0052/1519] Use the new shader system for textured particles. --- libs/video/renderer/glsl/Makefile.am | 2 - libs/video/renderer/glsl/glsl_particles.c | 24 ++++++---- libs/video/renderer/glsl/quakeforge.glsl | 55 +++++++++++++++++++++++ libs/video/renderer/glsl/quakepar.frag | 28 ------------ libs/video/renderer/glsl/quakepar.vert | 21 --------- 5 files changed, 71 insertions(+), 59 deletions(-) delete mode 100644 libs/video/renderer/glsl/quakepar.frag delete mode 100644 libs/video/renderer/glsl/quakepar.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 7c1b1869c..2afb4ccd2 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -6,13 +6,11 @@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) shader_src= quakeforge.glsl \ iqm.frag iqm.vert \ quake2d.frag quakeico.vert \ - quakepar.frag quakepar.vert \ quakespr.frag quakespr.vert \ quaketxt.vert shader_gen= quakeforge.slc \ iqm.fc iqm.vc \ quake2d.fc quakeico.vc \ - quakepar.fc quakepar.vc \ quakespr.fc quakespr.vc quaketxt.vc glsl_src = \ diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 902fef2c0..09ae06d6f 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -90,13 +90,17 @@ static const char *particle_point_frag_effects[] = 0 }; -static const char quakepart_vert[] = -#include "quakepar.vc" -; +static const char *particle_textured_vert_effects[] = +{ + "QuakeForge.Vertex.particle.textured", + 0 +}; -static const char quakepart_frag[] = -#include "quakepar.fc" -; +static const char *particle_textured_frag_effects[] = +{ + "QuakeForge.Fragment.particle.textured", + 0 +}; static struct { int program; @@ -243,9 +247,11 @@ glsl_R_InitParticles (void) GLSL_FreeShader (vert_shader); GLSL_FreeShader (frag_shader); - vert = GLSL_CompileShaderS ("quakepar.vert", quakepart_vert, + vert_shader = GLSL_BuildShader (particle_textured_vert_effects); + frag_shader = GLSL_BuildShader (particle_textured_frag_effects); + vert = GLSL_CompileShader ("quakepar.vert", vert_shader, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("quakepar.frag", quakepart_frag, + frag = GLSL_CompileShader ("quakepar.frag", frag_shader, GL_FRAGMENT_SHADER); quake_part.program = GLSL_LinkProgram ("quakepart", vert, frag); GLSL_ResolveShaderParam (quake_part.program, &quake_part.mvp_matrix); @@ -254,6 +260,8 @@ glsl_R_InitParticles (void) GLSL_ResolveShaderParam (quake_part.program, &quake_part.color); GLSL_ResolveShaderParam (quake_part.program, &quake_part.texture); GLSL_ResolveShaderParam (quake_part.program, &quake_part.fog); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); memset (data, 0, sizeof (data)); qfeglGenTextures (1, &part_tex); diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index cbde9ac81..097ef89ed 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -279,6 +279,30 @@ main (void) color = vcolor; } +-- Vertex.particle.textured + +uniform mat4 mvp_mat; +attribute vec4 vcolor; +attribute vec2 vst; +/** Vertex position. + + x, y, z, c + + c is the color of the point. +*/ +attribute vec3 vertex; + +varying vec4 color; +varying vec2 st; + +void +main (void) +{ + gl_Position = mvp_mat * vec4 (vertex, 1.0); + color = vcolor; + st = vst; +} + -- Fragment.particle.point //precision mediump float; @@ -310,3 +334,34 @@ main (void) discard; gl_FragColor = fogBlend (texture2D (palette, vec2 (color, 0.0))); } + +-- Fragment.particle.textured + +//precision mediump float; +uniform sampler2D texture; +uniform vec4 fog; + +varying vec4 color; +varying vec2 st; + +float +sqr (float x) +{ + return x * x; +} + +vec4 +fogBlend (vec4 color) +{ + float f; + vec4 fog_color = vec4 (fog.rgb, 1.0); + + f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); + return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); +} + +void +main (void) +{ + gl_FragColor = fogBlend (texture2D (texture, st) * color); +} diff --git a/libs/video/renderer/glsl/quakepar.frag b/libs/video/renderer/glsl/quakepar.frag deleted file mode 100644 index da829b0f3..000000000 --- a/libs/video/renderer/glsl/quakepar.frag +++ /dev/null @@ -1,28 +0,0 @@ -//precision mediump float; -uniform sampler2D texture; -uniform vec4 fog; - -varying vec4 color; -varying vec2 st; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -void -main (void) -{ - gl_FragColor = fogBlend (texture2D (texture, st) * color); -} diff --git a/libs/video/renderer/glsl/quakepar.vert b/libs/video/renderer/glsl/quakepar.vert deleted file mode 100644 index 3c80e6520..000000000 --- a/libs/video/renderer/glsl/quakepar.vert +++ /dev/null @@ -1,21 +0,0 @@ -uniform mat4 mvp_mat; -attribute vec4 vcolor; -attribute vec2 vst; -/** Vertex position. - - x, y, z, c - - c is the color of the point. -*/ -attribute vec3 vertex; - -varying vec4 color; -varying vec2 st; - -void -main (void) -{ - gl_Position = mvp_mat * vec4 (vertex, 1.0); - color = vcolor; - st = vst; -} From 68bd7e643d039a1f67bc1641ff2a1cb4b4c807be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 12:22:38 +0900 Subject: [PATCH 0053/1519] Remove the long dead text vertex shader. --- libs/video/renderer/glsl/Makefile.am | 5 ++- libs/video/renderer/glsl/glsl_draw.c | 4 --- libs/video/renderer/glsl/quaketxt.vert | 49 -------------------------- 3 files changed, 2 insertions(+), 56 deletions(-) delete mode 100644 libs/video/renderer/glsl/quaketxt.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 2afb4ccd2..34108e9d4 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -6,12 +6,11 @@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) shader_src= quakeforge.glsl \ iqm.frag iqm.vert \ quake2d.frag quakeico.vert \ - quakespr.frag quakespr.vert \ - quaketxt.vert + quakespr.frag quakespr.vert shader_gen= quakeforge.slc \ iqm.fc iqm.vc \ quake2d.fc quakeico.vc \ - quakespr.fc quakespr.vc quaketxt.vc + quakespr.fc quakespr.vc glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 9be2635cc..a42bc9370 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -76,10 +76,6 @@ static const char quakeicon_vert[] = #include "quakeico.vc" ; -static const char quaketext_vert[] = -#include "quaketxt.vc" -; - static const char quake2d_frag[] = #include "quake2d.fc" ; diff --git a/libs/video/renderer/glsl/quaketxt.vert b/libs/video/renderer/glsl/quaketxt.vert deleted file mode 100644 index 4c4c6f216..000000000 --- a/libs/video/renderer/glsl/quaketxt.vert +++ /dev/null @@ -1,49 +0,0 @@ -uniform mat4 mvp_mat; -/** Vertex position. - - x, y, cx, cy - - \a vertex provides the onscreen location at which to draw the character - (\a x, \a y) and which corner of the character cell this vertex - represents (\a cx, \a cy). \a cx and \a cy must be either 0 or 1, or - wierd things will happen with the character cell. -*/ -attribute vec4 vertex; - -/** Vectex color. - - r, g, b, a -*/ -attribute vec4 vcolor; - -/** The character to draw. - - The quake character map supports only 256 characters, 0-255. Any other - value will give interesting results. -*/ -attribute float dchar; - -/** Coordinate in character map texture. -*/ -varying vec4 color; -varying vec2 st; - -void -main (void) -{ - float row, col; - vec2 pos, corner, uv; - const vec2 inset = vec2 (0.03125, 0.03125); - const vec2 size = vec2 (0.0625, 0.0625); - - row = floor (dchar / 16.0); - col = mod (dchar, 16.0); - - pos = vertex.xy; - corner = vertex.zw; - uv = vec2 (col, row) + inset * (1.0 - 2.0 * corner) + corner; - uv *= size; - gl_Position = mvp_mat * vec4 (pos + corner * 8.0, 0.0, 1.0); - st = uv; - color = vcolor; -} From 50bb40be29b9eebce55b794ecac5513c0d80164a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 12:31:27 +0900 Subject: [PATCH 0054/1519] Use the new shader system for sprites. --- libs/video/renderer/glsl/Makefile.am | 6 +-- libs/video/renderer/glsl/glsl_sprite.c | 25 ++++++--- libs/video/renderer/glsl/quakeforge.glsl | 69 ++++++++++++++++++++++++ libs/video/renderer/glsl/quakespr.frag | 43 --------------- libs/video/renderer/glsl/quakespr.vert | 20 ------- 5 files changed, 88 insertions(+), 75 deletions(-) delete mode 100644 libs/video/renderer/glsl/quakespr.frag delete mode 100644 libs/video/renderer/glsl/quakespr.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 34108e9d4..1daa73c78 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -5,12 +5,10 @@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) shader_src= quakeforge.glsl \ iqm.frag iqm.vert \ - quake2d.frag quakeico.vert \ - quakespr.frag quakespr.vert + quake2d.frag quakeico.vert shader_gen= quakeforge.slc \ iqm.fc iqm.vc \ - quake2d.fc quakeico.vc \ - quakespr.fc quakespr.vc + quake2d.fc quakeico.vc glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index ab96b137e..6603a7e69 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -55,13 +55,17 @@ #include "r_internal.h" -static const char quakesprite_vert[] = -#include "quakespr.vc" -; +static const char *sprite_vert_effects[] = +{ + "QuakeForge.Vertex.sprite", + 0 +}; -static const char quakesprite_frag[] = -#include "quakespr.fc" -; +static const char *sprite_frag_effects[] = +{ + "QuakeForge.Fragment.sprite", + 0 +}; //static float proj_matrix[16]; @@ -96,11 +100,14 @@ static struct { void glsl_R_InitSprites (void) { + shader_t *vert_shader, *frag_shader; int frag, vert; - vert = GLSL_CompileShaderS ("quakespr.vert", quakesprite_vert, + vert_shader = GLSL_BuildShader (sprite_vert_effects); + frag_shader = GLSL_BuildShader (sprite_frag_effects); + vert = GLSL_CompileShader ("quakespr.vert", vert_shader, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("quakespr.frag", quakesprite_frag, + frag = GLSL_CompileShader ("quakespr.frag", frag_shader, GL_FRAGMENT_SHADER); quake_sprite.program = GLSL_LinkProgram ("quakespr", vert, frag); GLSL_ResolveShaderParam (quake_sprite.program, &quake_sprite.spritea); @@ -114,6 +121,8 @@ glsl_R_InitSprites (void) GLSL_ResolveShaderParam (quake_sprite.program, &quake_sprite.uvab); GLSL_ResolveShaderParam (quake_sprite.program, &quake_sprite.blend); GLSL_ResolveShaderParam (quake_sprite.program, &quake_sprite.fog); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); } static void diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 097ef89ed..fc4954252 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -365,3 +365,72 @@ main (void) { gl_FragColor = fogBlend (texture2D (texture, st) * color); } + +-- Vertex.sprite + +uniform mat4 mvp_mat; +attribute float vblend; +attribute vec4 vcolora, vcolorb; +attribute vec4 uvab; ///< ua va ub vb +attribute vec3 vertexa, vertexb; + +varying float blend; +varying vec4 colora, colorb; +varying vec2 sta, stb; + +void +main (void) +{ + gl_Position = mvp_mat * vec4 (mix (vertexa, vertexb, vblend), 1.0); + blend = vblend; + colora = vcolora; + colorb = vcolorb; + sta = uvab.xy; + stb = uvab.zw; +} + +-- Fragment.sprite + +uniform sampler2D spritea; +uniform sampler2D spriteb; +uniform sampler2D palette; +uniform vec4 fog; + +varying float blend; +varying vec4 colora, colorb; +varying vec2 sta, stb; + +float +sqr (float x) +{ + return x * x; +} + +vec4 +fogBlend (vec4 color) +{ + float f; + vec4 fog_color = vec4 (fog.rgb, 1.0); + + f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); + return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); +} + +void +main (void) +{ + float pixa, pixb; + vec4 cola, colb; + vec4 col; + + pixa = texture2D (spritea, sta).r; + pixb = texture2D (spriteb, stb).r; + if (pixa == 1.0 && pixb == 1.0) + discard; + cola = texture2D (palette, vec2 (pixa, 0.0)) * colora; + colb = texture2D (palette, vec2 (pixb, 0.0)) * colorb; + col = mix (cola, colb, blend); + if (col.a == 0.0) + discard; + gl_FragColor = fogBlend (col); +} diff --git a/libs/video/renderer/glsl/quakespr.frag b/libs/video/renderer/glsl/quakespr.frag deleted file mode 100644 index fd20a4fa4..000000000 --- a/libs/video/renderer/glsl/quakespr.frag +++ /dev/null @@ -1,43 +0,0 @@ -uniform sampler2D spritea; -uniform sampler2D spriteb; -uniform sampler2D palette; -uniform vec4 fog; - -varying float blend; -varying vec4 colora, colorb; -varying vec2 sta, stb; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -void -main (void) -{ - float pixa, pixb; - vec4 cola, colb; - vec4 col; - - pixa = texture2D (spritea, sta).r; - pixb = texture2D (spriteb, stb).r; - if (pixa == 1.0 && pixb == 1.0) - discard; - cola = texture2D (palette, vec2 (pixa, 0.0)) * colora; - colb = texture2D (palette, vec2 (pixb, 0.0)) * colorb; - col = mix (cola, colb, blend); - if (col.a == 0.0) - discard; - gl_FragColor = fogBlend (col); -} diff --git a/libs/video/renderer/glsl/quakespr.vert b/libs/video/renderer/glsl/quakespr.vert deleted file mode 100644 index c248d292c..000000000 --- a/libs/video/renderer/glsl/quakespr.vert +++ /dev/null @@ -1,20 +0,0 @@ -uniform mat4 mvp_mat; -attribute float vblend; -attribute vec4 vcolora, vcolorb; -attribute vec4 uvab; ///< ua va ub vb -attribute vec3 vertexa, vertexb; - -varying float blend; -varying vec4 colora, colorb; -varying vec2 sta, stb; - -void -main (void) -{ - gl_Position = mvp_mat * vec4 (mix (vertexa, vertexb, vblend), 1.0); - blend = vblend; - colora = vcolora; - colorb = vcolorb; - sta = uvab.xy; - stb = uvab.zw; -} From c89e612cd4280c0d874e288f71dee2686ffc3d1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 13:00:28 +0900 Subject: [PATCH 0055/1519] Remove redundant fog and palette shader code. --- libs/video/renderer/glsl/glsl_bsp.c | 5 +- libs/video/renderer/glsl/glsl_particles.c | 4 ++ libs/video/renderer/glsl/glsl_sprite.c | 2 + libs/video/renderer/glsl/quakeforge.glsl | 75 +++++------------------ 4 files changed, 23 insertions(+), 63 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 9f6d019ed..e52402660 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -125,8 +125,8 @@ static const char *bsp_turb_effects[] = { "QuakeForge.Math.const", "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.palette", "QuakeForge.env.warp.turb", - "QuakeForge.Fragment.colormap", "QuakeForge.Fragment.bsp.unlit", 0 }; @@ -134,7 +134,6 @@ static const char *bsp_turb_effects[] = static const char *bsp_sky_cube_effects[] = { "QuakeForge.Fragment.fog", - "QuakeForge.Fragment.colormap", "QuakeForge.env.sky.cube", "QuakeForge.Fragment.bsp.sky", 0 @@ -143,7 +142,7 @@ static const char *bsp_sky_cube_effects[] = static const char *bsp_sky_id_effects[] = { "QuakeForge.Fragment.fog", - "QuakeForge.Fragment.colormap", + "QuakeForge.Fragment.palette", "QuakeForge.env.sky.id", "QuakeForge.Fragment.bsp.sky", 0 diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 09ae06d6f..dba65db08 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -86,6 +86,8 @@ static const char *particle_point_vert_effects[] = static const char *particle_point_frag_effects[] = { + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.palette", "QuakeForge.Fragment.particle.point", 0 }; @@ -98,6 +100,8 @@ static const char *particle_textured_vert_effects[] = static const char *particle_textured_frag_effects[] = { + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.palette", "QuakeForge.Fragment.particle.textured", 0 }; diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 6603a7e69..83f116ee3 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -63,6 +63,8 @@ static const char *sprite_vert_effects[] = static const char *sprite_frag_effects[] = { + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.palette", "QuakeForge.Fragment.sprite", 0 }; diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index fc4954252..66371483e 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -38,6 +38,16 @@ fogBlend (vec4 color) return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); } +-- Fragment.palette + +uniform sampler2D palette; + +vec4 +palettedColor (float pix) +{ + return texture2D (palette, vec2 (pix, 0.0)); +} + -- Fragment.colormap uniform sampler2D colormap; @@ -88,7 +98,6 @@ sky_color (vec3 dir) -- env.sky.id -uniform sampler2D palette; uniform sampler2D solid; uniform sampler2D trans; uniform float time; @@ -114,7 +123,7 @@ sky_color (vec3 dir) st = base + flow * time / 16.0; pix = texture2D (solid, st).r; } - return texture2D (palette, vec2 (pix, 0)); + return palettedColor (pix); } -- Vertex.mdl @@ -225,7 +234,6 @@ main (void) -- Fragment.bsp.unlit uniform sampler2D texture; -uniform sampler2D palette; uniform float time; varying vec2 tst; @@ -240,7 +248,7 @@ main (void) st = warp_st (tst, time); pix = texture2D (texture, st).r; - c = texture2D (palette, vec2(pix, 0)) * color; + c = palettedColor (pix) * color; gl_FragColor = fogBlend (c); } @@ -306,60 +314,25 @@ main (void) -- Fragment.particle.point //precision mediump float; -uniform sampler2D palette; -uniform vec4 fog; varying float color; -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - void main (void) { if (color == 1.0) discard; - gl_FragColor = fogBlend (texture2D (palette, vec2 (color, 0.0))); + gl_FragColor = fogBlend (palettedColor (color)); } -- Fragment.particle.textured //precision mediump float; uniform sampler2D texture; -uniform vec4 fog; varying vec4 color; varying vec2 st; -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - void main (void) { @@ -393,29 +366,11 @@ main (void) uniform sampler2D spritea; uniform sampler2D spriteb; -uniform sampler2D palette; -uniform vec4 fog; varying float blend; varying vec4 colora, colorb; varying vec2 sta, stb; -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - void main (void) { @@ -427,8 +382,8 @@ main (void) pixb = texture2D (spriteb, stb).r; if (pixa == 1.0 && pixb == 1.0) discard; - cola = texture2D (palette, vec2 (pixa, 0.0)) * colora; - colb = texture2D (palette, vec2 (pixb, 0.0)) * colorb; + cola = palettedColor (pixa) * colora; + colb = palettedColor (pixb) * colorb; col = mix (cola, colb, blend); if (col.a == 0.0) discard; From 385175ca656802abe0b744ce3974ab2541a3c1b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 13:10:56 +0900 Subject: [PATCH 0056/1519] Use the new shader system for 2d drawing. --- libs/video/renderer/glsl/Makefile.am | 6 ++-- libs/video/renderer/glsl/glsl_draw.c | 26 ++++++++++----- libs/video/renderer/glsl/quake2d.frag | 16 --------- libs/video/renderer/glsl/quakeforge.glsl | 42 ++++++++++++++++++++++++ libs/video/renderer/glsl/quakeico.vert | 21 ------------ 5 files changed, 62 insertions(+), 49 deletions(-) delete mode 100644 libs/video/renderer/glsl/quake2d.frag delete mode 100644 libs/video/renderer/glsl/quakeico.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 1daa73c78..933108b6b 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -4,11 +4,9 @@ AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) shader_src= quakeforge.glsl \ - iqm.frag iqm.vert \ - quake2d.frag quakeico.vert + iqm.frag iqm.vert shader_gen= quakeforge.slc \ - iqm.fc iqm.vc \ - quake2d.fc quakeico.vc + iqm.fc iqm.vc glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index a42bc9370..528dc60da 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -72,13 +72,18 @@ typedef struct { float color[4]; } drawvert_t; -static const char quakeicon_vert[] = -#include "quakeico.vc" -; +static const char *twod_vert_effects[] = +{ + "QuakeForge.Vertex.2d", + 0 +}; -static const char quake2d_frag[] = -#include "quake2d.fc" -; +static const char *twod_frag_effects[] = +{ + "QuakeForge.Fragment.palette", + "QuakeForge.Fragment.2d", + 0 +}; static float proj_matrix[16]; @@ -364,6 +369,7 @@ Draw_ClearCache (int phase) void glsl_Draw_Init (void) { + shader_t *vert_shader, *frag_shader; int i; int frag, vert; qpic_t *pic; @@ -377,9 +383,11 @@ glsl_Draw_Init (void) draw_queue = dstring_new (); - vert = GLSL_CompileShaderS ("quakeico.vert", quakeicon_vert, + vert_shader = GLSL_BuildShader (twod_vert_effects); + frag_shader = GLSL_BuildShader (twod_frag_effects); + vert = GLSL_CompileShader ("quakeico.vert", vert_shader, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("quake2d.frag", quake2d_frag, + frag = GLSL_CompileShader ("quake2d.frag", frag_shader, GL_FRAGMENT_SHADER); quake_2d.program = GLSL_LinkProgram ("quake2d", vert, frag); GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.texture); @@ -387,6 +395,8 @@ glsl_Draw_Init (void) GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.matrix); GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.vertex); GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.color); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); draw_scrap = GLSL_CreateScrap (2048, GL_LUMINANCE, 0); diff --git a/libs/video/renderer/glsl/quake2d.frag b/libs/video/renderer/glsl/quake2d.frag deleted file mode 100644 index 730b48e22..000000000 --- a/libs/video/renderer/glsl/quake2d.frag +++ /dev/null @@ -1,16 +0,0 @@ -//precision mediump float; -uniform sampler2D texture; -uniform sampler2D palette; -varying vec4 color; -varying vec2 st; - -void -main (void) -{ - float pix; - - pix = texture2D (texture, st).r; - if (pix == 1.0) - discard; - gl_FragColor = texture2D (palette, vec2 (pix, 0.0)) * color; -} diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 66371483e..ff1fd57a2 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -389,3 +389,45 @@ main (void) discard; gl_FragColor = fogBlend (col); } + +-- Vertex.2d + +uniform mat4 mvp_mat; +attribute vec4 vcolor; +/** Vertex position. + + x, y, s, t + + \a vertex provides the onscreen location at which to draw the icon + (\a x, \a y) and texture coordinate for the icon (\a s=z, \a t=w). +*/ +attribute vec4 vertex; + +varying vec4 color; +varying vec2 st; + +void +main (void) +{ + gl_Position = mvp_mat * vec4 (vertex.xy, 0.0, 1.0); + st = vertex.zw; + color = vcolor; +} + +-- Fragment.2d + +//precision mediump float; +uniform sampler2D texture; +varying vec4 color; +varying vec2 st; + +void +main (void) +{ + float pix; + + pix = texture2D (texture, st).r; + if (pix == 1.0) + discard; + gl_FragColor = palettedColor (pix) * color; +} diff --git a/libs/video/renderer/glsl/quakeico.vert b/libs/video/renderer/glsl/quakeico.vert deleted file mode 100644 index 9f0399c75..000000000 --- a/libs/video/renderer/glsl/quakeico.vert +++ /dev/null @@ -1,21 +0,0 @@ -uniform mat4 mvp_mat; -attribute vec4 vcolor; -/** Vertex position. - - x, y, s, t - - \a vertex provides the onscreen location at which to draw the icon - (\a x, \a y) and texture coordinate for the icon (\a s=z, \a t=w). -*/ -attribute vec4 vertex; - -varying vec4 color; -varying vec2 st; - -void -main (void) -{ - gl_Position = mvp_mat * vec4 (vertex.xy, 0.0, 1.0); - st = vertex.zw; - color = vcolor; -} From 57d21981401d765e5be4e400c3f756708695ccf7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 13:28:35 +0900 Subject: [PATCH 0057/1519] Use the new shader system for iqm models. --- libs/video/renderer/glsl/Makefile.am | 6 +- libs/video/renderer/glsl/glsl_iqm.c | 27 +++-- libs/video/renderer/glsl/iqm.frag | 67 ------------- libs/video/renderer/glsl/iqm.vert | 82 --------------- libs/video/renderer/glsl/quakeforge.glsl | 122 ++++++++++++++++++++++- 5 files changed, 142 insertions(+), 162 deletions(-) delete mode 100644 libs/video/renderer/glsl/iqm.frag delete mode 100644 libs/video/renderer/glsl/iqm.vert diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index 933108b6b..68321ae78 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -3,10 +3,8 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) -shader_src= quakeforge.glsl \ - iqm.frag iqm.vert -shader_gen= quakeforge.slc \ - iqm.fc iqm.vc +shader_src= quakeforge.glsl +shader_gen= quakeforge.slc glsl_src = \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index b8cae10bd..d189a4cbe 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -55,13 +55,19 @@ #include "r_internal.h" -static const char iqm_vert[] = -#include "iqm.vc" -; +static const char *iqm_vert_effects[] = +{ + "QuakeForge.Math.quaternion", + "QuakeForge.Vertex.iqm", + 0 +}; -static const char iqm_frag[] = -#include "iqm.fc" -; +static const char *iqm_frag_effects[] = +{ + "QuakeForge.Fragment.fog", + "QuakeForge.Fragment.iqm", + 0 +}; typedef struct { shaderparam_t position; @@ -136,12 +142,15 @@ static mat4_t iqm_vp; void glsl_R_InitIQM (void) { + shader_t *vert_shader, *frag_shader; int vert; int frag; int i; - vert = GLSL_CompileShaderS ("iqm.vert", iqm_vert, GL_VERTEX_SHADER); - frag = GLSL_CompileShaderS ("iqm.frag", iqm_frag, GL_FRAGMENT_SHADER); + vert_shader = GLSL_BuildShader (iqm_vert_effects); + frag_shader = GLSL_BuildShader (iqm_frag_effects); + vert = GLSL_CompileShader ("iqm.vert", vert_shader, GL_VERTEX_SHADER); + frag = GLSL_CompileShader ("iqm.frag", frag_shader, GL_FRAGMENT_SHADER); iqm_shader.program = GLSL_LinkProgram ("iqm", vert, frag); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.mvp_matrix); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.norm_matrix); @@ -163,6 +172,8 @@ glsl_R_InitIQM (void) GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.texture); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.normalmap); GLSL_ResolveShaderParam (iqm_shader.program, &iqm_shader.fog); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); } static void diff --git a/libs/video/renderer/glsl/iqm.frag b/libs/video/renderer/glsl/iqm.frag deleted file mode 100644 index fd4b64b87..000000000 --- a/libs/video/renderer/glsl/iqm.frag +++ /dev/null @@ -1,67 +0,0 @@ -struct light { - vec4 position; // xyz = pos, w = strength - vec4 color; // rgb. a = ? -}; -uniform sampler2D texture; -uniform sampler2D normalmap; -uniform vec3 ambient; -uniform light lights[8]; -uniform vec4 fog; - -varying vec3 position; -varying vec3 bitangent; -varying vec3 tangent; -varying vec3 normal; -varying vec2 st; -varying vec4 color; - -float -sqr (float x) -{ - return x * x; -} - -vec4 -fogBlend (vec4 color) -{ - float f; - vec4 fog_color = vec4 (fog.rgb, 1.0); - - f = exp (-sqr (fog.a * gl_FragCoord.z / gl_FragCoord.w)); - return vec4 (mix (fog_color.rgb, color.rgb, f), color.a); -} - -vec3 -calc_light (vec3 n, int ind) -{ - vec3 d; - light l = lights[ind]; - float mag; - - d = l.position.xyz - position; - mag = dot (d, n); - mag = max (0.0, mag); - return l.color.rgb * (l.position.w * mag / dot (d, d)); -} - -void -main (void) -{ - mat3 tbn = mat3 (tangent, bitangent, normal); - vec3 norm, l; - vec4 col; - - norm = (texture2D (normalmap, st).xyz - vec3(0.5)) * 2.0; - norm = tbn * norm; - l = ambient; - l += calc_light (norm, 0); - l += calc_light (norm, 1); - l += calc_light (norm, 2); - l += calc_light (norm, 3); - l += calc_light (norm, 4); - l += calc_light (norm, 5); - l += calc_light (norm, 6); - l += calc_light (norm, 7); - col = texture2D (texture, st) * color * vec4 (l, 1.0); - gl_FragColor = fogBlend (col); -} diff --git a/libs/video/renderer/glsl/iqm.vert b/libs/video/renderer/glsl/iqm.vert deleted file mode 100644 index 180212e9f..000000000 --- a/libs/video/renderer/glsl/iqm.vert +++ /dev/null @@ -1,82 +0,0 @@ -uniform mat4 mvp_mat; -uniform mat3 norm_mat; -uniform mat4 bonemats[80]; -attribute vec4 vcolor; -attribute vec4 vweights; -attribute vec4 vbones; -attribute vec4 vtangent; -attribute vec3 vnormal; -attribute vec2 texcoord; -attribute vec3 vposition; - -varying vec3 position; -varying vec3 bitangent; -varying vec3 tangent; -varying vec3 normal; -varying vec2 st; -varying vec4 color; - -vec3 -qmult (vec4 q, vec3 v) -{ - float qs = q.w; - vec3 qv = q.xyz; - vec3 t = cross (qv, v); - return (qs * qs) * v + 2.0 * qs * t + dot (qv, v) * qv + cross (qv, t); -} - -vec3 -dqtrans (vec4 q0, vec4 qe) -{//2.0 * (q0.w * qe.xyz - qe.w * q0.xyz - cross (qe.xyz, q0.xyz)); - float qs = q0.w, Ts = qe.w; - vec3 qv = -q0.xyz, Tv = qe.xyz; - - return 2.0 * (Ts * qv + qs * Tv + cross (Tv, qv)); -} - -void -main (void) -{ - mat4 m; - vec4 q0, qe; - vec3 sh, sc, tr, v, n, t; - - m = bonemats[int (vbones.x)] * vweights.x; - m += bonemats[int (vbones.y)] * vweights.y; - m += bonemats[int (vbones.z)] * vweights.z; - m += bonemats[int (vbones.w)] * vweights.w; -#if 0 - q0 = m[0].yzwx; //swizzle for conversion betwen QF and GL - qe = m[1].yzwx; //swizzle for conversion betwen QF and GL - sh = m[2].xyz; - sc = m[3].xyz; - - // extract translation from dual quaternion - tr = dqtrans (q0, qe); - // apply rotation and translation - v = qmult (q0, vposition) + tr; - // apply shear - v.z += v.y * sh.z + v.x * sh.y; - v.y += v.x * sh.x; - // apply scale - v *= sc; - // rotate normal (won't bother with shear or scale: not super accurate, - // but probably good enough) - n = qmult (q0, vnormal); - // rotate tangent (won't bother with shear or scale: not super accurate, - // but probably good enough) - t = qmult (q0, vtangent.xyz); -#else - mat3 nm = mat3 (m[0].xyz, m[1].xyz, m[2].xyz); - v = (m * vec4 (vposition, 1.0)).xyz; - n = nm * vnormal; - t = nm * vtangent.xyz; -#endif - position = v; - normal = norm_mat * n; - tangent = norm_mat * t; - bitangent = cross (normal, tangent) * vtangent.w; - color = vcolor; - st = texcoord; - gl_Position = mvp_mat * vec4 (position, 1.0); -} diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index ff1fd57a2..8ac479219 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -8,7 +8,7 @@ const float E = 2.71828183; vec3 qmult (vec4 q, vec3 v) { - float qc = q.w; + float qs = q.w; vec3 qv = q.xyz; vec3 t = cross (qv, v); return (qs * qs) * v + 2.0 * qs * t + dot (qv, v) * qv + cross (qv, t); @@ -431,3 +431,123 @@ main (void) discard; gl_FragColor = palettedColor (pix) * color; } + +-- Vertex.iqm + +uniform mat4 mvp_mat; +uniform mat3 norm_mat; +uniform mat4 bonemats[80]; +attribute vec4 vcolor; +attribute vec4 vweights; +attribute vec4 vbones; +attribute vec4 vtangent; +attribute vec3 vnormal; +attribute vec2 texcoord; +attribute vec3 vposition; + +varying vec3 position; +varying vec3 bitangent; +varying vec3 tangent; +varying vec3 normal; +varying vec2 st; +varying vec4 color; + +void +main (void) +{ + mat4 m; + vec4 q0, qe; + vec3 sh, sc, tr, v, n, t; + + m = bonemats[int (vbones.x)] * vweights.x; + m += bonemats[int (vbones.y)] * vweights.y; + m += bonemats[int (vbones.z)] * vweights.z; + m += bonemats[int (vbones.w)] * vweights.w; +#if 0 + q0 = m[0].yzwx; //swizzle for conversion betwen QF and GL + qe = m[1].yzwx; //swizzle for conversion betwen QF and GL + sh = m[2].xyz; + sc = m[3].xyz; + + // extract translation from dual quaternion + tr = dqtrans (q0, qe); + // apply rotation and translation + v = qmult (q0, vposition) + tr; + // apply shear + v.z += v.y * sh.z + v.x * sh.y; + v.y += v.x * sh.x; + // apply scale + v *= sc; + // rotate normal (won't bother with shear or scale: not super accurate, + // but probably good enough) + n = qmult (q0, vnormal); + // rotate tangent (won't bother with shear or scale: not super accurate, + // but probably good enough) + t = qmult (q0, vtangent.xyz); +#else + mat3 nm = mat3 (m[0].xyz, m[1].xyz, m[2].xyz); + v = (m * vec4 (vposition, 1.0)).xyz; + n = nm * vnormal; + t = nm * vtangent.xyz; +#endif + position = v; + normal = norm_mat * n; + tangent = norm_mat * t; + bitangent = cross (normal, tangent) * vtangent.w; + color = vcolor; + st = texcoord; + gl_Position = mvp_mat * vec4 (position, 1.0); +} + +-- Fragment.iqm + +struct light { + vec4 position; // xyz = pos, w = strength + vec4 color; // rgb. a = ? +}; +uniform sampler2D texture; +uniform sampler2D normalmap; +uniform vec3 ambient; +uniform light lights[8]; + +varying vec3 position; +varying vec3 bitangent; +varying vec3 tangent; +varying vec3 normal; +varying vec2 st; +varying vec4 color; + +vec3 +calc_light (vec3 n, int ind) +{ + vec3 d; + light l = lights[ind]; + float mag; + + d = l.position.xyz - position; + mag = dot (d, n); + mag = max (0.0, mag); + return l.color.rgb * (l.position.w * mag / dot (d, d)); +} + +void +main (void) +{ + mat3 tbn = mat3 (tangent, bitangent, normal); + vec3 norm, l; + vec4 col; + + norm = (texture2D (normalmap, st).xyz - vec3(0.5)) * 2.0; + norm = tbn * norm; + l = ambient; + l += calc_light (norm, 0); + l += calc_light (norm, 1); + l += calc_light (norm, 2); + l += calc_light (norm, 3); + l += calc_light (norm, 4); + l += calc_light (norm, 5); + l += calc_light (norm, 6); + l += calc_light (norm, 7); + col = texture2D (texture, st) * color * vec4 (l, 1.0); + gl_FragColor = fogBlend (col); +} From a5db0b1a6583e7a3bf370c1d91fbfd4526e0e4cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 13:36:45 +0900 Subject: [PATCH 0058/1519] Remove the now unnecessary GLSL_CompileShaderS(). Now that the transition to using shader effects is comlete, there's no need for the wrapper. --- include/QF/GLSL/qf_vid.h | 1 - libs/video/renderer/glsl/vid_common_glsl.c | 9 --------- 2 files changed, 10 deletions(-) diff --git a/include/QF/GLSL/qf_vid.h b/include/QF/GLSL/qf_vid.h index 1dd324f05..57f6e5313 100644 --- a/include/QF/GLSL/qf_vid.h +++ b/include/QF/GLSL/qf_vid.h @@ -48,7 +48,6 @@ extern int glsl_colormap; void GLSL_Init_Common (void); int GLSL_CompileShader (const char *name, const shader_t *shader, int type); -int GLSL_CompileShaderS (const char *name, const char *src, int type); int GLSL_LinkProgram (const char *name, int vert, int frag); int GLSL_ResolveShaderParam (int program, shaderparam_t *param); void GLSL_DumpAttribArrays (void); diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 9f46fdc9c..d684fd4ff 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -217,15 +217,6 @@ GLSL_CompileShader (const char *name, const shader_t *shader, int type) return sid; } -int -GLSL_CompileShaderS (const char *name, const char *src, int type) -{ - const char *shader_src = src; - const char *shader_name = "wrapped"; - shader_t shader = {1, &shader_src, &shader_name}; - return GLSL_CompileShader (name, &shader, type); -} - static const char * type_name (GLenum type) { From 4d59282641bdc97ff5420caed2317ce755d8fcd6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Jan 2014 13:49:06 +0900 Subject: [PATCH 0059/1519] Find the remaining vertex attribute order issues. I hope. I do need to figure out why I made sprite blend an attribute rather than a uniform. --- libs/video/renderer/glsl/quakeforge.glsl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 8ac479219..e346b31af 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -268,7 +268,6 @@ main (void) -- Vertex.particle.point uniform mat4 mvp_mat; -attribute float vcolor; /** Vertex position. x, y, z, c @@ -276,6 +275,7 @@ attribute float vcolor; c is the color of the point. */ attribute vec3 vertex; +attribute float vcolor; varying float color; @@ -290,8 +290,6 @@ main (void) -- Vertex.particle.textured uniform mat4 mvp_mat; -attribute vec4 vcolor; -attribute vec2 vst; /** Vertex position. x, y, z, c @@ -299,6 +297,8 @@ attribute vec2 vst; c is the color of the point. */ attribute vec3 vertex; +attribute vec2 vst; +attribute vec4 vcolor; varying vec4 color; varying vec2 st; @@ -342,10 +342,10 @@ main (void) -- Vertex.sprite uniform mat4 mvp_mat; -attribute float vblend; -attribute vec4 vcolora, vcolorb; -attribute vec4 uvab; ///< ua va ub vb attribute vec3 vertexa, vertexb; +attribute vec4 uvab; ///< ua va ub vb +attribute float vblend; //FIXME why is this not a uniform? +attribute vec4 vcolora, vcolorb; varying float blend; varying vec4 colora, colorb; @@ -393,7 +393,6 @@ main (void) -- Vertex.2d uniform mat4 mvp_mat; -attribute vec4 vcolor; /** Vertex position. x, y, s, t @@ -402,6 +401,7 @@ attribute vec4 vcolor; (\a x, \a y) and texture coordinate for the icon (\a s=z, \a t=w). */ attribute vec4 vertex; +attribute vec4 vcolor; varying vec4 color; varying vec2 st; From 6910c50a4356fffa350ba52bfa6d112abcb69069 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 10:09:05 +0900 Subject: [PATCH 0060/1519] Clean up the #ifdef mess in _QFS_FOpenFile With proper initialization, only the one chunk of #ifdefs is needed. Now the code is much easier to read. --- libs/util/quakefs.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index b864dfb74..8c893d600 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -871,12 +871,8 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, { searchpath_t *search; char *path; -#ifdef HAVE_VORBIS - char *oggfilename; -#endif -#ifdef HAVE_ZLIB - char *gzfilename; -#endif + char *oggfilename = 0; + char *gzfilename = 0; // make sure they're not trying to do weird stuff with our private files path = QFS_CompressPath (filename); @@ -893,8 +889,6 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, QFS_StripExtension (path, oggfilename); strncat (oggfilename, ".ogg", sizeof (oggfilename) - strlen (oggfilename) - 1); - } else { - oggfilename = 0; } #endif #ifdef HAVE_ZLIB @@ -904,16 +898,13 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, // search through the path, one element at a time for (search = qfs_searchpaths; search; search = search->next) { -#ifdef HAVE_VORBIS //NOTE gzipped oggs not supported if (oggfilename && open_file (search, oggfilename, gzfile, foundname, false) != -1) goto ok; -#endif -#ifdef HAVE_ZLIB - if (open_file (search, gzfilename, gzfile, foundname, zip) != -1) + if (gzfilename + && open_file (search, gzfilename, gzfile, foundname, zip) != -1) goto ok; -#endif if (open_file (search, path, gzfile, foundname, zip) != -1) goto ok; } From f05c7179c3423b9bf35beae9f8887d204a6b292f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 13:41:30 +0900 Subject: [PATCH 0061/1519] Split up the search paths into vpath chunks. A vpath is the union of all locations searched for a file in a single gamedir (eg, shadows, id1 etc). This is a necessary step to preventing problems like id1/maps/start.lit being used for shadows/maps/start.bsp. However, QFS_FilelistFill still needs to be reworked as it does not compile yet (testing was done with a gutted QFS_FilelistFill). --- libs/util/quakefs.c | 202 ++++++++++++++++++++++++++++++++------------ 1 file changed, 146 insertions(+), 56 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 8c893d600..b73b9b6bc 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -74,7 +74,7 @@ #include #include "qfalloca.h" - +#include "QF/alloc.h" #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/dstring.h" @@ -136,7 +136,26 @@ typedef struct searchpath_s { struct searchpath_s *next; } searchpath_t; -static searchpath_t *qfs_searchpaths; +/** Represent a single game directory. + + A vpath is the union of all locations searched for a single gamedir. This + includes all pak files in the gamedir in the user's directory, the + filesystem in the user's gamedir, then all pak files in the share + game directory, and finally share's gamedir filesystem. + + The purpose is to enable searches to be limited to a single gamedir or to + not search past a certain gamedir. +*/ +typedef struct vpath_s { + char *name; // usually the gamedir name + searchpath_t *user; + searchpath_t *share; + struct vpath_s *next; +} vpath_t; + +static searchpath_t *free_searchpaths; +static vpath_t *free_vpaths; +static vpath_t *qfs_vpaths; //QFS @@ -145,7 +164,7 @@ typedef struct qfs_var_s { char *val; } qfs_var_t; -static void qfs_add_gamedir (const char *dir); +static void qfs_add_gamedir (vpath_t *vpath, const char *dir); VISIBLE gamedir_t *qfs_gamedir; static plitem_t *qfs_gd_plist; @@ -213,6 +232,55 @@ static gamedir_callback_t **gamedir_callbacks; static int num_gamedir_callbacks; static int max_gamedir_callbacks; +static searchpath_t * +new_searchpath (void) +{ + searchpath_t *searchpath; + ALLOC (16, searchpath_t, searchpaths, searchpath); + return searchpath; +} + +static void +delete_searchpath (searchpath_t *searchpath) +{ + if (searchpath->pack) { + Qclose (searchpath->pack->handle); + free (searchpath->pack->files); + free (searchpath->pack); + } + if (searchpath->filename) + free (searchpath->filename); + FREE (searchpaths, searchpath); +} + +static vpath_t * +new_vpath (void) +{ + vpath_t *vpath; + ALLOC (16, vpath_t, vpaths, vpath); + return vpath; +} + +static void +delete_vpath (vpath_t *vpath) +{ + searchpath_t *next; + + if (vpath->name) + free (vpath->name); + while (vpath->user) { + next = vpath->user->next; + delete_searchpath (vpath->user); + vpath->user = next; + } + while (vpath->share) { + next = vpath->share->next; + delete_searchpath (vpath->share); + vpath->share = next; + } + FREE (vpaths, vpath); +} + static const char * qfs_var_get_key (const void *_v, void *unused) { @@ -448,18 +516,22 @@ qfs_process_path (const char *path, const char *gamedir) { const char *e = path + strlen (path); const char *s = e; - dstring_t *dir = dstring_new (); + char *dir; + vpath_t *vpath; while (s >= path) { while (s != path && s[-1] !=':') s--; if (s != e) { - dsprintf (dir, "%.*s", (int) (e - s), s); - qfs_add_gamedir (dir->str); + dir = nva ("%.*s", (int) (e - s), s); + vpath = new_vpath (); + vpath->name = dir; + qfs_add_gamedir (vpath, dir); + vpath->next = qfs_vpaths; + qfs_vpaths = vpath; } e = --s; } - dstring_delete (dir); } static void @@ -497,20 +569,10 @@ qfs_build_gamedir (const char **list) free (qfs_gamedir); } - while (qfs_searchpaths) { - searchpath_t *next; - - if (qfs_searchpaths->pack) { - Qclose (qfs_searchpaths->pack->handle); - free (qfs_searchpaths->pack->files); - free (qfs_searchpaths->pack); - } - if (qfs_searchpaths->filename) - free (qfs_searchpaths->filename); - - next = qfs_searchpaths->next; - free (qfs_searchpaths); - qfs_searchpaths = next; + while (qfs_vpaths) { + vpath_t *next = qfs_vpaths->next; + delete_vpath (qfs_vpaths); + qfs_vpaths = next; } for (j = 0; list[j]; j++) @@ -688,19 +750,30 @@ QFS_FileBase (const char *in) return out; } +static void +qfs_path_print (searchpath_t *sp) +{ + if (sp->pack) { + Sys_Printf ("%s (%i files)\n", sp->pack->filename, sp->pack->numfiles); + } else { + Sys_Printf ("%s\n", sp->filename); + } +} static void qfs_path_f (void) { - searchpath_t *s; + vpath_t *vp; + searchpath_t *sp; Sys_Printf ("Current search path:\n"); - for (s = qfs_searchpaths; s; s = s->next) { - if (s->pack) - Sys_Printf ("%s (%i files)\n", s->pack->filename, - s->pack->numfiles); - else - Sys_Printf ("%s\n", s->filename); + for (vp = qfs_vpaths; vp; vp = vp->next) { + for (sp = vp->user; sp; sp = sp->next) { + qfs_path_print (sp); + } + for (sp = vp->share; sp; sp = sp->next) { + qfs_path_print (sp); + } } } @@ -865,10 +938,28 @@ open_file (searchpath_t *search, const char *filename, QFile **gzfile, return -1; } +static int +qfs_check_path (searchpath_t *search, const char *oggfilename, + const char *gzfilename, const char *path, QFile **gzfile, + dstring_t *foundname, int zip) +{ + //NOTE gzipped oggs not supported + if (oggfilename + && open_file (search, oggfilename, gzfile, foundname, false) != -1) + return 0; + if (gzfilename + && open_file (search, gzfilename, gzfile, foundname, zip) != -1) + return 0; + if (open_file (search, path, gzfile, foundname, zip) != -1) + return 0; + return -1; +} + VISIBLE int _QFS_FOpenFile (const char *filename, QFile **gzfile, dstring_t *foundname, int zip) { + vpath_t *vpath; searchpath_t *search; char *path; char *oggfilename = 0; @@ -897,16 +988,17 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, #endif // search through the path, one element at a time - for (search = qfs_searchpaths; search; search = search->next) { - //NOTE gzipped oggs not supported - if (oggfilename - && open_file (search, oggfilename, gzfile, foundname, false) != -1) - goto ok; - if (gzfilename - && open_file (search, gzfilename, gzfile, foundname, zip) != -1) - goto ok; - if (open_file (search, path, gzfile, foundname, zip) != -1) - goto ok; + for (vpath = qfs_vpaths; vpath; vpath = vpath->next) { + for (search = vpath->user; search; search = search->next) { + if (qfs_check_path (search, oggfilename, gzfilename, path, gzfile, + foundname, zip) != -1) + goto ok; + } + for (search = vpath->share; search; search = search->next) { + if (qfs_check_path (search, oggfilename, gzfilename, path, gzfile, + foundname, zip) != -1) + goto ok; + } } Sys_MaskPrintf (SYS_FS_NF, "FindFile: can't find %s\n", filename); @@ -1061,9 +1153,9 @@ qfs_file_sort (char **os1, char **os2) } static void -qfs_load_gamedir (const char *dir) +qfs_load_gamedir (searchpath_t **searchpath, const char *dir) { - searchpath_t *search; + searchpath_t *sp; pack_t *pak; DIR *dir_ptr; struct dirent *dirent; @@ -1117,11 +1209,10 @@ qfs_load_gamedir (const char *dir) if (!pak) { Sys_Error ("Bad pakfile %s!!", pakfiles[i]); } else { - search = malloc (sizeof (searchpath_t)); - search->filename = 0; - search->pack = pak; - search->next = qfs_searchpaths; - qfs_searchpaths = search; + sp = new_searchpath (); + sp->pack = pak; + sp->next = *searchpath; + *searchpath = sp; } } @@ -1138,23 +1229,22 @@ qfs_load_gamedir (const char *dir) pak1.pak ... */ static void -qfs_add_dir (const char *dir) +qfs_add_dir (searchpath_t **searchpath, const char *dir) { - searchpath_t *search; + searchpath_t *sp; // add the directory to the search path - search = malloc (sizeof (searchpath_t)); - search->filename = strdup (dir); - search->pack = 0; - search->next = qfs_searchpaths; - qfs_searchpaths = search; + sp = new_searchpath (); + sp->filename = strdup (dir); + sp->next = *searchpath; + *searchpath = sp; // add any pak files in the format pak0.pak pak1.pak, ... - qfs_load_gamedir (dir); + qfs_load_gamedir (searchpath, dir); } static void -qfs_add_gamedir (const char *dir) +qfs_add_gamedir (vpath_t *vpath, const char *dir) { const char *e; const char *s; @@ -1181,7 +1271,7 @@ qfs_add_gamedir (const char *dir) Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n", f_dir->str); - qfs_add_dir (f_dir->str); + qfs_add_dir (&vpath->share, f_dir->str); } } e = --s; @@ -1189,7 +1279,7 @@ qfs_add_gamedir (const char *dir) qfs_expand_userpath (f_dir, dir); Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n", f_dir->str); - qfs_add_dir (f_dir->str); + qfs_add_dir (&vpath->user, f_dir->str); dstring_delete (f_dir); dstring_delete (s_dir); From 098821e35d2cc94b3ddd30b7a4e98695a1c2c291 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 14:07:57 +0900 Subject: [PATCH 0062/1519] Fix QFS_FilelistFill to work with vpaths. --- libs/util/quakefs.c | 66 ++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index b73b9b6bc..f96361a0e 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1587,45 +1587,57 @@ QFS_FilelistAdd (filelist_t *filelist, const char *fname, const char *ext) filelist->list[filelist->count++] = str; } +static void +qfs_filelistfill_do (filelist_t *list, const searchpath_t *search, const char *cp, const char *ext, int strip) +{ + const char *separator = "/"; + + if (*cp && cp[strlen (cp) - 1] == '/') + separator = ""; + + if (search->pack) { + int i; + pack_t *pak = search->pack; + + for (i = 0; i < pak->numfiles; i++) { + char *name = pak->files[i].name; + if (!fnmatch (va("%s%s*.%s", cp, separator, ext), name, + FNM_PATHNAME) + || !fnmatch (va("%s%s*.%s.gz", cp, separator, ext), name, + FNM_PATHNAME)) + QFS_FilelistAdd (list, name, strip ? ext : 0); + } + } else { + DIR *dir_ptr; + struct dirent *dirent; + + dir_ptr = opendir (va ("%s/%s", search->filename, cp)); + if (!dir_ptr) + return; + while ((dirent = readdir (dir_ptr))) + if (!fnmatch (va("*.%s", ext), dirent->d_name, 0) + || !fnmatch (va("*.%s.gz", ext), dirent->d_name, 0)) + QFS_FilelistAdd (list, dirent->d_name, strip ? ext : 0); + closedir (dir_ptr); + } +} + VISIBLE void QFS_FilelistFill (filelist_t *list, const char *path, const char *ext, int strip) { + vpath_t *vpath; searchpath_t *search; - DIR *dir_ptr; - struct dirent *dirent; char *cpath, *cp; - const char *separator = "/"; if (strchr (ext, '/') || strchr (ext, '\\')) return; cp = cpath = QFS_CompressPath (path); - if (*cp && cp[strlen (cp) - 1] == '/') - separator = ""; - for (search = qfs_searchpaths; search != NULL; search = search->next) { - if (search->pack) { - int i; - pack_t *pak = search->pack; - - for (i = 0; i < pak->numfiles; i++) { - char *name = pak->files[i].name; - if (!fnmatch (va("%s%s*.%s", cp, separator, ext), name, - FNM_PATHNAME) - || !fnmatch (va("%s%s*.%s.gz", cp, separator, ext), name, - FNM_PATHNAME)) - QFS_FilelistAdd (list, name, strip ? ext : 0); - } - } else { - dir_ptr = opendir (va ("%s/%s", search->filename, cp)); - if (!dir_ptr) - continue; - while ((dirent = readdir (dir_ptr))) - if (!fnmatch (va("*.%s", ext), dirent->d_name, 0) - || !fnmatch (va("*.%s.gz", ext), dirent->d_name, 0)) - QFS_FilelistAdd (list, dirent->d_name, strip ? ext : 0); - closedir (dir_ptr); + for (vpath = qfs_vpaths; vpath; vpath = vpath->next) { + for (search = vpath->user; search; search = search->next) { + qfs_filelistfill_do (list, search, cp, ext, strip); } } free (cpath); From 8bc2f7f6df72aafeb2e9401991d193c0a4cd4f13 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 14:35:19 +0900 Subject: [PATCH 0063/1519] Print the vpath name when dumping the paths. --- libs/util/quakefs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index f96361a0e..a3f956195 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -768,6 +768,7 @@ qfs_path_f (void) Sys_Printf ("Current search path:\n"); for (vp = qfs_vpaths; vp; vp = vp->next) { + Sys_Printf ("%s\n", vp->name); for (sp = vp->user; sp; sp = sp->next) { qfs_path_print (sp); } From 6b87ddbb7c0e14a0ce84875ebdc33173fe2c1945 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 18:09:02 +0900 Subject: [PATCH 0064/1519] Add QFS_FindFile. QFS_FindFile's search can be constrained to begin or end at a certain vpath. --- include/QF/quakefs.h | 35 +++++++++++ libs/util/quakefs.c | 135 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 2 deletions(-) diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index 2579d78e0..dad69fc23 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -67,6 +67,17 @@ typedef struct gamedir_s { } dir; } gamedir_t; +typedef struct vpath_s vpath_t; + +typedef struct findfile_s { + const vpath_t *vpath; ///< vpath in which file was found + qboolean in_pak; ///< if true, path refers to a pak file rather + ///< than a directory + const char *realname; ///< the name of the file as found (may have + ///< .gz appended, or .ogg substituded for + ///< .wav) does not include the path +} findfile_t; + /** Cached information about the current game directory. \see \ref dirconf. */ extern gamedir_t *qfs_gamedir; @@ -121,6 +132,30 @@ void QFS_Init (const char *game); */ void QFS_Gamedir (const char *gamedir); +/** Search for a file in the quake file-system. + + The search will begin in the \a start vpath and end in the \a end vpath. + If \a start is null, the search will begin in the vpath specified by + qfs_vpaths (ie, the first directory in the \c Path attribute + (\ref dirconf). If \a end is null, the search will continue to the end + of the list of vpaths. If \a start and \a end are the same (and non-null), + then only the one vpath will be searched. + + \note All search paths in a vpath will be searched. This keeps \QF's + directory system transparent. + + \note It is a fatal error for \a end to be non-null but not in the list + of vpaths. + + \param fname The name of the file to be searched for. + \param start The first vpath (gamedir) to search. + \param start The last vpath (gamedir) to search. + \return Pointer to the findfile_t record indicating the location + of the file, or null if the file was not found. +*/ +findfile_t *QFS_FindFile (const char *fname, const vpath_t *start, + const vpath_t *end); + /** Open a file from within the user directory. If \a path attempts to leave the user directory, this function sets diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index a3f956195..6168abf4c 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -146,12 +146,20 @@ typedef struct searchpath_s { The purpose is to enable searches to be limited to a single gamedir or to not search past a certain gamedir. */ -typedef struct vpath_s { +struct vpath_s { // typedef to vpath_t is in quakefs.h char *name; // usually the gamedir name searchpath_t *user; searchpath_t *share; struct vpath_s *next; -} vpath_t; +}; + +typedef struct int_findfile_s { + findfile_t ff; + struct pack_s *pack; + dpackfile_t *packfile; + const char *path; + int fname_index; +} int_findfile_t; static searchpath_t *free_searchpaths; static vpath_t *free_vpaths; @@ -792,6 +800,129 @@ QFS_WriteFile (const char *filename, const void *data, int len) Qclose (f); } +static int_findfile_t * +qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, + const char **fnames) +{ + static int_findfile_t found; + const char **fn; + + found.ff.vpath = 0; + found.ff.in_pak = false; + found.pack = 0; + found.packfile = 0; + found.fname_index = 0; + if (found.ff.realname) { + free ((char *) found.ff.realname); + found.ff.realname = 0; + } + if (found.path) { + free ((char *) found.path); + found.path = 0; + } + // is the element a pak file? + if (sp->pack) { + dpackfile_t *packfile; + + for (fn = fnames; *fn; fn++) { + packfile = pack_find_file (sp->pack, *fn); + if (packfile) { + break; + } + } + if (packfile) { + Sys_MaskPrintf (SYS_FS_F, "PackFile: %s : %s\n", + sp->pack->filename, packfile->name); + found.ff.vpath = vpath; + found.ff.in_pak = true; + found.ff.realname = strdup (*fn); + found.pack = sp->pack; + found.packfile = packfile; + found.fname_index = fn - fnames; + found.path = strdup (sp->pack->filename); + return &found; + } + } else { + // check a file in the directory tree + dstring_t *path = dstring_new (); + + for (fn = fnames; *fn; fn++) { + if (qfs_expand_path (path, sp->filename, *fn, 1) == 0) { + if (Sys_FileTime (path->str) == -1) { + dstring_delete (path); + return 0; + } + + Sys_MaskPrintf (SYS_FS_F, "FindFile: %s\n", path->str); + + found.ff.vpath = vpath; + found.ff.in_pak = false; + found.ff.realname = strdup (*fn); + found.path = strdup (path->str); + found.fname_index = fn - fnames; + return &found; + } + } + dstring_delete (path); + } + return 0; +} + +static int_findfile_t * +qfs_findfile (const char **fnames, const vpath_t *start, const vpath_t *end) +{ + const vpath_t *vp; + searchpath_t *sp; + int_findfile_t *found; + + if (!start) { + start = qfs_vpaths; + } + if (end) { + for (vp = start; vp; vp = vp->next) { + if (vp == end) { + break; + } + } + if (!vp) { + Sys_Error ("QFS_FindFile: end vpath not in search list"); + } + end = end->next; + } + for (vp = start; vp && vp != end; vp = vp->next) { + for (sp = vp->user; sp; sp = sp->next) { + found = qfs_findfile_search (vp, sp, fnames); + if (found) { + return found; + } + } + for (sp = vp->share; sp; sp = sp->next) { + found = qfs_findfile_search (vp, sp, fnames); + if (found) { + return found; + } + } + } + // file not found + return 0; +} + +VISIBLE findfile_t * +QFS_FindFile (const char *fname, const vpath_t *start, const vpath_t *end) +{ + int_findfile_t *found; + const char *fname_list[2]; + + fname_list[0] = fname; + fname_list[1] = 0; + + found = qfs_findfile (fname_list, start, end); + if (found) { + return &found->ff; + } + return 0; +} + static QFile * qfs_openread (const char *path, int offs, int len, int zip) { From 40206904baf82740d61c1d5ac74c05fb804bee10 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 18:12:09 +0900 Subject: [PATCH 0065/1519] Reimplement _QFS_FOpenFile using QFS_FindFile's internals. _QFS_FOpenFile does a full search, however. --- libs/util/quakefs.c | 117 ++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 81 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 6168abf4c..ea8e9bd79 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1019,83 +1019,34 @@ VISIBLE int file_from_pak; // global indicating file came from pack file ZOID Sets qfs_filesize and one of handle or file */ -static int -open_file (searchpath_t *search, const char *filename, QFile **gzfile, - dstring_t *foundname, int zip) +static void +open_file (int_findfile_t *found, QFile **gzfile, dstring_t *foundname, + int zip) { - file_from_pak = 0; - - // is the element a pak file? - if (search->pack) { - dpackfile_t *packfile; - - packfile = pack_find_file (search->pack, filename); - if (packfile) { - Sys_MaskPrintf (SYS_FS_F, "PackFile: %s : %s\n", - search->pack->filename, packfile->name); - // open a new file on the pakfile - if (foundname) { - dstring_clearstr (foundname); - dstring_appendstr (foundname, packfile->name); - } - *gzfile = qfs_openread (search->pack->filename, packfile->filepos, - packfile->filelen, zip); - file_from_pak = 1; - return qfs_filesize; - } - } else { - // check a file in the directory tree - dstring_t *netpath = dstring_new (); - - if (qfs_expand_path (netpath, search->filename, filename, 1) == 0) { - if (foundname) { - dstring_clearstr (foundname); - dstring_appendstr (foundname, filename); - } - if (Sys_FileExists (netpath->str) == -1) { - dstring_delete (netpath); - return -1; - } - - Sys_MaskPrintf (SYS_FS_F, "FindFile: %s\n", netpath->str); - - *gzfile = qfs_openread (netpath->str, -1, -1, zip); - dstring_delete (netpath); - return qfs_filesize; - } - dstring_delete (netpath); - return -1; + file_from_pak = found->ff.in_pak; + if (foundname) { + dstring_copystr (foundname, found->ff.realname); + } + if (found->ff.in_pak) { + *gzfile = qfs_openread (found->pack->filename, + found->packfile->filepos, + found->packfile->filelen, zip); + } else { + *gzfile = qfs_openread (found->path, -1, -1, zip); } - - return -1; -} - -static int -qfs_check_path (searchpath_t *search, const char *oggfilename, - const char *gzfilename, const char *path, QFile **gzfile, - dstring_t *foundname, int zip) -{ - //NOTE gzipped oggs not supported - if (oggfilename - && open_file (search, oggfilename, gzfile, foundname, false) != -1) - return 0; - if (gzfilename - && open_file (search, gzfilename, gzfile, foundname, zip) != -1) - return 0; - if (open_file (search, path, gzfile, foundname, zip) != -1) - return 0; - return -1; } VISIBLE int _QFS_FOpenFile (const char *filename, QFile **gzfile, dstring_t *foundname, int zip) { - vpath_t *vpath; - searchpath_t *search; + int_findfile_t *found; char *path; char *oggfilename = 0; char *gzfilename = 0; + const char *fnames[4]; + int zip_flags[3]; + int ind; // make sure they're not trying to do weird stuff with our private files path = QFS_CompressPath (filename); @@ -1106,31 +1057,38 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, goto error; } + ind = 0; #ifdef HAVE_VORBIS if (strequal (".wav", QFS_FileExtension (path))) { oggfilename = alloca (strlen (path) + 1); QFS_StripExtension (path, oggfilename); strncat (oggfilename, ".ogg", sizeof (oggfilename) - strlen (oggfilename) - 1); + fnames[ind] = oggfilename; + zip_flags[ind] = 0; + ind++; } #endif #ifdef HAVE_ZLIB gzfilename = alloca (strlen (path) + 3 + 1); sprintf (gzfilename, "%s.gz", path); + fnames[ind] = gzfilename; + zip_flags[ind] = zip; + ind++; #endif - // search through the path, one element at a time - for (vpath = qfs_vpaths; vpath; vpath = vpath->next) { - for (search = vpath->user; search; search = search->next) { - if (qfs_check_path (search, oggfilename, gzfilename, path, gzfile, - foundname, zip) != -1) - goto ok; - } - for (search = vpath->share; search; search = search->next) { - if (qfs_check_path (search, oggfilename, gzfilename, path, gzfile, - foundname, zip) != -1) - goto ok; - } + fnames[ind] = path; + zip_flags[ind] = zip; + ind++; + + fnames[ind] = 0; + + found = qfs_findfile (fnames, 0, 0); + + if (found) { + open_file (found, gzfile, foundname, zip_flags[found->fname_index]); + free(path); + return qfs_filesize; } Sys_MaskPrintf (SYS_FS_NF, "FindFile: can't find %s\n", filename); @@ -1139,9 +1097,6 @@ error: qfs_filesize = -1; free (path); return -1; -ok: - free(path); - return qfs_filesize; } VISIBLE int From 4b18501b0073685482ce7dfa5b6ab23ed472ca9c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 21:04:16 +0900 Subject: [PATCH 0066/1519] Fix an uninitialized variable. --- libs/util/quakefs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index ea8e9bd79..56ec1f9ac 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -822,7 +822,7 @@ qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, } // is the element a pak file? if (sp->pack) { - dpackfile_t *packfile; + dpackfile_t *packfile = 0; for (fn = fnames; *fn; fn++) { packfile = pack_find_file (sp->pack, *fn); From 5560696a65c748a396c1458398e9a3838f06e88a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Jan 2013 21:09:16 +0900 Subject: [PATCH 0067/1519] Fix some unused variables. --- libs/util/quakefs.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 56ec1f9ac..34729f08f 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1042,8 +1042,6 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, { int_findfile_t *found; char *path; - char *oggfilename = 0; - char *gzfilename = 0; const char *fnames[4]; int zip_flags[3]; int ind; @@ -1060,6 +1058,7 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, ind = 0; #ifdef HAVE_VORBIS if (strequal (".wav", QFS_FileExtension (path))) { + char *oggfilename; oggfilename = alloca (strlen (path) + 1); QFS_StripExtension (path, oggfilename); strncat (oggfilename, ".ogg", @@ -1070,11 +1069,14 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile, } #endif #ifdef HAVE_ZLIB - gzfilename = alloca (strlen (path) + 3 + 1); - sprintf (gzfilename, "%s.gz", path); - fnames[ind] = gzfilename; - zip_flags[ind] = zip; - ind++; + { + char *gzfilename; + gzfilename = alloca (strlen (path) + 3 + 1); + sprintf (gzfilename, "%s.gz", path); + fnames[ind] = gzfilename; + zip_flags[ind] = zip; + ind++; + } #endif fnames[ind] = path; From 82ded3fbe5be3011305fed4cadc3659a9de29b42 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Nov 2013 12:28:13 +0900 Subject: [PATCH 0068/1519] Fix some bitrot resulting from a rebase. --- libs/util/quakefs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 34729f08f..9b51e2d32 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -161,8 +161,8 @@ typedef struct int_findfile_s { int fname_index; } int_findfile_t; -static searchpath_t *free_searchpaths; -static vpath_t *free_vpaths; +static searchpath_t *searchpaths_freelist; +static vpath_t *vpaths_freelist; static vpath_t *qfs_vpaths; //QFS @@ -848,7 +848,7 @@ qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, for (fn = fnames; *fn; fn++) { if (qfs_expand_path (path, sp->filename, *fn, 1) == 0) { - if (Sys_FileTime (path->str) == -1) { + if (Sys_FileExists (path->str) == -1) { dstring_delete (path); return 0; } From cb448f21b5a7b89a0bd2e133330487d15a6e9495 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Nov 2013 12:53:51 +0900 Subject: [PATCH 0069/1519] Update for doxygen 1.8.5 --- doc/quakeforge.dox.conf.in | 2314 ++++++++++++++++++++++-------------- 1 file changed, 1401 insertions(+), 913 deletions(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 0157cff40..f72ee72a5 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -1,110 +1,119 @@ -# Doxyfile 1.8.1.1 +# Doxyfile 1.8.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored. +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = @PACKAGE_NAME@ -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. PROJECT_NUMBER = @PACKAGE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. PROJECT_LOGO = -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. OUTPUT_DIRECTORY = doxygen -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- +# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, +# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# Turkish, Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO @@ -112,169 +121,204 @@ ALWAYS_DETAILED_SEC = NO # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = YES -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = @TOPSRC@ -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. STRIP_FROM_INC_PATH = @TOPSRC@/include -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. ALIASES = QF=QuakeForge # This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. TCL_SUBST = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. EXTENSION_MAPPING = -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. MARKDOWN_SUPPORT = YES +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES @@ -282,67 +326,61 @@ IDL_PROPERTY_SUPPORT = YES # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. INLINE_GROUPED_CLASSES = NO -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. INLINE_SIMPLE_STRUCTS = NO -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 @@ -351,309 +389,349 @@ LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. EXTRACT_PACKAGE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = @STATIC_DOC@ -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = NO -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = YES -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = NO -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. FORCE_LOCAL_INCLUDES = NO -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: NO. SORT_BRIEF_DOCS = YES -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. SORT_MEMBERS_CTORS_1ST = YES -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = YES -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. GENERATE_TESTLIST = NO -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. LAYOUT_FILE = -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. INPUT = @TOPSRC@/include \ @TOPSRC@/libs \ @@ -665,34 +743,37 @@ INPUT = @TOPSRC@/include \ @TOPSRC@/INSTALL # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. FILE_PATTERNS = *.c \ *.h \ *.dox -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# # Note that relative paths are relative to the directory from which doxygen is # run. @@ -715,14 +796,16 @@ EXCLUDE = @TOPSRC@/tools/qfcc/source/qc-lex.c \ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = @@ -731,33 +814,36 @@ EXCLUDE_PATTERNS = # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). EXAMPLE_PATH = @TOPSRC@/doc \ @TOPSRC@/doc/progs # If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). IMAGE_PATH = @TOPSRC@/doc \ @builddir@ \ @@ -766,724 +852,1046 @@ IMAGE_PATH = @TOPSRC@/doc \ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = NO -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = NO -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 4 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# style sheet in the HTML output directory as well, or it will be erased! +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = @TOPSRC@/doc/doxygen.css +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 228 -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 67 -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 100 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = YES # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. -# However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /