The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Data Structures | Macros | Functions | Variables
xlat_expr.c File Reference

Tokenizers and support functions for xlat expressions. More...

#include <freeradius-devel/server/base.h>
#include <freeradius-devel/unlang/xlat_priv.h>
#include <freeradius-devel/util/calc.h>
#include <freeradius-devel/server/tmpl_dcursor.h>
#include <freeradius-devel/unlang/xlat_func.h>
+ Include dependency graph for xlat_expr.c:

Go to the source code of this file.

Data Structures

struct  xlat_exists_inst_t
 
struct  xlat_exists_rctx_t
 
struct  xlat_logical_inst_t
 
struct  xlat_logical_rctx_t
 
struct  xlat_regex_inst_t
 
struct  xlat_regex_rctx_t
 

Macros

#define fr_sbuff_skip_whitespace(_x)
 
#define P(_x, _y)   (((_x) << 4) | (_y))
 
#define XLAT_BINARY_FUNC(_name, _op)
 
#define XLAT_CMP_FUNC(_name, _op)
 
#define XLAT_DEBUG(...)
 
#define XLAT_REGEX_FUNC(_name, _op)
 
#define XLAT_REGISTER_BINARY_CMP(_op, _name)
 
#define XLAT_REGISTER_BINARY_OP(_op, _name)
 
#define XLAT_REGISTER_MONO(_xlat, _func, _arg)
 
#define XLAT_REGISTER_NARY_OP(_op, _name, _func_name)
 
#define XLAT_REGISTER_REGEX_OP(_op, _name)
 
#define XLAT_REGISTER_UNARY(_op, _xlat, _func)
 

Functions

static xlat_exp_texpr_cast_alloc (TALLOC_CTX *ctx, fr_type_t type)
 Allocate a specific cast node. More...
 
static fr_slen_t expr_cast_from_substr (fr_type_t *cast, fr_sbuff_t *in)
 
static void fr_value_box_init_zero (fr_value_box_t *vb, fr_type_t type)
 
static int reparse_rcode (TALLOC_CTX *ctx, xlat_exp_t **p_arg, bool allow)
 
static ssize_t tokenize_expression (xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_token_t prev, fr_sbuff_parse_rules_t const *bracket_rules, fr_sbuff_parse_rules_t const *input_rules, bool cond)
 Tokenize a mathematical operation. More...
 
static ssize_t tokenize_field (xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_sbuff_parse_rules_t const *bracket_rules, char *out_c, bool cond)
 
static fr_slen_t tokenize_regex_rhs (xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in, tmpl_rules_t const *t_rules, fr_sbuff_parse_rules_t const *bracket_rules)
 
static fr_slen_t tokenize_unary (xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in, fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, fr_sbuff_parse_rules_t const *bracket_rules, char *out_c, bool cond)
 
static bool valid_type (xlat_exp_t *node)
 
static xlat_action_t xlat_attr_exists (TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, tmpl_t const *vpt, bool do_free)
 
static xlat_action_t xlat_binary_op (TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in, fr_token_t op, fr_type_t default_type, fr_dict_attr_t const *enumv)
 
static xlat_action_t xlat_cmp_op (TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in, fr_token_t op)
 
static xlat_exp_txlat_exists_alloc (TALLOC_CTX *ctx, xlat_exp_t *child)
 Allocate a specific cast node. More...
 
