*: Hide list implementation in other files as well

This commit is contained in:
ZyX 2017-12-10 22:04:43 +03:00
parent 5c1ddb5078
commit ac4bbf55f6
17 changed files with 278 additions and 235 deletions

View File

@ -789,7 +789,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
Object item = obj.data.array.items[i]; Object item = obj.data.array.items[i];
listitem_T *li = tv_list_item_alloc(); listitem_T *li = tv_list_item_alloc();
if (!object_to_vim(item, &li->li_tv, err)) { if (!object_to_vim(item, TV_LIST_ITEM_TV(li), err)) {
// cleanup // cleanup
tv_list_item_free(li); tv_list_item_free(li);
tv_list_free(list); tv_list_free(list);

View File

@ -3536,19 +3536,19 @@ theend:
/* /*
* Add completions from a list. * Add completions from a list.
*/ */
static void ins_compl_add_list(list_T *list) static void ins_compl_add_list(list_T *const list)
{ {
listitem_T *li;
int dir = compl_direction; int dir = compl_direction;
/* Go through the List with matches and add each of them. */ // Go through the List with matches and add each of them.
for (li = list->lv_first; li != NULL; li = li->li_next) { TV_LIST_ITER(list, li, {
if (ins_compl_add_tv(&li->li_tv, dir) == OK) if (ins_compl_add_tv(TV_LIST_ITEM_TV(li), dir) == OK) {
/* if dir was BACKWARD then honor it just once */ // If dir was BACKWARD then honor it just once.
dir = FORWARD; dir = FORWARD;
else if (did_emsg) } else if (did_emsg) {
break; break;
} }
});
} }
/* /*

View File

@ -120,7 +120,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
last_container = kv_last(*container_stack); last_container = kv_last(*container_stack);
} }
if (last_container.container.v_type == VAR_LIST) { if (last_container.container.v_type == VAR_LIST) {
if (last_container.container.vval.v_list->lv_len != 0 if (tv_list_len(last_container.container.vval.v_list) != 0
&& !obj.didcomma) { && !obj.didcomma) {
EMSG2(_("E474: Expected comma before list item: %s"), val_location); EMSG2(_("E474: Expected comma before list item: %s"), val_location);
tv_clear(&obj.val); tv_clear(&obj.val);
@ -128,7 +128,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
} }
assert(last_container.special_val == NULL); assert(last_container.special_val == NULL);
listitem_T *obj_li = tv_list_item_alloc(); listitem_T *obj_li = tv_list_item_alloc();
obj_li->li_tv = obj.val; *TV_LIST_ITEM_TV(obj_li) = obj.val;
tv_list_append(last_container.container.vval.v_list, obj_li); tv_list_append(last_container.container.vval.v_list, obj_li);
} else if (last_container.stack_index == kv_size(*stack) - 2) { } else if (last_container.stack_index == kv_size(*stack) - 2) {
if (!obj.didcolon) { if (!obj.didcolon) {
@ -155,10 +155,10 @@ static inline int json_decoder_pop(ValuesStackItem obj,
list_T *const kv_pair = tv_list_alloc(); list_T *const kv_pair = tv_list_alloc();
tv_list_append_list(last_container.special_val, kv_pair); tv_list_append_list(last_container.special_val, kv_pair);
listitem_T *const key_li = tv_list_item_alloc(); listitem_T *const key_li = tv_list_item_alloc();
key_li->li_tv = key.val; *TV_LIST_ITEM_TV(key_li) = key.val;
tv_list_append(kv_pair, key_li); tv_list_append(kv_pair, key_li);
listitem_T *const val_li = tv_list_item_alloc(); listitem_T *const val_li = tv_list_item_alloc();
val_li->li_tv = obj.val; *TV_LIST_ITEM_TV(val_li) = obj.val;
tv_list_append(kv_pair, val_li); tv_list_append(kv_pair, val_li);
} }
} else { } else {
@ -738,8 +738,9 @@ json_decode_string_cycle_start:
} else if (last_container.special_val == NULL } else if (last_container.special_val == NULL
? (last_container.container.v_type == VAR_DICT ? (last_container.container.v_type == VAR_DICT
? (DICT_LEN(last_container.container.vval.v_dict) == 0) ? (DICT_LEN(last_container.container.vval.v_dict) == 0)
: (last_container.container.vval.v_list->lv_len == 0)) : (tv_list_len(last_container.container.vval.v_list)
: (last_container.special_val->lv_len == 0)) { == 0))
: (tv_list_len(last_container.special_val) == 0)) {
emsgf(_("E474: Leading comma: %.*s"), LENP(p, e)); emsgf(_("E474: Leading comma: %.*s"), LENP(p, e));
goto json_decode_string_fail; goto json_decode_string_fail;
} }
@ -1047,9 +1048,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
}; };
for (size_t i = 0; i < mobj.via.array.size; i++) { for (size_t i = 0; i < mobj.via.array.size; i++) {
listitem_T *const li = tv_list_item_alloc(); listitem_T *const li = tv_list_item_alloc();
li->li_tv.v_type = VAR_UNKNOWN; TV_LIST_ITEM_TV(li)->v_type = VAR_UNKNOWN;
tv_list_append(list, li); tv_list_append(list, li);
if (msgpack_to_vim(mobj.via.array.ptr[i], &li->li_tv) == FAIL) { if (msgpack_to_vim(mobj.via.array.ptr[i], TV_LIST_ITEM_TV(li))
== FAIL) {
return FAIL; return FAIL;
} }
} }
@ -1094,15 +1096,17 @@ msgpack_to_vim_generic_map: {}
list_T *const kv_pair = tv_list_alloc(); list_T *const kv_pair = tv_list_alloc();
tv_list_append_list(list, kv_pair); tv_list_append_list(list, kv_pair);
listitem_T *const key_li = tv_list_item_alloc(); listitem_T *const key_li = tv_list_item_alloc();
key_li->li_tv.v_type = VAR_UNKNOWN; TV_LIST_ITEM_TV(key_li)->v_type = VAR_UNKNOWN;
tv_list_append(kv_pair, key_li); tv_list_append(kv_pair, key_li);
listitem_T *const val_li = tv_list_item_alloc(); listitem_T *const val_li = tv_list_item_alloc();
val_li->li_tv.v_type = VAR_UNKNOWN; TV_LIST_ITEM_TV(val_li)->v_type = VAR_UNKNOWN;
tv_list_append(kv_pair, val_li); tv_list_append(kv_pair, val_li);
if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_li->li_tv) == FAIL) { if (msgpack_to_vim(mobj.via.map.ptr[i].key, TV_LIST_ITEM_TV(key_li))
== FAIL) {
return FAIL; return FAIL;
} }
if (msgpack_to_vim(mobj.via.map.ptr[i].val, &val_li->li_tv) == FAIL) { if (msgpack_to_vim(mobj.via.map.ptr[i].val, TV_LIST_ITEM_TV(val_li))
== FAIL) {
return FAIL; return FAIL;
} }
} }

View File

@ -53,17 +53,18 @@ int encode_list_write(void *const data, const char *const buf, const size_t len)
list_T *const list = (list_T *) data; list_T *const list = (list_T *) data;
const char *const end = buf + len; const char *const end = buf + len;
const char *line_end = buf; const char *line_end = buf;
listitem_T *li = list->lv_last; listitem_T *li = tv_list_last(list);
// Continue the last list element // Continue the last list element
if (li != NULL) { if (li != NULL) {
line_end = xmemscan(buf, NL, len); line_end = xmemscan(buf, NL, len);
if (line_end != buf) { if (line_end != buf) {
const size_t line_length = (size_t)(line_end - buf); const size_t line_length = (size_t)(line_end - buf);
char *str = (char *)li->li_tv.vval.v_string; char *str = (char *)TV_LIST_ITEM_TV(li)->vval.v_string;
const size_t li_len = (str == NULL ? 0 : strlen(str)); const size_t li_len = (str == NULL ? 0 : strlen(str));
li->li_tv.vval.v_string = xrealloc(str, li_len + line_length + 1); TV_LIST_ITEM_TV(li)->vval.v_string = xrealloc(
str = (char *)li->li_tv.vval.v_string + li_len; str, li_len + line_length + 1);
str = (char *)TV_LIST_ITEM_TV(li)->vval.v_string + li_len;
memcpy(str, buf, line_length); memcpy(str, buf, line_length);
str[line_length] = 0; str[line_length] = 0;
memchrsub(str, NUL, NL, line_length); memchrsub(str, NUL, NL, line_length);
@ -135,21 +136,18 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack,
} }
case kMPConvPairs: case kMPConvPairs:
case kMPConvList: { case kMPConvList: {
int idx = 0; const listitem_T *const li = TV_LIST_ITEM_PREV(v.data.l.list,
const listitem_T *li; v.data.l.li);
for (li = v.data.l.list->lv_first; int idx = (int)tv_list_idx_of_item(v.data.l.list, li);
li != NULL && li->li_next != v.data.l.li;
li = li->li_next) {
idx++;
}
if (v.type == kMPConvList if (v.type == kMPConvList
|| li == NULL || li == NULL
|| (li->li_tv.v_type != VAR_LIST || (TV_LIST_ITEM_TV(li)->v_type != VAR_LIST
&& li->li_tv.vval.v_list->lv_len <= 0)) { && tv_list_len(TV_LIST_ITEM_TV(li)->vval.v_list) <= 0)) {
vim_snprintf((char *) IObuff, IOSIZE, idx_msg, idx); vim_snprintf((char *)IObuff, IOSIZE, idx_msg, idx);
ga_concat(&msg_ga, IObuff); ga_concat(&msg_ga, IObuff);
} else { } else {
typval_T key_tv = li->li_tv.vval.v_list->lv_first->li_tv; typval_T key_tv = *TV_LIST_ITEM_TV(
tv_list_first(TV_LIST_ITEM_TV(li)->vval.v_list));
char *const key = encode_tv2echo(&key_tv, NULL); char *const key = encode_tv2echo(&key_tv, NULL);
vim_snprintf((char *) IObuff, IOSIZE, key_pair_msg, key, idx); vim_snprintf((char *) IObuff, IOSIZE, key_pair_msg, key, idx);
xfree(key); xfree(key);
@ -202,21 +200,17 @@ bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len,
FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2, 3) FUNC_ATTR_WARN_UNUSED_RESULT
{ {
size_t len = 0; size_t len = 0;
if (list != NULL) { TV_LIST_ITER_CONST(list, li, {
for (const listitem_T *li = list->lv_first; if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
li != NULL; return false;
li = li->li_next) {
if (li->li_tv.v_type != VAR_STRING) {
return false;
}
len++;
if (li->li_tv.vval.v_string != 0) {
len += STRLEN(li->li_tv.vval.v_string);
}
} }
if (len) { len++;
len--; if (TV_LIST_ITEM_TV(li)->vval.v_string != 0) {
len += STRLEN(TV_LIST_ITEM_TV(li)->vval.v_string);
} }
});
if (len) {
len--;
} }
*ret_len = len; *ret_len = len;
if (len == 0) { if (len == 0) {
@ -253,31 +247,34 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,
char *const buf_end = buf + nbuf; char *const buf_end = buf + nbuf;
char *p = buf; char *p = buf;
while (p < buf_end) { while (p < buf_end) {
assert(state->li_length == 0 || state->li->li_tv.vval.v_string != NULL); assert(state->li_length == 0
|| TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL);
for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) { for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) {
assert(state->li->li_tv.vval.v_string != NULL); assert(TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL);
const char ch = (char)state->li->li_tv.vval.v_string[state->offset++]; const char ch = (char)(
TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]);
*p++ = (char)((char)ch == (char)NL ? (char)NUL : (char)ch); *p++ = (char)((char)ch == (char)NL ? (char)NUL : (char)ch);
} }
if (p < buf_end) { if (p < buf_end) {
state->li = state->li->li_next; state->li = TV_LIST_ITEM_NEXT(state->list, state->li);
if (state->li == NULL) { if (state->li == NULL) {
*read_bytes = (size_t) (p - buf); *read_bytes = (size_t) (p - buf);
return OK; return OK;
} }
*p++ = NL; *p++ = NL;
if (state->li->li_tv.v_type != VAR_STRING) { if (TV_LIST_ITEM_TV(state->li)->v_type != VAR_STRING) {
*read_bytes = (size_t) (p - buf); *read_bytes = (size_t) (p - buf);
return FAIL; return FAIL;
} }
state->offset = 0; state->offset = 0;
state->li_length = (state->li->li_tv.vval.v_string == NULL state->li_length = (TV_LIST_ITEM_TV(state->li)->vval.v_string == NULL
? 0 ? 0
: STRLEN(state->li->li_tv.vval.v_string)); : STRLEN(TV_LIST_ITEM_TV(state->li)->vval.v_string));
} }
} }
*read_bytes = nbuf; *read_bytes = nbuf;
return (state->offset < state->li_length || state->li->li_next != NULL return ((state->offset < state->li_length
|| TV_LIST_ITEM_NEXT(state->list, state->li) != NULL)
? NOTDONE ? NOTDONE
: OK); : OK);
} }
@ -727,12 +724,11 @@ bool encode_check_json_key(const typval_T *const tv)
if (val_di->di_tv.vval.v_list == NULL) { if (val_di->di_tv.vval.v_list == NULL) {
return true; return true;
} }
for (const listitem_T *li = val_di->di_tv.vval.v_list->lv_first; TV_LIST_ITER_CONST(val_di->di_tv.vval.v_list, li, {
li != NULL; li = li->li_next) { if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
if (li->li_tv.v_type != VAR_STRING) {
return false; return false;
} }
} });
return true; return true;
} }

View File

@ -33,9 +33,10 @@ int encode_vim_to_echo(garray_T *const packer,
/// Structure defining state for read_from_list() /// Structure defining state for read_from_list()
typedef struct { typedef struct {
const list_T *const list; ///< List being currently read.
const listitem_T *li; ///< Item currently read. const listitem_T *li; ///< Item currently read.
size_t offset; ///< Byte offset inside the read item. size_t offset; ///< Byte offset inside the read item.
size_t li_length; ///< Length of the string inside the read item. size_t li_length; ///< Length of the string inside the read item.
} ListReaderState; } ListReaderState;
/// Initialize ListReaderState structure /// Initialize ListReaderState structure
@ -43,11 +44,13 @@ static inline ListReaderState encode_init_lrstate(const list_T *const list)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
return (ListReaderState) { return (ListReaderState) {
.li = list->lv_first, .list = list,
.li = tv_list_first(list),
.offset = 0, .offset = 0,
.li_length = (list->lv_first->li_tv.vval.v_string == NULL .li_length = (TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string == NULL
? 0 ? 0
: STRLEN(list->lv_first->li_tv.vval.v_string)), : STRLEN(TV_LIST_ITEM_TV(
tv_list_first(list))->vval.v_string)),
}; };
} }

View File

@ -383,6 +383,22 @@ static inline listitem_T *tv_list_first(const list_T *const l)
return l->lv_first; return l->lv_first;
} }
static inline listitem_T *tv_list_last(const list_T *const l)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
/// Get last list item
///
/// @param[in] l List to get item from.
///
/// @return List item or NULL in case of an empty list.
static inline listitem_T *tv_list_last(const list_T *const l)
{
if (l == NULL) {
return NULL;
}
return l->lv_last;
}
static inline long tv_dict_len(const dict_T *const d) static inline long tv_dict_len(const dict_T *const d)
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;

View File

@ -355,14 +355,14 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
break; break;
} }
case VAR_LIST: { case VAR_LIST: {
if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { if (tv->vval.v_list == NULL || tv_list_len(tv->vval.v_list) == 0) {
TYPVAL_ENCODE_CONV_EMPTY_LIST(tv); TYPVAL_ENCODE_CONV_EMPTY_LIST(tv);
break; break;
} }
const int saved_copyID = tv->vval.v_list->lv_copyID; const int saved_copyID = tv->vval.v_list->lv_copyID;
_TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID, _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID,
kMPConvList); kMPConvList);
TYPVAL_ENCODE_CONV_LIST_START(tv, tv->vval.v_list->lv_len); TYPVAL_ENCODE_CONV_LIST_START(tv, tv_list_len(tv->vval.v_list));
assert(saved_copyID != copyID && saved_copyID != copyID - 1); assert(saved_copyID != copyID && saved_copyID != copyID - 1);
_mp_push(*mpstack, ((MPConvStackVal) { _mp_push(*mpstack, ((MPConvStackVal) {
.type = kMPConvList, .type = kMPConvList,
@ -371,7 +371,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
.data = { .data = {
.l = { .l = {
.list = tv->vval.v_list, .list = tv->vval.v_list,
.li = tv->vval.v_list->lv_first, .li = tv_list_first(tv->vval.v_list),
}, },
}, },
})); }));
@ -440,23 +440,43 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
// bits is not checked), other unsigned and have at most 31 // bits is not checked), other unsigned and have at most 31
// non-zero bits (number of bits is not checked). // non-zero bits (number of bits is not checked).
if (val_di->di_tv.v_type != VAR_LIST if (val_di->di_tv.v_type != VAR_LIST
|| (val_list = val_di->di_tv.vval.v_list) == NULL || tv_list_len(val_list = val_di->di_tv.vval.v_list) != 4) {
|| val_list->lv_len != 4
|| val_list->lv_first->li_tv.v_type != VAR_NUMBER
|| (sign = val_list->lv_first->li_tv.vval.v_number) == 0
|| val_list->lv_first->li_next->li_tv.v_type != VAR_NUMBER
|| (highest_bits =
val_list->lv_first->li_next->li_tv.vval.v_number) < 0
|| val_list->lv_last->li_prev->li_tv.v_type != VAR_NUMBER
|| (high_bits =
val_list->lv_last->li_prev->li_tv.vval.v_number) < 0
|| val_list->lv_last->li_tv.v_type != VAR_NUMBER
|| (low_bits = val_list->lv_last->li_tv.vval.v_number) < 0) {
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }
uint64_t number = ((uint64_t)(((uint64_t)highest_bits) << 62)
| (uint64_t)(((uint64_t)high_bits) << 31) const listitem_T *const sign_li = tv_list_first(val_list);
| (uint64_t)low_bits); if (TV_LIST_ITEM_TV(sign_li)->v_type != VAR_NUMBER
|| (sign = TV_LIST_ITEM_TV(sign_li)->vval.v_number) == 0) {
goto _convert_one_value_regular_dict;
}
const listitem_T *const highest_bits_li = (
TV_LIST_ITEM_NEXT(val_list, sign_li));
if (TV_LIST_ITEM_TV(highest_bits_li)->v_type != VAR_NUMBER
|| ((highest_bits
= TV_LIST_ITEM_TV(highest_bits_li)->vval.v_number)
< 0)) {
goto _convert_one_value_regular_dict;
}
const listitem_T *const high_bits_li = (
TV_LIST_ITEM_NEXT(val_list, highest_bits_li));
if (TV_LIST_ITEM_TV(high_bits_li)->v_type != VAR_NUMBER
|| ((high_bits = TV_LIST_ITEM_TV(high_bits_li)->vval.v_number)
< 0)) {
goto _convert_one_value_regular_dict;
}
const listitem_T *const low_bits_li = tv_list_last(val_list);
if (TV_LIST_ITEM_TV(low_bits_li)->v_type != VAR_NUMBER
|| ((low_bits = TV_LIST_ITEM_TV(low_bits_li)->vval.v_number)
< 0)) {
goto _convert_one_value_regular_dict;
}
const uint64_t number = ((uint64_t)(((uint64_t)highest_bits) << 62)
| (uint64_t)(((uint64_t)high_bits) << 31)
| (uint64_t)low_bits);
if (sign > 0) { if (sign > 0) {
TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, number); TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, number);
} else { } else {
@ -499,8 +519,8 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
_TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list,
lv_copyID, copyID, lv_copyID, copyID,
kMPConvList); kMPConvList);
TYPVAL_ENCODE_CONV_LIST_START(tv, TYPVAL_ENCODE_CONV_LIST_START(
val_di->di_tv.vval.v_list->lv_len); tv, tv_list_len(val_di->di_tv.vval.v_list));
assert(saved_copyID != copyID && saved_copyID != copyID - 1); assert(saved_copyID != copyID && saved_copyID != copyID - 1);
_mp_push(*mpstack, ((MPConvStackVal) { _mp_push(*mpstack, ((MPConvStackVal) {
.tv = tv, .tv = tv,
@ -509,7 +529,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
.data = { .data = {
.l = { .l = {
.list = val_di->di_tv.vval.v_list, .list = val_di->di_tv.vval.v_list,
.li = val_di->di_tv.vval.v_list->lv_first, .li = tv_list_first(val_di->di_tv.vval.v_list),
}, },
}, },
})); }));
@ -520,22 +540,21 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }
list_T *const val_list = val_di->di_tv.vval.v_list; list_T *const val_list = val_di->di_tv.vval.v_list;
if (val_list == NULL || val_list->lv_len == 0) { if (val_list == NULL || tv_list_len(val_list) == 0) {
TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, TYPVAL_ENCODE_NODICT_VAR); TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, TYPVAL_ENCODE_NODICT_VAR);
break; break;
} }
for (const listitem_T *li = val_list->lv_first; li != NULL; TV_LIST_ITER_CONST(val_list, li, {
li = li->li_next) { if (TV_LIST_ITEM_TV(li)->v_type != VAR_LIST
if (li->li_tv.v_type != VAR_LIST || tv_list_len(TV_LIST_ITEM_TV(li)->vval.v_list) != 2) {
|| li->li_tv.vval.v_list->lv_len != 2) {
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }
} });
const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID; const int saved_copyID = val_di->di_tv.vval.v_list->lv_copyID;
_TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID, _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID,
kMPConvPairs); kMPConvPairs);
TYPVAL_ENCODE_CONV_DICT_START(tv, TYPVAL_ENCODE_NODICT_VAR, TYPVAL_ENCODE_CONV_DICT_START(tv, TYPVAL_ENCODE_NODICT_VAR,
val_list->lv_len); tv_list_len(val_list));
assert(saved_copyID != copyID && saved_copyID != copyID - 1); assert(saved_copyID != copyID && saved_copyID != copyID - 1);
_mp_push(*mpstack, ((MPConvStackVal) { _mp_push(*mpstack, ((MPConvStackVal) {
.tv = tv, .tv = tv,
@ -544,7 +563,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
.data = { .data = {
.l = { .l = {
.list = val_list, .list = val_list,
.li = val_list->lv_first, .li = tv_list_first(val_list),
}, },
}, },
})); }));
@ -554,18 +573,22 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
const list_T *val_list; const list_T *val_list;
varnumber_T type; varnumber_T type;
if (val_di->di_tv.v_type != VAR_LIST if (val_di->di_tv.v_type != VAR_LIST
|| (val_list = val_di->di_tv.vval.v_list) == NULL || tv_list_len((val_list = val_di->di_tv.vval.v_list)) != 2
|| val_list->lv_len != 2 || (TV_LIST_ITEM_TV(tv_list_first(val_list))->v_type
|| (val_list->lv_first->li_tv.v_type != VAR_NUMBER) != VAR_NUMBER)
|| (type = val_list->lv_first->li_tv.vval.v_number) > INT8_MAX || ((type
= TV_LIST_ITEM_TV(tv_list_first(val_list))->vval.v_number)
> INT8_MAX)
|| type < INT8_MIN || type < INT8_MIN
|| (val_list->lv_last->li_tv.v_type != VAR_LIST)) { || (TV_LIST_ITEM_TV(tv_list_last(val_list))->v_type
!= VAR_LIST)) {
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }
size_t len; size_t len;
char *buf; char *buf;
if (!encode_vim_list_to_buf(val_list->lv_last->li_tv.vval.v_list, if (!encode_vim_list_to_buf(
&len, &buf)) { TV_LIST_ITEM_TV(tv_list_last(val_list))->vval.v_list, &len,
&buf)) {
goto _convert_one_value_regular_dict; goto _convert_one_value_regular_dict;
} }
TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type); TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type);
@ -674,11 +697,13 @@ typval_encode_stop_converting_one_item:
cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID; cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID;
TYPVAL_ENCODE_CONV_LIST_END(cur_mpsv->tv); TYPVAL_ENCODE_CONV_LIST_END(cur_mpsv->tv);
continue; continue;
} else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { } else if (cur_mpsv->data.l.li
!= tv_list_first(cur_mpsv->data.l.list)) {
TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(cur_mpsv->tv); TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(cur_mpsv->tv);
} }
tv = &cur_mpsv->data.l.li->li_tv; tv = TV_LIST_ITEM_TV(cur_mpsv->data.l.li);
cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; cur_mpsv->data.l.li = TV_LIST_ITEM_NEXT(cur_mpsv->data.l.list,
cur_mpsv->data.l.li);
break; break;
} }
case kMPConvPairs: { case kMPConvPairs: {
@ -687,24 +712,26 @@ typval_encode_stop_converting_one_item:
cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID; cur_mpsv->data.l.list->lv_copyID = cur_mpsv->saved_copyID;
TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR); TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR);
continue; continue;
} else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { } else if (cur_mpsv->data.l.li
!= tv_list_first(cur_mpsv->data.l.list)) {
TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS( TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(
cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR); cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR);
} }
const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; const list_T *const kv_pair = (
TV_LIST_ITEM_TV(cur_mpsv->data.l.li)->vval.v_list);
TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK( TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(
encode_vim_to__error_ret, kv_pair->lv_first->li_tv); encode_vim_to__error_ret, *TV_LIST_ITEM_TV(tv_list_first(kv_pair)));
if (_TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, if (_TYPVAL_ENCODE_CONVERT_ONE_VALUE(
&mpstack, cur_mpsv, TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, cur_mpsv,
&kv_pair->lv_first->li_tv, TV_LIST_ITEM_TV(tv_list_first(kv_pair)), copyID, objname)
copyID, == FAIL) {
objname) == FAIL) {
goto encode_vim_to__error_ret; goto encode_vim_to__error_ret;
} }
TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(cur_mpsv->tv, TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(cur_mpsv->tv,
TYPVAL_ENCODE_NODICT_VAR); TYPVAL_ENCODE_NODICT_VAR);
tv = &kv_pair->lv_last->li_tv; tv = TV_LIST_ITEM_TV(tv_list_last(kv_pair));
cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; cur_mpsv->data.l.li = TV_LIST_ITEM_NEXT(cur_mpsv->data.l.list,
cur_mpsv->data.l.li);
break; break;
} }
case kMPConvPartial: { case kMPConvPartial: {

View File

@ -6334,7 +6334,6 @@ char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
void ex_oldfiles(exarg_T *eap) void ex_oldfiles(exarg_T *eap)
{ {
list_T *l = get_vim_var_list(VV_OLDFILES); list_T *l = get_vim_var_list(VV_OLDFILES);
listitem_T *li;
long nr = 0; long nr = 0;
if (l == NULL) { if (l == NULL) {
@ -6342,19 +6341,22 @@ void ex_oldfiles(exarg_T *eap)
} else { } else {
msg_start(); msg_start();
msg_scroll = true; msg_scroll = true;
for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) { TV_LIST_ITER(l, li, {
if (got_int) {
break;
}
nr++; nr++;
const char *fname = tv_get_string(&li->li_tv); const char *fname = tv_get_string(TV_LIST_ITEM_TV(li));
if (!message_filtered((char_u *)fname)) { if (!message_filtered((char_u *)fname)) {
msg_outnum(nr); msg_outnum(nr);
MSG_PUTS(": "); MSG_PUTS(": ");
msg_outtrans((char_u *)tv_get_string(&li->li_tv)); msg_outtrans((char_u *)tv_get_string(TV_LIST_ITEM_TV(li)));
msg_clr_eos(); msg_clr_eos();
msg_putchar('\n'); msg_putchar('\n');
ui_flush(); // output one line at a time ui_flush(); // output one line at a time
os_breakcheck(); os_breakcheck();
} }
} });
// Assume "got_int" was set to truncate the listing. // Assume "got_int" was set to truncate the listing.
got_int = false; got_int = false;
@ -6364,7 +6366,7 @@ void ex_oldfiles(exarg_T *eap)
quit_more = false; quit_more = false;
nr = prompt_for_number(false); nr = prompt_for_number(false);
msg_starthere(); msg_starthere();
if (nr > 0 && nr <= l->lv_len) { if (nr > 0 && nr <= tv_list_len(l)) {
const char *const p = tv_list_find_str(l, nr - 1); const char *const p = tv_list_find_str(l, nr - 1);
if (p == NULL) { if (p == NULL) {
return; return;

View File

@ -2618,20 +2618,20 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
} }
varnumber_T prev_end = 0; varnumber_T prev_end = 0;
int i = 0; int i = 0;
for (const listitem_T *li = tv.vval.v_list->lv_first; TV_LIST_ITER_CONST(tv.vval.v_list, li, {
li != NULL; li = li->li_next, i++) { if (TV_LIST_ITEM_TV(li)->v_type != VAR_LIST) {
if (li->li_tv.v_type != VAR_LIST) {
PRINT_ERRMSG(_("E5401: List item %i is not a List"), i); PRINT_ERRMSG(_("E5401: List item %i is not a List"), i);
goto color_cmdline_error; goto color_cmdline_error;
} }
const list_T *const l = li->li_tv.vval.v_list; const list_T *const l = TV_LIST_ITEM_TV(li)->vval.v_list;
if (tv_list_len(l) != 3) { if (tv_list_len(l) != 3) {
PRINT_ERRMSG(_("E5402: List item %i has incorrect length: %li /= 3"), PRINT_ERRMSG(_("E5402: List item %i has incorrect length: %li /= 3"),
i, tv_list_len(l)); i, tv_list_len(l));
goto color_cmdline_error; goto color_cmdline_error;
} }
bool error = false; bool error = false;
const varnumber_T start = tv_get_number_chk(&l->lv_first->li_tv, &error); const varnumber_T start = (
tv_get_number_chk(TV_LIST_ITEM_TV(tv_list_first(l)), &error));
if (error) { if (error) {
goto color_cmdline_error; goto color_cmdline_error;
} else if (!(prev_end <= start && start < colored_ccline->cmdlen)) { } else if (!(prev_end <= start && start < colored_ccline->cmdlen)) {
@ -2651,8 +2651,8 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
.attr = 0, .attr = 0,
})); }));
} }
const varnumber_T end = tv_get_number_chk(&l->lv_first->li_next->li_tv, const varnumber_T end = tv_get_number_chk(
&error); TV_LIST_ITEM_TV(TV_LIST_ITEM_NEXT(l, tv_list_first(l))), &error);
if (error) { if (error) {
goto color_cmdline_error; goto color_cmdline_error;
} else if (!(start < end && end <= colored_ccline->cmdlen)) { } else if (!(start < end && end <= colored_ccline->cmdlen)) {
@ -2668,7 +2668,8 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
goto color_cmdline_error; goto color_cmdline_error;
} }
prev_end = end; prev_end = end;
const char *const group = tv_get_string_chk(&l->lv_last->li_tv); const char *const group = tv_get_string_chk(
TV_LIST_ITEM_TV(tv_list_last(l)));
if (group == NULL) { if (group == NULL) {
goto color_cmdline_error; goto color_cmdline_error;
} }
@ -2679,7 +2680,7 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
.end = end, .end = end,
.attr = attr, .attr = attr,
})); }));
} });
if (prev_end < colored_ccline->cmdlen) { if (prev_end < colored_ccline->cmdlen) {
kv_push(ccline_colors->colors, ((CmdlineColorChunk) { kv_push(ccline_colors->colors, ((CmdlineColorChunk) {
.start = prev_end, .start = prev_end,
@ -5021,24 +5022,24 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file,
*/ */
static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file) static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file)
{ {
list_T *retlist; list_T *const retlist = call_user_expand_func(
listitem_T *li; (user_expand_func_T)call_func_retlist, xp, num_file, file);
garray_T ga;
retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp,
num_file, file);
if (retlist == NULL) { if (retlist == NULL) {
return FAIL; return FAIL;
} }
garray_T ga;
ga_init(&ga, (int)sizeof(char *), 3); ga_init(&ga, (int)sizeof(char *), 3);
/* Loop over the items in the list. */ // Loop over the items in the list.
for (li = retlist->lv_first; li != NULL; li = li->li_next) { TV_LIST_ITER_CONST(retlist, li, {
if (li->li_tv.v_type != VAR_STRING || li->li_tv.vval.v_string == NULL) if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING
continue; /* Skip non-string items and empty strings */ || TV_LIST_ITEM_TV(li)->vval.v_string == NULL) {
continue; // Skip non-string items and empty strings.
}
GA_APPEND(char_u *, &ga, vim_strsave(li->li_tv.vval.v_string)); GA_APPEND(char *, &ga, xstrdup(
} (const char *)TV_LIST_ITEM_TV(li)->vval.v_string));
});
tv_list_unref(retlist); tv_list_unref(retlist);
*file = ga.ga_data; *file = ga.ga_data;

