ssize_t dec_len;
xlat_exp_head_t *head = NULL;
size_t input_len = strlen(in), escaped_len;
-
- if (!el) {
- fr_strerror_const("Flag '-p' not used. xlat_purify is disabled");
- goto return_error;
- }
-
- dec_len = xlat_tokenize_ephemeral_expression(cc->tmp_ctx, &head, el, &FR_SBUFF_IN(in, input_len), NULL,
- &(tmpl_rules_t) {
+ tmpl_rules_t t_rules = (tmpl_rules_t) {
.attr = {
- .dict_def = cc->tmpl_rules.attr.dict_def ?
+ .dict_def = cc->tmpl_rules.attr.dict_def ?
cc->tmpl_rules.attr.dict_def : cc->config->dict,
.allow_unresolved = cc->tmpl_rules.attr.allow_unresolved,
.list_def = request_attr_request,
},
.xlat = cc->tmpl_rules.xlat,
- });
+ .at_runtime = true,
+ };
+
+ if (!el) {
+ fr_strerror_const("Flag '-p' not used. xlat_purify is disabled");
+ goto return_error;
+ }
+ t_rules.xlat.runtime_el = el;
+
+ dec_len = xlat_tokenize_expression(cc->tmp_ctx, &head, &FR_SBUFF_IN(in, input_len), NULL, &t_rules);
if (dec_len <= 0) {
fr_strerror_printf_push_head("ERROR offset %d", (int) -dec_len);
TALLOC_CTX *xlat_ctx = talloc_init_const("xlat");
xlat_exp_head_t *head = NULL;
- slen = xlat_tokenize_ephemeral_expression(xlat_ctx, &head, el,
- &line,
- NULL,
- &(tmpl_rules_t) {
- .attr = {
- .dict_def = dict_protocol,
- .list_def = request_attr_request,
- .allow_unresolved = true,
- }
- }
- );
+ slen = xlat_tokenize_expression(xlat_ctx, &head,
+ &line,
+ NULL,
+ &(tmpl_rules_t) {
+ .attr = {
+ .dict_def = dict_protocol,
+ .list_def = request_attr_request,
+ .allow_unresolved = true,
+ },
+ .xlat = {
+ .runtime_el = el,
+ },
+ .at_runtime = true,
+ });
if (slen <= 0) {
talloc_free(xlat_ctx);
fr_sbuff_in_sprintf(&out, "ERROR offset %d '%s'", (int) -slen, fr_strerror());
fr_slen_t xlat_tokenize_condition(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-fr_slen_t xlat_tokenize_ephemeral_expression(TALLOC_CTX *ctx, xlat_exp_head_t **head,
- fr_event_list_t *el,
- fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-
fr_slen_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_head_t **head,
fr_event_list_t *el, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
/*
* Parse the input as an expression.
*/
- if (xlat_tokenize_ephemeral_expression(rctx,
- &rctx->ex, unlang_interpret_event_list(request),
- &FR_SBUFF_IN(arg->vb_strvalue, arg->vb_length),
- &(fr_sbuff_parse_rules_t){
- .escapes = &escape_rules
- },
- &(tmpl_rules_t){
- .attr = {
- .dict_def = request->dict,
- .list_def = request_attr_request,
- .allow_unknown = false,
- .allow_unresolved = false,
- .allow_foreign = false,
- },
- .at_runtime = true
- }) < 0) {
+ if (xlat_tokenize_expression(rctx,
+ &rctx->ex,
+ &FR_SBUFF_IN(arg->vb_strvalue, arg->vb_length),
+ &(fr_sbuff_parse_rules_t){
+ .escapes = &escape_rules
+ },
+ &(tmpl_rules_t){
+ .attr = {
+ .dict_def = request->dict,
+ .list_def = request_attr_request,
+ .allow_unknown = false,
+ .allow_unresolved = false,
+ .allow_foreign = false,
+ },
+ .xlat = {
+ .runtime_el = unlang_interpret_event_list(request),
+ },
+ .at_runtime = true,
+ }
+ ) < 0) {
RPEDEBUG("Failed parsing expansion");
error:
talloc_free(rctx);
static fr_slen_t xlat_tokenize_expression_internal(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool cond)
{
+ int rcode;
ssize_t slen;
fr_sbuff_parse_rules_t *bracket_rules = NULL;
fr_sbuff_parse_rules_t *terminal_rules = NULL;
* Add nodes that need to be bootstrapped to
* the registry.
*/
- if (xlat_bootstrap(head) < 0) {
+ if (!t_rules || !t_rules->xlat.runtime_el) {
+ rcode = xlat_bootstrap(head);
+ } else {
+ rcode = xlat_instantiate_ephemeral(head, t_rules->xlat.runtime_el);
+ }
+ if (rcode < 0) {
talloc_free(head);
return -1;
}
fr_slen_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
{
- fr_assert(!t_rules || !t_rules->xlat.runtime_el);
-
return xlat_tokenize_expression_internal(ctx, out, in, p_rules, t_rules, false);
}
return xlat_tokenize_expression_internal(ctx, out, in, p_rules, t_rules, true);
}
-
-/** Tokenize an xlat expression at runtime
- *
- * This function is only for testing. It should be deleted when
- * expressions are integrated into the main xlat parser.
- *
- * @param[in] ctx to allocate dynamic buffers in.
- * @param[out] out the head of the xlat list / tree structure.
- * @param[in] el for registering any I/O handlers.
- * @param[in] in the format string to expand.
- * @param[in] p_rules from the encompassing grammar.
- * @param[in] t_rules controlling how attribute references are parsed.
- * @return
- * - >0 on success.
- * - 0 and *head == NULL - Parse failure on first char.
- * - 0 and *head != NULL - Zero length expansion
- * - <0 the negative offset of the parse failure.
- */
-fr_slen_t xlat_tokenize_ephemeral_expression(TALLOC_CTX *ctx, xlat_exp_head_t **out,
- fr_event_list_t *el, fr_sbuff_t *in,
- fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
-{
- ssize_t slen;
- fr_sbuff_parse_rules_t *bracket_rules = NULL;
- fr_sbuff_parse_rules_t *terminal_rules = NULL;
- tmpl_rules_t my_rules = { };
- xlat_exp_head_t *head;
- xlat_exp_t *node = NULL;
-
- /*
- * Whatever the caller passes, ensure that we have a
- * terminal rule which ends on operators, and a terminal
- * rule which ends on ')'.
- */
- MEM(bracket_rules = talloc_zero(ctx, fr_sbuff_parse_rules_t));
- MEM(terminal_rules = talloc_zero(ctx, fr_sbuff_parse_rules_t));
- if (p_rules) {
- *bracket_rules = *p_rules;
- *terminal_rules = *p_rules;
-
- if (p_rules->terminals) {
- MEM(terminal_rules->terminals = fr_sbuff_terminals_amerge(terminal_rules,
- p_rules->terminals,
- &operator_terms));
- } else {
- terminal_rules->terminals = &operator_terms;
- }
- } else {
- terminal_rules->terminals = &operator_terms;
- }
- MEM(bracket_rules->terminals = fr_sbuff_terminals_amerge(bracket_rules,
- terminal_rules->terminals,
- &bracket_terms));
- MEM(head = xlat_exp_head_alloc(ctx));
-
- if (t_rules) {
- my_rules = *t_rules;
- head->dict = t_rules->attr.dict_def;
- }
-
- my_rules.xlat.runtime_el = el;
- my_rules.at_runtime = true;
-
- slen = tokenize_expression(head, &node, in, terminal_rules, &my_rules, T_INVALID, bracket_rules, p_rules, false);
- talloc_free(bracket_rules);
- talloc_free(terminal_rules);
-
- if (slen < 0) {
- talloc_free(head);
- FR_SBUFF_ERROR_RETURN(in);
- }
-
- if (!node) {
- *out = head;
- return slen;
- }
-
- /*
- * Convert raw rcodes to xlat's.
- */
- if (reparse_rcode(head, &node, true) < 0) {
- talloc_free(head);
- return -1;
- }
-
- xlat_exp_insert_tail(head, node);
-
- /*
- * Create ephemeral instance data for the xlat
- */
- if (xlat_instantiate_ephemeral(head, el) < 0) {
- talloc_free(head);
- return -1;
- }
-
- *out = head;
- return slen;
-}
-
/** Allow callers to see if an xlat is truthy
*
* So the caller can cache it, and needs to check fewer things at run
MEM(node = xlat_exp_alloc(head, XLAT_TMPL, NULL, 0));
MEM(node->vpt = tmpl_alloc(node, TMPL_TYPE_XLAT, T_BARE_WORD, "", 1));
- if (t_rules->xlat.runtime_el) {
- ret = xlat_tokenize_ephemeral_expression(node->vpt, &child, t_rules->xlat.runtime_el, in, &attr_p_rules, t_rules);
- } else {
- ret = xlat_tokenize_expression(node->vpt, &child, in, &attr_p_rules, t_rules);
- }
+ ret = xlat_tokenize_expression(node->vpt, &child, in, &attr_p_rules, t_rules);
if (ret <= 0) {
talloc_free(node);
return ret;