Mercurial > vim
comparison src/eval.c @ 15454:1d2b5c016f17 v8.1.0735
patch 8.1.0735: cannot handle binary data
commit https://github.com/vim/vim/commit/6e5ea8d2a995b32bbc5972edc4f827b959f2702f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 12 22:47:31 2019 +0100
patch 8.1.0735: cannot handle binary data
Problem: Cannot handle binary data.
Solution: Add the Blob type. (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/3638)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 12 Jan 2019 23:00:06 +0100 |
parents | dada0b389d4f |
children | f01eb1aed348 |
comparison
equal
deleted
inserted
replaced
15453:cdee6e827112 | 15454:1d2b5c016f17 |
---|---|
76 { | 76 { |
77 int fi_semicolon; /* TRUE if ending in '; var]' */ | 77 int fi_semicolon; /* TRUE if ending in '; var]' */ |
78 int fi_varcount; /* nr of variables in the list */ | 78 int fi_varcount; /* nr of variables in the list */ |
79 listwatch_T fi_lw; /* keep an eye on the item used. */ | 79 listwatch_T fi_lw; /* keep an eye on the item used. */ |
80 list_T *fi_list; /* list being used */ | 80 list_T *fi_list; /* list being used */ |
81 int fi_bi; /* index of blob */ | |
82 blob_T *fi_blob; /* blob being used */ | |
81 } forinfo_T; | 83 } forinfo_T; |
82 | 84 |
83 | 85 |
84 /* | 86 /* |
85 * Array to hold the value of v: variables. | 87 * Array to hold the value of v: variables. |
185 {VV_NAME("t_float", VAR_NUMBER), VV_RO}, | 187 {VV_NAME("t_float", VAR_NUMBER), VV_RO}, |
186 {VV_NAME("t_bool", VAR_NUMBER), VV_RO}, | 188 {VV_NAME("t_bool", VAR_NUMBER), VV_RO}, |
187 {VV_NAME("t_none", VAR_NUMBER), VV_RO}, | 189 {VV_NAME("t_none", VAR_NUMBER), VV_RO}, |
188 {VV_NAME("t_job", VAR_NUMBER), VV_RO}, | 190 {VV_NAME("t_job", VAR_NUMBER), VV_RO}, |
189 {VV_NAME("t_channel", VAR_NUMBER), VV_RO}, | 191 {VV_NAME("t_channel", VAR_NUMBER), VV_RO}, |
192 {VV_NAME("t_blob", VAR_NUMBER), VV_RO}, | |
190 {VV_NAME("termrfgresp", VAR_STRING), VV_RO}, | 193 {VV_NAME("termrfgresp", VAR_STRING), VV_RO}, |
191 {VV_NAME("termrbgresp", VAR_STRING), VV_RO}, | 194 {VV_NAME("termrbgresp", VAR_STRING), VV_RO}, |
192 {VV_NAME("termu7resp", VAR_STRING), VV_RO}, | 195 {VV_NAME("termu7resp", VAR_STRING), VV_RO}, |
193 {VV_NAME("termstyleresp", VAR_STRING), VV_RO}, | 196 {VV_NAME("termstyleresp", VAR_STRING), VV_RO}, |
194 {VV_NAME("termblinkresp", VAR_STRING), VV_RO}, | 197 {VV_NAME("termblinkresp", VAR_STRING), VV_RO}, |
200 #define vv_nr vv_di.di_tv.vval.v_number | 203 #define vv_nr vv_di.di_tv.vval.v_number |
201 #define vv_float vv_di.di_tv.vval.v_float | 204 #define vv_float vv_di.di_tv.vval.v_float |
202 #define vv_str vv_di.di_tv.vval.v_string | 205 #define vv_str vv_di.di_tv.vval.v_string |
203 #define vv_list vv_di.di_tv.vval.v_list | 206 #define vv_list vv_di.di_tv.vval.v_list |
204 #define vv_dict vv_di.di_tv.vval.v_dict | 207 #define vv_dict vv_di.di_tv.vval.v_dict |
208 #define vv_blob vv_di.di_tv.vval.v_blob | |
205 #define vv_tv vv_di.di_tv | 209 #define vv_tv vv_di.di_tv |
206 | 210 |
207 static dictitem_T vimvars_var; /* variable used for v: */ | 211 static dictitem_T vimvars_var; /* variable used for v: */ |
208 #define vimvarht vimvardict.dv_hashtab | 212 #define vimvarht vimvardict.dv_hashtab |
209 | 213 |
336 set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT); | 340 set_vim_var_nr(VV_TYPE_FLOAT, VAR_TYPE_FLOAT); |
337 set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL); | 341 set_vim_var_nr(VV_TYPE_BOOL, VAR_TYPE_BOOL); |
338 set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE); | 342 set_vim_var_nr(VV_TYPE_NONE, VAR_TYPE_NONE); |
339 set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB); | 343 set_vim_var_nr(VV_TYPE_JOB, VAR_TYPE_JOB); |
340 set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL); | 344 set_vim_var_nr(VV_TYPE_CHANNEL, VAR_TYPE_CHANNEL); |
345 set_vim_var_nr(VV_TYPE_BLOB, VAR_TYPE_BLOB); | |
341 | 346 |
342 set_reg_var(0); /* default for v:register is not 0 but '"' */ | 347 set_reg_var(0); /* default for v:register is not 0 but '"' */ |
343 | 348 |
344 #ifdef EBCDIC | 349 #ifdef EBCDIC |
345 /* | 350 /* |
1916 var2.v_type = VAR_UNKNOWN; | 1921 var2.v_type = VAR_UNKNOWN; |
1917 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT)) | 1922 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT)) |
1918 { | 1923 { |
1919 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL) | 1924 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL) |
1920 && !(lp->ll_tv->v_type == VAR_DICT | 1925 && !(lp->ll_tv->v_type == VAR_DICT |
1921 && lp->ll_tv->vval.v_dict != NULL)) | 1926 && lp->ll_tv->vval.v_dict != NULL) |
1927 && !(lp->ll_tv->v_type == VAR_BLOB | |
1928 && lp->ll_tv->vval.v_blob != NULL)) | |
1922 { | 1929 { |
1923 if (!quiet) | 1930 if (!quiet) |
1924 EMSG(_("E689: Can only index a List or Dictionary")); | 1931 EMSG(_("E689: Can only index a List, Dictionary or Blob")); |
1925 return NULL; | 1932 return NULL; |
1926 } | 1933 } |
1927 if (lp->ll_range) | 1934 if (lp->ll_range) |
1928 { | 1935 { |
1929 if (!quiet) | 1936 if (!quiet) |
1972 if (!quiet) | 1979 if (!quiet) |
1973 EMSG(_(e_dictrange)); | 1980 EMSG(_(e_dictrange)); |
1974 clear_tv(&var1); | 1981 clear_tv(&var1); |
1975 return NULL; | 1982 return NULL; |
1976 } | 1983 } |
1977 if (rettv != NULL && (rettv->v_type != VAR_LIST | 1984 if (rettv != NULL |
1978 || rettv->vval.v_list == NULL)) | 1985 && !(rettv->v_type == VAR_LIST |
1986 || rettv->vval.v_list != NULL) | |
1987 && !(rettv->v_type == VAR_BLOB | |
1988 || rettv->vval.v_blob != NULL)) | |
1979 { | 1989 { |
1980 if (!quiet) | 1990 if (!quiet) |
1981 EMSG(_("E709: [:] requires a List value")); | 1991 EMSG(_("E709: [:] requires a List or Blob value")); |
1982 clear_tv(&var1); | 1992 clear_tv(&var1); |
1983 return NULL; | 1993 return NULL; |
1984 } | 1994 } |
1985 p = skipwhite(p + 1); | 1995 p = skipwhite(p + 1); |
1986 if (*p == ']') | 1996 if (*p == ']') |
2095 } | 2105 } |
2096 | 2106 |
2097 clear_tv(&var1); | 2107 clear_tv(&var1); |
2098 lp->ll_tv = &lp->ll_di->di_tv; | 2108 lp->ll_tv = &lp->ll_di->di_tv; |
2099 } | 2109 } |
2110 else if (lp->ll_tv->v_type == VAR_BLOB) | |
2111 { | |
2112 /* | |
2113 * Get the number and item for the only or first index of the List. | |
2114 */ | |
2115 if (empty1) | |
2116 lp->ll_n1 = 0; | |
2117 else | |
2118 // is number or string | |
2119 lp->ll_n1 = (long)tv_get_number(&var1); | |
2120 clear_tv(&var1); | |
2121 | |
2122 if (lp->ll_n1 < 0 | |
2123 || lp->ll_n1 > blob_len(lp->ll_tv->vval.v_blob)) | |
2124 { | |
2125 if (!quiet) | |
2126 EMSGN(_(e_listidx), lp->ll_n1); | |
2127 return NULL; | |
2128 } | |
2129 if (lp->ll_range && !lp->ll_empty2) | |
2130 { | |
2131 lp->ll_n2 = (long)tv_get_number(&var2); | |
2132 clear_tv(&var2); | |
2133 } | |
2134 lp->ll_blob = lp->ll_tv->vval.v_blob; | |
2135 lp->ll_tv = NULL; | |
2136 } | |
2100 else | 2137 else |
2101 { | 2138 { |
2102 /* | 2139 /* |
2103 * Get the number and item for the only or first index of the List. | 2140 * Get the number and item for the only or first index of the List. |
2104 */ | 2141 */ |
2199 | 2236 |
2200 if (lp->ll_tv == NULL) | 2237 if (lp->ll_tv == NULL) |
2201 { | 2238 { |
2202 cc = *endp; | 2239 cc = *endp; |
2203 *endp = NUL; | 2240 *endp = NUL; |
2204 if (op != NULL && *op != '=') | 2241 if (lp->ll_blob != NULL) |
2242 { | |
2243 int error = FALSE, val; | |
2244 if (op != NULL && *op != '=') | |
2245 { | |
2246 EMSG2(_(e_letwrong), op); | |
2247 return; | |
2248 } | |
2249 | |
2250 if (lp->ll_range && rettv->v_type == VAR_BLOB) | |
2251 { | |
2252 int i; | |
2253 | |
2254 if (blob_len(rettv->vval.v_blob) != blob_len(lp->ll_blob)) | |
2255 { | |
2256 EMSG(_("E972: Blob value has more items than target")); | |
2257 return; | |
2258 } | |
2259 | |
2260 for (i = lp->ll_n1; i <= lp->ll_n2; i++) | |
2261 blob_set(lp->ll_blob, i, | |
2262 blob_get(rettv->vval.v_blob, i)); | |
2263 } | |
2264 else | |
2265 { | |
2266 val = (int)tv_get_number_chk(rettv, &error); | |
2267 if (!error) | |
2268 { | |
2269 garray_T *gap = &lp->ll_blob->bv_ga; | |
2270 | |
2271 // Allow for appending a byte. Setting a byte beyond | |
2272 // the end is an error otherwise. | |
2273 if (lp->ll_n1 < gap->ga_len | |
2274 || (lp->ll_n1 == gap->ga_len | |
2275 && ga_grow(&lp->ll_blob->bv_ga, 1) == OK)) | |
2276 { | |
2277 blob_set(lp->ll_blob, lp->ll_n1, val); | |
2278 if (lp->ll_n1 == gap->ga_len) | |
2279 ++gap->ga_len; | |
2280 } | |
2281 else | |
2282 EMSG(_(e_invrange)); | |
2283 } | |
2284 } | |
2285 } | |
2286 else if (op != NULL && *op != '=') | |
2205 { | 2287 { |
2206 typval_T tv; | 2288 typval_T tv; |
2207 | 2289 |
2208 /* handle +=, -= and .= */ | 2290 /* handle +=, -= and .= */ |
2209 di = NULL; | 2291 di = NULL; |
2349 case VAR_PARTIAL: | 2431 case VAR_PARTIAL: |
2350 case VAR_SPECIAL: | 2432 case VAR_SPECIAL: |
2351 case VAR_JOB: | 2433 case VAR_JOB: |
2352 case VAR_CHANNEL: | 2434 case VAR_CHANNEL: |
2353 break; | 2435 break; |
2436 | |
2437 case VAR_BLOB: | |
2438 if (*op != '+' || tv2->v_type != VAR_BLOB) | |
2439 break; | |
2440 // BLOB += BLOB | |
2441 if (tv1->vval.v_blob != NULL && tv2->vval.v_blob != NULL) | |
2442 { | |
2443 blob_T *b1 = tv1->vval.v_blob; | |
2444 blob_T *b2 = tv2->vval.v_blob; | |
2445 int i, len = blob_len(b2); | |
2446 for (i = 0; i < len; i++) | |
2447 ga_append(&b1->bv_ga, blob_get(b2, i)); | |
2448 } | |
2449 return OK; | |
2354 | 2450 |
2355 case VAR_LIST: | 2451 case VAR_LIST: |
2356 if (*op != '+' || tv2->v_type != VAR_LIST) | 2452 if (*op != '+' || tv2->v_type != VAR_LIST) |
2357 break; | 2453 break; |
2358 /* List += List */ | 2454 /* List += List */ |
2449 { | 2545 { |
2450 forinfo_T *fi; | 2546 forinfo_T *fi; |
2451 char_u *expr; | 2547 char_u *expr; |
2452 typval_T tv; | 2548 typval_T tv; |
2453 list_T *l; | 2549 list_T *l; |
2550 blob_T *b; | |
2454 | 2551 |
2455 *errp = TRUE; /* default: there is an error */ | 2552 *errp = TRUE; /* default: there is an error */ |
2456 | 2553 |
2457 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T)); | 2554 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T)); |
2458 if (fi == NULL) | 2555 if (fi == NULL) |
2474 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK) | 2571 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK) |
2475 { | 2572 { |
2476 *errp = FALSE; | 2573 *errp = FALSE; |
2477 if (!skip) | 2574 if (!skip) |
2478 { | 2575 { |
2479 l = tv.vval.v_list; | 2576 if (tv.v_type == VAR_LIST) |
2480 if (tv.v_type != VAR_LIST) | 2577 { |
2578 l = tv.vval.v_list; | |
2579 if (l == NULL) | |
2580 { | |
2581 // a null list is like an empty list: do nothing | |
2582 clear_tv(&tv); | |
2583 } | |
2584 else | |
2585 { | |
2586 // No need to increment the refcount, it's already set for | |
2587 // the list being used in "tv". | |
2588 fi->fi_list = l; | |
2589 list_add_watch(l, &fi->fi_lw); | |
2590 fi->fi_lw.lw_item = l->lv_first; | |
2591 } | |
2592 } | |
2593 else if (tv.v_type == VAR_BLOB) | |
2594 { | |
2595 b = tv.vval.v_blob; | |
2596 if (b == NULL) | |
2597 clear_tv(&tv); | |
2598 else | |
2599 { | |
2600 fi->fi_blob = b; | |
2601 fi->fi_bi = 0; | |
2602 } | |
2603 } | |
2604 else | |
2481 { | 2605 { |
2482 EMSG(_(e_listreq)); | 2606 EMSG(_(e_listreq)); |
2483 clear_tv(&tv); | 2607 clear_tv(&tv); |
2484 } | |
2485 else if (l == NULL) | |
2486 { | |
2487 /* a null list is like an empty list: do nothing */ | |
2488 clear_tv(&tv); | |
2489 } | |
2490 else | |
2491 { | |
2492 /* No need to increment the refcount, it's already set for the | |
2493 * list being used in "tv". */ | |
2494 fi->fi_list = l; | |
2495 list_add_watch(l, &fi->fi_lw); | |
2496 fi->fi_lw.lw_item = l->lv_first; | |
2497 } | 2608 } |
2498 } | 2609 } |
2499 } | 2610 } |
2500 if (skip) | 2611 if (skip) |
2501 --emsg_skip; | 2612 --emsg_skip; |
2513 next_for_item(void *fi_void, char_u *arg) | 2624 next_for_item(void *fi_void, char_u *arg) |
2514 { | 2625 { |
2515 forinfo_T *fi = (forinfo_T *)fi_void; | 2626 forinfo_T *fi = (forinfo_T *)fi_void; |
2516 int result; | 2627 int result; |
2517 listitem_T *item; | 2628 listitem_T *item; |
2629 | |
2630 if (fi->fi_blob != NULL) | |
2631 { | |
2632 typval_T tv; | |
2633 | |
2634 if (fi->fi_bi >= blob_len(fi->fi_blob)) | |
2635 return FALSE; | |
2636 tv.v_type = VAR_NUMBER; | |
2637 tv.v_lock = VAR_FIXED; | |
2638 tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi); | |
2639 ++fi->fi_bi; | |
2640 return ex_let_vars(arg, &tv, TRUE, | |
2641 fi->fi_semicolon, fi->fi_varcount, NULL) == OK; | |
2642 } | |
2518 | 2643 |
2519 item = fi->fi_lw.lw_item; | 2644 item = fi->fi_lw.lw_item; |
2520 if (item == NULL) | 2645 if (item == NULL) |
2521 result = FALSE; | 2646 result = FALSE; |
2522 else | 2647 else |
2953 { | 3078 { |
2954 static int recurse = 0; | 3079 static int recurse = 0; |
2955 list_T *l; | 3080 list_T *l; |
2956 listitem_T *li; | 3081 listitem_T *li; |
2957 dict_T *d; | 3082 dict_T *d; |
3083 blob_T *b; | |
2958 hashitem_T *hi; | 3084 hashitem_T *hi; |
2959 int todo; | 3085 int todo; |
2960 | 3086 |
2961 if (recurse >= DICT_MAXNEST) | 3087 if (recurse >= DICT_MAXNEST) |
2962 { | 3088 { |
2984 case VAR_SPECIAL: | 3110 case VAR_SPECIAL: |
2985 case VAR_JOB: | 3111 case VAR_JOB: |
2986 case VAR_CHANNEL: | 3112 case VAR_CHANNEL: |
2987 break; | 3113 break; |
2988 | 3114 |
3115 case VAR_BLOB: | |
3116 if ((b = tv->vval.v_blob) != NULL) | |
3117 { | |
3118 if (lock) | |
3119 b->bv_lock |= VAR_LOCKED; | |
3120 else | |
3121 b->bv_lock &= ~VAR_LOCKED; | |
3122 } | |
3123 break; | |
2989 case VAR_LIST: | 3124 case VAR_LIST: |
2990 if ((l = tv->vval.v_list) != NULL) | 3125 if ((l = tv->vval.v_list) != NULL) |
2991 { | 3126 { |
2992 if (lock) | 3127 if (lock) |
2993 l->lv_lock |= VAR_LOCKED; | 3128 l->lv_lock |= VAR_LOCKED; |
3607 { | 3742 { |
3608 op = **arg; | 3743 op = **arg; |
3609 if (op != '+' && op != '-' && op != '.') | 3744 if (op != '+' && op != '-' && op != '.') |
3610 break; | 3745 break; |
3611 | 3746 |
3612 if ((op != '+' || rettv->v_type != VAR_LIST) | 3747 if ((op != '+' || (rettv->v_type != VAR_LIST |
3748 && rettv->v_type != VAR_BLOB)) | |
3613 #ifdef FEAT_FLOAT | 3749 #ifdef FEAT_FLOAT |
3614 && (op == '.' || rettv->v_type != VAR_FLOAT) | 3750 && (op == '.' || rettv->v_type != VAR_FLOAT) |
3615 #endif | 3751 #endif |
3616 ) | 3752 ) |
3617 { | 3753 { |
3656 } | 3792 } |
3657 p = concat_str(s1, s2); | 3793 p = concat_str(s1, s2); |
3658 clear_tv(rettv); | 3794 clear_tv(rettv); |
3659 rettv->v_type = VAR_STRING; | 3795 rettv->v_type = VAR_STRING; |
3660 rettv->vval.v_string = p; | 3796 rettv->vval.v_string = p; |
3797 } | |
3798 else if (op == '+' && rettv->v_type == VAR_BLOB | |
3799 && var2.v_type == VAR_BLOB) | |
3800 { | |
3801 blob_T *b1 = rettv->vval.v_blob; | |
3802 blob_T *b2 = var2.vval.v_blob; | |
3803 blob_T *b = blob_alloc(); | |
3804 int i; | |
3805 | |
3806 if (b != NULL) | |
3807 { | |
3808 for (i = 0; i < blob_len(b1); i++) | |
3809 ga_append(&b->bv_ga, blob_get(b1, i)); | |
3810 for (i = 0; i < blob_len(b2); i++) | |
3811 ga_append(&b->bv_ga, blob_get(b2, i)); | |
3812 | |
3813 clear_tv(rettv); | |
3814 rettv_blob_set(rettv, b); | |
3815 } | |
3661 } | 3816 } |
3662 else if (op == '+' && rettv->v_type == VAR_LIST | 3817 else if (op == '+' && rettv->v_type == VAR_LIST |
3663 && var2.v_type == VAR_LIST) | 3818 && var2.v_type == VAR_LIST) |
3664 { | 3819 { |
3665 /* concatenate Lists */ | 3820 /* concatenate Lists */ |
3919 } | 4074 } |
3920 | 4075 |
3921 /* | 4076 /* |
3922 * Handle sixth level expression: | 4077 * Handle sixth level expression: |
3923 * number number constant | 4078 * number number constant |
4079 * 0zFFFFFFFF Blob constant | |
3924 * "string" string constant | 4080 * "string" string constant |
3925 * 'string' literal string constant | 4081 * 'string' literal string constant |
3926 * &option-name option value | 4082 * &option-name option value |
3927 * @r register contents | 4083 * @r register contents |
3928 * identifier variable value | 4084 * identifier variable value |
4025 rettv->vval.v_float = f; | 4181 rettv->vval.v_float = f; |
4026 } | 4182 } |
4027 } | 4183 } |
4028 else | 4184 else |
4029 #endif | 4185 #endif |
4186 if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) | |
4030 { | 4187 { |
4188 char_u *bp; | |
4189 blob_T *blob; | |
4190 | |
4191 // Blob constant: 0z0123456789abcdef | |
4192 if (evaluate) | |
4193 blob = blob_alloc(); | |
4194 for (bp = *arg + 2; vim_isxdigit(bp[0]); bp += 2) | |
4195 { | |
4196 if (!vim_isxdigit(bp[1])) | |
4197 { | |
4198 EMSG(_("E973: Blob literal should have an even number of hex characters'")); | |
4199 vim_free(blob); | |
4200 ret = FAIL; | |
4201 break; | |
4202 } | |
4203 if (blob != NULL) | |
4204 ga_append(&blob->bv_ga, | |
4205 (hex2nr(*bp) << 4) + hex2nr(*(bp+1))); | |
4206 } | |
4207 if (blob != NULL) | |
4208 { | |
4209 ++blob->bv_refcount; | |
4210 rettv->v_type = VAR_BLOB; | |
4211 rettv->vval.v_blob = blob; | |
4212 } | |
4213 *arg = bp; | |
4214 } | |
4215 else | |
4216 { | |
4217 // decimal, hex or octal number | |
4031 vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0); | 4218 vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0); |
4032 *arg += len; | 4219 *arg += len; |
4033 if (evaluate) | 4220 if (evaluate) |
4034 { | 4221 { |
4035 rettv->v_type = VAR_NUMBER; | 4222 rettv->v_type = VAR_NUMBER; |
4261 int evaluate, | 4448 int evaluate, |
4262 int verbose) /* give error messages */ | 4449 int verbose) /* give error messages */ |
4263 { | 4450 { |
4264 int empty1 = FALSE, empty2 = FALSE; | 4451 int empty1 = FALSE, empty2 = FALSE; |
4265 typval_T var1, var2; | 4452 typval_T var1, var2; |
4453 long i; | |
4266 long n1, n2 = 0; | 4454 long n1, n2 = 0; |
4267 long len = -1; | 4455 long len = -1; |
4268 int range = FALSE; | 4456 int range = FALSE; |
4269 char_u *s; | 4457 char_u *s; |
4270 char_u *key = NULL; | 4458 char_u *key = NULL; |
4295 | 4483 |
4296 case VAR_STRING: | 4484 case VAR_STRING: |
4297 case VAR_NUMBER: | 4485 case VAR_NUMBER: |
4298 case VAR_LIST: | 4486 case VAR_LIST: |
4299 case VAR_DICT: | 4487 case VAR_DICT: |
4488 case VAR_BLOB: | |
4300 break; | 4489 break; |
4301 } | 4490 } |
4302 | 4491 |
4303 init_tv(&var1); | 4492 init_tv(&var1); |
4304 init_tv(&var2); | 4493 init_tv(&var2); |
4437 clear_tv(rettv); | 4626 clear_tv(rettv); |
4438 rettv->v_type = VAR_STRING; | 4627 rettv->v_type = VAR_STRING; |
4439 rettv->vval.v_string = s; | 4628 rettv->vval.v_string = s; |
4440 break; | 4629 break; |
4441 | 4630 |
4631 case VAR_BLOB: | |
4632 len = blob_len(rettv->vval.v_blob); | |
4633 if (range) | |
4634 { | |
4635 // The resulting variable is a substring. If the indexes | |
4636 // are out of range the result is empty. | |
4637 if (n1 < 0) | |
4638 { | |
4639 n1 = len + n1; | |
4640 if (n1 < 0) | |
4641 n1 = 0; | |
4642 } | |
4643 if (n2 < 0) | |
4644 n2 = len + n2; | |
4645 else if (n2 >= len) | |
4646 n2 = len - 1; | |
4647 if (n1 >= len || n2 < 0 || n1 > n2) | |
4648 { | |
4649 clear_tv(rettv); | |
4650 rettv->v_type = VAR_BLOB; | |
4651 rettv->vval.v_blob = NULL; | |
4652 } | |
4653 else | |
4654 { | |
4655 blob_T *blob = blob_alloc(); | |
4656 | |
4657 if (blob != NULL) | |
4658 { | |
4659 if (ga_grow(&blob->bv_ga, n2 - n1 + 1) == FAIL) | |
4660 { | |
4661 blob_free(blob); | |
4662 return FAIL; | |
4663 } | |
4664 blob->bv_ga.ga_len = n2 - n1 + 1; | |
4665 for (i = n1; i <= n2; i++) | |
4666 blob_set(blob, i - n1, | |
4667 blob_get(rettv->vval.v_blob, i)); | |
4668 | |
4669 clear_tv(rettv); | |
4670 rettv_blob_set(rettv, blob); | |
4671 } | |
4672 } | |
4673 } | |
4674 else | |
4675 { | |
4676 // The resulting variable is a string of a single | |
4677 // character. If the index is too big or negative the | |
4678 // result is empty. | |
4679 if (n1 < len && n1 >= 0) | |
4680 { | |
4681 int v = (int)blob_get(rettv->vval.v_blob, n1); | |
4682 | |
4683 clear_tv(rettv); | |
4684 rettv->v_type = VAR_NUMBER; | |
4685 rettv->vval.v_number = v; | |
4686 } | |
4687 else | |
4688 EMSGN(_(e_blobidx), n1); | |
4689 } | |
4690 break; | |
4691 | |
4442 case VAR_LIST: | 4692 case VAR_LIST: |
4443 len = list_len(rettv->vval.v_list); | 4693 len = list_len(rettv->vval.v_list); |
4444 if (n1 < 0) | 4694 if (n1 < 0) |
4445 n1 = len + n1; | 4695 n1 = len + n1; |
4446 if (!empty1 && (n1 < 0 || n1 >= len)) | 4696 if (!empty1 && (n1 < 0 || n1 >= len)) |
4968 ++recursive_cnt; | 5218 ++recursive_cnt; |
4969 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE); | 5219 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE); |
4970 --recursive_cnt; | 5220 --recursive_cnt; |
4971 return r; | 5221 return r; |
4972 | 5222 |
5223 case VAR_BLOB: | |
5224 return blob_equal(tv1->vval.v_blob, tv2->vval.v_blob); | |
5225 | |
4973 case VAR_NUMBER: | 5226 case VAR_NUMBER: |
4974 return tv1->vval.v_number == tv2->vval.v_number; | 5227 return tv1->vval.v_number == tv2->vval.v_number; |
4975 | 5228 |
4976 case VAR_STRING: | 5229 case VAR_STRING: |
4977 s1 = tv_get_string_buf(tv1, buf1); | 5230 s1 = tv_get_string_buf(tv1, buf1); |
5600 *tofree = ga.ga_data; | 5853 *tofree = ga.ga_data; |
5601 r = *tofree; | 5854 r = *tofree; |
5602 break; | 5855 break; |
5603 } | 5856 } |
5604 | 5857 |
5858 case VAR_BLOB: | |
5859 if (tv->vval.v_blob == NULL) | |
5860 { | |
5861 *tofree = NULL; | |
5862 r = (char_u *)"[]"; | |
5863 } | |
5864 else | |
5865 { | |
5866 blob_T *b; | |
5867 int i; | |
5868 garray_T ga; | |
5869 | |
5870 // Store bytes in the growarray. | |
5871 ga_init2(&ga, 1, 4000); | |
5872 b = tv->vval.v_blob; | |
5873 ga_append(&ga, '['); | |
5874 for (i = 0; i < blob_len(b); i++) | |
5875 { | |
5876 if (i > 0) | |
5877 ga_concat(&ga, (char_u *)","); | |
5878 vim_snprintf((char *)numbuf, NUMBUFLEN, "0x%02X", | |
5879 (int)blob_get(b, i)); | |
5880 ga_concat(&ga, numbuf); | |
5881 } | |
5882 ga_append(&ga, ']'); | |
5883 *tofree = ga.ga_data; | |
5884 r = *tofree; | |
5885 } | |
5886 break; | |
5887 | |
5605 case VAR_LIST: | 5888 case VAR_LIST: |
5606 if (tv->vval.v_list == NULL) | 5889 if (tv->vval.v_list == NULL) |
5607 { | 5890 { |
5608 *tofree = NULL; | 5891 *tofree = NULL; |
5609 r = NULL; | 5892 r = NULL; |
6838 case VAR_STRING: | 7121 case VAR_STRING: |
6839 vim_free(varp->vval.v_string); | 7122 vim_free(varp->vval.v_string); |
6840 break; | 7123 break; |
6841 case VAR_PARTIAL: | 7124 case VAR_PARTIAL: |
6842 partial_unref(varp->vval.v_partial); | 7125 partial_unref(varp->vval.v_partial); |
7126 break; | |
7127 case VAR_BLOB: | |
7128 blob_unref(varp->vval.v_blob); | |
6843 break; | 7129 break; |
6844 case VAR_LIST: | 7130 case VAR_LIST: |
6845 list_unref(varp->vval.v_list); | 7131 list_unref(varp->vval.v_list); |
6846 break; | 7132 break; |
6847 case VAR_DICT: | 7133 case VAR_DICT: |
6884 VIM_CLEAR(varp->vval.v_string); | 7170 VIM_CLEAR(varp->vval.v_string); |
6885 break; | 7171 break; |
6886 case VAR_PARTIAL: | 7172 case VAR_PARTIAL: |
6887 partial_unref(varp->vval.v_partial); | 7173 partial_unref(varp->vval.v_partial); |
6888 varp->vval.v_partial = NULL; | 7174 varp->vval.v_partial = NULL; |
7175 break; | |
7176 case VAR_BLOB: | |
7177 blob_unref(varp->vval.v_blob); | |
7178 varp->vval.v_blob = NULL; | |
6889 break; | 7179 break; |
6890 case VAR_LIST: | 7180 case VAR_LIST: |
6891 list_unref(varp->vval.v_list); | 7181 list_unref(varp->vval.v_list); |
6892 varp->vval.v_list = NULL; | 7182 varp->vval.v_list = NULL; |
6893 break; | 7183 break; |
6988 case VAR_CHANNEL: | 7278 case VAR_CHANNEL: |
6989 #ifdef FEAT_JOB_CHANNEL | 7279 #ifdef FEAT_JOB_CHANNEL |
6990 EMSG(_("E913: Using a Channel as a Number")); | 7280 EMSG(_("E913: Using a Channel as a Number")); |
6991 break; | 7281 break; |
6992 #endif | 7282 #endif |
7283 case VAR_BLOB: | |
7284 EMSG(_("E974: Using a Blob as a Number")); | |
7285 break; | |
6993 case VAR_UNKNOWN: | 7286 case VAR_UNKNOWN: |
6994 internal_error("tv_get_number(UNKNOWN)"); | 7287 internal_error("tv_get_number(UNKNOWN)"); |
6995 break; | 7288 break; |
6996 } | 7289 } |
6997 if (denote == NULL) /* useful for values that must be unsigned */ | 7290 if (denote == NULL) /* useful for values that must be unsigned */ |
7035 case VAR_CHANNEL: | 7328 case VAR_CHANNEL: |
7036 # ifdef FEAT_JOB_CHANNEL | 7329 # ifdef FEAT_JOB_CHANNEL |
7037 EMSG(_("E914: Using a Channel as a Float")); | 7330 EMSG(_("E914: Using a Channel as a Float")); |
7038 break; | 7331 break; |
7039 # endif | 7332 # endif |
7333 case VAR_BLOB: | |
7334 EMSG(_("E975: Using a Blob as a Float")); | |
7335 break; | |
7040 case VAR_UNKNOWN: | 7336 case VAR_UNKNOWN: |
7041 internal_error("tv_get_float(UNKNOWN)"); | 7337 internal_error("tv_get_float(UNKNOWN)"); |
7042 break; | 7338 break; |
7043 } | 7339 } |
7044 return 0; | 7340 return 0; |
7111 return varp->vval.v_string; | 7407 return varp->vval.v_string; |
7112 return (char_u *)""; | 7408 return (char_u *)""; |
7113 case VAR_SPECIAL: | 7409 case VAR_SPECIAL: |
7114 STRCPY(buf, get_var_special_name(varp->vval.v_number)); | 7410 STRCPY(buf, get_var_special_name(varp->vval.v_number)); |
7115 return buf; | 7411 return buf; |
7412 case VAR_BLOB: | |
7413 EMSG(_("E976: using Blob as a String")); | |
7414 break; | |
7116 case VAR_JOB: | 7415 case VAR_JOB: |
7117 #ifdef FEAT_JOB_CHANNEL | 7416 #ifdef FEAT_JOB_CHANNEL |
7118 { | 7417 { |
7119 job_T *job = varp->vval.v_job; | 7418 job_T *job = varp->vval.v_job; |
7120 char *status; | 7419 char *status; |
7803 { | 8102 { |
7804 to->vval.v_partial = from->vval.v_partial; | 8103 to->vval.v_partial = from->vval.v_partial; |
7805 ++to->vval.v_partial->pt_refcount; | 8104 ++to->vval.v_partial->pt_refcount; |
7806 } | 8105 } |
7807 break; | 8106 break; |
8107 case VAR_BLOB: | |
8108 if (from->vval.v_blob == NULL) | |
8109 to->vval.v_blob = NULL; | |
8110 else | |
8111 { | |
8112 to->vval.v_blob = from->vval.v_blob; | |
8113 ++to->vval.v_blob->bv_refcount; | |
8114 } | |
8115 break; | |
7808 case VAR_LIST: | 8116 case VAR_LIST: |
7809 if (from->vval.v_list == NULL) | 8117 if (from->vval.v_list == NULL) |
7810 to->vval.v_list = NULL; | 8118 to->vval.v_list = NULL; |
7811 else | 8119 else |
7812 { | 8120 { |
7861 case VAR_FUNC: | 8169 case VAR_FUNC: |
7862 case VAR_PARTIAL: | 8170 case VAR_PARTIAL: |
7863 case VAR_SPECIAL: | 8171 case VAR_SPECIAL: |
7864 case VAR_JOB: | 8172 case VAR_JOB: |
7865 case VAR_CHANNEL: | 8173 case VAR_CHANNEL: |
8174 case VAR_BLOB: | |
7866 copy_tv(from, to); | 8175 copy_tv(from, to); |
7867 break; | 8176 break; |
7868 case VAR_LIST: | 8177 case VAR_LIST: |
7869 to->v_type = VAR_LIST; | 8178 to->v_type = VAR_LIST; |
7870 to->v_lock = 0; | 8179 to->v_lock = 0; |
8599 #ifdef FEAT_FLOAT | 8908 #ifdef FEAT_FLOAT |
8600 case 'F': type = VAR_FLOAT; break; | 8909 case 'F': type = VAR_FLOAT; break; |
8601 #endif | 8910 #endif |
8602 case 'D': type = VAR_DICT; break; | 8911 case 'D': type = VAR_DICT; break; |
8603 case 'L': type = VAR_LIST; break; | 8912 case 'L': type = VAR_LIST; break; |
8913 case 'B': type = VAR_BLOB; break; | |
8604 case 'X': type = VAR_SPECIAL; break; | 8914 case 'X': type = VAR_SPECIAL; break; |
8605 } | 8915 } |
8606 | 8916 |
8607 tab = vim_strchr(tab, '\t'); | 8917 tab = vim_strchr(tab, '\t'); |
8608 if (tab != NULL) | 8918 if (tab != NULL) |
8609 { | 8919 { |
8610 tv.v_type = type; | 8920 tv.v_type = type; |
8611 if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST) | 8921 if (type == VAR_STRING || type == VAR_DICT || |
8922 type == VAR_LIST || type == VAR_BLOB) | |
8612 tv.vval.v_string = viminfo_readstring(virp, | 8923 tv.vval.v_string = viminfo_readstring(virp, |
8613 (int)(tab - virp->vir_line + 1), TRUE); | 8924 (int)(tab - virp->vir_line + 1), TRUE); |
8614 #ifdef FEAT_FLOAT | 8925 #ifdef FEAT_FLOAT |
8615 else if (type == VAR_FLOAT) | 8926 else if (type == VAR_FLOAT) |
8616 (void)string2float(tab + 1, &tv.vval.v_float); | 8927 (void)string2float(tab + 1, &tv.vval.v_float); |
8617 #endif | 8928 #endif |
8618 else | 8929 else |
8619 tv.vval.v_number = atol((char *)tab + 1); | 8930 tv.vval.v_number = atol((char *)tab + 1); |
8620 if (type == VAR_DICT || type == VAR_LIST) | 8931 if (type == VAR_DICT || type == VAR_LIST || type == VAR_BLOB) |
8621 { | 8932 { |
8622 typval_T *etv = eval_expr(tv.vval.v_string, NULL); | 8933 typval_T *etv = eval_expr(tv.vval.v_string, NULL); |
8623 | 8934 |
8624 if (etv == NULL) | 8935 if (etv == NULL) |
8625 /* Failed to parse back the dict or list, use it as a | 8936 /* Failed to parse back the dict or list, use it as a |
8638 set_var(virp->vir_line + 1, &tv, FALSE); | 8949 set_var(virp->vir_line + 1, &tv, FALSE); |
8639 restore_funccal(); | 8950 restore_funccal(); |
8640 | 8951 |
8641 if (tv.v_type == VAR_STRING) | 8952 if (tv.v_type == VAR_STRING) |
8642 vim_free(tv.vval.v_string); | 8953 vim_free(tv.vval.v_string); |
8643 else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST) | 8954 else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST || |
8955 tv.v_type == VAR_BLOB) | |
8644 clear_tv(&tv); | 8956 clear_tv(&tv); |
8645 } | 8957 } |
8646 } | 8958 } |
8647 } | 8959 } |
8648 | 8960 |
8682 case VAR_STRING: s = "STR"; break; | 8994 case VAR_STRING: s = "STR"; break; |
8683 case VAR_NUMBER: s = "NUM"; break; | 8995 case VAR_NUMBER: s = "NUM"; break; |
8684 case VAR_FLOAT: s = "FLO"; break; | 8996 case VAR_FLOAT: s = "FLO"; break; |
8685 case VAR_DICT: s = "DIC"; break; | 8997 case VAR_DICT: s = "DIC"; break; |
8686 case VAR_LIST: s = "LIS"; break; | 8998 case VAR_LIST: s = "LIS"; break; |
8999 case VAR_BLOB: s = "BLO"; break; | |
8687 case VAR_SPECIAL: s = "XPL"; break; | 9000 case VAR_SPECIAL: s = "XPL"; break; |
8688 | 9001 |
8689 case VAR_UNKNOWN: | 9002 case VAR_UNKNOWN: |
8690 case VAR_FUNC: | 9003 case VAR_FUNC: |
8691 case VAR_PARTIAL: | 9004 case VAR_PARTIAL: |
9247 if (type_is && typ1->v_type != typ2->v_type) | 9560 if (type_is && typ1->v_type != typ2->v_type) |
9248 { | 9561 { |
9249 /* For "is" a different type always means FALSE, for "notis" | 9562 /* For "is" a different type always means FALSE, for "notis" |
9250 * it means TRUE. */ | 9563 * it means TRUE. */ |
9251 n1 = (type == TYPE_NEQUAL); | 9564 n1 = (type == TYPE_NEQUAL); |
9565 } | |
9566 else if (typ1->v_type == VAR_BLOB || typ2->v_type == VAR_BLOB) | |
9567 { | |
9568 if (type_is) | |
9569 { | |
9570 n1 = (typ1->v_type == typ2->v_type | |
9571 && typ1->vval.v_blob == typ2->vval.v_blob); | |
9572 if (type == TYPE_NEQUAL) | |
9573 n1 = !n1; | |
9574 } | |
9575 else if (typ1->v_type != typ2->v_type | |
9576 || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) | |
9577 { | |
9578 if (typ1->v_type != typ2->v_type) | |
9579 EMSG(_("E977: Can only compare Blob with Blob")); | |
9580 else | |
9581 EMSG(_(e_invalblob)); | |
9582 clear_tv(typ1); | |
9583 return FAIL; | |
9584 } | |
9585 else | |
9586 { | |
9587 // Compare two Blobs for being equal or unequal. | |
9588 n1 = blob_equal(typ1->vval.v_blob, typ2->vval.v_blob); | |
9589 if (type == TYPE_NEQUAL) | |
9590 n1 = !n1; | |
9591 } | |
9252 } | 9592 } |
9253 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) | 9593 else if (typ1->v_type == VAR_LIST || typ2->v_type == VAR_LIST) |
9254 { | 9594 { |
9255 if (type_is) | 9595 if (type_is) |
9256 { | 9596 { |
10276 hashtab_T *ht; | 10616 hashtab_T *ht; |
10277 hashitem_T *hi; | 10617 hashitem_T *hi; |
10278 dict_T *d = NULL; | 10618 dict_T *d = NULL; |
10279 typval_T save_val; | 10619 typval_T save_val; |
10280 typval_T save_key; | 10620 typval_T save_key; |
10621 blob_T *b = NULL; | |
10281 int rem; | 10622 int rem; |
10282 int todo; | 10623 int todo; |
10283 char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); | 10624 char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); |
10284 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") | 10625 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") |
10285 : N_("filter() argument")); | 10626 : N_("filter() argument")); |
10286 int save_did_emsg; | 10627 int save_did_emsg; |
10287 int idx = 0; | 10628 int idx = 0; |
10288 | 10629 |
10289 if (argvars[0].v_type == VAR_LIST) | 10630 if (argvars[0].v_type == VAR_BLOB) |
10631 { | |
10632 if ((b = argvars[0].vval.v_blob) == NULL) | |
10633 return; | |
10634 } | |
10635 else if (argvars[0].v_type == VAR_LIST) | |
10290 { | 10636 { |
10291 if ((l = argvars[0].vval.v_list) == NULL | 10637 if ((l = argvars[0].vval.v_list) == NULL |
10292 || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TRUE))) | 10638 || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TRUE))) |
10293 return; | 10639 return; |
10294 } | 10640 } |
10351 } | 10697 } |
10352 } | 10698 } |
10353 } | 10699 } |
10354 hash_unlock(ht); | 10700 hash_unlock(ht); |
10355 } | 10701 } |
10702 else if (argvars[0].v_type == VAR_BLOB) | |
10703 { | |
10704 int i; | |
10705 typval_T tv; | |
10706 | |
10707 vimvars[VV_KEY].vv_type = VAR_NUMBER; | |
10708 for (i = 0; i < b->bv_ga.ga_len; i++) | |
10709 { | |
10710 tv.v_type = VAR_NUMBER; | |
10711 tv.vval.v_number = blob_get(b, i); | |
10712 vimvars[VV_KEY].vv_nr = idx; | |
10713 if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg) | |
10714 break; | |
10715 if (tv.v_type != VAR_NUMBER) | |
10716 { | |
10717 EMSG(_(e_invalblob)); | |
10718 return; | |
10719 } | |
10720 tv.v_type = VAR_NUMBER; | |
10721 blob_set(b, i, tv.vval.v_number); | |
10722 if (!map && rem) | |
10723 { | |
10724 char_u *p = (char_u *)argvars[0].vval.v_blob->bv_ga.ga_data; | |
10725 | |
10726 mch_memmove(p + idx, p + i + 1, | |
10727 (size_t)b->bv_ga.ga_len - i - 1); | |
10728 --b->bv_ga.ga_len; | |
10729 --i; | |
10730 } | |
10731 } | |
10732 } | |
10356 else | 10733 else |
10357 { | 10734 { |
10358 vimvars[VV_KEY].vv_type = VAR_NUMBER; | 10735 vimvars[VV_KEY].vv_type = VAR_NUMBER; |
10359 | 10736 |
10360 for (li = l->lv_first; li != NULL; li = nli) | 10737 for (li = l->lv_first; li != NULL; li = nli) |