static xlat_action_t xlat_exists_resume (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
 
static int xlat_expr_logical_purify (xlat_exp_t *node, void *instance, request_t *request)
 If any argument resolves to inst->stop_on_match, the entire thing is a bool of inst->stop_on_match. More...
 
static fr_slen_t xlat_expr_print_binary (fr_sbuff_t *out, xlat_exp_t const *node, UNUSED void *inst, fr_sbuff_escape_rules_t const *e_rules)
 
static fr_slen_t xlat_expr_print_exists (fr_sbuff_t *out, xlat_exp_t const *node, void *instance, fr_sbuff_escape_rules_t const *e_rules)
 
static fr_slen_t xlat_expr_print_nary (fr_sbuff_t *out, xlat_exp_t const *node, void *instance, fr_sbuff_escape_rules_t const *e_rules)
 
static fr_slen_t xlat_expr_print_regex (fr_sbuff_t *out, xlat_exp_t const *node, void *instance, fr_sbuff_escape_rules_t const *e_rules)
 
static fr_slen_t xlat_expr_print_unary (fr_sbuff_t *out, xlat_exp_t const *node, UNUSED void *inst, fr_sbuff_escape_rules_t const *e_rules)
 
static int xlat_expr_resolve_binary (xlat_exp_t *node, UNUSED void *inst, xlat_res_rules_t const *xr_rules)
 
static void xlat_func_append_arg (xlat_exp_t *head, xlat_exp_t *node, bool exists)
 
static xlat_action_t xlat_func_exists (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
 See if a named attribute exists. More...
 
static xlat_action_t xlat_func_logical (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
 Process logical &&, ||. More...
 
static xlat_action_t xlat_func_rcode (TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *args)
 Return the rcode as a string, or bool match if the argument is an rcode name. More...
 
static xlat_action_t xlat_func_unary_complement (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
 
static xlat_action_t xlat_func_unary_minus (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
 
static xlat_action_t xlat_func_unary_not (TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in)
 
static xlat_action_t xlat_func_unary_op (TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in, fr_token_t op)
 
static int xlat_function_args_to_tmpl (xlat_inst_ctx_t const *xctx)
 Convert XLAT_BOX arguments to XLAT_TMPL. More...
 
static int xlat_instantiate_exists (xlat_inst_ctx_t const *xctx)
 
static int xlat_instantiate_logical (xlat_inst_ctx_t const *xctx)
 
static int xlat_instantiate_regex (xlat_inst_ctx_t const *xctx)
 
bool xlat_is_truthy (xlat_exp_head_t const *head, bool *out)
 Allow callers to see if an xlat is truthy. More...
 
static bool xlat_logical_and (xlat_logical_rctx_t *rctx, fr_value_box_list_t const *in)
 See if the input is truthy or not. More...
 
static xlat_action_t xlat_logical_and_resume (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
 
static bool xlat_logical_or (xlat_logical_rctx_t *rctx, fr_value_box_list_t const *in)
 See if the input is truthy or not. More...
 
static xlat_action_t xlat_logical_or_resume (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
 
static xlat_action_t xlat_logical_process_arg (UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
 Process one argument of a logical operation. More...
 
static bool xlat_node_matches_bool (bool *result, xlat_exp_t *parent, xlat_exp_head_t *head, bool sense)
 
static xlat_action_t xlat_regex_match (TALLOC_CTX *ctx, request_t *request, fr_value_box_list_t *in, regex_t **preg, fr_dcursor_t *out, fr_token_t op)
 Perform a regular expressions comparison between two operands. More...
 
static xlat_action_t xlat_regex_op (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in, fr_token_t op)
 
static xlat_action_t xlat_regex_resume (TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
 
int xlat_register_expressions (void)
 
fr_slen_t xlat_tokenize_condition (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)
 
fr_slen_t xlat_tokenize_expression (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)
 
static fr_slen_t xlat_tokenize_expression_internal (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, bool cond)
 
static void xlat_ungroup (xlat_exp_head_t *head)
 Undo work which shouldn't have been done. More...
 

Variables

static xlat_arg_parser_t const binary_cmp_xlat_args []
 
static xlat_arg_parser_t const binary_op_xlat_args []
 
static const fr_sbuff_term_elem_t binary_ops [T_TOKEN_LAST]
 
static const fr_sbuff_term_t bracket_terms
 
static fr_table_num_ordered_t const expr_assignment_op_table []
 
static size_t const expr_assignment_op_table_len = NUM_ELEMENTS(expr_assignment_op_table)
 
static fr_table_num_sorted_t const expr_quote_table []
 
static size_t expr_quote_table_len = NUM_ELEMENTS(expr_quote_table)
 
static const bool logical_ops [T_TOKEN_LAST]
 
static const bool multivalue_ops [T_TOKEN_LAST]
 
static const fr_sbuff_term_t operator_terms
 
static const int precedence [T_TOKEN_LAST]
 
static const fr_sbuff_escape_rules_t regex_escape_rules
 
static xlat_arg_parser_t const regex_op_xlat_args []
 
static xlat_arg_parser_t const unary_op_xlat_args []
 
static xlat_arg_parser_t const xlat_func_exists_arg []
 
static xlat_arg_parser_t const xlat_func_rcode_arg []
 

Detailed Description

Tokenizers and support functions for xlat expressions.

Id
1793441aef55022ee960429ea63e78b8aaa998e8

Definition in file xlat_expr.c.


Data Structure Documentation

◆ xlat_exists_inst_t

struct xlat_exists_inst_t

Definition at line 1574 of file xlat_expr.c.

+ Collaboration diagram for xlat_exists_inst_t:
Data Fields
tmpl_t const * vpt the attribute reference
xlat_exp_head_t * xlat the xlat which needs expanding

◆ xlat_exists_rctx_t

struct xlat_exists_rctx_t

Definition at line 1579 of file xlat_expr.c.

Data Fields
bool last_success
fr_value_box_list_t list

◆ xlat_logical_inst_t

struct xlat_logical_inst_t

Definition at line 839 of file xlat_expr.c.

+ Collaboration diagram for xlat_logical_inst_t:
Data Fields
int argc
xlat_exp_head_t ** argv
xlat_func_t callback
bool stop_on_match

◆ xlat_logical_rctx_t

struct xlat_logical_rctx_t

Definition at line 846 of file xlat_expr.c.

+ Collaboration diagram for xlat_logical_rctx_t:
Data Fields
fr_value_box_t * box output value-box
TALLOC_CTX * ctx
int current
bool last_success
fr_value_box_list_t list

◆ xlat_regex_inst_t

struct xlat_regex_inst_t

Definition at line 516 of file xlat_expr.c.

+ Collaboration diagram for xlat_regex_inst_t:
Data Fields
fr_token_t op
regex_t * regex precompiled regex
fr_regex_flags_t * regex_flags
xlat_exp_t * xlat to expand

◆ xlat_regex_rctx_t

struct xlat_regex_rctx_t

Definition at line 523 of file xlat_expr.c.

Data Fields
bool last_success
fr_value_box_list_t list

Macro Definition Documentation

◆ fr_sbuff_skip_whitespace

#define fr_sbuff_skip_whitespace (   _x)
Value:
do { \
while (isspace((uint8_t) fr_sbuff_char(_x, '\0'))) fr_sbuff_advance(_x, 1); \
} while (0)
while(1)
Definition: acutest.h:856
unsigned char uint8_t
Definition: merged_model.c:30
#define fr_sbuff_char(_sbuff_or_marker, _eob)
#define fr_sbuff_advance(_sbuff_or_marker, _len)

Definition at line 1970 of file xlat_expr.c.

◆ P

#define P (   _x,
  _y 
)    (((_x) << 4) | (_y))

Definition at line 1914 of file xlat_expr.c.

◆ XLAT_BINARY_FUNC

#define XLAT_BINARY_FUNC (   _name,
  _op 
)
Value:
static xlat_action_t xlat_func_ ## _name(TALLOC_CTX *ctx, fr_dcursor_t *out, \
xlat_ctx_t const *xctx, \
request_t *request, fr_value_box_list_t *in) \
{ \
return xlat_binary_op(ctx, out, xctx, request, in, _op, FR_TYPE_NULL, NULL); \
}
static fr_slen_t in
Definition: dict.h:645
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
xlat_action_t
Definition: xlat.h:35
static size_t char ** out
Definition: value.h:984
An xlat calling ctx.
Definition: xlat_ctx.h:42
static xlat_action_t xlat_binary_op(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in, fr_token_t op, fr_type_t default_type, fr_dict_attr_t const *enumv)
Definition: xlat_expr.c:370

Definition at line 436 of file xlat_expr.c.

◆ XLAT_CMP_FUNC

#define XLAT_CMP_FUNC (   _name,
  _op 
)
Value:
static xlat_action_t xlat_func_ ## _name(TALLOC_CTX *ctx, fr_dcursor_t *out, \
xlat_ctx_t const *xctx, \
request_t *request, fr_value_box_list_t *in) \
{ \
return xlat_cmp_op(ctx, out, xctx, request, in, _op); \
}
static xlat_action_t xlat_cmp_op(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, fr_value_box_list_t *in, fr_token_t op)
Definition: xlat_expr.c:461

Definition at line 499 of file xlat_expr.c.

◆ XLAT_DEBUG

#define XLAT_DEBUG (   ...)

Definition at line 39 of file xlat_expr.c.

◆ XLAT_REGEX_FUNC

#define XLAT_REGEX_FUNC (   _name,
  _op 
)
Value:
static xlat_action_t xlat_func_ ## _name(TALLOC_CTX *ctx, fr_dcursor_t *out, \
xlat_ctx_t const *xctx, \
request_t *request, fr_value_box_list_t *in) \
{ \
return xlat_regex_op(ctx, out, xctx, request, in, _op); \
}
static xlat_action_t xlat_regex_op(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in, fr_token_t op)
Definition: xlat_expr.c:795

Definition at line 828 of file xlat_expr.c.

◆ XLAT_REGISTER_BINARY_CMP

#define XLAT_REGISTER_BINARY_CMP (   _op,
  _name 
)
Value:
do { \
if (unlikely((xlat = xlat_func_register(NULL, "cmp_" STRINGIFY(_name), xlat_func_cmp_ ## _name, FR_TYPE_BOOL)) == NULL)) return -1; \
xlat_func_args_set(xlat, binary_cmp_xlat_args); \
xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE | XLAT_FUNC_FLAG_INTERNAL); \
xlat_func_print_set(xlat, xlat_expr_print_binary); \
xlat_func_resolve_set(xlat, xlat_expr_resolve_binary); \
xlat->token = _op; \
} while (0)
#define STRINGIFY(x)
Definition: build.h:195
#define unlikely(_x)
Definition: build.h:378
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
static fr_slen_t xlat_expr_print_binary(fr_sbuff_t *out, xlat_exp_t const *node, UNUSED void *inst, fr_sbuff_escape_rules_t const *e_rules)
Definition: xlat_expr.c:219
static int xlat_expr_resolve_binary(xlat_exp_t *node, UNUSED void *inst, xlat_res_rules_t const *xr_rules)
Definition: xlat_expr.c:242
static xlat_arg_parser_t const binary_cmp_xlat_args[]
Definition: xlat_expr.c:455
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition: xlat_func.c:195
@ XLAT_FUNC_FLAG_PURE
Definition: xlat_func.h:38
@ XLAT_FUNC_FLAG_INTERNAL
Definition: xlat_func.h:39

Definition at line 1759 of file xlat_expr.c.

◆ XLAT_REGISTER_BINARY_OP

#define XLAT_REGISTER_BINARY_OP (   _op,
  _name 
)
Value:
do { \
if (unlikely((xlat = xlat_func_register(NULL, "op_" STRINGIFY(_name), xlat_func_op_ ## _name, FR_TYPE_VOID)) == NULL)) return -1; \
xlat_func_args_set(xlat, binary_op_xlat_args); \
xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE | XLAT_FUNC_FLAG_INTERNAL); \
xlat_func_print_set(xlat, xlat_expr_print_binary); \
xlat_func_instantiate_set(xlat, xlat_function_args_to_tmpl, NULL, NULL, NULL); \
xlat->token = _op; \
} while (0)
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
static int xlat_function_args_to_tmpl(xlat_inst_ctx_t const *xctx)
Convert XLAT_BOX arguments to XLAT_TMPL.
Definition: xlat_expr.c:1493
static xlat_arg_parser_t const binary_op_xlat_args[]
Definition: xlat_expr.c:364

Definition at line 1748 of file xlat_expr.c.

◆ XLAT_REGISTER_MONO

#define XLAT_REGISTER_MONO (   _xlat,
  _func,
  _arg 
)
Value:
do { \
if (unlikely((xlat = xlat_func_register(NULL, _xlat, _func, FR_TYPE_VOID)) == NULL)) return -1; \
xlat_func_mono_set(xlat, _arg); \
xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_INTERNAL); \
} while (0)

Definition at line 1791 of file xlat_expr.c.

◆ XLAT_REGISTER_NARY_OP

#define XLAT_REGISTER_NARY_OP (   _op,
  _name,
  _func_name 
)
Value:
do { \
if (unlikely((xlat = xlat_func_register(NULL, STRINGIFY(_name), xlat_func_ ## _func_name, FR_TYPE_VOID)) == NULL)) return -1; \
xlat_func_instantiate_set(xlat, xlat_instantiate_ ## _func_name, xlat_ ## _func_name ## _inst_t, NULL, NULL); \
xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE | XLAT_FUNC_FLAG_INTERNAL); \
xlat_func_print_set(xlat, xlat_expr_print_nary); \
xlat_purify_func_set(xlat, xlat_expr_logical_purify); \
xlat->token = _op; \
} while (0)
static fr_slen_t xlat_expr_print_nary(fr_sbuff_t *out, xlat_exp_t const *node, void *instance, fr_sbuff_escape_rules_t const *e_rules)
Definition: xlat_expr.c:854
static int xlat_expr_logical_purify(xlat_exp_t *node, void *instance, request_t *request)
If any argument resolves to inst->stop_on_match, the entire thing is a bool of inst->stop_on_match.
Definition: xlat_expr.c:979

Definition at line 1770 of file xlat_expr.c.

◆ XLAT_REGISTER_REGEX_OP

#define XLAT_REGISTER_REGEX_OP (   _op,
  _name 
)
Value:
do { \
if (unlikely((xlat = xlat_func_register(NULL, STRINGIFY(_name), xlat_func_ ## _name, FR_TYPE_VOID)) == NULL)) return -1; \
xlat_func_args_set(xlat, regex_op_xlat_args); \
xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE | XLAT_FUNC_FLAG_INTERNAL); \
xlat_func_instantiate_set(xlat, xlat_instantiate_regex, xlat_regex_inst_t, NULL, NULL); \
xlat_func_print_set(xlat, xlat_expr_print_regex); \
xlat->token = _op; \
} while (0)
static xlat_arg_parser_t const regex_op_xlat_args[]
Definition: xlat_expr.c:642
static int xlat_instantiate_regex(xlat_inst_ctx_t const *xctx)
Definition: xlat_expr.c:567
static fr_slen_t xlat_expr_print_regex(fr_sbuff_t *out, xlat_exp_t const *node, void *instance, fr_sbuff_escape_rules_t const *e_rules)
Definition: xlat_expr.c:528

Definition at line 1781 of file xlat_expr.c.

◆ XLAT_REGISTER_UNARY

#define XLAT_REGISTER_UNARY (   _op,
  _xlat,
  _func 
)
Value:
do { \
if (unlikely((xlat = xlat_func_register(NULL, _xlat, _func, FR_TYPE_VOID)) == NULL)) return -1; \
xlat_func_args_set(xlat, unary_op_xlat_args); \
xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE | XLAT_FUNC_FLAG_INTERNAL); \
xlat_func_print_set(xlat, xlat_expr_print_unary); \
xlat->token = _op; \
} while (0)
static fr_slen_t xlat_expr_print_unary(fr_sbuff_t *out, xlat_exp_t const *node, UNUSED void *inst, fr_sbuff_escape_rules_t const *e_rules)
Definition: xlat_expr.c:209
static xlat_arg_parser_t const unary_op_xlat_args[]
Definition: xlat_expr.c:1392

Definition at line 1798 of file xlat_expr.c.

Function Documentation

◆ expr_cast_alloc()

static xlat_exp_t* expr_cast_alloc ( TALLOC_CTX *  ctx,
fr_type_t  type 
)
static

Allocate a specific cast node.

With the first argument being a UINT8 of the data type. See xlat_func_cast() for the implementation.

Definition at line 2121 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expr_cast_from_substr()

static fr_slen_t expr_cast_from_substr ( fr_type_t cast,
fr_sbuff_t in 
)
static

Definition at line 2156 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_value_box_init_zero()

static void fr_value_box_init_zero ( fr_value_box_t vb,
fr_type_t  type 
)
static

Definition at line 347 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reparse_rcode()

static int reparse_rcode ( TALLOC_CTX *  ctx,
xlat_exp_t **  p_arg,
bool  allow 
)
static

Definition at line 133 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tokenize_expression()

static fr_slen_t tokenize_expression ( xlat_exp_head_t head,
xlat_exp_t **  out,
fr_sbuff_t in,
fr_sbuff_parse_rules_t const *  p_rules,
tmpl_rules_t const *  t_rules,
fr_token_t  prev,
fr_sbuff_parse_rules_t const *  bracket_rules,
fr_sbuff_parse_rules_t const *  input_rules,
bool  cond 
)
static

Tokenize a mathematical operation.

(EXPR)
!EXPR
A OP B

If "out" is NULL then the expression is added to "head".
Otherwise, it's returned to the caller.

Definition at line 2649 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tokenize_field()

static fr_slen_t tokenize_field ( xlat_exp_head_t head,
xlat_exp_t **  out,
fr_sbuff_t in,
fr_sbuff_parse_rules_t const *  p_rules,
tmpl_rules_t const *  t_rules,
fr_sbuff_parse_rules_t const *  bracket_rules,
char *  out_c,
bool  cond 
)
static

Definition at line 2296 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tokenize_regex_rhs()

static fr_slen_t tokenize_regex_rhs ( xlat_exp_head_t head,
xlat_exp_t **  out,
fr_sbuff_t in,
tmpl_rules_t const *  t_rules,
fr_sbuff_parse_rules_t const *  bracket_rules 
)
static

Definition at line 2196 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ tokenize_unary()

static fr_slen_t tokenize_unary ( xlat_exp_head_t head,
xlat_exp_t **  out,
fr_sbuff_t in,
fr_sbuff_parse_rules_t const *  p_rules,
tmpl_rules_t const *  t_rules,
fr_sbuff_parse_rules_t const *  bracket_rules,
char *  out_c,
bool  cond 
)
static

Definition at line 2006 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ valid_type()

static bool valid_type ( xlat_exp_t node)
static

Definition at line 2610 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_attr_exists()

static xlat_action_t xlat_attr_exists ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
request_t request,
tmpl_t const *  vpt,
bool  do_free 
)
static

Definition at line 1633 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_binary_op()

static xlat_action_t xlat_binary_op ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
UNUSED xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in,
fr_token_t  op,
fr_type_t  default_type,
fr_dict_attr_t const *  enumv 
)
static

Definition at line 370 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_cmp_op()

static xlat_action_t xlat_cmp_op ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
UNUSED xlat_ctx_t const *  xctx,
UNUSED request_t request,
fr_value_box_list_t *  in,
fr_token_t  op 
)
static

Definition at line 461 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_exists_alloc()

static xlat_exp_t * xlat_exists_alloc ( TALLOC_CTX *  ctx,
xlat_exp_t child 
)
static

Allocate a specific cast node.

With the first argument being a UINT8 of the data type. See xlat_func_cast() for the implementation.

Definition at line 111 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_exists_resume()

static xlat_action_t xlat_exists_resume ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
UNUSED fr_value_box_list_t *  in 
)
static

Definition at line 1652 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_expr_logical_purify()

static int xlat_expr_logical_purify ( xlat_exp_t node,
void *  instance,
request_t request 
)
static

If any argument resolves to inst->stop_on_match, the entire thing is a bool of inst->stop_on_match.

If any argument resolves to !inst->stop_on_match, it is removed.

Definition at line 979 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_expr_print_binary()

static fr_slen_t xlat_expr_print_binary ( fr_sbuff_t out,
xlat_exp_t const *  node,
UNUSED void *  inst,
fr_sbuff_escape_rules_t const *  e_rules 
)
static

Definition at line 219 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_expr_print_exists()

static fr_slen_t xlat_expr_print_exists ( fr_sbuff_t out,
xlat_exp_t const *  node,
void *  instance,
fr_sbuff_escape_rules_t const *  e_rules 
)
static

Definition at line 1592 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_expr_print_nary()

static fr_slen_t xlat_expr_print_nary ( fr_sbuff_t out,
xlat_exp_t const *  node,
void *  instance,
fr_sbuff_escape_rules_t const *  e_rules 
)
static

Definition at line 854 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_expr_print_regex()

static fr_slen_t xlat_expr_print_regex ( fr_sbuff_t out,
xlat_exp_t const *  node,
void *  instance,
fr_sbuff_escape_rules_t const *  e_rules 
)
static

Definition at line 528 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_expr_print_unary()

static fr_slen_t xlat_expr_print_unary ( fr_sbuff_t out,
xlat_exp_t const *  node,
UNUSED void *  inst,
fr_sbuff_escape_rules_t const *  e_rules 
)
static

Definition at line 209 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_expr_resolve_binary()

static int xlat_expr_resolve_binary ( xlat_exp_t node,
UNUSED void *  inst,
xlat_res_rules_t const *  xr_rules 
)
static

Definition at line 242 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_func_append_arg()

static void xlat_func_append_arg ( xlat_exp_t head,
xlat_exp_t node,
bool  exists 
)
static

Definition at line 71 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_func_logical()

static xlat_action_t xlat_func_logical ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in 
)
static

Process logical &&, ||.

Definition at line 1367 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_func_unary_complement()

static xlat_action_t xlat_func_unary_complement ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in 
)
static

Definition at line 1475 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_func_unary_minus()

static xlat_action_t xlat_func_unary_minus ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in 
)
static

