return fr_sbuff_used_total(out) - at_in;
}
+static int xlat_expr_resolve_binary(xlat_exp_t *self, UNUSED void *inst, xlat_res_rules_t const *xr_rules)
+{
+ xlat_exp_t *arg1, *arg2;
+ xlat_exp_t *a, *b;
+ tmpl_res_rules_t my_tr_rules;
+
+ arg1 = xlat_exp_head(self->call.args);
+ fr_assert(arg1);
+ fr_assert(arg1->type == XLAT_GROUP);
+
+ arg2 = xlat_exp_next(self->call.args, arg1);
+ fr_assert(arg2);
+ fr_assert(arg2->type == XLAT_GROUP);
+
+ a = xlat_exp_head(arg1->group);
+ b = xlat_exp_head(arg2->group);
+
+ /*
+ * We have many things here, just call resolve recursively.
+ */
+ if (xlat_exp_next(arg1->group, a) || (xlat_exp_next(arg2->group, b))) {
+ return xlat_resolve(self->call.args, xr_rules);
+ }
+
+ /*
+ * Anything else must get resolved at run time.
+ */
+ if ((a->type != XLAT_TMPL) || (b->type != XLAT_TMPL)) {
+ return xlat_resolve(self->call.args, xr_rules);
+ }
+
+ /*
+ * The tr_rules should always contain dict_def
+ */
+ fr_assert(xr_rules); /* always set by xlat_resolve() */
+ if (xr_rules->tr_rules) {
+ my_tr_rules = *xr_rules->tr_rules;
+ } else {
+ my_tr_rules = (tmpl_res_rules_t) { };
+ }
+
+ /*
+ * The LHS attribute dictates the enumv for the RHS one.
+ */
+ if (tmpl_contains_attr(a->vpt)) {
+ if (tmpl_resolve(a->vpt, &my_tr_rules) < 0) return -1;
+
+ my_tr_rules.enumv = tmpl_da(a->vpt);
+
+ return tmpl_resolve(b->vpt, &my_tr_rules);
+ }
+
+ if (tmpl_contains_attr(b->vpt)) {
+ if (tmpl_resolve(b->vpt, &my_tr_rules) < 0) return -1;
+
+ my_tr_rules.enumv = tmpl_da(b->vpt);
+
+ return tmpl_resolve(a->vpt, &my_tr_rules);
+ }
+
+ if (tmpl_resolve(a->vpt, xr_rules->tr_rules) < 0) return -1;
+
+ return tmpl_resolve(b->vpt, xr_rules->tr_rules);
+}
+
+
static void xlat_func_append_arg(xlat_exp_t *head, xlat_exp_t *node)
{
xlat_exp_t *group;
xlat_func_args(xlat, binary_op_xlat_args); \
xlat_internal(xlat); \
xlat_print_set(xlat, xlat_expr_print_binary); \
+ xlat_resolve_set(xlat, xlat_expr_resolve_binary); \
xlat->token = _op; \
} while (0)
#endif
typedef fr_slen_t (*xlat_print_t)(fr_sbuff_t *in, xlat_exp_t const *self, void *inst, fr_sbuff_escape_rules_t const *e_rules);
+typedef int (*xlat_resolve_t)(xlat_exp_t *self, void *inst, xlat_res_rules_t const *xr_rules);
typedef struct xlat_s {
fr_rb_node_t node; //!< Entry in the xlat function tree.
void *thread_uctx; //!< uctx to pass to instantiation functions.
xlat_print_t print; //!< function to call when printing
+ xlat_resolve_t resolve; //!< function to call when resolving
xlat_flags_t flags; //!< various flags
/** Set a print routine for an xlat function.
*
- * @param[in] xlat to mark as internal.
+ * @param[in] xlat to set
*/
static inline void xlat_print_set(xlat_t *xlat, xlat_print_t func)
{
}
+/** Set a resolve routine for an xlat function.
+ *
+ * @param[in] xlat to set
+ */
+static inline void xlat_resolve_set(xlat_t *xlat, xlat_resolve_t func)
+{
+ xlat->resolve = func;
+}
+
+
/** Walker callback for xlat_walk()
*
* @param[in] exp being evaluated.
* A resolved function with unresolved args
*/
case XLAT_FUNC:
- if (xlat_resolve(node->call.args, xr_rules) < 0) return -1;
+ if (node->call.func->resolve) {
+ void *inst = node->call.inst ? node->call.inst->data : NULL;
+
+ if (node->call.func->resolve(node, inst, xr_rules) < 0) return -1;
+ } else {
+ if (xlat_resolve(node->call.args, xr_rules) < 0) return -1;
+ }
node->flags = node->call.func->flags;
xlat_flags_merge(&node->flags, &node->call.args->flags);
# * the tokenizer needs to track offsets, so it can return the offset which cause the error.
#
xlat_purify &Service-Type == Framed-User
-#match (%{Service-Type} == Framed-User)
-match ERROR offset 1: Invalid attribute reference, missing '&' prefix: Failed resolving attribute in expansion: Framed-User
+match (%{Service-Type} == Framed-User)
#xlat_purify 1 + (&Service-Type == Framed-User)
#match (1 + (%{Service-Type} == Framed-User))
xlat_purify 1 < 2 < 3
match yes
+xlat_purify &Service-Type == 1
+match (%{Service-Type} == 1)
+
+#
+# Convert the RHS to a simpler version
+#
+xlat_purify &Service-Type == (1 + 2)
+match (%{Service-Type} == 3)
+
+#
+# This is so wrong...
+#
+xlat_purify &Reply-Message == "foo"
+match ERROR offset 1: Failed resolving attribute in expansion: Message
+
count
-match 51
+match 57