The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
xlat_alloc.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 3733fdc5c965dc98502f59252556ce8b9084b3c5 $
19 *
20 * @file xlat_alloc.c
21 * @brief Functions to allocate different types of xlat nodes
22 */
23
24RCSID("$Id: 3733fdc5c965dc98502f59252556ce8b9084b3c5 $")
25
26#include <freeradius-devel/server/base.h>
27
28
29#define _XLAT_PRIVATE
30#include <freeradius-devel/unlang/xlat_priv.h>
31
33{
35
36 MEM(head = talloc_zero(ctx, xlat_exp_head_t));
37
38 fr_dlist_init(&head->dlist, xlat_exp_t, entry);
39 head->flags = XLAT_FLAGS_INIT;
40#ifndef NDEBUG
41 head->file = file;
42 head->line = line;
43#endif
44
45 return head;
46}
47
48/** Set the type of an xlat node
49 *
50 * Also initialises any xlat_exp_head necessary
51 *
52 * @param[in] node to set type for.
53 * @param[in] type to set.
54 */
56{
57 /*
58 * Do nothing if it's the same type
59 */
60 if (node->type == type) return;
61
62 /*
63 * Free existing lists if present
64 */
65 if (node->type != 0) switch (node->type) {
66 case XLAT_GROUP:
67 TALLOC_FREE(node->group);
68 break;
69
71 if (type == XLAT_FUNC) goto done; /* Just switching from unresolved to resolved */
73
74 case XLAT_FUNC:
75 TALLOC_FREE(node->call.args);
76 break;
77
78 case XLAT_TMPL:
79 if (!node->vpt) break;
80
81 if (node->fmt == node->vpt->name) (void) talloc_steal(node, node->fmt);
82
83 /*
84 * Converting a tmpl to a box. If the tmpl is data, we can then just steal the contents
85 * of the box.
86 */
87 if (type == XLAT_BOX) {
88 tmpl_t *vpt = node->vpt;
89
91
92 /*
93 * Why is someone converting an XLAT_TMPL to an XLAT_BOX, when the content isn't data?
94 */
95 if (!tmpl_is_data(vpt)) {
96 TALLOC_FREE(node->vpt);
97 break;
98 }
99
100 /*
101 * Initialize the box from the tmpl data. And then do NOT re-initialize the box
102 * later.
103 */
104 node->flags = XLAT_FLAGS_INIT;
105 fr_value_box_steal(node, &node->data, tmpl_value(vpt));
107 goto done;
108 }
109
110 /*
111 * Converting a tmpl to a group. If the tmpl contains an xlat, we hoist that xlat out
112 * of the tmpl, instead of throwing it away and then allocating an empty group.
113 */
114 if ((type == XLAT_GROUP) && tmpl_is_xlat(node->vpt)) {
115 tmpl_t *vpt = node->vpt;
116 xlat_exp_head_t *group;
117
118 /*
119 * "group" and "vpt" share a union, so we have to be done with the tmpl before
120 * we set the group.
121 */
122 group = talloc_steal(node, tmpl_xlat(vpt));
124
125 node->group = group;
126 node->flags = group->flags;
127 goto done;
128 }
129
130 /*
131 * Why is someone converting an XLAT_TMPL to ???
132 */
133 TALLOC_FREE(node->vpt);
134 break;
135
136 default:
137 break;
138 }
139
140 /*
141 * Alloc new lists to match the type
142 */
143 switch (type) {
144 case XLAT_GROUP:
145 node->group = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node);
146 node->flags = node->group->flags;
147 break;
148
149 case XLAT_FUNC:
150 node->flags = XLAT_FLAGS_INIT;
151 break;
152
154 node->flags = XLAT_FLAGS_INIT;
155 node->flags.needs_resolving = true;
156 break;
157
158 case XLAT_BOX:
159 node->flags = XLAT_FLAGS_INIT;
160 fr_value_box_init_null(&node->data);
161 break;
162
163#ifdef HAVE_REGEX
164 case XLAT_REGEX:
165 node->flags = (xlat_flags_t) {};
166 break;
167#endif
168
169 case XLAT_ONE_LETTER:
170 /*
171 * %% is pure. Everything else is not.
172 */
173 fr_assert(node->fmt);
174
175 if (node->fmt[0] != '%') {
176 node->flags = (xlat_flags_t) {};
177 } else {
178 node->flags = XLAT_FLAGS_INIT;
179 }
180 break;
181
182 default:
183 node->flags = XLAT_FLAGS_INIT;
184 break;
185 }
186
187done:
188 node->type = type;
189}
190
191static xlat_exp_t *xlat_exp_alloc_pool(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra)
192{
193 xlat_exp_t *node;
194
195 MEM(node = talloc_zero_pooled_object(ctx, xlat_exp_t, extra_hdrs, sizeof(xlat_exp_t) + extra * extra_hdrs));
196 node->flags = XLAT_FLAGS_INIT;
197 node->quote = T_BARE_WORD;
198#ifndef NDEBUG
199 node->file = file;
200 node->line = line;
201#endif
202
203 return node;
204}
205
206/** Allocate an xlat node with no name, and no type set
207 *
208 * @param[in] ctx to allocate node in.
209 * @return A new xlat node.
210 */
215
216/** Allocate an xlat node
217 *
218 * @param[in] ctx to allocate node in.
219 * @param[in] type of the node.
220 * @param[in] in original input string.
221 * @param[in] inlen the length of the original input string.
222 * @return A new xlat node.
223 */
224xlat_exp_t *_xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen)
225{
226 xlat_exp_t *node;
227 unsigned int extra_hdrs;
228 size_t extra;
229
230 /*
231 * Figure out how much extra memory we
232 * need to allocate for this node type.
233 */
234 switch (type) {
235 case XLAT_GROUP:
236 extra_hdrs = 1;
237 extra = sizeof(xlat_exp_head_t);
238 break;
239
240 case XLAT_FUNC:
241 extra_hdrs = 1;
242 extra = sizeof(xlat_exp_head_t);
243 break;
244
245 default:
246 extra_hdrs = 0;
247 extra = 0;
248 }
249
251 ctx,
252 (in != NULL) + extra_hdrs,
253 inlen + extra);
255
256 node->quote = T_BARE_WORD; /* ensure that this is always initialized */
257
258 if (!in) return node;
259
260 node->fmt = talloc_bstrndup(node, in, inlen);
261 switch (type) {
262 case XLAT_BOX:
263 fr_value_box_strdup_shallow(&node->data, NULL, node->fmt, false);
264 break;
265
266 default:
267 break;
268 }
269
270 return node;
271}
272
273/** Set the tmpl for a node, along with flags and the name.
274 *
275 * @param[in] node to set fmt for.
276 * @param[in] vpt the tmpl to set
277 */
279{
280 if (tmpl_contains_xlat(vpt)) {
281 node->flags = tmpl_xlat(vpt)->flags;
282 }
283
285 node->flags = (xlat_flags_t) {};
286 }
287
289
290 node->vpt = vpt;
291 xlat_exp_set_name_shallow(node, vpt->name);
292}
293
294/** Set the function for a node
295 *
296 * @param[in] node to set fmt for.
297 * @param[in] func to set
298 * @param[in] dict the dictionary to set
299 */
300void xlat_exp_set_func(xlat_exp_t *node, xlat_t const *func, fr_dict_t const *dict)
301{
302 node->call.func = func;
303 node->call.dict = dict;
304 node->flags = func->flags;
305 node->flags.impure_func = !func->flags.pure;
306
307 if (!dict) node->flags.needs_resolving = true;
308}
309
311{
312 if (!node->call.args) return;
313
314 node->call.args->is_argv = true;
315
316 if (node->type == XLAT_FUNC_UNRESOLVED) return;
317
318 xlat_flags_merge(&node->flags, &node->call.args->flags);
319
320 /*
321 * We might not be able to purify the function call, but perhaps we can purify the arguments to it.
322 */
323 node->flags.can_purify = (node->call.func->flags.pure && node->call.args->flags.pure) | node->call.args->flags.can_purify;
324 node->flags.impure_func = !node->call.func->flags.pure;
325}
326
327
328/** Set the format string for an xlat node
329 *
330 * @param[in] node to set fmt for.
331 * @param[in] fmt talloced buffer to set as the fmt string.
332 * @param[in] len of fmt string.
333 */
334void xlat_exp_set_name(xlat_exp_t *node, char const *fmt, size_t len)
335{
336 fr_assert(node->fmt != fmt);
337
338 if (node->fmt) talloc_const_free(node->fmt);
339 MEM(node->fmt = talloc_bstrndup(node, fmt, len));
340}
341
342/** Set the format string for an xlat node, copying from a talloc'd buffer
343 *
344 * @param[in] node to set fmt for.
345 * @param[in] fmt talloced buffer to set as the fmt string.
346 */
348{
349 if (node->fmt) {
350 if (node->fmt == fmt) {
351 (void) talloc_steal(node, fmt);
352 } else {
353 talloc_const_free(node->fmt);
354 }
355 }
356 MEM(node->fmt = talloc_typed_strdup_buffer(node, fmt));
357}
358
359/** Set the format string for an xlat node from a pre-existing buffer
360 *
361 * @param[in] node to set fmt for.
362 * @param[in] fmt talloced buffer to set as the fmt string.
363 */
365{
366 fr_assert(node->fmt != fmt);
367
368 if (node->fmt) talloc_const_free(node->fmt);
369 node->fmt = talloc_get_type_abort_const(fmt, char);
370}
371
372/** Copy all nodes in the input list to the output list
373 *
374 * @param[in] ctx to allocate new nodes in.
375 * @param[out] out Where to write new nodes.
376 * @param[in] in Input nodes.
377 * @return
378 * - 0 on success.
379 * - -1 on failure.
380 */
382{
383 xlat_flags_merge(&out->flags, &in->flags);
384
385 /*
386 * Copy everything in the list of nodes
387 */
388 xlat_exp_foreach(in, p) {
389 xlat_exp_t *node;
390
391 (void)talloc_get_type_abort(p, xlat_exp_t);
392
393 /*
394 * Ensure the format string is valid... At this point
395 * they should all be talloc'd strings.
396 */
397 MEM(node = xlat_exp_alloc(ctx, p->type,
398 talloc_get_type_abort_const(p->fmt, char), talloc_strlen(p->fmt)));
399
400 node->quote = p->quote;
401 node->flags = p->flags;
402
403 switch (p->type) {
404 case XLAT_INVALID:
405 fr_strerror_printf("Cannot copy xlat node of type \"invalid\"");
406 error:
407 return -1;
408
409 case XLAT_BOX:
410 if (unlikely(fr_value_box_copy(node, &node->data, &p->data) < 0)) goto error;
411 break;
412
413 case XLAT_ONE_LETTER: /* Done with format */
415 break;
416
417 case XLAT_FUNC:
418 /*
419 * Only copy the function pointer, and whether this
420 * is ephemeral.
421 *
422 * All instance data is specific to the xlat node and
423 * cannot be duplicated.
424 *
425 * The node xlat nodes will need to be registered in
426 * the xlat instantiation table later.
427 */
428 node->call.func = p->call.func;
429 node->call.dict = p->call.dict;
430 node->call.ephemeral = p->call.ephemeral;
431 node->call.args = xlat_exp_head_alloc(node);
432 node->call.args->is_argv = true;
434 node, node->call.args, p->call.args) < 0)) goto error;
435 break;
436
437 case XLAT_TMPL:
438 if (unlikely((node->vpt = tmpl_copy(node, p->vpt)) == NULL)) goto error;
439 break;
440
441#ifdef HAVE_REGEX
442 case XLAT_REGEX:
443 node->regex_index = p->regex_index;
444 break;
445#endif
446
447 case XLAT_GROUP:
449 node, node->group, p->group) < 0)) goto error;
450 break;
451 }
452
454 }
455
456 return 0;
457}
458
460{
461 int ret;
462
463 if (!in) return 0;
464
468
469 return ret;
470}
471
472#ifdef WITH_VERIFY_PTR
473void xlat_exp_verify(xlat_exp_t const *node)
474{
476
477 switch (node->type) {
478 case XLAT_GROUP:
479 xlat_exp_head_verify(node->group);
480
481 if (!node->fmt) return;
482 (void)talloc_get_type_abort_const(node->fmt, char);
483 return;
484
485 case XLAT_FUNC:
486 if (!node->call.args) return;
487
488 fr_assert(node->call.args->is_argv);
489
490 xlat_exp_foreach(node->call.args, arg) {
491 fr_assert(arg->type == XLAT_GROUP);
492
493 /*
494 * We can't do this yet, because the old function argument parser doesn't do the
495 * right thing.
496 */
497// fr_assert(arg->quote == T_BARE_WORD);
498 }
499
500 xlat_exp_head_verify(node->call.args);
501
502 if (!node->fmt) return;
503 (void)talloc_get_type_abort_const(node->fmt, char);
504 return;
505
506 case XLAT_TMPL: {
507 tmpl_t const *vpt = node->vpt;
508
509 if (node->quote != node->vpt->quote) {
510 if (node->vpt->quote == T_SOLIDUS_QUOTED_STRING) {
511 /*
512 * m'foo' versus /foo/
513 */
514 fr_assert(node->quote != T_BARE_WORD);
515 } else {
516 /*
517 * Mismatching quotes are bad.
518 */
519 fr_assert(node->quote == T_BARE_WORD);
520 }
521 }
522
523 if (tmpl_is_attr(vpt)) {
524 fr_dict_attr_t const *da;
525
526 da = tmpl_attr_tail_da(node->vpt);
527 fr_assert(da != NULL); /* otherwise we can't check casts */
528
529 if (tmpl_rules_cast(node->vpt) != FR_TYPE_NULL) {
530 /*
531 * Casts must be omitted, unless we're using a cast as a way to get rid
532 * of enum names.
533 */
534 if (tmpl_rules_cast(node->vpt) == da->type) {
535 fr_assert(da->flags.has_value);
536 }
537
538 } else if (node->quote != T_BARE_WORD) {
539 fr_assert(da->type != FR_TYPE_STRING);
540 }
541
543 return;
544 }
545
546 /*
547 * Casts should have been hoisted.
548 */
549 if (tmpl_is_data(node->vpt)) {
551 VALUE_BOX_VERIFY(tmpl_value(node->vpt));
552 }
553
554#if 0
555 /*
556 * @todo - xlats SHOULD have been hoisted, unless they're quoted or cast.
557 */
558 if (tmpl_is_xlat(node->vpt)) {
559 fr_assert((node->vpt->quote != T_BARE_WORD) ||
560 (tmpl_rules_cast(node->vpt) != FR_TYPE_NULL));
561 return;
562 }
563#endif
564
565 if (tmpl_is_exec(node->vpt) || tmpl_is_exec_unresolved(node->vpt)) {
567 fr_assert(!node->flags.constant);
568 fr_assert(!node->flags.pure);
569 fr_assert(!node->flags.can_purify);
570 }
571
573 return;
574 }
575
576 case XLAT_BOX:
577 fr_assert(node->flags.constant);
578 fr_assert(node->flags.pure);
579// fr_assert(node->flags.can_purify);
580 VALUE_BOX_VERIFY(&node->data);
581 break;
582
583 default:
584 break;
585 }
586}
587
588/** Performs recursive validation of node lists
589 */
590void xlat_exp_head_verify(xlat_exp_head_t const *head)
591{
593
594 xlat_exp_foreach(head, node) xlat_exp_verify(node);
595}
596#endif
int const char * file
Definition acutest.h:849
static int const char * fmt
Definition acutest.h:632
void int line
Definition acutest.h:804
#define RCSID(id)
Definition build.h:560
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:391
#define unlikely(_x)
Definition build.h:455
#define NDEBUG_LOCATION_VALS
Definition build.h:331
#define NDEBUG_LOCATION_ARGS
Pass caller information to the function.
Definition build.h:330
fr_dict_t * dict
Definition common.c:31
#define MEM(x)
Definition debug.h:38
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition dlist.h:242
talloc_free(hp)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
#define fr_assert(_expr)
Definition rad_assert.h:37
static bool done
Definition radclient.c:80
#define tmpl_contains_xlat(vpt)
Definition tmpl.h:234
#define TMPL_VERIFY(_vpt)
Definition tmpl.h:984
#define tmpl_is_xlat(vpt)
Definition tmpl.h:217
#define tmpl_value(_tmpl)
Definition tmpl.h:960
#define tmpl_is_attr(vpt)
Definition tmpl.h:215
#define tmpl_is_exec(vpt)
Definition tmpl.h:218
#define tmpl_is_exec_unresolved(vpt)
Definition tmpl.h:225
#define tmpl_xlat(_tmpl)
Definition tmpl.h:953
#define tmpl_rules_cast(_tmpl)
Definition tmpl.h:965
#define tmpl_contains_attr(vpt)
Definition tmpl.h:232
tmpl_t * tmpl_copy(TALLOC_CTX *ctx, tmpl_t const *in)
Copy a tmpl.
#define TMPL_ATTR_VERIFY(_vpt)
Definition tmpl.h:983
#define tmpl_is_data(vpt)
Definition tmpl.h:213
static fr_slen_t vpt
Definition tmpl.h:1298
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition tmpl.h:824
#define tmpl_needs_resolving(vpt)
Definition tmpl.h:230
fr_aka_sim_id_type_t type
char * talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
Call talloc_strndup, setting the type on the new chunk correctly.
Definition talloc.c:571
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Definition talloc.c:693
#define talloc_get_type_abort_const
Definition talloc.h:117
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
Definition talloc.h:209
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:289
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
@ T_BARE_WORD
Definition token.h:118
@ T_BACK_QUOTED_STRING
Definition token.h:121
@ T_SOLIDUS_QUOTED_STRING
Definition token.h:122
#define XLAT_HEAD_VERIFY(_head)
Definition xlat.h:456
#define XLAT_FLAGS_INIT
Definition xlat.h:119
unsigned int pure
has no external side effects, true for BOX, LITERAL, and some functions
Definition xlat.h:110
unsigned int impure_func
xlat contains an impure function
Definition xlat.h:111
static fr_slen_t head
Definition xlat.h:410
unsigned int can_purify
if the xlat has a pure function with pure arguments.
Definition xlat.h:112
unsigned int constant
xlat is just tmpl_attr_tail_data, or XLAT_BOX
Definition xlat.h:114
unsigned int needs_resolving
Needs pass2 resolution.
Definition xlat.h:109
Flags that control resolution and evaluation.
Definition xlat.h:108
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
Definition value.c:4434
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
Definition value.c:4781
int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
Copy value data verbatim moving any buffers to the specified context.
Definition value.c:4596
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:640
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
#define VALUE_BOX_VERIFY(_x)
Definition value.h:1388
int nonnull(2, 5))
xlat_exp_head_t * _xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx)
Definition xlat_alloc.c:32
void xlat_exp_finalize_func(xlat_exp_t *node)
Definition xlat_alloc.c:310
void xlat_exp_set_vpt(xlat_exp_t *node, tmpl_t *vpt)
Set the tmpl for a node, along with flags and the name.
Definition xlat_alloc.c:278
xlat_exp_t * _xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen)
Allocate an xlat node.
Definition xlat_alloc.c:224
void xlat_exp_set_name(xlat_exp_t *node, char const *fmt, size_t len)
Set the format string for an xlat node.
Definition xlat_alloc.c:334
void xlat_exp_set_name_buffer(xlat_exp_t *node, char const *fmt)
Set the format string for an xlat node, copying from a talloc'd buffer.
Definition xlat_alloc.c:347
xlat_exp_t * _xlat_exp_alloc_null(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx)
Allocate an xlat node with no name, and no type set.
Definition xlat_alloc.c:211
int _xlat_copy(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in)
Definition xlat_alloc.c:459
void xlat_exp_set_func(xlat_exp_t *node, xlat_t const *func, fr_dict_t const *dict)
Set the function for a node.
Definition xlat_alloc.c:300
static xlat_exp_t * xlat_exp_alloc_pool(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra)
Definition xlat_alloc.c:191
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.
Definition xlat_alloc.c:364
static int _xlat_copy_internal(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in)
Copy all nodes in the input list to the output list.
Definition xlat_alloc.c:381
void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type)
Set the type of an xlat node.
Definition xlat_alloc.c:55
struct xlat_exp_head_s xlat_exp_head_t
Definition xlat_ctx.h:36
#define xlat_exp_head_alloc(_ctx)
Definition xlat_priv.h:276
xlat_flags_t flags
Flags that control resolution and evaluation.
Definition xlat_priv.h:156
xlat_flags_t flags
Flags that control resolution and evaluation.
Definition xlat_priv.h:192
int line
Line where the xlat was allocated.
Definition xlat_priv.h:161
fr_token_t quote
Type of quoting around XLAT_GROUP types.
Definition xlat_priv.h:154
xlat_type_t
Definition xlat_priv.h:108
@ XLAT_ONE_LETTER
Special "one-letter" expansion.
Definition xlat_priv.h:111
@ XLAT_BOX
fr_value_box_t
Definition xlat_priv.h:110
@ XLAT_TMPL
xlat attribute
Definition xlat_priv.h:114
@ XLAT_FUNC
xlat module
Definition xlat_priv.h:112
@ XLAT_GROUP
encapsulated string of xlats
Definition xlat_priv.h:118
@ XLAT_FUNC_UNRESOLVED
func needs resolution during pass2.
Definition xlat_priv.h:113
@ XLAT_INVALID
Bad expansion.
Definition xlat_priv.h:109
static void xlat_flags_merge(xlat_flags_t *parent, xlat_flags_t const *child)
Merge flags from child to parent.
Definition xlat_priv.h:232
char const *_CONST fmt
The original format string (a talloced buffer).
Definition xlat_priv.h:153
xlat_type_t _CONST type
type of this expansion.
Definition xlat_priv.h:157
char const *_CONST file
File where the xlat was allocated.
Definition xlat_priv.h:160
#define xlat_exp_alloc(_ctx, _type, _in, _inlen)
Definition xlat_priv.h:285
xlat_flags_t flags
various flags
Definition xlat_priv.h:94
#define xlat_exp_foreach(_list_head, _iter)
Iterate over the contents of a list, only one level.
Definition xlat_priv.h:225
static int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
Definition xlat_priv.h:241
An xlat expansion node.
Definition xlat_priv.h:150