From: Arran Cudbard-Bell Date: Mon, 13 Feb 2023 03:35:34 +0000 (-0600) Subject: xlat: Integrate list allocation into node init X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3fd82695cc223fd7b9777acabbfa9ec75bc8c3ab;p=thirdparty%2Ffreeradius-server.git xlat: Integrate list allocation into node init --- diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index aa57a30119a..c5b97fa8efd 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -86,14 +86,12 @@ static void xlat_func_append_arg(xlat_exp_t *head, xlat_exp_t *node, bool exists 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); @@ -117,7 +115,6 @@ static xlat_exp_t *xlat_exists_alloc(TALLOC_CTX *ctx, xlat_exp_t *child) * 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; @@ -191,7 +188,6 @@ static int reparse_rcode(TALLOC_CTX *ctx, xlat_exp_t **p_arg, bool allow) } 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; @@ -1945,7 +1941,6 @@ static fr_slen_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf *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; @@ -1999,7 +1994,6 @@ static xlat_exp_t *expr_cast_alloc(TALLOC_CTX *ctx, fr_type_t type) * 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; @@ -2010,8 +2004,7 @@ static xlat_exp_t *expr_cast_alloc(TALLOC_CTX *ctx, fr_type_t type) * 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, @@ -2105,8 +2098,7 @@ static fr_slen_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_ /* * 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 '/' @@ -2265,8 +2257,7 @@ static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf /* * 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 @@ -2493,7 +2484,6 @@ static fr_slen_t tokenize_expression(xlat_exp_head_t *head, xlat_exp_t **out, fr 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))); @@ -2704,7 +2694,6 @@ redo: * 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; diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index 24a8e341526..d65947c0b0d 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -33,6 +33,7 @@ extern "C" { #include #include #include +#include #ifdef DEBUG_XLAT # define XLAT_DEBUG RDEBUG3 @@ -175,6 +176,21 @@ typedef struct { * 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 @@ -188,32 +204,87 @@ static inline CC_HINT(nonnull) void xlat_flags_merge(xlat_flags_t *parent, xlat_ 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. @@ -226,9 +297,38 @@ 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; - 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; @@ -374,47 +474,6 @@ ssize_t xlat_print_node(fr_sbuff_t *out, xlat_exp_head_t const *head, xlat_exp_ */ 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 diff --git a/src/lib/unlang/xlat_purify.c b/src/lib/unlang/xlat_purify.c index 7338b9bda31..42714a7431a 100644 --- a/src/lib/unlang/xlat_purify.c +++ b/src/lib/unlang/xlat_purify.c @@ -36,9 +36,7 @@ static void xlat_value_list_to_xlat(xlat_exp_head_t *head, FR_DLIST_HEAD(fr_valu 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); @@ -305,8 +303,7 @@ static int binary_peephole_optimize(TALLOC_CTX *ctx, xlat_exp_t **out, xlat_exp_ 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; diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index 40b968dd454..9f852e0dd0e 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -159,11 +159,7 @@ static inline int xlat_tokenize_alternation(xlat_exp_head_t *head, fr_sbuff_t *i 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: @@ -189,7 +185,7 @@ static inline int xlat_tokenize_alternation(xlat_exp_head_t *head, fr_sbuff_t *i * 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); @@ -288,7 +284,7 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head, 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; @@ -322,8 +318,7 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head, /* * 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"); @@ -533,7 +528,7 @@ int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in, 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); @@ -940,7 +935,7 @@ static int xlat_tokenize_string(xlat_exp_head_t *head, /* * 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 @@ -951,7 +946,6 @@ static int xlat_tokenize_string(xlat_exp_head_t *head, * 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; @@ -1526,9 +1520,7 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t * 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) { @@ -1564,8 +1556,7 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t 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,