diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/private/helpers.c | 8 | ||||
-rw-r--r-- | src/nvim/eval.c | 75 | ||||
-rw-r--r-- | src/nvim/eval/decode.c | 40 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 76 | ||||
-rw-r--r-- | src/nvim/lua/converter.c | 36 |
5 files changed, 119 insertions, 116 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 4492f8bb93..26ad7ac1a6 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -787,16 +787,14 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err) for (uint32_t i = 0; i < obj.data.array.size; i++) { Object item = obj.data.array.items[i]; - listitem_T *li = tv_list_item_alloc(); + typval_T li_tv; - if (!object_to_vim(item, TV_LIST_ITEM_TV(li), err)) { - // cleanup - tv_list_item_free(li); + if (!object_to_vim(item, &li_tv, err)) { tv_list_free(list); return false; } - tv_list_append(list, li); + tv_list_append_owned_tv(list, li_tv); } tv_list_ref(list); diff --git a/src/nvim/eval.c b/src/nvim/eval.c index e6cb8cdec0..fac15770a6 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -4874,8 +4874,6 @@ void partial_unref(partial_T *pt) static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) { list_T *l = NULL; - typval_T tv; - listitem_T *item; if (evaluate) { l = tv_list_alloc(); @@ -4883,13 +4881,13 @@ static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate) *arg = skipwhite(*arg + 1); while (**arg != ']' && **arg != NUL) { - if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ + typval_T tv; + if (eval1(arg, &tv, evaluate) == FAIL) { // Recursive! goto failret; + } if (evaluate) { - item = tv_list_item_alloc(); - *TV_LIST_ITEM_TV(item) = tv; - TV_LIST_ITEM_TV(item)->v_lock = VAR_UNLOCKED; - tv_list_append(l, item); + tv.v_lock = VAR_UNLOCKED; + tv_list_append_owned_tv(l, tv); } if (**arg == ']') { @@ -11441,40 +11439,38 @@ static void dict_list(typval_T *const tv, typval_T *const rettv, tv_list_alloc_ret(rettv); TV_DICT_ITER(tv->vval.v_dict, di, { - listitem_T *const li = tv_list_item_alloc(); - tv_list_append(rettv->vval.v_list, li); + typval_T tv = { .v_lock = VAR_UNLOCKED }; switch (what) { case kDictListKeys: { - TV_LIST_ITEM_TV(li)->v_type = VAR_STRING; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_string = vim_strsave(di->di_key); + tv.v_type = VAR_STRING; + tv.vval.v_string = vim_strsave(di->di_key); break; } case kDictListValues: { - tv_copy(&di->di_tv, TV_LIST_ITEM_TV(li)); + tv_copy(&di->di_tv, &tv); break; } case kDictListItems: { // items() list_T *const sub_l = tv_list_alloc(); - TV_LIST_ITEM_TV(li)->v_type = VAR_LIST; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_list = sub_l; + tv.v_type = VAR_LIST; + tv.vval.v_list = sub_l; tv_list_ref(sub_l); - listitem_T *sub_li = tv_list_item_alloc(); - tv_list_append(sub_l, sub_li); - TV_LIST_ITEM_TV(sub_li)->v_type = VAR_STRING; - TV_LIST_ITEM_TV(sub_li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(sub_li)->vval.v_string = vim_strsave(di->di_key); + tv_list_append_owned_tv(sub_l, (typval_T) { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = (char_u *)xstrdup((const char *)di->di_key), + }); + + tv_list_append_tv(sub_l, &di->di_tv); - sub_li = tv_list_item_alloc(); - tv_list_append(sub_l, sub_li); - tv_copy(&di->di_tv, TV_LIST_ITEM_TV(sub_li)); break; } } + + tv_list_append_owned_tv(rettv->vval.v_list, tv); }); } @@ -12762,13 +12758,12 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) goto f_msgpackparse_exit; } if (result == MSGPACK_UNPACK_SUCCESS) { - listitem_T *li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(li)->v_type = VAR_UNKNOWN; - tv_list_append(ret_list, li); - if (msgpack_to_vim(unpacked.data, TV_LIST_ITEM_TV(li)) == FAIL) { + typval_T tv = { .v_type = VAR_UNKNOWN }; + if (msgpack_to_vim(unpacked.data, &tv) == FAIL) { EMSG2(_(e_invarg2), "Failed to convert msgpack string"); goto f_msgpackparse_exit; } + tv_list_append_owned_tv(ret_list, tv); } if (result == MSGPACK_UNPACK_CONTINUE) { if (rlret == OK) { @@ -13030,7 +13025,6 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary)); ++p) { if (*p == '\n' || readlen <= 0) { - listitem_T *li; char_u *s = NULL; size_t len = p - start; @@ -13057,11 +13051,11 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) prevlen = prevsize = 0; } - li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(li)->v_type = VAR_STRING; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_string = s; - tv_list_append(rettv->vval.v_list, li); + tv_list_append_owned_tv(rettv->vval.v_list, (typval_T) { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = s, + }); start = p + 1; /* step over newline */ if ((++cnt >= maxline && maxline >= 0) || readlen <= 0) @@ -14310,11 +14304,7 @@ static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Copy addrs into a linked list. list_T *l = tv_list_alloc_ret(rettv); for (size_t i = 0; i < n; i++) { - listitem_T *li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(li)->v_type = VAR_STRING; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_string = (char_u *)addrs[i]; - tv_list_append(l, li); + tv_list_append_allocated_string(l, addrs[i]); } xfree(addrs); } @@ -15619,12 +15609,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) for (int i = 0; i < ga.ga_len; i++) { char *p = ((char **)ga.ga_data)[i]; - - listitem_T *const li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(li)->v_type = VAR_STRING; - TV_LIST_ITEM_TV(li)->v_lock = VAR_LOCKED; - TV_LIST_ITEM_TV(li)->vval.v_string = (char_u *)p; - tv_list_append(rettv->vval.v_list, li); + tv_list_append_allocated_string(rettv->vval.v_list, p); } ga_clear(&ga); } diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index d5c65ebe81..af4e055d23 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -127,9 +127,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, return FAIL; } assert(last_container.special_val == NULL); - listitem_T *obj_li = tv_list_item_alloc(); - *TV_LIST_ITEM_TV(obj_li) = obj.val; - tv_list_append(last_container.container.vval.v_list, obj_li); + tv_list_append_owned_tv(last_container.container.vval.v_list, obj.val); } else if (last_container.stack_index == kv_size(*stack) - 2) { if (!obj.didcolon) { EMSG2(_("E474: Expected colon before dictionary value: %s"), @@ -154,12 +152,8 @@ static inline int json_decoder_pop(ValuesStackItem obj, } else { list_T *const kv_pair = tv_list_alloc(); tv_list_append_list(last_container.special_val, kv_pair); - listitem_T *const key_li = tv_list_item_alloc(); - *TV_LIST_ITEM_TV(key_li) = key.val; - tv_list_append(kv_pair, key_li); - listitem_T *const val_li = tv_list_item_alloc(); - *TV_LIST_ITEM_TV(val_li) = obj.val; - tv_list_append(kv_pair, val_li); + tv_list_append_owned_tv(kv_pair, key.val); + tv_list_append_owned_tv(kv_pair, obj.val); } } else { // Object with key only @@ -1047,10 +1041,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) .vval = { .v_list = list }, }; for (size_t i = 0; i < mobj.via.array.size; i++) { - listitem_T *const li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(li)->v_type = VAR_UNKNOWN; - tv_list_append(list, li); - if (msgpack_to_vim(mobj.via.array.ptr[i], TV_LIST_ITEM_TV(li)) + // Not populated yet, need to create list item to push. + tv_list_append_owned_tv(list, (typval_T) { .v_type = VAR_UNKNOWN }); + if (msgpack_to_vim(mobj.via.array.ptr[i], + TV_LIST_ITEM_TV(tv_list_last(list))) == FAIL) { return FAIL; } @@ -1095,20 +1089,20 @@ msgpack_to_vim_generic_map: {} for (size_t i = 0; i < mobj.via.map.size; i++) { list_T *const kv_pair = tv_list_alloc(); tv_list_append_list(list, kv_pair); - listitem_T *const key_li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(key_li)->v_type = VAR_UNKNOWN; - tv_list_append(kv_pair, key_li); - listitem_T *const val_li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(val_li)->v_type = VAR_UNKNOWN; - tv_list_append(kv_pair, val_li); - if (msgpack_to_vim(mobj.via.map.ptr[i].key, TV_LIST_ITEM_TV(key_li)) - == FAIL) { + + typval_T key_tv = { .v_type = VAR_UNKNOWN }; + if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_tv) == FAIL) { + tv_clear(&key_tv); return FAIL; } - if (msgpack_to_vim(mobj.via.map.ptr[i].val, TV_LIST_ITEM_TV(val_li)) - == FAIL) { + tv_list_append_owned_tv(kv_pair, key_tv); + + typval_T val_tv = { .v_type = VAR_UNKNOWN }; + if (msgpack_to_vim(mobj.via.map.ptr[i].val, &val_tv) == FAIL) { + tv_clear(&val_tv); return FAIL; } + tv_list_append_owned_tv(kv_pair, val_tv); } break; } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 53c56d0ffd..0755507f91 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -393,19 +393,30 @@ void tv_list_append_tv(list_T *const l, typval_T *const tv) tv_list_append(l, li); } +/// Like tv_list_append_tv(), but tv is moved to a list +/// +/// This means that it is no longer valid to use contents of the typval_T after +/// function exits. +void tv_list_append_owned_tv(list_T *const l, typval_T tv) + FUNC_ATTR_NONNULL_ALL +{ + listitem_T *const li = tv_list_item_alloc(); + *TV_LIST_ITEM_TV(li) = tv; + tv_list_append(l, li); +} + /// Append a list to a list as one item /// /// @param[out] l List to append to. /// @param[in,out] itemlist List to append. Reference count is increased. -void tv_list_append_list(list_T *const list, list_T *const itemlist) +void tv_list_append_list(list_T *const l, list_T *const itemlist) FUNC_ATTR_NONNULL_ARG(1) { - listitem_T *const li = tv_list_item_alloc(); - - TV_LIST_ITEM_TV(li)->v_type = VAR_LIST; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_list = itemlist; - tv_list_append(list, li); + tv_list_append_owned_tv(l, (typval_T) { + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval.v_list = itemlist, + }); tv_list_ref(itemlist); } @@ -413,15 +424,14 @@ void tv_list_append_list(list_T *const list, list_T *const itemlist) /// /// @param[out] l List to append to. /// @param[in,out] dict Dictionary to append. Reference count is increased. -void tv_list_append_dict(list_T *const list, dict_T *const dict) +void tv_list_append_dict(list_T *const l, dict_T *const dict) FUNC_ATTR_NONNULL_ARG(1) { - listitem_T *const li = tv_list_item_alloc(); - - TV_LIST_ITEM_TV(li)->v_type = VAR_DICT; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_dict = dict; - tv_list_append(list, li); + tv_list_append_owned_tv(l, (typval_T) { + .v_type = VAR_DICT, + .v_lock = VAR_UNLOCKED, + .vval.v_dict = dict, + }); if (dict != NULL) { dict->dv_refcount++; } @@ -438,14 +448,15 @@ void tv_list_append_string(list_T *const l, const char *const str, const ssize_t len) FUNC_ATTR_NONNULL_ARG(1) { - if (str == NULL) { - assert(len == 0 || len == -1); - tv_list_append_allocated_string(l, NULL); - } else { - tv_list_append_allocated_string(l, (len >= 0 - ? xmemdupz(str, (size_t)len) - : xstrdup(str))); - } + tv_list_append_owned_tv(l, (typval_T) { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = (str == NULL + ? NULL + : (len >= 0 + ? xmemdupz(str, (size_t)len) + : xstrdup(str))), + }); } /// Append given string to the list @@ -457,12 +468,11 @@ void tv_list_append_string(list_T *const l, const char *const str, void tv_list_append_allocated_string(list_T *const l, char *const str) FUNC_ATTR_NONNULL_ARG(1) { - listitem_T *const li = tv_list_item_alloc(); - - tv_list_append(l, li); - TV_LIST_ITEM_TV(li)->v_type = VAR_STRING; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_string = (char_u *)str; + tv_list_append_owned_tv(l, (typval_T) { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = (char_u *)str, + }); } /// Append number to the list @@ -472,11 +482,11 @@ void tv_list_append_allocated_string(list_T *const l, char *const str) /// listitem_T. void tv_list_append_number(list_T *const l, const varnumber_T n) { - listitem_T *const li = tv_list_item_alloc(); - TV_LIST_ITEM_TV(li)->v_type = VAR_NUMBER; - TV_LIST_ITEM_TV(li)->v_lock = VAR_UNLOCKED; - TV_LIST_ITEM_TV(li)->vval.v_number = n; - tv_list_append(l, li); + tv_list_append_owned_tv(l, (typval_T) { + .v_type = VAR_NUMBER, + .v_lock = VAR_UNLOCKED, + .vval.v_number = n, + }); } //{{{2 Operations on the whole list diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c index 8303ecdd37..89fedae73a 100644 --- a/src/nvim/lua/converter.c +++ b/src/nvim/lua/converter.c @@ -212,19 +212,27 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv) const char *s = lua_tolstring(lstate, -2, &len); if (cur.special) { list_T *const kv_pair = tv_list_alloc(); + tv_list_append_list(cur.tv->vval.v_list, kv_pair); - listitem_T *const key = tv_list_item_alloc(); - *TV_LIST_ITEM_TV(key) = decode_string(s, len, kTrue, false, false); - tv_list_append(kv_pair, key); - if (TV_LIST_ITEM_TV(key)->v_type == VAR_UNKNOWN) { + typval_T s_tv = decode_string(s, len, kTrue, false, false); + if (s_tv.v_type == VAR_UNKNOWN) { ret = false; tv_list_unref(kv_pair); continue; } - listitem_T *const val = tv_list_item_alloc(); - tv_list_append(kv_pair, val); + tv_list_append_owned_tv(kv_pair, s_tv); + + // Value: not populated yet, need to create list item to push. + tv_list_append_owned_tv(kv_pair, (typval_T) { + .v_type = VAR_UNKNOWN, + }); kv_push(stack, cur); - cur = (TVPopStackItem) { TV_LIST_ITEM_TV(val), false, false, 0 }; + cur = (TVPopStackItem) { + .tv = TV_LIST_ITEM_TV(tv_list_last(kv_pair)), + .container = false, + .special = false, + .idx = 0, + }; } else { dictitem_T *const di = tv_dict_item_alloc_len(s, len); if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) { @@ -244,10 +252,18 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv) lua_pop(lstate, 2); continue; } - listitem_T *const li = tv_list_item_alloc(); - tv_list_append(cur.tv->vval.v_list, li); + // Not populated yet, need to create list item to push. + tv_list_append_owned_tv(cur.tv->vval.v_list, (typval_T) { + .v_type = VAR_UNKNOWN, + }); kv_push(stack, cur); - cur = (TVPopStackItem) { TV_LIST_ITEM_TV(li), false, false, 0 }; + // TODO(ZyX-I): Use indexes, here list item *will* be reallocated. + cur = (TVPopStackItem) { + .tv = TV_LIST_ITEM_TV(tv_list_last(cur.tv->vval.v_list)), + .container = false, + .special = false, + .idx = 0, + }; } } assert(!cur.container); |