diff options
Diffstat (limited to 'src/nvim/eval/encode.c')
| -rw-r--r-- | src/nvim/eval/encode.c | 622 | 
1 files changed, 120 insertions, 502 deletions
| diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index da000bf670..54daf7557e 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -6,6 +6,7 @@  #include <msgpack.h>  #include <inttypes.h> +#include <stddef.h>  #include <assert.h>  #include <math.h> @@ -22,6 +23,7 @@  #include "nvim/ascii.h"  #include "nvim/vim.h"  // For _()  #include "nvim/lib/kvec.h" +#include "nvim/eval/typval_encode.h"  #define ga_concat(a, b) ga_concat(a, (char_u *)b)  #define utf_ptr2char(b) utf_ptr2char((char_u *)b) @@ -32,29 +34,6 @@  #define convert_setup(vcp, from, to) \      (convert_setup(vcp, (char_u *)from, (char_u *)to)) -/// Structure representing current VimL to messagepack conversion state -typedef struct { -  enum { -    kMPConvDict,   ///< Convert dict_T *dictionary. -    kMPConvList,   ///< Convert list_T *list. -    kMPConvPairs,  ///< Convert mapping represented as a list_T* of pairs. -  } type; -  union { -    struct { -      dict_T *dict;    ///< Currently converted dictionary. -      hashitem_T *hi;  ///< Currently converted dictionary item. -      size_t todo;     ///< Amount of items left to process. -    } d;  ///< State of dictionary conversion. -    struct { -      list_T *list;    ///< Currently converted list. -      listitem_T *li;  ///< Currently converted list item. -    } l;  ///< State of list or generic mapping conversion. -  } data;  ///< Data to convert. -} MPConvStackVal; - -/// Stack used to convert VimL values to messagepack. -typedef kvec_t(MPConvStackVal) MPConvStack; -  const char *const encode_special_var_names[] = {    [kSpecialVarNull] = "null",    [kSpecialVarTrue] = "true", @@ -275,368 +254,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf,            : OK);  } -/// 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. -#define CHECK_SELF_REFERENCE(val, copyID_attr, conv_type) \ -    do { \ -      if ((val)->copyID_attr == copyID) { \ -        CONV_RECURSE((val), conv_type); \ -      } \ -      (val)->copyID_attr = copyID; \ -    } while (0) - -#define TV_STRLEN(tv) \ -    (tv->vval.v_string == NULL ? 0 : STRLEN(tv->vval.v_string)) - -/// Define functions which convert VimL value to something else -/// -/// Creates function `vim_to_{name}(firstargtype firstargname, typval_T *const -/// tv)` which returns OK or FAIL and helper functions. -/// -/// @param  firstargtype  Type of the first argument. It will be used to return -///                       the results. -/// @param  firstargname  Name of the first argument. -/// @param  name  Name of the target converter. -#define DEFINE_VIML_CONV_FUNCTIONS(scope, name, firstargtype, firstargname) \ -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: { \ -      CONV_STRING(tv->vval.v_string, TV_STRLEN(tv)); \ -      break; \ -    } \ -    case VAR_NUMBER: { \ -      CONV_NUMBER(tv->vval.v_number); \ -      break; \ -    } \ -    case VAR_FLOAT: { \ -      CONV_FLOAT(tv->vval.v_float); \ -      break; \ -    } \ -    case VAR_FUNC: { \ -      CONV_FUNC(tv->vval.v_string); \ -      break; \ -    } \ -    case VAR_LIST: { \ -      if (tv->vval.v_list == NULL || tv->vval.v_list->lv_len == 0) { \ -        CONV_EMPTY_LIST(); \ -        break; \ -      } \ -      CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, kMPConvList); \ -      CONV_LIST_START(tv->vval.v_list); \ -      kv_push(*mpstack, ((MPConvStackVal) { \ -        .type = kMPConvList, \ -        .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: { \ -          CONV_NIL(); \ -          break; \ -        } \ -        case kSpecialVarTrue: \ -        case kSpecialVarFalse: { \ -          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) { \ -        CONV_EMPTY_DICT(); \ -        break; \ -      } \ -      const dictitem_T *type_di; \ -      const dictitem_T *val_di; \ -      if (CONV_ALLOW_SPECIAL \ -          && 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: { \ -            CONV_NIL(); \ -            break; \ -          } \ -          case kMPBoolean: { \ -            if (val_di->di_tv.v_type != VAR_NUMBER) { \ -              goto name##_convert_one_value_regular_dict; \ -            } \ -            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) { \ -              CONV_UNSIGNED_NUMBER(number); \ -            } else { \ -              CONV_NUMBER(-number); \ -            } \ -            break; \ -          } \ -          case kMPFloat: { \ -            if (val_di->di_tv.v_type != VAR_FLOAT) { \ -              goto name##_convert_one_value_regular_dict; \ -            } \ -            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) { \ -              CONV_STR_STRING(buf, len); \ -            } else { \ -              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; \ -            } \ -            CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, lv_copyID, \ -                                 kMPConvList); \ -            CONV_LIST_START(val_di->di_tv.vval.v_list); \ -            kv_push(*mpstack, ((MPConvStackVal) { \ -              .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) { \ -              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; \ -              } \ -            } \ -            CHECK_SELF_REFERENCE(val_list, lv_copyID, kMPConvPairs); \ -            CONV_DICT_START(val_list->lv_len); \ -            kv_push(*mpstack, ((MPConvStackVal) { \ -              .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; \ -            } \ -            CONV_EXT_STRING(buf, len, type); \ -            xfree(buf); \ -            break; \ -          } \ -        } \ -        break; \ -      } \ -name##_convert_one_value_regular_dict: \ -      CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, kMPConvDict); \ -      CONV_DICT_START(tv->vval.v_dict->dv_hashtab.ht_used); \ -      kv_push(*mpstack, ((MPConvStackVal) { \ -        .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; \ -  kv_init(mpstack); \ -  if (name##_convert_one_value(firstargname, &mpstack, tv, copyID, objname) \ -      == FAIL) { \ -    goto encode_vim_to_##name##_error_ret; \ -  } \ -  while (kv_size(mpstack)) { \ -    MPConvStackVal *cur_mpsv = &kv_A(mpstack, kv_size(mpstack) - 1); \ -    typval_T *cur_tv = NULL; \ -    switch (cur_mpsv->type) { \ -      case kMPConvDict: { \ -        if (!cur_mpsv->data.d.todo) { \ -          (void) kv_pop(mpstack); \ -          cur_mpsv->data.d.dict->dv_copyID = copyID - 1; \ -          CONV_DICT_END(); \ -          continue; \ -        } else if (cur_mpsv->data.d.todo \ -                   != cur_mpsv->data.d.dict->dv_hashtab.ht_used) { \ -          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++; \ -        CONV_STR_STRING(&di->di_key[0], STRLEN(&di->di_key[0])); \ -        CONV_DICT_AFTER_KEY(); \ -        cur_tv = &di->di_tv; \ -        break; \ -      } \ -      case kMPConvList: { \ -        if (cur_mpsv->data.l.li == NULL) { \ -          (void) kv_pop(mpstack); \ -          cur_mpsv->data.l.list->lv_copyID = copyID - 1; \ -          CONV_LIST_END(cur_mpsv->data.l.list); \ -          continue; \ -        } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ -          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) kv_pop(mpstack); \ -          cur_mpsv->data.l.list->lv_copyID = copyID - 1; \ -          CONV_DICT_END(); \ -          continue; \ -        } else if (cur_mpsv->data.l.li != cur_mpsv->data.l.list->lv_first) { \ -          CONV_DICT_BETWEEN_ITEMS(); \ -        } \ -        const list_T *const kv_pair = cur_mpsv->data.l.li->li_tv.vval.v_list; \ -        CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair); \ -        if (name##_convert_one_value(firstargname, &mpstack, \ -                                     &kv_pair->lv_first->li_tv, copyID, \ -                                     objname) == FAIL) { \ -          goto encode_vim_to_##name##_error_ret; \ -        } \ -        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; \ -      } \ -    } \ -    assert(cur_tv != NULL); \ -    if (name##_convert_one_value(firstargname, &mpstack, cur_tv, copyID, \ -                                 objname) == FAIL) { \ -      goto encode_vim_to_##name##_error_ret; \ -    } \ -  } \ -  kv_destroy(mpstack); \ -  return OK; \ -encode_vim_to_##name##_error_ret: \ -  kv_destroy(mpstack); \ -  return FAIL; \ -} - -#define CONV_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STRING(buf, len) \      do { \        const char *const buf_ = (const char *) buf; \        if (buf == NULL) { \ @@ -655,19 +273,19 @@ encode_vim_to_##name##_error_ret: \        } \      } while (0) -#define CONV_STR_STRING(buf, len) \ -    CONV_STRING(buf, len) +#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \ +    TYPVAL_ENCODE_CONV_STRING(buf, len) -#define CONV_EXT_STRING(buf, len, type) +#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) -#define CONV_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_NUMBER(num) \      do { \        char numbuf[NUMBUFLEN]; \        vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRId64, (int64_t) (num)); \        ga_concat(gap, numbuf); \      } while (0) -#define CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(flt) \      do { \        const float_T flt_ = (flt); \        switch (fpclassify(flt_)) { \ @@ -690,51 +308,51 @@ encode_vim_to_##name##_error_ret: \        } \      } while (0) -#define CONV_FUNC(fun) \ +#define TYPVAL_ENCODE_CONV_FUNC(fun) \      do { \        ga_concat(gap, "function("); \ -      CONV_STRING(fun, STRLEN(fun)); \ +      TYPVAL_ENCODE_CONV_STRING(fun, STRLEN(fun)); \        ga_append(gap, ')'); \      } while (0) -#define CONV_EMPTY_LIST() \ +#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \      ga_concat(gap, "[]") -#define CONV_LIST_START(lst) \ +#define TYPVAL_ENCODE_CONV_LIST_START(len) \      ga_append(gap, '[') -#define CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \      ga_concat(gap, "{}") -#define CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL() \      ga_concat(gap, "v:null") -#define CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(num) \      ga_concat(gap, ((num)? "v:true": "v:false")) -#define CONV_UNSIGNED_NUMBER(num) +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) -#define CONV_DICT_START(len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(len) \      ga_append(gap, '{') -#define CONV_DICT_END() \ +#define TYPVAL_ENCODE_CONV_DICT_END() \      ga_append(gap, '}') -#define CONV_DICT_AFTER_KEY() \ +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() \      ga_concat(gap, ": ") -#define CONV_DICT_BETWEEN_ITEMS() \ +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() \      ga_concat(gap, ", ") -#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair) +#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) -#define CONV_LIST_END(lst) \ +#define TYPVAL_ENCODE_CONV_LIST_END() \      ga_append(gap, ']') -#define CONV_LIST_BETWEEN_ITEMS() \ -    CONV_DICT_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() \ +    TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() -#define CONV_RECURSE(val, conv_type) \ +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \      do { \        if (!did_echo_string_emsg) { \          /* Only give this message once for a recursive call to avoid */ \ @@ -764,12 +382,12 @@ encode_vim_to_##name##_error_ret: \        return OK; \      } while (0) -#define CONV_ALLOW_SPECIAL false +#define TYPVAL_ENCODE_ALLOW_SPECIALS false -DEFINE_VIML_CONV_FUNCTIONS(static, string, garray_T *const, gap) +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(static, string, garray_T *const, gap) -#undef CONV_RECURSE -#define CONV_RECURSE(val, conv_type) \ +#undef TYPVAL_ENCODE_CONV_RECURSE +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \      do { \        char ebuf[NUMBUFLEN + 7]; \        size_t backref = 0; \ @@ -796,10 +414,10 @@ DEFINE_VIML_CONV_FUNCTIONS(static, string, garray_T *const, gap)        return OK; \      } while (0) -DEFINE_VIML_CONV_FUNCTIONS(, echo, garray_T *const, gap) +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(, echo, garray_T *const, gap) -#undef CONV_RECURSE -#define CONV_RECURSE(val, conv_type) \ +#undef TYPVAL_ENCODE_CONV_RECURSE +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \      do { \        if (!did_echo_string_emsg) { \          /* Only give this message once for a recursive call to avoid */ \ @@ -811,27 +429,27 @@ DEFINE_VIML_CONV_FUNCTIONS(, echo, garray_T *const, gap)        return OK; \      } while (0) -#undef CONV_ALLOW_SPECIAL -#define CONV_ALLOW_SPECIAL true +#undef TYPVAL_ENCODE_ALLOW_SPECIALS +#define TYPVAL_ENCODE_ALLOW_SPECIALS true -#undef CONV_NIL -#define CONV_NIL() \ +#undef TYPVAL_ENCODE_CONV_NIL +#define TYPVAL_ENCODE_CONV_NIL() \        ga_concat(gap, "null") -#undef CONV_BOOL -#define CONV_BOOL(num) \ +#undef TYPVAL_ENCODE_CONV_BOOL +#define TYPVAL_ENCODE_CONV_BOOL(num) \        ga_concat(gap, ((num)? "true": "false")) -#undef CONV_UNSIGNED_NUMBER -#define CONV_UNSIGNED_NUMBER(num) \ +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \        do { \          char numbuf[NUMBUFLEN]; \          vim_snprintf(numbuf, ARRAY_SIZE(numbuf), "%" PRIu64, (num)); \          ga_concat(gap, numbuf); \        } while (0) -#undef CONV_FLOAT -#define CONV_FLOAT(flt) \ +#undef TYPVAL_ENCODE_CONV_FLOAT +#define TYPVAL_ENCODE_CONV_FLOAT(flt) \      do { \        const float_T flt_ = (flt); \        switch (fpclassify(flt_)) { \ @@ -1019,24 +637,24 @@ static inline int convert_to_json_string(garray_T *const gap,    return OK;  } -#undef CONV_STRING -#define CONV_STRING(buf, len) \ +#undef TYPVAL_ENCODE_CONV_STRING +#define TYPVAL_ENCODE_CONV_STRING(buf, len) \      do { \        if (convert_to_json_string(gap, (const char *) (buf), (len)) != OK) { \          return FAIL; \        } \      } while (0) -#undef CONV_EXT_STRING -#define CONV_EXT_STRING(buf, len, type) \ +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \      do { \        xfree(buf); \        EMSG(_("E474: Unable to convert EXT string to JSON")); \        return FAIL; \      } while (0) -#undef CONV_FUNC -#define CONV_FUNC(fun) \ +#undef TYPVAL_ENCODE_CONV_FUNC +#define TYPVAL_ENCODE_CONV_FUNC(fun) \      return conv_error(_("E474: Error while dumping %s, %s: " \                          "attempt to dump function reference"), \                        mpstack, objname) @@ -1080,38 +698,38 @@ static inline bool check_json_key(const typval_T *const tv)    return true;  } -#undef CONV_SPECIAL_DICT_KEY_CHECK -#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair) \ +#undef TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK +#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) \      do { \        if (!check_json_key(&kv_pair->lv_first->li_tv)) { \          EMSG(_("E474: Invalid key in special dictionary")); \ -        goto encode_vim_to_##name##_error_ret; \ +        goto label; \        } \      } while (0) -DEFINE_VIML_CONV_FUNCTIONS(static, json, garray_T *const, gap) - -#undef CONV_STRING -#undef CONV_STR_STRING -#undef CONV_EXT_STRING -#undef CONV_NUMBER -#undef CONV_FLOAT -#undef CONV_FUNC -#undef CONV_EMPTY_LIST -#undef CONV_LIST_START -#undef CONV_EMPTY_DICT -#undef CONV_NIL -#undef CONV_BOOL -#undef CONV_UNSIGNED_NUMBER -#undef CONV_DICT_START -#undef CONV_DICT_END -#undef CONV_DICT_AFTER_KEY -#undef CONV_DICT_BETWEEN_ITEMS -#undef CONV_SPECIAL_DICT_KEY_CHECK -#undef CONV_LIST_END -#undef CONV_LIST_BETWEEN_ITEMS -#undef CONV_RECURSE -#undef CONV_ALLOW_SPECIAL +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(static, json, garray_T *const, gap) + +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_FUNC +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CONV_NIL +#undef TYPVAL_ENCODE_CONV_BOOL +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#undef TYPVAL_ENCODE_CONV_DICT_START +#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_CONV_LIST_END +#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_RECURSE +#undef TYPVAL_ENCODE_ALLOW_SPECIALS  /// Return a string with the string representation of a variable.  /// Puts quotes around strings, so that they can be parsed back by eval(). @@ -1181,7 +799,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)    return (char *) ga.ga_data;  } -#define CONV_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STRING(buf, len) \      do { \        if (buf == NULL) { \          msgpack_pack_bin(packer, 0); \ @@ -1192,7 +810,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)        } \      } while (0) -#define CONV_STR_STRING(buf, len) \ +#define TYPVAL_ENCODE_CONV_STR_STRING(buf, len) \      do { \        if (buf == NULL) { \          msgpack_pack_str(packer, 0); \ @@ -1203,7 +821,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)        } \      } while (0) -#define CONV_EXT_STRING(buf, len, type) \ +#define TYPVAL_ENCODE_CONV_EXT_STRING(buf, len, type) \      do { \        if (buf == NULL) { \          msgpack_pack_ext(packer, 0, (int8_t) type); \ @@ -1214,30 +832,30 @@ char *encode_tv2json(typval_T *tv, size_t *len)        } \      } while (0) -#define CONV_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_NUMBER(num) \      msgpack_pack_int64(packer, (int64_t) (num)) -#define CONV_FLOAT(flt) \ +#define TYPVAL_ENCODE_CONV_FLOAT(flt) \      msgpack_pack_double(packer, (double) (flt)) -#define CONV_FUNC(fun) \ +#define TYPVAL_ENCODE_CONV_FUNC(fun) \      return conv_error(_("E951: Error while dumping %s, %s: " \                          "attempt to dump function reference"), \                        mpstack, objname) -#define CONV_EMPTY_LIST() \ +#define TYPVAL_ENCODE_CONV_EMPTY_LIST() \      msgpack_pack_array(packer, 0) -#define CONV_LIST_START(lst) \ -    msgpack_pack_array(packer, (size_t) (lst)->lv_len) +#define TYPVAL_ENCODE_CONV_LIST_START(len) \ +    msgpack_pack_array(packer, (size_t) (len)) -#define CONV_EMPTY_DICT() \ +#define TYPVAL_ENCODE_CONV_EMPTY_DICT() \      msgpack_pack_map(packer, 0) -#define CONV_NIL() \ +#define TYPVAL_ENCODE_CONV_NIL() \      msgpack_pack_nil(packer) -#define CONV_BOOL(num) \ +#define TYPVAL_ENCODE_CONV_BOOL(num) \      do { \        if ((num)) { \          msgpack_pack_true(packer); \ @@ -1246,51 +864,51 @@ char *encode_tv2json(typval_T *tv, size_t *len)        } \      } while (0) -#define CONV_UNSIGNED_NUMBER(num) \ +#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(num) \      msgpack_pack_uint64(packer, (num)) -#define CONV_DICT_START(len) \ +#define TYPVAL_ENCODE_CONV_DICT_START(len) \      msgpack_pack_map(packer, (size_t) (len)) -#define CONV_DICT_END() +#define TYPVAL_ENCODE_CONV_DICT_END() -#define CONV_DICT_AFTER_KEY() +#define TYPVAL_ENCODE_CONV_DICT_AFTER_KEY() -#define CONV_DICT_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_DICT_BETWEEN_ITEMS() -#define CONV_SPECIAL_DICT_KEY_CHECK(name, kv_pair) +#define TYPVAL_ENCODE_CONV_SPECIAL_DICT_KEY_CHECK(label, kv_pair) -#define CONV_LIST_END(lst) +#define TYPVAL_ENCODE_CONV_LIST_END() -#define CONV_LIST_BETWEEN_ITEMS() +#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS() -#define CONV_RECURSE(val, conv_type) \ +#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \      return conv_error(_("E952: Unable to dump %s: " \                          "container references itself in %s"), \                        mpstack, objname) -#define CONV_ALLOW_SPECIAL true - -DEFINE_VIML_CONV_FUNCTIONS(, msgpack, msgpack_packer *const, packer) - -#undef CONV_STRING -#undef CONV_STR_STRING -#undef CONV_EXT_STRING -#undef CONV_NUMBER -#undef CONV_FLOAT -#undef CONV_FUNC -#undef CONV_EMPTY_LIST -#undef CONV_LIST_START -#undef CONV_EMPTY_DICT -#undef CONV_NIL -#undef CONV_BOOL -#undef CONV_UNSIGNED_NUMBER -#undef CONV_DICT_START -#undef CONV_DICT_END -#undef CONV_DICT_AFTER_KEY -#undef CONV_DICT_BETWEEN_ITEMS -#undef CONV_SPECIAL_DICT_KEY_CHECK -#undef CONV_LIST_END -#undef CONV_LIST_BETWEEN_ITEMS -#undef CONV_RECURSE -#undef CONV_ALLOW_SPECIAL +#define TYPVAL_ENCODE_ALLOW_SPECIALS true + +TYPVAL_ENCODE_DEFINE_CONV_FUNCTIONS(, msgpack, msgpack_packer *const, packer) + +#undef TYPVAL_ENCODE_CONV_STRING +#undef TYPVAL_ENCODE_CONV_STR_STRING +#undef TYPVAL_ENCODE_CONV_EXT_STRING +#undef TYPVAL_ENCODE_CONV_NUMBER +#undef TYPVAL_ENCODE_CONV_FLOAT +#undef TYPVAL_ENCODE_CONV_FUNC +#undef TYPVAL_ENCODE_CONV_EMPTY_LIST +#undef TYPVAL_ENCODE_CONV_LIST_START +#undef TYPVAL_ENCODE_CONV_EMPTY_DICT +#undef TYPVAL_ENCODE_CONV_NIL +#undef TYPVAL_ENCODE_CONV_BOOL +#undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER +#undef TYPVAL_ENCODE_CONV_DICT_START +#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_CONV_LIST_END +#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS +#undef TYPVAL_ENCODE_CONV_RECURSE +#undef TYPVAL_ENCODE_ALLOW_SPECIALS | 
