Patch 8.1.0252
Problem:    Quickfix functions are too long.
Solution:   Refactor. (Yegappan Lakshmanan, closes #2950)
Files:      src/quickfix.c


*** ../vim-8.1.0251/src/quickfix.c      2018-08-07 19:47:46.746434541 +0200
--- src/quickfix.c      2018-08-07 21:52:51.654369210 +0200
***************
*** 201,306 ****
  
  /*
   * Convert an errorformat pattern to a regular expression pattern.
!  * See fmt_pat definition above for the list of supported patterns.
   */
      static char_u *
! fmtpat_to_regpat(
!       char_u  *efmp,
!       efm_T   *fmt_ptr,
        int     idx,
        int     round,
-       char_u  *ptr,
        char_u  *errmsg)
  {
      char_u    *srcptr;
  
!     if (fmt_ptr->addr[idx])
      {
        /* Each errorformat pattern can occur only once */
        sprintf((char *)errmsg,
!               _("E372: Too many %%%c in format string"), *efmp);
        EMSG(errmsg);
        return NULL;
      }
      if ((idx && idx < 6
!               && vim_strchr((char_u *)"DXOPQ", fmt_ptr->prefix) != NULL)
            || (idx == 6
!               && vim_strchr((char_u *)"OPQ", fmt_ptr->prefix) == NULL))
      {
        sprintf((char *)errmsg,
!               _("E373: Unexpected %%%c in format string"), *efmp);
        EMSG(errmsg);
        return NULL;
      }
!     fmt_ptr->addr[idx] = (char_u)++round;
!     *ptr++ = '\\';
!     *ptr++ = '(';
  #ifdef BACKSLASH_IN_FILENAME
!     if (*efmp == 'f')
      {
        /* Also match "c:" in the file name, even when
         * checking for a colon next: "%f:".
         * "\%(\a:\)\=" */
!       STRCPY(ptr, "\\%(\\a:\\)\\=");
!       ptr += 10;
      }
  #endif
!     if (*efmp == 'f' && efmp[1] != NUL)
      {
!       if (efmp[1] != '\\' && efmp[1] != '%')
        {
            /* A file name may contain spaces, but this isn't
             * in "\f".  For "%f:%l:%m" there may be a ":" in
             * the file name.  Use ".\{-1,}x" instead (x is
             * the next character), the requirement that :999:
             * follows should work. */
!           STRCPY(ptr, ".\\{-1,}");
!           ptr += 7;
        }
        else
        {
            /* File name followed by '\\' or '%': include as
             * many file name chars as possible. */
!           STRCPY(ptr, "\\f\\+");
!           ptr += 4;
        }
      }
      else
      {
        srcptr = (char_u *)fmt_pat[idx].pattern;
!       while ((*ptr = *srcptr++) != NUL)
!           ++ptr;
      }
!     *ptr++ = '\\';
!     *ptr++ = ')';
  
!     return ptr;
  }
  
  /*
   * Convert a scanf like format in 'errorformat' to a regular expression.
   */
      static char_u *
  scanf_fmt_to_regpat(
        char_u  *efm,
        int     len,
!       char_u  **pefmp,
!       char_u  *ptr,
        char_u  *errmsg)
  {
      char_u    *efmp = *pefmp;
  
!     if (*++efmp == '[' || *efmp == '\\')
      {
!       if ((*ptr++ = *efmp) == '[')    /* %*[^a-z0-9] etc. */
        {
            if (efmp[1] == '^')
!               *ptr++ = *++efmp;
            if (efmp < efm + len)
            {
!               *ptr++ = *++efmp;           /* could be ']' */
                while (efmp < efm + len
!                       && (*ptr++ = *++efmp) != ']')
                    /* skip */;
                if (efmp == efm + len)
                {
--- 201,309 ----
  
  /*
   * Convert an errorformat pattern to a regular expression pattern.
!  * See fmt_pat definition above for the list of supported patterns.  The
!  * pattern specifier is supplied in "efmpat".  The converted pattern is stored
!  * in "regpat".  Returns a pointer to the location after the pattern.
   */
      static char_u *
! efmpat_to_regpat(
!       char_u  *efmpat,
!       char_u  *regpat,
!       efm_T   *efminfo,
        int     idx,
        int     round,
        char_u  *errmsg)
  {
      char_u    *srcptr;
  
!     if (efminfo->addr[idx])
      {
        /* Each errorformat pattern can occur only once */
        sprintf((char *)errmsg,
!               _("E372: Too many %%%c in format string"), *efmpat);
        EMSG(errmsg);
        return NULL;
      }
      if ((idx && idx < 6
!               && vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL)
            || (idx == 6
!               && vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL))
      {
        sprintf((char *)errmsg,
!               _("E373: Unexpected %%%c in format string"), *efmpat);
        EMSG(errmsg);
        return NULL;
      }
!     efminfo->addr[idx] = (char_u)++round;
!     *regpat++ = '\\';
!     *regpat++ = '(';
  #ifdef BACKSLASH_IN_FILENAME
!     if (*efmpat == 'f')
      {
        /* Also match "c:" in the file name, even when
         * checking for a colon next: "%f:".
         * "\%(\a:\)\=" */
!       STRCPY(regpat, "\\%(\\a:\\)\\=");
!       regpat += 10;
      }
  #endif
!     if (*efmpat == 'f' && efmpat[1] != NUL)
      {
!       if (efmpat[1] != '\\' && efmpat[1] != '%')
        {
            /* A file name may contain spaces, but this isn't
             * in "\f".  For "%f:%l:%m" there may be a ":" in
             * the file name.  Use ".\{-1,}x" instead (x is
             * the next character), the requirement that :999:
             * follows should work. */
!           STRCPY(regpat, ".\\{-1,}");
!           regpat += 7;
        }
        else
        {
            /* File name followed by '\\' or '%': include as
             * many file name chars as possible. */
!           STRCPY(regpat, "\\f\\+");
!           regpat += 4;
        }
      }
      else
      {
        srcptr = (char_u *)fmt_pat[idx].pattern;
!       while ((*regpat = *srcptr++) != NUL)
!           ++regpat;
      }
!     *regpat++ = '\\';
!     *regpat++ = ')';
  
!     return regpat;
  }
  
  /*
   * Convert a scanf like format in 'errorformat' to a regular expression.
+  * Returns a pointer to the location after the pattern.
   */
      static char_u *
  scanf_fmt_to_regpat(
+       char_u  **pefmp,
        char_u  *efm,
        int     len,
!       char_u  *regpat,
        char_u  *errmsg)
  {
      char_u    *efmp = *pefmp;
  
!     if (*efmp == '[' || *efmp == '\\')
      {
!       if ((*regpat++ = *efmp) == '[') /* %*[^a-z0-9] etc. */
        {
            if (efmp[1] == '^')
!               *regpat++ = *++efmp;
            if (efmp < efm + len)
            {
!               *regpat++ = *++efmp;        /* could be ']' */
                while (efmp < efm + len
!                       && (*regpat++ = *++efmp) != ']')
                    /* skip */;
                if (efmp == efm + len)
                {
***************
*** 310,318 ****
            }
        }
        else if (efmp < efm + len)      /* %*\D, %*\s etc. */
!           *ptr++ = *++efmp;
!       *ptr++ = '\\';
!       *ptr++ = '+';
      }
      else
      {
--- 313,321 ----
            }
        }
        else if (efmp < efm + len)      /* %*\D, %*\s etc. */
!           *regpat++ = *++efmp;
!       *regpat++ = '\\';
!       *regpat++ = '+';
      }
      else
      {
***************
*** 325,360 ****
  
      *pefmp = efmp;
  
!     return ptr;
  }
  
  /*
   * Analyze/parse an errorformat prefix.
   */
!     static int
! efm_analyze_prefix(char_u **pefmp, efm_T *fmt_ptr, char_u *errmsg)
  {
-     char_u    *efmp = *pefmp;
- 
      if (vim_strchr((char_u *)"+-", *efmp) != NULL)
!       fmt_ptr->flags = *efmp++;
      if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL)
!       fmt_ptr->prefix = *efmp;
      else
      {
        sprintf((char *)errmsg,
                _("E376: Invalid %%%c in format string prefix"), *efmp);
        EMSG(errmsg);
!       return FAIL;
      }
  
!     *pefmp = efmp;
! 
!     return OK;
  }
  
  /*
!  * Converts a 'errorformat' string to regular expression pattern
   */
      static int
  efm_to_regpat(
--- 328,362 ----
  
      *pefmp = efmp;
  
!     return regpat;
  }
  
  /*
   * Analyze/parse an errorformat prefix.
   */
!     static char_u *
! efm_analyze_prefix(char_u *efmp, efm_T *efminfo, char_u *errmsg)
  {
      if (vim_strchr((char_u *)"+-", *efmp) != NULL)
!       efminfo->flags = *efmp++;
      if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL)
!       efminfo->prefix = *efmp;
      else
      {
        sprintf((char *)errmsg,
                _("E376: Invalid %%%c in format string prefix"), *efmp);
        EMSG(errmsg);
!       return NULL;
      }
  
!     return efmp;
  }
  
  /*
!  * Converts a 'errorformat' string part in 'efm' to a regular expression
!  * pattern.  The resulting regex pattern is returned in "regpat". Additional
!  * information about the 'erroformat' pattern is returned in "fmt_ptr".
!  * Returns OK or FAIL.
   */
      static int
  efm_to_regpat(
***************
*** 370,376 ****
      int               idx = 0;
  
      /*
!      * Build regexp pattern from current 'errorformat' option
       */
      ptr = regpat;
      *ptr++ = '^';
--- 372,378 ----
      int               idx = 0;
  
      /*
!      * Build a regexp pattern for a 'errorformat' option part
       */
      ptr = regpat;
      *ptr++ = '^';
***************
*** 385,401 ****
                    break;
            if (idx < FMT_PATTERNS)
            {
!               ptr = fmtpat_to_regpat(efmp, fmt_ptr, idx, round, ptr,
                                                                errmsg);
                if (ptr == NULL)
!                   return -1;
                round++;
            }
            else if (*efmp == '*')
            {
!               ptr = scanf_fmt_to_regpat(efm, len, &efmp, ptr, errmsg);
                if (ptr == NULL)
!                   return -1;
            }
            else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL)
                *ptr++ = *efmp;         /* regexp magic characters */
--- 387,404 ----
                    break;
            if (idx < FMT_PATTERNS)
            {
!               ptr = efmpat_to_regpat(efmp, ptr, fmt_ptr, idx, round,
                                                                errmsg);
                if (ptr == NULL)
!                   return FAIL;
                round++;
            }
            else if (*efmp == '*')
            {
!               ++efmp;
!               ptr = scanf_fmt_to_regpat(&efmp, efm, len, ptr, errmsg);
                if (ptr == NULL)
!                   return FAIL;
            }
            else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL)
                *ptr++ = *efmp;         /* regexp magic characters */
***************
*** 405,419 ****
                fmt_ptr->conthere = TRUE;
            else if (efmp == efm + 1)           /* analyse prefix */
            {
!               if (efm_analyze_prefix(&efmp, fmt_ptr, errmsg) == FAIL)
!                   return -1;
            }
            else
            {
                sprintf((char *)errmsg,
                        _("E377: Invalid %%%c in format string"), *efmp);
                EMSG(errmsg);
!               return -1;
            }
        }
        else                    /* copy normal character */
--- 408,427 ----
                fmt_ptr->conthere = TRUE;
            else if (efmp == efm + 1)           /* analyse prefix */
            {
!               /*
!                * prefix is allowed only at the beginning of the errorformat
!                * option part
!                */
!               efmp = efm_analyze_prefix(efmp, fmt_ptr, errmsg);
!               if (efmp == NULL)
!                   return FAIL;
            }
            else
            {
                sprintf((char *)errmsg,
                        _("E377: Invalid %%%c in format string"), *efmp);
                EMSG(errmsg);
!               return FAIL;
            }
        }
        else                    /* copy normal character */
***************
*** 429,437 ****
      *ptr++ = '$';
      *ptr = NUL;
  
!     return 0;
  }
  
      static void
  free_efm_list(efm_T **efm_first)
  {
--- 437,448 ----
      *ptr++ = '$';
      *ptr = NUL;
  
!     return OK;
  }
  
