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:
Famiu Haque
2024-10-27 19:09:24 +06:00
committed by GitHub
parent 123c0b6b4e
commit b136a9ee4c
7 changed files with 47 additions and 114 deletions

View File

@@ -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.