comparison src/list.c @ 26638:6fd15d82e898 v8.2.3848

patch 8.2.3848: cannot use reduce() for a string Commit: https://github.com/vim/vim/commit/0ccb5842f5fb103763d106c7aa364d758343c35a Author: rbtnn <naru123456789@gmail.com> Date: Sat Dec 18 18:33:46 2021 +0000 patch 8.2.3848: cannot use reduce() for a string Problem: Cannot use reduce() for a string. Solution: Make reduce() work with a string. (Naruhiko Nishino, closes https://github.com/vim/vim/issues/9366)
author Bram Moolenaar <Bram@vim.org>
date Sat, 18 Dec 2021 19:45:03 +0100
parents 0d2a709e2ff0
children 7c055fdd6200
comparison
equal deleted inserted replaced
26637:eeac85e187e7 26638:6fd15d82e898
309 */ 309 */
310 listitem_T * 310 listitem_T *
311 listitem_alloc(void) 311 listitem_alloc(void)
312 { 312 {
313 return ALLOC_ONE(listitem_T); 313 return ALLOC_ONE(listitem_T);
314 }
315
316 /*
317 * Make a typval_T of the first character of "input" and store it in "output".
318 * Return OK or FAIL.
319 */
320 static int
321 tv_get_first_char(char_u *input, typval_T *output)
322 {
323 char_u buf[MB_MAXBYTES + 1];
324 int len;
325
326 if (input == NULL || output == NULL)
327 return FAIL;
328
329 len = has_mbyte ? mb_ptr2len(input) : 1;
330 STRNCPY(buf, input, len);
331 buf[len] = NUL;
332 output->v_type = VAR_STRING;
333 output->vval.v_string = vim_strsave(buf);
334
335 return output->vval.v_string == NULL ? FAIL : OK;
314 } 336 }
315 337
316 /* 338 /*
317 * Free a list item, unless it was allocated together with the list itself. 339 * Free a list item, unless it was allocated together with the list itself.
318 * Does not clear the value. Does not notify watchers. 340 * Does not clear the value. Does not notify watchers.
2490 else if (argvars[0].v_type == VAR_STRING) 2512 else if (argvars[0].v_type == VAR_STRING)
2491 { 2513 {
2492 char_u *p; 2514 char_u *p;
2493 typval_T tv; 2515 typval_T tv;
2494 garray_T ga; 2516 garray_T ga;
2495 char_u buf[MB_MAXBYTES + 1];
2496 int len; 2517 int len;
2497 2518
2498 // set_vim_var_nr() doesn't set the type 2519 // set_vim_var_nr() doesn't set the type
2499 set_vim_var_type(VV_KEY, VAR_NUMBER); 2520 set_vim_var_type(VV_KEY, VAR_NUMBER);
2500 2521
2501 ga_init2(&ga, (int)sizeof(char), 80); 2522 ga_init2(&ga, (int)sizeof(char), 80);
2502 for (p = tv_get_string(&argvars[0]); *p != NUL; p += len) 2523 for (p = tv_get_string(&argvars[0]); *p != NUL; p += len)
2503 { 2524 {
2504 typval_T newtv; 2525 typval_T newtv;
2505 2526
2506 if (has_mbyte) 2527 if (tv_get_first_char(p, &tv) == FAIL)
2507 len = mb_ptr2len(p); 2528 break;
2508 else 2529 len = STRLEN(tv.vval.v_string);
2509 len = 1;
2510
2511 STRNCPY(buf, p, len);
2512 buf[len] = NUL;
2513
2514 tv.v_type = VAR_STRING;
2515 tv.vval.v_string = vim_strsave(buf);
2516 2530
2517 set_vim_var_nr(VV_KEY, idx); 2531 set_vim_var_nr(VV_KEY, idx);
2518 if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL 2532 if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL
2519 || did_emsg) 2533 || did_emsg)
2520 break; 2534 break;
3246 typval_T initial; 3260 typval_T initial;
3247 char_u *func_name; 3261 char_u *func_name;
3248 partial_T *partial = NULL; 3262 partial_T *partial = NULL;
3249 funcexe_T funcexe; 3263 funcexe_T funcexe;
3250 typval_T argv[3]; 3264 typval_T argv[3];
3251 3265 int r;
3252 if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) 3266 int called_emsg_start = called_emsg;
3253 { 3267
3254 emsg(_(e_listblobreq)); 3268 if (in_vim9script()
3269 && check_for_string_or_list_or_blob_arg(argvars, 0) == FAIL)
3255 return; 3270 return;
3256 } 3271
3272 if (argvars[0].v_type != VAR_STRING
3273 && argvars[0].v_type != VAR_LIST
3274 && argvars[0].v_type != VAR_BLOB)
3275 semsg(_(e_string_list_or_blob_required), "reduce()");
3257 3276
3258 if (argvars[1].v_type == VAR_FUNC) 3277 if (argvars[1].v_type == VAR_FUNC)
3259 func_name = argvars[1].vval.v_string; 3278 func_name = argvars[1].vval.v_string;
3260 else if (argvars[1].v_type == VAR_PARTIAL) 3279 else if (argvars[1].v_type == VAR_PARTIAL)
3261 { 3280 {
3276 3295
3277 if (argvars[0].v_type == VAR_LIST) 3296 if (argvars[0].v_type == VAR_LIST)
3278 { 3297 {
3279 list_T *l = argvars[0].vval.v_list; 3298 list_T *l = argvars[0].vval.v_list;
3280 listitem_T *li = NULL; 3299 listitem_T *li = NULL;
3281 int r;
3282 int called_emsg_start = called_emsg;
3283 3300
3284 if (l != NULL) 3301 if (l != NULL)
3285 CHECK_LIST_MATERIALIZE(l); 3302 CHECK_LIST_MATERIALIZE(l);
3286 if (argvars[2].v_type == VAR_UNKNOWN) 3303 if (argvars[2].v_type == VAR_UNKNOWN)
3287 { 3304 {
3317 break; 3334 break;
3318 } 3335 }
3319 l->lv_lock = prev_locked; 3336 l->lv_lock = prev_locked;
3320 } 3337 }
3321 } 3338 }
3339 else if (argvars[0].v_type == VAR_STRING)
3340 {
3341 char_u *p = tv_get_string(&argvars[0]);
3342 int len;
3343
3344 if (argvars[2].v_type == VAR_UNKNOWN)
3345 {
3346 if (*p == NUL)
3347 {
3348 semsg(_(e_reduceempty), "String");
3349 return;
3350 }
3351 if (tv_get_first_char(p, rettv) == FAIL)
3352 return;
3353 p += STRLEN(rettv->vval.v_string);
3354 }
3355 else if (argvars[2].v_type != VAR_STRING)
3356 {
3357 semsg(_(e_string_expected_for_argument_nr), 3);
3358 return;
3359 }
3360 else
3361 copy_tv(&argvars[2], rettv);
3362
3363 for ( ; *p != NUL; p += len)
3364 {
3365 argv[0] = *rettv;
3366 if (tv_get_first_char(p, &argv[1]) == FAIL)
3367 break;
3368 len = STRLEN(argv[1].vval.v_string);
3369 r = call_func(func_name, -1, rettv, 2, argv, &funcexe);
3370 clear_tv(&argv[0]);
3371 clear_tv(&argv[1]);
3372 if (r == FAIL || called_emsg != called_emsg_start)
3373 break;
3374 }
3375 }
3322 else 3376 else
3323 { 3377 {
3324 blob_T *b = argvars[0].vval.v_blob; 3378 blob_T *b = argvars[0].vval.v_blob;
3325 int i; 3379 int i;
3326 3380