+ /*
+  * Free the 'errorformat' information list
+  */
      static void
  free_efm_list(efm_T **efm_first)
  {
***************
*** 446,452 ****
      fmt_start = NULL;
  }
  
! /* Parse 'errorformat' option */
      static efm_T *
  parse_efm_option(char_u *efm)
  {
--- 457,504 ----
      fmt_start = NULL;
  }
  
! /*
!  * Compute the size of the buffer used to convert a 'errorformat' pattern into
!  * a regular expression pattern.
!  */
!     static int
! efm_regpat_bufsz(char_u *efm)
! {
!     int sz;
!     int i;
! 
!     sz = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2);
!     for (i = FMT_PATTERNS; i > 0; )
!       sz += (int)STRLEN(fmt_pat[--i].pattern);
! #ifdef BACKSLASH_IN_FILENAME
!     sz += 12; /* "%f" can become twelve chars longer (see efm_to_regpat) */
! #else
!     sz += 2; /* "%f" can become two chars longer */
! #endif
! 
!     return sz;
! }
! 
! /*
!  * Return the length of a 'errorformat' option part (separated by ",").
!  */
!     static int
! efm_option_part_len(char_u *efm)
! {
!     int len;
! 
!     for (len = 0; efm[len] != NUL && efm[len] != ','; ++len)
!       if (efm[len] == '\\' && efm[len + 1] != NUL)
!           ++len;
! 
!     return len;
! }
! 
! /*
!  * Parse the 'errorformat' option. Multiple parts in the 'errorformat' option
!  * are parsed and converted to regular expressions. Returns information about
!  * the parsed 'errorformat' option.
!  */
      static efm_T *
  parse_efm_option(char_u *efm)
  {
***************
*** 457,464 ****
      efm_T     *fmt_last = NULL;
      char_u    *fmtstr = NULL;
      int               len;
!     int               i;
!     int               round;
  
      errmsglen = CMDBUFFSIZE + 1;
      errmsg = alloc_id(errmsglen, aid_qf_errmsg);
--- 509,515 ----
      efm_T     *fmt_last = NULL;
      char_u    *fmtstr = NULL;
      int               len;
!     int               sz;
  
      errmsglen = CMDBUFFSIZE + 1;
      errmsg = alloc_id(errmsglen, aid_qf_errmsg);
***************
*** 473,487 ****
      /*
       * Get some space to modify the format string into.
       */
!     i = (FMT_PATTERNS * 3) + ((int)STRLEN(efm) << 2);
!     for (round = FMT_PATTERNS; round > 0; )
!       i += (int)STRLEN(fmt_pat[--round].pattern);
! #ifdef BACKSLASH_IN_FILENAME
!     i += 12; /* "%f" can become twelve chars longer (see efm_to_regpat) */
! #else
!     i += 2; /* "%f" can become two chars longer */
! #endif
!     if ((fmtstr = alloc(i)) == NULL)
        goto parse_efm_error;
  
      while (efm[0] != NUL)
--- 524,531 ----
      /*
       * Get some space to modify the format string into.
       */
!     sz = efm_regpat_bufsz(efm);
!     if ((fmtstr = alloc(sz)) == NULL)
        goto parse_efm_error;
  
      while (efm[0] != NUL)
***************
*** 501,511 ****
        /*
         * Isolate one part in the 'errorformat' option
         */
!       for (len = 0; efm[len] != NUL && efm[len] != ','; ++len)
!           if (efm[len] == '\\' && efm[len + 1] != NUL)
!               ++len;
  
!       if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg) == -1)
            goto parse_efm_error;
        if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL)
            goto parse_efm_error;
