From: Wolfgang Bumiller Date: Thu, 20 Dec 2012 18:51:30 +0000 (+0100) Subject: process_condition function used by parse_if - need to still add it to loops X-Git-Tag: 0.2~49 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=d72cb42b0883b7f382d9bd1240e78cab34ab14ca;p=xonotic%2Fgmqcc.git process_condition function used by parse_if - need to still add it to loops --- diff --git a/ast.c b/ast.c index cbcfb09..79a74c0 100644 --- 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); } diff --git a/parser.c b/parser.c index c788206..688c8ef 100644 --- 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