the RHS of a map is NOT resolved in the context of the LHS.
Instead, the RHS is really a pointer to a value. And the final
value is then resolved in the context of the LHS.
}
/*
- * If we know that the assignment is forbidden, then fail early.
+ * If we can resolve the RHS in the context of the LHS,
+ * and are allowed to do so, then do that now.
*
- * Note that we can do some assignment of strings to
- * structural elements. The string is parsed as a list
- * of edit instructions.
+ * The "map" keyword uses the RHS not as the value which
+ * is assigned to the LHS. Instead, it is a pointer to
+ * the value. As such, we cannot immediately resolve the
+ * RHS in the context of the LHS.
+ *
+ * The edit code allows string assignments to lists, and
+ * will interpret the string as a sequence of edit
+ * operations. So we skip casting strings to lists.
+ *
+ * @todo - that could arguably be done immediately here,
+ * and the RHS could be parsed and created as a child
+ * map. That would allow for more compile-time sanity
+ * checks.
*/
if (tmpl_is_attr(map->lhs) && tmpl_is_data(map->rhs) &&
+ (!input_rhs_rules || !input_rhs_rules->attr.disallow_rhs_resolve) &&
fr_type_is_leaf(tmpl_attr_tail_da(map->lhs)->type)) {
fr_type_t cast_type;
uint8_t xlat:1 ; //!< for %{User-Name}
uint8_t bare_word_enum:1; //!< for v3 compatibility.
+
+ uint8_t disallow_rhs_resolve:1; //!< map RHS is NOT immediately resolved in the context of the LHS.
};
struct tmpl_xlat_rules_s {
};
/*
- * We allow unknown attributes here.
+ * The RHS is NOT resolved in the context of the LHS.
*/
t_rules = *(unlang_ctx->rules);
- t_rules.attr.allow_unknown = true;
+ t_rules.attr.disallow_rhs_resolve = true;
RULES_VERIFY(&t_rules);
modules = cf_section_find(cf_root(cs), "modules", NULL);
* This looks at cs->name2 to determine which list to update
*/
map_list_init(&gext->map);
- rcode = map_afrom_cs(gext, &gext->map, cs, &t_rules, &t_rules, unlang_fixup_map, NULL, 256);
+ rcode = map_afrom_cs(gext, &gext->map, cs, unlang_ctx->rules, &t_rules, unlang_fixup_map, NULL, 256);
if (rcode < 0) return NULL; /* message already printed */
if (map_list_empty(&gext->map)) {
cf_log_err(cs, "'map' sections cannot be empty");