if (c->negate) rcode = !rcode;
- if (!c->next) break;
-
- /*
- * Do short-circuit evaluations.
- */
- if (c->next) {
- switch (c->next->type) {
- case COND_TYPE_AND:
- if (!rcode) goto return_to_parent;
-
- c = c->next; /* skip the && */
- break;
-
- case COND_TYPE_OR:
- if (rcode) goto return_to_parent;
-
- c = c->next; /* skip the || */
- break;
-
- default:
- break;
- }
- }
-
/*
* We've fallen off of the end of this evaluation
* string. Go back up to the parent, and then to
* the next sibling of the parent.
+ *
+ * Do this repeatedly until we have a c->next
*/
- if (!c->next) {
+ while (!c->next) {
return_to_parent:
c = c->parent;
- depth--;
+ if (!c) return rcode;
- if (!c) break; /* we have to do this, otherwise the next line will fail */
+ depth--;
+ fr_assert(depth >= 0);
}
- c = c->next;
+ /*
+ * Do short-circuit evaluations.
+ */
+ switch (c->next->type) {
+ case COND_TYPE_AND:
+ if (!rcode) goto return_to_parent;
+
+ c = c->next->next; /* skip the && */
+ break;
+
+ case COND_TYPE_OR:
+ if (rcode) goto return_to_parent;
+
+ c = c->next->next; /* skip the || */
+ break;
+
+ default:
+ c = c->next;
+ break;
+ }
}
if (rcode < 0) {
*/
if (!child->next) {
(void) talloc_steal(ctx, child);
+ child->parent = c->parent;
child->next = talloc_steal(child, c->next);
/*
* !(!FOO) --> FOO, etc.
*/
child->negate = (c->negate != child->negate);
- child->parent = c->parent;
+
talloc_free(c);
c = child;
continue;
if (!c->next && !c->negate) {
(void) talloc_steal(ctx, child);
child->parent = c->parent;
+
talloc_free(c);
c = child;
continue;
*
* @param[in] ctx talloc ctx
* @param[out] out pointer to the returned condition structure
- * @param[in] parent the parent of this #fr_cond_t
* @param[in] cs our configuration section
* @param[in] in the start of the string to process. Should be "(..."
* @param[in] brace look for a closing brace (how many deep we are)
* - Length of the string skipped.
* - < 0 (the offset to the offending error) on error.
*/
-static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **out, fr_cond_t *parent,
+static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **out,
CONF_SECTION *cs, fr_sbuff_t *in, int brace,
tmpl_rules_t const *t_rules)
{
fr_sbuff_marker_t m_lhs, m_lhs_cast, m_op, m_rhs, m_rhs_cast;
MEM(c = talloc_zero(ctx, fr_cond_t));
- c->parent = parent;
fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
if (!fr_sbuff_extend(&our_in)) {
* (COND)
*/
if (fr_sbuff_next_if_char(&our_in, '(')) {
-
/*
* We've already eaten one layer of
* brackets. Go recurse to get more.
/*
* Children are allocated from the parent.
*/
- slen = cond_tokenize(c, &c->data.child, c, cs, &our_in, brace + 1, t_rules);
+ slen = cond_tokenize(c, &c->data.child, cs, &our_in, brace + 1, t_rules);
if (slen <= 0) {
fr_sbuff_advance(&our_in, slen * -1);
goto error;
*/
MEM(child = talloc_zero(c, fr_cond_t));
child->type = cond_op;
- child->parent = c->parent;
/*
* siblings are allocated from their older
* siblings.
*/
- slen = cond_tokenize(child, &child->next, parent, cs, &our_in, brace, t_rules);
+ slen = cond_tokenize(child, &child->next, cs, &our_in, brace, t_rules);
if (slen <= 0) {
fr_sbuff_advance(&our_in, slen * -1);
goto error;
* siblings are allocated from their older
* siblings.
*/
- slen = cond_tokenize(c, &c->next, parent, cs, &our_in, brace, t_rules);
+ slen = cond_tokenize(c, &c->next, cs, &our_in, brace, t_rules);
if (slen <= 0) {
fr_sbuff_advance(&our_in, slen * -1);
goto error;
return fr_sbuff_set(in, &our_in);
}
+/*
+ * Normalisation will restructure the conditional tree, including
+ * removing and/or rearranging the parents. So we reparent
+ * everything after the full normalization has run.
+ */
+static void cond_reparent(fr_cond_t *c, fr_cond_t *parent)
+{
+ while (c) {
+ c->parent = parent;
+
+ if (c->type == COND_TYPE_CHILD) cond_reparent(c->data.child, c);
+
+ c = c->next;
+ }
+}
+
/** Tokenize a conditional check
*
* @param[in] cs current CONF_SECTION and talloc ctx
char buffer[8192];
ssize_t diff, slen;
+ *head = NULL;
+
if (!cf_expand_variables(cf_filename(cs), cf_lineno(cs), cf_item_to_section(cf_parent(cs)),
buffer, sizeof(buffer),
fr_sbuff_current(in), fr_sbuff_remaining(in), NULL)) {
}
diff = fr_sbuff_remaining(in) - strlen(buffer); /* Hack so that we appear to consume more of the string */
- slen = cond_tokenize(cs, head, NULL, cs, &FR_SBUFF_IN(buffer, strlen(buffer)), 0, rules);
+ slen = cond_tokenize(cs, head, cs, &FR_SBUFF_IN(buffer, strlen(buffer)), 0, rules);
if (slen < 0) return slen;
+ /*
+ * Now that everything has been normalized, reparent the children.
+ */
+ if (*head) cond_reparent(*head, NULL);
+
return slen + diff;
}