#include "unlang_priv.h"
#include "module_priv.h"
+#define UNLANG_IGNORE ((unlang_t *) -1)
+
/*
* When we switch to a new unlang ctx, we use the new component
* name and number, but we use the CURRENT actions.
if (!cf_item_next(cs, NULL)) {
talloc_free(vpt);
- return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_MAP);
+ return UNLANG_IGNORE;
}
/*
tmpl_rules_t parse_rules;
- if (!cf_item_next(cs, NULL)) {
- return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_UPDATE);
- }
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
/*
* We allow unknown attributes here.
tmpl_rules_t parse_rules;
- if (!cf_item_next(cs, NULL)) {
- return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_FILTER);
- }
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
/*
* We allow unknown attributes here.
fr_assert(0); /* not a known configuration item data type */
add_child:
+ if (single == UNLANG_IGNORE) continue;
+
/*
* Do optimizations for "if" conditions.
*/
unlang_t *c;
char const *name1, *name2;
- if (!cf_item_next(cs, NULL)) {
- return compile_empty(parent, unlang_ctx, cs, mod_type);
- }
+ /*
+ * We always create a group, even if the section is empty.
+ */
g = group_allocate(parent, cs, mod_type);
if (!g) return NULL;
static unlang_t *compile_group(unlang_t *parent, unlang_compile_t *unlang_ctx, CONF_SECTION *cs)
{
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
+
return compile_section(parent, unlang_ctx, cs, UNLANG_TYPE_GROUP);
}
return NULL;
}
- if (!cf_item_next(cs, NULL)) {
- return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_SWITCH);
- }
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
g = group_allocate(parent, cs, UNLANG_TYPE_SWITCH);
if (!g) return NULL;
}
} /* else it's a default 'case' statement */
+ /*
+ * If we were asked to match something, then we MUST
+ * match it, even if the section is empty. Otherwise we
+ * will silently skip the match, and then fall through to
+ * the "default" statement.
+ */
c = compile_section(parent, unlang_ctx, cs, UNLANG_TYPE_CASE);
if (!c) {
talloc_free(vpt);
return NULL;
}
+
g = unlang_generic_to_group(c);
g->vpt = talloc_steal(g, vpt);
if (!cf_item_next(cs, NULL)) {
talloc_free(vpt);
- return compile_empty(parent, unlang_ctx, cs, UNLANG_TYPE_FOREACH);
+ return UNLANG_IGNORE;
}
/*
* them up.
*/
if (!fr_cond_walk(cond, pass2_cond_callback, unlang_ctx)) return NULL;
-
c = compile_section(parent, unlang_ctx, cs, mod_type);
}
if (!c) return NULL;
+ fr_assert(c != UNLANG_IGNORE);
g = unlang_generic_to_group(c);
g->cond = cond;
char const *name2;
unlang_t *c;
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
+
if (!all_children_are_modules(cs, cf_section_name1(cs))) {
return NULL;
}
bool clone = true;
bool detach = false;
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
+
/*
* Parallel sections can create empty children, if the
* admin demands it. Otherwise, the principle of least
}
}
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
+
parse_rules = *unlang_ctx->rules;
parse_rules.dict_def = dict;
}
c = compile_item(parent, &unlang_ctx2, cf_section_to_item(subcs), modname);
- if (!c) return NULL;
} else {
UPDATE_CTX2;
*/
c = compile_section(parent, &unlang_ctx2, subcs,
policy ? UNLANG_TYPE_POLICY : UNLANG_TYPE_GROUP);
- if (!c) return NULL;
}
+ if (!c) return NULL;
+ fr_assert(c != UNLANG_IGNORE);
/*
* Return the compiled thing if we can.