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>
This commit is contained in:
committed by
Christian Brabandt
parent
f51ff96532
commit
734286e4c6
275
src/eval.c
275
src/eval.c
@ -3946,6 +3946,40 @@ eval_addlist(typval_T *tv1, typval_T *tv2)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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:
|
* 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;
|
char_u *p;
|
||||||
int getnext;
|
int getnext;
|
||||||
exprtype_T type;
|
exprtype_T exprtype;
|
||||||
int evaluate;
|
int evaluate;
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
int vim9script;
|
int vim9script;
|
||||||
|
|
||||||
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||||
if (p[0] == '<' && p[1] == '<')
|
if (p[0] == '<' && p[1] == '<')
|
||||||
type = EXPR_LSHIFT;
|
exprtype = EXPR_LSHIFT;
|
||||||
else if (p[0] == '>' && p[1] == '>')
|
else if (p[0] == '>' && p[1] == '>')
|
||||||
type = EXPR_RSHIFT;
|
exprtype = EXPR_RSHIFT;
|
||||||
else
|
else
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
@ -4026,27 +4060,8 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
|
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
if (var2.v_type != VAR_NUMBER || var2.vval.v_number < 0)
|
if (eval_shift_number(rettv, &var2, exprtype) == FAIL)
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
return 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);
|
clear_tv(&var2);
|
||||||
@ -4100,7 +4115,7 @@ eval_concat_str(typval_T *tv1, typval_T *tv2)
|
|||||||
* The numbers can be whole numbers or floats.
|
* The numbers can be whole numbers or floats.
|
||||||
*/
|
*/
|
||||||
static int
|
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;
|
int error = FALSE;
|
||||||
varnumber_T n1, n2;
|
varnumber_T n1, n2;
|
||||||
@ -4290,7 +4305,7 @@ eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (eval_addsub_num(rettv, &var2, op) == FAIL)
|
if (eval_addsub_number(rettv, &var2, op) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
clear_tv(&var2);
|
clear_tv(&var2);
|
||||||
@ -4299,6 +4314,113 @@ eval6(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
return OK;
|
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)
|
||||||
|
{
|
||||||
|
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:
|
* Handle sixth level expression:
|
||||||
* * number multiplication
|
* * number multiplication
|
||||||
@ -4317,8 +4439,6 @@ eval7(
|
|||||||
evalarg_T *evalarg,
|
evalarg_T *evalarg,
|
||||||
int want_string) // after "." operator
|
int want_string) // after "." operator
|
||||||
{
|
{
|
||||||
int use_float = FALSE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the first expression.
|
* Get the first expression.
|
||||||
*/
|
*/
|
||||||
@ -4335,9 +4455,6 @@ eval7(
|
|||||||
typval_T var2;
|
typval_T var2;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int op;
|
int op;
|
||||||
varnumber_T n1, n2;
|
|
||||||
float_T f1, f2;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
// "*=", "/=" and "%=" are assignments
|
// "*=", "/=" and "%=" are assignments
|
||||||
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||||
@ -4359,26 +4476,6 @@ eval7(
|
|||||||
*arg = p;
|
*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.
|
* Get the second variable.
|
||||||
*/
|
*/
|
||||||
@ -4393,81 +4490,9 @@ eval7(
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
{
|
// Compute the result.
|
||||||
if (var2.v_type == VAR_FLOAT)
|
if (eval_multdiv_number(rettv, &var2, op) == FAIL)
|
||||||
{
|
return FAIL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|||||||
@ -439,8 +439,8 @@ check_script_symlink(int sid)
|
|||||||
SCRIPT_ITEM(real_sid)->sn_import_autoload
|
SCRIPT_ITEM(real_sid)->sn_import_autoload
|
||||||
= si->sn_import_autoload;
|
= si->sn_import_autoload;
|
||||||
if (si->sn_autoload_prefix != NULL)
|
if (si->sn_autoload_prefix != NULL)
|
||||||
SCRIPT_ITEM(real_sid)->sn_autoload_prefix =
|
SCRIPT_ITEM(real_sid)->sn_autoload_prefix =
|
||||||
vim_strsave(si->sn_autoload_prefix);
|
vim_strsave(si->sn_autoload_prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
462,
|
||||||
/**/
|
/**/
|
||||||
461,
|
461,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user