static int cond_normalise(TALLOC_CTX *ctx, fr_token_t lhs_type, fr_cond_t **c_out)
{
fr_cond_t *c = *c_out;
+ fr_cond_t *next;
/*
* Normalize the condition before returning.
* return.
*/
if (c->type == COND_TYPE_CHILD) {
- *c_out = c;
- return 0;
+ goto check_short_circuit;
}
/*
*/
default:
break;
-
}
/*
* We now do short-circuit evaluation of && and ||.
*/
+check_short_circuit:
+ if (!c->next) goto done;
+
/*
* true && FOO --> FOO
*/
- if ((c->type == COND_TYPE_TRUE) && c->next &&
+ if ((c->type == COND_TYPE_TRUE) &&
(c->next->type == COND_TYPE_AND)) {
goto hoist_grandchild;
}
/*
* false && FOO --> false
*/
- if ((c->type == COND_TYPE_FALSE) && c->next &&
+ if ((c->type == COND_TYPE_FALSE) &&
(c->next->type == COND_TYPE_AND)) {
goto drop_child;
}
/*
* false || FOO --> FOO
*/
- if ((c->type == COND_TYPE_FALSE) && c->next &&
- (c->next->type == COND_TYPE_OR)) {
- fr_cond_t *next;
-
+ if ((c->type == COND_TYPE_FALSE) &&
+ (c->next->type == COND_TYPE_OR)) {
hoist_grandchild:
next = talloc_steal(ctx, c->next->next);
talloc_free(c->next);
talloc_free(c);
c = next;
+ goto done; /* we've already called normalise for FOO */
}
/*
* true || FOO --> true
*/
- if ((c->type == COND_TYPE_TRUE) && c->next &&
- (c->next->type == COND_TYPE_OR)) {
+ if ((c->type == COND_TYPE_TRUE) &&
+ (c->next->type == COND_TYPE_OR)) {
+
drop_child:
+ TALLOC_FREE(c->next);
+ goto done; /* we don't need to normalise a boolean */
+ }
+
+ /*
+ * the short-circuit operators don't call normalise, so
+ * we have to check for that, too.
+ */
+ next = c->next;
+ if (!next->next) goto done;
+
+ /*
+ * FOO && true --> FOO
+ */
+ if ((next->type == COND_TYPE_AND) &&
+ (next->next->type == COND_TYPE_TRUE)) {
+ goto drop_next_child;
+ }
+
+ /*
+ * FOO && false --> false
+ */
+ if ((next->type == COND_TYPE_AND) &&
+ (next->next->type == COND_TYPE_FALSE)) {
+ goto hoist_next_grandchild;
+ }
+
+ /*
+ * FOO || false --> FOO
+ */
+ if ((next->type == COND_TYPE_OR) &&
+ (next->next->type == COND_TYPE_FALSE)) {
+ drop_next_child:
+ TALLOC_FREE(c->next);
+ }
+
+ /*
+ * FOO || true --> true
+ */
+ if ((next->type == COND_TYPE_OR) &&
+ (next->next->type == COND_TYPE_TRUE)) {
+ hoist_next_grandchild:
+ next = talloc_steal(ctx, next->next);
talloc_free(c->next);
- c->next = NULL;
+ c = next;
}
+done:
*c_out = c;
return 0;