From 37b44d17727a03e6a2638da4d16ea85e80069d13 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:27:42 +0000 Subject: refactor(option.c): add do_set_num --- src/nvim/option.c | 121 +++++++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 01a5c7677f..10773fffde 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -726,6 +726,67 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } +static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, const set_op_T op, + const char *varp, char *errbuf, size_t errbuflen, char **errmsg) +{ + varnumber_T value; + char *arg = *argp; + + // Different ways to set a number option: + // & set to default value + // < set to global value + // accept special key codes for 'wildchar' + // c accept any non-digit for 'wildchar' + // [-]0-9 set number + // other error + arg++; + if (nextchar == '&') { + value = (long)(intptr_t)options[opt_idx].def_val; + } else if (nextchar == '<') { + // For 'undolevels' NO_LOCAL_UNDOLEVEL means to + // use the global value. + if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) { + value = NO_LOCAL_UNDOLEVEL; + } else { + value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); + } + } else if (((long *)varp == &p_wc + || (long *)varp == &p_wcm) + && (*arg == '<' + || *arg == '^' + || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1])) + && !ascii_isdigit(*arg)))) { + value = string_to_key(arg); + if (value == 0 && (long *)varp != &p_wcm) { + *errmsg = e_invarg; + return; + } + } else if (*arg == '-' || ascii_isdigit(*arg)) { + int i; + // Allow negative, octal and hex numbers. + vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); + if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { + *errmsg = e_number_required_after_equal; + return; + } + } else { + *errmsg = e_number_required_after_equal; + return; + } + + if (op == OP_ADDING) { + value = *(long *)varp + value; + } + if (op == OP_PREPENDING) { + value = *(long *)varp * value; + } + if (op == OP_REMOVING) { + value = *(long *)varp - value; + } + *errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value, + errbuf, errbuflen, opt_flags); +} + /// Part of do_set() for string options. /// @return FAIL on failure, do not process further options. static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, @@ -1352,61 +1413,12 @@ int do_set(char *arg, int opt_flags) goto skip; } - if (flags & P_NUM) { // numeric - // Different ways to set a number option: - // & set to default value - // < set to global value - // accept special key codes for 'wildchar' - // c accept any non-digit for 'wildchar' - // [-]0-9 set number - // other error - arg++; - if (nextchar == '&') { - value = (long)(intptr_t)options[opt_idx].def_val; - } else if (nextchar == '<') { - // For 'undolevels' NO_LOCAL_UNDOLEVEL means to - // use the global value. - if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) { - value = NO_LOCAL_UNDOLEVEL; - } else { - value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); - } - } else if (((long *)varp == &p_wc - || (long *)varp == &p_wcm) - && (*arg == '<' - || *arg == '^' - || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1])) - && !ascii_isdigit(*arg)))) { - value = string_to_key(arg); - if (value == 0 && (long *)varp != &p_wcm) { - errmsg = e_invarg; - goto skip; - } - } else if (*arg == '-' || ascii_isdigit(*arg)) { - int i; - // Allow negative, octal and hex numbers. - vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); - if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { - errmsg = e_number_required_after_equal; - goto skip; - } - } else { - errmsg = e_number_required_after_equal; + if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, &arg, nextchar, op, varp, errbuf, sizeof(errbuf), + &errmsg); + if (errmsg != NULL) { goto skip; } - - if (op == OP_ADDING) { - value = *(long *)varp + value; - } - if (op == OP_PREPENDING) { - value = *(long *)varp * value; - } - if (op == OP_REMOVING) { - value = *(long *)varp - value; - } - errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value, - errbuf, sizeof(errbuf), - opt_flags); } else if (opt_idx >= 0) { // String. if (do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, sizeof(errbuf), @@ -2245,8 +2257,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, errmsg = e_positive; } } else if (pp == &p_ch) { - int minval = 0; - if (value < minval) { + if (value < 0) { errmsg = e_positive; } else { p_ch_was_zero = value == 0; -- cgit From ca1ad8977c9e1c79666978aef905c2a2a7f5c16e Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:33:23 +0000 Subject: refactor(option.c): add do_set_bool --- src/nvim/option.c | 81 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 10773fffde..c02c30c413 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -726,6 +726,49 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } +static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, int afterchar, + const char *varp, char **errmsg) +{ + if (nextchar == '=' || nextchar == ':') { + *errmsg = e_invarg; + return; + } + + varnumber_T value; + + // ":set opt!": invert + // ":set opt&": reset to default value + // ":set opt<": reset to global value + if (nextchar == '!') { + value = *(int *)(varp) ^ 1; + } else if (nextchar == '&') { + value = (int)(intptr_t)options[opt_idx].def_val; + } else if (nextchar == '<') { + // For 'autoread' -1 means to use global value. + if ((int *)varp == &curbuf->b_p_ar + && opt_flags == OPT_LOCAL) { + value = -1; + } else { + value = *(int *)get_varp_scope(&(options[opt_idx]), + OPT_GLOBAL); + } + } else { + // ":set invopt": invert + // ":set opt" or ":set noopt": set or reset + if (nextchar != NUL && !ascii_iswhite(afterchar)) { + *errmsg = e_trailing; + return; + } + if (prefix == 2) { // inv + value = *(int *)(varp) ^ 1; + } else { + value = prefix; + } + } + + *errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags); +} + static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, const set_op_T op, const char *varp, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1367,45 +1410,11 @@ int do_set(char *arg, int opt_flags) } } else { int value_checked = false; - varnumber_T value; - if (flags & P_BOOL) { // boolean - if (nextchar == '=' || nextchar == ':') { - errmsg = e_invarg; + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, &errmsg); + if (errmsg != NULL) { goto skip; } - - // ":set opt!": invert - // ":set opt&": reset to default value - // ":set opt<": reset to global value - if (nextchar == '!') { - value = *(int *)(varp) ^ 1; - } else if (nextchar == '&') { - value = (int)(intptr_t)options[opt_idx].def_val; - } else if (nextchar == '<') { - // For 'autoread' -1 means to use global value. - if ((int *)varp == &curbuf->b_p_ar - && opt_flags == OPT_LOCAL) { - value = -1; - } else { - value = *(int *)get_varp_scope(&(options[opt_idx]), - OPT_GLOBAL); - } - } else { - // ":set invopt": invert - // ":set opt" or ":set noopt": set or reset - if (nextchar != NUL && !ascii_iswhite(afterchar)) { - errmsg = e_trailing; - goto skip; - } - if (prefix == 2) { // inv - value = *(int *)(varp) ^ 1; - } else { - value = prefix; - } - } - - errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags); } else { // Numeric or string. if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL || prefix != 1) { -- cgit From 9679d058d42c22179fe3cf56e97983b2e67fb3f3 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:36:46 +0000 Subject: refactor(option.c): simplify do_set_string --- src/nvim/option.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index c02c30c413..84bc72e834 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -831,10 +831,9 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co } /// Part of do_set() for string options. -/// @return FAIL on failure, do not process further options. -static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, - uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen, - int *value_checked, char **errmsg) +static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, + uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen, + int *value_checked, char **errmsg) { char *arg = *argp; set_op_T op = op_arg; @@ -1163,7 +1162,6 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, xfree(saved_newval); *argp = arg; - return *errmsg == NULL ? OK : FAIL; } /// Parse 'arg' for option settings. @@ -1429,13 +1427,10 @@ int do_set(char *arg, int opt_flags) goto skip; } } else if (opt_idx >= 0) { // String. - if (do_set_string(opt_idx, opt_flags, &arg, nextchar, - op, flags, varp, errbuf, sizeof(errbuf), - &value_checked, &errmsg) == FAIL) { - if (errmsg != NULL) { - goto skip; - } - break; + do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, + sizeof(errbuf), &value_checked, &errmsg); + if (errmsg != NULL) { + goto skip; } } else { // key code option(FIXME(tarruda): Show a warning or something -- cgit From 18c37c616ec521bb79271c0b51fa198d9f664540 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:38:07 +0000 Subject: refactor(option.c): factor out common skip check --- src/nvim/option.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 84bc72e834..d1ecfa0dd7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1410,9 +1410,6 @@ int do_set(char *arg, int opt_flags) int value_checked = false; if (flags & P_BOOL) { // boolean do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, &errmsg); - if (errmsg != NULL) { - goto skip; - } } else { // Numeric or string. if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL || prefix != 1) { @@ -1423,21 +1420,19 @@ int do_set(char *arg, int opt_flags) if (flags & P_NUM) { // numeric do_set_num(opt_idx, opt_flags, &arg, nextchar, op, varp, errbuf, sizeof(errbuf), &errmsg); - if (errmsg != NULL) { - goto skip; - } } else if (opt_idx >= 0) { // String. do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, sizeof(errbuf), &value_checked, &errmsg); - if (errmsg != NULL) { - goto skip; - } } else { // key code option(FIXME(tarruda): Show a warning or something // similar) } } + if (errmsg != NULL) { + goto skip; + } + if (opt_idx >= 0) { did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); } -- cgit From e368560c80f162a67dd1ef5369ebaf57fb937de6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:50:29 +0000 Subject: refactor(option.c): factor out loop code from do_set() --- src/nvim/option.c | 456 +++++++++++++++++++++++++++--------------------------- 1 file changed, 230 insertions(+), 226 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index d1ecfa0dd7..5326251d2d 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1164,6 +1164,234 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, *argp = arg; } +static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, + size_t errbuflen, char **errmsg) +{ + int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name + + if (strncmp(*argp, "no", 2) == 0) { + prefix = 0; + *argp += 2; + } else if (strncmp(*argp, "inv", 3) == 0) { + prefix = 2; + *argp += 3; + } + + char *arg = *argp; + + // find end of name + int key = 0; + int len; + int opt_idx; + if (*arg == '<') { + opt_idx = -1; + // look out for ;> + if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) { + len = 5; + } else { + len = 1; + while (arg[len] != NUL && arg[len] != '>') { + len++; + } + } + if (arg[len] != '>') { + *errmsg = e_invarg; + return; + } + if (arg[1] == 't' && arg[2] == '_') { // could be term code + opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); + } + len++; + if (opt_idx == -1) { + key = find_key_option(arg + 1, true); + } + } else { + len = 0; + // The two characters after "t_" may not be alphanumeric. + if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) { + len = 4; + } else { + while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') { + len++; + } + } + opt_idx = findoption_len((const char *)arg, (size_t)len); + if (opt_idx == -1) { + key = find_key_option(arg, false); + } + } + + // remember character after option name + int afterchar = (uint8_t)arg[len]; + + // skip white space, allow ":set ai ?" + while (ascii_iswhite(arg[len])) { + len++; + } + + set_op_T op = OP_NONE; + if (arg[len] != NUL && arg[len + 1] == '=') { + if (arg[len] == '+') { + op = OP_ADDING; // "+=" + len++; + } else if (arg[len] == '^') { + op = OP_PREPENDING; // "^=" + len++; + } else if (arg[len] == '-') { + op = OP_REMOVING; // "-=" + len++; + } + } + char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name + + if (opt_idx == -1 && key == 0) { // found a mismatch: skip + *errmsg = e_unknown_option; + return; + } + + uint32_t flags; // flags for current option + char *varp = NULL; // pointer to variable for current option + + if (opt_idx >= 0) { + if (options[opt_idx].var == NULL) { // hidden option: skip + // Only give an error message when requesting the value of + // a hidden option, ignore setting it. + if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL + && (!(options[opt_idx].flags & P_BOOL) + || nextchar == '?')) { + *errmsg = e_unsupportedoption; + } + return; + } + + flags = options[opt_idx].flags; + varp = get_varp_scope(&(options[opt_idx]), opt_flags); + } else { + flags = P_STRING; + } + + // Skip all options that are not window-local (used when showing + // an already loaded buffer in a window). + if ((opt_flags & OPT_WINONLY) + && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { + return; + } + + // Skip all options that are window-local (used for :vimgrep). + if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 + && options[opt_idx].var == VAR_WIN) { + return; + } + + // Disallow changing some options from modelines. + if (opt_flags & OPT_MODELINE) { + if (flags & (P_SECURE | P_NO_ML)) { + *errmsg = e_not_allowed_in_modeline; + return; + } + if ((flags & P_MLE) && !p_mle) { + *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; + return; + } + // In diff mode some options are overruled. This avoids that + // 'foldmethod' becomes "marker" instead of "diff" and that + // "wrap" gets set. + if (curwin->w_p_diff + && opt_idx >= 0 // shut up coverity warning + && (options[opt_idx].indir == PV_FDM + || options[opt_idx].indir == PV_WRAP)) { + return; + } + } + + // Disallow changing some options in the sandbox + if (sandbox != 0 && (flags & P_SECURE)) { + *errmsg = e_sandbox; + return; + } + + if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) { + *argp += len; + if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') { + if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default + *argp += 3; + } else { // "opt&vi": set to Vi default + *argp += 2; + } + } + if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL + && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) { + *errmsg = e_trailing; + return; + } + } + + // + // allow '=' and ':' as MS-DOS command.com allows only one + // '=' character per "set" command line. grrr. (jw) + // + if (nextchar == '?' + || (prefix == 1 + && vim_strchr("=:&<", (uint8_t)nextchar) == NULL + && !(flags & P_BOOL))) { + // print value + if (*did_show) { + msg_putchar('\n'); // cursor below last one + } else { + gotocmdline(true); // cursor at status line + *did_show = true; // remember that we did a line + } + if (opt_idx >= 0) { + showoneopt(&options[opt_idx], opt_flags); + if (p_verbose > 0) { + // Mention where the option was last set. + if (varp == (char *)options[opt_idx].var) { + option_last_set_msg(options[opt_idx].last_set); + } else if ((int)options[opt_idx].indir & PV_WIN) { + option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]); + } else if ((int)options[opt_idx].indir & PV_BUF) { + option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]); + } + } + } else { + *errmsg = e_key_code_not_set; + return; + } + if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) { + *errmsg = e_trailing; + } + } else { + int value_checked = false; + if (flags & P_BOOL) { // boolean + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + } else { // Numeric or string. + if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL + || prefix != 1) { + *errmsg = e_invarg; + return; + } + + if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // String. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) + } + } + + if (*errmsg != NULL) { + return; + } + + if (opt_idx >= 0) { + did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + } + } +} + /// Parse 'arg' for option settings. /// /// 'arg' may be IObuff, but only when no errors can be present and option @@ -1181,7 +1409,7 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, /// @return FAIL if an error is detected, OK otherwise int do_set(char *arg, int opt_flags) { - int did_show = false; // already showed one value + bool did_show = false; // already showed one value if (*arg == NUL) { showoptions(0, opt_flags); @@ -1213,232 +1441,8 @@ int do_set(char *arg, int opt_flags) did_show = true; } } else { - int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name - if (strncmp(arg, "no", 2) == 0) { - prefix = 0; - arg += 2; - } else if (strncmp(arg, "inv", 3) == 0) { - prefix = 2; - arg += 3; - } - - // find end of name - int key = 0; - int len; - int opt_idx; - if (*arg == '<') { - opt_idx = -1; - // look out for ;> - if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) { - len = 5; - } else { - len = 1; - while (arg[len] != NUL && arg[len] != '>') { - len++; - } - } - if (arg[len] != '>') { - errmsg = e_invarg; - goto skip; - } - if (arg[1] == 't' && arg[2] == '_') { // could be term code - opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); - } - len++; - if (opt_idx == -1) { - key = find_key_option(arg + 1, true); - } - } else { - len = 0; - // The two characters after "t_" may not be alphanumeric. - if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) { - len = 4; - } else { - while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') { - len++; - } - } - opt_idx = findoption_len((const char *)arg, (size_t)len); - if (opt_idx == -1) { - key = find_key_option(arg, false); - } - } - - // remember character after option name - int afterchar = (uint8_t)arg[len]; - - // skip white space, allow ":set ai ?" - while (ascii_iswhite(arg[len])) { - len++; - } - - set_op_T op = OP_NONE; - if (arg[len] != NUL && arg[len + 1] == '=') { - if (arg[len] == '+') { - op = OP_ADDING; // "+=" - len++; - } else if (arg[len] == '^') { - op = OP_PREPENDING; // "^=" - len++; - } else if (arg[len] == '-') { - op = OP_REMOVING; // "-=" - len++; - } - } - char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name - - if (opt_idx == -1 && key == 0) { // found a mismatch: skip - errmsg = e_unknown_option; - goto skip; - } - - uint32_t flags; // flags for current option - char *varp = NULL; // pointer to variable for current option - - if (opt_idx >= 0) { - if (options[opt_idx].var == NULL) { // hidden option: skip - // Only give an error message when requesting the value of - // a hidden option, ignore setting it. - if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL - && (!(options[opt_idx].flags & P_BOOL) - || nextchar == '?')) { - errmsg = e_unsupportedoption; - } - goto skip; - } - - flags = options[opt_idx].flags; - varp = get_varp_scope(&(options[opt_idx]), opt_flags); - } else { - flags = P_STRING; - } - - // Skip all options that are not window-local (used when showing - // an already loaded buffer in a window). - if ((opt_flags & OPT_WINONLY) - && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { - goto skip; - } - - // Skip all options that are window-local (used for :vimgrep). - if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 - && options[opt_idx].var == VAR_WIN) { - goto skip; - } - - // Disallow changing some options from modelines. - if (opt_flags & OPT_MODELINE) { - if (flags & (P_SECURE | P_NO_ML)) { - errmsg = e_not_allowed_in_modeline; - goto skip; - } - if ((flags & P_MLE) && !p_mle) { - errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; - goto skip; - } - // In diff mode some options are overruled. This avoids that - // 'foldmethod' becomes "marker" instead of "diff" and that - // "wrap" gets set. - if (curwin->w_p_diff - && opt_idx >= 0 // shut up coverity warning - && (options[opt_idx].indir == PV_FDM - || options[opt_idx].indir == PV_WRAP)) { - goto skip; - } - } - - // Disallow changing some options in the sandbox - if (sandbox != 0 && (flags & P_SECURE)) { - errmsg = e_sandbox; - goto skip; - } - - if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) { - arg += len; - if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i') { - if (arg[3] == 'm') { // "opt&vim": set to Vim default - arg += 3; - } else { // "opt&vi": set to Vi default - arg += 2; - } - } - if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL - && arg[1] != NUL && !ascii_iswhite(arg[1])) { - errmsg = e_trailing; - goto skip; - } - } - - // - // allow '=' and ':' as MS-DOS command.com allows only one - // '=' character per "set" command line. grrr. (jw) - // - if (nextchar == '?' - || (prefix == 1 - && vim_strchr("=:&<", (uint8_t)nextchar) == NULL - && !(flags & P_BOOL))) { - // print value - if (did_show) { - msg_putchar('\n'); // cursor below last one - } else { - gotocmdline(true); // cursor at status line - did_show = true; // remember that we did a line - } - if (opt_idx >= 0) { - showoneopt(&options[opt_idx], opt_flags); - if (p_verbose > 0) { - // Mention where the option was last set. - if (varp == (char *)options[opt_idx].var) { - option_last_set_msg(options[opt_idx].last_set); - } else if ((int)options[opt_idx].indir & PV_WIN) { - option_last_set_msg(curwin->w_p_script_ctx[ - (int)options[opt_idx].indir & PV_MASK]); - } else if ((int)options[opt_idx].indir & PV_BUF) { - option_last_set_msg(curbuf->b_p_script_ctx[ - (int)options[opt_idx].indir & PV_MASK]); - } - } - } else { - errmsg = e_key_code_not_set; - goto skip; - } - if (nextchar != '?' - && nextchar != NUL && !ascii_iswhite(afterchar)) { - errmsg = e_trailing; - } - } else { - int value_checked = false; - if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, &errmsg); - } else { // Numeric or string. - if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL - || prefix != 1) { - errmsg = e_invarg; - goto skip; - } - - if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, &arg, nextchar, op, varp, errbuf, sizeof(errbuf), - &errmsg); - } else if (opt_idx >= 0) { // String. - do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, - sizeof(errbuf), &value_checked, &errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } - } - - if (errmsg != NULL) { - goto skip; - } - - if (opt_idx >= 0) { - did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); - } - } + do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); -skip: // Advance to next argument. // - skip until a blank found, taking care of backslashes // - skip blanks -- cgit From 3ae3e47d541db6e2cbf7c42b1ccce9cf48b0e4c9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:53:42 +0000 Subject: refactor(option.c): reduce scope or errmsg --- src/nvim/option.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 5326251d2d..f19d1d1517 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1420,7 +1420,6 @@ int do_set(char *arg, int opt_flags) char errbuf[80]; while (*arg != NUL) { // loop to process all options - char *errmsg = NULL; char *startarg = arg; // remember for error message if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) @@ -1441,6 +1440,7 @@ int do_set(char *arg, int opt_flags) did_show = true; } } else { + char *errmsg = NULL; do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); // Advance to next argument. @@ -1458,26 +1458,26 @@ int do_set(char *arg, int opt_flags) break; } } - } - if (errmsg != NULL) { - xstrlcpy(IObuff, _(errmsg), IOSIZE); - int i = (int)strlen(IObuff) + 2; - if (i + (arg - startarg) < IOSIZE) { - // append the argument with the error - STRCAT(IObuff, ": "); - assert(arg >= startarg); - memmove(IObuff + i, startarg, (size_t)(arg - startarg)); - IObuff[i + (arg - startarg)] = NUL; - } - // make sure all characters are printable - trans_characters(IObuff, IOSIZE); + if (errmsg != NULL) { + xstrlcpy(IObuff, _(errmsg), IOSIZE); + int i = (int)strlen(IObuff) + 2; + if (i + (arg - startarg) < IOSIZE) { + // append the argument with the error + STRCAT(IObuff, ": "); + assert(arg >= startarg); + memmove(IObuff + i, startarg, (size_t)(arg - startarg)); + IObuff[i + (arg - startarg)] = NUL; + } + // make sure all characters are printable + trans_characters(IObuff, IOSIZE); - no_wait_return++; // wait_return() done later - emsg(IObuff); // show error highlighted - no_wait_return--; + no_wait_return++; // wait_return() done later + emsg(IObuff); // show error highlighted + no_wait_return--; - return FAIL; + return FAIL; + } } arg = skipwhite(arg); -- cgit From b93bec68bcd681e06df4f977f4fef3b4ecff2555 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:06:32 +0000 Subject: refactor(option.c): reduce scope or errbuf --- src/nvim/option.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index f19d1d1517..535e162e91 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1417,8 +1417,6 @@ int do_set(char *arg, int opt_flags) goto theend; } - char errbuf[80]; - while (*arg != NUL) { // loop to process all options char *startarg = arg; // remember for error message @@ -1441,6 +1439,8 @@ int do_set(char *arg, int opt_flags) } } else { char *errmsg = NULL; + char errbuf[80]; + do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); // Advance to next argument. -- cgit From bb1efa85aa245b9d21f85fc541530be9f8d6dda4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:12:33 +0000 Subject: refactor(option.c): reduce scope or startarg --- src/nvim/option.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 535e162e91..490ce07c44 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1418,8 +1418,6 @@ int do_set(char *arg, int opt_flags) } while (*arg != NUL) { // loop to process all options - char *startarg = arg; // remember for error message - if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) && !(opt_flags & OPT_MODELINE)) { // ":set all" show all options. @@ -1438,6 +1436,7 @@ int do_set(char *arg, int opt_flags) did_show = true; } } else { + char *startarg = arg; // remember for error message char *errmsg = NULL; char errbuf[80]; -- cgit From a13e97ece52a4b6dccda08ec88c035306fd6d24a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:19:11 +0000 Subject: refactor(option.c): int -> bool --- src/nvim/option.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 490ce07c44..8df3063fec 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1412,7 +1412,7 @@ int do_set(char *arg, int opt_flags) bool did_show = false; // already showed one value if (*arg == NUL) { - showoptions(0, opt_flags); + showoptions(false, opt_flags); did_show = true; goto theend; } @@ -1432,7 +1432,7 @@ int do_set(char *arg, int opt_flags) ui_refresh_options(); redraw_all_later(UPD_CLEAR); } else { - showoptions(1, opt_flags); + showoptions(true, opt_flags); did_show = true; } } else { @@ -3124,11 +3124,11 @@ static int find_key_option(const char *arg, bool has_lt) return find_key_option_len(arg, strlen(arg), has_lt); } -/// if 'all' == 0: show changed options -/// if 'all' == 1: show all normal options +/// if 'all' == false: show changed options +/// if 'all' == true: show all normal options /// /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL -static void showoptions(int all, int opt_flags) +static void showoptions(bool all, int opt_flags) { #define INC 20 #define GAP 3 -- cgit From ef85238fde4560ae931dc98ac052a2b5564327fd Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:22:31 +0000 Subject: refactor(option.c): remove goto --- src/nvim/option.c | 116 +++++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 8df3063fec..ecec421e90 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1414,75 +1414,73 @@ int do_set(char *arg, int opt_flags) if (*arg == NUL) { showoptions(false, opt_flags); did_show = true; - goto theend; - } - - while (*arg != NUL) { // loop to process all options - if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) - && !(opt_flags & OPT_MODELINE)) { - // ":set all" show all options. - // ":set all&" set all options to their default value. - arg += 3; - if (*arg == '&') { - arg++; - // Only for :set command set global value of local options. - set_options_default(OPT_FREE | opt_flags); - didset_options(); - didset_options2(); - ui_refresh_options(); - redraw_all_later(UPD_CLEAR); + } else { + while (*arg != NUL) { // loop to process all options + if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) + && !(opt_flags & OPT_MODELINE)) { + // ":set all" show all options. + // ":set all&" set all options to their default value. + arg += 3; + if (*arg == '&') { + arg++; + // Only for :set command set global value of local options. + set_options_default(OPT_FREE | opt_flags); + didset_options(); + didset_options2(); + ui_refresh_options(); + redraw_all_later(UPD_CLEAR); + } else { + showoptions(true, opt_flags); + did_show = true; + } } else { - showoptions(true, opt_flags); - did_show = true; - } - } else { - char *startarg = arg; // remember for error message - char *errmsg = NULL; - char errbuf[80]; - - do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); - - // Advance to next argument. - // - skip until a blank found, taking care of backslashes - // - skip blanks - // - skip one "=val" argument (for hidden options ":set gfn =xx") - for (int i = 0; i < 2; i++) { - while (*arg != NUL && !ascii_iswhite(*arg)) { - if (*arg++ == '\\' && *arg != NUL) { - arg++; + char *startarg = arg; // remember for error message + char *errmsg = NULL; + char errbuf[80]; + + do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); + + // Advance to next argument. + // - skip until a blank found, taking care of backslashes + // - skip blanks + // - skip one "=val" argument (for hidden options ":set gfn =xx") + for (int i = 0; i < 2; i++) { + while (*arg != NUL && !ascii_iswhite(*arg)) { + if (*arg++ == '\\' && *arg != NUL) { + arg++; + } + } + arg = skipwhite(arg); + if (*arg != '=') { + break; } } - arg = skipwhite(arg); - if (*arg != '=') { - break; - } - } - if (errmsg != NULL) { - xstrlcpy(IObuff, _(errmsg), IOSIZE); - int i = (int)strlen(IObuff) + 2; - if (i + (arg - startarg) < IOSIZE) { - // append the argument with the error - STRCAT(IObuff, ": "); - assert(arg >= startarg); - memmove(IObuff + i, startarg, (size_t)(arg - startarg)); - IObuff[i + (arg - startarg)] = NUL; - } - // make sure all characters are printable - trans_characters(IObuff, IOSIZE); + if (errmsg != NULL) { + xstrlcpy(IObuff, _(errmsg), IOSIZE); + int i = (int)strlen(IObuff) + 2; + if (i + (arg - startarg) < IOSIZE) { + // append the argument with the error + STRCAT(IObuff, ": "); + assert(arg >= startarg); + memmove(IObuff + i, startarg, (size_t)(arg - startarg)); + IObuff[i + (arg - startarg)] = NUL; + } + // make sure all characters are printable + trans_characters(IObuff, IOSIZE); - no_wait_return++; // wait_return() done later - emsg(IObuff); // show error highlighted - no_wait_return--; + no_wait_return++; // wait_return() done later + emsg(IObuff); // show error highlighted + no_wait_return--; - return FAIL; + return FAIL; + } } - } - arg = skipwhite(arg); + arg = skipwhite(arg); + } } -theend: if (silent_mode && did_show) { // After displaying option values in silent mode. silent_mode = false; -- cgit From 334f5382677b3bcf91e74bb8502d38c7d2bd4281 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:41:55 +0000 Subject: refactor(option.c): change nextchar to uint8_t --- src/nvim/option.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index ecec421e90..ac889f2451 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1242,7 +1242,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb len++; } } - char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name + uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name if (opt_idx == -1 && key == 0) { // found a mismatch: skip *errmsg = e_unknown_option; @@ -1256,7 +1256,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb if (options[opt_idx].var == NULL) { // hidden option: skip // Only give an error message when requesting the value of // a hidden option, ignore setting it. - if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL + if (vim_strchr("=:!&<", nextchar) == NULL && (!(options[opt_idx].flags & P_BOOL) || nextchar == '?')) { *errmsg = e_unsupportedoption; @@ -1310,7 +1310,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } - if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) { + if (vim_strchr("?=:!&<", nextchar) != NULL) { *argp += len; if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') { if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default @@ -1319,7 +1319,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb *argp += 2; } } - if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL + if (vim_strchr("?!&<", nextchar) != NULL && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) { *errmsg = e_trailing; return; @@ -1332,7 +1332,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb // if (nextchar == '?' || (prefix == 1 - && vim_strchr("=:&<", (uint8_t)nextchar) == NULL + && vim_strchr("=:&<", nextchar) == NULL && !(flags & P_BOOL))) { // print value if (*did_show) { @@ -1365,8 +1365,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb if (flags & P_BOOL) { // boolean do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); } else { // Numeric or string. - if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL - || prefix != 1) { + if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { *errmsg = e_invarg; return; } -- cgit From 25310af06085c243c2b72a6a0f21cc45ce86a283 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:03:15 +0000 Subject: refactor(option.c): use skiptowhite_esc --- src/nvim/option.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index ac889f2451..a4e48f9c02 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1444,11 +1444,7 @@ int do_set(char *arg, int opt_flags) // - skip blanks // - skip one "=val" argument (for hidden options ":set gfn =xx") for (int i = 0; i < 2; i++) { - while (*arg != NUL && !ascii_iswhite(*arg)) { - if (*arg++ == '\\' && *arg != NUL) { - arg++; - } - } + arg = skiptowhite_esc(arg); arg = skipwhite(arg); if (*arg != '=') { break; -- cgit From 0f3fa5a30a6433ab32cfb3aaed946f858f7113a1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:12:21 +0000 Subject: refactor(option.c): factor out set op parsing --- src/nvim/option.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index a4e48f9c02..c511a8e622 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1164,6 +1164,21 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, *argp = arg; } +static set_op_T get_op(const char *arg) +{ + set_op_T op = OP_NONE; + if (*arg != NUL && *(arg + 1) == '=') { + if (*arg == '+') { + op = OP_ADDING; // "+=" + } else if (*arg == '^') { + op = OP_PREPENDING; // "^=" + } else if (*arg == '-') { + op = OP_REMOVING; // "-=" + } + } + return op; +} + static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1229,19 +1244,11 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb len++; } - set_op_T op = OP_NONE; - if (arg[len] != NUL && arg[len + 1] == '=') { - if (arg[len] == '+') { - op = OP_ADDING; // "+=" - len++; - } else if (arg[len] == '^') { - op = OP_PREPENDING; // "^=" - len++; - } else if (arg[len] == '-') { - op = OP_REMOVING; // "-=" - len++; - } + set_op_T op = get_op(arg + len); + if (op != OP_NONE) { + len++; } + uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name if (opt_idx == -1 && key == 0) { // found a mismatch: skip -- cgit From 9a9129c60b76cdfae5752071ec4c998c2f873c7c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:28:21 +0000 Subject: refactor(option.c): factor out option prefix parsing --- src/nvim/option.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index c511a8e622..a54dd4d877 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1179,19 +1179,25 @@ static set_op_T get_op(const char *arg) return op; } -static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, - size_t errbuflen, char **errmsg) +static int get_option_prefix(char **argp) { - int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name - if (strncmp(*argp, "no", 2) == 0) { - prefix = 0; *argp += 2; + return 0; } else if (strncmp(*argp, "inv", 3) == 0) { - prefix = 2; *argp += 3; + return 2; } + return 1; +} + +static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, + size_t errbuflen, char **errmsg) +{ + // 1: nothing, 0: "no", 2: "inv" in front of name + int prefix = get_option_prefix(argp); + char *arg = *argp; // find end of name @@ -1221,11 +1227,11 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb key = find_key_option(arg + 1, true); } } else { - len = 0; // The two characters after "t_" may not be alphanumeric. if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) { len = 4; } else { + len = 0; while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') { len++; } -- cgit From 2c601787ab2fead995fdecce08d0bd21d23eb284 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:33:09 +0000 Subject: refactor(option.c): factor out option name parsing --- src/nvim/option.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index a54dd4d877..babbe7e1b3 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1192,18 +1192,18 @@ static int get_option_prefix(char **argp) return 1; } -static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, - size_t errbuflen, char **errmsg) +/// @param[in] arg Pointer to start option name +/// @param[out] opt_idxp Option index in options[] table. +/// @param[out] keyp +/// @param[out] len Length of option name +/// @return FAIL if an error is detected, OK otherwise +static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp) { - // 1: nothing, 0: "no", 2: "inv" in front of name - int prefix = get_option_prefix(argp); - - char *arg = *argp; - // find end of name int key = 0; int len; int opt_idx; + if (*arg == '<') { opt_idx = -1; // look out for ;> @@ -1216,8 +1216,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb } } if (arg[len] != '>') { - *errmsg = e_invarg; - return; + return FAIL; } if (arg[1] == 't' && arg[2] == '_') { // could be term code opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); @@ -1242,6 +1241,30 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb } } + *keyp = key; + *lenp = len; + *opt_idxp = opt_idx; + + return OK; +} + +static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, + size_t errbuflen, char **errmsg) +{ + // 1: nothing, 0: "no", 2: "inv" in front of name + int prefix = get_option_prefix(argp); + + char *arg = *argp; + + // find end of name + int key = 0; + int len; + int opt_idx; + if (parse_option_name(arg, &key, &len, &opt_idx) == FAIL) { + *errmsg = e_invarg; + return; + } + // remember character after option name int afterchar = (uint8_t)arg[len]; -- cgit From e49ae04caf52ac848d090940a36393e4255726c8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 09:43:11 +0000 Subject: refactor(option.c): factor out opt_idx validation --- src/nvim/option.c | 83 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index babbe7e1b3..4c83eb2a1a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1248,6 +1248,51 @@ static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp) return OK; } +static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, char **errmsg) +{ + // Skip all options that are not window-local (used when showing + // an already loaded buffer in a window). + if ((opt_flags & OPT_WINONLY) + && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { + return FAIL; + } + + // Skip all options that are window-local (used for :vimgrep). + if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 + && options[opt_idx].var == VAR_WIN) { + return FAIL; + } + + // Disallow changing some options from modelines. + if (opt_flags & OPT_MODELINE) { + if (flags & (P_SECURE | P_NO_ML)) { + *errmsg = e_not_allowed_in_modeline; + return FAIL; + } + if ((flags & P_MLE) && !p_mle) { + *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; + return FAIL; + } + // In diff mode some options are overruled. This avoids that + // 'foldmethod' becomes "marker" instead of "diff" and that + // "wrap" gets set. + if (win->w_p_diff + && opt_idx >= 0 // shut up coverity warning + && (options[opt_idx].indir == PV_FDM + || options[opt_idx].indir == PV_WRAP)) { + return FAIL; + } + } + + // Disallow changing some options in the sandbox + if (sandbox != 0 && (flags & P_SECURE)) { + *errmsg = e_sandbox; + return FAIL; + } + + return OK; +} + static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1306,43 +1351,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb flags = P_STRING; } - // Skip all options that are not window-local (used when showing - // an already loaded buffer in a window). - if ((opt_flags & OPT_WINONLY) - && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { - return; - } - - // Skip all options that are window-local (used for :vimgrep). - if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 - && options[opt_idx].var == VAR_WIN) { - return; - } - - // Disallow changing some options from modelines. - if (opt_flags & OPT_MODELINE) { - if (flags & (P_SECURE | P_NO_ML)) { - *errmsg = e_not_allowed_in_modeline; - return; - } - if ((flags & P_MLE) && !p_mle) { - *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; - return; - } - // In diff mode some options are overruled. This avoids that - // 'foldmethod' becomes "marker" instead of "diff" and that - // "wrap" gets set. - if (curwin->w_p_diff - && opt_idx >= 0 // shut up coverity warning - && (options[opt_idx].indir == PV_FDM - || options[opt_idx].indir == PV_WRAP)) { - return; - } - } - - // Disallow changing some options in the sandbox - if (sandbox != 0 && (flags & P_SECURE)) { - *errmsg = e_sandbox; + if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, errmsg) == FAIL) { return; } -- cgit From c6907ea895694ea675ba8c912c3d8e9f67f5c7d4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 09:47:50 +0000 Subject: refactor(option.c): de-nest code in do_set_option --- src/nvim/option.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 4c83eb2a1a..1d5ceb70e6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1405,35 +1405,36 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) { *errmsg = e_trailing; } - } else { - int value_checked = false; - if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); - } else { // Numeric or string. - if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { - *errmsg = e_invarg; - return; - } - - if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); - } else if (opt_idx >= 0) { // String. - do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, - errbuflen, &value_checked, errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } - } + return; + } - if (*errmsg != NULL) { + int value_checked = false; + if (flags & P_BOOL) { // boolean + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + } else { // Numeric or string. + if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { + *errmsg = e_invarg; return; } - if (opt_idx >= 0) { - did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // String. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) } } + + if (*errmsg != NULL) { + return; + } + + if (opt_idx >= 0) { + did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + } } /// Parse 'arg' for option settings. -- cgit From 0170219e92ce211d935b78895825000f074c4cff Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 09:59:37 +0000 Subject: refactor(option.c): move bool prefix check --- src/nvim/option.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 1d5ceb70e6..50ccf9d302 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1248,8 +1248,15 @@ static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp) return OK; } -static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, char **errmsg) +static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, int prefix, + char **errmsg) { + // Only bools can have a prefix of 'inv' or 'no' + if (!(flags & P_BOOL) && prefix != 1) { + *errmsg = e_invarg; + return FAIL; + } + // Skip all options that are not window-local (used when showing // an already loaded buffer in a window). if ((opt_flags & OPT_WINONLY) @@ -1351,7 +1358,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb flags = P_STRING; } - if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, errmsg) == FAIL) { + if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, prefix, errmsg) == FAIL) { return; } @@ -1408,24 +1415,22 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } + if (!(flags & P_BOOL) && vim_strchr("=:&<", nextchar) == NULL) { + *errmsg = e_invarg; + return; + } + int value_checked = false; - if (flags & P_BOOL) { // boolean + if (flags & P_BOOL) { // boolean do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); - } else { // Numeric or string. - if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { - *errmsg = e_invarg; - return; - } - - if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); - } else if (opt_idx >= 0) { // String. - do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, - errbuflen, &value_checked, errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } + } else if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // string. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) } if (*errmsg != NULL) { -- cgit From 8f2d3537b49846f6e0d27ae5957b57a7ea57e232 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 10:37:05 +0000 Subject: refactor(option.c): add do_set_option_value --- src/nvim/option.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 50ccf9d302..641f07d70b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1300,6 +1300,32 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla return OK; } +static void do_set_option_value(int opt_idx, int opt_flags, char **argp, int prefix, int nextchar, + int afterchar, set_op_T op, uint32_t flags, char *varp, + char *errbuf, size_t errbuflen, char **errmsg) +{ + int value_checked = false; + if (flags & P_BOOL) { // boolean + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + } else if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // string. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) + } + + if (*errmsg != NULL) { + return; + } + + if (opt_idx >= 0) { + did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + } +} + static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1420,26 +1446,8 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } - int value_checked = false; - if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); - } else if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); - } else if (opt_idx >= 0) { // string. - do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, - errbuflen, &value_checked, errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } - - if (*errmsg != NULL) { - return; - } - - if (opt_idx >= 0) { - did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); - } + do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, afterchar, op, flags, varp, + errbuf, errbuflen, errmsg); } /// Parse 'arg' for option settings. -- cgit From 068151f5c69c9ba5e7d80101ccc62b4aea138a04 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 11:02:00 +0000 Subject: refactor(option.c): factor out some nextchar checks --- src/nvim/option.c | 53 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 641f07d70b..64128333a9 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -726,14 +726,9 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } -static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, int afterchar, - const char *varp, char **errmsg) +static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, const char *varp, + char **errmsg) { - if (nextchar == '=' || nextchar == ':') { - *errmsg = e_invarg; - return; - } - varnumber_T value; // ":set opt!": invert @@ -745,24 +740,16 @@ static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, in value = (int)(intptr_t)options[opt_idx].def_val; } else if (nextchar == '<') { // For 'autoread' -1 means to use global value. - if ((int *)varp == &curbuf->b_p_ar - && opt_flags == OPT_LOCAL) { + if ((int *)varp == &curbuf->b_p_ar && opt_flags == OPT_LOCAL) { value = -1; } else { - value = *(int *)get_varp_scope(&(options[opt_idx]), - OPT_GLOBAL); + value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); } } else { - // ":set invopt": invert - // ":set opt" or ":set noopt": set or reset - if (nextchar != NUL && !ascii_iswhite(afterchar)) { - *errmsg = e_trailing; - return; - } - if (prefix == 2) { // inv - value = *(int *)(varp) ^ 1; + if (prefix == 2) { + value = *(int *)varp ^ 1; // ":set invopt": invert } else { - value = prefix; + value = prefix; // ":set opt" or ":set noopt": set or reset } } @@ -1301,12 +1288,12 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla } static void do_set_option_value(int opt_idx, int opt_flags, char **argp, int prefix, int nextchar, - int afterchar, set_op_T op, uint32_t flags, char *varp, - char *errbuf, size_t errbuflen, char **errmsg) + set_op_T op, uint32_t flags, char *varp, char *errbuf, + size_t errbuflen, char **errmsg) { int value_checked = false; if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + do_set_bool(opt_idx, opt_flags, prefix, nextchar, varp, errmsg); } else if (flags & P_NUM) { // numeric do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); } else if (opt_idx >= 0) { // string. @@ -1441,12 +1428,24 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } - if (!(flags & P_BOOL) && vim_strchr("=:&<", nextchar) == NULL) { - *errmsg = e_invarg; - return; + if (flags & P_BOOL) { + if (vim_strchr("=:", nextchar) != NULL) { + *errmsg = e_invarg; + return; + } + + if (vim_strchr("!&<", nextchar) == NULL && nextchar != NUL && !ascii_iswhite(afterchar)) { + *errmsg = e_trailing; + return; + } + } else { + if (vim_strchr("=:&<", nextchar) == NULL) { + *errmsg = e_invarg; + return; + } } - do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, afterchar, op, flags, varp, + do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, op, flags, varp, errbuf, errbuflen, errmsg); } -- cgit From 77a0ce1d9b7c6c223fedec043cdd7379d0047bf8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 11:17:36 +0000 Subject: refactor(option.c): factor out string option special case handling --- src/nvim/option.c | 138 +++++++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 64128333a9..b8e234981a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -817,6 +817,78 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co errbuf, errbuflen, opt_flags); } +// Handle some special cases with string option values +static void munge_string_opt_val(char **varp, char **oldval, char **const origval, + char_u **const origval_l, char_u **const origval_g, + char **const argp, char *const whichwrap, size_t whichwraplen, + char **const save_argp) +{ + // Set 'keywordprg' to ":help" if an empty + // value was passed to :set by the user. + if (varp == &p_kp && (**argp == NUL || **argp == ' ')) { + *save_argp = *argp; + *argp = ":help"; + } else if (varp == &p_bs && ascii_isdigit(**(char_u **)varp)) { + // Convert 'backspace' number to string, for + // adding, prepending and removing string. + const int i = getdigits_int(varp, true, 0); + switch (i) { + case 0: + *varp = empty_option; + break; + case 1: + *varp = xstrdup("indent,eol"); + break; + case 2: + *varp = xstrdup("indent,eol,start"); + break; + case 3: + *varp = xstrdup("indent,eol,nostop"); + break; + } + xfree(*oldval); + if (*origval == *oldval) { + *origval = *varp; + } + if (*origval_l == (char_u *)(*oldval)) { + *origval_l = *(char_u **)varp; + } + if (*origval_g == (char_u *)(*oldval)) { + *origval_g = *(char_u **)varp; + } + *oldval = *varp; + } else if (varp == &p_ww && ascii_isdigit(**argp)) { + // Convert 'whichwrap' number to string, for backwards compatibility + // with Vim 3.0. + *whichwrap = NUL; + int i = getdigits_int(argp, true, 0); + if (i & 1) { + xstrlcat(whichwrap, "b,", whichwraplen); + } + if (i & 2) { + xstrlcat(whichwrap, "s,", whichwraplen); + } + if (i & 4) { + xstrlcat(whichwrap, "h,l,", whichwraplen); + } + if (i & 8) { + xstrlcat(whichwrap, "<,>,", whichwraplen); + } + if (i & 16) { + xstrlcat(whichwrap, "[,],", whichwraplen); + } + if (*whichwrap != NUL) { // remove trailing , + whichwrap[strlen(whichwrap) - 1] = NUL; + } + *save_argp = *argp; + *argp = whichwrap; + } else if (**argp == '>' && (varp == &p_dir || varp == &p_bdir)) { + // Remove '>' before 'dir' and 'bdir', for backwards compatibility with + // version 3.0 + (*argp)++; + } +} + /// Part of do_set() for string options. static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen, @@ -884,70 +956,8 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, } else { arg++; // jump to after the '=' or ':' - // Set 'keywordprg' to ":help" if an empty - // value was passed to :set by the user. - if (varp == (char *)&p_kp && (*arg == NUL || *arg == ' ')) { - save_arg = arg; - arg = ":help"; - } else if (varp == (char *)&p_bs && ascii_isdigit(**(char_u **)varp)) { - // Convert 'backspace' number to string, for - // adding, prepending and removing string. - int i = getdigits_int((char **)varp, true, 0); - switch (i) { - case 0: - *(char **)varp = empty_option; - break; - case 1: - *(char_u **)varp = (char_u *)xstrdup("indent,eol"); - break; - case 2: - *(char_u **)varp = (char_u *)xstrdup("indent,eol,start"); - break; - case 3: - *(char_u **)varp = (char_u *)xstrdup("indent,eol,nostop"); - break; - } - xfree(oldval); - if (origval == oldval) { - origval = *(char **)varp; - } - if (origval_l == (char_u *)oldval) { - origval_l = *(char_u **)varp; - } - if (origval_g == (char_u *)oldval) { - origval_g = *(char_u **)varp; - } - oldval = *(char **)varp; - } else if (varp == (char *)&p_ww && ascii_isdigit(*arg)) { - // Convert 'whichwrap' number to string, for backwards compatibility - // with Vim 3.0. - *whichwrap = NUL; - int i = getdigits_int(&arg, true, 0); - if (i & 1) { - xstrlcat(whichwrap, "b,", sizeof(whichwrap)); - } - if (i & 2) { - xstrlcat(whichwrap, "s,", sizeof(whichwrap)); - } - if (i & 4) { - xstrlcat(whichwrap, "h,l,", sizeof(whichwrap)); - } - if (i & 8) { - xstrlcat(whichwrap, "<,>,", sizeof(whichwrap)); - } - if (i & 16) { - xstrlcat(whichwrap, "[,],", sizeof(whichwrap)); - } - if (*whichwrap != NUL) { // remove trailing , - whichwrap[strlen(whichwrap) - 1] = NUL; - } - save_arg = arg; - arg = whichwrap; - } else if (*arg == '>' && (varp == (char *)&p_dir || varp == (char *)&p_bdir)) { - // Remove '>' before 'dir' and 'bdir', for backwards compatibility with - // version 3.0 - arg++; - } + munge_string_opt_val((char **)varp, &oldval, &origval, &origval_l, &origval_g, &arg, + whichwrap, sizeof(whichwrap), &save_arg); // Copy the new string into allocated memory. // Can't use set_string_option_direct(), because we need to remove the -- cgit