/*
* Assume we just want to get the current value and NOT set it to 0
*/
- if (!in_head)
- goto done;
+ if (in_head->type == FR_TYPE_NULL) goto done;
level = in_head->vb_int8;
if (level == 0) {
/*
* Fill is optional
*/
- if (fill) {
+ if (fill->type != FR_TYPE_NULL) {
fill_str = fill->vb_strvalue;
fill_len = talloc_array_length(fill_str) - 1;
}
/*
* Fill is optional
*/
- if (fill) {
+ if (fill->type != FR_TYPE_NULL) {
fill_str = fill->vb_strvalue;
fill_len = talloc_array_length(fill_str) - 1;
}
REDEBUG("Missing required argument %u", (unsigned int)((arg_p - args) + 1));
return XLAT_ACTION_FAIL;
}
+
+ /*
+ * Add a placeholder 'null' box
+ */
+ MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_NULL, NULL, false));
+ fr_dlist_insert_tail(list, vb);
return XLAT_ACTION_DONE;
}
* argument with the head of the group.
*/
if (arg_p->single || arg_p->concat) {
- fr_dlist_replace(list, vb, fr_dlist_pop_head(&vb->vb_group));
- talloc_free(vb);
+ /*
+ * If the group is empty, convert
+ * it to a null box to maintain
+ * correct ordering in the argument
+ * list.
+ */
+ if (fr_dlist_empty(&vb->vb_group)) {
+ fr_value_box_t *prev = fr_dlist_remove(list, vb);
+ fr_value_box_init_null(vb);
+ fr_dlist_insert_after(list, prev, vb);
+ } else {
+ fr_dlist_replace(list, vb, fr_dlist_pop_head(&vb->vb_group));
+ talloc_free(vb);
+ }
}
if (arg_p->variadic) {
case XLAT_GROUP:
XLAT_DEBUG("** [%i] %s(child) - %%{%s ...}", unlang_interpret_stack_depth(request), __FUNCTION__,
node->fmt);
+ if (!node->child) return XLAT_ACTION_DONE;
/*
* Hand back the child node to the caller
goto error;
}
/*
- * We're parsing the string *containing* the xlat
- * expansions.
+ * Empty input, emit no arguments
*/
- } else {
- /* If we have an empty node, finish building it and
- * emit it.
- *
- * We're about to return, and it's a useful
- * indication to the caller that this wasn't a parse
- * error but just an empty string.
- */
- if (len == 0) {
- /*
- * This isn't the only node in the sequence
- * don't emit an empty trailing literal.
- */
- if (*head) {
- talloc_free(node);
- break;
- }
-
- xlat_exp_set_type(node, XLAT_LITERAL);
- xlat_exp_set_name_buffer_shallow(node, str);
-
- XLAT_DEBUG("LITERAL <-- (empty)");
- node->flags.needs_async = false; /* literals are always true */
- xlat_flags_merge(flags, &node->flags);
- fr_cursor_insert(&cursor, node);
- }
+ } else if (len == 0) {
+ talloc_free(node);
+ XLAT_DEBUG("LITERAL <-- (empty)");
}
break;
}
*head = NULL;
fr_strerror_clear(); /* Clear error buffer */
- if (xlat_tokenize_literal(ctx, head, flags,
- &our_in, false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
+ if (xlat_tokenize_literal(ctx, head, flags, &our_in,
+ false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
/*
* Zero length expansion, return a zero length node.
*/
- if (fr_sbuff_used(&our_in) == 0) *head = xlat_exp_alloc(ctx, XLAT_LITERAL, "", 0);
+ if (!*head) {
+ *head = xlat_exp_alloc(ctx, XLAT_LITERAL, "", 0);
+ return 0;
+ }
/*
* Create ephemeral instance data for the xlat
fr_strerror_clear(); /* Clear error buffer */
- if (xlat_tokenize_literal(ctx, head, flags,
- &our_in, false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
+ if (xlat_tokenize_literal(ctx, head, flags, &our_in,
+ false, p_rules, t_rules) < 0) return -fr_sbuff_used(&our_in);
+
+ /*
+ * Zero length expansion, return a zero length node.
+ */
+ if (!*head) {
+ *head = xlat_exp_alloc(ctx, XLAT_LITERAL, "", 0);
+ return fr_sbuff_set(in, &our_in);
+ }
/*
* Add nodes that need to be bootstrapped to
#define network_min_size(_x) (fr_value_box_network_sizes[_x][0])
#define network_max_size(_x) (fr_value_box_network_sizes[_x][1])
static size_t const fr_value_box_network_sizes[FR_TYPE_MAX + 1][2] = {
- [FR_TYPE_NULL] = {~0, 0},
+ [FR_TYPE_NULL] = {~0, 0},
[FR_TYPE_STRING] = {0, ~0},
[FR_TYPE_OCTETS] = {0, ~0},
fr_value_box_t *client_ip = fr_dlist_next(in, field);
fr_value_box_t *vb;
- if (client_ip) {
+ if (!fr_box_is_null(client_ip)) {
if (fr_inet_pton(&ip, client_ip->vb_strvalue, -1, AF_UNSPEC, false, true) < 0) {
RDEBUG("Invalid client IP address \"%s\"", client_ip->vb_strvalue);
return XLAT_ACTION_FAIL;
--- /dev/null
+#
+# PRE: update if
+#
+
+update request {
+ &Tmp-Integer-0 := "%(debug:4)"
+}
+
+# Check debug level is now 4
+if ("%(debug:3)" != 4) {
+ test_fail
+}
+
+# Call with NULL arg, should report current level
+if ("%(debug:%{Tmp-String-8})" != 3) {
+ test_fail
+}
+
+# ...and again
+if ("%(debug:%{Tmp-String-8})" != 3) {
+ test_fail
+}
+
+# ...and again
+if ("%(debug:)" != 3) {
+ test_fail
+}
+
+# ...and again
+if ("%(debug:)" != 3) {
+ test_fail
+}
+
+success