aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-08-01 08:57:48 +0800
committerzeertzjq <zeertzjq@outlook.com>2024-08-01 09:28:21 +0800
commit7f1ba04421516c466ac9c3a63721f1e34abb3db1 (patch)
tree85f4a3dfbac23bd08a4d18abf9bb6876316ad035 /src/nvim/eval.c
parent8f47a95addf7387b660ae3b76b303a0f946e4f80 (diff)
downloadrneovim-7f1ba04421516c466ac9c3a63721f1e34abb3db1.tar.gz
rneovim-7f1ba04421516c466ac9c3a63721f1e34abb3db1.tar.bz2
rneovim-7f1ba04421516c466ac9c3a63721f1e34abb3db1.zip
vim-patch:partial:9.1.0462: eval5() and eval7 are too complex
Problem: eval5() and eval7 are too complex Solution: Refactor eval5() and eval7() in eval.c (Yegappan Lakshmanan) closes: vim/vim#14900 https://github.com/vim/vim/commit/734286e4c626f80ace27eeb252a5e384e798aebf Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c156
1 files changed, 83 insertions, 73 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index fa519ad701..b8c3df5688 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -2974,7 +2974,7 @@ static int eval_concat_str(typval_T *tv1, typval_T *tv2)
/// Add or subtract numbers "tv1" and "tv2" and store the result in "tv1".
/// The numbers can be whole numbers or floats.
-static int eval_addsub_num(typval_T *tv1, typval_T *tv2, int op)
+static int eval_addsub_number(typval_T *tv1, typval_T *tv2, int op)
{
bool error = false;
varnumber_T n1, n2;
@@ -3102,7 +3102,7 @@ static int eval5(char **arg, typval_T *rettv, evalarg_T *const evalarg)
return FAIL;
}
} else {
- if (eval_addsub_num(rettv, &var2, op) == FAIL) {
+ if (eval_addsub_number(rettv, &var2, op) == FAIL) {
return FAIL;
}
}
@@ -3112,6 +3112,85 @@ static int eval5(char **arg, typval_T *rettv, evalarg_T *const evalarg)
return OK;
}
+/// Multiply or divide or compute the modulo of numbers "tv1" and "tv2" and
+/// store the result in "tv1". The numbers can be whole numbers or floats.
+static int eval_multdiv_number(typval_T *tv1, typval_T *tv2, int op)
+ FUNC_ATTR_NO_SANITIZE_UNDEFINED
+{
+ varnumber_T n1, n2;
+ bool use_float = false;
+
+ float_T f1 = 0;
+ float_T f2 = 0;
+ bool error = false;
+ if (tv1->v_type == VAR_FLOAT) {
+ f1 = tv1->vval.v_float;
+ use_float = true;
+ n1 = 0;
+ } else {
+ n1 = tv_get_number_chk(tv1, &error);
+ }
+ tv_clear(tv1);
+ if (error) {
+ tv_clear(tv2);
+ return FAIL;
+ }
+
+ if (tv2->v_type == VAR_FLOAT) {
+ if (!use_float) {
+ f1 = (float_T)n1;
+ use_float = true;
+ }
+ f2 = tv2->vval.v_float;
+ n2 = 0;
+ } else {
+ n2 = tv_get_number_chk(tv2, &error);
+ tv_clear(tv2);
+ if (error) {
+ return FAIL;
+ }
+ if (use_float) {
+ f2 = (float_T)n2;
+ }
+ }
+
+ // Compute the result.
+ // When either side is a float the result is a float.
+ if (use_float) {
+ if (op == '*') {
+ f1 = f1 * f2;
+ } else if (op == '/') {
+ // uncrustify:off
+
+ // Division by zero triggers error from AddressSanitizer
+ f1 = (f2 == 0 ? (
+#ifdef NAN
+ f1 == 0 ? (float_T)NAN :
+#endif
+ (f1 > 0 ? (float_T)INFINITY : (float_T)-INFINITY)) : f1 / f2);
+
+ // uncrustify:on
+ } else {
+ emsg(_("E804: Cannot use '%' with Float"));
+ return FAIL;
+ }
+ tv1->v_type = VAR_FLOAT;
+ tv1->vval.v_float = f1;
+ } else {
+ if (op == '*') {
+ n1 = n1 * n2;
+ } else if (op == '/') {
+ n1 = num_divide(n1, n2);
+ } else {
+ n1 = num_modulus(n1, n2);
+ }
+ tv1->v_type = VAR_NUMBER;
+ tv1->vval.v_number = n1;
+ }
+
+ return OK;
+}
+
/// Handle fifth level expression:
/// - * number multiplication
/// - / number division
@@ -3125,10 +3204,7 @@ static int eval5(char **arg, typval_T *rettv, evalarg_T *const evalarg)
/// float
/// @return OK or FAIL.
static int eval6(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool want_string)
- FUNC_ATTR_NO_SANITIZE_UNDEFINED
{
- bool use_float = false;
-
// Get the first variable.
if (eval7(arg, rettv, evalarg, want_string) == FAIL) {
return FAIL;
@@ -3141,26 +3217,7 @@ static int eval6(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool wan
break;
}
- varnumber_T n1, n2;
- float_T f1 = 0;
- float_T f2 = 0;
- bool error = false;
const bool evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
- if (evaluate) {
- if (rettv->v_type == VAR_FLOAT) {
- f1 = rettv->vval.v_float;
- use_float = true;
- n1 = 0;
- } else {
- n1 = tv_get_number_chk(rettv, &error);
- }
- tv_clear(rettv);
- if (error) {
- return FAIL;
- }
- } else {
- n1 = 0;
- }
// Get the second variable.
*arg = skipwhite(*arg + 1);
@@ -3170,56 +3227,9 @@ static int eval6(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool wan
}
if (evaluate) {
- if (var2.v_type == VAR_FLOAT) {
- if (!use_float) {
- f1 = (float_T)n1;
- use_float = true;
- }
- f2 = var2.vval.v_float;
- n2 = 0;
- } else {
- n2 = tv_get_number_chk(&var2, &error);
- tv_clear(&var2);
- if (error) {
- return FAIL;
- }
- if (use_float) {
- f2 = (float_T)n2;
- }
- }
-
// Compute the result.
- // When either side is a float the result is a float.
- if (use_float) {
- if (op == '*') {
- f1 = f1 * f2;
- } else if (op == '/') {
- // uncrustify:off
-
- // Division by zero triggers error from AddressSanitizer
- f1 = (f2 == 0 ? (
-#ifdef NAN
- f1 == 0 ? (float_T)NAN :
-#endif
- (f1 > 0 ? (float_T)INFINITY : (float_T)-INFINITY)) : f1 / f2);
-
- // uncrustify:on
- } else {
- emsg(_("E804: Cannot use '%' with Float"));
- return FAIL;
- }
- rettv->v_type = VAR_FLOAT;
- rettv->vval.v_float = f1;
- } else {
- if (op == '*') {
- n1 = n1 * n2;
- } else if (op == '/') {
- n1 = num_divide(n1, n2);
- } else {
- n1 = num_modulus(n1, n2);
- }
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n1;
+ if (eval_multdiv_number(rettv, &var2, op) == FAIL) {
+ return FAIL;
}
}
}