Patch 9.0.0537
Problem: The do_set() function is much too long.
Solution: Move setting of a string option to a separate function.
Files: src/option.c
*** ../vim-9.0.0536/src/option.c 2022-09-12 13:35:06.514946763 +0100
--- src/option.c 2022-09-21 21:10:26.865408272 +0100
***************
*** 1205,1210 ****
--- 1205,1635 ----
}
}
+ typedef enum {
+ OP_NONE = 0,
+ OP_ADDING, // "opt+=arg"
+ OP_PREPENDING, // "opt^=arg"
+ OP_REMOVING, // "opt-=arg"
+ } set_op_T;
+
+ /*
+ * Part of do_set() for string options.
+ * Returns FAIL on failure, do not process further options.
+ */
+ static int
+ do_set_string(
+ int opt_idx,
+ int opt_flags,
+ char_u **arg,
+ int nextchar,
+ set_op_T op_arg,
+ int flags,
+ int cp_val,
+ char_u *varp_arg,
+ char *errbuf,
+ int *value_checked,
+ char **errmsg)
+ {
+ set_op_T op = op_arg;
+ char_u *varp = varp_arg;
+ char_u *save_arg = NULL;
+ char_u *s = NULL;
+ char_u *oldval = NULL; // previous value if *varp
+ char_u *newval;
+ char_u *origval = NULL;
+ char_u *origval_l = NULL;
+ char_u *origval_g = NULL;
+ #if defined(FEAT_EVAL)
+ char_u *saved_origval = NULL;
+ char_u *saved_origval_l = NULL;
+ char_u *saved_origval_g = NULL;
+ char_u *saved_newval = NULL;
+ #endif
+ unsigned newlen;
+ int comma;
+ char_u whichwrap[80];
+
+ // When using ":set opt=val" for a global option
+ // with a local value the local value will be
+ // reset, use the global value here.
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
+ && ((int)options[opt_idx].indir & PV_BOTH))
+ varp = options[opt_idx].var;
+
+ // The old value is kept until we are sure that the new value is valid.
+ oldval = *(char_u **)varp;
+
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
+ {
+ origval_l = *(char_u **)get_varp_scope(
+ &(options[opt_idx]), OPT_LOCAL);
+ origval_g = *(char_u **)get_varp_scope(
+ &(options[opt_idx]), OPT_GLOBAL);
+
+ // A global-local string option might have an empty option as value to
+ // indicate that the global value should be used.
+ if (((int)options[opt_idx].indir & PV_BOTH)
+ && origval_l == empty_option)
+ origval_l = origval_g;
+ }
+
+ // When setting the local value of a global option, the old value may be
+ // the global value.
+ if (((int)options[opt_idx].indir & PV_BOTH) && (opt_flags & OPT_LOCAL))
+ origval = *(char_u **)get_varp(&options[opt_idx]);
+ else
+ origval = oldval;
+
+ if (nextchar == '&') // set to default val
+ {
+ newval = options[opt_idx].def_val[((flags & P_VI_DEF) || cp_val)
+ ? VI_DEFAULT : VIM_DEFAULT];
+ if ((char_u **)varp == &p_bg)
+ {
+ // guess the value of 'background'
+ #ifdef FEAT_GUI
+ if (gui.in_use)
+ newval = gui_bg_default();
+ else
+ #endif
+ newval = term_bg_default();
+ }
+ else if ((char_u **)varp == &p_fencs && enc_utf8)
+ newval = fencs_utf8_default;
+
+ // expand environment variables and ~ since the default value was
+ // already expanded, only required when an environment variable was set
+ // later
+ if (newval == NULL)
+ newval = empty_option;
+ else
+ {
+ s = option_expand(opt_idx, newval);
+ if (s == NULL)
+ s = newval;
+ newval = vim_strsave(s);
+ }
+ }
+ else if (nextchar == '<') // set to global val
+ {
+ newval = vim_strsave(*(char_u **)get_varp_scope(
+ &(options[opt_idx]), OPT_GLOBAL));
+ }
+ else
+ {
+ ++*arg; // jump to after the '=' or ':'
+
+ /*
+ * Set 'keywordprg' to ":help" if an empty
+ * value was passed to :set by the user.
+ * Misuse errbuf[] for the resulting string.
+ */
+ if (varp == (char_u *)&p_kp && (**arg == NUL || **arg == ' '))
+ {
+ STRCPY(errbuf, ":help");
+ save_arg = *arg;
+ *arg = (char_u *)errbuf;
+ }
+ /*
+ * Convert 'backspace' number to string, for
+ * adding, prepending and removing string.
+ */
+ else if (varp == (char_u *)&p_bs && VIM_ISDIGIT(**(char_u **)varp))
+ {
+ int i = getdigits((char_u **)varp);
+
+ switch (i)
+ {
+ case 0:
+ *(char_u **)varp = empty_option;
+ break;
+ case 1:
+ *(char_u **)varp = vim_strsave((char_u *)"indent,eol");
+ break;
+ case 2:
+ *(char_u **)varp = vim_strsave(
+ (char_u *)"indent,eol,start");
+ break;
+ case 3:
+ *(char_u **)varp = vim_strsave(
+ (char_u *)"indent,eol,nostop");
+ break;
+ }
+ vim_free(oldval);
+ if (origval == oldval)
+ origval = *(char_u **)varp;
+ if (origval_l == oldval)
+ origval_l = *(char_u **)varp;
+ if (origval_g == oldval)
+ origval_g = *(char_u **)varp;
+ oldval = *(char_u **)varp;
+ }
+ /*
+ * Convert 'whichwrap' number to string, for backwards compatibility
+ * with Vim 3.0.
+ */
+ else if (varp == (char_u *)&p_ww && VIM_ISDIGIT(**arg))
+ {
+ *whichwrap = NUL;
+ int i = getdigits(arg);
+ if (i & 1)
+ STRCAT(whichwrap, "b,");
+ if (i & 2)
+ STRCAT(whichwrap, "s,");
+ if (i & 4)
+ STRCAT(whichwrap, "h,l,");
+ if (i & 8)
+ STRCAT(whichwrap, "<,>,");
+ if (i & 16)
+ STRCAT(whichwrap, "[,],");
+ if (*whichwrap != NUL) // remove trailing ,
+ whichwrap[STRLEN(whichwrap) - 1] = NUL;
+ save_arg = *arg;
+ *arg = (char_u *)whichwrap;
+ }
+ /*
+ * Remove '>' before 'dir' and 'bdir', for backwards compatibility with
+ * version 3.0
+ */
+ else if ( **arg == '>' && (varp == (char_u *)&p_dir
+ || varp == (char_u *)&p_bdir))
+ ++*arg;
+
+ /*
+ * Copy the new string into allocated memory.
+ * Can't use set_string_option_direct(), because we need to remove the
+ * backslashes.
+ */
+ // get a bit too much
+ newlen = (unsigned)STRLEN(*arg) + 1;
+ if (op != OP_NONE)
+ newlen += (unsigned)STRLEN(origval) + 1;
+ newval = alloc(newlen);
+ if (newval == NULL) // out of mem, don't change
+ return FAIL;
+ s = newval;
+
+ /*
+ * Copy the string, skip over escaped chars.
+ * For MS-DOS and WIN32 backslashes before normal file name characters
+ * are not removed, and keep backslash at start, for "\\machine\path",
+ * but do remove it for "\\\\machine\\path".
+ * The reverse is found in ExpandOldSetting().
+ */
+ while (**arg && !VIM_ISWHITE(**arg))
+ {
+ int i;
+
+ if (**arg == '\\' && (*arg)[1] != NUL
+ #ifdef BACKSLASH_IN_FILENAME
+ && !((flags & P_EXPAND)
+ && vim_isfilec((*arg)[1])
+ && !VIM_ISWHITE((*arg)[1])
+ && ((*arg)[1] != '\\'
+ || (s == newval && (*arg)[2] != '\\')))
+ #endif
+ )
+ ++*arg; // remove backslash
+ if (has_mbyte && (i = (*mb_ptr2len)(*arg)) > 1)
+ {
+ // copy multibyte char
+ mch_memmove(s, *arg, (size_t)i);
+ *arg += i;
+ s += i;
+ }
+ else
+ *s++ = *(*arg)++;
+ }
+ *s = NUL;
+
+ /*
+ * Expand environment variables and ~.
+ * Don't do it when adding without inserting a comma.
+ */
+ if (op == OP_NONE || (flags & P_COMMA))
+ {
+ s = option_expand(opt_idx, newval);
+ if (s != NULL)
+ {
+ vim_free(newval);
+ newlen = (unsigned)STRLEN(s) + 1;
+ if (op != OP_NONE)
+ newlen += (unsigned)STRLEN(origval) + 1;
+ newval = alloc(newlen);
+ if (newval == NULL)
+ return FAIL;
+ STRCPY(newval, s);
+ }
+ }
+
+ // locate newval[] in origval[] when removing it
+ // and when adding to avoid duplicates
+ int len = 0;
+ if (op == OP_REMOVING || (flags & P_NODUP))
+ {
+ len = (int)STRLEN(newval);
+ s = find_dup_item(origval, newval, flags);
+
+ // do not add if already there
+ if ((op == OP_ADDING || op == OP_PREPENDING) && s != NULL)
+ {
+ op = OP_NONE;
+ STRCPY(newval, origval);
+ }
+
+ // if no duplicate, move pointer to end of original value
+ if (s == NULL)
+ s = origval + (int)STRLEN(origval);
+ }
+
+ // concatenate the two strings; add a ',' if needed
+ if (op == OP_ADDING || op == OP_PREPENDING)
+ {
+ comma = ((flags & P_COMMA) && *origval != NUL && *newval != NUL);
+ if (op == OP_ADDING)
+ {
+ len = (int)STRLEN(origval);
+ // strip a trailing comma, would get 2
+ if (comma && len > 1
+ && (flags & P_ONECOMMA) == P_ONECOMMA
+ && origval[len - 1] == ','
+ && origval[len - 2] != '\\')
+ len--;
+ mch_memmove(newval + len + comma, newval, STRLEN(newval) + 1);
+ mch_memmove(newval, origval, (size_t)len);
+ }
+ else
+ {
+ len = (int)STRLEN(newval);
+ STRMOVE(newval + len + comma, origval);
+ }
+ if (comma)
+ newval[len] = ',';
+ }
+
+ // Remove newval[] from origval[]. (Note: "len" has been set above and
+ // is used here).
+ if (op == OP_REMOVING)
+ {
+ STRCPY(newval, origval);
+ if (*s)
+ {
+ // may need to remove a comma
+ if (flags & P_COMMA)
+ {
+ if (s == origval)
+ {
+ // include comma after string
+ if (s[len] == ',')
+ ++len;
+ }
+ else
+ {
+ // include comma before string
+ --s;
+ ++len;
+ }
+ }
+ STRMOVE(newval + (s - origval), s + len);
+ }
+ }
+
+ if (flags & P_FLAGLIST)
+ {
+ // Remove flags that appear twice.
+ for (s = newval; *s;)
+ {
+ // if options have P_FLAGLIST and P_ONECOMMA such as
+ // 'whichwrap'
+ if (flags & P_ONECOMMA)
+ {
+ if (*s != ',' && *(s + 1) == ','
+ && vim_strchr(s + 2, *s) != NULL)
+ {
+ // Remove the duplicated value and the next comma.
+ STRMOVE(s, s + 2);
+ continue;
+ }
+ }
+ else
+ {
+ if ((!(flags & P_COMMA) || *s != ',')
+ && vim_strchr(s + 1, *s) != NULL)
+ {
+ STRMOVE(s, s + 1);
+ continue;
+ }
+ }
+ ++s;
+ }
+ }
+
+ if (save_arg != NULL) // number for 'whichwrap'
+ *arg = save_arg;
+ }
+
+ /*
+ * Set the new value.
+ */
+ *(char_u **)(varp) = newval;
+
+ #if defined(FEAT_EVAL)
+ if (!starting
+ # ifdef FEAT_CRYPT
+ && options[opt_idx].indir != PV_KEY
+ # endif
+ && origval != NULL && newval != NULL)
+ {
+ // origval may be freed by did_set_string_option(), make a copy.
+ saved_origval = vim_strsave(origval);
+ // newval (and varp) may become invalid if the buffer is closed by
+ // autocommands.
+ saved_newval = vim_strsave(newval);
+ if (origval_l != NULL)
+ saved_origval_l = vim_strsave(origval_l);
+ if (origval_g != NULL)
+ saved_origval_g = vim_strsave(origval_g);
+ }
+ #endif
+
+ {
+ long_u *p = insecure_flag(opt_idx, opt_flags);
+ int secure_saved = secure;
+
+ // When an option is set in the sandbox, from a modeline or in secure
+ // mode, then deal with side effects in secure mode. Also when the
+ // value was set with the P_INSECURE flag and is not completely
+ // replaced.
+ if ((opt_flags & OPT_MODELINE)
+ #ifdef HAVE_SANDBOX
+ || sandbox != 0
+ #endif
+ || (op != OP_NONE && (*p & P_INSECURE)))
+ secure = 1;
+
+ // Handle side effects, and set the global value for ":set" on local
+ // options. Note: when setting 'syntax' or 'filetype' autocommands may
+ // be triggered that can cause havoc.
+ *errmsg = did_set_string_option(
+ opt_idx, (char_u **)varp, oldval, errbuf,
+ opt_flags, value_checked);
+
+ secure = secure_saved;
+ }
+
+ #if defined(FEAT_EVAL)
+ if (*errmsg == NULL)
+ trigger_optionsset_string(opt_idx, opt_flags, saved_origval,
+ saved_origval_l, saved_origval_g, saved_newval);
+ vim_free(saved_origval);
+ vim_free(saved_origval_l);
+ vim_free(saved_origval_g);
+ vim_free(saved_newval);
+ #endif
+
+ return *errmsg == NULL ? OK : FAIL;
+ }
+
/*
* Parse 'arg' for option settings.
*
***************
*** 1241,1249 ****
long_u flags; // flags for current option
char_u *varp = NULL; // pointer to variable for current option
int did_show = FALSE; // already showed one value
! int adding; // "opt+=arg"
! int prepending; // "opt^=arg"
! int removing; // "opt-=arg"
int cp_val = 0;
char_u key_name[2];
--- 1666,1672 ----
long_u flags; // flags for current option
char_u *varp = NULL; // pointer to variable for current option
int did_show = FALSE; // already showed one value
! set_op_T op = 0;
int cp_val = 0;
char_u key_name[2];
***************
*** 1371,1394 ****
while (VIM_ISWHITE(arg[len]))
++len;
! adding = FALSE;
! prepending = FALSE;
! removing = FALSE;
if (arg[len] != NUL && arg[len + 1] == '=')
{
if (arg[len] == '+')
{
! adding = TRUE; // "+="
++len;
}
else if (arg[len] == '^')
{
! prepending = TRUE; // "^="
++len;
}
else if (arg[len] == '-')
{
! removing = TRUE; // "-="
++len;
}
}
--- 1794,1815 ----
while (VIM_ISWHITE(arg[len]))
++len;
! 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;
}
}
***************
*** 1564,1570 ****
}
else
{
- int value_is_replaced = !prepending && !adding && !removing;
int value_checked = FALSE;
if (flags & P_BOOL) // boolean
--- 1985,1990 ----
***************
*** 1686,2125 ****
goto skip;
}
! if (adding)
value = *(long *)varp + value;
! if (prepending)
value = *(long *)varp * value;
! if (removing)
value = *(long *)varp - value;
errmsg = set_num_option(opt_idx, varp, value,
errbuf, sizeof(errbuf), opt_flags);
}
else if (opt_idx >= 0) // string
{
! char_u *save_arg = NULL;
! char_u *s = NULL;
! char_u *oldval = NULL; // previous value if *varp
! char_u *newval;
! char_u *origval = NULL;
! char_u *origval_l = NULL;
! char_u *origval_g = NULL;
! #if defined(FEAT_EVAL)
! char_u *saved_origval = NULL;
! char_u *saved_origval_l = NULL;
! char_u *saved_origval_g = NULL;
! char_u *saved_newval = NULL;
! #endif
! unsigned newlen;
! int comma;
!
! // When using ":set opt=val" for a global option
! // with a local value the local value will be
! // reset, use the global value here.
! if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
! && ((int)options[opt_idx].indir & PV_BOTH))
! varp = options[opt_idx].var;
!
! // The old value is kept until we are sure that the
! // new value is valid.
! oldval = *(char_u **)varp;
!
! if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0)
{
! origval_l = *(char_u **)get_varp_scope(
! &(options[opt_idx]), OPT_LOCAL);
! origval_g = *(char_u **)get_varp_scope(
! &(options[opt_idx]), OPT_GLOBAL);
!
! // A global-local string option might have an empty
! // option as value to indicate that the global
! // value should be used.
! if (((int)options[opt_idx].indir & PV_BOTH)
! && origval_l == empty_option)
! origval_l = origval_g;
! }
!
! // When setting the local value of a global
! // option, the old value may be the global value.
! if (((int)options[opt_idx].indir & PV_BOTH)
! && (opt_flags & OPT_LOCAL))
! origval = *(char_u **)get_varp(
! &options[opt_idx]);
! else
! origval = oldval;
!
! if (nextchar == '&') // set to default val
! {
! newval = options[opt_idx].def_val[
! ((flags & P_VI_DEF) || cp_val)
! ? VI_DEFAULT : VIM_DEFAULT];
! if ((char_u **)varp == &p_bg)
! {
! // guess the value of 'background'
! #ifdef FEAT_GUI
! if (gui.in_use)
! newval = gui_bg_default();
! else
! #endif
! newval = term_bg_default();
! }
! else if ((char_u **)varp == &p_fencs && enc_utf8)
! newval = fencs_utf8_default;
!
! // expand environment variables and ~ since the
! // default value was already expanded, only
! // required when an environment variable was set
! // later
! if (newval == NULL)
! newval = empty_option;
! else
! {
! s = option_expand(opt_idx, newval);
! if (s == NULL)
! s = newval;
! newval = vim_strsave(s);
! }
! }
! else if (nextchar == '<') // set to global val
! {
! newval = vim_strsave(*(char_u **)get_varp_scope(
! &(options[opt_idx]), OPT_GLOBAL));
! }
! else
! {
! ++arg; // jump to after the '=' or ':'
!
! /*
! * Set 'keywordprg' to ":help" if an empty
! * value was passed to :set by the user.
! * Misuse errbuf[] for the resulting string.
! */
! if (varp == (char_u *)&p_kp
! && (*arg == NUL || *arg == ' '))
! {
! STRCPY(errbuf, ":help");
! save_arg = arg;
! arg = (char_u *)errbuf;
! }
! /*
! * Convert 'backspace' number to string, for
! * adding, prepending and removing string.
! */
! else if (varp == (char_u *)&p_bs
! && VIM_ISDIGIT(**(char_u **)varp))
! {
! i = getdigits((char_u **)varp);
! switch (i)
! {
! case 0:
! *(char_u **)varp = empty_option;
! break;
! case 1:
! *(char_u **)varp = vim_strsave(
! (char_u *)"indent,eol");
! break;
! case 2:
! *(char_u **)varp = vim_strsave(
! (char_u *)"indent,eol,start");
! break;
! case 3:
! *(char_u **)varp = vim_strsave(
! (char_u *)"indent,eol,nostop");
! break;
! }
! vim_free(oldval);
! if (origval == oldval)
! origval = *(char_u **)varp;
! if (origval_l == oldval)
! origval_l = *(char_u **)varp;
! if (origval_g == oldval)
! origval_g = *(char_u **)varp;
! oldval = *(char_u **)varp;
! }
! /*
! * Convert 'whichwrap' number to string, for
! * backwards compatibility with Vim 3.0.
! * Misuse errbuf[] for the resulting string.
! */
! else if (varp == (char_u *)&p_ww
! && VIM_ISDIGIT(*arg))
! {
! *errbuf = NUL;
! i = getdigits(&arg);
! if (i & 1)
! STRCAT(errbuf, "b,");
! if (i & 2)
! STRCAT(errbuf, "s,");
! if (i & 4)
! STRCAT(errbuf, "h,l,");
! if (i & 8)
! STRCAT(errbuf, "<,>,");
! if (i & 16)
! STRCAT(errbuf, "[,],");
! if (*errbuf != NUL) // remove trailing ,
! errbuf[STRLEN(errbuf) - 1] = NUL;
! save_arg = arg;
! arg = (char_u *)errbuf;
! }
! /*
! * Remove '>' before 'dir' and 'bdir', for
! * backwards compatibility with version 3.0
! */
! else if ( *arg == '>'
! && (varp == (char_u *)&p_dir
! || varp == (char_u *)&p_bdir))
! {
! ++arg;
! }
!
! /*
! * Copy the new string into allocated memory.
! * Can't use set_string_option_direct(), because
! * we need to remove the backslashes.
! */
! // get a bit too much
! newlen = (unsigned)STRLEN(arg) + 1;
! if (adding || prepending || removing)
! newlen += (unsigned)STRLEN(origval) + 1;
! newval = alloc(newlen);
! if (newval == NULL) // out of mem, don't change
! break;
! s = newval;
!
! /*
! * Copy the string, skip over escaped chars.
! * For MS-DOS and WIN32 backslashes before normal
! * file name characters are not removed, and keep
! * backslash at start, for "\\machine\path", but
! * do remove it for "\\\\machine\\path".
! * The reverse is found in ExpandOldSetting().
! */
! while (*arg && !VIM_ISWHITE(*arg))
! {
! if (*arg == '\\' && arg[1] != NUL
! #ifdef BACKSLASH_IN_FILENAME
! && !((flags & P_EXPAND)
! && vim_isfilec(arg[1])
! && !VIM_ISWHITE(arg[1])
! && (arg[1] != '\\'
! || (s == newval
! && arg[2] != '\\')))
! #endif
! )
! ++arg; // remove backslash
! if (has_mbyte
! && (i = (*mb_ptr2len)(arg)) > 1)
! {
! // copy multibyte char
! mch_memmove(s, arg, (size_t)i);
! arg += i;
! s += i;
! }
! else
! *s++ = *arg++;
! }
! *s = NUL;
!
! /*
! * Expand environment variables and ~.
! * Don't do it when adding without inserting a
! * comma.
! */
! if (!(adding || prepending || removing)
! || (flags & P_COMMA))
! {
! s = option_expand(opt_idx, newval);
! if (s != NULL)
! {
! vim_free(newval);
! newlen = (unsigned)STRLEN(s) + 1;
! if (adding || prepending || removing)
! newlen += (unsigned)STRLEN(origval) + 1;
! newval = alloc(newlen);
! if (newval == NULL)
! break;
! STRCPY(newval, s);
! }
! }
!
! // locate newval[] in origval[] when removing it
! // and when adding to avoid duplicates
! i = 0; // init for GCC
! if (removing || (flags & P_NODUP))
! {
! i = (int)STRLEN(newval);
! s = find_dup_item(origval, newval, flags);
!
! // do not add if already there
! if ((adding || prepending) && s != NULL)
! {
! prepending = FALSE;
! adding = FALSE;
! STRCPY(newval, origval);
! }
!
! // if no duplicate, move pointer to end of
! // original value
! if (s == NULL)
! s = origval + (int)STRLEN(origval);
! }
!
! // concatenate the two strings; add a ',' if
! // needed
! if (adding || prepending)
! {
! comma = ((flags & P_COMMA) && *origval != NUL
! && *newval != NUL);
! if (adding)
! {
! i = (int)STRLEN(origval);
! // strip a trailing comma, would get 2
! if (comma && i > 1
! && (flags & P_ONECOMMA) == P_ONECOMMA
! && origval[i - 1] == ','
! && origval[i - 2] != '\\')
! i--;
! mch_memmove(newval + i + comma, newval,
! STRLEN(newval) + 1);
! mch_memmove(newval, origval, (size_t)i);
! }
! else
! {
! i = (int)STRLEN(newval);
! STRMOVE(newval + i + comma, origval);
! }
! if (comma)
! newval[i] = ',';
! }
!
! // Remove newval[] from origval[]. (Note: "i" has
! // been set above and is used here).
! if (removing)
! {
! STRCPY(newval, origval);
! if (*s)
! {
! // may need to remove a comma
! if (flags & P_COMMA)
! {
! if (s == origval)
! {
! // include comma after string
! if (s[i] == ',')
! ++i;
! }
! else
! {
! // include comma before string
! --s;
! ++i;
! }
! }
! STRMOVE(newval + (s - origval), s + i);
! }
! }
!
! if (flags & P_FLAGLIST)
! {
! // Remove flags that appear twice.
! for (s = newval; *s;)
! {
! // if options have P_FLAGLIST and
! // P_ONECOMMA such as 'whichwrap'
! if (flags & P_ONECOMMA)
! {
! if (*s != ',' && *(s + 1) == ','
! && vim_strchr(s + 2, *s) != NULL)
! {
! // Remove the duplicated value and
! // the next comma.
! STRMOVE(s, s + 2);
! continue;
! }
! }
! else
! {
! if ((!(flags & P_COMMA) || *s != ',')
! && vim_strchr(s + 1, *s) != NULL)
! {
! STRMOVE(s, s + 1);
! continue;
! }
! }
! ++s;
! }
! }
!
! if (save_arg != NULL) // number for 'whichwrap'
! arg = save_arg;
! }
!
! /*
! * Set the new value.
! */
! *(char_u **)(varp) = newval;
!
! #if defined(FEAT_EVAL)
! if (!starting
! # ifdef FEAT_CRYPT
! && options[opt_idx].indir != PV_KEY
! # endif
! && origval != NULL && newval != NULL)
! {
! // origval may be freed by
! // did_set_string_option(), make a copy.
! saved_origval = vim_strsave(origval);
! // newval (and varp) may become invalid if the
! // buffer is closed by autocommands.
! saved_newval = vim_strsave(newval);
! if (origval_l != NULL)
! saved_origval_l = vim_strsave(origval_l);
! if (origval_g != NULL)
! saved_origval_g = vim_strsave(origval_g);
! }
! #endif
!
! {
! long_u *p = insecure_flag(opt_idx, opt_flags);
! int secure_saved = secure;
!
! // When an option is set in the sandbox, from a
! // modeline or in secure mode, then deal with side
! // effects in secure mode. Also when the value was
! // set with the P_INSECURE flag and is not
! // completely replaced.
! if ((opt_flags & OPT_MODELINE)
! #ifdef HAVE_SANDBOX
! || sandbox != 0
! #endif
! || (!value_is_replaced && (*p & P_INSECURE)))
! secure = 1;
!
! // Handle side effects, and set the global value
! // for ":set" on local options. Note: when setting
! // 'syntax' or 'filetype' autocommands may be
! // triggered that can cause havoc.
! errmsg = did_set_string_option(
! opt_idx, (char_u **)varp, oldval, errbuf,
! opt_flags, &value_checked);
!
! secure = secure_saved;
}
-
- #if defined(FEAT_EVAL)
- if (errmsg == NULL)
- trigger_optionsset_string(
- opt_idx, opt_flags, saved_origval,
- saved_origval_l, saved_origval_g,
- saved_newval);
- vim_free(saved_origval);
- vim_free(saved_origval_l);
- vim_free(saved_origval_g);
- vim_free(saved_newval);
- #endif
- // If error detected, print the error message.
- if (errmsg != NULL)
- goto skip;
}
else // key code option
{
--- 2106,2130 ----
goto skip;
}
! if (op == OP_ADDING)
value = *(long *)varp + value;
! else if (op == OP_PREPENDING)
value = *(long *)varp * value;
! else if (op == OP_REMOVING)
value = *(long *)varp - value;
errmsg = set_num_option(opt_idx, varp, value,
errbuf, sizeof(errbuf), opt_flags);
}
else if (opt_idx >= 0) // string
{
! if (do_set_string(opt_idx, opt_flags, &arg, nextchar,
! op, flags, cp_val, varp, errbuf,
! &value_checked, &errmsg) == FAIL)
{
! if (errmsg != NULL)
! goto skip;
! break;
}
}
else // key code option
{
***************
*** 2149,2155 ****
if (opt_idx >= 0)
did_set_option(
! opt_idx, opt_flags, value_is_replaced, value_checked);
}
skip:
--- 2154,2160 ----
if (opt_idx >= 0)
did_set_option(
! opt_idx, opt_flags, op == OP_NONE, value_checked);
}
skip:
*** ../vim-9.0.0536/src/version.c 2022-09-21 19:41:52.172533866 +0100
--- src/version.c 2022-09-21 20:20:35.973014671 +0100
***************
*** 701,702 ****
--- 701,704 ----
{ /* Add new patch number below this line */
+ /**/
+ 537,
/**/
--
I'm writing a book. I've got the page numbers done.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///