--- 545,553 ----
        /*
         * Isolate one part in the 'errorformat' option
         */
!       len = efm_option_part_len(efm);
  
!       if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg) == FAIL)
            goto parse_efm_error;
        if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL)
            goto parse_efm_error;
***************
*** 539,544 ****
--- 581,590 ----
      QF_MULTISCAN = 5,
  };
  
+ /*
+  * State information used to parse lines and add entries to a 
quickfix/location
+  * list.
+  */
  typedef struct {
      char_u    *linebuf;
      int               linelen;
***************
*** 554,559 ****
--- 600,608 ----
      vimconv_T vc;
  } qfstate_T;
  
+ /*
+  * Allocate more memory for the line buffer used for parsing lines.
+  */
      static char_u *
  qf_grow_linebuf(qfstate_T *state, int newsz)
  {
***************
*** 861,870 ****
  } qffields_T;
  
  /*
!  * Parse the error format matches in 'regmatch' and set the values in 
'fields'.
!  * fmt_ptr contains the 'efm' format specifiers/prefixes that have a match.
!  * Returns QF_OK if all the matches are successfully parsed. On failure,
!  * returns QF_FAIL or QF_NOMEM.
   */
      static int
  qf_parse_match(
--- 910,1160 ----
  } qffields_T;
  
  /*
!  * Parse the match for filename ('%f') pattern in regmatch.
!  * Return the matched value in "fields->namebuf".
!  */
!     static int
! qf_parse_fmt_f(regmatch_T *rmp, int midx, qffields_T *fields, int prefix)
! {
!     int c;
! 
!     if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL)
!       return QF_FAIL;
! 
!     /* Expand ~/file and $HOME/file to full path. */
!     c = *rmp->endp[midx];
!     *rmp->endp[midx] = NUL;
!     expand_env(rmp->startp[midx], fields->namebuf, CMDBUFFSIZE);
!     *rmp->endp[midx] = c;
! 
!     /*
!      * For separate filename patterns (%O, %P and %Q), the specified file
!      * should exist.
!      */
!     if (vim_strchr((char_u *)"OPQ", prefix) != NULL
!           && mch_getperm(fields->namebuf) == -1)
!       return QF_FAIL;
! 
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for error number ('%n') pattern in regmatch.
!  * Return the matched value in "fields->enr".
!  */
!     static int
! qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     if (rmp->startp[midx] == NULL)
!       return QF_FAIL;
!     fields->enr = (int)atol((char *)rmp->startp[midx]);
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for line number (%l') pattern in regmatch.
!  * Return the matched value in "fields->lnum".
!  */
!     static int
! qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     if (rmp->startp[midx] == NULL)
!       return QF_FAIL;
!     fields->lnum = atol((char *)rmp->startp[midx]);
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for column number ('%c') pattern in regmatch.
!  * Return the matched value in "fields->col".
!  */
!     static int
! qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     if (rmp->startp[midx] == NULL)
!       return QF_FAIL;
!     fields->col = (int)atol((char *)rmp->startp[midx]);
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for error type ('%t') pattern in regmatch.
!  * Return the matched value in "fields->type".
!  */
!     static int
! qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     if (rmp->startp[midx] == NULL)
!       return QF_FAIL;
!     fields->type = *rmp->startp[midx];
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for '%+' format pattern. The whole matching line is 
included
!  * in the error string.  Return the matched line in "fields->errmsg".
!  */
!     static int
! qf_parse_fmt_plus(char_u *linebuf, int linelen, qffields_T *fields)
! {
!     char_u    *p;
! 
!     if (linelen >= fields->errmsglen)
!     {
!       /* linelen + null terminator */
!       if ((p = vim_realloc(fields->errmsg, linelen + 1)) == NULL)
!           return QF_NOMEM;
!       fields->errmsg = p;
!       fields->errmsglen = linelen + 1;
!     }
!     vim_strncpy(fields->errmsg, linebuf, linelen);
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for error message ('%m') pattern in regmatch.
!  * Return the matched value in "fields->errmsg".
!  */
!     static int
! qf_parse_fmt_m(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     char_u    *p;
!     int               len;
! 
!     if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL)
!       return QF_FAIL;
!     len = (int)(rmp->endp[midx] - rmp->startp[midx]);
!     if (len >= fields->errmsglen)
!     {
!       /* len + null terminator */
!       if ((p = vim_realloc(fields->errmsg, len + 1)) == NULL)
!           return QF_NOMEM;
!       fields->errmsg = p;
!       fields->errmsglen = len + 1;
!     }
!     vim_strncpy(fields->errmsg, rmp->startp[midx], len);
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for rest of a single-line file message ('%r') pattern.
!  * Return the matched value in "tail".
!  */
!     static int
! qf_parse_fmt_r(regmatch_T *rmp, int midx, char_u **tail)
! {
!     if (rmp->startp[midx] == NULL)
!       return QF_FAIL;
!     *tail = rmp->startp[midx];
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for the pointer line ('%p') pattern in regmatch.
!  * Return the matched value in "fields->col".
!  */
!     static int
! qf_parse_fmt_p(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     char_u    *match_ptr;
! 
!     if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL)
!       return QF_FAIL;
!     fields->col = 0;
!     for (match_ptr = rmp->startp[midx]; match_ptr != rmp->endp[midx];
!                                                               ++match_ptr)
!     {
!       ++fields->col;
!       if (*match_ptr == TAB)
!       {
!           fields->col += 7;
!           fields->col -= fields->col % 8;
!       }
!     }
!     ++fields->col;
!     fields->use_viscol = TRUE;
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for the virtual column number ('%v') pattern in regmatch.
!  * Return the matched value in "fields->col".
!  */
!     static int
! qf_parse_fmt_v(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     if (rmp->startp[midx] == NULL)
!       return QF_FAIL;
!     fields->col = (int)atol((char *)rmp->startp[midx]);
!     fields->use_viscol = TRUE;
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for the search text ('%s') pattern in regmatch.
!  * Return the matched value in "fields->pattern".
!  */
!     static int
! qf_parse_fmt_s(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     int               len;
! 
!     if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL)
!       return QF_FAIL;
!     len = (int)(rmp->endp[midx] - rmp->startp[midx]);
!     if (len > CMDBUFFSIZE - 5)
!       len = CMDBUFFSIZE - 5;
!     STRCPY(fields->pattern, "^\\V");
!     STRNCAT(fields->pattern, rmp->startp[midx], len);
!     fields->pattern[len + 3] = '\\';
!     fields->pattern[len + 4] = '$';
!     fields->pattern[len + 5] = NUL;
!     return QF_OK;
! }
! 
! /*
!  * Parse the match for the module ('%o') pattern in regmatch.
!  * Return the matched value in "fields->module".
!  */
!     static int
! qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields)
! {
!     int               len;
! 
!     if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL)
!       return QF_FAIL;
!     len = (int)(rmp->endp[midx] - rmp->startp[midx]);
!     if (len > CMDBUFFSIZE)
!       len = CMDBUFFSIZE;
!     STRNCAT(fields->module, rmp->startp[midx], len);
!     return QF_OK;
! }
! 
! /*
!  * 'errorformat' format pattern parser functions.
!  * The '%f' and '%r' formats are parsed differently from other formats.
!  * See qf_parse_match() for details.
!  */
! static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) =
! {
!     NULL,
!     qf_parse_fmt_n,
!     qf_parse_fmt_l,
!     qf_parse_fmt_c,
!     qf_parse_fmt_t,
!     qf_parse_fmt_m,
!     NULL,
!     qf_parse_fmt_p,
!     qf_parse_fmt_v,
!     qf_parse_fmt_s,
!     qf_parse_fmt_o
! };
! 
! /*
!  * Parse the error format pattern matches in "regmatch" and set the values in
!  * "fields".  fmt_ptr contains the 'efm' format specifiers/prefixes that have 
a
!  * match.  Returns QF_OK if all the matches are successfully parsed. On
!  * failure, returns QF_FAIL or QF_NOMEM.
   */
      static int
  qf_parse_match(
***************
*** 877,886 ****
        int             qf_multiscan,
        char_u          **tail)
  {
-     char_u    *p;
      int               idx = fmt_ptr->prefix;
      int               i;
!     int               len;
  
      if ((idx == 'C' || idx == 'Z') && !qf_multiline)
        return QF_FAIL;
--- 1167,1176 ----
        int             qf_multiscan,
        char_u          **tail)
  {
      int               idx = fmt_ptr->prefix;
      int               i;
!     int               midx;
!     int               status;
  
      if ((idx == 'C' || idx == 'Z') && !qf_multiline)
        return QF_FAIL;
***************
*** 893,1020 ****
       * We check for an actual submatch, because "\[" and "\]" in
       * the 'errorformat' may cause the wrong submatch to be used.
       */
!     if ((i = (int)fmt_ptr->addr[0]) > 0)              /* %f */
      {
!       int c;
  
!       if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL)
!           return QF_FAIL;
! 
!       /* Expand ~/file and $HOME/file to full path. */
!       c = *regmatch->endp[i];
!       *regmatch->endp[i] = NUL;
!       expand_env(regmatch->startp[i], fields->namebuf, CMDBUFFSIZE);
!       *regmatch->endp[i] = c;
! 
!       if (vim_strchr((char_u *)"OPQ", idx) != NULL
!               && mch_getperm(fields->namebuf) == -1)
!           return QF_FAIL;
!     }
!     if ((i = (int)fmt_ptr->addr[1]) > 0)              /* %n */
!     {
!       if (regmatch->startp[i] == NULL)
!           return QF_FAIL;
!       fields->enr = (int)atol((char *)regmatch->startp[i]);
!     }
!     if ((i = (int)fmt_ptr->addr[2]) > 0)              /* %l */
!     {
!       if (regmatch->startp[i] == NULL)
!           return QF_FAIL;
!       fields->lnum = atol((char *)regmatch->startp[i]);
!     }
!     if ((i = (int)fmt_ptr->addr[3]) > 0)              /* %c */
!     {
!       if (regmatch->startp[i] == NULL)
!           return QF_FAIL;
!       fields->col = (int)atol((char *)regmatch->startp[i]);
!     }
!     if ((i = (int)fmt_ptr->addr[4]) > 0)              /* %t */
!     {
!       if (regmatch->startp[i] == NULL)
!           return QF_FAIL;
!       fields->type = *regmatch->startp[i];
!     }
!     if (fmt_ptr->flags == '+' && !qf_multiscan)       /* %+ */
!     {
!       if (linelen >= fields->errmsglen)
!       {
!           /* linelen + null terminator */
!           if ((p = vim_realloc(fields->errmsg, linelen + 1)) == NULL)
!               return QF_NOMEM;
!           fields->errmsg = p;
!           fields->errmsglen = linelen + 1;
!       }
!       vim_strncpy(fields->errmsg, linebuf, linelen);
!     }
!     else if ((i = (int)fmt_ptr->addr[5]) > 0) /* %m */
!     {
!       if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL)
!           return QF_FAIL;
!       len = (int)(regmatch->endp[i] - regmatch->startp[i]);
!       if (len >= fields->errmsglen)
!       {
!           /* len + null terminator */
!           if ((p = vim_realloc(fields->errmsg, len + 1)) == NULL)
!               return QF_NOMEM;
!           fields->errmsg = p;
!           fields->errmsglen = len + 1;
!       }
!       vim_strncpy(fields->errmsg, regmatch->startp[i], len);
!     }
!     if ((i = (int)fmt_ptr->addr[6]) > 0)              /* %r */
!     {
!       if (regmatch->startp[i] == NULL)
!           return QF_FAIL;
!       *tail = regmatch->startp[i];
!     }
!     if ((i = (int)fmt_ptr->addr[7]) > 0)              /* %p */
!     {
!       char_u  *match_ptr;
! 
!       if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL)
!           return QF_FAIL;
!       fields->col = 0;
!       for (match_ptr = regmatch->startp[i];
!               match_ptr != regmatch->endp[i]; ++match_ptr)
!       {
!           ++fields->col;
!           if (*match_ptr == TAB)
!           {
!               fields->col += 7;
!               fields->col -= fields->col % 8;
!           }
!       }
!       ++fields->col;
!       fields->use_viscol = TRUE;
!     }
!     if ((i = (int)fmt_ptr->addr[8]) > 0)              /* %v */
!     {
!       if (regmatch->startp[i] == NULL)
!           return QF_FAIL;
!       fields->col = (int)atol((char *)regmatch->startp[i]);
!       fields->use_viscol = TRUE;
!     }
!     if ((i = (int)fmt_ptr->addr[9]) > 0)              /* %s */
!     {
!       if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL)
!           return QF_FAIL;
!       len = (int)(regmatch->endp[i] - regmatch->startp[i]);
!       if (len > CMDBUFFSIZE - 5)
!           len = CMDBUFFSIZE - 5;
!       STRCPY(fields->pattern, "^\\V");
!       STRNCAT(fields->pattern, regmatch->startp[i], len);
!       fields->pattern[len + 3] = '\\';
!       fields->pattern[len + 4] = '$';
!       fields->pattern[len + 5] = NUL;
!     }
!     if ((i = (int)fmt_ptr->addr[10]) > 0)             /* %o */
!     {
!       if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL)
!           return QF_FAIL;
!       len = (int)(regmatch->endp[i] - regmatch->startp[i]);
!       if (len > CMDBUFFSIZE)
!           len = CMDBUFFSIZE;
!       STRNCAT(fields->module, regmatch->startp[i], len);
      }
  
      return QF_OK;
