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>
diff --git a/src/eval.c b/src/eval.c
index 4a03979..7848fea 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3947,6 +3947,40 @@
 }
 
 /*
+ * 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 @@
     {
 	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 @@
 
 	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 @@
  * 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 @@
 	    }
 	    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 @@
 }
 
 /*
+ * 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 @@
     evalarg_T	*evalarg,
     int		want_string)  // after "." operator
 {
-    int	    use_float = FALSE;
-
     /*
      * Get the first expression.
      */
@@ -4335,9 +4455,6 @@
 	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 @@
 	    *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 @@
 	    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;