View File

@ -214,9 +214,9 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
list_T *const kv_pair = tv_list_alloc(); list_T *const kv_pair = tv_list_alloc();
tv_list_append_list(cur.tv->vval.v_list, kv_pair); tv_list_append_list(cur.tv->vval.v_list, kv_pair);
listitem_T *const key = tv_list_item_alloc(); listitem_T *const key = tv_list_item_alloc();
key->li_tv = decode_string(s, len, kTrue, false, false); *TV_LIST_ITEM_TV(key) = decode_string(s, len, kTrue, false, false);
tv_list_append(kv_pair, key); tv_list_append(kv_pair, key);
if (key->li_tv.v_type == VAR_UNKNOWN) { if (TV_LIST_ITEM_TV(key)->v_type == VAR_UNKNOWN) {
ret = false; ret = false;
tv_list_unref(kv_pair); tv_list_unref(kv_pair);
continue; continue;
@ -224,7 +224,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
listitem_T *const val = tv_list_item_alloc(); listitem_T *const val = tv_list_item_alloc();
tv_list_append(kv_pair, val); tv_list_append(kv_pair, val);
kv_push(stack, cur); kv_push(stack, cur);
cur = (TVPopStackItem) { &val->li_tv, false, false, 0 }; cur = (TVPopStackItem) { TV_LIST_ITEM_TV(val), false, false, 0 };
} else { } else {
dictitem_T *const di = tv_dict_item_alloc_len(s, len); dictitem_T *const di = tv_dict_item_alloc_len(s, len);
if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) { if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) {
@ -239,7 +239,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
} }
} else { } else {
assert(cur.tv->v_type == VAR_LIST); assert(cur.tv->v_type == VAR_LIST);
lua_rawgeti(lstate, -1, cur.tv->vval.v_list->lv_len + 1); lua_rawgeti(lstate, -1, tv_list_len(cur.tv->vval.v_list) + 1);
if (lua_isnil(lstate, -1)) { if (lua_isnil(lstate, -1)) {
lua_pop(lstate, 2); lua_pop(lstate, 2);
continue; continue;
@ -247,7 +247,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
listitem_T *const li = tv_list_item_alloc(); listitem_T *const li = tv_list_item_alloc();
tv_list_append(cur.tv->vval.v_list, li); tv_list_append(cur.tv->vval.v_list, li);
kv_push(stack, cur); kv_push(stack, cur);
cur = (TVPopStackItem) { &li->li_tv, false, false, 0 }; cur = (TVPopStackItem) { TV_LIST_ITEM_TV(li), false, false, 0 };
} }
} }
assert(!cur.container); assert(!cur.container);

View File

@ -4854,9 +4854,8 @@ static void *get_reg_wrap_one_line(char_u *s, int flags)
if (!(flags & kGRegList)) { if (!(flags & kGRegList)) {
return s; return s;
} }
list_T *list = tv_list_alloc(); list_T *const list = tv_list_alloc();
tv_list_append_string(list, NULL, 0); tv_list_append_allocated_string(list, (char *)s);
list->lv_first->li_tv.vval.v_string = s;
return list; return list;
} }
@ -5610,12 +5609,13 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
list_T *res = result.vval.v_list; list_T *res = result.vval.v_list;
list_T *lines = NULL; list_T *lines = NULL;
if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) { if (tv_list_len(res) == 2
lines = res->lv_first->li_tv.vval.v_list; && TV_LIST_ITEM_TV(tv_list_first(res))->v_type == VAR_LIST) {
if (res->lv_last->li_tv.v_type != VAR_STRING) { lines = TV_LIST_ITEM_TV(tv_list_first(res))->vval.v_list;
if (TV_LIST_ITEM_TV(tv_list_last(res))->v_type != VAR_STRING) {
goto err; goto err;
} }
char_u *regtype = res->lv_last->li_tv.vval.v_string; char_u *regtype = TV_LIST_ITEM_TV(tv_list_last(res))->vval.v_string;
if (regtype == NULL || strlen((char*)regtype) > 1) { if (regtype == NULL || strlen((char*)regtype) > 1) {
goto err; goto err;
} }
@ -5641,20 +5641,21 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
reg->y_type = kMTUnknown; reg->y_type = kMTUnknown;
} }
reg->y_array = xcalloc((size_t)lines->lv_len, sizeof(uint8_t *)); reg->y_array = xcalloc((size_t)tv_list_len(lines), sizeof(char_u *));
reg->y_size = (size_t)lines->lv_len; reg->y_size = (size_t)tv_list_len(lines);
reg->additional_data = NULL; reg->additional_data = NULL;
reg->timestamp = 0; reg->timestamp = 0;
// Timestamp is not saved for clipboard registers because clipboard registers // Timestamp is not saved for clipboard registers because clipboard registers
// are not saved in the ShaDa file. // are not saved in the ShaDa file.
int i = 0; int i = 0;
for (listitem_T *li = lines->lv_first; li != NULL; li = li->li_next) { TV_LIST_ITER_CONST(lines, li, {
if (li->li_tv.v_type != VAR_STRING) { if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
goto err; goto err;
} }
reg->y_array[i++] = (char_u *)xstrdupnul((char *)li->li_tv.vval.v_string); reg->y_array[i++] = (char_u *)xstrdupnul(
} (const char *)TV_LIST_ITEM_TV(li)->vval.v_string);
});
if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) { if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) {
// a known-to-be charwise yank might have a final linebreak // a known-to-be charwise yank might have a final linebreak

View File

@ -156,6 +156,7 @@ typedef struct {
FILE *fd; FILE *fd;
typval_T *tv; typval_T *tv;
char_u *p_str; char_u *p_str;
list_T *p_list;
listitem_T *p_li; listitem_T *p_li;
buf_T *buf; buf_T *buf;
linenr_T buflnum; linenr_T buflnum;
@ -516,17 +517,17 @@ static int qf_get_next_list_line(qfstate_T *state)
// Get the next line from the supplied list // Get the next line from the supplied list
while (p_li != NULL while (p_li != NULL
&& (p_li->li_tv.v_type != VAR_STRING && (TV_LIST_ITEM_TV(p_li)->v_type != VAR_STRING
|| p_li->li_tv.vval.v_string == NULL)) { || TV_LIST_ITEM_TV(p_li)->vval.v_string == NULL)) {
p_li = p_li->li_next; // Skip non-string items p_li = TV_LIST_ITEM_NEXT(state->p_list, p_li); // Skip non-string items.
} }
if (p_li == NULL) { // End of the list if (p_li == NULL) { // End of the list.
state->p_li = NULL; state->p_li = NULL;
return QF_END_OF_INPUT; return QF_END_OF_INPUT;
} }
len = STRLEN(p_li->li_tv.vval.v_string); len = STRLEN(TV_LIST_ITEM_TV(p_li)->vval.v_string);
if (len > IOSIZE - 2) { if (len > IOSIZE - 2) {
state->linebuf = qf_grow_linebuf(state, len); state->linebuf = qf_grow_linebuf(state, len);
} else { } else {
@ -534,9 +535,10 @@ static int qf_get_next_list_line(qfstate_T *state)
state->linelen = len; state->linelen = len;
} }
STRLCPY(state->linebuf, p_li->li_tv.vval.v_string, state->linelen + 1); STRLCPY(state->linebuf, TV_LIST_ITEM_TV(p_li)->vval.v_string,
state->linelen + 1);
state->p_li = p_li->li_next; // next item state->p_li = TV_LIST_ITEM_NEXT(state->p_list, p_li);
return QF_OK; return QF_OK;
} }
@ -983,7 +985,7 @@ qf_init_ext(
) )
{ {
qfstate_T state = { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, qfstate_T state = { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
NULL, 0, 0 }; NULL, NULL, 0, 0 };
qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 }; qffields_T fields = { NULL, NULL, 0, 0L, 0, false, NULL, 0, 0, 0 };
qfline_T *old_last = NULL; qfline_T *old_last = NULL;
bool adding = false; bool adding = false;
@ -1064,7 +1066,8 @@ qf_init_ext(
if (tv->v_type == VAR_STRING) { if (tv->v_type == VAR_STRING) {
state.p_str = tv->vval.v_string; state.p_str = tv->vval.v_string;
} else if (tv->v_type == VAR_LIST) { } else if (tv->v_type == VAR_LIST) {
state.p_li = tv->vval.v_list->lv_first; state.p_list = tv->vval.v_list;
state.p_li = tv_list_first(tv->vval.v_list);
} }
state.tv = tv; state.tv = tv;
} }
@ -4100,7 +4103,6 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
int action) int action)
{ {
listitem_T *li;
dict_T *d; dict_T *d;
qfline_T *old_last = NULL; qfline_T *old_last = NULL;
int retval = OK; int retval = OK;
@ -4117,13 +4119,15 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
qf_store_title(qi, title); qf_store_title(qi, title);
} }
for (li = list->lv_first; li != NULL; li = li->li_next) { TV_LIST_ITER_CONST(list, li, {
if (li->li_tv.v_type != VAR_DICT) if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT) {
continue; /* Skip non-dict items */ continue; // Skip non-dict items.
}
d = li->li_tv.vval.v_dict; d = TV_LIST_ITEM_TV(li)->vval.v_dict;
if (d == NULL) if (d == NULL) {
continue; continue;
}
char *const filename = tv_dict_get_string(d, "filename", true); char *const filename = tv_dict_get_string(d, "filename", true);
int bufnum = (int)tv_dict_get_number(d, "bufnr"); int bufnum = (int)tv_dict_get_number(d, "bufnr");
@ -4175,7 +4179,7 @@ static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
retval = FAIL; retval = FAIL;
break; break;
} }
} });
if (qi->qf_lists[qi->qf_curlist].qf_index == 0) { if (qi->qf_lists[qi->qf_curlist].qf_index == 0) {
// no valid entry // no valid entry

View File

@ -6477,10 +6477,6 @@ static regsubmatch_T rsm; // can only be used when can_f_submatch is true
/// vim_regsub_both(). /// vim_regsub_both().
static int fill_submatch_list(int argc, typval_T *argv, int argcount) static int fill_submatch_list(int argc, typval_T *argv, int argcount)
{ {
listitem_T *li;
int i;
char_u *s;
if (argcount == 0) { if (argcount == 0) {
// called function doesn't take an argument // called function doesn't take an argument
return 0; return 0;
@ -6490,28 +6486,26 @@ static int fill_submatch_list(int argc, typval_T *argv, int argcount)
init_static_list((staticList10_T *)(argv->vval.v_list)); init_static_list((staticList10_T *)(argv->vval.v_list));
// There are always 10 list items in staticList10_T. // There are always 10 list items in staticList10_T.
li = argv->vval.v_list->lv_first; listitem_T *li = tv_list_first(argv->vval.v_list);
for (i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
s = rsm.sm_match->startp[i]; char_u *s = rsm.sm_match->startp[i];
if (s == NULL || rsm.sm_match->endp[i] == NULL) { if (s == NULL || rsm.sm_match->endp[i] == NULL) {
s = NULL; s = NULL;
} else { } else {
s = vim_strnsave(s, (int)(rsm.sm_match->endp[i] - s)); s = vim_strnsave(s, (int)(rsm.sm_match->endp[i] - s));
} }
li->li_tv.v_type = VAR_STRING; TV_LIST_ITEM_TV(li)->v_type = VAR_STRING;
li->li_tv.vval.v_string = s; TV_LIST_ITEM_TV(li)->vval.v_string = s;
li = li->li_next; li = TV_LIST_ITEM_NEXT(argv->vval.v_list, li);
} }
return 1; return 1;
} }
static void clear_submatch_list(staticList10_T *sl) static void clear_submatch_list(staticList10_T *sl)
{ {
int i; TV_LIST_ITER(&sl->sl_list, li, {
xfree(TV_LIST_ITEM_TV(li)->vval.v_string);
for (i = 0; i < 10; i++) { });
xfree(sl->sl_items[i].li_tv.vval.v_string);
}
} }
/// vim_regsub() - perform substitutions after a vim_regexec() or /// vim_regsub() - perform substitutions after a vim_regexec() or
@ -6651,6 +6645,7 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
rettv.vval.v_string = NULL; rettv.vval.v_string = NULL;
argv[0].v_type = VAR_LIST; argv[0].v_type = VAR_LIST;
argv[0].vval.v_list = &matchList.sl_list; argv[0].vval.v_list = &matchList.sl_list;
// FIXME: Abstract away
matchList.sl_list.lv_len = 0; matchList.sl_list.lv_len = 0;
if (expr->v_type == VAR_FUNC) { if (expr->v_type == VAR_FUNC) {
s = expr->vval.v_string; s = expr->vval.v_string;

View File

@ -1180,8 +1180,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
list_T *oldfiles_list = get_vim_var_list(VV_OLDFILES); list_T *oldfiles_list = get_vim_var_list(VV_OLDFILES);
const bool force = flags & kShaDaForceit; const bool force = flags & kShaDaForceit;
const bool get_old_files = (flags & (kShaDaGetOldfiles | kShaDaForceit) const bool get_old_files = (flags & (kShaDaGetOldfiles | kShaDaForceit)
&& (force || oldfiles_list == NULL && (force || tv_list_len(oldfiles_list) == 0));
|| oldfiles_list->lv_len == 0));
const bool want_marks = flags & kShaDaWantMarks; const bool want_marks = flags & kShaDaWantMarks;
const unsigned srni_flags = (unsigned) ( const unsigned srni_flags = (unsigned) (
(flags & kShaDaWantInfo (flags & kShaDaWantInfo
@ -1599,13 +1598,13 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
#define DUMP_ADDITIONAL_ELEMENTS(src, what) \ #define DUMP_ADDITIONAL_ELEMENTS(src, what) \
do { \ do { \
if ((src) != NULL) { \ if ((src) != NULL) { \
for (listitem_T *li = (src)->lv_first; li != NULL; li = li->li_next) { \ TV_LIST_ITER((src), li, { \
if (encode_vim_to_msgpack(spacker, &li->li_tv, \ if (encode_vim_to_msgpack(spacker, TV_LIST_ITEM_TV(li), \
_("additional elements of ShaDa " what)) \ _("additional elements of ShaDa " what)) \
== FAIL) { \ == FAIL) { \
goto shada_pack_entry_error; \ goto shada_pack_entry_error; \
} \ } \
} \ }); \
} \ } \
} while (0) } while (0)
#define DUMP_ADDITIONAL_DATA(src, what) \ #define DUMP_ADDITIONAL_DATA(src, what) \
@ -1648,9 +1647,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
const bool is_hist_search = const bool is_hist_search =
entry.data.history_item.histtype == HIST_SEARCH; entry.data.history_item.histtype == HIST_SEARCH;
const size_t arr_size = 2 + (size_t) is_hist_search + (size_t) ( const size_t arr_size = 2 + (size_t) is_hist_search + (size_t) (
entry.data.history_item.additional_elements == NULL tv_list_len(entry.data.history_item.additional_elements));
? 0
: entry.data.history_item.additional_elements->lv_len);
msgpack_pack_array(spacker, arr_size); msgpack_pack_array(spacker, arr_size);
msgpack_pack_uint8(spacker, entry.data.history_item.histtype); msgpack_pack_uint8(spacker, entry.data.history_item.histtype);
PACK_BIN(cstr_as_string(entry.data.history_item.string)); PACK_BIN(cstr_as_string(entry.data.history_item.string));
@ -1663,9 +1660,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
} }
case kSDItemVariable: { case kSDItemVariable: {
const size_t arr_size = 2 + (size_t) ( const size_t arr_size = 2 + (size_t) (
entry.data.global_var.additional_elements == NULL tv_list_len(entry.data.global_var.additional_elements));
? 0
: entry.data.global_var.additional_elements->lv_len);
msgpack_pack_array(spacker, arr_size); msgpack_pack_array(spacker, arr_size);
const String varname = cstr_as_string(entry.data.global_var.name); const String varname = cstr_as_string(entry.data.global_var.name);
PACK_BIN(varname); PACK_BIN(varname);
@ -1685,9 +1680,7 @@ static ShaDaWriteResult shada_pack_entry(msgpack_packer *const packer,
} }
case kSDItemSubString: { case kSDItemSubString: {
const size_t arr_size = 1 + (size_t) ( const size_t arr_size = 1 + (size_t) (
entry.data.sub_string.additional_elements == NULL tv_list_len(entry.data.sub_string.additional_elements));
? 0
: entry.data.sub_string.additional_elements->lv_len);
msgpack_pack_array(spacker, arr_size); msgpack_pack_array(spacker, arr_size);
PACK_BIN(cstr_as_string(entry.data.sub_string.sub)); PACK_BIN(cstr_as_string(entry.data.sub_string.sub));
DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements, DUMP_ADDITIONAL_ELEMENTS(entry.data.sub_string.additional_elements,

View File

@ -3213,26 +3213,25 @@ spell_find_suggest (
// Find suggestions by evaluating expression "expr". // Find suggestions by evaluating expression "expr".
static void spell_suggest_expr(suginfo_T *su, char_u *expr) static void spell_suggest_expr(suginfo_T *su, char_u *expr)
{ {
list_T *list;
listitem_T *li;
int score; int score;
const char *p; const char *p;
// The work is split up in a few parts to avoid having to export // The work is split up in a few parts to avoid having to export
// suginfo_T. // suginfo_T.
// First evaluate the expression and get the resulting list. // First evaluate the expression and get the resulting list.
list = eval_spell_expr(su->su_badword, expr); list_T *const list = eval_spell_expr(su->su_badword, expr);
if (list != NULL) { if (list != NULL) {
// Loop over the items in the list. // Loop over the items in the list.
for (li = list->lv_first; li != NULL; li = li->li_next) TV_LIST_ITER(list, li, {
if (li->li_tv.v_type == VAR_LIST) { if (TV_LIST_ITEM_TV(li)->v_type == VAR_LIST) {
// Get the word and the score from the items. // Get the word and the score from the items.
score = get_spellword(li->li_tv.vval.v_list, &p); score = get_spellword(TV_LIST_ITEM_TV(li)->vval.v_list, &p);
if (score >= 0 && score <= su->su_maxscore) { if (score >= 0 && score <= su->su_maxscore) {
add_suggestion(su, &su->su_ga, (const char_u *)p, su->su_badlen, add_suggestion(su, &su->su_ga, (const char_u *)p, su->su_badlen,
score, 0, true, su->su_sallang, false); score, 0, true, su->su_sallang, false);
} }
} }
});
tv_list_unref(list); tv_list_unref(list);
} }

View File

@ -5579,30 +5579,26 @@ int match_add(win_T *wp, const char *const grp, const char *const pat,
// Set up position matches // Set up position matches
if (pos_list != NULL) if (pos_list != NULL)
{ {
linenr_T toplnum = 0; linenr_T toplnum = 0;
linenr_T botlnum = 0; linenr_T botlnum = 0;
listitem_T *li;
int i;
for (i = 0, li = pos_list->lv_first; li != NULL && i < MAXPOSMATCH; int i = 0;
i++, li = li->li_next) { TV_LIST_ITER(pos_list, li, {
linenr_T lnum = 0; linenr_T lnum = 0;
colnr_T col = 0; colnr_T col = 0;
int len = 1; int len = 1;
list_T *subl;
listitem_T *subli;
bool error = false; bool error = false;
if (li->li_tv.v_type == VAR_LIST) { if (TV_LIST_ITEM_TV(li)->v_type == VAR_LIST) {
subl = li->li_tv.vval.v_list; const list_T *const subl = TV_LIST_ITEM_TV(li)->vval.v_list;
if (subl == NULL) { if (subl == NULL) {
goto fail; goto fail;
} }
subli = subl->lv_first; const listitem_T *subli = tv_list_first(subl);
if (subli == NULL) { if (subli == NULL) {
goto fail; goto fail;
} }
lnum = tv_get_number_chk(&subli->li_tv, &error); lnum = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error);
if (error) { if (error) {
goto fail; goto fail;
} }
@ -5611,15 +5607,15 @@ int match_add(win_T *wp, const char *const grp, const char *const pat,
continue; continue;
} }
m->pos.pos[i].lnum = lnum; m->pos.pos[i].lnum = lnum;
subli = subli->li_next; subli = TV_LIST_ITEM_NEXT(subl, subli);
if (subli != NULL) { if (subli != NULL) {
col = tv_get_number_chk(&subli->li_tv, &error); col = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error);
if (error) { if (error) {
goto fail; goto fail;
} }
subli = subli->li_next; subli = TV_LIST_ITEM_NEXT(subl, subli);
if (subli != NULL) { if (subli != NULL) {
len = tv_get_number_chk(&subli->li_tv, &error); len = tv_get_number_chk(TV_LIST_ITEM_TV(subli), &error);
if (error) { if (error) {
goto fail; goto fail;
} }
@ -5627,12 +5623,12 @@ int match_add(win_T *wp, const char *const grp, const char *const pat,
} }
m->pos.pos[i].col = col; m->pos.pos[i].col = col;
m->pos.pos[i].len = len; m->pos.pos[i].len = len;
} else if (li->li_tv.v_type == VAR_NUMBER) { } else if (TV_LIST_ITEM_TV(li)->v_type == VAR_NUMBER) {
if (li->li_tv.vval.v_number == 0) { if (TV_LIST_ITEM_TV(li)->vval.v_number == 0) {
--i; i--;
continue; continue;
} }
m->pos.pos[i].lnum = li->li_tv.vval.v_number; m->pos.pos[i].lnum = TV_LIST_ITEM_TV(li)->vval.v_number;
m->pos.pos[i].col = 0; m->pos.pos[i].col = 0;
m->pos.pos[i].len = 0; m->pos.pos[i].len = 0;
} else { } else {
@ -5645,7 +5641,11 @@ int match_add(win_T *wp, const char *const grp, const char *const pat,
if (botlnum == 0 || lnum >= botlnum) { if (botlnum == 0 || lnum >= botlnum) {
botlnum = lnum + 1; botlnum = lnum + 1;
} }
} i++;
if (i >= MAXPOSMATCH) {
break;
}
});
// Calculate top and bottom lines for redrawing area // Calculate top and bottom lines for redrawing area
if (toplnum != 0){ if (toplnum != 0){

View File

@ -118,6 +118,8 @@ describe('NULL', function()
null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0) null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0)
null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {}) null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {})
null_expr_test('does not crash setline', 'setline(1, L)', 0, 0) null_expr_test('does not crash setline', 'setline(1, L)', 0, 0)
null_test('does not make Neovim crash when v:oldfiles gets assigned to that', ':let v:oldfiles = L|oldfiles', 0)
-- FIXME Add test for complete(, L)
end) end)
describe('dict', function() describe('dict', function()
it('does not crash when indexing NULL dict', function() it('does not crash when indexing NULL dict', function()