Definition at line 1468 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_func_unary_not()

static xlat_action_t xlat_func_unary_not ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
UNUSED xlat_ctx_t const *  xctx,
UNUSED request_t request,
fr_value_box_list_t *  in 
)
static

Definition at line 1441 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_func_unary_op()

static xlat_action_t xlat_func_unary_op ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
UNUSED xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in,
fr_token_t  op 
)
static

Definition at line 1397 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_function_args_to_tmpl()

static int xlat_function_args_to_tmpl ( xlat_inst_ctx_t const *  xctx)
static

Convert XLAT_BOX arguments to XLAT_TMPL.

xlat_tokenize() just makes all unknown arguments into XLAT_BOX, of data type FR_TYPE_STRING. Whereas xlat_tokenize_expr() calls tmpl_afrom_substr(), which tries hard to create a particular data type.

This function fixes up calls of the form op_add(3, 4), which normally passes 2 arguments of "3" and "4", so that the arguments are instead passed as integers 3 and 4.

This fixup isn't strictly necessary, but it's good to have no surprises in the code, if the user creates an expression manually.

Definition at line 1493 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_instantiate_exists()

static int xlat_instantiate_exists ( xlat_inst_ctx_t const *  xctx)
static

Definition at line 1609 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_instantiate_logical()

