]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
process_condition function used by parse_if - need to still add it to loops
authorWolfgang Bumiller <blub@speed.at>
Thu, 20 Dec 2012 18:51:30 +0000 (19:51 +0100)
committerWolfgang Bumiller <blub@speed.at>
Thu, 20 Dec 2012 18:51:30 +0000 (19:51 +0100)
ast.c
parser.c

diff --git a/ast.c b/ast.c
index cbcfb09d624ab227610a02f03eebfbb9a8a717db..79a74c0cc0176fce28f91ddc18cc4021f79b33e3 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -476,7 +476,7 @@ ast_unary* ast_unary_new(lex_ctx ctx, int op,
 
 void ast_unary_delete(ast_unary *self)
 {
-    ast_unref(self->operand);
+    if (self->operand) ast_unref(self->operand);
     ast_expression_delete((ast_expression*)self);
     mem_d(self);
 }
index c78820608d6c32c0b720662e67c340a7281c27d0..688c8ef69fe65789026ba40fdd2707afdbe34852 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1894,10 +1894,47 @@ static void parser_addlocal(parser_t *parser, const char *name, ast_expression *
     util_htset(vec_last(parser->variables), name, (void*)e);
 }
 
+static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
+{
+    bool       ifnot = false;
+    ast_unary *unary;
+
+    if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING) {
+        cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
+        ifnot = !ifnot;
+    }
+    else if (OPTS_FLAG(CORRECT_LOGIC)) {
+        /* everything must use a NOT_ */
+        unary = (ast_unary*)cond;
+        if (!ast_istype(cond, ast_unary) || unary->op < INSTR_NOT_F || unary->op > INSTR_NOT_FNC)
+        {
+            /* use the right NOT_ */
+            cond = (ast_expression*)ast_unary_new(ast_ctx(cond), type_not_instr[cond->expression.vtype], cond);
+            ifnot = !ifnot;
+        }
+    }
+
+    unary = (ast_unary*)cond;
+    while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F && unary->operand->expression.vtype != TYPE_STRING)
+    {
+        cond = unary->operand;
+        unary->operand = NULL;
+        ast_delete(unary);
+        ifnot = !ifnot;
+        unary = (ast_unary*)cond;
+    }
+
+    if (!cond)
+        parseerror(parser, "internal error: failed to process condition");
+
+    if (ifnot) *_ifnot = !*_ifnot;
+    return cond;
+}
+
 static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
 {
     ast_ifthen *ifthen;
-    ast_expression *cond, *ontrue, *onfalse = NULL;
+    ast_expression *cond, *ontrue = NULL, *onfalse = NULL;
     bool ifnot = false;
 
     lex_ctx ctx = parser_ctx(parser);
@@ -1961,6 +1998,13 @@ static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
         }
     }
 
+    cond = process_condition(parser, cond, &ifnot);
+    if (!cond) {
+        if (ontrue)  ast_delete(ontrue);
+        if (onfalse) ast_delete(onfalse);
+        return false;
+    }
+
     if (ifnot)
         ifthen = ast_ifthen_new(ctx, cond, onfalse, ontrue);
     else