From 3ccb5795168793e1b119a028da4035f77cef9f69 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 28 Nov 2021 19:53:42 +0000 Subject: patch 8.2.3689: ex_let_one() is too long Problem: ex_let_one() is too long. Solution: Split into multiple functions. --- src/evalvars.c | 412 ++++++++++++++++++++++++++++++++------------------------- src/version.c | 2 + 2 files changed, 235 insertions(+), 179 deletions(-) (limited to 'src') diff --git a/src/evalvars.c b/src/evalvars.c index 434fd96119..9124848c00 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1289,237 +1289,290 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first) } /* - * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value. - * Returns a pointer to the char just after the var name. - * Returns NULL if there is an error. + * Set an environment variable, part of ex_let_one(). */ static char_u * -ex_let_one( - char_u *arg, // points to variable name - typval_T *tv, // value to assign to variable - int copy, // copy value from "tv" - int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc. - char_u *endchars, // valid chars after variable name or NULL - char_u *op, // "+", "-", "." or NULL - int var_idx) // variable index for "let [a, b] = list" +ex_let_env( + char_u *arg, + typval_T *tv, + int flags, + char_u *endchars, + char_u *op) { - int c1; - char_u *name; - char_u *p; char_u *arg_end = NULL; + char_u *name; int len; - int opt_flags; - char_u *tofree = NULL; - if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0 - && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0 - && vim_strchr((char_u *)"$@&", *arg) != NULL) + if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) + && (flags & ASSIGN_FOR_LOOP) == 0) { - vim9_declare_error(arg); + emsg(_("E996: Cannot lock an environment variable")); return NULL; } - // ":let $VAR = expr": Set environment variable. - if (*arg == '$') + // Find the end of the name. + ++arg; + name = arg; + len = get_env_len(&arg); + if (len == 0) + semsg(_(e_invarg2), name - 1); + else { - if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) - && (flags & ASSIGN_FOR_LOOP) == 0) + if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) + semsg(_(e_letwrong), op); + else if (endchars != NULL + && vim_strchr(endchars, *skipwhite(arg)) == NULL) + emsg(_(e_unexpected_characters_in_let)); + else if (!check_secure()) { - emsg(_("E996: Cannot lock an environment variable")); - return NULL; - } + char_u *tofree = NULL; + int c1 = name[len]; + char_u *p; - // Find the end of the name. - ++arg; - name = arg; - len = get_env_len(&arg); - if (len == 0) - semsg(_(e_invarg2), name - 1); - else - { - if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) - semsg(_(e_letwrong), op); - else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg)) == NULL) - emsg(_(e_unexpected_characters_in_let)); - else if (!check_secure()) + name[len] = NUL; + p = tv_get_string_chk(tv); + if (p != NULL && op != NULL && *op == '.') { - c1 = name[len]; - name[len] = NUL; - p = tv_get_string_chk(tv); - if (p != NULL && op != NULL && *op == '.') - { - int mustfree = FALSE; - char_u *s = vim_getenv(name, &mustfree); + int mustfree = FALSE; + char_u *s = vim_getenv(name, &mustfree); - if (s != NULL) - { - p = tofree = concat_str(s, p); - if (mustfree) - vim_free(s); - } - } - if (p != NULL) + if (s != NULL) { - vim_setenv_ext(name, p); - arg_end = arg; + p = tofree = concat_str(s, p); + if (mustfree) + vim_free(s); } - name[len] = c1; - vim_free(tofree); } + if (p != NULL) + { + vim_setenv_ext(name, p); + arg_end = arg; + } + name[len] = c1; + vim_free(tofree); } } + return arg_end; +} - // ":let &option = expr": Set option value. - // ":let &l:option = expr": Set local option value. - // ":let &g:option = expr": Set global option value. - // ":for &ts in range(8)": Set option value for for loop - else if (*arg == '&') +/* + * Set an option, part of ex_let_one(). + */ + static char_u * +ex_let_option( + char_u *arg, + typval_T *tv, + int flags, + char_u *endchars, + char_u *op) +{ + char_u *p; + int opt_flags; + char_u *arg_end = NULL; + + if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) + && (flags & ASSIGN_FOR_LOOP) == 0) { - if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) - && (flags & ASSIGN_FOR_LOOP) == 0) + emsg(_(e_const_option)); + return NULL; + } + + // Find the end of the name. + p = find_option_end(&arg, &opt_flags); + if (p == NULL || (endchars != NULL + && vim_strchr(endchars, *skipwhite(p)) == NULL)) + emsg(_(e_unexpected_characters_in_let)); + else + { + int c1; + long n = 0; + getoption_T opt_type; + long numval; + char_u *stringval = NULL; + char_u *s = NULL; + int failed = FALSE; + + c1 = *p; + *p = NUL; + + opt_type = get_option_value(arg, &numval, &stringval, opt_flags); + if ((opt_type == gov_bool + || opt_type == gov_number + || opt_type == gov_hidden_bool + || opt_type == gov_hidden_number) + && (tv->v_type != VAR_STRING || !in_vim9script())) { - emsg(_(e_const_option)); - return NULL; + if (opt_type == gov_bool || opt_type == gov_hidden_bool) + // bool, possibly hidden + n = (long)tv_get_bool(tv); + else + // number, possibly hidden + n = (long)tv_get_number(tv); } - // Find the end of the name. - p = find_option_end(&arg, &opt_flags); - if (p == NULL || (endchars != NULL - && vim_strchr(endchars, *skipwhite(p)) == NULL)) - emsg(_(e_unexpected_characters_in_let)); - else - { - long n = 0; - getoption_T opt_type; - long numval; - char_u *stringval = NULL; - char_u *s = NULL; - int failed = FALSE; - - c1 = *p; - *p = NUL; - - opt_type = get_option_value(arg, &numval, &stringval, opt_flags); - if ((opt_type == gov_bool - || opt_type == gov_number - || opt_type == gov_hidden_bool - || opt_type == gov_hidden_number) - && (tv->v_type != VAR_STRING || !in_vim9script())) - { - if (opt_type == gov_bool || opt_type == gov_hidden_bool) - // bool, possibly hidden - n = (long)tv_get_bool(tv); - else - // number, possibly hidden - n = (long)tv_get_number(tv); - } - // Avoid setting a string option to the text "v:false" or similar. - // In Vim9 script also don't convert a number to string. - if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL - && (!in_vim9script() || tv->v_type != VAR_NUMBER)) - s = tv_get_string_chk(tv); + // Avoid setting a string option to the text "v:false" or similar. + // In Vim9 script also don't convert a number to string. + if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL + && (!in_vim9script() || tv->v_type != VAR_NUMBER)) + s = tv_get_string_chk(tv); - if (op != NULL && *op != '=') + if (op != NULL && *op != '=') + { + if (((opt_type == gov_bool || opt_type == gov_number) && *op == '.') + || (opt_type == gov_string && *op != '.')) { - if (((opt_type == gov_bool || opt_type == gov_number) - && *op == '.') - || (opt_type == gov_string && *op != '.')) - { - semsg(_(e_letwrong), op); - failed = TRUE; // don't set the value + semsg(_(e_letwrong), op); + failed = TRUE; // don't set the value - } - else + } + else + { + // number, in legacy script also bool + if (opt_type == gov_number + || (opt_type == gov_bool && !in_vim9script())) { - // number, in legacy script also bool - if (opt_type == gov_number - || (opt_type == gov_bool && !in_vim9script())) + switch (*op) { - switch (*op) - { - case '+': n = numval + n; break; - case '-': n = numval - n; break; - case '*': n = numval * n; break; - case '/': n = (long)num_divide(numval, n, + case '+': n = numval + n; break; + case '-': n = numval - n; break; + case '*': n = numval * n; break; + case '/': n = (long)num_divide(numval, n, &failed); break; - case '%': n = (long)num_modulus(numval, n, + case '%': n = (long)num_modulus(numval, n, &failed); break; - } - s = NULL; - } - else if (opt_type == gov_string - && stringval != NULL && s != NULL) - { - // string - s = concat_str(stringval, s); - vim_free(stringval); - stringval = s; } + s = NULL; + } + else if (opt_type == gov_string + && stringval != NULL && s != NULL) + { + // string + s = concat_str(stringval, s); + vim_free(stringval); + stringval = s; } } + } - if (!failed) + if (!failed) + { + if (opt_type != gov_string || s != NULL) { - if (opt_type != gov_string || s != NULL) - { - set_option_value(arg, n, s, opt_flags); - arg_end = p; - } - else - emsg(_(e_stringreq)); + set_option_value(arg, n, s, opt_flags); + arg_end = p; } - *p = c1; - vim_free(stringval); + else + emsg(_(e_stringreq)); } + *p = c1; + vim_free(stringval); } + return arg_end; +} - // ":let @r = expr": Set register contents. - else if (*arg == '@') +/* + * Set a register, part of ex_let_one(). + */ + static char_u * +ex_let_register( + char_u *arg, + typval_T *tv, + int flags, + char_u *endchars, + char_u *op) +{ + char_u *arg_end = NULL; + + if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) + && (flags & ASSIGN_FOR_LOOP) == 0) { - if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) - && (flags & ASSIGN_FOR_LOOP) == 0) - { - emsg(_("E996: Cannot lock a register")); - return NULL; - } - ++arg; - if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) - semsg(_(e_letwrong), op); - else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) - emsg(_(e_unexpected_characters_in_let)); - else + emsg(_("E996: Cannot lock a register")); + return NULL; + } + ++arg; + if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL) + semsg(_(e_letwrong), op); + else if (endchars != NULL + && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) + emsg(_(e_unexpected_characters_in_let)); + else + { + char_u *ptofree = NULL; + char_u *p; + + p = tv_get_string_chk(tv); + if (p != NULL && op != NULL && *op == '.') { - char_u *ptofree = NULL; - char_u *s; + char_u *s = get_reg_contents(*arg == '@' + ? '"' : *arg, GREG_EXPR_SRC); - p = tv_get_string_chk(tv); - if (p != NULL && op != NULL && *op == '.') + if (s != NULL) { - s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC); - if (s != NULL) - { - p = ptofree = concat_str(s, p); - vim_free(s); - } + p = ptofree = concat_str(s, p); + vim_free(s); } - if (p != NULL) - { - write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE); - arg_end = arg + 1; - } - vim_free(ptofree); } + if (p != NULL) + { + write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE); + arg_end = arg + 1; + } + vim_free(ptofree); + } + return arg_end; +} + +/* + * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value. + * Returns a pointer to the char just after the var name. + * Returns NULL if there is an error. + */ + static char_u * +ex_let_one( + char_u *arg, // points to variable name + typval_T *tv, // value to assign to variable + int copy, // copy value from "tv" + int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc. + char_u *endchars, // valid chars after variable name or NULL + char_u *op, // "+", "-", "." or NULL + int var_idx) // variable index for "let [a, b] = list" +{ + char_u *arg_end = NULL; + + if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0 + && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0 + && vim_strchr((char_u *)"$@&", *arg) != NULL) + { + vim9_declare_error(arg); + return NULL; } - // ":let var = expr": Set internal variable. - // ":let var: type = expr": Set internal variable with type. - // ":let {expr} = expr": Idem, name made with curly braces + if (*arg == '$') + { + // ":let $VAR = expr": Set environment variable. + return ex_let_env(arg, tv, flags, endchars, op); + } + else if (*arg == '&') + { + // ":let &option = expr": Set option value. + // ":let &l:option = expr": Set local option value. + // ":let &g:option = expr": Set global option value. + // ":for &ts in range(8)": Set option value for for loop + return ex_let_option(arg, tv, flags, endchars, op); + } + else if (*arg == '@') + { + // ":let @r = expr": Set register contents. + return ex_let_register(arg, tv, flags, endchars, op); + } else if (eval_isnamec1(*arg) || *arg == '{') { lval_T lv; + char_u *p; + // ":let var = expr": Set internal variable. + // ":let var: type = expr": Set internal variable with type. + // ":let {expr} = expr": Idem, name made with curly braces p = get_lval(arg, tv, &lv, FALSE, FALSE, (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) ? GLV_NO_DECL : 0, FNE_CHECK_START); @@ -1527,7 +1580,9 @@ ex_let_one( { if (endchars != NULL && vim_strchr(endchars, *skipwhite(lv.ll_name_end)) == NULL) + { emsg(_(e_unexpected_characters_in_let)); + } else { set_var_lval(&lv, p, tv, copy, flags, op, var_idx); @@ -1536,7 +1591,6 @@ ex_let_one( } clear_lval(&lv); } - else semsg(_(e_invarg2), arg); diff --git a/src/version.c b/src/version.c index f43b33c8f8..deefcf0c2f 100644 --- a/src/version.c +++ b/src/version.c @@ -757,6 +757,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 3689, /**/ 3688, /**/ -- cgit v1.2.3