static int xlat_instantiate_logical ( xlat_inst_ctx_t const *  xctx)
static

Definition at line 1347 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_instantiate_regex()

static int xlat_instantiate_regex ( xlat_inst_ctx_t const *  xctx)
static

Definition at line 567 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_is_truthy()

bool xlat_is_truthy ( xlat_exp_head_t const *  head,
bool out 
)

Allow callers to see if an xlat is truthy.

So the caller can cache it, and needs to check fewer things at run time.

Parameters
[in]headof the xlat to check
[out]outtruthiness of the box
Returns

Definition at line 3040 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_logical_and()

static bool xlat_logical_and ( xlat_logical_rctx_t rctx,
fr_value_box_list_t const *  in 
)
static

See if the input is truthy or not.

Parameters
[in]rctxour ctx
[in]inlist of value-boxes to check
Returns
  • false on failure
  • true for match, with dst updated to contain the relevant box.

Empty lists are not truthy.

Definition at line 1245 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_logical_and_resume()

static xlat_action_t xlat_logical_and_resume ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in 
)
static

Definition at line 1295 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_logical_or()

static bool xlat_logical_or ( xlat_logical_rctx_t rctx,
fr_value_box_list_t const *  in 
)
static

See if the input is truthy or not.

Parameters
[in]rctxour ctx
[in]inlist of value-boxes to check
Returns
  • false if there are no truthy values. The last box is copied to the rctx. This is to allow us to return default values which may not be truthy, e.g. %{&Counter || 0} or %{&Framed-IP-Address || 0.0.0.0}. If we don't copy the last box to the rctx, the expression just returns NULL which is never useful...
  • true if we find a truthy value. The first truthy box is copied to the rctx.

