29RCSID(
"$Id: 2699e0106b9345dfdbfda0faa146ddc89f92e873 $")
31#include <freeradius-devel/util/debug.h>
32#include <freeradius-devel/util/event.h>
33#include <freeradius-devel/util/sbuff.h>
34#include <freeradius-devel/util/value.h>
35#include <freeradius-devel/server/regex.h>
36#include <freeradius-devel/unlang/xlat_priv.h>
41# define XLAT_DEBUG(_fmt, ...) DEBUG3("%s[%i] "_fmt, __FILE__, __LINE__, ##__VA_ARGS__)
42# define XLAT_HEXDUMP(_data, _len, _fmt, ...) HEXDUMP3(_data, _len, "%s[%i] "_fmt, __FILE__, __LINE__, ##__VA_ARGS__)
44# define XLAT_DEBUG(...)
45# define XLAT_HEXDUMP(...)
138 if (num > REQUEST_MAX_REGEX) {
139 fr_strerror_printf(
"Invalid regex reference. Must be in range 0-%d", REQUEST_MAX_REGEX);
145 node->regex_index = num;
156 [
'.'] =
true, [
'-'] =
true, [
'_'] =
true,
275 if (arg_p->
type == node->data.
type) {
301 if (!node->call.func->args) {
302 if (node->call.args) {
313 if (!node->call.args) {
321 for (arg_p = node->call.func->args, i = 0; arg_p->
type !=
FR_TYPE_NULL; arg_p++) {
326 (
unsigned int)(arg_p - node->call.func->args) + 1);
367 fr_sbuff_marker(&m_s,
in);
381 if (strchr(
"cCdDeGHIlmMnSstTY", c) != NULL) {
390 if (!
n)
goto one_letter;
417 fr_sbuff_marker_release(&m_s);
419#ifdef STATIC_ANALYZER
420 if (!node->
fmt)
return -1;
450 fr_sbuff_marker_release(&m_s);
459 fr_sbuff_marker_release(&m_s);
461 (void) fr_sbuff_next(
in);
468 my_t_rules = *t_rules;
470 t_rules = &my_t_rules;
499 fr_sbuff_parse_rules_t const *p_rules,
tmpl_rules_t const *t_rules)
514 our_t_rules = *t_rules;
517 fr_sbuff_marker(&m_s,
in);
529 fr_sbuff_marker_release(&m_s);
538 if (!t_rules->attr.allow_unresolved) {
563 fr_sbuff_marker_release(&m_s);
569 [
'-'] =
true, [
'/'] =
true, [
'_'] =
true,
570 [
'.'] =
true, [
'*'] =
true, [
'#'] =
true,
571 [
'['] =
true, [
']'] =
true,
587 fr_sbuff_parse_rules_t attr_p_rules = {
597 fr_sbuff_marker(&m_s,
in);
601 if (ret < 0)
return ret;
617 if (!len)
goto empty_disallowed;
623 fr_sbuff_marker_release(&m_s);
641 my_rules.
enumv = NULL;
668 (void) fr_sbuff_next(
in);
684 fr_sbuff_marker(&m_s,
in);
695 fr_sbuff_marker_release(&m_s);
701 XLAT_DEBUG(
"EXPANSION HINT TOKEN '%c'", hint);
728 fr_sbuff_marker_release(&m_s);
776 fr_sbuff_parse_rules_t const *p_rules,
tmpl_rules_t const *t_rules)
789 escapes = p_rules ? p_rules->escapes : NULL;
790 tokens = p_rules && p_rules->terminals ?
805 fr_sbuff_marker(&m_s, &our_in);
806 slen = fr_sbuff_out_aunescape_until(node, &str, &our_in, SIZE_MAX, tokens,
escapes);
816 fr_sbuff_marker_release(&m_s);
841 fr_sbuff_marker_release(&m_s);
861 fr_strerror_const(
"Old style alternation of %{...:-...} is no longer supported");
866 fr_sbuff_marker_release(&m_s);
898 fr_sbuff_marker_release(&m_s);
917#define INFO_INDENT(_fmt, ...) INFO("%*s"_fmt, depth * 2, " ", ## __VA_ARGS__)
940 switch (node->
type) {
974 list = tmpl_request(node->vpt);
975 while ((rr = tmpl_request_list_next(list, rr))) {
1024 INFO_INDENT(
"regex-var -- %d", node->regex_index);
1029 DEBUG(
"XLAT-INVALID");
1049 head->flags.needs_resolving ?
"need_resolving," :
"",
1050 head->flags.pure ?
"pure" :
"",
1051 head->flags.can_purify ?
"can_purify" :
"",
1052 head->flags.constant ?
"constant" :
"",
1053 head->flags.xlat ?
"xlat" :
"");
1081 if (!node)
return 0;
1085 switch (node->
type) {
1103 if (node->data.enumv &&
1104 (strncmp(node->
fmt,
"::", 2) == 0)) {
1134 if (node->vpt->data.literal.enumv &&
1135 (strncmp(node->
fmt,
"::", 2) == 0)) {
1173 fr_assert(talloc_parent(node->vpt) == node);
1179 if (!node->vpt->rules.attr.xlat) {
1180 char const *p = node->
fmt;
1198 if (node->call.func->print) {
1199 slen = node->call.func->print(
out, node, node->call.inst->data, e_rules);
1200 if (slen < 0)
return slen;
1220 switch (node->
type) {
1223 if (slen < 0)
return slen;
1246 if (slen < 0)
return slen;
1292 switch (node->
type) {
1294 if (node->data.safe_for != safe_for) {
1295 ERROR(
"FAILED %lx %lx - %s", node->data.safe_for, safe_for, node->
fmt);
1297 fr_assert(node->data.safe_for == safe_for);
1301 xlat_safe_for(node->group, safe_for);
1307 xlat_safe_for(
tmpl_xlat(node->vpt), safe_for);
1319 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules)
1343 fr_sbuff_marker(&m, &our_in);
1352 fr_sbuff_marker(&m_s, &our_in);
1357 if (ret == 1)
goto done;
1386 (void) talloc_steal(ctx, node);
1405 if ((p[0] == c) && (p[1] == c)) {
1421 node->
quote = quote;
1450 node->
quote = quote;
1452 fr_sbuff_marker(&m, &our_in);
1487 node->
quote = quote;
1501 node->
quote = quote;
1503 slen = fr_sbuff_out_aunescape_until(node, &str, &our_in, SIZE_MAX, p_rules->terminals, p_rules->escapes);
1504 if (slen < 0)
goto error;
1523 fr_sbuff_set_to_start(&our_in);
1528 }
while (--triple > 0);
1561 fr_sbuff_parse_rules_t
const *our_p_rules;
1562 fr_sbuff_parse_rules_t tmp_p_rules;
1567 if (xlat && xlat->
args) {
1568 arg_start = arg = xlat->
args;
1572 arg_start = arg = &default_arg[0];
1574 arg_t_rules = *t_rules;
1581 tmp_p_rules = (fr_sbuff_parse_rules_t){
1586 our_p_rules = &tmp_p_rules;
1595 our_p_rules = p_rules;
1607 arg_t_rules.
enumv = NULL;
1609 arg_t_rules.
attr.namespace = NULL;
1610 arg_t_rules.
attr.request_def = NULL;
1621 fr_sbuff_marker(&m, &our_in);
1653 node->
quote = quote;
1664 slen =
xlat_tokenize_word(node->group, &child, &our_in, quote, our_p_rules, &arg_t_rules);
1698 (
size_t) (arg - arg_start), argc);
1728 fr_assert(p_rules && p_rules->terminals);
1746 if (our_p_rules->terminals) {
1771 (
size_t) (arg - arg_start), argc);
1800 fr_sbuff_parse_rules_t
const *p_rules,
tmpl_rules_t const *t_rules)
1853 return head->flags.needs_resolving;
1873 if (!*
head)
return false;
1883 len += talloc_array_length(node->
fmt) - 1;
1886 fr_sbuff_init_talloc(ctx, &
out, &tctx, len, SIZE_MAX);
1912 if (!
head->flags.needs_resolving)
return 0;
1914 if (!xr_rules) xr_rules = &xr_default;
1927 switch (node->
type) {
1929 if (
xlat_resolve(node->group, xr_rules) < 0)
return -1;
1980 if (node->call.func->resolve) {
1981 void *
inst = node->call.inst ? node->call.inst->data : NULL;
1983 if (node->call.func->resolve(node,
inst, xr_rules) < 0)
return -1;
1985 }
else if (node->call.args) {
1986 if (
xlat_resolve(node->call.args, xr_rules) < 0)
return -1;
2014 head->flags = our_flags;
2044 if (!
vpt)
return NULL;
2055 return head->flags.impure_func;
2073 return node->call.func->return_type;
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
static char const * spaces
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
static void * fr_dlist_pop_head(fr_dlist_head_t *list_head)
Remove the head item in a list.
#define FR_DLIST_HEAD(_name)
Expands to the type name used for the head wrapper structure.
static const bool escapes[UINT8_MAX+1]
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_BOOL
A truth value.
@ FR_SBUFF_PARSE_OK
No error.
static uint8_t depth(fr_minmax_heap_index_t i)
static void print_args(fr_log_t const *log, char const *file, int line, size_t arg_cnt, uint8_t const *argv, uint8_t const *start, uint8_t const *end)
fr_dict_attr_t const * request_attr_request
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static UINT8_MAX+1], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
ssize_t fr_sbuff_in_bstrcpy_buffer(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
fr_sbuff_term_t * fr_sbuff_terminals_amerge(TALLOC_CTX *ctx, fr_sbuff_term_t const *a, fr_sbuff_term_t const *b)
Merge two sets of terminal strings.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
bool const sbuff_char_alpha_num[UINT8_MAX+1]
#define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def)
#define fr_sbuff_adv_past_str_literal(_sbuff, _needle)
#define fr_sbuff_is_str_literal(_sbuff, _str)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define fr_sbuff_is_alnum(_sbuff_or_marker)
#define fr_sbuff_adv_past_whitespace(_sbuff, _len, _tt)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_char(_sbuff_or_marker, _eob)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
char const * name
Name for rule set to aid we debugging.
#define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str)
#define fr_sbuff_extend(_sbuff_or_marker)
#define fr_sbuff_buff(_sbuff_or_marker)
#define fr_sbuff_used_total(_sbuff_or_marker)
#define SBUFF_CHAR_CLASS_ALPHA_NUM
#define FR_SBUFF_RETURN(_func, _sbuff,...)
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define SBUFF_CHAR_UNPRINTABLES_EXTENDED
#define FR_SBUFF(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_out(_err, _out, _in)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define SBUFF_CHAR_UNPRINTABLES_LOW
#define fr_sbuff_behind(_sbuff_or_marker)
#define FR_SBUFF_TERM(_str)
Initialise a terminal structure with a single string.
#define FR_SBUFF_IN_STRCPY_RETURN(...)
#define FR_SBUFF_IN_BSTRCPY_BUFFER_RETURN(...)
Set of terminal elements.
Talloc sbuff extension structure.
Set of parsing rules for *unescape_until functions.
static int16_t tmpl_attr_tail_num(tmpl_t const *vpt)
Return the last attribute reference's attribute number.
#define tmpl_contains_xlat(vpt)
#define TMPL_VERIFY(_vpt)
#define tmpl_is_xlat(vpt)
#define tmpl_is_attr_unresolved(vpt)
#define tmpl_contains_data(vpt)
int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules))
Attempt to resolve functions and attributes in xlats and attribute references.
#define tmpl_value(_tmpl)
static fr_slen_t rql fr_slen_t tmpl_attr_print(fr_sbuff_t *out, tmpl_t const *vpt)
Print an attribute or list tmpl_t to a string.
tmpl_t * tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, fr_token_t quote, char const *name, ssize_t len)
Create a new heap allocated tmpl_t.
int tmpl_attr_unknown_add(tmpl_t *vpt)
Add an unknown fr_dict_attr_t specified by a tmpl_t to the main dictionary.
#define tmpl_contains_regex(vpt)
fr_value_box_safe_for_t literals_safe_for
safe_for value assigned to literal values in xlats, execs, and data.
#define tmpl_is_attr(vpt)
fr_dict_attr_t const * enumv
Enumeration attribute used to resolve enum values.
#define tmpl_value_enumv(_tmpl)
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
#define tmpl_rules_cast(_tmpl)
@ TMPL_TYPE_ATTR
Reference to one or more attributes.
ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Convert an arbitrary string into a tmpl_t.
fr_type_t tmpl_data_type(tmpl_t const *vpt)
tmpl_xlat_rules_t xlat
Rules/data for parsing xlats.
bool at_runtime
Produce an ephemeral/runtime tmpl.
ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, fr_sbuff_t *name, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
#define tmpl_is_data(vpt)
fr_dict_t const * dict_def
Alternative default dictionary to use if vpt->rules->dict_def is NULL.
#define tmpl_value_type(_tmpl)
static fr_type_t tmpl_cast_get(tmpl_t *vpt)
@ TMPL_ATTR_ERROR_MISSING_TERMINATOR
Unexpected text found after attribute reference.
#define tmpl_is_data_unresolved(vpt)
fr_type_t cast
Whether there was an explicit cast.
tmpl_attr_rules_t attr
Rules/data for parsing attribute references.
int tmpl_attr_copy(tmpl_t *dst, tmpl_t const *src)
Copy a list of attribute and request references from one tmpl to another.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
@ TMPL_ATTR_LIST_ALLOW
Attribute refs are allowed to have a list.
static char const * tmpl_list_name(fr_dict_attr_t const *list, char const *def)
Return the name of a tmpl list or def if list not provided.
fr_event_list_t * runtime_el
The eventlist to use for runtime instantiation of xlats.
#define tmpl_needs_resolving(vpt)
Optional arguments passed to vp_tmpl functions.
eap_aka_sim_process_conf_t * inst
Define entry and head types for tmpl request references.
tmpl_attr_list_presence_t list_presence
Whether the attribute reference can have a list, forbid it, or require it.
fr_dict_attr_t const * list_def
Default list to use with unqualified attribute reference.
uint8_t allow_unresolved
Allow attributes that look valid but were not found in the dictionaries.
fr_dict_t const * dict_def
Default dictionary to use with unqualified attribute references.
uint8_t allow_wildcard
Allow the special case of .
Define manipulation functions for the attribute reference list.
tmpl_request_ref_t _CONST request
An element in a lexicographically sorted array of name to num mappings.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
static int talloc_const_free(void const *ptr)
Free const'd memory.
const char fr_token_quote[T_TOKEN_LAST]
Convert tokens back to a quoting character.
@ T_SOLIDUS_QUOTED_STRING
tmpl_res_rules_t const * tr_rules
tmpl resolution rules.
fr_type_t type
Type to cast argument to.
#define XLAT_HEAD_VERIFY(_head)
uint8_t xlat
it's an xlat wrapper
int xlat_instance_register_func(xlat_exp_t *node)
Callback for creating "permanent" instance data for a xlat_exp_t.
bool required
Argument must be present, and non-empty.
xlat_escape_func_t func
Function to handle tainted values.
bool allow_unresolved
If false, all resolution steps must be completed.
@ XLAT_ARG_VARIADIC_EMPTY_SQUASH
Empty argument groups are removed.
xlat_arg_parser_variadic_t variadic
All additional boxes should be processed using this definition.
bool will_escape
the function will do escaping and concatenation.
fr_value_box_safe_for_t safe_for
Escaped value to set for boxes processed by this escape function.
uint8_t needs_resolving
Needs pass2 resolution.
uint8_t can_purify
if the xlat has a pure function with pure arguments.
uint8_t pure
has no external side effects, true for BOX, LITERAL, and some functions
#define XLAT_ARG_PARSER_TERMINATOR
int xlat_finalize(xlat_exp_head_t *head, fr_event_list_t *runtime_el)
Bootstrap static xlats, or instantiate ephemeral ones.
uint8_t constant
xlat is just tmpl_attr_tail_data, or XLAT_BOX
fr_slen_t xlat_tokenize_expression(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))
Definition for a single argument consumend by an xlat function.
Flags that control resolution and evaluation.
char const * fr_strerror(void)
Get the last library error.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules)
Print one boxed value to a string.
fr_sbuff_parse_rules_t const * value_parse_rules_quoted[T_TOKEN_LAST]
Parse rules for quoted strings.
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
fr_sbuff_escape_rules_t * fr_value_escape_by_quote[T_TOKEN_LAST]
fr_sbuff_parse_rules_t const * value_parse_rules_3quoted[T_TOKEN_LAST]
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, fr_token_t quote)
Print one boxed value to a string with quotes (where needed)
fr_sbuff_parse_rules_t const value_parse_rules_bareword_quoted
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
#define fr_value_box_mark_safe_for(_box, _safe_for)
#define fr_box_strvalue_buffer(_val)
#define fr_box_strvalue_len(_val, _len)
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out
void xlat_exp_finalize_func(xlat_exp_t *node)
void xlat_exp_set_vpt(xlat_exp_t *node, tmpl_t *vpt)
Set the tmpl for a node, along with flags and the name.
void xlat_exp_set_name(xlat_exp_t *node, char const *fmt, size_t len)
Set the format string for an xlat node.
void xlat_exp_set_func(xlat_exp_t *node, xlat_t const *func, fr_dict_t const *dict)
Set the function for a node.
void xlat_exp_set_name_shallow(xlat_exp_t *node, char const *fmt)
Set the format string for an xlat node from a pre-existing buffer.
fr_dict_attr_t const * attr_expr_bool_enum
xlat_t * xlat_func_find(char const *in, ssize_t inlen)
#define xlat_exp_head_alloc(_ctx)
xlat_flags_t flags
Flags that control resolution and evaluation.
#define xlat_exp_alloc_null(_ctx)
static xlat_exp_t * xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node)
int xlat_tokenize_regex(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in, fr_sbuff_marker_t *m_s)
fr_token_t quote
Type of quoting around XLAT_GROUP types.
@ XLAT_ONE_LETTER
Special "one-letter" expansion.
@ XLAT_TMPL
xlat attribute
@ XLAT_GROUP
encapsulated string of xlats
@ XLAT_FUNC_UNRESOLVED
func needs resolution during pass2.
@ XLAT_INVALID
Bad expansion.
xlat_arg_parser_t const * args
Definition of args consumed.
static void xlat_flags_merge(xlat_flags_t *parent, xlat_flags_t const *child)
Merge flags from child to parent.
#define xlat_exp_set_type(_node, _type)
char const *_CONST fmt
The original format string (a talloced buffer).
xlat_type_t _CONST type
type of this expansion.
#define xlat_exp_alloc(_ctx, _type, _in, _inlen)
#define xlat_exp_foreach(_list_head, _iter)
Iterate over the contents of a list, only one level.
static int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
static xlat_exp_t * xlat_exp_head(xlat_exp_head_t const *head)
bool xlat_needs_resolving(xlat_exp_head_t const *head)
Check to see if the expansion needs resolving.
#define INFO_INDENT(_fmt,...)
fr_slen_t xlat_tokenize(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)
Tokenize an xlat expansion.
bool xlat_is_literal(xlat_exp_head_t const *head)
Check to see if the expansion consists entirely of value-box elements.
static int xlat_validate_function_arg(xlat_arg_parser_t const *arg_p, xlat_exp_t *arg, int argc)
bool const xlat_func_chars[UINT8_MAX+1]
int xlat_validate_function_args(xlat_exp_t *node)
static fr_table_num_sorted_t const xlat_quote_table[]
void xlat_debug_head(xlat_exp_head_t const *head)
static void _xlat_debug_head(xlat_exp_head_t const *head, int depth)
bool xlat_impure_func(xlat_exp_head_t const *head)
fr_slen_t xlat_tokenize_word(TALLOC_CTX *ctx, xlat_exp_t **out, fr_sbuff_t *in, fr_token_t quote, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
static size_t xlat_quote_table_len
fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in, xlat_t const *xlat, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool spaces)
Tokenize an xlat expansion into a series of XLAT_TYPE_CHILD arguments.
tmpl_t * xlat_to_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t *head)
Try to convert an xlat to a tmpl for efficiency.
ssize_t xlat_print(fr_sbuff_t *out, xlat_exp_head_t const *head, fr_sbuff_escape_rules_t const *e_rules)
Reconstitute an xlat expression from its constituent nodes.
#define XLAT_HEXDUMP(...)
static fr_sbuff_parse_rules_t const xlat_function_arg_rules
Parse rules for literal values inside of an expansion.
bool xlat_to_string(TALLOC_CTX *ctx, char **str, xlat_exp_head_t **head)
Convert an xlat node to an unescaped literal string and free the original node.
static void _xlat_debug_node(xlat_exp_t const *node, int depth, bool print_flags)
static int xlat_tmpl_normalize(xlat_exp_t *node)
Normalize an xlat which contains a tmpl.
static fr_sbuff_unescape_rules_t const xlat_unescape
These rules apply to literal values and function arguments inside of an expansion.
static ssize_t xlat_tokenize_input(xlat_exp_head_t *head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
Parse an xlat string i.e.
void xlat_debug(xlat_exp_t const *node)
ssize_t xlat_print_node(fr_sbuff_t *out, xlat_exp_head_t const *head, xlat_exp_t const *node, fr_sbuff_escape_rules_t const *e_rules, char c)
static bool const tmpl_attr_allowed_chars[UINT8_MAX+1]
static fr_sbuff_escape_rules_t const xlat_escape
These rules apply to literal values and function arguments inside of an expansion.
static int xlat_tokenize_expansion(xlat_exp_head_t *head, fr_sbuff_t *in, tmpl_rules_t const *t_rules)
static ssize_t xlat_tokenize_attribute(xlat_exp_head_t *head, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
Parse an attribute ref or a virtual attribute.
int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
Walk over an xlat tree recursively, resolving any unresolved functions or references.
static int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in, tmpl_rules_t const *t_rules)
Parse an xlat function and its child argument.
fr_type_t xlat_data_type(xlat_exp_head_t const *head)