diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/private/helpers.c | 42 | ||||
-rw-r--r-- | src/nvim/eval.c | 212 | ||||
-rw-r--r-- | src/nvim/eval/encode.c | 116 | ||||
-rw-r--r-- | src/nvim/eval/typval_encode.c.h | 165 | ||||
-rw-r--r-- | src/nvim/eval/typval_encode.h | 9 |
5 files changed, 317 insertions, 227 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index a195b8c0a1..5bd76bc238 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -326,21 +326,21 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) #define TYPVAL_ENCODE_ALLOW_SPECIALS false -#define TYPVAL_ENCODE_CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL(tv) \ kv_push(edata->stack, NIL) -#define TYPVAL_ENCODE_CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ kv_push(edata->stack, BOOLEAN_OBJ((Boolean)(num))) -#define TYPVAL_ENCODE_CONV_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ kv_push(edata->stack, INTEGER_OBJ((Integer)(num))) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER -#define TYPVAL_ENCODE_CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ kv_push(edata->stack, FLOATING_OBJ((Float)(flt))) -#define TYPVAL_ENCODE_CONV_STRING(str, len) \ +#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \ do { \ const size_t len_ = (size_t)(len); \ const char *const str_ = (const char *)(str); \ @@ -353,20 +353,20 @@ void set_option_to(void *to, int type, String name, Object value, Error *err) #define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING -#define TYPVAL_ENCODE_CONV_EXT_STRING(str, len, type) \ +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, str, len, type) \ TYPVAL_ENCODE_CONV_NIL() -#define TYPVAL_ENCODE_CONV_FUNC_START(fun, is_partial, pt) \ +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ TYPVAL_ENCODE_CONV_NIL() -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(len) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(len) -#define TYPVAL_ENCODE_CONV_FUNC_END() +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) -#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \ +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ kv_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 }))) -#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \ kv_push(edata->stack, \ DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 }))) @@ -381,7 +381,7 @@ static inline void typval_encode_list_start(EncodedData *const edata, }))); } -#define TYPVAL_ENCODE_CONV_LIST_START(len) \ +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ typval_encode_list_start(edata, (size_t)(len)) static inline void typval_encode_between_list_items(EncodedData *const edata) @@ -394,7 +394,7 @@ static inline void typval_encode_between_list_items(EncodedData *const edata) list->data.array.items[list->data.array.size++] = item; } -#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() \ +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ typval_encode_between_list_items(edata) static inline void typval_encode_list_end(EncodedData *const edata) @@ -407,7 +407,7 @@ static inline void typval_encode_list_end(EncodedData *const edata) #endif } -#define TYPVAL_ENCODE_CONV_LIST_END() \ +#define TYPVAL_ENCODE_CONV_LIST_END(tv) \ typval_encode_list_end(edata) static inline void typval_encode_dict_start(EncodedData *const edata, @@ -421,10 +421,10 @@ static inline void typval_encode_dict_start(EncodedData *const edata, }))); } -#define TYPVAL_ENCODE_CONV_DICT_START(len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ typval_encode_dict_start(edata, (size_t)(len)) -#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, kv_pair) static inline void typval_encode_after_key(EncodedData *const edata) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL @@ -443,7 +443,7 @@ static inline void typval_encode_after_key(EncodedData *const edata) } } -#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() \ +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \ typval_encode_after_key(edata) static inline void typval_encode_between_dict_items(EncodedData *const edata) @@ -456,7 +456,7 @@ static inline void typval_encode_between_dict_items(EncodedData *const edata) dict->data.dictionary.items[dict->data.dictionary.size++].value = val; } -#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() \ +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ typval_encode_between_dict_items(edata) static inline void typval_encode_dict_end(EncodedData *const edata) @@ -469,7 +469,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) #endif } -#define TYPVAL_ENCODE_CONV_DICT_END() \ +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ typval_encode_dict_end(edata) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ @@ -506,7 +506,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata) #undef TYPVAL_ENCODE_CONV_DICT_END #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS -#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK #undef TYPVAL_ENCODE_CONV_LIST_END #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_RECURSE diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7b1365785f..79134d748a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -19034,147 +19034,185 @@ void free_tv(typval_T *varp) #define TYPVAL_ENCODE_ALLOW_SPECIALS false -#define TYPVAL_ENCODE_CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL(tv) \ do { \ tv->vval.v_special = kSpecialVarFalse; \ tv->v_lock = VAR_UNLOCKED; \ } while (0) -#define TYPVAL_ENCODE_CONV_BOOL(ignored) \ - TYPVAL_ENCODE_CONV_NIL() +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ + TYPVAL_ENCODE_CONV_NIL(tv) -#define TYPVAL_ENCODE_CONV_NUMBER(ignored) \ +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ do { \ - (void)ignored; \ + (void)num; \ tv->vval.v_number = 0; \ tv->v_lock = VAR_UNLOCKED; \ } while (0) -#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(ignored) \ - assert(false) +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) -#define TYPVAL_ENCODE_CONV_FLOAT(ignored) \ +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ do { \ tv->vval.v_float = 0; \ tv->v_lock = VAR_UNLOCKED; \ } while (0) -#define TYPVAL_ENCODE_CONV_STRING(str, ignored) \ +#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ - xfree(str); \ + xfree(buf); \ tv->vval.v_string = NULL; \ tv->v_lock = VAR_UNLOCKED; \ } while (0) -#define TYPVAL_ENCODE_CONV_STR_STRING(ignored1, ignored2) +#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) -#define TYPVAL_ENCODE_CONV_EXT_STRING(ignored1, ignored2, ignored3) +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) -#define TYPVAL_ENCODE_CONV_FUNC_START(fun, is_partial, pt) \ +static inline int _nothing_conv_func_start(typval_T *const tv, + char_u *const fun) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1) +{ + tv->v_lock = VAR_UNLOCKED; + if (tv->v_type == VAR_PARTIAL) { + partial_T *const pt_ = tv->vval.v_partial; + if (pt_ != NULL && pt_->pt_refcount > 1) { + pt_->pt_refcount--; + tv->vval.v_partial = NULL; + return OK; + } + } else { + func_unref(fun); + if (fun != empty_string) { + xfree(fun); + } + tv->vval.v_string = NULL; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ do { \ - partial_T *const pt_ = (pt); \ - tv->v_lock = VAR_UNLOCKED; \ - if (is_partial) { \ - if (pt_ != NULL && pt_->pt_refcount > 1) { \ - pt_->pt_refcount--; \ - tv->vval.v_partial = NULL; \ - return OK; \ - } \ - } else { \ - func_unref(fun); \ - if (fun != empty_string) { \ - xfree(fun); \ - } \ - tv->vval.v_string = NULL; \ + if (_nothing_conv_func_start(tv, fun) != NOTDONE) { \ + return OK; \ } \ } while (0) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(len) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(len) -#define TYPVAL_ENCODE_CONV_FUNC_END() \ - do { \ - assert(cur_mpsv != NULL || tv->v_type == VAR_FUNC); \ - if (cur_mpsv != NULL && cur_mpsv->type == kMPConvPartial) { \ - typval_T *const cur_tv = cur_mpsv->tv; \ - partial_T *const pt = cur_mpsv->data.p.pt; \ - partial_unref(pt); \ - if (cur_tv != NULL) { \ - cur_tv->vval.v_partial = NULL; \ - cur_tv->v_lock = VAR_UNLOCKED; \ - } \ - } \ - } while (0) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) -#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \ +static inline void _nothing_conv_func_end(typval_T *const tv) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL +{ + if (tv->v_type == VAR_PARTIAL) { + partial_T *const pt = tv->vval.v_partial; + if (pt == NULL) { + return; + } + // Dictionaly should already be freed by the time. + assert(pt->pt_dict == NULL); + // As well as all arguments. + pt->pt_argc = 0; + assert(pt->pt_refcount <= 1); + partial_unref(pt); + tv->vval.v_partial = NULL; + assert(tv->v_lock == VAR_UNLOCKED); + } +} +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) _nothing_conv_func_end(tv) + +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ do { \ list_unref(tv->vval.v_list); \ tv->vval.v_list = NULL; \ tv->v_lock = VAR_UNLOCKED; \ } while (0) -#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \ do { \ dict_unref(tv->vval.v_dict); \ tv->vval.v_dict = NULL; \ tv->v_lock = VAR_UNLOCKED; \ } while (0) -#define TYPVAL_ENCODE_CONV_LIST_START(ignored) \ +static inline int _nothing_conv_list_start(typval_T *const tv) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (tv == NULL) { + return NOTDONE; + } + tv->v_lock = VAR_UNLOCKED; + if (tv->vval.v_list->lv_refcount > 1) { + tv->vval.v_list->lv_refcount--; + tv->vval.v_list = NULL; + return OK; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ do { \ - tv->v_lock = VAR_UNLOCKED; \ - if (tv->vval.v_list->lv_refcount > 1) { \ - tv->vval.v_list->lv_refcount--; \ - tv->vval.v_list = NULL; \ + if (_nothing_conv_list_start(tv) != NOTDONE) { \ return OK; \ } \ } while (0) -#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) -#define TYPVAL_ENCODE_CONV_LIST_END() \ - do { \ - if (cur_mpsv->type == kMPConvPartialList) { \ - break; \ - } \ - typval_T *const cur_tv = cur_mpsv->tv; \ - list_T *const list = cur_mpsv->data.l.list; \ - list_unref(list); \ - if (cur_tv != NULL) { \ - assert(list == cur_tv->vval.v_list); \ - assert(cur_tv->v_type == VAR_LIST); \ - cur_tv->vval.v_list = NULL; \ - } \ - } while (0) +static inline void _nothing_conv_list_end(typval_T *const tv) + FUNC_ATTR_ALWAYS_INLINE +{ + if (tv == NULL) { + return; + } + assert(tv->v_type == VAR_LIST); + list_T *const list = tv->vval.v_list; + list_unref(list); + tv->vval.v_list = NULL; +} +#define TYPVAL_ENCODE_CONV_LIST_END(tv) _nothing_conv_list_end(tv) -#define TYPVAL_ENCODE_CONV_DICT_START(ignored) \ +static inline int _nothing_conv_dict_start(typval_T *const tv, + dict_T **const dictp, + const void *const nodictvar) + FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (tv != NULL) { + tv->v_lock = VAR_UNLOCKED; + } + if ((const void *)dictp != nodictvar && (*dictp)->dv_refcount > 1) { + (*dictp)->dv_refcount--; + *dictp = NULL; + return OK; + } + return NOTDONE; +} +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ do { \ - tv->v_lock = VAR_UNLOCKED; \ - if (tv->vval.v_dict->dv_refcount > 1) { \ - tv->vval.v_dict->dv_refcount--; \ - tv->vval.v_dict = NULL; \ + if (_nothing_conv_dict_start(tv, (dict_T **)&dict, \ + (void *)&TYPVAL_ENCODE_NODICT_VAR) \ + != NOTDONE) { \ return OK; \ } \ } while (0) -#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(ignored1, ignored2) - -#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() - -#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(tv, dict) +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) -#define TYPVAL_ENCODE_CONV_DICT_END() \ - do { \ - typval_T *const cur_tv = cur_mpsv->tv; \ - dict_T *const dict = cur_mpsv->data.d.dict; \ - dict_unref(cur_tv->vval.v_dict); \ - if (cur_tv != NULL) { \ - assert(dict == cur_tv->vval.v_dict); \ - assert(cur_tv->v_type == VAR_DICT); \ - cur_tv->vval.v_dict = NULL; \ - } \ - } while (0) +static inline void _nothing_conv_dict_end(typval_T *const tv, + dict_T **const dictp, + const void *const nodictvar) + FUNC_ATTR_ALWAYS_INLINE +{ + if ((const void *)dictp != nodictvar) { + dict_unref(*dictp); + *dictp = NULL; + } +} +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ + _nothing_conv_dict_end(tv, (dict_T **)&dict, \ + (void *)&TYPVAL_ENCODE_NODICT_VAR) -#define TYPVAL_ENCODE_CONV_RECURSE(ignored1, ignored2) +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) #define TYPVAL_ENCODE_SCOPE static #define TYPVAL_ENCODE_NAME nothing @@ -19207,7 +19245,7 @@ void free_tv(typval_T *varp) #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_LIST_END #undef TYPVAL_ENCODE_CONV_DICT_START -#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_DICT_END diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 38f0863195..73133b7b29 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -280,7 +280,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, : OK); } -#define TYPVAL_ENCODE_CONV_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ const char *const buf_ = (const char *) buf; \ if (buf == NULL) { \ @@ -299,19 +299,19 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, } \ } while (0) -#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \ - TYPVAL_ENCODE_CONV_STRING(buf, len) +#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) \ + TYPVAL_ENCODE_CONV_STRING(tv, buf, len) -#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) -#define TYPVAL_ENCODE_CONV_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ do { \ char numbuf[NUMBUFLEN]; \ vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t) (num)); \ ga_concat(gap, numbuf); \ } while (0) -#define TYPVAL_ENCODE_CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ do { \ const float_T flt_ = (flt); \ switch (fpclassify(flt_)) { \ @@ -334,65 +334,65 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, } \ } while (0) -#define TYPVAL_ENCODE_CONV_FUNC_START(fun, is_partial, pt) \ +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ do { \ ga_concat(gap, "function("); \ - TYPVAL_ENCODE_CONV_STRING(fun, STRLEN(fun)); \ + TYPVAL_ENCODE_CONV_STRING(tv, fun, STRLEN(fun)); \ } while (0) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(len) \ +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) \ do { \ if (len != 0) { \ ga_concat(gap, ", "); \ } \ } while (0) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(len) \ +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) \ do { \ if ((ptrdiff_t)len != -1) { \ ga_concat(gap, ", "); \ } \ } while (0) -#define TYPVAL_ENCODE_CONV_FUNC_END() \ +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) \ ga_append(gap, ')') -#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \ +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ ga_concat(gap, "[]") -#define TYPVAL_ENCODE_CONV_LIST_START(len) \ +#define TYPVAL_ENCODE_CONV_LIST_START(tv, dict) \ ga_append(gap, '[') -#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \ ga_concat(gap, "{}") -#define TYPVAL_ENCODE_CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL(tv) \ ga_concat(gap, "v:null") -#define TYPVAL_ENCODE_CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ ga_concat(gap, ((num)? "v:true": "v:false")) -#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) -#define TYPVAL_ENCODE_CONV_DICT_START(len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ ga_append(gap, '{') -#define TYPVAL_ENCODE_CONV_DICT_END() \ +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ ga_append(gap, '}') -#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() \ +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) \ ga_concat(gap, ": ") -#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() \ +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) \ ga_concat(gap, ", ") -#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, key) +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key) -#define TYPVAL_ENCODE_CONV_LIST_END() \ +#define TYPVAL_ENCODE_CONV_LIST_END(tv) \ ga_append(gap, ']') -#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() \ - TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \ + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, NULL) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ do { \ @@ -493,15 +493,15 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, #define TYPVAL_ENCODE_ALLOW_SPECIALS true #undef TYPVAL_ENCODE_CONV_NIL -#define TYPVAL_ENCODE_CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL(tv) \ ga_concat(gap, "null") #undef TYPVAL_ENCODE_CONV_BOOL -#define TYPVAL_ENCODE_CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ ga_concat(gap, ((num)? "true": "false")) #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER -#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \ do { \ char numbuf[NUMBUFLEN]; \ vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \ @@ -509,7 +509,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, } while (0) #undef TYPVAL_ENCODE_CONV_FLOAT -#define TYPVAL_ENCODE_CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ do { \ const float_T flt_ = (flt); \ switch (fpclassify(flt_)) { \ @@ -698,7 +698,7 @@ static inline int convert_to_json_string(garray_T *const gap, } #undef TYPVAL_ENCODE_CONV_STRING -#define TYPVAL_ENCODE_CONV_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ if (convert_to_json_string(gap, (const char *) (buf), (len)) != OK) { \ return FAIL; \ @@ -706,7 +706,7 @@ static inline int convert_to_json_string(garray_T *const gap, } while (0) #undef TYPVAL_ENCODE_CONV_EXT_STRING -#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \ +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \ do { \ xfree(buf); \ EMSG(_("E474: Unable to convert EXT string to JSON")); \ @@ -714,7 +714,7 @@ static inline int convert_to_json_string(garray_T *const gap, } while (0) #undef TYPVAL_ENCODE_CONV_FUNC_START -#define TYPVAL_ENCODE_CONV_FUNC_START(fun, is_partial, pt) \ +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ return conv_error(_("E474: Error while dumping %s, %s: " \ "attempt to dump function reference"), \ mpstack, objname) @@ -757,8 +757,8 @@ bool encode_check_json_key(const typval_T *const tv) return true; } -#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK -#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, key) \ +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key) \ do { \ if (!encode_check_json_key(&key)) { \ EMSG(_("E474: Invalid key in special dictionary")); \ @@ -797,7 +797,7 @@ bool encode_check_json_key(const typval_T *const tv) #undef TYPVAL_ENCODE_CONV_DICT_END #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS -#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK #undef TYPVAL_ENCODE_CONV_LIST_END #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_RECURSE @@ -875,7 +875,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) return (char *) ga.ga_data; } -#define TYPVAL_ENCODE_CONV_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ if (buf == NULL) { \ msgpack_pack_bin(packer, 0); \ @@ -886,7 +886,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) \ do { \ if (buf == NULL) { \ msgpack_pack_str(packer, 0); \ @@ -897,7 +897,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \ +#define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \ do { \ if (buf == NULL) { \ msgpack_pack_ext(packer, 0, (int8_t) type); \ @@ -908,34 +908,34 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define TYPVAL_ENCODE_CONV_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ msgpack_pack_int64(packer, (int64_t) (num)) -#define TYPVAL_ENCODE_CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ msgpack_pack_double(packer, (double) (flt)) -#define TYPVAL_ENCODE_CONV_FUNC_START(fun, is_partial, pt) \ +#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ return conv_error(_("E5004: Error while dumping %s, %s: " \ "attempt to dump function reference"), \ mpstack, objname) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(len) -#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(len) -#define TYPVAL_ENCODE_CONV_FUNC_END() +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) +#define TYPVAL_ENCODE_CONV_FUNC_END(tv) -#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \ +#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ msgpack_pack_array(packer, 0) -#define TYPVAL_ENCODE_CONV_LIST_START(len) \ +#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \ msgpack_pack_array(packer, (size_t) (len)) -#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv) \ msgpack_pack_map(packer, 0) -#define TYPVAL_ENCODE_CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL(tv) \ msgpack_pack_nil(packer) -#define TYPVAL_ENCODE_CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ do { \ if ((num)) { \ msgpack_pack_true(packer); \ @@ -944,23 +944,23 @@ char *encode_tv2json(typval_T *tv, size_t *len) } \ } while (0) -#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \ msgpack_pack_uint64(packer, (num)) -#define TYPVAL_ENCODE_CONV_DICT_START(len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \ msgpack_pack_map(packer, (size_t) (len)) -#define TYPVAL_ENCODE_CONV_DICT_END() +#define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) -#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(tv, dict) -#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(tv, dict) -#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, key) +#define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key) -#define TYPVAL_ENCODE_CONV_LIST_END() +#define TYPVAL_ENCODE_CONV_LIST_END(tv) -#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \ return conv_error(_("E5005: Unable to dump %s: " \ @@ -1000,7 +1000,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) #undef TYPVAL_ENCODE_CONV_DICT_END #undef TYPVAL_ENCODE_CONV_DICT_AFTER_KEY #undef TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS -#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +#undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK #undef TYPVAL_ENCODE_CONV_LIST_END #undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS #undef TYPVAL_ENCODE_CONV_RECURSE diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 5c807bb169..8caffaf7f5 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -8,8 +8,10 @@ /// @brief Macros used to convert NIL value /// /// Is called both for special dictionary (unless #TYPVAL_ENCODE_ALLOW_SPECIALS -/// is false) and `v:null`. Accepts no arguments, but still must be -/// a function-like macros. +/// is false) and `v:null`. +/// +/// @param tv Pointer to typval where value is stored. May not be NULL. May +/// point to special dictionary. /// @def TYPVAL_ENCODE_CONV_BOOL /// @brief Macros used to convert boolean value @@ -17,12 +19,16 @@ /// Is called both for special dictionary (unless #TYPVAL_ENCODE_ALLOW_SPECIALS /// is false) and `v:true`/`v:false`. /// +/// @param tv Pointer to typval where value is stored. May not be NULL. May +/// point to a special dictionary. /// @param num Boolean value to convert. Value is an expression which /// evaluates to some integer. /// @def TYPVAL_ENCODE_CONV_NUMBER /// @brief Macros used to convert integer /// +/// @param tv Pointer to typval where value is stored. May not be NULL. May +/// point to a special dictionary. /// @param num Integer to convert, must accept both varnumber_T and int64_t. /// @def TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER @@ -31,11 +37,15 @@ /// Not used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be /// defined. /// +/// @param tv Pointer to typval where value is stored. May not be NULL. Points +/// to a special dictionary. /// @param num Integer to convert, must accept uint64_t. /// @def TYPVAL_ENCODE_CONV_FLOAT /// @brief Macros used to convert floating-point number /// +/// @param tv Pointer to typval where value is stored. May not be NULL. May +/// point to a special dictionary. /// @param flt Number to convert, must accept float_T. /// @def TYPVAL_ENCODE_CONV_STRING @@ -44,6 +54,8 @@ /// Is used to convert VAR_STRING objects as well as BIN strings represented as /// special dictionary. /// +/// @param tv Pointer to typval where value is stored. May not be NULL. May +/// point to a special dictionary. /// @param buf String to convert. Is a char[] buffer, not NUL-terminated. /// @param len String length. @@ -52,6 +64,11 @@ /// /// Is used to convert dictionary keys and STR strings represented as special /// dictionaries. +/// +/// @param tv Pointer to typval where value is stored. May be NULL. May +/// point to a special dictionary. +/// @param buf String to convert. Is a char[] buffer, not NUL-terminated. +/// @param len String length. /// @def TYPVAL_ENCODE_CONV_EXT_STRING /// @brief Macros used to convert EXT string @@ -60,31 +77,29 @@ /// actually used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be /// defined. /// +/// @param tv Pointer to typval where value is stored. May not be NULL. Points +/// to a special dictionary. /// @param buf String to convert. Is a char[] buffer, not NUL-terminated. /// @param len String length. /// @param type EXT type. -/// @def TYPVAL_ENCODE_CONV_FUNC -/// @brief Macros used to convert a function reference -/// -/// @param fun Function name. - /// @def TYPVAL_ENCODE_CONV_FUNC_START /// @brief Macros used when starting to convert a funcref or a partial /// +/// @param tv Pointer to typval where value is stored. May not be NULL. /// @param fun Function name. -/// @param is_partial True if converted function is a partial. -/// @param pt Pointer to partial or NULL. /// @def TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS /// @brief Macros used before starting to convert partial arguments /// +/// @param tv Pointer to typval where value is stored. May not be NULL. /// @param len Number of arguments. Zero for absent arguments or when /// converting a funcref. /// @def TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF /// @brief Macros used before starting to convert self dictionary /// +/// @param tv Pointer to typval where value is stored. May not be NULL. /// @param len Number of arguments. May be zero for empty dictionary or -1 for /// missing self dictionary, also when converting function /// reference. @@ -92,40 +107,47 @@ /// @def TYPVAL_ENCODE_CONV_FUNC_END /// @brief Macros used after converting a funcref or a partial /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where value is stored. May not be NULL. /// @def TYPVAL_ENCODE_CONV_EMPTY_LIST /// @brief Macros used to convert an empty list /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where value is stored. May not be NULL. /// @def TYPVAL_ENCODE_CONV_EMPTY_DICT /// @brief Macros used to convert an empty dictionary /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where value is stored. May not be NULL. May +/// point to a special dictionary. /// @def TYPVAL_ENCODE_CONV_LIST_START /// @brief Macros used before starting to convert non-empty list /// +/// @param tv Pointer to typval where value is stored. May be NULL. May +/// point to a special dictionary. /// @param len List length. Is an expression which evaluates to an integer. /// @def TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS /// @brief Macros used after finishing converting non-last list item /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where list is stored. May be NULL. /// @def TYPVAL_ENCODE_CONV_LIST_END /// @brief Macros used after converting non-empty list /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where list is stored. May be NULL. /// @def TYPVAL_ENCODE_CONV_DICT_START /// @brief Macros used before starting to convert non-empty dictionary /// +/// @param tv Pointer to typval where dictionary is stored. May be NULL. May +/// point to a special dictionary. +/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR +/// (for dictionaries represented as special lists). /// @param len Dictionary length. Is an expression which evaluates to an /// integer. -/// @def TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +/// @def TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK /// @brief Macros used to check special dictionary key /// /// @param label Label for goto in case check was not successfull. @@ -134,17 +156,26 @@ /// @def TYPVAL_ENCODE_CONV_DICT_AFTER_KEY /// @brief Macros used after finishing converting dictionary key /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where dictionary is stored. May be NULL. May +/// point to a special dictionary. +/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR +/// (for dictionaries represented as special lists). /// @def TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS /// @brief Macros used after finishing converting non-last dictionary value /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where dictionary is stored. May be NULL. May +/// point to a special dictionary. +/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR +/// (for dictionaries represented as special lists). /// @def TYPVAL_ENCODE_CONV_DICT_END /// @brief Macros used after converting non-empty dictionary /// -/// Accepts no arguments, but still must be a function-like macros. +/// @param tv Pointer to typval where dictionary is stored. May be NULL. May +/// point to a special dictionary. +/// @param dict Converted dictionary, lvalue or &#TYPVAL_ENCODE_NODICT_VAR +/// (for dictionaries represented as special lists). /// @def TYPVAL_ENCODE_CONV_RECURSE /// @brief Macros used when self-containing container is detected @@ -193,6 +224,8 @@ #include "nvim/func_attr.h" #include "nvim/eval/typval_encode.h" +const dict_T *const TYPVAL_ENCODE_NODICT_VAR = NULL; + static inline int _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, void *const val, int *const val_copyID, @@ -263,28 +296,28 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( { switch (tv->v_type) { case VAR_STRING: { - TYPVAL_ENCODE_CONV_STRING(tv->vval.v_string, tv_strlen(tv)); + TYPVAL_ENCODE_CONV_STRING(tv, tv->vval.v_string, tv_strlen(tv)); break; } case VAR_NUMBER: { - TYPVAL_ENCODE_CONV_NUMBER(tv->vval.v_number); + TYPVAL_ENCODE_CONV_NUMBER(tv, tv->vval.v_number); break; } case VAR_FLOAT: { - TYPVAL_ENCODE_CONV_FLOAT(tv->vval.v_float); + TYPVAL_ENCODE_CONV_FLOAT(tv, tv->vval.v_float); break; } case VAR_FUNC: { - TYPVAL_ENCODE_CONV_FUNC_START(tv->vval.v_string, false, NULL); - TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(0); - TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(-1); - TYPVAL_ENCODE_CONV_FUNC_END(); + TYPVAL_ENCODE_CONV_FUNC_START(tv, tv->vval.v_string); + TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, 0); + TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1); + TYPVAL_ENCODE_CONV_FUNC_END(tv); break; } case VAR_PARTIAL: { partial_T *const pt = tv->vval.v_partial; (void)pt; - TYPVAL_ENCODE_CONV_FUNC_START(pt->pt_name, true, pt); + TYPVAL_ENCODE_CONV_FUNC_START(tv, pt->pt_name); _mp_push(*mpstack, ((MPConvStackVal) { .type = kMPConvPartial, .tv = tv, @@ -299,12 +332,12 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } case VAR_LIST: { if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { - TYPVAL_ENCODE_CONV_EMPTY_LIST(); + TYPVAL_ENCODE_CONV_EMPTY_LIST(tv); break; } _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID, kMPConvList); - TYPVAL_ENCODE_CONV_LIST_START(tv->vval.v_list->lv_len); + TYPVAL_ENCODE_CONV_LIST_START(tv, tv->vval.v_list->lv_len); _mp_push(*mpstack, ((MPConvStackVal) { .type = kMPConvList, .tv = tv, @@ -320,12 +353,12 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( case VAR_SPECIAL: { switch (tv->vval.v_special) { case kSpecialVarNull: { - TYPVAL_ENCODE_CONV_NIL(); + TYPVAL_ENCODE_CONV_NIL(tv); break; } case kSpecialVarTrue: case kSpecialVarFalse: { - TYPVAL_ENCODE_CONV_BOOL(tv->vval.v_special == kSpecialVarTrue); + TYPVAL_ENCODE_CONV_BOOL(tv, tv->vval.v_special == kSpecialVarTrue); break; } } @@ -334,7 +367,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( case VAR_DICT: { if (tv->vval.v_dict == NULL || tv->vval.v_dict->dv_hashtab.ht_used == 0) { - TYPVAL_ENCODE_CONV_EMPTY_DICT(); + TYPVAL_ENCODE_CONV_EMPTY_DICT(tv); break; } const dictitem_T *type_di; @@ -357,14 +390,14 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } switch ((MessagePackType)i) { case kMPNil: { - TYPVAL_ENCODE_CONV_NIL(); + TYPVAL_ENCODE_CONV_NIL(tv); break; } case kMPBoolean: { if (val_di->di_tv.v_type != VAR_NUMBER) { goto _convert_one_value_regular_dict; } - TYPVAL_ENCODE_CONV_BOOL(val_di->di_tv.vval.v_number); + TYPVAL_ENCODE_CONV_BOOL(tv, val_di->di_tv.vval.v_number); break; } case kMPInteger: { @@ -397,9 +430,9 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( | (uint64_t)(((uint64_t)high_bits) << 31) | (uint64_t)low_bits); if (sign > 0) { - TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(number); + TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, number); } else { - TYPVAL_ENCODE_CONV_NUMBER(-number); + TYPVAL_ENCODE_CONV_NUMBER(tv, -number); } break; } @@ -407,7 +440,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( if (val_di->di_tv.v_type != VAR_FLOAT) { goto _convert_one_value_regular_dict; } - TYPVAL_ENCODE_CONV_FLOAT(val_di->di_tv.vval.v_float); + TYPVAL_ENCODE_CONV_FLOAT(tv, val_di->di_tv.vval.v_float); break; } case kMPString: @@ -423,9 +456,9 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( goto _convert_one_value_regular_dict; } if (is_string) { - TYPVAL_ENCODE_CONV_STR_STRING(buf, len); + TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len); } else { - TYPVAL_ENCODE_CONV_STRING(buf, len); + TYPVAL_ENCODE_CONV_STRING(tv, buf, len); } xfree(buf); break; @@ -437,7 +470,8 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, lv_copyID, copyID, kMPConvList); - TYPVAL_ENCODE_CONV_LIST_START(val_di->di_tv.vval.v_list->lv_len); + TYPVAL_ENCODE_CONV_LIST_START(tv, + val_di->di_tv.vval.v_list->lv_len); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvList, @@ -456,7 +490,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } list_T *const val_list = val_di->di_tv.vval.v_list; if (val_list == NULL || val_list->lv_len == 0) { - TYPVAL_ENCODE_CONV_EMPTY_DICT(); + TYPVAL_ENCODE_CONV_EMPTY_DICT(tv); break; } for (const listitem_T *li = val_list->lv_first; li != NULL; @@ -468,7 +502,8 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID, kMPConvPairs); - TYPVAL_ENCODE_CONV_DICT_START(val_list->lv_len); + TYPVAL_ENCODE_CONV_DICT_START(tv, TYPVAL_ENCODE_NODICT_VAR, + val_list->lv_len); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvPairs, @@ -499,7 +534,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( &len, &buf)) { goto _convert_one_value_regular_dict; } - TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type); + TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type); xfree(buf); break; } @@ -509,7 +544,8 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( _convert_one_value_regular_dict: _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, copyID, kMPConvDict); - TYPVAL_ENCODE_CONV_DICT_START(tv->vval.v_dict->dv_hashtab.ht_used); + TYPVAL_ENCODE_CONV_DICT_START(tv, tv->vval.v_dict, + tv->vval.v_dict->dv_hashtab.ht_used); _mp_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvDict, @@ -566,11 +602,12 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( if (!cur_mpsv->data.d.todo) { (void)_mp_pop(mpstack); cur_mpsv->data.d.dict->dv_copyID = copyID - 1; - TYPVAL_ENCODE_CONV_DICT_END(); + TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, cur_mpsv->tv->vval.v_dict); continue; } else if (cur_mpsv->data.d.todo != cur_mpsv->data.d.dict->dv_hashtab.ht_used) { - TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(cur_mpsv->tv, + cur_mpsv->tv->vval.v_dict); } while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { cur_mpsv->data.d.hi++; @@ -578,9 +615,10 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi); cur_mpsv->data.d.todo--; cur_mpsv->data.d.hi++; - TYPVAL_ENCODE_CONV_STR_STRING(&di->di_key[0], + TYPVAL_ENCODE_CONV_STR_STRING(NULL, &di->di_key[0], strlen((char *)&di->di_key[0])); - TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); + TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(cur_mpsv->tv, + cur_mpsv->tv->vval.v_dict); tv = &di->di_tv; break; } @@ -588,10 +626,10 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( if (cur_mpsv->data.l.li == NULL) { (void)_mp_pop(mpstack); cur_mpsv->data.l.list->lv_copyID = copyID - 1; - TYPVAL_ENCODE_CONV_LIST_END(); + TYPVAL_ENCODE_CONV_LIST_END(cur_mpsv->tv); continue; } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { - TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(); + TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(cur_mpsv->tv); } tv = &cur_mpsv->data.l.li->li_tv; cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; @@ -601,13 +639,14 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( if (cur_mpsv->data.l.li == NULL) { (void)_mp_pop(mpstack); cur_mpsv->data.l.list->lv_copyID = copyID - 1; - TYPVAL_ENCODE_CONV_DICT_END(); + TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR); continue; } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { - TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); + TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS( + cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR); } const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; - TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK( + TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK( encode_vim_to__error_ret, kv_pair->lv_first->li_tv); if (_TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, cur_mpsv, @@ -616,19 +655,22 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( objname) == FAIL) { goto encode_vim_to__error_ret; } - TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); + TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(cur_mpsv->tv, + TYPVAL_ENCODE_NODICT_VAR); tv = &kv_pair->lv_last->li_tv; cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; break; } case kMPConvPartial: { partial_T *const pt = cur_mpsv->data.p.pt; + tv = cur_mpsv->tv; switch (cur_mpsv->data.p.stage) { case kMPConvPartialArgs: { - TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(pt == NULL ? 0 : pt->pt_argc); + TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, + pt == NULL ? 0 : pt->pt_argc); cur_mpsv->data.p.stage = kMPConvPartialSelf; if (pt != NULL && pt->pt_argc > 0) { - TYPVAL_ENCODE_CONV_LIST_START(pt->pt_argc); + TYPVAL_ENCODE_CONV_LIST_START(NULL, pt->pt_argc); _mp_push(mpstack, ((MPConvStackVal) { .type = kMPConvPartialList, .tv = NULL, @@ -647,7 +689,7 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( cur_mpsv->data.p.stage = kMPConvPartialEnd; dict_T *const dict = pt == NULL ? NULL : pt->pt_dict; if (dict != NULL) { - TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(dict->dv_hashtab.ht_used); + TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, dict->dv_hashtab.ht_used); const int te_csr_ret = _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( TYPVAL_ENCODE_FIRST_ARG_NAME, dict, &dict->dv_copyID, &mpstack, copyID, kMPConvDict, @@ -659,7 +701,8 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( continue; } } - TYPVAL_ENCODE_CONV_DICT_START(dict->dv_hashtab.ht_used); + TYPVAL_ENCODE_CONV_DICT_START(NULL, pt->pt_dict, + dict->dv_hashtab.ht_used); _mp_push(mpstack, ((MPConvStackVal) { .type = kMPConvDict, .tv = NULL, @@ -672,12 +715,12 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( }, })); } else { - TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(-1); + TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1); } break; } case kMPConvPartialEnd: { - TYPVAL_ENCODE_CONV_FUNC_END(); + TYPVAL_ENCODE_CONV_FUNC_END(tv); (void)_mp_pop(mpstack); break; } @@ -687,10 +730,10 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( case kMPConvPartialList: { if (!cur_mpsv->data.a.todo) { (void)_mp_pop(mpstack); - TYPVAL_ENCODE_CONV_LIST_END(); + TYPVAL_ENCODE_CONV_LIST_END(NULL); continue; } else if (cur_mpsv->data.a.argv != cur_mpsv->data.a.arg) { - TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(); + TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(NULL); } tv = cur_mpsv->data.a.arg++; cur_mpsv->data.a.todo--; diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index 9208cdc752..5813059cda 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -284,4 +284,13 @@ static inline size_t tv_strlen(const typval_T *const tv) #define _TYPVAL_ENCODE_CONVERT_ONE_VALUE \ _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER(TYPVAL_ENCODE_NAME) +#define _TYPVAL_ENCODE_NODICT_VAR_INNER_2(name) \ + _typval_encode_##name##_nodict_var +#define _TYPVAL_ENCODE_NODICT_VAR_INNER(name) \ + _TYPVAL_ENCODE_NODICT_VAR_INNER_2(name) + +/// Name of the dummy const dict_T *const variable +#define TYPVAL_ENCODE_NODICT_VAR \ + _TYPVAL_ENCODE_NODICT_VAR_INNER(TYPVAL_ENCODE_NAME) + #endif // NVIM_EVAL_TYPVAL_ENCODE_H |