Mercurial > vim
comparison src/eval.c @ 8710:af3cb5c068fd v7.4.1644
commit https://github.com/vim/vim/commit/24c77a1e3a2ad510582116229462b482d69b4b8e
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Mar 24 21:23:06 2016 +0100
patch 7.4.1644
Problem: Using string() on a partial that exists in the dictionary it binds
results in an error. (Nikolai Pavlov)
Solution: Make string() not fail on a recursively nested structure. (Ken
Takta)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 24 Mar 2016 21:30:06 +0100 |
parents | 31f9fa8e1532 |
children | 65130a9d3386 |
comparison
equal
deleted
inserted
replaced
8709:0e13fb6f07f4 | 8710:af3cb5c068fd |
---|---|
7849 *tofree = NULL; | 7849 *tofree = NULL; |
7850 r = tv->vval.v_string; | 7850 r = tv->vval.v_string; |
7851 break; | 7851 break; |
7852 | 7852 |
7853 case VAR_PARTIAL: | 7853 case VAR_PARTIAL: |
7854 *tofree = NULL; | |
7855 /* TODO: arguments */ | |
7856 r = tv->vval.v_partial == NULL ? NULL : tv->vval.v_partial->pt_name; | |
7857 break; | |
7858 | |
7859 case VAR_LIST: | |
7860 if (tv->vval.v_list == NULL) | |
7861 { | |
7862 *tofree = NULL; | |
7863 r = NULL; | |
7864 } | |
7865 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID) | |
7866 { | |
7867 *tofree = NULL; | |
7868 r = (char_u *)"[...]"; | |
7869 } | |
7870 else | |
7871 { | |
7872 tv->vval.v_list->lv_copyID = copyID; | |
7873 *tofree = list2string(tv, copyID); | |
7874 r = *tofree; | |
7875 } | |
7876 break; | |
7877 | |
7878 case VAR_DICT: | |
7879 if (tv->vval.v_dict == NULL) | |
7880 { | |
7881 *tofree = NULL; | |
7882 r = NULL; | |
7883 } | |
7884 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID) | |
7885 { | |
7886 *tofree = NULL; | |
7887 r = (char_u *)"{...}"; | |
7888 } | |
7889 else | |
7890 { | |
7891 tv->vval.v_dict->dv_copyID = copyID; | |
7892 *tofree = dict2string(tv, copyID); | |
7893 r = *tofree; | |
7894 } | |
7895 break; | |
7896 | |
7897 case VAR_STRING: | |
7898 case VAR_NUMBER: | |
7899 case VAR_UNKNOWN: | |
7900 case VAR_JOB: | |
7901 case VAR_CHANNEL: | |
7902 *tofree = NULL; | |
7903 r = get_tv_string_buf(tv, numbuf); | |
7904 break; | |
7905 | |
7906 case VAR_FLOAT: | |
7907 #ifdef FEAT_FLOAT | |
7908 *tofree = NULL; | |
7909 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float); | |
7910 r = numbuf; | |
7911 break; | |
7912 #endif | |
7913 | |
7914 case VAR_SPECIAL: | |
7915 *tofree = NULL; | |
7916 r = (char_u *)get_var_special_name(tv->vval.v_number); | |
7917 break; | |
7918 } | |
7919 | |
7920 if (--recurse == 0) | |
7921 did_echo_string_emsg = FALSE; | |
7922 return r; | |
7923 } | |
7924 | |
7925 /* | |
7926 * Return a string with the string representation of a variable. | |
7927 * If the memory is allocated "tofree" is set to it, otherwise NULL. | |
7928 * "numbuf" is used for a number. | |
7929 * Puts quotes around strings, so that they can be parsed back by eval(). | |
7930 * May return NULL. | |
7931 */ | |
7932 static char_u * | |
7933 tv2string( | |
7934 typval_T *tv, | |
7935 char_u **tofree, | |
7936 char_u *numbuf, | |
7937 int copyID) | |
7938 { | |
7939 switch (tv->v_type) | |
7940 { | |
7941 case VAR_FUNC: | |
7942 *tofree = string_quote(tv->vval.v_string, TRUE); | |
7943 return *tofree; | |
7944 case VAR_PARTIAL: | |
7945 { | 7854 { |
7946 partial_T *pt = tv->vval.v_partial; | 7855 partial_T *pt = tv->vval.v_partial; |
7947 char_u *fname = string_quote(pt == NULL ? NULL | 7856 char_u *fname = string_quote(pt == NULL ? NULL |
7948 : pt->pt_name, FALSE); | 7857 : pt->pt_name, FALSE); |
7949 garray_T ga; | 7858 garray_T ga; |
7981 vim_free(tf); | 7890 vim_free(tf); |
7982 } | 7891 } |
7983 ga_concat(&ga, (char_u *)")"); | 7892 ga_concat(&ga, (char_u *)")"); |
7984 | 7893 |
7985 *tofree = ga.ga_data; | 7894 *tofree = ga.ga_data; |
7986 return *tofree; | 7895 r = *tofree; |
7896 break; | |
7987 } | 7897 } |
7898 | |
7899 case VAR_LIST: | |
7900 if (tv->vval.v_list == NULL) | |
7901 { | |
7902 *tofree = NULL; | |
7903 r = NULL; | |
7904 } | |
7905 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID) | |
7906 { | |
7907 *tofree = NULL; | |
7908 r = (char_u *)"[...]"; | |
7909 } | |
7910 else | |
7911 { | |
7912 tv->vval.v_list->lv_copyID = copyID; | |
7913 *tofree = list2string(tv, copyID); | |
7914 r = *tofree; | |
7915 } | |
7916 break; | |
7917 | |
7918 case VAR_DICT: | |
7919 if (tv->vval.v_dict == NULL) | |
7920 { | |
7921 *tofree = NULL; | |
7922 r = NULL; | |
7923 } | |
7924 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID) | |
7925 { | |
7926 *tofree = NULL; | |
7927 r = (char_u *)"{...}"; | |
7928 } | |
7929 else | |
7930 { | |
7931 tv->vval.v_dict->dv_copyID = copyID; | |
7932 *tofree = dict2string(tv, copyID); | |
7933 r = *tofree; | |
7934 } | |
7935 break; | |
7936 | |
7937 case VAR_STRING: | |
7938 case VAR_NUMBER: | |
7939 case VAR_UNKNOWN: | |
7940 case VAR_JOB: | |
7941 case VAR_CHANNEL: | |
7942 *tofree = NULL; | |
7943 r = get_tv_string_buf(tv, numbuf); | |
7944 break; | |
7945 | |
7946 case VAR_FLOAT: | |
7947 #ifdef FEAT_FLOAT | |
7948 *tofree = NULL; | |
7949 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float); | |
7950 r = numbuf; | |
7951 break; | |
7952 #endif | |
7953 | |
7954 case VAR_SPECIAL: | |
7955 *tofree = NULL; | |
7956 r = (char_u *)get_var_special_name(tv->vval.v_number); | |
7957 break; | |
7958 } | |
7959 | |
7960 if (--recurse == 0) | |
7961 did_echo_string_emsg = FALSE; | |
7962 return r; | |
7963 } | |
7964 | |
7965 /* | |
7966 * Return a string with the string representation of a variable. | |
7967 * If the memory is allocated "tofree" is set to it, otherwise NULL. | |
7968 * "numbuf" is used for a number. | |
7969 * Puts quotes around strings, so that they can be parsed back by eval(). | |
7970 * May return NULL. | |
7971 */ | |
7972 static char_u * | |
7973 tv2string( | |
7974 typval_T *tv, | |
7975 char_u **tofree, | |
7976 char_u *numbuf, | |
7977 int copyID) | |
7978 { | |
7979 switch (tv->v_type) | |
7980 { | |
7981 case VAR_FUNC: | |
7982 *tofree = string_quote(tv->vval.v_string, TRUE); | |
7983 return *tofree; | |
7988 case VAR_STRING: | 7984 case VAR_STRING: |
7989 *tofree = string_quote(tv->vval.v_string, FALSE); | 7985 *tofree = string_quote(tv->vval.v_string, FALSE); |
7990 return *tofree; | 7986 return *tofree; |
7991 case VAR_FLOAT: | 7987 case VAR_FLOAT: |
7992 #ifdef FEAT_FLOAT | 7988 #ifdef FEAT_FLOAT |
7995 return numbuf; | 7991 return numbuf; |
7996 #endif | 7992 #endif |
7997 case VAR_NUMBER: | 7993 case VAR_NUMBER: |
7998 case VAR_LIST: | 7994 case VAR_LIST: |
7999 case VAR_DICT: | 7995 case VAR_DICT: |
7996 case VAR_PARTIAL: | |
8000 case VAR_SPECIAL: | 7997 case VAR_SPECIAL: |
8001 case VAR_JOB: | 7998 case VAR_JOB: |
8002 case VAR_CHANNEL: | 7999 case VAR_CHANNEL: |
8003 case VAR_UNKNOWN: | 8000 case VAR_UNKNOWN: |
8004 break; | 8001 break; |
19256 { | 19253 { |
19257 char_u *tofree; | 19254 char_u *tofree; |
19258 char_u numbuf[NUMBUFLEN]; | 19255 char_u numbuf[NUMBUFLEN]; |
19259 | 19256 |
19260 rettv->v_type = VAR_STRING; | 19257 rettv->v_type = VAR_STRING; |
19261 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0); | 19258 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, |
19259 get_copyID()); | |
19262 /* Make a copy if we have a value but it's not in allocated memory. */ | 19260 /* Make a copy if we have a value but it's not in allocated memory. */ |
19263 if (rettv->vval.v_string != NULL && tofree == NULL) | 19261 if (rettv->vval.v_string != NULL && tofree == NULL) |
19264 rettv->vval.v_string = vim_strsave(rettv->vval.v_string); | 19262 rettv->vval.v_string = vim_strsave(rettv->vval.v_string); |
19265 } | 19263 } |
19266 | 19264 |