Empty lists are not truthy.

Definition at line 1142 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_logical_or_resume()

static xlat_action_t xlat_logical_or_resume ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in 
)
static

Definition at line 1187 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_logical_process_arg()

static xlat_action_t xlat_logical_process_arg ( UNUSED TALLOC_CTX *  ctx,
UNUSED fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
UNUSED fr_value_box_list_t *  in 
)
static

Process one argument of a logical operation.

If we see a list in a truthy context, then we DON'T expand the list. Instead, we return a bool which indicates if the list was empty (or not). This prevents us from returning a whole mess of value-boxes when the user just wanted to see if the list existed.

Otherwise, we expand the xlat, and continue.

Definition at line 1105 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_node_matches_bool()

static bool xlat_node_matches_bool ( bool result,
xlat_exp_t parent,
xlat_exp_head_t head,
bool  sense 
)
static

Definition at line 902 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_regex_match()

static xlat_action_t xlat_regex_match ( TALLOC_CTX *  ctx,
request_t request,
fr_value_box_list_t *  in,
regex_t **  preg,
fr_dcursor_t out,
fr_token_t  op 
)
static

Perform a regular expressions comparison between two operands.

Parameters
[in]ctxto allocate resulting box in.
[in]requestThe current request.
[in]inlist of item or items
[in,out]pregPointer to pre-compiled or runtime-compiled regular expression. In the case of runtime-compiled the pattern may be stolen by the regex_sub_to_request function as the original pattern is needed to resolve capture groups. The caller should only free the regex_t * if it compiled it, and the pointer has not been set to NULL when this function returns.
[out]outWhere result is written.
[in]opthe operation to perform.
Returns
  • -1 on failure.
  • 0 for "no match".
  • 1 for "match".