--- 1183,1208 ----
       * We check for an actual submatch, because "\[" and "\]" in
       * the 'errorformat' may cause the wrong submatch to be used.
       */
!     for (i = 0; i < FMT_PATTERNS; i++)
      {
!       status = QF_OK;
!       midx = (int)fmt_ptr->addr[i];
!       if (i == 0 && midx > 0)                         /* %f */
!           status = qf_parse_fmt_f(regmatch, midx, fields, idx);
!       else if (i == 5)
!       {
!           if (fmt_ptr->flags == '+' && !qf_multiscan) /* %+ */
!               status = qf_parse_fmt_plus(linebuf, linelen, fields);
!           else if (midx > 0)                          /* %m */
!               status = qf_parse_fmt_m(regmatch, midx, fields);
!       }
!       else if (i == 6 && midx > 0)                    /* %r */
!           status = qf_parse_fmt_r(regmatch, midx, tail);
!       else if (midx > 0)                              /* others */
!           status = (qf_parse_fmt[i])(regmatch, midx, fields);
  
!       if (status != QF_OK)
!           return status;
      }
  
      return QF_OK;
***************
*** 1308,1313 ****
--- 1496,1513 ----
  }
  
  /*
+  * Returns TRUE if the specified quickfix/location list is empty.
+  */
+     static int
+ qf_list_empty(qf_info_T *qi, int qf_idx)
+ {
+     if (qi == NULL || qf_idx < 0 || qf_idx >= LISTCOUNT)
+       return TRUE;
+     return qi->qf_lists[qf_idx].qf_count <= 0;
+ }
+ 
+ 
+ /*
   * Allocate the fields used for parsing lines and populating a quickfix list.
   */
      static int
