case XLAT_FUNC:
{
- xlat_exp_t const *arg = node->call.args;
char *out, *n_out;
TALLOC_CTX *pool;
char open = '{', close = '}';
open = '(';
close = ')';
}
- if (!arg) return talloc_asprintf(ctx, "%%%c%s:%c", open, node->call.func->name, close);
+
+ /*
+ * No arguments, just print an empty function.
+ */
+ if (!node->call.args) return talloc_asprintf(ctx, "%%%c%s:%c", open, node->call.func->name, close);
out = talloc_asprintf(ctx, "%%%c%s:", open, node->call.func->name);
pool = talloc_pool(NULL, 128); /* Size of a single child (probably ok...) */
- do {
+
+ xlat_exp_foreach(node->call.args, arg) {
char *arg_str;
arg_str = xlat_fmt_aprint(pool, arg);
first_done = true;
}
talloc_free_children(pool); /* Clear pool contents */
- } while ((arg = arg->next));
+ }
talloc_free(pool);
n_out = talloc_strndup_append_buffer(out, &close, 1);
fr_assert(0);
return XLAT_ACTION_FAIL;
}
-
}
finish:
* @param ctx The talloc_ctx
* @param[out] argv the argv array of resulting strings, size is argc + 1
* @param request the request
- * @param xlat from xlat_tokenize_argv()
+ * @param head from xlat_tokenize_argv()
* @param escape escape function
* @param escape_ctx context for escape function
* @return
* - >0 on success which is argc to the corresponding argv
*/
int xlat_aeval_compiled_argv(TALLOC_CTX *ctx, char ***argv, request_t *request,
- xlat_exp_t const *xlat, xlat_escape_legacy_t escape, void const *escape_ctx)
+ xlat_exp_t const *head, xlat_escape_legacy_t escape, void const *escape_ctx)
{
int i;
ssize_t slen;
char **my_argv;
size_t count;
- xlat_exp_t const *node;
- if (xlat->type != XLAT_GROUP) return -1;
+ if (head->type != XLAT_GROUP) return -1;
- for (count = 0, node = xlat; node != NULL; node = node->next) count++;
+ count = 0;
+ xlat_exp_foreach(head, node) {
+ count++;
+ }
MEM(my_argv = talloc_zero_array(ctx, char *, count + 1));
*argv = my_argv;
fr_assert(done_init);
- for (i = 0, node = xlat; node != NULL; i++, node = node->next) {
+ i = 0;
+ xlat_exp_foreach(head, node) {
my_argv[i] = NULL;
slen = _xlat_eval_compiled(my_argv, &my_argv[i], 0, request, node->group, escape, escape_ctx);
if (slen < 0) return -i;
+
+ i++;
}
return count;
*
* This is mostly for async use.
*/
-int xlat_flatten_compiled_argv(TALLOC_CTX *ctx, xlat_exp_t const ***argv, xlat_exp_t const *xlat)
+int xlat_flatten_compiled_argv(TALLOC_CTX *ctx, xlat_exp_t const ***argv, xlat_exp_t const *head)
{
int i;
xlat_exp_t const **my_argv;
- xlat_exp_t const *node;
size_t count;
- if (xlat->type != XLAT_GROUP) return -1;
+ if (head->type != XLAT_GROUP) return -1;
- for (count = 0, node = xlat; node != NULL; node = node->next) count++;
+ count = 0;
+ xlat_exp_foreach(head, node) {
+ count++;
+ }
MEM(my_argv = talloc_zero_array(ctx, xlat_exp_t const *, count + 1));
*argv = my_argv;
fr_assert(done_init);
- for (i = 0, node = xlat; node != NULL; i++, node = node->next) {
- my_argv[i] = node->group;
+ i = 0;
+ xlat_exp_foreach(head, node) {
+ my_argv[i++] = node->group;
}
return count;
/** Walk over all xlat nodes (depth first) in a xlat expansion, calling a callback
*
- * @param[in] exp to evaluate.
+ * @param[in] head to evaluate.
* @param[in] walker callback to pass nodes to.
* @param[in] type if > 0 a mask of types to call walker for.
* @param[in] uctx to pass to walker.
* - 0 on success (walker always returned 0).
* - <0 if walker returned <0.
*/
-int xlat_eval_walk(xlat_exp_t *exp, xlat_walker_t walker, xlat_type_t type, void *uctx)
+int xlat_eval_walk(xlat_exp_t *head, xlat_walker_t walker, xlat_type_t type, void *uctx)
{
- xlat_exp_t *node;
int ret;
/*
* Iterate over nodes at the same depth
*/
- for (node = exp; node; node = node->next) {
+ xlat_exp_foreach(head, node) {
switch (node->type){
case XLAT_FUNC:
if (!type || (type & XLAT_FUNC)) {
*
* If the xlat yields, then async is required.
*/
-bool xlat_async_required(xlat_exp_t const *xlat)
+bool xlat_async_required(xlat_exp_t const *head)
{
- xlat_exp_t const *node;
-
- if (xlat->type != XLAT_GROUP) {
- return xlat->flags.needs_async;
+ if (head->type != XLAT_GROUP) {
+ return head->flags.needs_async;
}
/*
* Set needs_async on the entire list.
*/
- for (node = xlat; node != NULL; node = node->next) {
+ xlat_exp_foreach(head, node) {
if (node->flags.needs_async) return true;
}
/*
* A pure function can have impure arguments, e.g. hash(sql query).
*/
- while (args) {
- node->flags.pure &= args->flags.pure;
- args = args->next;
+ xlat_exp_foreach(args, arg) {
+ node->flags.pure &= arg->flags.pure;
}
return node;
*/
fr_assert(arg->type == XLAT_GROUP);
- arg = arg->next;
+ arg = xlat_exp_next(node->call.args, arg);
}
return 0;
/*
* Temporary things until we swap to using tlists
*/
-#define xlat_append(_tail, _node) do { \
+#define xlat_exp_append(_tail, _node) do { \
*_tail = _node; \
_tail = &(_node)->next; \
_node = NULL; \
escapes ? escapes->name : "(none)",
fr_box_strvalue_len(str, talloc_array_length(str) - 1));
XLAT_HEXDUMP((uint8_t const *)str, talloc_array_length(str) - 1, " VALUE-BOX ");
- xlat_append(tail, node);
+ xlat_exp_append(tail, node);
} else if (slen < 0) {
error:
talloc_free(node);
if (slen == 0) TALLOC_FREE(node); /* Free the empty node */
if (xlat_tokenize_expansion(ctx, &node, flags, in, t_rules) < 0) goto error;
- xlat_append(tail, node);
+ xlat_exp_append(tail, node);
continue;
}
if (slen == 0) TALLOC_FREE(node); /* Free the empty node */
if (xlat_tokenize_function_args(ctx, &node, flags, in, t_rules) < 0) goto error;
- xlat_append(tail, node);
+ xlat_exp_append(tail, node);
continue;
}
node->flags.needs_async = false; /* value boxes are always non-async */
xlat_flags_merge(flags, &node->flags);
- xlat_append(tail, node);
+ xlat_exp_append(tail, node);
continue;
}
};
static size_t xlat_quote_table_len = NUM_ELEMENTS(xlat_quote_table);
-static void _xlat_debug(xlat_exp_t const *node, int depth)
+static void _xlat_debug(xlat_exp_t const *head, int depth)
{
-
#define INFO_INDENT(_fmt, ...) INFO("%*s"_fmt, depth * 2, " ", ## __VA_ARGS__)
- fr_assert(node != NULL);
- while (node) {
+ fr_assert(head != NULL);
+
+ xlat_exp_foreach(head, node) {
switch (node->type) {
case XLAT_BOX:
INFO_INDENT("value --> %pV", &node->data);
DEBUG("XLAT-INVALID");
break;
}
- node = node->next;
}
}
{
ssize_t slen;
size_t at_in = fr_sbuff_used_total(out);
- xlat_exp_t const *node = head;
+ xlat_exp_t const *node;
char close;
+ node = xlat_exp_head(head);
if (!node) return 0;
switch (node->type) {
if (node->quote != T_BARE_WORD) FR_SBUFF_IN_CHAR_RETURN(out, fr_token_quote[node->quote]);
xlat_print(out, node->group, fr_value_escape_by_quote[node->quote]);
if (node->quote != T_BARE_WORD) FR_SBUFF_IN_CHAR_RETURN(out, fr_token_quote[node->quote]);
- if (node->next) FR_SBUFF_IN_CHAR_RETURN(out, ' '); /* Add ' ' between args */
+
+ if (xlat_exp_next(head, node)) FR_SBUFF_IN_CHAR_RETURN(out, ' '); /* Add ' ' between args */
goto done;
case XLAT_BOX:
{
ssize_t slen;
size_t at_in = fr_sbuff_used_total(out);
- xlat_exp_t const *node = head;
-
- if (!node) return 0;
- while (node) {
+ xlat_exp_foreach(head, node) {
slen = xlat_print_node(out, node, e_rules);
if (slen < 0) return slen - (fr_sbuff_used_total(out) - at_in);
-
- node = node->next;
}
return fr_sbuff_used_total(out) - at_in;
xlat_exp_set_name_buffer_shallow(node, fmt);
xlat_flags_merge(flags, &node->flags);
- xlat_append(tail, node);
+ xlat_exp_append(tail, node);
/*
* If we're not and the end of the string
*/
bool xlat_is_literal(xlat_exp_t const *head)
{
- xlat_exp_t const *node;
-
- for (node = head;
- node;
- node = node->next) {
+ xlat_exp_foreach(head, node) {
if (node->type != XLAT_BOX) return false;
}
*/
bool xlat_to_string(TALLOC_CTX *ctx, char **str, xlat_exp_t **head)
{
- xlat_exp_t *node;
fr_sbuff_t out;
fr_sbuff_uctx_talloc_t tctx;
size_t len = 0;
* literals, so we need to walk the
* list until we find a non-literal.
*/
- for (node = *head; node; node = node->next) {
+ xlat_exp_foreach(*head, node) {
if (!xlat_is_literal(node)) return false;
len += talloc_array_length(node->fmt) - 1;
}
fr_sbuff_init_talloc(ctx, &out, &tctx, len, SIZE_MAX);
- for (node = *head; node; node = node->next) fr_sbuff_in_bstrcpy_buffer(&out, node->fmt);
+
+ xlat_exp_foreach(*head, node) {
+ fr_sbuff_in_bstrcpy_buffer(&out, node->fmt);
+ }
*str = fr_sbuff_buff(&out); /* No need to trim, should be the correct length */
int xlat_resolve(xlat_exp_t **head, xlat_flags_t *flags, xlat_res_rules_t const *xr_rules)
{
static xlat_res_rules_t xr_default;
- xlat_exp_t *node;
xlat_flags_t our_flags;
if (!flags->needs_resolving) return 0; /* Already done */
our_flags = *flags;
our_flags.needs_resolving = false; /* We flip this if not all resolutions are successful */
- for (node = *head; node; node = node->next) {
+ xlat_exp_foreach(*head, node) {
if (!node->flags.needs_resolving) continue; /* This node and non of its children need resolving */
switch (node->type) {
*/
int xlat_copy(TALLOC_CTX *ctx, xlat_exp_t **out, xlat_exp_t const *in)
{
- xlat_exp_t const *p;
xlat_exp_t **tail;
if (!in) {
/*
* Copy everything in the list of nodes
*/
- for (p = in; p; p = p->next) {
+ 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));
break;
}
- xlat_append(tail, node);
+ xlat_exp_append(tail, node);
}
return 0;