Definition at line 669 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_regex_op()

static xlat_action_t xlat_regex_op ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in,
fr_token_t  op 
)
static

Definition at line 795 of file xlat_expr.c.

+ Here is the call graph for this function:

◆ xlat_regex_resume()

static xlat_action_t xlat_regex_resume ( TALLOC_CTX *  ctx,
fr_dcursor_t out,
xlat_ctx_t const *  xctx,
request_t request,
fr_value_box_list_t *  in 
)
static

Definition at line 755 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_register_expressions()

int xlat_register_expressions ( void  )

Definition at line 1807 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_tokenize_condition()

fr_slen_t xlat_tokenize_condition ( 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 
)

Definition at line 3023 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_tokenize_expression()

fr_slen_t xlat_tokenize_expression ( 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 
)

Definition at line 3017 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_tokenize_expression_internal()

static fr_slen_t xlat_tokenize_expression_internal ( 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,
bool  cond 
)
static

Definition at line 2935 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ xlat_ungroup()

static void xlat_ungroup ( xlat_exp_head_t head)
static

Undo work which shouldn't have been done.

:(

Definition at line 953 of file xlat_expr.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ binary_cmp_xlat_args

xlat_arg_parser_t const binary_cmp_xlat_args[]
static
Initial value:
= {
{ .required = false, .type = FR_TYPE_VOID },
{ .required = false, .type = FR_TYPE_VOID },
}
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:166

Definition at line 455 of file xlat_expr.c.

◆ binary_op_xlat_args

xlat_arg_parser_t const binary_op_xlat_args[]
static
Initial value:
= {
{ .required = false, .type = FR_TYPE_VOID },
{ .required = false, .type = FR_TYPE_VOID },
}

Definition at line 364 of file xlat_expr.c.

◆ binary_ops

const fr_sbuff_term_elem_t binary_ops[T_TOKEN_LAST]
static
Initial value:
= {
[ T_ADD ] = L("op_add"),
[ T_SUB ] = L("op_sub"),
[ T_MUL ] = L("op_mul"),
[ T_DIV ] = L("op_div"),
[ T_MOD ] = L("op_mod"),
[ T_AND ] = L("op_and"),
[ T_OR ] = L("op_or"),
[ T_XOR ] = L("op_xor"),
[ T_RSHIFT ] = L("op_rshift"),
[ T_LSHIFT ] = L("op_lshift"),
[ T_LAND ] = L("logical_and"),
[ T_LOR ] = L("logical_or"),
[ T_OP_CMP_EQ ] = L("cmp_eq"),
[ T_OP_NE ] = L("cmp_ne"),
[ T_OP_LT ] = L("cmp_lt"),
[ T_OP_LE ] = L("cmp_le"),
[ T_OP_GT ] = L("cmp_gt"),
[ T_OP_GE ] = L("cmp_ge"),
[ T_OP_CMP_EQ_TYPE ] = L("cmp_eq_type"),
[ T_OP_CMP_NE_TYPE ] = L("cmp_ne_type"),
[ T_OP_REG_EQ ] = L("reg_eq"),
[ T_OP_REG_NE ] = L("reg_ne"),
}
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
@ T_AND
Definition: token.h:55
@ T_SUB
Definition: token.h:52
@ T_RSHIFT
Definition: token.h:62
@ T_XOR
Definition: token.h:58
@ T_DIV
Definition: token.h:54
@ T_MOD
Definition: token.h:60
@ T_LAND
Definition: token.h:91
@ T_ADD
Definition: token.h:51
@ T_OP_NE
Definition: token.h:97
@ T_LOR
Definition: token.h:92
@ T_LSHIFT
Definition: token.h:63
@ T_OP_REG_EQ
Definition: token.h:102
@ T_OP_CMP_EQ_TYPE
Definition: token.h:107
@ T_OP_CMP_EQ
Definition: token.h:106
@ T_MUL
Definition: token.h:53
@ T_OP_LE
Definition: token.h:100
@ T_OP_CMP_NE_TYPE
Definition: token.h:108
@ T_OP_GE
Definition: token.h:98
@ T_OP_GT
Definition: token.h:99
@ T_OP_LT
Definition: token.h:101
@ T_OP_REG_NE
Definition: token.h:103
@ T_OR
Definition: token.h:56

Definition at line 1863 of file xlat_expr.c.

◆ bracket_terms

const fr_sbuff_term_t bracket_terms
static
Initial value:
L(""),
L(")"),
)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition: sbuff.h:167

