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 {