]> granicus.if.org Git - vim/commitdiff
patch 8.1.1371: cannot recover from a swap file v8.1.1371
authorBram Moolenaar <Bram@vim.org>
Thu, 23 May 2019 19:35:48 +0000 (21:35 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 23 May 2019 19:35:48 +0000 (21:35 +0200)
Problem:    Cannot recover from a swap file.
Solution:   Do not expand environment variables in the swap file name.
            Do not check the extension when we already know a file is a swap
            file.  (Ken Takata, closes 4415, closes #4369)

18 files changed:
src/buffer.c
src/ex_cmds.c
src/ex_cmds2.c
src/ex_docmd.c
src/gui.c
src/if_cscope.c
src/main.c
src/memline.c
src/misc1.c
src/proto/memline.pro
src/proto/misc1.pro
src/search.c
src/spell.c
src/spellfile.c
src/tag.c
src/testdir/test_swap.vim
src/version.c
src/vim.h

index e10368483db7195924eee686b8ed3380356de51b..0e45f0e66c95a14b03cbef26179a2784688c9d3e 100644 (file)
@@ -1071,7 +1071,7 @@ handle_swap_exists(bufref_T *old_curbuf)
 
        /* User selected Recover at ATTENTION prompt. */
        msg_scroll = TRUE;
-       ml_recover();
+       ml_recover(FALSE);
        msg_puts("\n"); /* don't overwrite the last message */
        cmdline_row = msg_row;
        do_modelines(0);
@@ -4943,7 +4943,7 @@ do_arg_all(
                    if (i < alist->al_ga.ga_len
                            && (AARGLIST(alist)[i].ae_fnum == buf->b_fnum
                                || fullpathcmp(alist_name(&AARGLIST(alist)[i]),
-                                             buf->b_ffname, TRUE) & FPC_SAME))
+                                       buf->b_ffname, TRUE, TRUE) & FPC_SAME))
                    {
                        int weight = 1;
 
index 0174fd6b012f927e1b5e6f25bf67753affac738f..040514cdc5676930e601a102e928a6f76fd19287 100644 (file)
@@ -7002,7 +7002,8 @@ fix_help_buffer(void)
                copy_option_part(&p, NameBuff, MAXPATHL, ",");
                mustfree = FALSE;
                rt = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
-               if (rt != NULL && fullpathcmp(rt, NameBuff, FALSE) != FPC_SAME)
+               if (rt != NULL &&
+                           fullpathcmp(rt, NameBuff, FALSE, TRUE) != FPC_SAME)
                {
                    int         fcount;
                    char_u      **fnames;
@@ -7224,7 +7225,7 @@ helptags_one(
      */
     ga_init2(&ga, (int)sizeof(char_u *), 100);
     if (add_help_tags || fullpathcmp((char_u *)"$VIMRUNTIME/doc",
-                                                     dir, FALSE) == FPC_SAME)
+                                               dir, FALSE, TRUE) == FPC_SAME)
     {
        if (ga_grow(&ga, 1) == FAIL)
            got_int = TRUE;
index bf6e5512090fd5c21847789841b2ae6f2c5b07da..59452032bd92375dd71a3926db445cff5b0dbe20 100644 (file)
@@ -1715,7 +1715,7 @@ editing_arg_idx(win_T *win)
                    && (win->w_buffer->b_ffname == NULL
                         || !(fullpathcmp(
                                 alist_name(&WARGLIST(win)[win->w_arg_idx]),
-                               win->w_buffer->b_ffname, TRUE) & FPC_SAME))));
+                         win->w_buffer->b_ffname, TRUE, TRUE) & FPC_SAME))));
 }
 
 /*
@@ -1737,7 +1737,7 @@ check_arg_idx(win_T *win)
                && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum
                    || (win->w_buffer->b_ffname != NULL
                        && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]),
-                               win->w_buffer->b_ffname, TRUE) & FPC_SAME))))
+                         win->w_buffer->b_ffname, TRUE, TRUE) & FPC_SAME))))
            arg_had_last = TRUE;
     }
     else
index 16f505967d1c3aae30da8b842b0e5d81d0500504..f4f7639e775203b1e6f454cb250a18946d8b3d80 100644 (file)
@@ -6725,7 +6725,7 @@ ex_recover(exarg_T *eap)
 
            && (*eap->arg == NUL
                             || setfname(curbuf, eap->arg, NULL, TRUE) == OK))
-       ml_recover();
+       ml_recover(TRUE);
     recoverymode = FALSE;
 }
 
index da7284f937c2e32f058aa8f240c30da69fd9d954..8568c204540539fc25f97aed1224611d1ba56210 100644 (file)
--- a/src/gui.c
+++ b/src/gui.c
@@ -603,22 +603,22 @@ gui_init(void)
 #endif
 
                if (       fullpathcmp((char_u *)USR_GVIMRC_FILE,
-                                    (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)GVIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #ifdef SYS_GVIMRC_FILE
                        && fullpathcmp((char_u *)SYS_GVIMRC_FILE,
-                                    (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)GVIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
 #ifdef USR_GVIMRC_FILE2
                        && fullpathcmp((char_u *)USR_GVIMRC_FILE2,
-                                    (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)GVIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
 #ifdef USR_GVIMRC_FILE3
                        && fullpathcmp((char_u *)USR_GVIMRC_FILE3,
-                                    (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)GVIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
 #ifdef USR_GVIMRC_FILE4
                        && fullpathcmp((char_u *)USR_GVIMRC_FILE4,
-                                    (char_u *)GVIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)GVIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
                        )
                    do_source((char_u *)GVIMRC_FILE, TRUE, DOSO_GVIMRC);
index 03346749c90279da9beb46e89a3780f2aa5478b1..93a0458b4fbea0f7cb669d600b19d3306ad6f162 100644 (file)
@@ -1401,10 +1401,10 @@ cs_insert_filelist(
 #if defined(UNIX)
            && csinfo[j].st_dev == sb->st_dev && csinfo[j].st_ino == sb->st_ino
 #else
-           /* compare pathnames first */
+           // compare pathnames first
            && ((fullpathcmp((char_u *)csinfo[j].fname,
-                       (char_u *)fname, FALSE) & FPC_SAME)
-               /* test index file attributes too */
+                       (char_u *)fname, FALSE, TRUE) & FPC_SAME)
+               // test index file attributes too
                || (csinfo[j].nVolume == bhfi.dwVolumeSerialNumber
                    && csinfo[j].nIndexHigh == bhfi.nFileIndexHigh
                    && csinfo[j].nIndexLow == bhfi.nFileIndexLow))
