From: Alan T. DeKok Date: Tue, 23 Aug 2022 13:59:09 +0000 (-0400) Subject: add support for mod (%) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34e70543c8dc73693f0de2c17e5c02d42a313cfe;p=thirdparty%2Ffreeradius-server.git add support for mod (%) --- diff --git a/doc/antora/modules/reference/nav.adoc b/doc/antora/modules/reference/nav.adoc index 790aa85fde6..8264e91eca6 100644 --- a/doc/antora/modules/reference/nav.adoc +++ b/doc/antora/modules/reference/nav.adoc @@ -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] diff --git a/doc/antora/modules/reference/pages/unlang/expression.adoc b/doc/antora/modules/reference/pages/unlang/expression.adoc index ae47ecf25d5..b1014579955 100644 --- a/doc/antora/modules/reference/pages/unlang/expression.adoc +++ b/doc/antora/modules/reference/pages/unlang/expression.adoc @@ -15,7 +15,7 @@ The following operators are supported (in order of precedence). | - | subtraction | * | multiplication | / | division -| %% | remainder TODO +| % | remainder | ^ | xor | (...) | sub-expression |=== diff --git a/src/bin/unit_test_attribute.c b/src/bin/unit_test_attribute.c index f34f72d08ac..94e28a49aee 100644 --- a/src/bin/unit_test_attribute.c +++ b/src/bin/unit_test_attribute.c @@ -1208,6 +1208,7 @@ static const fr_token_t token2op[UINT8_MAX + 1] = { [ '.' ] = T_ADD, [ '&' ] = T_AND, [ '|' ] = T_OR, + [ '%' ] = T_MOD, }; /** Perform calculations diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index c3ba9ada926..6e10908b7d8 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -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 }, diff --git a/src/lib/util/calc.c b/src/lib/util/calc.c index 7b5bf1b22d6..276db9e8bd5 100644 --- a/src/lib/util/calc.c +++ b/src/lib/util/calc.c @@ -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: diff --git a/src/lib/util/token.c b/src/lib/util/token.c index 47fc882a319..d194becf5e3 100644 --- a/src/lib/util/token.c +++ b/src/lib/util/token.c @@ -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), }; diff --git a/src/lib/util/token.h b/src/lib/util/token.h index ce14f78ae82..79c01df894f 100644 --- a/src/lib/util/token.h +++ b/src/lib/util/token.h @@ -57,6 +57,7 @@ typedef enum fr_token { T_NOT, /* ! */ T_XOR, /* ^ */ T_COMPLEMENT, /* ~ */ + T_MOD, /* % */ T_RSHIFT, /* >> */ T_LSHIFT, /* << */ diff --git a/src/tests/keywords/expr b/src/tests/keywords/expr index 1f2c02fa594..448a3138d63 100644 --- a/src/tests/keywords/expr +++ b/src/tests/keywords/expr @@ -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 } diff --git a/src/tests/keywords/redundant b/src/tests/keywords/redundant index f858ad9a858..f1c80178771 100644 --- a/src/tests/keywords/redundant +++ b/src/tests/keywords/redundant @@ -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 { diff --git a/src/tests/keywords/redundant-load-balance b/src/tests/keywords/redundant-load-balance index 35aa1f19399..5966de527aa 100644 --- a/src/tests/keywords/redundant-load-balance +++ b/src/tests/keywords/redundant-load-balance @@ -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 { diff --git a/src/tests/unit/calc.txt b/src/tests/unit/calc.txt index 1036c94a7ee..d0f2e60b82f 100644 --- a/src/tests/unit/calc.txt +++ b/src/tests/unit/calc.txt @@ -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