node = xlat_exists_alloc(head, node);
}
- group = xlat_exp_alloc_null(head->call.args);
- xlat_exp_set_type(group, XLAT_GROUP);
+ 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 */
group->flags = node->flags;
- MEM(group->group = xlat_exp_head_alloc(group));
talloc_steal(group->group, node);
xlat_exp_insert_tail(group->group, node);
* Create an "exists" node.
*/
MEM(node = xlat_exp_alloc(ctx, XLAT_FUNC, "exists", 6));
- MEM(node->call.args = xlat_exp_head_alloc(node));
MEM(node->call.func = xlat_func_find("exists", 6));
fr_assert(node->call.func != NULL);
node->flags = node->call.func->flags;
}
MEM(node = xlat_exp_alloc(ctx, XLAT_FUNC, arg->vpt->name, len));
- MEM(node->call.args = xlat_exp_head_alloc(node));
node->call.func = func;
node->flags = func->flags;
*out_c = c;
MEM(unary = xlat_exp_alloc(head, XLAT_FUNC, func->name, strlen(func->name)));
- MEM(unary->call.args = xlat_exp_head_alloc(unary));
unary->fmt = fr_tokens[func->token];
unary->call.func = func;
unary->flags = func->flags;
* whatever "node" comes next.
*/
MEM(cast = xlat_exp_alloc(ctx, XLAT_FUNC, "cast", 4));
- MEM(cast->call.args = xlat_exp_head_alloc(cast));
MEM(cast->call.func = xlat_func_find("cast", 4));
fr_assert(cast->call.func != NULL);
cast->flags = cast->call.func->flags;
* to print the name of the type, and not the
* number.
*/
- MEM(node = xlat_exp_alloc_null(cast));
- xlat_exp_set_type(node, XLAT_BOX);
+ MEM(node = xlat_exp_alloc(cast, XLAT_BOX, NULL, 0));
node->flags.constant = true;
xlat_exp_set_name_buffer_shallow(node,
talloc_strdup(node,
/*
* Allocate the xlat node now so the talloc hierarchy is correct
*/
- MEM(node = xlat_exp_alloc_null(head));
- xlat_exp_set_type(node, XLAT_TMPL);
+ MEM(node = xlat_exp_alloc(head, XLAT_TMPL, NULL, 0));
/*
* tmpl_afrom_substr does pretty much all the work of parsing the operand. Note that we pass '/'
/*
* Allocate the xlat node now so the talloc hierarchy is correct
*/
- MEM(node = xlat_exp_alloc_null(head));
- xlat_exp_set_type(node, XLAT_TMPL);
+ MEM(node = xlat_exp_alloc(head, XLAT_TMPL, NULL, 0));
/*
* tmpl_afrom_substr does pretty much all the work of
ssize_t slen;
fr_sbuff_marker_t m_lhs, m_op, m_rhs;
fr_sbuff_t our_in = FR_SBUFF(in);
- xlat_exp_head_t *args;
char c = '\0';
XLAT_DEBUG("EXPRESSION <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
* Create the function node, with the LHS / RHS arguments.
*/
MEM(node = xlat_exp_alloc(head, XLAT_FUNC, fr_tokens[op], strlen(fr_tokens[op])));
- MEM(node->call.args = args = xlat_exp_head_alloc(node));
node->fmt = fr_tokens[op];
node->call.func = func;
node->flags = func->flags;
#include <freeradius-devel/unlang/xlat_ctx.h>
#include <freeradius-devel/unlang/xlat.h>
#include <freeradius-devel/io/pair.h>
+#include <freeradius-devel/util/talloc.h>
#ifdef DEBUG_XLAT
# define XLAT_DEBUG RDEBUG3
* Helper functions
*/
+static inline xlat_exp_t *xlat_exp_head(xlat_exp_head_t const *head)
+{
+ if (!head) return NULL;
+
+ return fr_dlist_head(&head->dlist);
+}
+
+/** Iterate over the contents of a list, only one level
+ *
+ * @param[in] _list_head to iterate over.
+ * @param[in] _iter Name of iteration variable.
+ * Will be declared in the scope of the loop.
+ */
+#define xlat_exp_foreach(_list_head, _iter) fr_dlist_foreach(&((_list_head)->dlist), xlat_exp_t, _iter)
+
/** Merge flags from child to parent
*
* For pass2, if either the parent or child is marked up for pass2, then the parent
parent->constant &= child->constant;
}
+static inline CC_HINT(nonnull) int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
+{
+ xlat_flags_merge(&head->flags, &node->flags);
+ return fr_dlist_insert_tail(&head->dlist, node);
+}
+
+static inline xlat_exp_t *xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node)
+{
+ if (!head) return NULL;
+
+ 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;
+ }
}
-/** 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)
+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(ctx, xlat_exp_t));
+ 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.
char const *in, size_t inlen)
{
xlat_exp_t *node;
+ unsigned int extra_hdrs;
+ size_t extra;
- node = xlat_exp_alloc_null(ctx);
- node->type = type;
+ /*
+ * 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;
*/
int xlat_inst_remove(xlat_exp_t *node);
-static inline xlat_exp_t *xlat_exp_head(xlat_exp_head_t const *head)
-{
- if (!head) return NULL;
-
- return fr_dlist_head(&head->dlist);
-}
-
-/** Iterate over the contents of a list, only one level
- *
- * @param[in] _list_head to iterate over.
- * @param[in] _iter Name of iteration variable.
- * Will be declared in the scope of the loop.
- */
-#define xlat_exp_foreach(_list_head, _iter) fr_dlist_foreach(&((_list_head)->dlist), xlat_exp_t, _iter)
-
-static inline xlat_exp_t *xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node)
-{
- if (!head) return NULL;
-
- return fr_dlist_next(&head->dlist, node);
-}
-
-static inline int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
-{
- xlat_flags_merge(&head->flags, &node->flags);
- return fr_dlist_insert_tail(&head->dlist, node);
-}
-
-static inline xlat_exp_head_t *xlat_exp_head_alloc(TALLOC_CTX *ctx)
-{
- xlat_exp_head_t *head;
-
- head = talloc_zero(ctx, xlat_exp_head_t);
- if (!head) return NULL;
-
- fr_dlist_init(&head->dlist, xlat_exp_t, entry);
- head->flags.pure = true;
-
- return head;
-}
-
#ifdef __cplusplus
}
#endif
xlat_exp_t *node;
while ((box = fr_value_box_list_pop_head(list)) != NULL) {
- MEM(node = xlat_exp_alloc_null(head));
- node->type = XLAT_BOX;
-
+ MEM(node = xlat_exp_alloc(head, XLAT_BOX, NULL, 0));
fr_value_box_copy(node, &node->data, box);
talloc_free(box);
if (fr_value_calc_binary_op(lhs, &box, FR_TYPE_NULL, lhs_box, op, rhs_box) < 0) return -1;
- MEM(node = xlat_exp_alloc_null(ctx));
- xlat_exp_set_type(node, XLAT_BOX);
+ MEM(node = xlat_exp_alloc(ctx, XLAT_BOX, NULL, 0));
if (box.type == FR_TYPE_BOOL) box.enumv = attr_expr_bool_enum;
XLAT_DEBUG("ALTERNATE <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
- node = xlat_exp_alloc_null(head);
- xlat_exp_set_type(node, XLAT_ALTERNATE);
- MEM(node->alternate[0] = xlat_exp_head_alloc(node));
- MEM(node->alternate[1] = xlat_exp_head_alloc(node));
-
+ node = xlat_exp_alloc(head, XLAT_ALTERNATE, NULL, 0);
if (func_args) {
if (xlat_tokenize_function_args(node->alternate[0], in, t_rules) < 0) {
error:
* Parse the alternate expansion.
*/
if (xlat_tokenize_string(node->alternate[1], in,
- true, &xlat_expansion_rules, t_rules) < 0) goto error;
+ true, &xlat_expansion_rules, t_rules) < 0) goto error;
if (!xlat_exp_head(node->alternate[1])) {
talloc_free(node);
fr_sbuff_t *in,
tmpl_rules_t const *t_rules)
{
- xlat_exp_t *node;
+ xlat_exp_t *node, *arg_group;
xlat_t *func;
fr_sbuff_marker_t m_s;
/*
* Allocate a node to hold the function
*/
- MEM(node = xlat_exp_alloc(head, XLAT_FUNC, fr_sbuff_current(&m_s), fr_sbuff_behind(&m_s)));
- MEM(node->call.args = xlat_exp_head_alloc(node));
+ node = xlat_exp_alloc(head, XLAT_FUNC, fr_sbuff_current(&m_s), fr_sbuff_behind(&m_s));
if (!func) {
if (!t_rules || !t_rules->attr.allow_unresolved) {
fr_strerror_const("Unresolved expansion functions are not allowed here");
xlat_exp_set_type(node, XLAT_FUNC_UNRESOLVED);
node->flags.needs_resolving = true; /* Needs resolution during pass2 */
} else {
- if (func && (func->input_type != XLAT_INPUT_ARGS)) {
+ if (func->input_type != XLAT_INPUT_ARGS) {
fr_strerror_const("Function should be called using %{func:arg} syntax");
error:
talloc_free(node);
/*
* pre-allocate the node so we don't have to steal it later.
*/
- node = xlat_exp_alloc_null(head);
+ node = xlat_exp_alloc(head, XLAT_BOX, NULL, 0);
/*
* Find the next token
* It's a value box, create an appropriate node
*/
if (slen > 0) {
- xlat_exp_set_type(node, XLAT_BOX);
xlat_exp_set_name_buffer_shallow(node, str);
fr_value_box_strdup_shallow(&node->data, NULL, str, false);
node->flags.constant = true;
* Alloc a new node to hold the child nodes
* that make up the argument.
*/
- MEM(node = xlat_exp_alloc_null(head));
- xlat_exp_set_type(node, XLAT_GROUP);
- MEM(node->group = xlat_exp_head_alloc(node));
+ MEM(node = xlat_exp_alloc(head, XLAT_GROUP, 0, NULL));
node->quote = quote;
switch (quote) {
char *str;
xlat_exp_t *child;
- child = xlat_exp_alloc_null(node->group);
- xlat_exp_set_type(child, XLAT_BOX);
+ child = xlat_exp_alloc(node->group, XLAT_BOX, NULL, 0);
node->flags.constant = true;
slen = fr_sbuff_out_aunescape_until(child, &str, &our_in, SIZE_MAX,