Skip to content

Commit ccb52a6

Browse files
committed
use xlat_tmpl_normalize() in more places
so that we don't have duplicate code
1 parent 494b9fc commit ccb52a6

2 files changed

Lines changed: 72 additions & 85 deletions

File tree

src/lib/unlang/xlat_alloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type)
8989
tmpl_t *vpt = node->vpt;
9090

9191
if (!vpt) break;
92-
92+
9393
fr_assert(tmpl_rules_cast(vpt) == FR_TYPE_NULL);
9494

9595
if (!tmpl_is_data(vpt)) {

src/lib/unlang/xlat_tokenize.c

Lines changed: 71 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,71 @@ bool const xlat_func_chars[UINT8_MAX + 1] = {
159159
};
160160

161161

162+
static int xlat_tmpl_normalize(xlat_exp_t *node)
163+
{
164+
tmpl_t *vpt = node->vpt;
165+
166+
/*
167+
* Any casting, etc. has to be taken care of in the xlat expression parser, and not here.
168+
*/
169+
fr_assert(tmpl_rules_cast(vpt) == FR_TYPE_NULL);
170+
171+
/*
172+
* Add in unknown attributes, by defining them in the local dictionary.
173+
*/
174+
if (tmpl_is_attr(vpt)) {
175+
if (tmpl_attr_unknown_add(vpt) < 0) {
176+
fr_strerror_printf("Failed defining attribute %s", tmpl_attr_tail_da(vpt)->name);
177+
return -1;
178+
}
179+
180+
node->flags.constant = node->flags.pure = node->flags.can_purify = false;
181+
return 0;
182+
}
183+
184+
#if 0
185+
/*
186+
* We have a nested xlat. This is likely bad. The caller SHOULD have checked for %{...}, and
187+
* created an XLAT_GROUP, and then parsed that.
188+
*/
189+
if (tmpl_contains_xlat(vpt)) {
190+
fr_assert(!tmpl_needs_resolving(vpt));
191+
fr_assert(!tmpl_contains_regex(vpt));
192+
193+
return 0;
194+
}
195+
#endif
196+
197+
if (!tmpl_contains_data(vpt)) {
198+
fr_assert(!tmpl_needs_resolving(vpt));
199+
fr_assert(!tmpl_contains_regex(vpt));
200+
201+
return 0;
202+
}
203+
204+
if (tmpl_is_data_unresolved(vpt) && (tmpl_resolve(vpt, NULL) < 0)) return -1;
205+
206+
/*
207+
* Hoist data to an XLAT_BOX instead of an XLAT_TMPL
208+
*/
209+
fr_assert(tmpl_is_data(vpt));
210+
211+
/*
212+
* Print "true" and "false" instead of "yes" and "no".
213+
*/
214+
if ((tmpl_value_type(vpt) == FR_TYPE_BOOL) && !tmpl_value_enumv(vpt)) {
215+
tmpl_value_enumv(vpt) = attr_expr_bool_enum;
216+
}
217+
218+
/*
219+
* Convert the XLAT_TMPL to XLAT_BOX
220+
*/
221+
xlat_exp_set_type(node, XLAT_BOX);
222+
223+
return 0;
224+
}
225+
226+
162227
static int xlat_validate_function_arg(xlat_arg_parser_t const *arg_p, xlat_exp_t *arg, int argc)
163228
{
164229
xlat_exp_t *node;
@@ -182,40 +247,17 @@ static int xlat_validate_function_arg(xlat_arg_parser_t const *arg_p, xlat_exp_t
182247
}
183248

184249
/*
185-
* @todo - check arg_p->single, and complain.
250+
* @todo - if arg->group->flags.constant AND there is more than one child, then concat in place,
251+
* etc.
186252
*/
187-
if (xlat_exp_next(arg->group, node)) {
188-
return 0;
189-
}
190253

191254
/*
192-
* Hoist constant factors.
255+
* Do at least somewhat of a pass of normalizing the nodes, even if there are more than one.
193256
*/
194-
if (node->type == XLAT_TMPL) {
195-
/*
196-
* @todo - hoist the xlat, and then check the hoisted value again.
197-
* However, there seem to be few cases where this is used?
198-
*/
199-
if (tmpl_is_xlat(node->vpt)) {
200-
return 0;
201-
202-
/*
203-
* Raw data can be hoisted to a value-box in this xlat node.
204-
*/
205-
} else if (tmpl_is_data(node->vpt)) {
206-
xlat_exp_set_type(node, XLAT_BOX); /* also steals the data */
207-
fr_value_box_mark_safe_for(&node->data, arg_p->safe_for);
208-
209-
} else {
210-
fr_assert(!tmpl_is_data_unresolved(node->vpt));
211-
fr_assert(!tmpl_contains_regex(node->vpt));
257+
xlat_exp_foreach(arg->group, child) {
258+
if (child->type != XLAT_TMPL) continue;
212259

213-
/*
214-
* Can't cast the attribute / exec/ etc. to the expected data type of the
215-
* argument, that has to happen at run-time.
216-
*/
217-
return 0;
218-
}
260+
if (xlat_tmpl_normalize(child) < 0) return -1;
219261
}
220262

221263
/*
@@ -1264,61 +1306,6 @@ static void xlat_safe_for(xlat_exp_head_t *head, fr_value_box_safe_for_t safe_fo
12641306
}
12651307
#endif
12661308

1267-
static int xlat_tmpl_normalize(xlat_exp_t *node)
1268-
{
1269-
tmpl_t *vpt = node->vpt;
1270-
1271-
/*
1272-
* Any casting, etc. has to be taken care of in the xlat expression parser, and not here.
1273-
*/
1274-
fr_assert(tmpl_rules_cast(vpt) == FR_TYPE_NULL);
1275-
1276-
/*
1277-
* Add in unknown attributes, by defining them in the local dictionary.
1278-
*/
1279-
if (tmpl_is_attr(vpt)) {
1280-
if (tmpl_attr_unknown_add(vpt) < 0) {
1281-
fr_strerror_printf("Failed defining attribute %s", tmpl_attr_tail_da(vpt)->name);
1282-
return -1;
1283-
}
1284-
1285-
node->flags.pure = node->flags.can_purify = false;
1286-
return 0;
1287-
}
1288-
1289-
if (tmpl_is_data_unresolved(vpt) && (tmpl_resolve(vpt, NULL) < 0)) return -1;
1290-
1291-
/*
1292-
* Hoist data to an XLAT_BOX instead of an XLAT_TMPL
1293-
*/
1294-
if (tmpl_is_data(node->vpt)) {
1295-
/*
1296-
* Print "true" and "false" instead of "yes" and "no".
1297-
*/
1298-
if ((tmpl_value_type(vpt) == FR_TYPE_BOOL) && !tmpl_value_enumv(vpt)) {
1299-
tmpl_value_enumv(vpt) = attr_expr_bool_enum;
1300-
}
1301-
1302-
/*
1303-
* The name is set later, by the caller.
1304-
*/
1305-
fr_value_box_steal(node, &node->data, tmpl_value(vpt));
1306-
talloc_free(vpt);
1307-
xlat_exp_set_type(node, XLAT_BOX);
1308-
1309-
node->flags.pure = node->flags.can_purify = true;
1310-
return 0;
1311-
}
1312-
1313-
fr_assert(!tmpl_contains_regex(vpt));
1314-
1315-
/*
1316-
* We have a nested xlat. This is likely bad. The caller SHOULD have checked for %{...}, and
1317-
* created an XLAT_GROUP, and then parsed that.
1318-
*/
1319-
return 0;
1320-
}
1321-
13221309
static ssize_t xlat_tokenize_word(TALLOC_CTX *ctx, xlat_exp_t **out, fr_sbuff_t *in, fr_sbuff_marker_t *m,
13231310
fr_token_t quote,
13241311
fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)

0 commit comments

Comments
 (0)