***************
*** 1450,1456 ****
      {
        /* Adding to existing list, use last entry. */
        adding = TRUE;
!       if (qi->qf_lists[qf_idx].qf_count > 0)
            old_last = qi->qf_lists[qf_idx].qf_last;
      }
  
--- 1650,1656 ----
      {
        /* Adding to existing list, use last entry. */
        adding = TRUE;
!       if (!qf_list_empty(qi, qf_idx))
            old_last = qi->qf_lists[qf_idx].qf_last;
      }
  
***************
*** 1777,1784 ****
      qfp->qf_valid = valid;
  
      lastp = &qi->qf_lists[qf_idx].qf_last;
!     if (qi->qf_lists[qf_idx].qf_count == 0)
!                               /* first element in the list */
      {
        qi->qf_lists[qf_idx].qf_start = qfp;
        qi->qf_lists[qf_idx].qf_ptr = qfp;
--- 1977,1983 ----
      qfp->qf_valid = valid;
  
      lastp = &qi->qf_lists[qf_idx].qf_last;
!     if (qf_list_empty(qi, qf_idx))    /* first element in the list */
      {
        qi->qf_lists[qf_idx].qf_start = qfp;
        qi->qf_lists[qf_idx].qf_ptr = qfp;
***************
*** 1875,1881 ****
      to->w_llist->qf_listcount = qi->qf_listcount;
  
      /* Copy the location lists one at a time */
!     for (idx = 0; idx < qi->qf_listcount; idx++)
      {
        qf_list_T   *from_qfl;
        qf_list_T   *to_qfl;
--- 2074,2080 ----
      to->w_llist->qf_listcount = qi->qf_listcount;
  
      /* Copy the location lists one at a time */
!     for (idx = 0; idx < qi->qf_listcount; ++idx)
      {
        qf_list_T   *from_qfl;
        qf_list_T   *to_qfl;
***************
*** 2907,2913 ****
        qi = &ql_info;
  
      if (qi->qf_curlist >= qi->qf_listcount
!       || qi->qf_lists[qi->qf_curlist].qf_count == 0)
      {
        EMSG(_(e_quickfix));
        return;
--- 3106,3112 ----
        qi = &ql_info;
  
      if (qi->qf_curlist >= qi->qf_listcount
!       || qf_list_empty(qi, qi->qf_curlist))
      {
        EMSG(_(e_quickfix));
        return;
***************
*** 3033,3056 ****
  }
  
  /*
   * ":clist": list all errors
   * ":llist": list all locations
   */
      void
  qf_list(exarg_T *eap)
  {
-     buf_T     *buf;
-     char_u    *fname;
      qfline_T  *qfp;
      int               i;
      int               idx1 = 1;
      int               idx2 = -1;
      char_u    *arg = eap->arg;
      int               plus = FALSE;
-     int               qfFileAttr;
-     int               qfSepAttr;
-     int               qfLineAttr;
-     int               filter_entry;
      int               all = eap->forceit;     /* if not :cl!, only show
                                                   recognised errors */
      qf_info_T *qi = &ql_info;
--- 3232,3336 ----
  }
  
  /*
+  * Highlight attributes used for displaying entries from the quickfix list.
+  */
+ static int    qfFileAttr;
+ static int    qfSepAttr;
+ static int    qfLineAttr;
+ 
+ /*
+  * Display information about a single entry from the quickfix/location list.
+  * Used by ":clist/:llist" commands.
+  */
+     static void
+ qf_list_entry(qf_info_T *qi, qfline_T *qfp, int qf_idx)
+ {
+     char_u    *fname;
+     buf_T     *buf;
+     int               filter_entry;
+ 
+     fname = NULL;
+     if (qfp->qf_module != NULL && *qfp->qf_module != NUL)
+       vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", qf_idx,
+                                               (char *)qfp->qf_module);
+     else {
+       if (qfp->qf_fnum != 0
+               && (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
+       {
+           fname = buf->b_fname;
+           if (qfp->qf_type == 1)      /* :helpgrep */
+               fname = gettail(fname);
+       }
+       if (fname == NULL)
+           sprintf((char *)IObuff, "%2d", qf_idx);
+       else
+           vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
+                   qf_idx, (char *)fname);
+     }
+ 
+     // Support for filtering entries using :filter /pat/ clist
+     // Match against the module name, file name, search pattern and
+     // text of the entry.
+     filter_entry = TRUE;
+     if (qfp->qf_module != NULL && *qfp->qf_module != NUL)
+       filter_entry &= message_filtered(qfp->qf_module);
+     if (filter_entry && fname != NULL)
+       filter_entry &= message_filtered(fname);
+     if (filter_entry && qfp->qf_pattern != NULL)
+       filter_entry &= message_filtered(qfp->qf_pattern);
+     if (filter_entry)
+       filter_entry &= message_filtered(qfp->qf_text);
+     if (filter_entry)
+       return;
+ 
+     msg_putchar('\n');
+     msg_outtrans_attr(IObuff, qf_idx == qi->qf_lists[qi->qf_curlist].qf_index
+           ? HL_ATTR(HLF_QFL) : qfFileAttr);
+ 
+     if (qfp->qf_lnum != 0)
+       msg_puts_attr((char_u *)":", qfSepAttr);
+     if (qfp->qf_lnum == 0)
+       IObuff[0] = NUL;
+     else if (qfp->qf_col == 0)
+       sprintf((char *)IObuff, "%ld", qfp->qf_lnum);
+     else
+       sprintf((char *)IObuff, "%ld col %d",
+               qfp->qf_lnum, qfp->qf_col);
+     sprintf((char *)IObuff + STRLEN(IObuff), "%s",
+           (char *)qf_types(qfp->qf_type, qfp->qf_nr));
+     msg_puts_attr(IObuff, qfLineAttr);
+     msg_puts_attr((char_u *)":", qfSepAttr);
+     if (qfp->qf_pattern != NULL)
+     {
+       qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
+       msg_puts(IObuff);
+       msg_puts_attr((char_u *)":", qfSepAttr);
+     }
+     msg_puts((char_u *)" ");
+ 
+     /* Remove newlines and leading whitespace from the text.  For an
+      * unrecognized line keep the indent, the compiler may mark a word
+      * with ^^^^. */
+     qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
+                               ? skipwhite(qfp->qf_text) : qfp->qf_text,
+                               IObuff, IOSIZE);
+     msg_prt_line(IObuff, FALSE);
+     out_flush();              /* show one line at a time */
+ }
+ 
+ /*
   * ":clist": list all errors
   * ":llist": list all locations
   */
      void
  qf_list(exarg_T *eap)
  {
      qfline_T  *qfp;
      int               i;
      int               idx1 = 1;
      int               idx2 = -1;
      char_u    *arg = eap->arg;
      int               plus = FALSE;
      int               all = eap->forceit;     /* if not :cl!, only show
                                                   recognised errors */
      qf_info_T *qi = &ql_info;
***************
*** 3066,3072 ****
      }
  
      if (qi->qf_curlist >= qi->qf_listcount
!       || qi->qf_lists[qi->qf_curlist].qf_count == 0)
      {
        EMSG(_(e_quickfix));
        return;
--- 3346,3352 ----
      }
  
      if (qi->qf_curlist >= qi->qf_listcount
!       || qf_list_empty(qi, qi->qf_curlist))
      {
        EMSG(_(e_quickfix));
        return;
***************
*** 3123,3197 ****
            if (got_int)
                break;
  
!           fname = NULL;
!           if (qfp->qf_module != NULL && *qfp->qf_module != NUL)
!               vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i, (char 
*)qfp->qf_module);
!           else {
!               if (qfp->qf_fnum != 0
!                               && (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
!               {
!                   fname = buf->b_fname;
!                   if (qfp->qf_type == 1)      /* :helpgrep */
!                       fname = gettail(fname);
!               }
!               if (fname == NULL)
!                   sprintf((char *)IObuff, "%2d", i);
!               else
!                   vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
!                                                            i, (char *)fname);
!           }
! 
!           // Support for filtering entries using :filter /pat/ clist
!           // Match against the module name, file name, search pattern and
!           // text of the entry.
!           filter_entry = TRUE;
!           if (qfp->qf_module != NULL && *qfp->qf_module != NUL)
!               filter_entry &= message_filtered(qfp->qf_module);
!           if (filter_entry && fname != NULL)
!               filter_entry &= message_filtered(fname);
!           if (filter_entry && qfp->qf_pattern != NULL)
!               filter_entry &= message_filtered(qfp->qf_pattern);
!           if (filter_entry)
!               filter_entry &= message_filtered(qfp->qf_text);
!           if (filter_entry)
!               goto next_entry;
! 
!           msg_putchar('\n');
!           msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index
!                                          ? HL_ATTR(HLF_QFL) : qfFileAttr);
! 
!           if (qfp->qf_lnum != 0)
!               msg_puts_attr((char_u *)":", qfSepAttr);
!           if (qfp->qf_lnum == 0)
!               IObuff[0] = NUL;
!           else if (qfp->qf_col == 0)
!               sprintf((char *)IObuff, "%ld", qfp->qf_lnum);
!           else
!               sprintf((char *)IObuff, "%ld col %d",
!                                                  qfp->qf_lnum, qfp->qf_col);
!           sprintf((char *)IObuff + STRLEN(IObuff), "%s",
!                                 (char *)qf_types(qfp->qf_type, qfp->qf_nr));
!           msg_puts_attr(IObuff, qfLineAttr);
!           msg_puts_attr((char_u *)":", qfSepAttr);
!           if (qfp->qf_pattern != NULL)
!           {
!               qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
!               msg_puts(IObuff);
!               msg_puts_attr((char_u *)":", qfSepAttr);
!           }
!           msg_puts((char_u *)" ");
! 
!           /* Remove newlines and leading whitespace from the text.  For an
!            * unrecognized line keep the indent, the compiler may mark a word
!            * with ^^^^. */
!           qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
!                                    ? skipwhite(qfp->qf_text) : qfp->qf_text,
!                                                             IObuff, IOSIZE);
!           msg_prt_line(IObuff, FALSE);
!           out_flush();                /* show one line at a time */
        }
  
- next_entry:
        qfp = qfp->qf_next;
        if (qfp == NULL)
            break;
--- 3403,3411 ----
            if (got_int)
                break;
  
!           qf_list_entry(qi, qfp, i);
        }
  
        qfp = qfp->qf_next;
        if (qfp == NULL)
            break;
***************
*** 3320,3326 ****
      if (eap->cmdidx == CMD_lhistory)
        qi = GET_LOC_LIST(curwin);
      if (qi == NULL || (qi->qf_listcount == 0
!                               && qi->qf_lists[qi->qf_curlist].qf_count == 0))
        MSG(_("No entries"));
      else
        for (i = 0; i < qi->qf_listcount; ++i)
--- 3534,3540 ----
      if (eap->cmdidx == CMD_lhistory)
        qi = GET_LOC_LIST(curwin);
      if (qi == NULL || (qi->qf_listcount == 0
!                               && qf_list_empty(qi, qi->qf_curlist)))
        MSG(_("No entries"));
      else
        for (i = 0; i < qi->qf_listcount; ++i)
***************
*** 3421,3427 ****
      }
  
      for (idx = 0; idx < qi->qf_listcount; ++idx)