index d01cf9b073571f6a54bd4c6434e8095aaf0dd5d6..98359505363d042982e71721b747083407027b5d 100644 (file)
@@ -2684,7 +2684,7 @@ create_windows(mparm_T *parmp UNUSED)
     if (recoverymode)                  /* do recover */
     {
        msg_scroll = TRUE;              /* scroll message up */
-       ml_recover();
+       ml_recover(TRUE);
        if (curbuf->b_ml.ml_mfp == NULL) /* failed */
            getout(1);
        do_modelines(0);                /* do modelines */
@@ -3101,18 +3101,18 @@ source_startup_scripts(mparm_T *parmp)
 
            i = FAIL;
            if (fullpathcmp((char_u *)USR_VIMRC_FILE,
-                                     (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #ifdef USR_VIMRC_FILE2
                    && fullpathcmp((char_u *)USR_VIMRC_FILE2,
-                                     (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
 #ifdef USR_VIMRC_FILE3
                    && fullpathcmp((char_u *)USR_VIMRC_FILE3,
-                                     (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
 #ifdef SYS_VIMRC_FILE
                    && fullpathcmp((char_u *)SYS_VIMRC_FILE,
-                                     (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)VIMRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
                                )
                i = do_source((char_u *)VIMRC_FILE, TRUE, DOSO_VIMRC);
@@ -3127,10 +3127,10 @@ source_startup_scripts(mparm_T *parmp)
                    secure = 0;
 #endif
                if (       fullpathcmp((char_u *)USR_EXRC_FILE,
-                                     (char_u *)EXRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)EXRC_FILE, FALSE, TRUE) != FPC_SAME
 #ifdef USR_EXRC_FILE2
                        && fullpathcmp((char_u *)USR_EXRC_FILE2,
-                                     (char_u *)EXRC_FILE, FALSE) != FPC_SAME
+                               (char_u *)EXRC_FILE, FALSE, TRUE) != FPC_SAME
 #endif
                                )
                    (void)do_source((char_u *)EXRC_FILE, FALSE, DOSO_NONE);
index 8772c4a8e4eee6196640ebfc9cfe3599633f959e..46b5ce8c174df9a80b9348be3cdca5c6088d89e6 100644 (file)
@@ -1084,9 +1084,11 @@ add_b0_fenc(
 
 /*
  * Try to recover curbuf from the .swp file.
+ * If "checkext" is TRUE, check the extension and detect whether it is
+ * a swap file.
  */
     void
-ml_recover(void)
+ml_recover(int checkext)
 {
     buf_T      *buf = NULL;
     memfile_T  *mfp = NULL;
@@ -1136,7 +1138,7 @@ ml_recover(void)
     if (fname == NULL)             /* When there is no file name */
        fname = (char_u *)"";
     len = (int)STRLEN(fname);
-    if (len >= 4 &&
+    if (checkext && len >= 4 &&
 #if defined(VMS)
            STRNICMP(fname + len - 4, "_s", 2)
 #else
@@ -1887,7 +1889,7 @@ recover_names(
        if (num_names == 0)
            num_files = 0;
        else if (expand_wildcards(num_names, names, &num_files, &files,
-                                       EW_KEEPALL|EW_FILE|EW_SILENT) == FAIL)
+                           EW_NOTENV|EW_KEEPALL|EW_FILE|EW_SILENT) == FAIL)
            num_files = 0;
 
        /*
@@ -1930,11 +1932,13 @@ recover_names(
                               && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
        {
            for (i = 0; i < num_files; ++i)
-               if (fullpathcmp(p, files[i], TRUE) & FPC_SAME)
+               // Do not expand wildcards, on windows would try to expand
+               // "%tmp%" in "%tmp%file".
+               if (fullpathcmp(p, files[i], TRUE, FALSE) & FPC_SAME)
                {
-                   /* Remove the name from files[i].  Move further entries
-                    * down.  When the array becomes empty free it here, since
-                    * FreeWild() won't be called below. */
+                   // Remove the name from files[i].  Move further entries
+                   // down.  When the array becomes empty free it here, since
+                   // FreeWild() won't be called below.
                    vim_free(files[i]);
                    if (--num_files == 0)
                        vim_free(files);
index e76e4a4a374c256ccbd6a9d93c72fec59452b879..550a7273e2b8485081b420748136d16c75d9d49f 100644 (file)
@@ -2691,13 +2691,15 @@ home_replace_save(
  * FPC_DIFF   if they both exist and are different files.
  * FPC_NOTX   if they both don't exist.
  * FPC_DIFFX  if one of them doesn't exist.
- * For the first name environment variables are expanded
+ * For the first name environment variables are expanded if "expandenv" is
+ * TRUE.
  */
     int
 fullpathcmp(
     char_u *s1,
     char_u *s2,
-    int            checkname)          /* when both don't exist, check file names */
+    int            checkname,          // when both don't exist, check file names
+    int            expandenv)
 {
 #ifdef UNIX
     char_u         exp1[MAXPATHL];
@@ -2706,7 +2708,10 @@ fullpathcmp(
     stat_T         st1, st2;
     int                    r1, r2;
 
-    expand_env(s1, exp1, MAXPATHL);
+    if (expandenv)
+       expand_env(s1, exp1, MAXPATHL);
+    else
+       vim_strncpy(exp1, s1, MAXPATHL - 1);
     r1 = mch_stat((char *)exp1, &st1);
     r2 = mch_stat((char *)s2, &st2);
     if (r1 != 0 && r2 != 0)
@@ -2741,7 +2746,10 @@ fullpathcmp(
        full1 = exp1 + MAXPATHL;
        full2 = full1 + MAXPATHL;
 
-       expand_env(s1, exp1, MAXPATHL);
+       if (expandenv)
+           expand_env(s1, exp1, MAXPATHL);
+       else
+           vim_strncpy(exp1, s1, MAXPATHL - 1);
        r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE);
        r2 = vim_FullName(s2, full2, MAXPATHL, FALSE);
 
@@ -4027,7 +4035,7 @@ gen_expand_wildcards(
            /*
             * First expand environment variables, "~/" and "~user/".
             */
-           if (has_env_var(p) || *p == '~')
+           if ((has_env_var(p) && !(flags & EW_NOTENV)) || *p == '~')
            {
                p = expand_env_save_opt(p, TRUE);
                if (p == NULL)
index 57cc76760409fce8c4e892e65c7f875ce1f4f3aa..3199ba98ed8ffa7fde8a44b6c3b8d34c33d178a9 100644 (file)
@@ -9,7 +9,7 @@ void ml_close(buf_T *buf, int del_file);
 void ml_close_all(int del_file);
 void ml_close_notmod(void);
 void ml_timestamp(buf_T *buf);
-void ml_recover(void);
+void ml_recover(int checkext);
 int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
 char_u *make_percent_swname(char_u *dir, char_u *name);
 void get_b0_dict(char_u *fname, dict_T *d);
index ed8e99c0833a6cb861d00ff03450aad39ed6755a..3f58d30468466fdb308e3d14c042fdbf1fd2862a 100644 (file)
@@ -45,7 +45,7 @@ char_u *get_users(expand_T *xp, int idx);
 int match_user(char_u *name);
 void home_replace(buf_T *buf, char_u *src, char_u *dst, int dstlen, int one);
 char_u *home_replace_save(buf_T *buf, char_u *src);
-int fullpathcmp(char_u *s1, char_u *s2, int checkname);
+int fullpathcmp(char_u *s1, char_u *s2, int checkname, int expandenv);
 char_u *gettail(char_u *fname);
 char_u *gettail_sep(char_u *fname);
 char_u *getnextcomp(char_u *fname);
index 56bd763dda28174d8cf1aa1be2bac91a647c7c69..033f16384f4a6ef1101947a42693015414d78408 100644 (file)
@@ -5170,7 +5170,8 @@ find_pattern_in_path(
                        i = old_files;
                    if (i == max_path_depth)
                        break;
-                   if (fullpathcmp(new_fname, files[i].name, TRUE) & FPC_SAME)
+                   if (fullpathcmp(new_fname, files[i].name, TRUE, TRUE)
+                                                                   & FPC_SAME)
                    {
                        if (type != CHECK_PATH &&
                                action == ACTION_SHOW_ALL && files[i].matched)
index 8f32fd7c3ab9d66d668ae81edac4a02744ee5020..fbe20802cbdbd059eec7060f527db52430099ca8 100644 (file)
@@ -2343,7 +2343,7 @@ did_set_spelllang(win_T *wp)
 
            /* Check if we loaded this language before. */
            for (slang = first_lang; slang != NULL; slang = slang->sl_next)
-               if (fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME)
+               if (fullpathcmp(lang, slang->sl_fname, FALSE, TRUE) == FPC_SAME)
                    break;
        }
        else
@@ -2395,7 +2395,8 @@ did_set_spelllang(win_T *wp)
         * Loop over the languages, there can be several files for "lang".
         */
        for (slang = first_lang; slang != NULL; slang = slang->sl_next)
-           if (filename ? fullpathcmp(lang, slang->sl_fname, FALSE) == FPC_SAME
+           if (filename ? fullpathcmp(lang, slang->sl_fname, FALSE, TRUE)
+                                                                   == FPC_SAME
                         : STRICMP(lang, slang->sl_name) == 0)
            {
                region_mask = REGION_ALL;
@@ -2463,7 +2464,8 @@ did_set_spelllang(win_T *wp)
            for (c = 0; c < ga.ga_len; ++c)
            {
                p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
-               if (p != NULL && fullpathcmp(spf_name, p, FALSE) == FPC_SAME)
+               if (p != NULL && fullpathcmp(spf_name, p, FALSE, TRUE)
+                                                               == FPC_SAME)
                    break;
            }
            if (c < ga.ga_len)
@@ -2472,7 +2474,8 @@ did_set_spelllang(win_T *wp)
 
        /* Check if it was loaded already. */
        for (slang = first_lang; slang != NULL; slang = slang->sl_next)
-           if (fullpathcmp(spf_name, slang->sl_fname, FALSE) == FPC_SAME)
+           if (fullpathcmp(spf_name, slang->sl_fname, FALSE, TRUE)
+                                                               == FPC_SAME)
                break;
        if (slang == NULL)
        {
index 2616afbbb11712c61261d33c37fa9728ed1982a3..00c72f6f1a609e3897a520b3ce8c05a71fe1a57b 100644 (file)
@@ -1734,7 +1734,7 @@ spell_reload_one(
 
     for (slang = first_lang; slang != NULL; slang = slang->sl_next)
     {
-       if (fullpathcmp(fname, slang->sl_fname, FALSE) == FPC_SAME)
+       if (fullpathcmp(fname, slang->sl_fname, FALSE, TRUE) == FPC_SAME)
        {
            slang_clear(slang);
            if (spell_load_file(fname, NULL, slang, FALSE) == NULL)
@@ -5440,7 +5440,7 @@ spell_make_sugfile(spellinfo_T *spin, char_u *wfname)
      * It might have been done already by spell_reload_one().
      */
     for (slang = first_lang; slang != NULL; slang = slang->sl_next)
-       if (fullpathcmp(wfname, slang->sl_fname, FALSE) == FPC_SAME)
+       if (fullpathcmp(wfname, slang->sl_fname, FALSE, TRUE) == FPC_SAME)
            break;
     if (slang == NULL)
     {
index 2d46e14003c277652c4c8873f87501aa2d4401d1..6781a18906702346fc9011169fa7f924a1066810 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -3781,7 +3781,7 @@ test_for_current(
        fullname = expand_tag_fname(fname, tag_fname, TRUE);
        if (fullname != NULL)
        {
-           retval = (fullpathcmp(fullname, buf_ffname, TRUE) & FPC_SAME);
+           retval = (fullpathcmp(fullname, buf_ffname, TRUE, TRUE) & FPC_SAME);
            vim_free(fullname);
        }
 #ifdef FEAT_EMACS_TAGS
index 9eda9b223d06a36d81a3f93be8d458ed3462b4c9..856c663b72ce896f48489bbbd6f2aa38562816d6 100644 (file)
@@ -220,3 +220,87 @@ func Test_swapfile_delete()
   augroup END
   augroup! test_swapfile_delete
 endfunc
+
+func Test_swap_recover()
+  autocmd! SwapExists
+  augroup test_swap_recover
+    autocmd!
+    autocmd SwapExists * let v:swapchoice = 'r'
+  augroup END
+
+
+  call mkdir('Xswap')
+  let $Xswap = 'foo'  " Check for issue #4369.
+  set dir=Xswap//
+  " Create a valid swapfile by editing a file.
+  split Xswap/text
+  call setline(1, ['one', 'two', 'three'])
+  write  " file is written, not modified
+  " read the swapfile as a Blob
+  let swapfile_name = swapname('%')
+  let swapfile_bytes = readfile(swapfile_name, 'B')
+
+  " Close the file and recreate the swap file.
+  quit
+  call writefile(swapfile_bytes, swapfile_name)
+  " Edit the file again. This triggers recovery.
+  try
+    split Xswap/text
+  catch
+    " E308 should be caught, not E305.
+    call assert_exception('E308:')  " Original file may have been changed
+  endtry
+  " The file should be recovered.
+  call assert_equal(['one', 'two', 'three'], getline(1, 3))
+  quit!
+
+  call delete('Xswap/text')
+  call delete(swapfile_name)
+  call delete('Xswap', 'd')
+  unlet $Xswap
+  set dir&
+  augroup test_swap_recover
+    autocmd!
+  augroup END
+  augroup! test_swap_recover
+endfunc
+
+func Test_swap_recover_ext()
+  autocmd! SwapExists
+  augroup test_swap_recover_ext
+    autocmd!
+    autocmd SwapExists * let v:swapchoice = 'r'
+  augroup END
+
+
+  " Create a valid swapfile by editing a file with a special extension.
+  split Xtest.scr
+  call setline(1, ['one', 'two', 'three'])
+  write  " file is written, not modified
+  write  " write again to make sure the swapfile is created
+  " read the swapfile as a Blob
+  let swapfile_name = swapname('%')
+  let swapfile_bytes = readfile(swapfile_name, 'B')
+
+  " Close and delete the file and recreate the swap file.
+  quit
+  call delete('Xtest.scr')
+  call writefile(swapfile_bytes, swapfile_name)
+  " Edit the file again. This triggers recovery.
+  try
+    split Xtest.scr
+  catch
+    " E308 should be caught, not E306.
+    call assert_exception('E308:')  " Original file may have been changed
+  endtry
+  " The file should be recovered.
+  call assert_equal(['one', 'two', 'three'], getline(1, 3))
+  quit!
+
+  call delete('Xtest.scr')
+  call delete(swapfile_name)
+  augroup test_swap_recover_ext
+    autocmd!
+  augroup END
+  augroup! test_swap_recover_ext
+endfunc
index d2e4b90245af039978fa03ca3520d18370a1f1c7..c2ee827a8c5fac6077463329ad2fa5469581e794 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1371,
 /**/
     1370,
 /**/
index 153a8c6ed9e832e2f43403985a4c09950c9543ff..57fbe36af6336edb3d76e8b4a9cf7d6a9f881ad7 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -781,26 +781,27 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
 #define WILD_ICASE             0x100
 #define WILD_ALLLINKS          0x200
 
-/* Flags for expand_wildcards() */
-#define EW_DIR         0x01    /* include directory names */
-#define EW_FILE                0x02    /* include file names */
-#define EW_NOTFOUND    0x04    /* include not found names */
-#define EW_ADDSLASH    0x08    /* append slash to directory name */
-#define EW_KEEPALL     0x10    /* keep all matches */
-#define EW_SILENT      0x20    /* don't print "1 returned" from shell */
-#define EW_EXEC                0x40    /* executable files */
-#define EW_PATH                0x80    /* search in 'path' too */
-#define EW_ICASE       0x100   /* ignore case */
-#define EW_NOERROR     0x200   /* no error for bad regexp */
-#define EW_NOTWILD     0x400   /* add match with literal name if exists */
-#define EW_KEEPDOLLAR  0x800   /* do not escape $, $var is expanded */
-/* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
- * is used when executing commands and EW_SILENT for interactive expanding. */
-#define EW_ALLLINKS    0x1000  /* also links not pointing to existing file */
-#define EW_SHELLCMD    0x2000  /* called from expand_shellcmd(), don't check
-                                * if executable is in $PATH */
-#define EW_DODOT       0x4000  /* also files starting with a dot */
-#define EW_EMPTYOK     0x8000  /* no matches is not an error */
+// Flags for expand_wildcards()
+#define EW_DIR         0x01    // include directory names
+#define EW_FILE                0x02    // include file names
+#define EW_NOTFOUND    0x04    // include not found names
+#define EW_ADDSLASH    0x08    // append slash to directory name
+#define EW_KEEPALL     0x10    // keep all matches
+#define EW_SILENT      0x20    // don't print "1 returned" from shell
+#define EW_EXEC                0x40    // executable files
+#define EW_PATH                0x80    // search in 'path' too
+#define EW_ICASE       0x100   // ignore case
+#define EW_NOERROR     0x200   // no error for bad regexp
+#define EW_NOTWILD     0x400   // add match with literal name if exists
+#define EW_KEEPDOLLAR  0x800   // do not escape $, $var is expanded
+// Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
+// is used when executing commands and EW_SILENT for interactive expanding.
+#define EW_ALLLINKS    0x1000  // also links not pointing to existing file
+#define EW_SHELLCMD    0x2000  // called from expand_shellcmd(), don't check
+                               // if executable is in $PATH
+#define EW_DODOT       0x4000  // also files starting with a dot
+#define EW_EMPTYOK     0x8000  // no matches is not an error
+#define EW_NOTENV      0x10000 // do not expand environment variables
 
 /* Flags for find_file_*() functions. */
 #define FINDFILE_FILE  0       /* only files */