aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c101
-rw-r--r--src/nvim/eval_defs.h28
2 files changed, 66 insertions, 63 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d9bf475e35..f5c9571ce4 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -3112,68 +3112,71 @@ static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock)
static void item_lock(typval_T *tv, int deep, int lock)
{
static int recurse = 0;
- list_T *l;
- listitem_T *li;
- dict_T *d;
- hashitem_T *hi;
- int todo;
if (recurse >= DICT_MAXNEST) {
EMSG(_("E743: variable nested too deep for (un)lock"));
return;
}
- if (deep == 0)
+ if (deep == 0) {
return;
- ++recurse;
+ }
+ recurse++;
- /* lock/unlock the item itself */
- if (lock)
- tv->v_lock |= VAR_LOCKED;
- else
- tv->v_lock &= ~VAR_LOCKED;
+ // lock/unlock the item itself
+#define CHANGE_LOCK(var, lock) \
+ do { \
+ var = ((VarLockStatus[]) { \
+ [VAR_UNLOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \
+ [VAR_LOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \
+ [VAR_FIXED] = VAR_FIXED, \
+ })[var]; \
+ } while (0)
+ CHANGE_LOCK(tv->v_lock, lock);
switch (tv->v_type) {
- case VAR_LIST:
- if ((l = tv->vval.v_list) != NULL) {
- if (lock)
- l->lv_lock |= VAR_LOCKED;
- else
- l->lv_lock &= ~VAR_LOCKED;
- if (deep < 0 || deep > 1)
- /* recursive: lock/unlock the items the List contains */
- for (li = l->lv_first; li != NULL; li = li->li_next)
- item_lock(&li->li_tv, deep - 1, lock);
+ case VAR_LIST: {
+ list_T *const l = tv->vval.v_list;
+ if (l != NULL) {
+ CHANGE_LOCK(l->lv_lock, lock);
+ if (deep < 0 || deep > 1)
+ // Recursive: lock/unlock the items the List contains.
+ for (listitem_T *li = l->lv_first; li != NULL; li = li->li_next) {
+ item_lock(&li->li_tv, deep - 1, lock);
+ }
+ }
+ break;
}
- break;
- case VAR_DICT:
- if ((d = tv->vval.v_dict) != NULL) {
- if (lock)
- d->dv_lock |= VAR_LOCKED;
- else
- d->dv_lock &= ~VAR_LOCKED;
- if (deep < 0 || deep > 1) {
- /* recursive: lock/unlock the items the List contains */
- todo = (int)d->dv_hashtab.ht_used;
- for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) {
- if (!HASHITEM_EMPTY(hi)) {
- --todo;
- item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
+ case VAR_DICT: {
+ dict_T *const d = tv->vval.v_dict;
+ if (d != NULL) {
+ CHANGE_LOCK(d->dv_lock, lock);
+ if (deep < 0 || deep > 1) {
+ // Recursive: lock/unlock the items the List contains.
+ int todo = (int)d->dv_hashtab.ht_used;
+ for (hashitem_T *hi = d->dv_hashtab.ht_array; todo > 0; hi++) {
+ if (!HASHITEM_EMPTY(hi)) {
+ todo--;
+ item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
+ }
}
}
}
+ break;
+ }
+ case VAR_NUMBER:
+ case VAR_FLOAT:
+ case VAR_STRING:
+ case VAR_FUNC:
+ case VAR_PARTIAL:
+ case VAR_SPECIAL: {
+ break;
+ }
+ case VAR_UNKNOWN: {
+ assert(false);
}
- break;
- case VAR_NUMBER:
- case VAR_FLOAT:
- case VAR_STRING:
- case VAR_FUNC:
- case VAR_PARTIAL:
- case VAR_SPECIAL:
- break;
- case VAR_UNKNOWN:
- assert(false);
}
- --recurse;
+#undef CHANGE_LOCK
+ recurse--;
}
/*
@@ -6350,7 +6353,7 @@ dict_T *dict_alloc(void) FUNC_ATTR_NONNULL_RET
first_dict = d;
hash_init(&d->dv_hashtab);
- d->dv_lock = 0;
+ d->dv_lock = VAR_UNLOCKED;
d->dv_scope = 0;
d->dv_refcount = 0;
d->dv_copyID = 0;
@@ -20293,7 +20296,7 @@ void new_script_vars(scid_T id)
void init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope)
{
hash_init(&dict->dv_hashtab);
- dict->dv_lock = 0;
+ dict->dv_lock = VAR_UNLOCKED;
dict->dv_scope = scope;
dict->dv_refcount = DO_NOT_FREE_CNT;
dict->dv_copyID = 0;
diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h
index a61ddb7605..fb2822b851 100644
--- a/src/nvim/eval_defs.h
+++ b/src/nvim/eval_defs.h
@@ -30,8 +30,8 @@ typedef enum {
/// Variable lock status for typval_T.v_lock
typedef enum {
VAR_UNLOCKED = 0, ///< Not locked.
- VAR_LOCKED, ///< User lock, can be unlocked.
- VAR_FIXED, ///< Locked forever.
+ VAR_LOCKED = 1, ///< User lock, can be unlocked.
+ VAR_FIXED = 2, ///< Locked forever.
} VarLockStatus;
/// VimL variable types, for use in typval_T.v_type
@@ -93,18 +93,18 @@ struct listwatch_S {
* Structure to hold info about a list.
*/
struct listvar_S {
- listitem_T *lv_first; /* first item, NULL if none */
- listitem_T *lv_last; /* last item, NULL if none */
- int lv_refcount; /* reference count */
- int lv_len; /* number of items */
- listwatch_T *lv_watch; /* first watcher, NULL if none */
- int lv_idx; /* cached index of an item */
- listitem_T *lv_idx_item; /* when not NULL item at index "lv_idx" */
- int lv_copyID; /* ID used by deepcopy() */
- list_T *lv_copylist; /* copied list used by deepcopy() */
- char lv_lock; /* zero, VAR_LOCKED, VAR_FIXED */
- list_T *lv_used_next; /* next list in used lists list */
- list_T *lv_used_prev; /* previous list in used lists list */
+ listitem_T *lv_first; ///< First item, NULL if none.
+ listitem_T *lv_last; ///< Last item, NULL if none.
+ int lv_refcount; ///< Reference count.
+ int lv_len; ///< Number of items.
+ listwatch_T *lv_watch; ///< First watcher, NULL if none.
+ int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
+ listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
+ int lv_copyID; ///< ID used by deepcopy().
+ list_T *lv_copylist; ///< Copied list used by deepcopy().
+ VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
+ list_T *lv_used_next; ///< next list in used lists list.
+ list_T *lv_used_prev; ///< Previous list in used lists list.
};
// Static list with 10 items. Use init_static_list() to initialize.