!       if (qi->qf_lists[idx].qf_count)
            for (i = 0, qfp = qi->qf_lists[idx].qf_start;
                        i < qi->qf_lists[idx].qf_count && qfp != NULL;
                        ++i, qfp = qfp->qf_next)
--- 3635,3641 ----
      }
  
      for (idx = 0; idx < qi->qf_listcount; ++idx)
!       if (!qf_list_empty(qi, idx))
            for (i = 0, qfp = qi->qf_lists[idx].qf_start;
                        i < qi->qf_lists[idx].qf_count && qfp != NULL;
                        ++i, qfp = qfp->qf_next)
***************
*** 3552,3558 ****
       * it if we have errors; otherwise, leave it closed.
       */
      if (qi->qf_lists[qi->qf_curlist].qf_nonevalid
!           || qi->qf_lists[qi->qf_curlist].qf_count == 0
            || qi->qf_curlist >= qi->qf_listcount)
      {
        if (win != NULL)
--- 3766,3772 ----
       * it if we have errors; otherwise, leave it closed.
       */
      if (qi->qf_lists[qi->qf_curlist].qf_nonevalid
!           || qf_list_empty(qi, qi->qf_curlist)
            || qi->qf_curlist >= qi->qf_listcount)
      {
        if (win != NULL)
***************
*** 5154,5160 ****
        qi->qf_curlist = qf_id2nr(qi, save_qfid);
  
      /* Jump to first match. */
!     if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
      {
        if ((flags & VGR_NOJUMP) == 0)
            vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy,
--- 5368,5374 ----
        qi->qf_curlist = qf_id2nr(qi, save_qfid);
  
      /* Jump to first match. */
!     if (!qf_list_empty(qi, qi->qf_curlist))
      {
        if ((flags & VGR_NOJUMP) == 0)
            vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy,
***************
*** 5387,5394 ****
      if (qf_idx == INVALID_QFIDX)
        qf_idx = qi->qf_curlist;
  
!     if (qf_idx >= qi->qf_listcount
!           || qi->qf_lists[qf_idx].qf_count == 0)
        return FAIL;
  
      qfp = qi->qf_lists[qf_idx].qf_start;
--- 5601,5607 ----
      if (qf_idx == INVALID_QFIDX)
        qf_idx = qi->qf_curlist;
  
!     if (qf_idx >= qi->qf_listcount || qf_list_empty(qi, qf_idx))
        return FAIL;
  
      qfp = qi->qf_lists[qf_idx].qf_start;
***************
*** 5709,5715 ****
  qf_getprop_idx(qf_info_T *qi, int qf_idx, dict_T *retdict)
  {
      int idx = qi->qf_lists[qf_idx].qf_index;
!     if (qi->qf_lists[qf_idx].qf_count == 0)
        /* For empty lists, qf_index is set to 1 */
        idx = 0;
      return dict_add_number(retdict, "idx", idx);
--- 5922,5928 ----
  qf_getprop_idx(qf_info_T *qi, int qf_idx, dict_T *retdict)
  {
      int idx = qi->qf_lists[qf_idx].qf_index;
!     if (qf_list_empty(qi, qf_idx))
        /* For empty lists, qf_index is set to 1 */
        idx = 0;
      return dict_add_number(retdict, "idx", idx);
***************
*** 5798,5804 ****
        qf_new_list(qi, title);
        qf_idx = qi->qf_curlist;
      }
!     else if (action == 'a' && qi->qf_lists[qf_idx].qf_count > 0)
        /* Adding to existing list, use last entry. */
        old_last = qi->qf_lists[qf_idx].qf_last;
      else if (action == 'r')
--- 6011,6017 ----
        qf_new_list(qi, title);
        qf_idx = qi->qf_curlist;
      }
!     else if (action == 'a' && !qf_list_empty(qi, qf_idx))
        /* Adding to existing list, use last entry. */
        old_last = qi->qf_lists[qf_idx].qf_last;
      else if (action == 'r')
***************
*** 5887,5893 ****
      {
        qi->qf_lists[qf_idx].qf_ptr =
            qi->qf_lists[qf_idx].qf_start;
!       if (qi->qf_lists[qf_idx].qf_count > 0)
            qi->qf_lists[qf_idx].qf_index = 1;
      }
  
--- 6100,6106 ----
      {
        qi->qf_lists[qf_idx].qf_ptr =
            qi->qf_lists[qf_idx].qf_start;
!       if (!qf_list_empty(qi, qf_idx))
            qi->qf_lists[qf_idx].qf_index = 1;
      }
  
***************
*** 6746,6752 ****
      }
  
      /* Jump to first match. */
!     if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
        qf_jump(qi, 0, 0, FALSE);
      else
        EMSG2(_(e_nomatch2), eap->arg);
--- 6959,6965 ----
      }
  
      /* Jump to first match. */
!     if (!qf_list_empty(qi, qi->qf_curlist))
        qf_jump(qi, 0, 0, FALSE);
      else
        EMSG2(_(e_nomatch2), eap->arg);
*** ../vim-8.1.0251/src/version.c       2018-08-07 21:39:09.251060096 +0200
--- src/version.c       2018-08-07 21:43:08.981711510 +0200
***************
*** 796,797 ****
--- 796,799 ----
  {   /* Add new patch number below this line */
+ /**/
+     252,
  /**/

-- 
Q: How do you tell the difference between a female cat and a male cat?
A: You ask it a question and if HE answers, it's a male but, if SHE
   answers, it's a female.

 /// 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].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui