Patch 8.1.2297
Problem:    The ex_vimgrep() function is too long.
Solution:   Split it in three parts. (Yegappan Lakshmanan, closes #5211)
Files:      src/quickfix.c


*** ../vim-8.1.2296/src/quickfix.c      2019-11-02 22:54:37.405188813 +0100
--- src/quickfix.c      2019-11-12 22:58:43.664763269 +0100
***************
*** 5319,5329 ****
   * as one.
   */
      static void
! qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
  {
      while (n-- > 0 && !got_int)
      {
-       qfline_T        *first_entry = entry;
        int             first_errornr = *errornr;
  
        if (linewise)
--- 5319,5330 ----
   * as one.
   */
      static void
! qf_get_nth_below_entry(qfline_T *entry_arg, int n, int linewise, int *errornr)
  {
+     qfline_T *entry = entry_arg;
+ 
      while (n-- > 0 && !got_int)
      {
        int             first_errornr = *errornr;
  
        if (linewise)
***************
*** 5334,5345 ****
                || entry->qf_next->qf_fnum != entry->qf_fnum)
        {
            if (linewise)
-           {
-               // If multiple entries are on the same line, then use the first
-               // entry
-               entry = first_entry;
                *errornr = first_errornr;
-           }
            break;
        }
  
--- 5335,5341 ----
***************
*** 5815,5933 ****
  }
  
  /*
!  * ":vimgrep {pattern} file(s)"
!  * ":vimgrepadd {pattern} file(s)"
!  * ":lvimgrep {pattern} file(s)"
!  * ":lvimgrepadd {pattern} file(s)"
   */
!     void
! ex_vimgrep(exarg_T *eap)
  {
-     regmmatch_T       regmatch;
-     int               fcount;
-     char_u    **fnames;
-     char_u    *fname;
-     char_u    *title;
-     char_u    *s;
      char_u    *p;
-     int               fi;
-     qf_info_T *qi;
-     qf_list_T *qfl;
-     int_u     save_qfid;
-     win_T     *wp = NULL;
-     buf_T     *buf;
-     int               duplicate_name = FALSE;
-     int               using_dummy;
-     int               redraw_for_dummy = FALSE;
-     int               found_match;
-     buf_T     *first_match_buf = NULL;
-     time_t    seconds = 0;
-     aco_save_T        aco;
-     int               flags = 0;
-     long      tomatch;
-     char_u    *dirname_start = NULL;
-     char_u    *dirname_now = NULL;
-     char_u    *target_dir = NULL;
-     char_u    *au_name =  NULL;
  
!     au_name = vgr_get_auname(eap->cmdidx);
!     if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
!                                              curbuf->b_fname, TRUE, curbuf))
!     {
! #ifdef FEAT_EVAL
!       if (aborting())
!           return;
! #endif
!     }
  
!     qi = qf_cmd_get_or_alloc_stack(eap, &wp);
!     if (qi == NULL)
!       return;
  
      if (eap->addr_count > 0)
!       tomatch = eap->line2;
      else
!       tomatch = MAXLNUM;
  
      // Get the search pattern: either white-separated or enclosed in //
!     regmatch.regprog = NULL;
!     title = vim_strsave(qf_cmdtitle(*eap->cmdlinep));
!     p = skip_vimgrep_pat(eap->arg, &s, &flags);
      if (p == NULL)
      {
        emsg(_(e_invalpat));
!       goto theend;
      }
  
!     vgr_init_regmatch(&regmatch, s);
!     if (regmatch.regprog == NULL)
!       goto theend;
  
      p = skipwhite(p);
      if (*p == NUL)
      {
        emsg(_("E683: File name missing or invalid pattern"));
!       goto theend;
      }
  
-     if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd
-               && eap->cmdidx != CMD_vimgrepadd
-               && eap->cmdidx != CMD_lvimgrepadd)
-                                       || qf_stack_empty(qi))
-       // make place for a new list
-       qf_new_list(qi, title != NULL ? title : qf_cmdtitle(*eap->cmdlinep));
- 
      // parse the list of arguments
!     if (get_arglist_exp(p, &fcount, &fnames, TRUE) == FAIL)
!       goto theend;
!     if (fcount == 0)
      {
        emsg(_(e_nomatch));
!       goto theend;
      }
  
      dirname_start = alloc_id(MAXPATHL, aid_qf_dirname_start);
      dirname_now = alloc_id(MAXPATHL, aid_qf_dirname_now);
      if (dirname_start == NULL || dirname_now == NULL)
-     {
-       FreeWild(fcount, fnames);
        goto theend;
-     }
  
      // Remember the current directory, because a BufRead autocommand that does
      // ":lcd %:p:h" changes the meaning of short path names.
      mch_dirname(dirname_start, MAXPATHL);
  
-     incr_quickfix_busy();
- 
-     // Remember the current quickfix list identifier, so that we can check for
-     // autocommands changing the current quickfix list.
-     save_qfid = qf_get_curlist(qi)->qf_id;
- 
      seconds = (time_t)0;
!     for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi)
      {
!       fname = shorten_fname1(fnames[fi]);
        if (time(NULL) > seconds)
        {
            // Display the file name every second or so, show the user we are
--- 5811,5922 ----
  }
  
  /*
!  * :vimgrep command arguments
   */
! typedef struct
! {
!     long      tomatch;        // maximum number of matches to find
!     char_u    *spat;          // search pattern
!     int               flags;          // search modifier
!     char_u    **fnames;       // list of files to search
!     int               fcount;         // number of files
!     regmmatch_T       regmatch;       // compiled search pattern
!     char_u    *qf_title;      // quickfix list title
! } vgr_args_T;
! 
! /*
!  * Process :vimgrep command arguments. The command syntax is:
!  *
!  *    :{count}vimgrep /{pattern}/[g][j] {file} ...
!  */
!     static int
! vgr_process_args(
!       exarg_T         *eap,
!       vgr_args_T      *args)
  {
      char_u    *p;
  
!     vim_memset(args, 0, sizeof(*args));
  
!     args->regmatch.regprog = NULL;
!     args->qf_title = vim_strsave(qf_cmdtitle(*eap->cmdlinep));
  
      if (eap->addr_count > 0)
!       args->tomatch = eap->line2;
      else
!       args->tomatch = MAXLNUM;
  
      // Get the search pattern: either white-separated or enclosed in //
!     p = skip_vimgrep_pat(eap->arg, &args->spat, &args->flags);
      if (p == NULL)
      {
        emsg(_(e_invalpat));
!       return FAIL;
      }
  
!     vgr_init_regmatch(&args->regmatch, args->spat);
!     if (args->regmatch.regprog == NULL)
!       return FAIL;
  
      p = skipwhite(p);
      if (*p == NUL)
      {
        emsg(_("E683: File name missing or invalid pattern"));
!       return FAIL;
      }
  
      // parse the list of arguments
!     if (get_arglist_exp(p, &args->fcount, &args->fnames, TRUE) == FAIL)
!       return FAIL;
!     if (args->fcount == 0)
      {
        emsg(_(e_nomatch));
!       return FAIL;
      }
  
+     return OK;
+ }
+ 
+ /*
+  * Search for a pattern in a list of files and populate the quickfix list with
+  * the matches.
+  */
+     static int
+ vgr_process_files(
+       win_T           *wp,
+       qf_info_T       *qi,
+       vgr_args_T      *cmd_args,
+       int             *redraw_for_dummy,
+       buf_T           **first_match_buf,
+       char_u          **target_dir)
+ {
+     int               status = FAIL;
+     int_u     save_qfid = qf_get_curlist(qi)->qf_id;
+     time_t    seconds = 0;
+     char_u    *fname;
+     int               fi;
+     buf_T     *buf;
+     int               duplicate_name = FALSE;
+     int               using_dummy;
+     char_u    *dirname_start = NULL;
+     char_u    *dirname_now = NULL;
+     int               found_match;
+     aco_save_T        aco;
+ 
      dirname_start = alloc_id(MAXPATHL, aid_qf_dirname_start);
      dirname_now = alloc_id(MAXPATHL, aid_qf_dirname_now);
      if (dirname_start == NULL || dirname_now == NULL)
        goto theend;
  
      // Remember the current directory, because a BufRead autocommand that does
      // ":lcd %:p:h" changes the meaning of short path names.
      mch_dirname(dirname_start, MAXPATHL);
  
      seconds = (time_t)0;
!     for (fi = 0; fi < cmd_args->fcount && !got_int && cmd_args->tomatch > 0;
!                                                                       ++fi)
      {
!       fname = shorten_fname1(cmd_args->fnames[fi]);
        if (time(NULL) > seconds)
        {
            // Display the file name every second or so, show the user we are
***************
*** 5936,5948 ****
            vgr_display_fname(fname);
        }
  
!       buf = buflist_findname_exp(fnames[fi]);
        if (buf == NULL || buf->b_ml.ml_mfp == NULL)
        {
            // Remember that a buffer with this name already exists.
            duplicate_name = (buf != NULL);
            using_dummy = TRUE;
!           redraw_for_dummy = TRUE;
  
            buf = vgr_load_dummy_buf(fname, dirname_start, dirname_now);
        }
--- 5925,5937 ----
            vgr_display_fname(fname);
        }
  
!       buf = buflist_findname_exp(cmd_args->fnames[fi]);
        if (buf == NULL || buf->b_ml.ml_mfp == NULL)
        {
            // Remember that a buffer with this name already exists.
            duplicate_name = (buf != NULL);
            using_dummy = TRUE;
!           *redraw_for_dummy = TRUE;
  
            buf = vgr_load_dummy_buf(fname, dirname_start, dirname_now);
        }
***************
*** 5952,5963 ****
  
        // Check whether the quickfix list is still valid. When loading a
        // buffer above, autocommands might have changed the quickfix list.
!       if (!vgr_qflist_valid(wp, qi, save_qfid, qf_cmdtitle(*eap->cmdlinep)))
!       {
!           FreeWild(fcount, fnames);
!           decr_quickfix_busy();
            goto theend;
!       }
        save_qfid = qf_get_curlist(qi)->qf_id;
  
        if (buf == NULL)
--- 5941,5949 ----
  
        // Check whether the quickfix list is still valid. When loading a
        // buffer above, autocommands might have changed the quickfix list.
!       if (!vgr_qflist_valid(wp, qi, save_qfid, cmd_args->qf_title))
            goto theend;
! 
        save_qfid = qf_get_curlist(qi)->qf_id;
  
        if (buf == NULL)
***************
*** 5970,5982 ****
            // Try for a match in all lines of the buffer.
            // For ":1vimgrep" look for first match only.
            found_match = vgr_match_buflines(qf_get_curlist(qi),
!                   fname, buf, &regmatch,
!                   &tomatch, duplicate_name, flags);
  
            if (using_dummy)
            {
!               if (found_match && first_match_buf == NULL)
!                   first_match_buf = buf;
                if (duplicate_name)
                {
                    // Never keep a dummy buffer if there is another buffer
--- 5956,5968 ----
            // Try for a match in all lines of the buffer.
            // For ":1vimgrep" look for first match only.
            found_match = vgr_match_buflines(qf_get_curlist(qi),
!                   fname, buf, &cmd_args->regmatch,
!                   &cmd_args->tomatch, duplicate_name, cmd_args->flags);
  
            if (using_dummy)
            {
!               if (found_match && *first_match_buf == NULL)
!                   *first_match_buf = buf;
                if (duplicate_name)
                {
                    // Never keep a dummy buffer if there is another buffer
***************
*** 6000,6006 ****
                        wipe_dummy_buffer(buf, dirname_start);
                        buf = NULL;
                    }
!                   else if (buf != first_match_buf || (flags & VGR_NOJUMP))
                    {
                        unload_dummy_buffer(buf, dirname_start);
                        // Keeping the buffer, remove the dummy flag.
--- 5986,5993 ----
                        wipe_dummy_buffer(buf, dirname_start);
                        buf = NULL;
                    }
!                   else if (buf != *first_match_buf
!                                       || (cmd_args->flags & VGR_NOJUMP))
                    {
                        unload_dummy_buffer(buf, dirname_start);
                        // Keeping the buffer, remove the dummy flag.
***************
*** 6016,6025 ****
  
                    // If the buffer is still loaded we need to use the
                    // directory we jumped to below.
!                   if (buf == first_match_buf
!                           && target_dir == NULL
                            && STRCMP(dirname_start, dirname_now) != 0)
!                       target_dir = vim_strsave(dirname_now);
  
                    // The buffer is still loaded, the Filetype autocommands
                    // need to be done now, in that buffer.  And the modelines
--- 6003,6012 ----
  
                    // If the buffer is still loaded we need to use the
                    // directory we jumped to below.
!                   if (buf == *first_match_buf
!                           && *target_dir == NULL
                            && STRCMP(dirname_start, dirname_now) != 0)
!                       *target_dir = vim_strsave(dirname_now);
  
                    // The buffer is still loaded, the Filetype autocommands
                    // need to be done now, in that buffer.  And the modelines
***************
*** 6037,6043 ****
        }
      }
  
!     FreeWild(fcount, fnames);
  
      qfl = qf_get_curlist(qi);
      qfl->qf_nonevalid = FALSE;
--- 6024,6093 ----
        }
      }
  
!     status = OK;
! 
! theend:
!     vim_free(dirname_now);
!     vim_free(dirname_start);
!     return status;
! }
! 
! /*
!  * ":vimgrep {pattern} file(s)"
!  * ":vimgrepadd {pattern} file(s)"
!  * ":lvimgrep {pattern} file(s)"
!  * ":lvimgrepadd {pattern} file(s)"
!  */
!     void
! ex_vimgrep(exarg_T *eap)
! {
!     vgr_args_T        args;
!     qf_info_T *qi;
!     qf_list_T *qfl;
!     int_u     save_qfid;
!     win_T     *wp = NULL;
!     int               redraw_for_dummy = FALSE;
!     buf_T     *first_match_buf = NULL;
!     char_u    *target_dir = NULL;
!     char_u    *au_name =  NULL;
!     int               status;
! 
!     au_name = vgr_get_auname(eap->cmdidx);
!     if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
!                                              curbuf->b_fname, TRUE, curbuf))
!     {
! #ifdef FEAT_EVAL
!       if (aborting())
!           return;
! #endif
!     }
! 
!     qi = qf_cmd_get_or_alloc_stack(eap, &wp);
!     if (qi == NULL)
!       return;
! 
!     if (vgr_process_args(eap, &args) == FAIL)
!       goto theend;
! 
!     if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd
!               && eap->cmdidx != CMD_vimgrepadd
!               && eap->cmdidx != CMD_lvimgrepadd)
!                                       || qf_stack_empty(qi))
!       // make place for a new list
!       qf_new_list(qi, args.qf_title);
! 
!     incr_quickfix_busy();
! 
!     status = vgr_process_files(wp, qi, &args, &redraw_for_dummy,
!                                               &first_match_buf, &target_dir);
!     if (status != OK)
!     {
!       FreeWild(args.fcount, args.fnames);
!       decr_quickfix_busy();
!       goto theend;
!     }
! 
!     FreeWild(args.fcount, args.fnames);
  
      qfl = qf_get_curlist(qi);
      qfl->qf_nonevalid = FALSE;
***************
*** 6047,6052 ****
--- 6097,6106 ----
  
      qf_update_buffer(qi, NULL);
  
+     // Remember the current quickfix list identifier, so that we can check for
+     // autocommands changing the current quickfix list.
+     save_qfid = qf_get_curlist(qi)->qf_id;
+ 
      if (au_name != NULL)
        apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
                                               curbuf->b_fname, TRUE, curbuf);
***************
*** 6062,6073 ****
      // Jump to first match.
      if (!qf_list_empty(qf_get_curlist(qi)))
      {
!       if ((flags & VGR_NOJUMP) == 0)
            vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy,
                    first_match_buf, target_dir);
      }
      else
!       semsg(_(e_nomatch2), s);
  
      decr_quickfix_busy();
  
--- 6116,6127 ----
      // Jump to first match.
      if (!qf_list_empty(qf_get_curlist(qi)))
      {
!       if ((args.flags & VGR_NOJUMP) == 0)
            vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy,
                    first_match_buf, target_dir);
      }
      else
!       semsg(_(e_nomatch2), args.spat);
  
      decr_quickfix_busy();
  
***************
*** 6083,6093 ****
      }
  
  theend:
!     vim_free(title);
!     vim_free(dirname_now);
!     vim_free(dirname_start);
      vim_free(target_dir);
!     vim_regfree(regmatch.regprog);
  }
  
  /*
--- 6137,6145 ----
      }
  
  theend:
!     vim_free(args.qf_title);
      vim_free(target_dir);
!     vim_regfree(args.regmatch.regprog);
  }
  
  /*
*** ../vim-8.1.2296/src/version.c       2019-11-12 22:44:16.415538386 +0100
--- src/version.c       2019-11-12 22:48:11.278841830 +0100
***************
*** 743,744 ****
--- 743,746 ----
  {   /* Add new patch number below this line */
+ /**/
+     2297,
  /**/

-- 
ASCII stupid question, get a stupid ANSI.

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201911122201.xACM11NN019470%40masaka.moolenaar.net.

Raspunde prin e-mail lui