changeset 35320:8cd13d3c8154 v9.1.0462

patch 9.1.0462: eval5() and eval7 are too complex Commit: https://github.com/vim/vim/commit/734286e4c626f80ace27eeb252a5e384e798aebf Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Mon Jun 3 18:52:22 2024 +0200 patch 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: #14900 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Mon, 03 Jun 2024 19:15:05 +0200
parents 96dcc3359d6a
children 61ecc55e0127
files src/eval.c src/scriptfile.c src/version.c
diffstat 3 files changed, 154 insertions(+), 127 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -3947,6 +3947,40 @@ eval_addlist(typval_T *tv1, typval_T *tv
 }
 
 /*
+ * 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, eva
     {
 	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, eva
 
 	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 
  * 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, eva
 	    }
 	    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, eva
 }
 
 /*
+ * 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;
--- 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);
 	    }
 	}
     }
--- 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,