]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow cast to same data type to mean "print value, not enum name"
authorAlan T. DeKok <aland@freeradius.org>
Fri, 16 Aug 2024 20:06:25 +0000 (16:06 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 17 Aug 2024 13:07:36 +0000 (09:07 -0400)
because I tried to use it, and it didn't work.  So the logical
next step is to make it work.

src/lib/server/tmpl_tokenize.c
src/lib/unlang/xlat_expr.c
src/tests/keywords/cast-integer
src/tests/unit/xlat/expr.txt

index b5d9d4abf5e88ef98964ef54f85306a1010c8827..7add1c3d07ac6034cf2137f943ccaa00d82ec806 100644 (file)
@@ -3593,15 +3593,33 @@ int tmpl_cast_set(tmpl_t *vpt, fr_type_t dst_type)
                goto check_types;
 
        case TMPL_TYPE_ATTR:
-               src_type = tmpl_attr_tail_da(vpt)->type;
+               {
+                       fr_dict_attr_t const *da = tmpl_attr_tail_da(vpt);
 
+                       /*
+                        *      If the attribute has an enum, then the cast means "use the raw value, and not
+                        *      the enum name".
+                        */
+                       if (da->type == dst_type) {
+                               if (da->flags.has_value) goto done;
+                               return 0;
+                       }
+                       src_type = da->type;
+               }
 
                /*
-                *      Suppress casts where they are duplicate.
+                *      Suppress casts where they are duplicate, unless there's an enumv.  In which case the
+                *      cast means "don't print the enumv value, just print the raw data".
                 */
        check_types:
                if (src_type == dst_type) {
-                       tmpl_rules_cast(vpt) = FR_TYPE_NULL;
+                       /*
+                        *      Cast with enumv means "use the raw value, and not the enum name".
+                        */
+                       if (tmpl_rules_enumv(vpt)) {
+                               tmpl_rules_enumv(vpt) = NULL;
+                               goto done;
+                       }
                        return 0;
                }
 
index c2ab44cdad664a33d6f1c1d07adfdcaebf414264..f1349db83d9cf769ca1fdb71e6f2e881094338ed 100644 (file)
@@ -2589,7 +2589,8 @@ static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf
                         *      case, the cast will convert the value-box to one _without_ an enumv entry, which means
                         *      that the value will get printed as its underlying data type, and not as the enum name.
                         */
-                       if (da && !da->flags.has_value && (da->type == cast_type)) {
+                       if (da && (da->type == cast_type)) {
+                               tmpl_cast_set(vpt, cast_type);
                                cast_type = FR_TYPE_NULL;
                        }
 
index 09ba3fd1fbcc2bef4875fe6aaa5033959d950f14..c5cd8f79e8ca8518ba5ee87db93441087be2204d 100644 (file)
@@ -30,3 +30,16 @@ if (&foo != (&zscore + (uint64) 0x10000000000000)) {
        test_fail
 }
 
+&Service-Type := ::Framed-User
+
+if ((uint32) &Service-Type != 2) {
+       test_fail
+}
+
+#
+#  Cast Service-Type to it's underlying data type,
+#  which means "don't print the enum name".
+#
+if ("%{(uint32) &Service-Type}" != "2") {
+       test_fail
+}
index f192bfa56e5145c039279fbda642d831adcd0ecd..b09b6a35a0dac400e7e4ba37a71bee092359d34d 100644 (file)
@@ -136,8 +136,12 @@ xlat_expr 5 + 5 - 10
 match ((5 + 5) - 10)
 
 xlat_expr (integer) &Service-Type
-match %cast(uint32, &Service-Type)
+match (uint32)&Service-Type
 
+#
+#  Wrapping the RHS in brackets means that the parse doesn't hoist
+#  things, and thus can't add the cast to the tmpl.
+#
 xlat_expr (uint32) (&Service-Type)
 match %cast(uint32, &Service-Type)