diff options
author | Patrick McHardy <kaber@trash.net> | 2014-02-16 20:35:37 +0000 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2014-02-17 17:17:18 +0000 |
commit | 5a140c9cf95724f971ec9cb40217bea8fc4d089f (patch) | |
tree | 19733bb86ac658978291abeb5139a8d1de156b90 | |
parent | 6bad82aba5d304c7a2dd1b19fe57464dca327f4a (diff) |
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 <kaber@trash.net>
-rw-r--r-- | include/expression.h | 2 | ||||
-rw-r--r-- | src/expression.c | 30 |
2 files changed, 30 insertions, 2 deletions
diff --git a/include/expression.h b/include/expression.h index 0633102e..5128a5bb 100644 --- a/include/expression.h +++ b/include/expression.h @@ -80,7 +80,9 @@ enum ops { OP_FLAGCMP, /* Set lookup */ OP_LOOKUP, + __OP_MAX }; +#define OP_MAX (__OP_MAX - 1) extern const char *expr_op_symbols[]; 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) |