size_t at_in = fr_sbuff_used_total(out);
FR_SBUFF_IN_STRCPY_RETURN(out, fr_tokens[node->call.func->token]);
- xlat_print_node(out, node->call.args, xlat_exp_head(node->call.args), e_rules);
+ xlat_print_node(out, node->call.args, xlat_exp_head(node->call.args), e_rules, 0);
return fr_sbuff_used_total(out) - at_in;
}
fr_assert(child != NULL);
FR_SBUFF_IN_CHAR_RETURN(out, '(');
- xlat_print_node(out, node->call.args, child, e_rules); /* prints a space after the first argument */
+ xlat_print_node(out, node->call.args, child, e_rules, 0); /* prints a space after the first argument */
FR_SBUFF_IN_STRCPY_RETURN(out, fr_tokens[node->call.func->token]);
FR_SBUFF_IN_CHAR_RETURN(out, ' ');
child = xlat_exp_next(node->call.args, child);
fr_assert(child != NULL);
- xlat_print_node(out, node->call.args, child, e_rules);
+ xlat_print_node(out, node->call.args, child, e_rules, 0);
FR_SBUFF_IN_CHAR_RETURN(out, ')');
fr_assert(child != NULL);
FR_SBUFF_IN_CHAR_RETURN(out, '(');
- xlat_print_node(out, node->call.args, child, e_rules);
+ xlat_print_node(out, node->call.args, child, e_rules, 0);
/*
* A space is printed after the first argument only if
fr_assert(head != NULL);
xlat_exp_foreach(head, child) {
- xlat_print_node(out, head, child, e_rules);
+ xlat_print_node(out, head, child, e_rules, 0);
if (!xlat_exp_next(head, child)) break;
if (inst->xlat) {
xlat_print(out, inst->xlat, e_rules);
} else {
- xlat_print_node(out, node->call.args, xlat_exp_head(node->call.args), e_rules);
+ xlat_print_node(out, node->call.args, xlat_exp_head(node->call.args), e_rules, 0);
}
return fr_sbuff_used_total(out) - at_in;
tmpl_rules_t const *t_rules);
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);
+ fr_sbuff_escape_rules_t const *e_rules, char c);
#ifdef __cplusplus
}
}
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)
+ fr_sbuff_escape_rules_t const *e_rules, char c)
{
ssize_t slen;
size_t at_in = fr_sbuff_used_total(out);
xlat_print(out, node->group, fr_value_escape_by_quote[node->quote]);
if (node->quote != T_BARE_WORD) FR_SBUFF_IN_CHAR_RETURN(out, fr_token_quote[node->quote]);
- if (xlat_exp_next(head, node)) FR_SBUFF_IN_CHAR_RETURN(out, ' '); /* Add ' ' between args */
+ if (xlat_exp_next(head, node)) {
+ if (c) FR_SBUFF_IN_CHAR_RETURN(out, c);
+ FR_SBUFF_IN_CHAR_RETURN(out, ' '); /* Add ' ' between args */
+ }
goto done;
case XLAT_BOX:
/*
* Now print %(...) or %{...}
*/
- if ((node->type == XLAT_FUNC) && (node->call.func->input_type == XLAT_INPUT_ARGS)) {
- FR_SBUFF_IN_STRCPY_LITERAL_RETURN(out, "%(");
+ if ((node->type == XLAT_FUNC) || (node->type == XLAT_FUNC_UNRESOLVED)) {
+ FR_SBUFF_IN_CHAR_RETURN(out, '%'); /* then the name */
close = ')';
} else {
FR_SBUFF_IN_STRCPY_LITERAL_RETURN(out, "%{");
case XLAT_FUNC:
FR_SBUFF_IN_BSTRCPY_BUFFER_RETURN(out, node->call.func->name);
- FR_SBUFF_IN_CHAR_RETURN(out, ':');
+ FR_SBUFF_IN_CHAR_RETURN(out, '(');
- if (xlat_exp_head(node->call.args)) {
- slen = xlat_print(out, node->call.args, &xlat_escape);
- if (slen < 0) return slen;
- }
- break;
+ goto print_args;
case XLAT_FUNC_UNRESOLVED:
FR_SBUFF_IN_BSTRCPY_BUFFER_RETURN(out, node->fmt);
- FR_SBUFF_IN_CHAR_RETURN(out, ':');
+ FR_SBUFF_IN_CHAR_RETURN(out, '(');
+ print_args:
if (xlat_exp_head(node->call.args)) {
- slen = xlat_print(out, node->call.args, &xlat_escape);
- if (slen < 0) return slen;
+ xlat_exp_foreach(node->call.args, child) {
+ slen = xlat_print_node(out, node->call.args, child, &xlat_escape, ',');
+ if (slen < 0) return slen;
+ }
}
break;
size_t at_in = fr_sbuff_used_total(out);
xlat_exp_foreach(head, node) {
- slen = xlat_print_node(out, head, node, e_rules);
+ slen = xlat_print_node(out, head, node, e_rules, 0);
if (slen < 0) return slen - (fr_sbuff_used_total(out) - at_in);
}
# sillyness is OK, but cleaned up.
condition ((((((ok))))))
-match %{rcode:'ok'}
+match %rcode('ok')
#
# Extra braces get squashed
match (&User-Name == &User-Password)
condition (!ok)
-match !%{rcode:'ok'}
+match !%rcode('ok')
condition !(ok)
-match !%{rcode:'ok'}
+match !%rcode('ok')
condition !!ok
match ERROR offset 2: Double operator is invalid
# @todo - peephole - do optimization to get rid of double negation?
#
condition !(!ok)
-match !!%{rcode:'ok'}
+match !!%rcode('ok')
#
# These next two are identical after normalization
#match ERROR offset 23: Unexpected closing brace
condition (handled && (&Packet-Type == Access-Challenge))
-match (%{rcode:'handled'} && (&Packet-Type == Access-Challenge))
+match (%rcode('handled') && (&Packet-Type == Access-Challenge))
# This is OK, without the braces
condition handled && &Packet-Type == Access-Challenge
-match (%{rcode:'handled'} && (&Packet-Type == Access-Challenge))
+match (%rcode('handled') && (&Packet-Type == Access-Challenge))
# and this, though it's not a good idea.
condition handled &&&Packet-Type == Access-Challenge
-match (%{rcode:'handled'} && (&Packet-Type == Access-Challenge))
+match (%rcode('handled') && (&Packet-Type == Access-Challenge))
condition &reply == &request
match ERROR offset 1: Cannot use list references in condition
# Except for dates, which can be humanly readable!
# This one is be an expansion, so it's left as-is.
condition &Event-Timestamp == "January 1, 2012 %{blah}"
-match (&Event-Timestamp == %(cast:string "January 1, 2012 %{blah}"))
+match (&Event-Timestamp == %cast(string, "January 1, 2012 %{blah}"))
# This one is NOT an expansion, so it's parsed into normal form
condition &Event-Timestamp == 'January 1, 2012'
condition (ipaddr)127.0.0.1 == "127.0.0.1"
match true
-condition (ipaddr)127.0.0.1 == "%{md4: 127.0.0.1}"
-match (127.0.0.1 == %(cast:string "%{md4: 127.0.0.1}"))
+condition (ipaddr)127.0.0.1 == "%md4(' 127.0.0.1')"
+match (127.0.0.1 == %cast(string, "%md4(' 127.0.0.1')"))
#
# Bare %{...} is allowed.
#
-condition (ipaddr)127.0.0.1 == %{md4:127.0.0.1}
-match (127.0.0.1 == %{md4:127.0.0.1})
+condition (ipaddr)127.0.0.1 == %md4('127.0.0.1')
+match (127.0.0.1 == %md4('127.0.0.1'))
-condition (ipaddr)127.0.0.1 == %{md4: SELECT user FROM table WHERE user='%{User-Name}'}
-match (127.0.0.1 == %{md4: SELECT user FROM table WHERE user='%{User-Name}'})
+condition (ipaddr)127.0.0.1 == %md4("SELECT user FROM table WHERE user='%{User-Name}'")
+match (127.0.0.1 == %md4("SELECT user FROM table WHERE user='%{User-Name}'"))
condition (ether) 00:11:22:33:44:55 == "00:11:22:33:44:55"
match true
-condition (ether) 00:11:22:33:44:55 == "%{md4:00:11:22:33:44:55}"
-match (00:11:22:33:44:55 == %(cast:string "%{md4:00:11:22:33:44:55}"))
+condition (ether) 00:11:22:33:44:55 == "%md4('00:11:22:33:44:55')"
+match (00:11:22:33:44:55 == %cast(string, "%md4('00:11:22:33:44:55')"))
condition (ether) 00:XX:22:33:44:55 == 00:11:22:33:44:55
match ERROR offset 12: Missing separator, expected ':'
condition ('foo' == 'foo')
match true
-condition ("foo" == "%{md4: foo}")
-match ("foo" == %(cast:string "%{md4: foo}"))
+condition ("foo" == "%md4(' foo')")
+match ("foo" == %cast(string, "%md4(' foo')"))
-condition ("foo bar" == "%{md4: foo}")
-match ("foo bar" == %(cast:string "%{md4: foo}"))
+condition ("foo bar" == "%md4(' foo')")
+match ("foo bar" == %cast(string, "%md4(' foo')"))
condition ("foo" == "bar")
match false
condition (&User-Name == "bob")
match (&User-Name == "bob")
-condition (&User-Name == "%{md4: blah}")
-match (&User-Name == %(cast:string "%{md4: blah}"))
+condition (&User-Name == "%md4(' blah')")
+match (&User-Name == %cast(string, "%md4(' blah')"))
condition (ipaddr)127.0.0.1 == 2130706433
match true
# Module return codes are OK
#
condition (ok)
-match %{rcode:'ok'}
+match %rcode('ok')
condition (handled)
-match %{rcode:'handled'}
+match %rcode('handled')
condition (fail)
-match %{rcode:'fail'}
+match %rcode('fail')
condition ("a")
match "a"
match ("foo" == &User-Name)
# This used to be expr, but expr isn't a builtin, so it failed...
-condition (integer)"%{md4: 1 + 1}" < &NAS-Port
-match (%(cast:uint32 "%{md4: 1 + 1}") < &NAS-Port)
+condition (integer)"%md4(' 1 + 1')" < &NAS-Port
+match (%cast(uint32, "%md4(' 1 + 1')") < &NAS-Port)
#
# The string gets parsed as an IP address.
# but these are allowed
condition (ether)&Tmp-uint64-0 == "%interpreter('foo')"
-match ((ether)&Tmp-uint64-0 == %(cast:string "%(interpreter:'foo')"))
+match ((ether)&Tmp-uint64-0 == %cast(string, "%interpreter('foo')"))
condition (ipaddr)&Filter-Id == &Framed-IP-Address
match ((ipaddr)&Filter-Id == &Framed-IP-Address)
# data &Acct-Input-Octets > &Session-Timeout
#
condition &Acct-Input-Octets > "%{Session-Timeout}"
-match (&Acct-Input-Octets > %(cast:string "%{Session-Timeout}"))
+match (&Acct-Input-Octets > %cast(string, "%{Session-Timeout}"))
# Separate types aren't optimized
condition &Acct-Input-Octets-64 > "%{Session-Timeout}"
-match (&Acct-Input-Octets-64 > %(cast:string "%{Session-Timeout}"))
+match (&Acct-Input-Octets-64 > %cast(string, "%{Session-Timeout}"))
#
# Parse OIDs into known attributes, where possible.
xlat %{Tunnel-Password}
match %{Tunnel-Password}
-xlat %{test:bar}
-match %{test:bar}
+xlat %test('bar')
+match %test('bar')
xlat %{Tunnel-Password}
match %{Tunnel-Password}
xlat /([A-Z0-9\\-]*)_%{Calling-Station-Id}/
match /([A-Z0-9\\-]*)_%{Calling-Station-Id}/
-xlat %(length:)
-match %(length:)
+xlat %length()
+match %length()
xlat %(length:
match ERROR offset 10: Missing closing brace
match \"%t\t%{NAS-IP-Address}\"
xlat \"foo %test('foo')\"
-match \"foo %{test:'foo'}\"
+match \"foo %test('foo')\"
#
# Alternations
xlat %{:bar}
match ERROR offset 3: Missing expansion function
-xlat %{foo: bar}
-match ERROR offset 3: Unresolved expansion functions are not allowed here
+xlat %foo(' bar')
+match ERROR offset 2: Unresolved expansion functions are not allowed here
xlat %{[}
match ERROR offset 3: Missing attribute name
match [0]{ echo }, [1]{ hello }, [2]{ %{Tmp-String-0}:1234 }, [3]{ world }
xlat %(debug: 5)
-match %(debug: 5)
+match %debug(, 5)
xlat %(debug: "foo")
-match %(debug: "foo")
+match %debug(, "foo")
#
# This is correct.
#
xlat %(rpad:&User-Name 5 x)
-match %(rpad:&User-Name 5 x)
+match %rpad(&User-Name, 5, x)
#
# The second argument should be an integer.
#
# Argument quoting
#
-xlat %{md5:"arg"}
-match %{md5:"arg"}
+xlat %md5('"arg"')
+match %md5('"arg"')
-xlat %{md5:"arg}"}
-match %{md5:"arg}"}
+xlat %md5('"arg')"}
+match %md5('"arg')\"}
-xlat %{md5:"arg}
-match ERROR offset 12: Missing closing '"'
+xlat %md5('"arg')
+match %md5('"arg')
-xlat %{md5:"arg\""}
-match %{md5:"arg\""}
+#
+# @todo - ??? not sure here
+#
+xlat %md5('"arg\""')
+match %md5('"arg\\""')
xlat %{md5:'arg'}
-match %{md5:'arg'}
+match %md5('arg')
xlat %{md5:'arg"'}
-match %{md5:'arg"'}
+match %md5('arg"')
count
match 157
# Truthy strings get omitted.
#
xlat_purify ('handled' && (&Packet-Type == Access-Challenge))
-match (&Packet-Type == Access-Challenge)
+match (&Packet-Type == Access-Challenge)
xlat_purify (handled && (&Packet-Type == Access-Challenge))
-match (%{rcode:'handled'} && (&Packet-Type == Access-Challenge))
+match (%rcode('handled') && (&Packet-Type == Access-Challenge))
# This is OK, without the braces
xlat_purify 'handled' && &Packet-Type == Access-Challenge
# This one is be an expansion, so it's left as-is.
#
xlat_purify &Event-Timestamp == "January 1, 2012 %{User-Name}"
-match (&Event-Timestamp == %(cast:string "January 1, 2012 %{User-Name}"))
+match (&Event-Timestamp == %cast(string, "January 1, 2012 %{User-Name}"))
# This one is NOT an expansion, so it's parsed into normal form
xlat_purify &Event-Timestamp == 'January 1 2012'
# LHS is IPaddr, RHS is string (malformed IP address).
# We can only fail this at run-time.
-xlat_purify (ipaddr)127.0.0.1 == "%{md4: 127.0.0.1}"
-match (127.0.0.1 == %(cast:string "%{md4: 127.0.0.1}"))
+xlat_purify (ipaddr)127.0.0.1 == "%md4(' 127.0.0.1')"
+match (127.0.0.1 == %cast(string, "%md4(' 127.0.0.1')"))
#
# Bare %{...} is allowed.
#
# Invalid cast from octets to ipaddr.
-xlat_purify (ipaddr)127.0.0.1 == %{md4:127.0.0.1}
-match (127.0.0.1 == %{md4:127.0.0.1})
+xlat_purify (ipaddr)127.0.0.1 == %md4('127.0.0.1')
+match (127.0.0.1 == %md4('127.0.0.1'))
xlat_purify (ipaddr)127.0.0.1 == %{md4: SELECT user FROM table WHERE user='%{User-Name}'}
-match (127.0.0.1 == %{md4: SELECT user FROM table WHERE user='%{User-Name}'})
+match (127.0.0.1 == %md4( SELECT user FROM table WHERE user='%{User-Name}'))
xlat_purify (ether) 00:11:22:33:44:55 == "00:11:22:33:44:55"
match true
# Invalid cast from octets to ether.
-xlat_purify (ether)00:11:22:33:44:55 == "%{md4:00:11:22:33:44:55}"
-match (00:11:22:33:44:55 == %(cast:string "%{md4:00:11:22:33:44:55}"))
+xlat_purify (ether)00:11:22:33:44:55 == "%md4('00:11:22:33:44:55')"
+match (00:11:22:33:44:55 == %cast(string, "%md4('00:11:22:33:44:55')"))
xlat_purify (ether) 00:XX:22:33:44:55 == 00:11:22:33:44:55
match ERROR offset 12: Missing separator, expected ':'
#
# MD4 hash is not equal to other things
#
-xlat_purify ("foo" == "%{md4: foo}")
+xlat_purify ("foo" == "%md4(' foo')")
match false
-xlat_purify ("foo bar" == "%{md4: foo}")
+xlat_purify ("foo bar" == "%md4(' foo')")
match false
xlat_purify ("foo" == "bar")
xlat_purify (&User-Name == "bob")
match (&User-Name == "bob")
-xlat_purify (&User-Name == %{md4: blah})
+xlat_purify (&User-Name == %md4(' blah'))
match (&User-Name == 0x544924d05ec4481925ba3749a096a0a7)
# and without the double quotes.
-xlat_purify (&User-Name == %{md4: blah})
+xlat_purify (&User-Name == %md4(' blah'))
match (&User-Name == 0x544924d05ec4481925ba3749a096a0a7)
xlat_purify (ipaddr)127.0.0.1 == 2130706433
#
# ERROR: Failed casting 0x002ade8665c69219ca16bd108d92c8d5 to data type uint32: Invalid cast from octets to uint32. Source length 16 is greater than destination type size 4
#
-xlat_purify (integer)"%{md4: 1 + 1}" < &NAS-Port
-match (%(cast:uint32 "%{md4: 1 + 1}") < &NAS-Port)
+xlat_purify (integer)"%md4(' 1 + 1')" < &NAS-Port
+match (%cast(uint32, "%md4(' 1 + 1')") < &NAS-Port)
#
# The string gets parsed as an IP address.
# but these are allowed
xlat_purify (ether)&Tmp-uint64-0 == "%interpreter('foo')"
-match ((ether)&Tmp-uint64-0 == %(cast:string "%(interpreter:'foo')"))
+match ((ether)&Tmp-uint64-0 == %cast(string, "%interpreter('foo')"))
xlat_purify (ipaddr)&Filter-Id == &Framed-IP-Address
match ((ipaddr)&Filter-Id == &Framed-IP-Address)
#match &Foo-Bar
xlat_purify &Acct-Input-Octets > "%{Session-Timeout}"
-match (&Acct-Input-Octets > %(cast:string "%{Session-Timeout}"))
+match (&Acct-Input-Octets > %cast(string, "%{Session-Timeout}"))
xlat_purify &Acct-Input-Octets > &Session-Timeout
match (&Acct-Input-Octets > &Session-Timeout)
# rcode tests
#
xlat_purify handled && (&User-Name == "bob")
-match (%{rcode:'handled'} && (&User-Name == "bob"))
+match (%rcode('handled') && (&User-Name == "bob"))
xlat_purify (&User-Name == "bob") && (&User-Password == "bob") && handled
-match ((&User-Name == "bob") && (&User-Password == "bob") && %{rcode:'handled'})
+match ((&User-Name == "bob") && (&User-Password == "bob") && %rcode('handled'))
xlat_purify handledx
match ERROR offset 1: Unexpected text - attribute names must prefixed with '&'
xlat_purify handled
-match %{rcode:'handled'}
+match %rcode('handled')
#
# Automatic casting
xlat_expr &Filter-Id
match &Filter-Id
-xlat_expr %{md5:foo} + "foo"
-match (%{md5:foo} + "foo")
+xlat_expr %md5('foo') + "foo"
+match (%md5('foo') + "foo")
# We can name the xlat's, tho we don't need to
xlat_expr %(op_add:4 3) + 6
match ((1 < 2) < 3)
xlat_expr (uint32) %(concat:1 2)
-match %(cast:uint32 %(concat:1 2))
+match %cast(uint32, %concat(1, 2))
#
# Mashing multiple brackets together. The brackets are removed as
match ((5 + 5) - 10)
xlat_expr (integer) &Service-Type
-match %(cast:uint32 &Service-Type)
+match %cast(uint32, &Service-Type)
xlat_expr (uint32) (&Service-Type)
-match %(cast:uint32 &Service-Type)
+match %cast(uint32, &Service-Type)
count
match 69
match %Y
xlat %explode("a,b,c,d", ',')
-match %(explode:"a,b,c,d" ',')
+match %explode("a,b,c,d", ',')
#xlat %md5(foo)
#match foo
xlat_purify &Filter-Id
match &Filter-Id
-xlat_purify %{md5:foo} + "bar"
+xlat_purify %md5('foo') + "bar"
match 0xacbd18db4cc2f85cedef654fccc4a4d8626172
# We can name the xlat's, tho we don't need to
match ERROR offset 6: Invalid operation on module return code
xlat_purify !fail
-match !%{rcode:'fail'}
+match !%rcode('fail')
#
# Casts and such
# @todo - xlat_tokenize() does not call purify
#
xlat_purify (string)(%{1 + 2})
-match %(cast:string (1 + 2))
+match %cast(string, (1 + 2))
#
# This is a different code path than the above.
#
xlat_purify (string)%{1 + 2}
-match %(cast:string (1 + 2))
+match %cast(string, (1 + 2))
xlat_purify "hello"
match "hello"
# The real run-time tests work
#
xlat_purify "hello %{1 + 2} bob"
-match %(cast:string "hello (1 + 2) bob")
+match %cast(string, "hello (1 + 2) bob")
#
# New syntax!
#
migrate xlat_new_functions = yes
-xlat_purify %{md5:foo}
+xlat_purify %md5('foo')
match 0xacbd18db4cc2f85cedef654fccc4a4d8
xlat_purify %explode("a,b,c,d", ',')
# This is a reference to the contents of &User-Name
#
xlat_purify %md5(&User-Name)
-match %{md5:&User-Name}
+match %md5(&User-Name)
xlat_purify %md5('foo')