Mercurial > vim
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); } } }