Definition at line 2910 of file xlat_expr.c.

◆ expr_assignment_op_table

fr_table_num_ordered_t const expr_assignment_op_table[]
static

Definition at line 2576 of file xlat_expr.c.

◆ expr_assignment_op_table_len

size_t const expr_assignment_op_table_len = NUM_ELEMENTS(expr_assignment_op_table)
static

Definition at line 2608 of file xlat_expr.c.

◆ expr_quote_table

fr_table_num_sorted_t const expr_quote_table[]
static
Initial value:
= {
}
@ T_SINGLE_QUOTED_STRING
Definition: token.h:122
@ T_BACK_QUOTED_STRING
Definition: token.h:123
@ T_DOUBLE_QUOTED_STRING
Definition: token.h:121
@ T_SOLIDUS_QUOTED_STRING
Definition: token.h:124

Definition at line 1984 of file xlat_expr.c.

◆ expr_quote_table_len

size_t expr_quote_table_len = NUM_ELEMENTS(expr_quote_table)
static

Definition at line 1990 of file xlat_expr.c.

◆ logical_ops

const bool logical_ops[T_TOKEN_LAST]
static
Initial value:
= {
[T_LAND] = true,
[T_LOR] = true,
}

Definition at line 1895 of file xlat_expr.c.

◆ multivalue_ops

