summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYegappan Lakshmanan <yegappan@yahoo.com>2024-06-03 18:52:22 +0200
committerChristian Brabandt <cb@256bit.org>2024-06-03 18:52:22 +0200
commit734286e4c626f80ace27eeb252a5e384e798aebf (patch)
tree5a87a878cb8a82bd071eec1ce64b6ebef27f7160
parentf51ff96532ab8f97f779b44d17dccdda9d8ce566 (diff)
patch 9.1.0462: eval5() and eval7 are too complexv9.1.0462
Problem: eval5() and eval7 are too complex Solution: Refactor eval5() and eval7() in eval.c (Yegappan Lakshmanan) closes: #14900 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r--src/eval.c275
-rw-r--r--src/scriptfile.c4
-rw-r--r--src/version.c2
3 files changed, 154 insertions, 127 deletions
diff --git a/src/eval.c b/src/eval.c
index 4a039792c8..7848feaa87 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3947,6 +3947,40 @@ eval_addlist(typval_T *tv1, typval_T *tv2)
}
/*
+ * Left or right shift the number "tv1" by the number "tv2" and store the
+ * result in "tv1".
+ *
+ * Return OK or FAIL.
+ */
+ static int
+eval_shift_number(typval_T *tv1, typval_T *tv2, int shift_type)
+{
+ if (tv2->v_type != VAR_NUMBER || tv2->vval.v_number < 0)
+ {
+ // right operand should be a positive number
+ if (tv2->v_type != VAR_NUMBER)
+ emsg(_(e_bitshift_ops_must_be_number));
+ else
+ emsg(_(e_bitshift_ops_must_be_positive));
+ clear_tv(tv1);
+ clear_tv(tv2);
+ return FAIL;
+ }
+
+ if (tv2->vval.v_number > MAX_LSHIFT_BITS)
+ // shifting more bits than we have always results in zero
+ tv1->vval.v_number = 0;
+ else if (shift_type == EXPR_LSHIFT)
+ tv1->vval.v_number =
+ (uvarnumber_T)tv1->vval.v_number << tv2->vval.v_number;
+ else
+ tv1->vval.v_number =
+ (uvarnumber_T)tv1->vval.v_number >> tv2->vval.v_number;
+
+ return OK;
+}
+
+/*
* Handle the bitwise left/right shift operator expression:
* var1 << var2
* var1 >> var2
@@ -3972,16 +4006,16 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
char_u *p;
int getnext;
- exprtype_T type;
+ exprtype_T exprtype;
int evaluate;
typval_T var2;
int vim9script;
p = eval_next_non_blank(*arg, evalarg, &getnext);
if (p[0] == '<' && p[1] == '<')
- type = EXPR_LSHIFT;
+ exprtype = EXPR_LSHIFT;
else if (p[0] == '>' && p[1] == '>')
- type = EXPR_RSHIFT;
+ exprtype = EXPR_RSHIFT;
else
return OK;
@@ -4026,27 +4060,8 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
if (evaluate)
{
- if (var2.v_type != VAR_NUMBER || var2.vval.v_number < 0)
- {
- // right operand should be a positive number
- if (var2.v_type != VAR_NUMBER)
- emsg(_(e_bitshift_ops_must_be_number));
- else
- emsg(_(e_bitshift_ops_must_be_positive));
- clear_tv(rettv);
- clear_tv(&var2);
+ if (eval_shift_number(rettv, &var2, exprtype) == FAIL)
return FAIL;
- }
-
- if (var2.vval.v_number > MAX_LSHIFT_BITS)
- // shifting more bits than we have always results in zero
- rettv->vval.v_number = 0;
- else if (type == EXPR_LSHIFT)
- rettv->vval.v_number =
- (uvarnumber_T)rettv->vval.v_number << var2.vval.v_number;
- else
- rettv->vval.v_number =
- (uvarnumber_T)rettv->vval.v_number >> var2.vval.v_number;
}
clear_tv(&var2);
@@ -4100,7 +4115,7 @@ eval_concat_str(typval_T *tv1, typval_T *tv2)
* The numbers can be whole numbers or floats.
*/
static int
-eval_addsub_num(typval_T *tv1, typval_T *tv2, int op)
+eval_addsub_number(typval_T *tv1, typval_T *tv2, int op)
{
int error = FALSE;
varnumber_T n1, n2;
@@ -4290,7 +4305,7 @@ eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
}
else
{
- if (eval_addsub_num(rettv, &var2, op) == FAIL)
+ if (eval_addsub_number(rettv, &var2, op) == FAIL)
return FAIL;
}
clear_tv(&var2);
@@ -4300,6 +4315,113 @@ eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
}
/*
+ * 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)
+{
+ varnumber_T n1, n2;
+ float_T f1, f2;
+ int error;
+ int use_float = FALSE;
+
+ f1 = 0;
+ f2 = 0;
+ 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);
+ clear_tv(tv1);
+ if (error)
+ {
+ clear_tv(tv2);
+ return FAIL;
+ }
+
+ if (tv2->v_type == VAR_FLOAT)
+ {
+ if (!use_float)
+ {
+ f1 = n1;
+ use_float = TRUE;
+ }
+ f2 = tv2->vval.v_float;
+ n2 = 0;
+ }
+ else
+ {
+ n2 = tv_get_number_chk(tv2, &error);
+ clear_tv(tv2);
+ if (error)
+ return FAIL;
+ if (use_float)
+ f2 = 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 == '/')
+ {
+#ifdef VMS
+ // VMS crashes on divide by zero, work around it
+ if (f2 == 0.0)
+ {
+ if (f1 == 0)
+ f1 = -1 * __F_FLT_MAX - 1L; // similar to NaN
+ else if (f1 < 0)
+ f1 = -1 * __F_FLT_MAX;
+ else
+ f1 = __F_FLT_MAX;
+ }
+ else
+ f1 = f1 / f2;
+#else
+ // We rely on the floating point library to handle divide
+ // by zero to result in "inf" and not a crash.
+ f1 = f1 / f2;
+#endif
+ }
+ else
+ {
+ emsg(_(e_cannot_use_percent_with_float));
+ return FAIL;
+ }
+ tv1->v_type = VAR_FLOAT;
+ tv1->vval.v_float = f1;
+ }
+ else
+ {
+ int failed = FALSE;
+
+ if (op == '*')
+ n1 = n1 * n2;
+ else if (op == '/')
+ n1 = num_divide(n1, n2, &failed);
+ else
+ n1 = num_modulus(n1, n2, &failed);
+ if (failed)
+ return FAIL;
+
+ tv1->v_type = VAR_NUMBER;
+ tv1->vval.v_number = n1;
+ }
+
+ return OK;
+}
+
+/*
* Handle sixth level expression:
* * number multiplication
* / number division
@@ -4317,8 +4439,6 @@ eval7(
evalarg_T *evalarg,
int want_string) // after "." operator
{
- int use_float = FALSE;
-
/*
* Get the first expression.
*/
@@ -4335,9 +4455,6 @@ eval7(
typval_T var2;
char_u *p;
int op;
- varnumber_T n1, n2;
- float_T f1, f2;
- int error;
// "*=", "/=" and "%=" are assignments
p = eval_next_non_blank(*arg, evalarg, &getnext);
@@ -4359,26 +4476,6 @@ eval7(
*arg = p;
}
- f1 = 0;
- f2 = 0;
- error = FALSE;
- 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);
- clear_tv(rettv);
- if (error)
- return FAIL;
- }
- else
- n1 = 0;
-
/*
* Get the second variable.
*/
@@ -4393,81 +4490,9 @@ eval7(
return FAIL;
if (evaluate)
- {
- if (var2.v_type == VAR_FLOAT)
- {
- if (!use_float)
- {
- f1 = n1;
- use_float = TRUE;
- }
- f2 = var2.vval.v_float;
- n2 = 0;
- }
- else
- {
- n2 = tv_get_number_chk(&var2, &error);
- clear_tv(&var2);
- if (error)
- return FAIL;
- if (use_float)
- f2 = 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 == '/')
- {
-#ifdef VMS
- // VMS crashes on divide by zero, work around it
- if (f2 == 0.0)
- {
- if (f1 == 0)
- f1 = -1 * __F_FLT_MAX - 1L; // similar to NaN
- else if (f1 < 0)
- f1 = -1 * __F_FLT_MAX;
- else
- f1 = __F_FLT_MAX;
- }
- else
- f1 = f1 / f2;
-#else
- // We rely on the floating point library to handle divide
- // by zero to result in "inf" and not a crash.
- f1 = f1 / f2;
-#endif
- }
- else
- {
- emsg(_(e_cannot_use_percent_with_float));
- return FAIL;
- }
- rettv->v_type = VAR_FLOAT;
- rettv->vval.v_float = f1;
- }
- else
- {
- int failed = FALSE;
-
- if (op == '*')
- n1 = n1 * n2;
- else if (op == '/')
- n1 = num_divide(n1, n2, &failed);
- else
- n1 = num_modulus(n1, n2, &failed);
- if (failed)
- return FAIL;
-
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n1;
- }
- }
+ // Compute the result.
+ if (eval_multdiv_number(rettv, &var2, op) == FAIL)
+ return FAIL;
}
return OK;
diff --git a/src/scriptfile.c b/src/scriptfile.c
index 6a6a037e32..711f576c09 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -439,8 +439,8 @@ check_script_symlink(int sid)
SCRIPT_ITEM(real_sid)->sn_import_autoload
= si->sn_import_autoload;
if (si->sn_autoload_prefix != NULL)
- SCRIPT_ITEM(real_sid)->sn_autoload_prefix =
- vim_strsave(si->sn_autoload_prefix);
+ SCRIPT_ITEM(real_sid)->sn_autoload_prefix =
+ vim_strsave(si->sn_autoload_prefix);
}
}
}
diff --git a/src/version.c b/src/version.c
index 13010a386d..55282ab82b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 462,
+/**/
461,
/**/
460,