mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 06:28:35 +00:00
refactor(options): always allocate option values (#30917)
Instead of keeping `P_ALLOCED` and `P_DEF_ALLOCED` flags to check if an option value is allocated, always allocate option values to simplify the logic. Ref: #25672
This commit is contained in:
@@ -291,8 +291,7 @@ static void set_init_default_cdpath(void)
|
||||
}
|
||||
}
|
||||
buf[j] = NUL;
|
||||
options[kOptCdpath].def_val = CSTR_AS_OPTVAL(buf);
|
||||
options[kOptCdpath].flags |= P_DEF_ALLOCED;
|
||||
change_option_default(kOptCdpath, CSTR_AS_OPTVAL(buf));
|
||||
|
||||
xfree(cdpath);
|
||||
}
|
||||
@@ -302,8 +301,6 @@ static void set_init_default_cdpath(void)
|
||||
/// only happen for non-indirect options.
|
||||
/// Also set the default to the expanded value, so ":set" does not list
|
||||
/// them.
|
||||
/// Don't set the P_ALLOCED flag, because we don't want to free the
|
||||
/// default.
|
||||
static void set_init_expand_env(void)
|
||||
{
|
||||
for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
|
||||
@@ -318,14 +315,8 @@ static void set_init_expand_env(void)
|
||||
p = option_expand(opt_idx, NULL);
|
||||
}
|
||||
if (p != NULL) {
|
||||
set_option_varp(opt_idx, opt->var, CSTR_TO_OPTVAL(p), opt->flags & P_ALLOCED);
|
||||
opt->flags |= P_ALLOCED;
|
||||
|
||||
if (opt->flags & P_DEF_ALLOCED) {
|
||||
optval_free(opt->def_val);
|
||||
}
|
||||
opt->def_val = CSTR_TO_OPTVAL(p);
|
||||
opt->flags |= P_DEF_ALLOCED;
|
||||
set_option_varp(opt_idx, opt->var, CSTR_TO_OPTVAL(p), true);
|
||||
change_option_default(opt_idx, CSTR_TO_OPTVAL(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -356,6 +347,9 @@ void set_init_1(bool clean_arg)
|
||||
{
|
||||
langmap_init();
|
||||
|
||||
// Allocate the default option values.
|
||||
alloc_options_default();
|
||||
|
||||
set_init_default_shell();
|
||||
set_init_default_backupskip();
|
||||
set_init_default_cdpath();
|
||||
@@ -463,6 +457,25 @@ static OptVal get_option_default(const OptIndex opt_idx, int opt_flags)
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocate the default values for all options by copying them from the stack.
|
||||
/// This ensures that we don't need to always check if the option default is allocated or not.
|
||||
static void alloc_options_default(void)
|
||||
{
|
||||
for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
|
||||
options[opt_idx].def_val = optval_copy(options[opt_idx].def_val);
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the default value for an option.
|
||||
///
|
||||
/// @param opt_idx Option index in options[] table.
|
||||
/// @param value New default value. Must be allocated.
|
||||
static void change_option_default(const OptIndex opt_idx, OptVal value)
|
||||
{
|
||||
optval_free(options[opt_idx].def_val);
|
||||
options[opt_idx].def_val = value;
|
||||
}
|
||||
|
||||
/// Set an option to its default value.
|
||||
/// This does not take care of side effects!
|
||||
///
|
||||
@@ -512,17 +525,8 @@ static void set_options_default(int opt_flags)
|
||||
static void set_string_default(OptIndex opt_idx, char *val, bool allocated)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (opt_idx == kOptInvalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
vimoption_T *opt = &options[opt_idx];
|
||||
if (opt->flags & P_DEF_ALLOCED) {
|
||||
optval_free(opt->def_val);
|
||||
}
|
||||
|
||||
opt->def_val = CSTR_AS_OPTVAL(allocated ? val : xstrdup(val));
|
||||
opt->flags |= P_DEF_ALLOCED;
|
||||
assert(opt_idx != kOptInvalid);
|
||||
change_option_default(opt_idx, CSTR_AS_OPTVAL(allocated ? val : xstrdup(val)));
|
||||
}
|
||||
|
||||
/// For an option value that contains comma separated items, find "newval" in
|
||||
@@ -563,16 +567,14 @@ void free_all_options(void)
|
||||
for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
|
||||
if (options[opt_idx].indir == PV_NONE) {
|
||||
// global option: free value and default value.
|
||||
if ((options[opt_idx].flags & P_ALLOCED) && options[opt_idx].var != NULL) {
|
||||
if (options[opt_idx].var != NULL) {
|
||||
optval_free(optval_from_varp(opt_idx, options[opt_idx].var));
|
||||
}
|
||||
if (options[opt_idx].flags & P_DEF_ALLOCED) {
|
||||
optval_free(options[opt_idx].def_val);
|
||||
}
|
||||
} else if (options[opt_idx].var != VAR_WIN) {
|
||||
// buffer-local option: free global value
|
||||
optval_free(optval_from_varp(opt_idx, options[opt_idx].var));
|
||||
}
|
||||
optval_free(options[opt_idx].def_val);
|
||||
}
|
||||
free_operatorfunc_option();
|
||||
free_tagfunc_option();
|
||||
@@ -600,7 +602,7 @@ void set_init_2(bool headless)
|
||||
if (!option_was_set(kOptWindow)) {
|
||||
p_window = Rows - 1;
|
||||
}
|
||||
options[kOptWindow].def_val = NUMBER_OPTVAL(Rows - 1);
|
||||
change_option_default(kOptWindow, NUMBER_OPTVAL(Rows - 1));
|
||||
}
|
||||
|
||||
/// Initialize the options, part three: After reading the .vimrc
|
||||
@@ -632,12 +634,12 @@ void set_init_3(void)
|
||||
const OptVal sp =
|
||||
is_csh ? STATIC_CSTR_AS_OPTVAL("|& tee") : STATIC_CSTR_AS_OPTVAL("2>&1| tee");
|
||||
set_option_direct(kOptShellpipe, sp, 0, SID_NONE);
|
||||
options[kOptShellpipe].def_val = sp;
|
||||
change_option_default(kOptShellpipe, optval_copy(sp));
|
||||
}
|
||||
if (do_srr) {
|
||||
const OptVal srr = is_csh ? STATIC_CSTR_AS_OPTVAL(">&") : STATIC_CSTR_AS_OPTVAL(">%s 2>&1");
|
||||
set_option_direct(kOptShellredir, srr, 0, SID_NONE);
|
||||
options[kOptShellredir].def_val = srr;
|
||||
change_option_default(kOptShellredir, optval_copy(srr));
|
||||
}
|
||||
}
|
||||
xfree(p);
|
||||
@@ -670,9 +672,7 @@ void set_helplang_default(const char *lang)
|
||||
return;
|
||||
}
|
||||
|
||||
if (options[kOptHelplang].flags & P_ALLOCED) {
|
||||
free_string_option(p_hlg);
|
||||
}
|
||||
free_string_option(p_hlg);
|
||||
p_hlg = xmemdupz(lang, lang_len);
|
||||
// zh_CN becomes "cn", zh_TW becomes "tw".
|
||||
if (STRNICMP(p_hlg, "zh_", 3) == 0 && lang_len >= 5) {
|
||||
@@ -684,7 +684,6 @@ void set_helplang_default(const char *lang)
|
||||
p_hlg[1] = 'n';
|
||||
}
|
||||
p_hlg[2] = NUL;
|
||||
options[kOptHelplang].flags |= P_ALLOCED;
|
||||
}
|
||||
|
||||
/// 'title' and 'icon' only default to true if they have not been set or reset
|
||||
@@ -698,11 +697,11 @@ void set_title_defaults(void)
|
||||
// icon name. Saves a bit of time, because the X11 display server does
|
||||
// not need to be contacted.
|
||||
if (!(options[kOptTitle].flags & P_WAS_SET)) {
|
||||
options[kOptTitle].def_val = BOOLEAN_OPTVAL(false);
|
||||
change_option_default(kOptTitle, BOOLEAN_OPTVAL(false));
|
||||
p_title = 0;
|
||||
}
|
||||
if (!(options[kOptIcon].flags & P_WAS_SET)) {
|
||||
options[kOptIcon].def_val = BOOLEAN_OPTVAL(false);
|
||||
change_option_default(kOptIcon, BOOLEAN_OPTVAL(false));
|
||||
p_icon = 0;
|
||||
}
|
||||
}
|
||||
@@ -3441,7 +3440,6 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
|
||||
vimoption_T *opt = &options[opt_idx];
|
||||
const char *errmsg = NULL;
|
||||
bool restore_chartab = false;
|
||||
bool free_oldval = (opt->flags & P_ALLOCED);
|
||||
bool value_changed = false;
|
||||
bool value_checked = false;
|
||||
|
||||
@@ -3517,12 +3515,7 @@ static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value
|
||||
set_option_sctx(opt_idx, opt_flags, script_ctx);
|
||||
}
|
||||
|
||||
// Free options that are in allocated memory.
|
||||
// Use "free_oldval", because recursiveness may change the flags (esp. init_highlight()).
|
||||
if (free_oldval) {
|
||||
optval_free(old_value);
|
||||
}
|
||||
opt->flags |= P_ALLOCED;
|
||||
optval_free(old_value);
|
||||
|
||||
const bool scope_both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
|
||||
|
||||
@@ -5398,7 +5391,7 @@ void reset_modifiable(void)
|
||||
{
|
||||
curbuf->b_p_ma = false;
|
||||
p_ma = false;
|
||||
options[kOptModifiable].def_val = BOOLEAN_OPTVAL(false);
|
||||
change_option_default(kOptModifiable, BOOLEAN_OPTVAL(false));
|
||||
}
|
||||
|
||||
/// Set the global value for 'iminsert' to the local value.
|
||||
|
Reference in New Issue
Block a user