To: vim_dev@googlegroups.com Subject: Patch 8.2.1666 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1666 Problem: The initial value of 'backupskip' can have duplicate items. Solution: Remove duplicates, like when it is set later. (Tom Ryder, closes #6940) Files: src/option.c, src/testdir/test_options.vim *** ../vim-8.2.1665/src/option.c 2020-08-07 19:12:38.092576940 +0200 --- src/option.c 2020-09-12 14:51:03.675534570 +0200 *************** *** 37,42 **** --- 37,43 ---- static void set_options_default(int opt_flags); static void set_string_default_esc(char *name, char_u *val, int escape); + static char_u *find_dup_item(char_u *origval, char_u *newval, long_u flags); static char_u *option_expand(int opt_idx, char_u *val); static void didset_options(void); static void didset_options2(void); *************** *** 139,144 **** --- 140,148 ---- int len; garray_T ga; int mustfree; + char_u *item; + + opt_idx = findoption((char_u *)"backupskip"); ga_init2(&ga, 1, 100); for (n = 0; n < (long)(sizeof(names) / sizeof(char *)); ++n) *************** *** 158,172 **** { // First time count the NUL, otherwise count the ','. len = (int)STRLEN(p) + 3; ! if (ga_grow(&ga, len) == OK) { if (ga.ga_len > 0) STRCAT(ga.ga_data, ","); ! STRCAT(ga.ga_data, p); ! add_pathsep(ga.ga_data); ! STRCAT(ga.ga_data, "*"); ga.ga_len += len; } } if (mustfree) vim_free(p); --- 162,181 ---- { // First time count the NUL, otherwise count the ','. len = (int)STRLEN(p) + 3; ! item = alloc(len); ! STRCPY(item, p); ! add_pathsep(item); ! STRCAT(item, "*"); ! if (find_dup_item(ga.ga_data, item, options[opt_idx].flags) ! == NULL ! && ga_grow(&ga, len) == OK) { if (ga.ga_len > 0) STRCAT(ga.ga_data, ","); ! STRCAT(ga.ga_data, item); ga.ga_len += len; } + vim_free(item); } if (mustfree) vim_free(p); *************** *** 668,673 **** --- 677,722 ---- } /* + * For an option value that contains comma separated items, find "newval" in + * "origval". Return NULL if not found. + */ + static char_u * + find_dup_item(char_u *origval, char_u *newval, long_u flags) + { + int bs; + size_t newlen; + char_u *s; + + if (origval == NULL) + return NULL; + + newlen = STRLEN(newval); + for (s = origval; *s != NUL; ++s) + { + if ((!(flags & P_COMMA) + || s == origval + || (s[-1] == ',' && !(bs & 1))) + && STRNCMP(s, newval, newlen) == 0 + && (!(flags & P_COMMA) + || s[newlen] == ',' + || s[newlen] == NUL)) + return s; + // Count backslashes. Only a comma with an even number of backslashes + // or a single backslash preceded by a comma before it is recognized as + // a separator. + if ((s > origval + 1 + && s[-1] == '\\' + && s[-2] != ',') + || (s == origval + 1 + && s[-1] == '\\')) + ++bs; + else + bs = 0; + } + return NULL; + } + + /* * Set the Vi-default value of a number option. * Used for 'lines' and 'columns'. */ *************** *** 1572,1578 **** #endif unsigned newlen; int comma; - int bs; int new_value_alloced; // new string option // was allocated --- 1621,1626 ---- *************** *** 1811,1849 **** if (removing || (flags & P_NODUP)) { i = (int)STRLEN(newval); ! bs = 0; ! for (s = origval; *s; ++s) ! { ! if ((!(flags & P_COMMA) ! || s == origval ! || (s[-1] == ',' && !(bs & 1))) ! && STRNCMP(s, newval, i) == 0 ! && (!(flags & P_COMMA) ! || s[i] == ',' ! || s[i] == NUL)) ! break; ! // Count backslashes. Only a comma with an ! // even number of backslashes or a single ! // backslash preceded by a comma before it ! // is recognized as a separator ! if ((s > origval + 1 ! && s[-1] == '\\' ! && s[-2] != ',') ! || (s == origval + 1 ! && s[-1] == '\\')) ! ! ++bs; ! else ! bs = 0; ! } // do not add if already there ! if ((adding || prepending) && *s) { prepending = FALSE; adding = FALSE; STRCPY(newval, origval); } } // concatenate the two strings; add a ',' if --- 1859,1878 ---- if (removing || (flags & P_NODUP)) { i = (int)STRLEN(newval); ! s = find_dup_item(origval, newval, flags); // do not add if already there ! if ((adding || prepending) && s != NULL) { prepending = FALSE; adding = FALSE; STRCPY(newval, origval); } + + // if no duplicate, move pointer to end of + // original value + if (s == NULL) + s = origval + (int)STRLEN(origval); } // concatenate the two strings; add a ',' if *** ../vim-8.2.1665/src/testdir/test_options.vim 2020-08-13 18:57:56.562214742 +0200 --- src/testdir/test_options.vim 2020-09-12 14:40:30.105787221 +0200 *************** *** 1,5 **** --- 1,6 ---- " Test for options + source shared.vim source check.vim source view_util.vim *************** *** 587,592 **** --- 588,622 ---- endif endfor + " Duplicates from environment variables should be filtered out (option has + " P_NODUP). Run this in a separate instance and write v:errors in a file, + " so that we see what happens on startup. + let after =<< trim [CODE] + let bsklist = split(&backupskip, ',') + call assert_equal(uniq(copy(bsklist)), bsklist) + call writefile(['errors:'] + v:errors, 'Xtestout') + qall + [CODE] + call writefile(after, 'Xafter') + let cmd = GetVimProg() . ' --not-a-term -S Xafter --cmd "set enc=utf8"' + + let saveenv = {} + for var in ['TMPDIR', 'TMP', 'TEMP'] + let saveenv[var] = getenv(var) + call setenv(var, '/duplicate/path') + endfor + + exe 'silent !' . cmd + call assert_equal(['errors:'], readfile('Xtestout')) + + " restore environment variables + for var in ['TMPDIR', 'TMP', 'TEMP'] + call setenv(var, saveenv[var]) + endfor + + call delete('Xtestout') + call delete('Xafter') + " Duplicates should be filtered out (option has P_NODUP) let backupskip = &backupskip set backupskip= *** ../vim-8.2.1665/src/version.c 2020-09-11 22:25:11.298775020 +0200 --- src/version.c 2020-09-12 14:33:00.571400472 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 1666, /**/ -- Every person is responsible for the choices he makes. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///