diff options
Diffstat (limited to 'src/nvim/eval/typval_encode.h')
-rw-r--r-- | src/nvim/eval/typval_encode.h | 593 |
1 files changed, 79 insertions, 514 deletions
diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index b79158b30c..6517efa961 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -1,161 +1,35 @@ -/// @file eval/typval_convert.h +/// @file eval/typval_encode.h /// -/// Contains set of macros used to convert (possibly recursive) typval_T into -/// something else. For these macros to work the following macros must be -/// defined: - -/// @def TYPVAL_ENCODE_CONV_NIL -/// @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. - -/// @def TYPVAL_ENCODE_CONV_BOOL -/// @brief Macros used to convert boolean value -/// -/// Is called both for special dictionary (unless #TYPVAL_ENCODE_ALLOW_SPECIALS -/// is false) and `v:true`/`v:false`. -/// -/// @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 num Integer to convert, must accept both varnumber_T and int64_t. - -/// @def TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER -/// @brief Macros used to convert unsigned integer -/// -/// Not used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be -/// defined. -/// -/// @param num Integer to convert, must accept uint64_t. - -/// @def TYPVAL_ENCODE_CONV_FLOAT -/// @brief Macros used to convert floating-point number -/// -/// @param flt Number to convert, must accept float_T. - -/// @def TYPVAL_ENCODE_CONV_STRING -/// @brief Macros used to convert plain string -/// -/// Is used to convert VAR_STRING objects as well as BIN strings represented as -/// special dictionary. -/// -/// @param buf String to convert. Is a char[] buffer, not NUL-terminated. -/// @param len String length. - -/// @def TYPVAL_ENCODE_CONV_STR_STRING -/// @brief Like #TYPVAL_ENCODE_CONV_STRING, but for STR strings -/// -/// Is used to convert dictionary keys and STR strings represented as special -/// dictionaries. - -/// @def TYPVAL_ENCODE_CONV_EXT_STRING -/// @brief Macros used to convert EXT string -/// -/// Is used to convert EXT strings represented as special dictionaries. Never -/// actually used if #TYPVAL_ENCODE_ALLOW_SPECIALS is false, but still must be -/// defined. -/// -/// @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_PARTIAL -/// @brief Macros used to convert a partial -/// -/// @param pt Partial name. - -/// @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. - -/// @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. - -/// @def TYPVAL_ENCODE_CONV_LIST_START -/// @brief Macros used before starting to convert non-empty list -/// -/// @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. - -/// @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. - -/// @def TYPVAL_ENCODE_CONV_DICT_START -/// @brief Macros used before starting to convert non-empty dictionary -/// -/// @param len Dictionary length. Is an expression which evaluates to an -/// integer. - -/// @def TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK -/// @brief Macros used to check special dictionary key -/// -/// @param label Label for goto in case check was not successfull. -/// @param key typval_T key to check. - -/// @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. - -/// @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. - -/// @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. - -/// @def TYPVAL_ENCODE_CONV_RECURSE -/// @brief Macros used when self-containing container is detected -/// -/// @param val Container for which this situation was detected. -/// @param conv_type Type of the stack entry, @see MPConvStackValType. - -/// @def TYPVAL_ENCODE_ALLOW_SPECIALS -/// @brief Macros that specifies whether special dictionaries are special -/// -/// Must be something that evaluates to boolean, most likely `true` or `false`. -/// If it is false then special dictionaries are not treated specially. +/// Contains common definitions for eval/typval_encode.c.h. Most of time should +/// not be included directly. #ifndef NVIM_EVAL_TYPVAL_ENCODE_H #define NVIM_EVAL_TYPVAL_ENCODE_H #include <stddef.h> #include <inttypes.h> +#include <string.h> #include <assert.h> #include "nvim/lib/kvec.h" #include "nvim/eval_defs.h" -#include "nvim/eval/encode.h" #include "nvim/func_attr.h" /// Type of the stack entry typedef enum { - kMPConvDict, ///< Convert dict_T *dictionary. - kMPConvList, ///< Convert list_T *list. + kMPConvDict, ///< Convert dict_T *dictionary. + kMPConvList, ///< Convert list_T *list. kMPConvPairs, ///< Convert mapping represented as a list_T* of pairs. + kMPConvPartial, ///< Convert partial_T* partial. + kMPConvPartialList, ///< Convert argc/argv pair coming from a partial. } MPConvStackValType; +/// Stage at which partial is being converted +typedef enum { + kMPConvPartialArgs, ///< About to convert arguments. + kMPConvPartialSelf, ///< About to convert self dictionary. + kMPConvPartialEnd, ///< Already converted everything. +} MPConvPartialStage; + /// Structure representing current VimL to messagepack conversion state typedef struct { MPConvStackValType type; ///< Type of the stack entry. @@ -163,6 +37,9 @@ typedef struct { union { struct { dict_T *dict; ///< Currently converted dictionary. + dict_T **dictp; ///< Location where that dictionary is stored. + ///< Normally it is &.tv->vval.v_dict, but not when + ///< converting partials. hashitem_T *hi; ///< Currently converted dictionary item. size_t todo; ///< Amount of items left to process. } d; ///< State of dictionary conversion. @@ -170,6 +47,15 @@ typedef struct { list_T *list; ///< Currently converted list. listitem_T *li; ///< Currently converted list item. } l; ///< State of list or generic mapping conversion. + struct { + MPConvPartialStage stage; ///< Stage at which partial is being converted. + partial_T *pt; ///< Currently converted partial. + } p; ///< State of partial conversion. + struct { + typval_T *arg; ///< Currently converted argument. + typval_T *argv; ///< Start of the argument list. + size_t todo; ///< Number of items left to process. + } a; ///< State of list or generic mapping conversion. } data; ///< Data to convert. } MPConvStackVal; @@ -184,21 +70,9 @@ typedef kvec_withinit_t(MPConvStackVal, 8) MPConvStack; #define _mp_pop kv_pop #define _mp_last kv_last -/// Code for checking whether container references itself -/// -/// @param[in,out] val Container to check. -/// @param copyID_attr Name of the container attribute that holds copyID. -/// After checking whether value of this attribute is -/// copyID (variable) it is set to copyID. -/// @param conv_type Type of the conversion, @see MPConvStackValType. -#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val, copyID_attr, conv_type) \ - do { \ - if ((val)->copyID_attr == copyID) { \ - TYPVAL_ENCODE_CONV_RECURSE((val), conv_type); \ - return OK; \ - } \ - (val)->copyID_attr = copyID; \ - } while (0) +static inline size_t tv_strlen(const typval_T *const tv) + REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT + REAL_FATTR_NONNULL_ALL; /// Length of the string stored in typval_T /// @@ -208,8 +82,6 @@ typedef kvec_withinit_t(MPConvStackVal, 8) MPConvStack; /// @return Length of the string stored in typval_T, including 0 for NULL /// string. static inline size_t tv_strlen(const typval_T *const tv) - FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT - FUNC_ATTR_NONNULL_ALL { assert(tv->v_type == VAR_STRING); return (tv->vval.v_string == NULL @@ -217,363 +89,56 @@ static inline size_t tv_strlen(const typval_T *const tv) : strlen((char *) tv->vval.v_string)); } -/// Define functions to convert a VimL value: -/// `{name}_convert_one_value(...)` -/// `encode_vim_to_{name}(...)` +/// Code for checking whether container references itself /// -/// @param scope Scope of the main function: either nothing or `static`. -/// @param name Name of the target converter. -/// @param firstargtype Type of the first argument. It will be used to return -/// the results. -/// @param firstargname Name of the first argument. -#define TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(scope, name, firstargtype, \ - firstargname) \ -/* Returns OK or FAIL */ \ -static int name##_convert_one_value(firstargtype firstargname, \ - MPConvStack *const mpstack, \ - typval_T *const tv, \ - const int copyID, \ - const char *const objname) \ - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT \ -{ \ - switch (tv->v_type) { \ - case VAR_STRING: { \ - TYPVAL_ENCODE_CONV_STRING(tv->vval.v_string, tv_strlen(tv)); \ - break; \ - } \ - case VAR_NUMBER: { \ - TYPVAL_ENCODE_CONV_NUMBER(tv->vval.v_number); \ - break; \ - } \ - case VAR_FLOAT: { \ - TYPVAL_ENCODE_CONV_FLOAT(tv->vval.v_float); \ - break; \ - } \ - case VAR_FUNC: { \ - TYPVAL_ENCODE_CONV_FUNC(tv->vval.v_string); \ - break; \ - } \ - case VAR_PARTIAL: { \ - TYPVAL_ENCODE_CONV_PARTIAL(tv->vval.v_partial); \ - break; \ - } \ - case VAR_LIST: { \ - if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { \ - TYPVAL_ENCODE_CONV_EMPTY_LIST(); \ - break; \ - } \ - _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, \ - kMPConvList); \ - TYPVAL_ENCODE_CONV_LIST_START(tv->vval.v_list->lv_len); \ - _mp_push(*mpstack, ((MPConvStackVal) { \ - .type = kMPConvList, \ - .tv = tv, \ - .data = { \ - .l = { \ - .list = tv->vval.v_list, \ - .li = tv->vval.v_list->lv_first, \ - }, \ - }, \ - })); \ - break; \ - } \ - case VAR_SPECIAL: { \ - switch (tv->vval.v_special) { \ - case kSpecialVarNull: { \ - TYPVAL_ENCODE_CONV_NIL(); \ - break; \ - } \ - case kSpecialVarTrue: \ - case kSpecialVarFalse: { \ - TYPVAL_ENCODE_CONV_BOOL(tv->vval.v_special == kSpecialVarTrue); \ - break; \ - } \ - } \ - break; \ - } \ - case VAR_DICT: { \ - if (tv->vval.v_dict == NULL \ - || tv->vval.v_dict->dv_hashtab.ht_used == 0) { \ - TYPVAL_ENCODE_CONV_EMPTY_DICT(); \ - break; \ - } \ - const dictitem_T *type_di; \ - const dictitem_T *val_di; \ - if (TYPVAL_ENCODE_ALLOW_SPECIALS \ - && tv->vval.v_dict->dv_hashtab.ht_used == 2 \ - && (type_di = dict_find((dict_T *) tv->vval.v_dict, \ - (char_u *) "_TYPE", -1)) != NULL \ - && type_di->di_tv.v_type == VAR_LIST \ - && (val_di = dict_find((dict_T *) tv->vval.v_dict, \ - (char_u *) "_VAL", -1)) != NULL) { \ - size_t i; \ - for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) { \ - if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) { \ - break; \ - } \ - } \ - if (i == ARRAY_SIZE(eval_msgpack_type_lists)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - switch ((MessagePackType) i) { \ - case kMPNil: { \ - TYPVAL_ENCODE_CONV_NIL(); \ - break; \ - } \ - case kMPBoolean: { \ - if (val_di->di_tv.v_type != VAR_NUMBER) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - TYPVAL_ENCODE_CONV_BOOL(val_di->di_tv.vval.v_number); \ - break; \ - } \ - case kMPInteger: { \ - const list_T *val_list; \ - varnumber_T sign; \ - varnumber_T highest_bits; \ - varnumber_T high_bits; \ - varnumber_T low_bits; \ - /* List of 4 integers; first is signed (should be 1 or -1, but */ \ - /* this is not checked), second is unsigned and have at most */ \ - /* one (sign is -1) or two (sign is 1) non-zero bits (number of */ \ - /* bits is not checked), other unsigned and have at most 31 */ \ - /* non-zero bits (number of bits is not checked).*/ \ - if (val_di->di_tv.v_type != VAR_LIST \ - || (val_list = val_di->di_tv.vval.v_list) == NULL \ - || 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 name##_convert_one_value_regular_dict; \ - } \ - uint64_t number = ((uint64_t) (((uint64_t) highest_bits) << 62) \ - | (uint64_t) (((uint64_t) high_bits) << 31) \ - | (uint64_t) low_bits); \ - if (sign > 0) { \ - TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(number); \ - } else { \ - TYPVAL_ENCODE_CONV_NUMBER(-number); \ - } \ - break; \ - } \ - case kMPFloat: { \ - if (val_di->di_tv.v_type != VAR_FLOAT) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - TYPVAL_ENCODE_CONV_FLOAT(val_di->di_tv.vval.v_float); \ - break; \ - } \ - case kMPString: \ - case kMPBinary: { \ - const bool is_string = ((MessagePackType) i == kMPString); \ - if (val_di->di_tv.v_type != VAR_LIST) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - size_t len; \ - char *buf; \ - if (!encode_vim_list_to_buf(val_di->di_tv.vval.v_list, &len, \ - &buf)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - if (is_string) { \ - TYPVAL_ENCODE_CONV_STR_STRING(buf, len); \ - } else { \ - TYPVAL_ENCODE_CONV_STRING(buf, len); \ - } \ - xfree(buf); \ - break; \ - } \ - case kMPArray: { \ - if (val_di->di_tv.v_type != VAR_LIST) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, \ - lv_copyID, kMPConvList); \ - TYPVAL_ENCODE_CONV_LIST_START(val_di->di_tv.vval.v_list->lv_len); \ - _mp_push(*mpstack, ((MPConvStackVal) { \ - .tv = tv, \ - .type = kMPConvList, \ - .data = { \ - .l = { \ - .list = val_di->di_tv.vval.v_list, \ - .li = val_di->di_tv.vval.v_list->lv_first, \ - }, \ - }, \ - })); \ - break; \ - } \ - case kMPMap: { \ - if (val_di->di_tv.v_type != VAR_LIST) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - 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(); \ - break; \ - } \ - for (const listitem_T *li = val_list->lv_first; li != NULL; \ - li = li->li_next) { \ - if (li->li_tv.v_type != VAR_LIST \ - || li->li_tv.vval.v_list->lv_len != 2) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - } \ - _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(val_list, lv_copyID, \ - kMPConvPairs); \ - TYPVAL_ENCODE_CONV_DICT_START(val_list->lv_len); \ - _mp_push(*mpstack, ((MPConvStackVal) { \ - .tv = tv, \ - .type = kMPConvPairs, \ - .data = { \ - .l = { \ - .list = val_list, \ - .li = val_list->lv_first, \ - }, \ - }, \ - })); \ - break; \ - } \ - case kMPExt: { \ - const list_T *val_list; \ - varnumber_T type; \ - if (val_di->di_tv.v_type != VAR_LIST \ - || (val_list = val_di->di_tv.vval.v_list) == NULL \ - || val_list->lv_len != 2 \ - || (val_list->lv_first->li_tv.v_type != VAR_NUMBER) \ - || (type = val_list->lv_first->li_tv.vval.v_number) > INT8_MAX \ - || type < INT8_MIN \ - || (val_list->lv_last->li_tv.v_type != VAR_LIST)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - size_t len; \ - char *buf; \ - if (!encode_vim_list_to_buf(val_list->lv_last->li_tv.vval.v_list, \ - &len, &buf)) { \ - goto name##_convert_one_value_regular_dict; \ - } \ - TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type); \ - xfree(buf); \ - break; \ - } \ - } \ - break; \ - } \ -name##_convert_one_value_regular_dict: \ - _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, \ - kMPConvDict); \ - TYPVAL_ENCODE_CONV_DICT_START(tv->vval.v_dict->dv_hashtab.ht_used); \ - _mp_push(*mpstack, ((MPConvStackVal) { \ - .tv = tv, \ - .type = kMPConvDict, \ - .data = { \ - .d = { \ - .dict = tv->vval.v_dict, \ - .hi = tv->vval.v_dict->dv_hashtab.ht_array, \ - .todo = tv->vval.v_dict->dv_hashtab.ht_used, \ - }, \ - }, \ - })); \ - break; \ - } \ - case VAR_UNKNOWN: { \ - EMSG2(_(e_intern2), #name "_convert_one_value()"); \ - return FAIL; \ - } \ - } \ - return OK; \ -} \ -\ -scope int encode_vim_to_##name(firstargtype firstargname, typval_T *const tv, \ - const char *const objname) \ - FUNC_ATTR_WARN_UNUSED_RESULT \ -{ \ - const int copyID = get_copyID(); \ - MPConvStack mpstack; \ - _mp_init(mpstack); \ - if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \ - == FAIL) { \ - goto encode_vim_to_##name##_error_ret; \ - } \ - while (_mp_size(mpstack)) { \ - MPConvStackVal *cur_mpsv = &_mp_last(mpstack); \ - typval_T *cur_tv = NULL; \ - switch (cur_mpsv->type) { \ - case kMPConvDict: { \ - if (!cur_mpsv->data.d.todo) { \ - (void) _mp_pop(mpstack); \ - cur_mpsv->data.d.dict->dv_copyID = copyID - 1; \ - TYPVAL_ENCODE_CONV_DICT_END(); \ - continue; \ - } else if (cur_mpsv->data.d.todo \ - != cur_mpsv->data.d.dict->dv_hashtab.ht_used) { \ - TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); \ - } \ - while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) { \ - cur_mpsv->data.d.hi++; \ - } \ - 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], \ - strlen((char *) &di->di_key[0])); \ - TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); \ - cur_tv = &di->di_tv; \ - break; \ - } \ - case kMPConvList: { \ - 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(); \ - continue; \ - } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ - TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(); \ - } \ - cur_tv = &cur_mpsv->data.l.li->li_tv; \ - cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \ - break; \ - } \ - case kMPConvPairs: { \ - 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(); \ - continue; \ - } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ - TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS(); \ - } \ - const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \ - TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK( \ - encode_vim_to_##name##_error_ret, kv_pair->lv_first->li_tv); \ - if (name##_convert_one_value(firstargname, &mpstack, \ - &kv_pair->lv_first->li_tv, copyID, \ - objname) == FAIL) { \ - goto encode_vim_to_##name##_error_ret; \ - } \ - TYPVAL_ENCODE_CONV_DICT_AFTER_KEY(); \ - cur_tv = &kv_pair->lv_last->li_tv; \ - cur_mpsv->data.l.li = cur_mpsv->data.l.li->li_next; \ - break; \ +/// @param[in,out] val Container to check. +/// @param copyID_attr Name of the container attribute that holds copyID. +/// After checking whether value of this attribute is +/// copyID (variable) it is set to copyID. +/// @param[in] copyID CopyID used by the caller. +/// @param conv_type Type of the conversion, @see MPConvStackValType. +#define _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val, copyID_attr, copyID, \ + conv_type) \ + do { \ + const int te_csr_ret = _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( \ + TYPVAL_ENCODE_FIRST_ARG_NAME, \ + (val), &(val)->copyID_attr, mpstack, copyID, conv_type, objname); \ + if (te_csr_ret != NOTDONE) { \ + return te_csr_ret; \ } \ - } \ - assert(cur_tv != NULL); \ - if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \ - objname) == FAIL) { \ - goto encode_vim_to_##name##_error_ret; \ - } \ - } \ - _mp_destroy(mpstack); \ - return OK; \ -encode_vim_to_##name##_error_ret: \ - _mp_destroy(mpstack); \ - return FAIL; \ -} + } while (0) + +#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER_2(name) \ + _typval_encode_##name##_check_self_reference +#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER(name) \ + _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER_2(name) + +/// Self reference checker function name +#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE \ + _TYPVAL_ENCODE_CHECK_SELF_REFERENCE_INNER(TYPVAL_ENCODE_NAME) + +#define _TYPVAL_ENCODE_ENCODE_INNER_2(name) encode_vim_to_##name +#define _TYPVAL_ENCODE_ENCODE_INNER(name) _TYPVAL_ENCODE_ENCODE_INNER_2(name) + +/// Entry point function name +#define _TYPVAL_ENCODE_ENCODE _TYPVAL_ENCODE_ENCODE_INNER(TYPVAL_ENCODE_NAME) + +#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER_2(name) \ + _typval_encode_##name##_convert_one_value +#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER(name) \ + _TYPVAL_ENCODE_CONVERT_ONE_VALUE_INNER_2(name) + +/// Name of the …convert_one_value function +#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 |