From 5a140c9cf95724f971ec9cb40217bea8fc4d089f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 16 Feb 2014 20:35:37 +0000 Subject: binop: take care of operator precedence when printing binop arguments When the argument of a binop is a binop itself, we may need to add parens if the precedence of the argument is lower then the binop. Before: tcp flags & syn | ack == syn | ack tcp flags & syn | ack != syn | ack After: tcp flags & (syn | ack) == syn | ack tcp flags & (syn | ack) != syn | ack Signed-off-by: Patrick McHardy --- src/expression.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expression.c b/src/expression.c index c8566224..6cc79b2e 100644 --- a/src/expression.c +++ b/src/expression.c @@ -404,16 +404,42 @@ struct expr *unary_expr_alloc(const struct location *loc, return expr; } +static uint8_t expr_binop_precedence[OP_MAX + 1] = { + [OP_LSHIFT] = 1, + [OP_RSHIFT] = 1, + [OP_AND] = 2, + [OP_XOR] = 3, + [OP_OR] = 4, +}; + +static void binop_arg_print(const struct expr *op, const struct expr *arg) +{ + bool prec = false; + + if (arg->ops->type == EXPR_BINOP && + expr_binop_precedence[op->op] != 0 && + expr_binop_precedence[op->op] < expr_binop_precedence[arg->op]) + prec = 1; + + if (prec) + printf("("); + expr_print(arg); + if (prec) + printf(")"); +} + static void binop_expr_print(const struct expr *expr) { - expr_print(expr->left); + binop_arg_print(expr, expr->left); + if (expr_op_symbols[expr->op] && (expr->op != OP_EQ || expr->left->ops->type == EXPR_BINOP)) printf(" %s ", expr_op_symbols[expr->op]); else printf(" "); - expr_print(expr->right); + + binop_arg_print(expr, expr->right); } static void binop_expr_clone(struct expr *new, const struct expr *expr) -- cgit v1.2.3