const bool multivalue_ops[T_TOKEN_LAST]
static
Initial value:
= {
[T_LAND] = true,
[T_LOR] = true,
}

Definition at line 1903 of file xlat_expr.c.

◆ operator_terms

const fr_sbuff_term_t operator_terms
static
Initial value:
L("\t"),
L("\n"),
L("\r"),
L(" "),
L("!"),
L("%"),
L("&"),
L("*"),
L("+"),
L("-"),
L("/"),
L("<"),
L("="),
L(">"),
L("^"),
L("|"),
L("~"),
)

Definition at line 2915 of file xlat_expr.c.

◆ precedence

const int precedence[T_TOKEN_LAST]
static

Definition at line 1916 of file xlat_expr.c.

◆ regex_escape_rules

const fr_sbuff_escape_rules_t regex_escape_rules
static
Initial value:
= {
.name = "regex",
.chr = '\\',
.subs = {
['$'] = '$',
['('] = '(',
['*'] = '*',
['+'] = '+',
['.'] = '.',
['/'] = '/',
['?'] = '?',
['['] = '[',
['\\'] = '\\',
['^'] = '^',
['`'] = '`',
['|'] = '|',
['\a'] = 'a',
['\b'] = 'b',
['\n'] = 'n',
['\r'] = 'r',
['\t'] = 't',
['\v'] = 'v'
},
.esc = {
},
.do_utf8 = true,
.do_oct = true
}
#define SBUFF_CHAR_UNPRINTABLES_EXTENDED
#define SBUFF_CHAR_UNPRINTABLES_LOW

Definition at line 611 of file xlat_expr.c.

◆ regex_op_xlat_args

xlat_arg_parser_t const regex_op_xlat_args[]
static
Initial value:
= {
{ .required = true, .type = FR_TYPE_STRING },
{ .concat = true, .type = FR_TYPE_STRING },
}
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83

Definition at line 642 of file xlat_expr.c.

◆ unary_op_xlat_args

xlat_arg_parser_t const unary_op_xlat_args[]
static
Initial value:
= {
{ .required = true, .single = true, .concat = true },
}

Definition at line 1392 of file xlat_expr.c.

◆ xlat_func_exists_arg

xlat_arg_parser_t const xlat_func_exists_arg[]
static
Initial value:
= {
{ .concat = true, .type = FR_TYPE_STRING },
}

Definition at line 1584 of file xlat_expr.c.

◆ xlat_func_rcode_arg

xlat_arg_parser_t const xlat_func_rcode_arg[]
static
Initial value:
= {
{ .concat = true, .type = FR_TYPE_STRING },
}

Definition at line 1527 of file xlat_expr.c.