From ccf7c4fc9af2b982c24a7a3b40ecc5ebbe93ecef Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 11 Jan 2018 16:30:22 +0100 Subject: evaluate: handle binop adjustment recursively currently this is fine, but a followup commit will add EXPR_SET_ELEM handling. And unlike RANGE we cannot assume the key is a value. Therefore make binop_can_transfer and binop_transfer_one handle right hand recursively if needed. For RANGE, call it again with from/to. For future SET_ELEM, we can then just call the function recursively again with right->key as new RHS. Signed-off-by: Florian Westphal --- src/evaluate.c | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/evaluate.c b/src/evaluate.c index 114c831f..46ac9e43 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1403,6 +1403,20 @@ static int expr_evaluate_hash(struct eval_ctx *ctx, struct expr **exprp) static int binop_can_transfer(struct eval_ctx *ctx, struct expr *left, struct expr *right) { + int err; + + switch (right->ops->type) { + case EXPR_VALUE: + break; + case EXPR_RANGE: + err = binop_can_transfer(ctx, left, right->left); + if (err <= 0) + return err; + return binop_can_transfer(ctx, left, right->right); + default: + return 0; + } + switch (left->op) { case OP_LSHIFT: if (mpz_scan1(right->value, 0) < mpz_get_uint32(left->right->value)) @@ -1423,6 +1437,20 @@ static int binop_can_transfer(struct eval_ctx *ctx, static int binop_transfer_one(struct eval_ctx *ctx, const struct expr *left, struct expr **right) { + int err; + + switch ((*right)->ops->type) { + case EXPR_VALUE: + break; + case EXPR_RANGE: + err = binop_transfer_one(ctx, left, &(*right)->left); + if (err < 0) + return err; + return binop_transfer_one(ctx, left, &(*right)->right); + default: + return 0; + } + expr_get(*right); switch (left->op) { @@ -1463,15 +1491,10 @@ static int binop_transfer(struct eval_ctx *ctx, struct expr **expr) return -1; break; case EXPR_RANGE: - err = binop_can_transfer(ctx, left, (*expr)->right->left); - if (err <= 0) - return err; - err = binop_can_transfer(ctx, left, (*expr)->right->right); + err = binop_can_transfer(ctx, left, (*expr)->right); if (err <= 0) return err; - if (binop_transfer_one(ctx, left, &(*expr)->right->left) < 0) - return -1; - if (binop_transfer_one(ctx, left, &(*expr)->right->right) < 0) + if (binop_transfer_one(ctx, left, &(*expr)->right) < 0) return -1; break; case EXPR_SET: @@ -1492,15 +1515,8 @@ static int binop_transfer(struct eval_ctx *ctx, struct expr **expr) list_for_each_entry(i, &(*expr)->right->set->init->expressions, list) { switch (i->key->ops->type) { case EXPR_VALUE: - err = binop_can_transfer(ctx, left, i->key); - if (err <= 0) - return err; - break; case EXPR_RANGE: - err = binop_can_transfer(ctx, left, i->key->left); - if (err <= 0) - return err; - err = binop_can_transfer(ctx, left, i->key->right); + err = binop_can_transfer(ctx, left, i->key); if (err <= 0) return err; break; @@ -1513,13 +1529,8 @@ static int binop_transfer(struct eval_ctx *ctx, struct expr **expr) list_del(&i->list); switch (i->key->ops->type) { case EXPR_VALUE: - if (binop_transfer_one(ctx, left, &i->key) < 0) - return -1; - break; case EXPR_RANGE: - if (binop_transfer_one(ctx, left, &i->key->left) < 0) - return -1; - if (binop_transfer_one(ctx, left, &i->key->right) < 0) + if (binop_transfer_one(ctx, left, &i->key) < 0) return -1; break; default: -- cgit v1.2.3