]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add support for mod (%)
authorAlan T. DeKok <aland@freeradius.org>
Tue, 23 Aug 2022 13:59:09 +0000 (09:59 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 23 Aug 2022 15:11:57 +0000 (11:11 -0400)
doc/antora/modules/reference/nav.adoc
doc/antora/modules/reference/pages/unlang/expression.adoc
src/bin/unit_test_attribute.c
src/lib/unlang/xlat_expr.c
src/lib/util/calc.c
src/lib/util/token.c
src/lib/util/token.h
src/tests/keywords/expr
src/tests/keywords/redundant
src/tests/keywords/redundant-load-balance
src/tests/unit/calc.txt

index 790aa85fde62d5bec632314504b28c6290aa768e..8264e91eca695b3d4fb5aad34274082a4bb3f374 100644 (file)
@@ -33,7 +33,7 @@
 
 *** xref:unlang/condition/index.adoc[Conditional Expressions]
 **** xref:unlang/condition/cmp.adoc[Comparisons]
-**** xref:unlang/expressions.adoc[expressions]
+**** xref:unlang/expression.adoc[expressions]
 **** xref:unlang/condition/operands.adoc[Operands]
 **** xref:unlang/condition/return_code.adoc[The Return Code Operator]
 **** xref:unlang/condition/eq.adoc[The '==' Operator]
index ae47ecf25d5f97bf8b5b7e578d9019d3385bb9c8..b10145799558057929255b785d08ed515fcff81e 100644 (file)
@@ -15,7 +15,7 @@ The following operators are supported (in order of precedence).
 | -         | subtraction
 | *         | multiplication
 | /         | division
-| %%        | remainder TODO
+| %         | remainder
 | ^         | xor
 | (...)     | sub-expression
 |===
index f34f72d08acff5e296c0bd3b97029128161b8db8..94e28a49aee2bbcb5d70af81fde7c5f7f73a6a97 100644 (file)
@@ -1208,6 +1208,7 @@ static const fr_token_t token2op[UINT8_MAX + 1] = {
        [ '.' ] = T_ADD,
        [ '&' ] = T_AND,
        [ '|' ] = T_OR,
+       [ '%' ] = T_MOD,
 };
 
 /** Perform calculations
index c3ba9ada926a4dbdf22d41a1dfca8a6c478a9dab..6e10908b7d838472110f523a6add8cf6ef0e3b8f 100644 (file)
@@ -468,6 +468,7 @@ XLAT_BINARY_FUNC(op_add, T_ADD)
 XLAT_BINARY_FUNC(op_sub, T_SUB)
 XLAT_BINARY_FUNC(op_mul, T_MUL)
 XLAT_BINARY_FUNC(op_div, T_DIV)
+XLAT_BINARY_FUNC(op_mod, T_MOD)
 XLAT_BINARY_FUNC(op_and, T_AND)
 XLAT_BINARY_FUNC(op_or,  T_OR)
 XLAT_BINARY_FUNC(op_xor,  T_XOR)
@@ -1677,6 +1678,7 @@ int xlat_register_expressions(void)
        XLAT_REGISTER_BINARY_OP(T_SUB, sub);
        XLAT_REGISTER_BINARY_OP(T_MUL, mul);
        XLAT_REGISTER_BINARY_OP(T_DIV, div);
+       XLAT_REGISTER_BINARY_OP(T_MOD, mod);
        XLAT_REGISTER_BINARY_OP(T_AND, and);
        XLAT_REGISTER_BINARY_OP(T_OR, or);
        XLAT_REGISTER_BINARY_OP(T_XOR, xor);
@@ -1734,6 +1736,7 @@ static const fr_sbuff_term_elem_t binary_ops[T_TOKEN_LAST] = {
        [ T_SUB ]               = L("op_sub"),
        [ T_MUL ]               = L("op_mul"),
        [ T_DIV ]               = L("op_div"),
+       [ T_MOD ]               = L("op_mod"),
        [ T_AND ]               = L("op_and"),
        [ T_OR ]                = L("op_or"),
        [ T_XOR ]               = L("op_xor"),
@@ -1822,6 +1825,7 @@ static const int precedence[T_TOKEN_LAST] = {
 
        [T_MUL]         = P(8,0),
        [T_DIV]         = P(8,1),
+       [T_MOD]         = P(8,2),
 
        [T_OP_REG_EQ]   = P(9,0),
        [T_OP_REG_NE]   = P(9,0),
@@ -2410,6 +2414,7 @@ static fr_table_num_ordered_t const expr_assignment_op_table[] = {
        { L("+"),       T_ADD                   },
        { L("-"),       T_SUB                   },
        { L("/"),       T_DIV                   },
+       { L("%"),       T_MOD                   },
        { L("^"),       T_XOR                   },
 
        { L("|"),       T_OR                    },
index 7b5bf1b22d65020aff0c9f612ea607a4dfae6550..276db9e8bd50285f35a9a5cd634db1dc63e384a7 100644 (file)
@@ -1436,6 +1436,12 @@ static int calc_float32(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_bo
                dst->vb_float32 = a->vb_float64 / b->vb_float64;
                break;
 
+       case T_MOD:
+               if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
+
+               dst->vb_float32 = fmod(a->vb_float64, b->vb_float64);
+               break;
+
        default:
                return ERR_INVALID;
        }
@@ -1474,6 +1480,12 @@ static int calc_float64(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_bo
                dst->vb_float64 = a->vb_float64 / b->vb_float64;
                break;
 
+       case T_MOD:
+               if (fpclassify(b->vb_float64) == FP_ZERO) return ERR_ZERO;
+
+               dst->vb_float64 = fmod(a->vb_float64, b->vb_float64);
+               break;
+
        default:
                return ERR_INVALID;
        }
@@ -1498,8 +1510,16 @@ static int calc_float64(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_bo
                break; \
  \
        case T_DIV: \
+               if (in2->vb_ ## _t == 0) return ERR_ZERO; \
+ \
                dst->vb_ ## _t = in1->vb_ ## _t /  in2->vb_ ## _t; \
                break; \
+ \
+       case T_MOD: \
+               if (in2->vb_ ## _t == 0) return ERR_ZERO; \
+ \
+               dst->vb_ ## _t = in1->vb_ ## _t %  in2->vb_ ## _t; \
+               break; \
  \
        case T_AND: \
                dst->vb_ ## _t = in1->vb_ ## _t &  in2->vb_ ## _t; \
@@ -1761,6 +1781,7 @@ int fr_value_calc_binary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t hint
                case T_SUB:
                case T_MUL:
                case T_DIV:
+               case T_MOD:
                case T_XOR:
                        /*
                         *      Nothing else set it.  If the input types are
@@ -1896,6 +1917,7 @@ int fr_value_calc_binary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t hint
        case T_SUB:
        case T_MUL:
        case T_DIV:
+       case T_MOD:
        case T_AND:
        case T_OR:
        case T_XOR:
index 47fc882a31933ffa00bc9ab8fd5870d91c9f00be..d194becf5e3bafef08633f3ed6c46963baa2e2b2 100644 (file)
@@ -69,7 +69,7 @@ fr_table_num_sorted_t const fr_token_quotes_table[] = {
 size_t fr_token_quotes_table_len = NUM_ELEMENTS(fr_token_quotes_table);
 
 /*
- *  This is a hack, and has to be kept in sync with tokens.h
+ *  String versions for all of the tokens.
  */
 char const *fr_tokens[T_TOKEN_LAST] = {
        [T_INVALID] = "?",
@@ -91,6 +91,7 @@ char const *fr_tokens[T_TOKEN_LAST] = {
        [T_NOT]      = "!",
        [T_XOR]      = "^",
        [T_COMPLEMENT]  = "~",
+       [T_MOD]  = "%",
 
        [T_RSHIFT]   = ">>",
        [T_LSHIFT]   = "<<",
@@ -210,6 +211,7 @@ const bool fr_binary_op[T_TOKEN_LAST] = {
        T(DIV),
        T(AND),
        T(OR),
+       T(MOD),
        T(RSHIFT),
        T(LSHIFT),
 };
index ce14f78ae82734e1a6b41752465e33bf445de916..79c01df894fe3cdd2d2c60471b4600718a4b5792 100644 (file)
@@ -57,6 +57,7 @@ typedef enum fr_token {
        T_NOT,                          /* ! */
        T_XOR,                          /* ^ */
        T_COMPLEMENT,                   /* ~ */
+       T_MOD,                          /* % */
 
        T_RSHIFT,                       /* >> */
        T_LSHIFT,                       /* << */
index 1f2c02fa5949ac2a6706ba9657c9d4e1f1e755cd..448a3138d633eab4d94179eb3b49e815874916a3 100644 (file)
@@ -73,6 +73,13 @@ if (-1 * 2 != -2) {
        test_fail
 }
 
+if ("%{expr: 11 % 2}" != 1) {
+       test_fail
+}
+if (11 % 2 != 1) {
+       test_fail
+}
+
 if ("%{expr: 2 - -1}" != 3) {
        test_fail
 }
index f858ad9a858c7ab511f87918c6949b55e7b89609..f1c80178771b2f4cef5b148322dc45e05ed00d68 100644 (file)
@@ -39,7 +39,7 @@ foreach &Tmp-Integer-1 {
        redundant {
                group {
                        # fail on even numbered values, succeed on odd numbered ones
-                       if ("%{expr:%{Foreach-Variable-0} % 2}" == 0) {
+                       if (%{Foreach-Variable-0} % 2 == 0) {
                                fail
                        }
                        else {
@@ -52,7 +52,7 @@ foreach &Tmp-Integer-1 {
                }
                group {
                        # succeed on even-numbered values, fail on off-numbered ones.
-                       if ("%{expr:%{Foreach-Variable-0} % 2}" == 1) {
+                       if (%{Foreach-Variable-0} % 2 == 1) {
                                fail
                        }
                        else {
index 35aa1f193994baa89af3645641ae1158e99a16bc..5966de527aacc67ae42e6553aa37dbd417ddaf31 100644 (file)
@@ -25,7 +25,7 @@ foreach &Tmp-Integer-1 {
        redundant-load-balance {
                group {
                        # fail on even numbered values, succeed on odd numbered ones
-                       if ("%{expr:%{Foreach-Variable-0} % 2}" == 0) {
+                       if (%{Foreach-Variable-0} % 2 == 0) {
                                fail
                        }
                        else {
@@ -38,7 +38,7 @@ foreach &Tmp-Integer-1 {
                }
                group {
                        # succeed on even-numbered values, fail on off-numbered ones.
-                       if ("%{expr:%{Foreach-Variable-0} % 2}" == 1) {
+                       if (%{Foreach-Variable-0} % 2 == 1) {
                                fail
                        }
                        else {
index 1036c94a7ee3c6a11fc3767910dbc54a180b742b..d0f2e60b82f909704d4b76cc219da266cdc8fb78 100644 (file)
@@ -23,6 +23,9 @@ match 13
 calc int32 -1 + uint8 14 -> int16
 match 13
 
+calc int32 11 % uint8 2 -> int16
+match 1
+
 calc int8 0x7f & uint8 0x40 -> uint8
 match 64
 
@@ -150,6 +153,12 @@ match 3.500000
 calc float32 1.0 * float32 2.5 -> float32
 match 2.500000
 
+calc float32 11.0 % float32 2.0 -> float32
+match 1.000000
+
+calc float32 11.0 % float32 0.0 -> float32
+match Cannot divide by zero.
+
 ######################################################################
 #
 #  Assignment operations
@@ -164,4 +173,4 @@ calc string "2" += string "test"
 match 2test
 
 count
-match 70
+match 76