if (quote != T_BARE_WORD) {
if (tmpl_rules_cast(vpt) != FR_TYPE_NULL) {
type = tmpl_rules_cast(vpt);
+ MEM(cast = expr_cast_alloc(head, type));
+
} else {
type = FR_TYPE_STRING;
- }
- MEM(cast = expr_cast_alloc(head, type));
+ /*
+ * The string is T_DOUBLE_QUOTED_STRING, or T_BACK_QUOTED_STRING,
+ * both of which have double-quoting rules.
+ *
+ * 'foo' can't contain an xlat.
+ * /foo/ is forbidden, as we don't expect a regex here.
+ */
+ MEM(cast = xlat_exp_alloc(head, XLAT_FUNC, "print", 5));
+ MEM(cast->call.args = xlat_exp_head_alloc(cast));
+ MEM(cast->call.func = xlat_func_find("print", 5));
+ fr_assert(cast->call.func != NULL);
+ cast->flags = cast->call.func->flags;
+ }
xlat_func_append_arg(cast, node, false);
node = cast;
# @todo - yuck. Suppress full path?
#
xlat_purify &Event-Timestamp == "January 1, 2012 %{User-Name}"
-match (&Event-Timestamp == %(cast:string "January 1, 2012 %{Request[0].User-Name}"))
+match (&Event-Timestamp == %(print:"January 1, 2012 %{Request[0].User-Name}"))
# This one is NOT an expansion, so it's parsed into normal form
xlat_purify &Event-Timestamp == 'January 1 2012'
# but these are allowed
xlat_purify <ether>&Tmp-uint64-0 == "%{module: foo}"
-match ((ether)&Tmp-uint64-0 == %(cast:string "%{module: foo}"))
+match ((ether)&Tmp-uint64-0 == %(print:"%{module: 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 "%{Request[0].Session-Timeout}"))
+match (&Acct-Input-Octets > %(print:"%{Request[0].Session-Timeout}"))
xlat_purify &Acct-Input-Octets > &Session-Timeout
match (&Acct-Input-Octets > &Session-Timeout)
xlat_expr -&NAS-IP-Address
match ERROR expanding xlat: Input is empty
+xlat_expr "foo" + (string)&Packet-Src-IP-Address
+match foo127.0.0.1
+
+xlat_expr "foo%{Packet-Src-IP-Address}"
+match foo127.0.0.1
+
+xlat_expr "foo" + (octets)&Packet-Src-IP-Address
+match 0x666f6f7f000001
+
+#
+# @todo - fix escaping of "match" results?
+# This just casts the octets to 'string', without
+# any escaping.
+#
+xlat_expr "foo" + (string)&Packet-Authentication-Vector
+match foo
+
+xlat_expr "foo" + &Packet-Authentication-Vector
+match 0x666f6f00000000000000000000000000000000
+
+#
+# Really "foo" + 16 octets of 0, but it isn't
+# printed correctly. See xlat_expr in unit_test_module.
+#
+xlat_expr "foo" + (string) &Packet-Authentication-Vector
+match foo
+
+# this is "foo" + PRINTABLE version of &Packet-Authentication-Vector
+xlat_expr "foo%{Packet-Authentication-Vector}"
+match foo0x00000000000000000000000000000000
+
+# no escaping!
+xlat_expr 'foo%{Packet-Authentication-Vector}'
+match foo%{Packet-Authentication-Vector}
+
+
+
xlat_expr (uint16) ((uint32) 1 + (uint8) 2)
match 3