/*
* Copy the xlat component
*/
- if (tmpl_contains_xlat(vpt) && unlikely(xlat_copy(vpt, &vpt->data.xlat.ex, in->data.xlat.ex) < 0)) goto error;
+ if (tmpl_contains_xlat(vpt) && unlikely(xlat_copy(vpt, vpt->data.xlat.ex, in->data.xlat.ex) < 0)) goto error;
return vpt;
}
tmpl.c \
variable.c \
xlat.c \
+ xlat_alloc.c \
xlat_builtin.c \
xlat_eval.c \
xlat_expr.c \
xlat_inst.c \
- xlat_tokenize.c \
xlat_pair.c \
+ xlat_tokenize.c \
xlat_purify.c
HEADERS := $(subst src/lib/,,$(wildcard src/lib/unlang/*.h))
int xlat_from_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t **head, tmpl_t **vpt_p);
-int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t **out, xlat_exp_head_t const *in);
+int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in);
/*
* xlat_inst.c
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @file xlat_alloc.c
+ * @brief Functions to allocate different types of xlat nodes
+ */
+
+RCSID("$Id$")
+
+#include <freeradius-devel/server/base.h>
+#include <freeradius-devel/unlang/xlat.h>
+
+#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/types.h>
+
+#define _XLAT_PRIVATE
+#include <freeradius-devel/unlang/xlat_priv.h>
+
+xlat_exp_head_t *_xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx)
+{
+ xlat_exp_head_t *head;
+
+ MEM(head = talloc_zero(ctx, xlat_exp_head_t));
+
+ fr_dlist_init(&head->dlist, xlat_exp_t, entry);
+ head->flags.pure = true;
+#ifndef NDEBUG
+ head->file = file;
+ head->line = line;
+#endif
+
+ return head;
+}
+
+/** Set the type of an xlat node
+ *
+ * Also initialises any xlat_exp_head necessary
+ *
+ * @param[in] node to set type for.
+ * @param[in] type to set.
+ */
+void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type)
+{
+ /*
+ * Do nothing if it's the same type
+ */
+ if (node->type == type) return;
+
+ /*
+ * Free existing lists if present
+ */
+ if (node->type != 0) switch (node->type) {
+ case XLAT_ALTERNATE:
+ TALLOC_FREE(node->alternate[0]);
+ TALLOC_FREE(node->alternate[1]);
+ break;
+
+ case XLAT_GROUP:
+ TALLOC_FREE(node->group);
+ break;
+
+ case XLAT_FUNC:
+ case XLAT_FUNC_UNRESOLVED:
+ if (type != XLAT_FUNC) {
+ TALLOC_FREE(node->call.args); /* Just switching from unresolved to resolved */
+ } else goto done;
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * Alloc new lists to match the type
+ */
+ switch (type) {
+ case XLAT_ALTERNATE:
+ node->alternate[0] = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node);
+ node->alternate[1] = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node);
+ break;
+
+ case XLAT_GROUP:
+ node->group = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node);
+ break;
+
+ case XLAT_FUNC:
+ case XLAT_FUNC_UNRESOLVED:
+ node->call.args = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node);
+ break;
+
+ default:
+ break;
+ }
+
+done:
+ node->type = type;
+}
+
+static xlat_exp_t *xlat_exp_alloc_pool(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra)
+{
+ xlat_exp_t *node;
+
+ MEM(node = talloc_zero_pooled_object(ctx, xlat_exp_t, extra_hdrs, extra));
+ node->flags.pure = true; /* everything starts pure */
+ node->quote = T_BARE_WORD;
+#ifndef NDEBUG
+ node->file = file;
+ node->line = line;
+#endif
+
+ return node;
+}
+
+/** Allocate an xlat node with no name, and no type set
+ *
+ * @param[in] ctx to allocate node in.
+ * @return A new xlat node.
+ */
+xlat_exp_t *_xlat_exp_alloc_null(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx)
+{
+ return xlat_exp_alloc_pool(NDEBUG_LOCATION_VALS ctx, 0, 0);
+}
+
+/** Allocate an xlat node
+ *
+ * @param[in] ctx to allocate node in.
+ * @param[in] type of the node.
+ * @param[in] in original input string.
+ * @param[in] inlen the length of the original input string.
+ * @return A new xlat node.
+ */
+xlat_exp_t *_xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen)
+{
+ xlat_exp_t *node;
+ unsigned int extra_hdrs;
+ size_t extra;
+
+ /*
+ * Figure out how much extra memory we
+ * need to allocate for this node type.
+ */
+ switch (type) {
+ case XLAT_ALTERNATE:
+ extra_hdrs = 2;
+ extra = sizeof(xlat_exp_head_t) * 2;
+ break;
+
+ case XLAT_GROUP:
+ extra_hdrs = 1;
+ extra = sizeof(xlat_exp_head_t);
+ break;
+
+ case XLAT_FUNC:
+ extra_hdrs = 1;
+ extra = sizeof(xlat_exp_head_t);
+ break;
+
+ default:
+ extra_hdrs = 0;
+ extra = 0;
+ }
+
+ node = xlat_exp_alloc_pool(NDEBUG_LOCATION_VALS
+ ctx,
+ (in != NULL) + extra_hdrs,
+ inlen + extra);
+ _xlat_exp_set_type(NDEBUG_LOCATION_VALS node, type);
+
+ if (!in) return node;
+
+ node->fmt = talloc_bstrndup(node, in, inlen);
+ switch (type) {
+ case XLAT_BOX:
+ fr_value_box_strdup_shallow(&node->data, NULL, node->fmt, false);
+ break;
+
+ default:
+ break;
+ }
+
+ return node;
+}
+
+/** Set the format string for an xlat node
+ *
+ * @param[in] node to set fmt for.
+ * @param[in] fmt talloced buffer to set as the fmt string.
+ */
+void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt)
+{
+ if (node->fmt) talloc_const_free(node->fmt);
+ node->fmt = talloc_get_type_abort(fmt, char);
+}
group = xlat_exp_alloc(head->call.args, XLAT_GROUP, NULL, 0);
group->quote = T_BARE_WORD;
- group->fmt = node->fmt; /* not entirely correct, but good enough for now */
+ xlat_exp_set_name_buffer_shallow(group, node->fmt); /* not entirely correct, but good enough for now */
group->flags = node->flags;
talloc_steal(group->group, node);
fr_assert(child->type == XLAT_TMPL);
fr_assert(tmpl_contains_attr(child->vpt));
- node->fmt = child->vpt->name;
+ xlat_exp_set_name_buffer_shallow(node, child->vpt->name);
xlat_func_append_arg(node, child, false);
* result is "false" for "delete this argument"
* result is "true" for "return this argument".
*/
-static bool xlat_node_matches_bool(xlat_exp_t *parent, xlat_exp_head_t *head, bool sense, bool *result)
+static bool xlat_node_matches_bool(bool *result, xlat_exp_t *parent, xlat_exp_head_t *head, bool sense)
{
fr_value_box_t *box;
xlat_exp_t *node;
xlat_inst_remove(parent);
- parent->type = XLAT_BOX;
+ xlat_exp_set_type(parent, XLAT_BOX);
fr_value_box_copy(parent, &parent->data, box);
parent->flags = (xlat_flags_t) { .pure = true, .constant = true, };
*/
static int xlat_expr_logical_purify(xlat_exp_t *node, void *instance, request_t *request)
{
- int i, j;
- int deleted = 0;
- bool result;
- xlat_logical_inst_t *inst = talloc_get_type_abort(instance, xlat_logical_inst_t);
- xlat_exp_head_t *group;
+ int i, j;
+ int deleted = 0;
+ bool result;
+ xlat_logical_inst_t *inst = talloc_get_type_abort(instance, xlat_logical_inst_t);
+ xlat_exp_head_t *group;
fr_assert(node->type == XLAT_FUNC);
/*
- * Don't check the last argument. If everything else gets deleted, then we just return the last
- * argument.
+ * Don't check the last argument. If everything else gets deleted,
+ * then we just return the last argument.
*/
for (i = 0; i < inst->argc; i++) {
/*
* result is "false" for "delete this argument"
* result is "true" for "return this argument".
*/
- if (!xlat_node_matches_bool(node, inst->argv[i], inst->stop_on_match, &result)) {
- continue;
- }
+ if (!xlat_node_matches_bool(&result, node, inst->argv[i], inst->stop_on_match)) continue;
/*
* 0 && EXPR --> 0.
*/
group = inst->argv[0];
fr_assert(group != NULL);
+ fr_assert(group->fmt != NULL);
talloc_steal(node, group);
xlat_inst_remove(node);
- node->type = XLAT_GROUP;
- node->fmt = group->fmt;
+ xlat_exp_set_type(node, XLAT_BOX);
+ xlat_exp_set_name_buffer_shallow(node, group->fmt);
node->group = group;
node->flags = group->flags;
*/
*out_c = c;
- MEM(unary = xlat_exp_alloc(head, XLAT_FUNC, func->name, strlen(func->name)));
- unary->fmt = fr_tokens[func->token];
+ MEM(unary = xlat_exp_alloc(head, XLAT_FUNC, fr_tokens[func->token], strlen(fr_tokens[func->token])));
unary->call.func = func;
unary->flags = func->flags;
MEM(node = xlat_exp_alloc(cast, XLAT_BOX, NULL, 0));
node->flags.constant = true;
xlat_exp_set_name_buffer_shallow(node,
- talloc_strdup(node,
- fr_table_str_by_value(fr_type_table,
- type, "<INVALID>")));
+ talloc_typed_strdup(node,
+ fr_table_str_by_value(fr_type_table, type, "<INVALID>")));
fr_value_box_init(&node->data, FR_TYPE_UINT8, attr_cast_base, false);
node->data.vb_uint8 = type;
node->vpt = vpt;
node->quote = quote;
- node->fmt = vpt->name;
+ xlat_exp_set_name_buffer_shallow(node, vpt->name);
node->flags.pure = !tmpl_contains_xlat(node->vpt);
node->flags.needs_resolving = tmpl_needs_resolving(node->vpt);
*/
if (tmpl_is_xlat(vpt) || tmpl_is_xlat_unresolved(vpt)) {
xlat_exp_head_t *xlat = tmpl_xlat(vpt);
- xlat_exp_t *cast;
- fr_type_t type = FR_TYPE_NULL;
-
- talloc_steal(node, xlat);
- node->fmt = talloc_typed_strdup(node, vpt->name);
-
- xlat_exp_set_type(node, XLAT_GROUP);
- node->quote = quote;
- node->group = xlat;
-
- node->flags = xlat->flags;
+ fr_type_t type = FR_TYPE_NULL;
+ xlat_exp_t *arg = NULL;
+ xlat_exp_t *cast = NULL;
/*
* Enforce a cast type.
if (type != FR_TYPE_NULL) {
MEM(cast = expr_cast_alloc(head, type));
- xlat_func_append_arg(cast, node, false);
+ head = cast->call.args; /* Arguments */
+ }
+
+ MEM(arg = xlat_exp_alloc(head, XLAT_GROUP, vpt->name, strlen(vpt->name)));
+
+ /*
+ * This is less efficient than just stealing the
+ * xlat into the context of the new node...
+ *
+ * But talloc_steal can be extremely inefficient O(N)
+ * where N is chunk siblings.
+ */
+ xlat_copy(arg->group, arg->group, xlat);
+ arg->quote = quote;
+ arg->flags = xlat->flags;
+
+ talloc_free(node); /* also frees tmpl, leaving just the xlat */
+
+ if (cast) {
+ xlat_func_append_arg(cast, arg, false);
node = cast;
+ } else {
+ node = arg;
}
- talloc_free(vpt);
goto done;
}
*/
node->vpt = vpt;
node->quote = quote;
- node->fmt = vpt->name;
+ xlat_exp_set_name_buffer_shallow(node, vpt->name);
node->flags.pure = tmpl_is_data(node->vpt);
node->flags.constant = node->flags.pure;
* Create the function node, with the LHS / RHS arguments.
*/
MEM(node = xlat_exp_alloc(head, XLAT_FUNC, fr_tokens[op], strlen(fr_tokens[op])));
- node->fmt = fr_tokens[op];
node->call.func = func;
node->flags = func->flags;
TALLOC_FREE(node->call.inst);
}
-
- node->type = XLAT_INVALID;
return 0;
}
#include <freeradius-devel/unlang/xlat.h>
#include <freeradius-devel/io/pair.h>
#include <freeradius-devel/util/talloc.h>
+#include <freeradius-devel/build.h>
#ifdef DEBUG_XLAT
# define XLAT_DEBUG RDEBUG3
# define XLAT_DEBUG(...)
#endif
+/*
+ * Allow public and private versions of the same structures
+ */
+#ifdef _CONST
+# error _CONST can only be defined in the local header
+#endif
+#ifndef _XLAT_PRIVATE
+# define _CONST const
+#else
+# define _CONST
+#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 int (*xlat_purify_t)(xlat_exp_t *self, void *inst, request_t *request);
* These nodes form a tree which represents one or more nested expansions.
*/
struct xlat_exp_s {
- char const *fmt; //!< The original format string (a talloced buffer).
- fr_token_t quote; //!< Type of quoting around XLAT_GROUP types.
+ char const * _CONST fmt; //!< The original format string (a talloced buffer).
+ fr_token_t quote; //!< Type of quoting around XLAT_GROUP types.
+
+ xlat_flags_t flags; //!< Flags that control resolution and evaluation.
- xlat_flags_t flags; //!< Flags that control resolution and evaluation.
+ xlat_type_t _CONST type; //!< type of this expansion.
+ fr_dlist_t entry;
- xlat_type_t type; //!< type of this expansion.
- fr_dlist_t entry;
+#ifndef NDEBUG
+ char const * _CONST file; //!< File where the xlat was allocated.
+ int line; //!< Line where the xlat was alocated.
+#endif
union {
xlat_exp_head_t *alternate[2]; //!< alternate expansions
};
struct xlat_exp_head_s {
- char const *fmt; //!< The original format string (a talloced buffer).
- xlat_flags_t flags; //!< Flags that control resolution and evaluation.
- bool instantiated; //!< temporary flag until we fix more things
- fr_dict_t const *dict; //!< dictionary for this xlat
- fr_dlist_head_t dlist;
+ fr_dlist_head_t dlist;
+ char const * _CONST fmt; //!< The original format string (a talloced buffer).
+ xlat_flags_t flags; //!< Flags that control resolution and evaluation.
+ bool instantiated; //!< temporary flag until we fix more things
+ fr_dict_t const *dict; //!< dictionary for this xlat
+
+#ifndef NDEBUG
+ char const * _CONST file; //!< File where the xlat was allocated.
+ int line; //!< Line where the xlat was alocated.
+#endif
};
return fr_dlist_next(&head->dlist, node);
}
-static inline xlat_exp_head_t *xlat_exp_head_alloc(TALLOC_CTX *ctx)
-{
- xlat_exp_head_t *head;
-
- MEM(head = talloc_zero(ctx, xlat_exp_head_t));
-
- fr_dlist_init(&head->dlist, xlat_exp_t, entry);
- head->flags.pure = true;
-
- return head;
-}
-
-/** Set the type of an xlat node
- *
- * Also initialises any xlat_exp_head necessary
- *
- * @param[in] node to set type for.
- * @param[in] type to set.
- */
-static inline void xlat_exp_set_type(xlat_exp_t *node, xlat_type_t type)
-{
- xlat_type_t existing_type = node->type;
-
- node->type = type;
-
- if (existing_type != 0) return;
-
- switch (type) {
- case XLAT_ALTERNATE:
- node->alternate[0] = xlat_exp_head_alloc(node);
- node->alternate[1] = xlat_exp_head_alloc(node);
- break;
-
- case XLAT_GROUP:
- node->group = xlat_exp_head_alloc(node);
- break;
-
- case XLAT_FUNC:
- case XLAT_FUNC_UNRESOLVED:
- node->call.args = xlat_exp_head_alloc(node);
- break;
-
- default:
- break;
- }
-}
-
-static inline xlat_exp_t *xlat_exp_alloc_pool(TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra)
-{
- xlat_exp_t *node;
-
- MEM(node = talloc_zero_pooled_object(ctx, xlat_exp_t, extra_hdrs, extra));
- node->flags.pure = true; /* everything starts pure */
- node->quote = T_BARE_WORD;
-
- return node;
-}
-
-/** Allocate an xlat node with no name, and no type set
- *
- * @param[in] ctx to allocate node in.
- * @return A new xlat node.
- */
-static inline xlat_exp_t *xlat_exp_alloc_null(TALLOC_CTX *ctx)
-{
- return xlat_exp_alloc_pool(ctx, 0, 0);
-}
-
-/** Allocate an xlat node
- *
- * @param[in] ctx to allocate node in.
- * @param[in] type of the node.
- * @param[in] in original input string.
- * @param[in] inlen the length of the original input string.
- * @return A new xlat node.
- */
-static inline xlat_exp_t *xlat_exp_alloc(TALLOC_CTX *ctx, xlat_type_t type,
- char const *in, size_t inlen)
-{
- xlat_exp_t *node;
- unsigned int extra_hdrs;
- size_t extra;
-
- /*
- * Figure out how much extra memory we
- * need to allocate for this node type.
- */
- switch (type) {
- case XLAT_ALTERNATE:
- extra_hdrs = 2;
- extra = sizeof(xlat_exp_head_t) * 2;
- break;
-
- case XLAT_GROUP:
- extra_hdrs = 1;
- extra = sizeof(xlat_exp_head_t);
- break;
-
- case XLAT_FUNC:
- extra_hdrs = 1;
- extra = sizeof(xlat_exp_head_t);
- break;
-
- default:
- extra_hdrs = 0;
- extra = 0;
- }
-
- node = xlat_exp_alloc_pool(ctx,
- (in != NULL) + extra_hdrs,
- inlen + extra);
- xlat_exp_set_type(node, type);
-
- if (!in) return node;
-
- node->fmt = talloc_bstrndup(node, in, inlen);
- switch (type) {
- case XLAT_BOX:
- fr_value_box_strdup_shallow(&node->data, NULL, node->fmt, false);
- break;
-
- default:
- break;
- }
-
- return node;
-}
-
-/** Set the format string for an xlat node
- *
- * @param[in] node to set fmt for.
- * @param[in] fmt talloced buffer to set as the fmt string.
- */
-static inline void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt)
-{
- if (node->fmt) talloc_const_free(node->fmt);
- node->fmt = fmt;
-}
-
-
/** Mark an xlat function as internal
*
* @param[in] xlat to mark as internal.
*/
typedef int (*xlat_walker_t)(xlat_exp_t *exp, void *uctx);
+/*
+ * xlat_alloc.c
+ */
+xlat_exp_head_t *_xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx);
+#define xlat_exp_head_alloc(_ctx) _xlat_exp_head_alloc(NDEBUG_LOCATION_EXP _ctx)
+
+void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type);
+#define xlat_exp_set_type(_node, _type) _xlat_exp_set_type(NDEBUG_LOCATION_EXP _node, _type)
+
+xlat_exp_t *_xlat_exp_alloc_null(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx);
+#define xlat_exp_alloc_null(_ctx) _xlat_exp_alloc_null(NDEBUG_LOCATION_EXP _ctx)
+
+xlat_exp_t *_xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen);
+#define xlat_exp_alloc(_ctx, _type, _in, _inlen) _xlat_exp_alloc(NDEBUG_LOCATION_EXP _ctx, _type, _in, _inlen)
+
+void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt) CC_HINT(nonnull);
+
/*
* xlat_func.c
*/
-xlat_t *xlat_func_find(char const *name, ssize_t namelen);
+xlat_t *xlat_func_find(char const *name, ssize_t namelen);
/*
* xlat_eval.c
int unlang_xlat_push_node(TALLOC_CTX *ctx, bool *p_success, FR_DLIST_HEAD(fr_value_box_list) *out,
request_t *request, xlat_exp_t *node);
-int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out,
- request_t *request, void *decode_ctx, fr_pair_decode_t decode,
- FR_DLIST_HEAD(fr_value_box_list) *in);
+int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out,
+ request_t *request, void *decode_ctx, fr_pair_decode_t decode,
+ FR_DLIST_HEAD(fr_value_box_list) *in);
/*
* xlat_expr.c
*/
while ((box = fr_value_box_list_pop_head(list)) != NULL) {
MEM(node = xlat_exp_alloc(head, XLAT_BOX, NULL, 0));
fr_value_box_copy(node, &node->data, box);
- talloc_free(box);
if (node->data.type == FR_TYPE_STRING) {
node->quote = T_DOUBLE_QUOTED_STRING;
- node->fmt = node->data.vb_strvalue;
+ xlat_exp_set_name_buffer_shallow(node, node->data.vb_strvalue);
} else {
+ char *name;
+
node->quote = T_BARE_WORD;
- node->fmt = ""; /* @todo - fixme? */
+ fr_value_box_aprint(node, &name, box, NULL);
+
+ xlat_exp_set_name_buffer_shallow(node, name);
}
+ talloc_free(box);
xlat_exp_insert_tail(head, node);
}
{
int rcode;
bool success;
- xlat_exp_head_t *group;
FR_DLIST_HEAD(fr_value_box_list) list;
xlat_flags_t our_flags;
if (!success) return -1;
/*
- * The function call becomes a GROUP of boxes. We just re-use the argument head,
- * which is already of the type we need.
+ * The function call becomes a GROUP of boxes
*/
- /* coverity[dead_error_begin] */
- group = node->call.args;
- fr_dlist_talloc_free(&group->dlist);
-
xlat_inst_remove(node);
- node->type = XLAT_GROUP;
- node->group = group;
+ xlat_exp_set_type(node, XLAT_GROUP); /* Frees the argument list */
- xlat_value_list_to_xlat(group, &list);
- node->flags = group->flags;
+ xlat_value_list_to_xlat(node->group, &list);
+ node->flags = node->group->flags;
break;
}
MEM(node = xlat_exp_alloc(ctx, XLAT_FUNC, func->name, strlen(func->name)));
node->call.func = func;
- if (unlikely(xlat_copy(node, &node->call.args, args) < 0)) {
+ if (unlikely(xlat_copy(node, node->call.args, args) < 0)) {
talloc_free(node);
return NULL;
}
fr_sbuff_t *in,
tmpl_rules_t const *t_rules)
{
- xlat_exp_t *node, *arg_group;
+ xlat_exp_t *node;
xlat_t *func;
fr_sbuff_marker_t m_s;
fr_assert(head != NULL);
- INFO_INDENT("head flags = { %s %s %s }",
- head->flags.needs_resolving ? "need_resolving" : "",
+ INFO_INDENT("head flags = %s %s %s",
+ head->flags.needs_resolving ? "need_resolving," : "",
head->flags.pure ? "pure" : "",
head->flags.can_purify ? "can_purify" : "");
+ depth++;
+
xlat_exp_foreach(head, node) {
- INFO_INDENT("[%d] flags = { %s %s %s }", i++,
+ INFO_INDENT("[%d] flags = %s %s %s ", i++,
node->flags.needs_resolving ? "need_resolving" : "",
node->flags.pure ? "pure" : "",
node->flags.can_purify ? "can_purify" : "");
needs_resolving |= node->flags.needs_resolving;
#endif
+ INFO_INDENT("{");
+ depth++;
+
if (node->quote != T_BARE_WORD) INFO_INDENT("quote = %c", fr_token_quote[node->quote]);
switch (node->type) {
case XLAT_ALTERNATE:
DEBUG("XLAT-IF {");
- _xlat_debug(node->alternate[0], depth + 1);
+ _xlat_debug(node->alternate[0], depth);
DEBUG("}");
DEBUG("XLAT-ELSE {");
- _xlat_debug(node->alternate[1], depth + 1);
+ _xlat_debug(node->alternate[1], depth);
DEBUG("}");
break;
DEBUG("XLAT-INVALID");
break;
}
+
+ depth--;
+ INFO_INDENT("}");
}
fr_assert(needs_resolving == head->flags.needs_resolving);
* - 0 on success.
* - -1 on failure.
*/
-int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t **out, xlat_exp_head_t const *in)
+int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in)
{
- xlat_exp_head_t *head;
+ xlat_exp_head_t *head = NULL;
- if (!in) {
- *out = NULL;
- return 0;
- }
+ if (!in) return 0;
- MEM(head = xlat_exp_head_alloc(ctx));
- head->flags = in->flags;
+ xlat_flags_merge(&out->flags, &in->flags);
/*
* Copy everything in the list of nodes
xlat_exp_foreach(in, p) {
xlat_exp_t *node;
- MEM(node = xlat_exp_alloc(ctx, p->type, p->fmt, talloc_array_length(p->fmt) - 1));
+ (void)talloc_get_type_abort(p, xlat_exp_t);
+
+ /*
+ * Ensure the format string is valid... At this point
+ * they should all be talloc'd strings.
+ */
+ MEM(node = xlat_exp_alloc(ctx, p->type,
+ talloc_get_type_abort(p->fmt, char), talloc_array_length(p->fmt) - 1));
node->quote = p->quote;
node->flags = p->flags;
*/
node->call.func = p->call.func;
node->call.ephemeral = p->call.ephemeral;
- if (unlikely(xlat_copy(node, &node->call.args, p->call.args) < 0)) goto error;
+ if (unlikely(xlat_copy(node, node->call.args, p->call.args) < 0)) goto error;
break;
case XLAT_TMPL:
node->vpt = tmpl_copy(node, p->vpt);
- continue;
+ break;
#ifdef HAVE_REGEX
case XLAT_REGEX:
#endif
case XLAT_ALTERNATE:
- if (unlikely(xlat_copy(node, &node->alternate[0], p->alternate[0]) < 0)) goto error;
- if (unlikely(xlat_copy(node, &node->alternate[1], p->alternate[1]) < 0)) goto error;
+ if (unlikely(xlat_copy(node, node->alternate[0], p->alternate[0]) < 0)) goto error;
+ if (unlikely(xlat_copy(node, node->alternate[1], p->alternate[1]) < 0)) goto error;
break;
case XLAT_GROUP:
- if (unlikely(xlat_copy(node, &node->group, p->group) < 0)) goto error;
+ if (unlikely(xlat_copy(node, node->group, p->group) < 0)) goto error;
break;
}
- xlat_exp_insert_tail(head, node);
+ xlat_exp_insert_tail(out, node);
}
- *out = head;
return 0;
}