Patch 8.0.1805
Problem:    qf_parse_line() is too long.
Solution:   Split it in parts.  Properly handle vim_realloc() failing.
            (Yegappan Lakshmanan, closes #2881)
Files:      src/quickfix.c


*** ../vim-8.0.1804/src/quickfix.c      2018-05-01 15:01:56.938414623 +0200
--- src/quickfix.c      2018-05-08 22:13:18.144601079 +0200
***************
*** 213,231 ****
      char_u    convchar;
      char      *pattern;
  } fmt_pat[FMT_PATTERNS] =
!               {
!                   {'f', ".\\+"},          /* only used when at end */
!                   {'n', "\\d\\+"},
!                   {'l', "\\d\\+"},
!                   {'c', "\\d\\+"},
!                   {'t', "."},
!                   {'m', ".\\+"},
!                   {'r', ".*"},
!                   {'p', "[-   .]*"},
!                   {'v', "\\d\\+"},
!                   {'s', ".\\+"},
!                   {'o', ".\\+"}
!               };
  
  /*
   * Converts a 'errorformat' string to regular expression pattern
--- 213,231 ----
      char_u    convchar;
      char      *pattern;
  } fmt_pat[FMT_PATTERNS] =
!     {
!       {'f', ".\\+"},      /* only used when at end */
!       {'n', "\\d\\+"},
!       {'l', "\\d\\+"},
!       {'c', "\\d\\+"},
!       {'t', "."},
!       {'m', ".\\+"},
!       {'r', ".*"},
!       {'p', "[-       .]*"},
!       {'v', "\\d\\+"},
!       {'s', ".\\+"},
!       {'o', ".\\+"}
!     };
  
  /*
   * Converts a 'errorformat' string to regular expression pattern
***************
*** 504,510 ****
      QF_OK = 1,
      QF_END_OF_INPUT = 2,
      QF_NOMEM = 3,
!     QF_IGNORE_LINE = 4
  };
  
  typedef struct {
--- 504,511 ----
      QF_OK = 1,
      QF_END_OF_INPUT = 2,
      QF_NOMEM = 3,
!     QF_IGNORE_LINE = 4,
!     QF_MULTISCAN = 5,
  };
  
  typedef struct {
***************
*** 525,530 ****
--- 526,533 ----
      static char_u *
  qf_grow_linebuf(qfstate_T *state, int newsz)
  {
+     char_u    *p;
+ 
      /*
       * If the line exceeds LINE_MAXLEN exclude the last
       * byte since it's not a NL character.
***************
*** 539,547 ****
      }
      else if (state->linelen > state->growbufsiz)
      {
!       state->growbuf = vim_realloc(state->growbuf, state->linelen + 1);
!       if (state->growbuf == NULL)
            return NULL;
        state->growbufsiz = state->linelen;
      }
      return state->growbuf;
--- 542,550 ----
      }
      else if (state->linelen > state->growbufsiz)
      {
!       if ((p = vim_realloc(state->growbuf, state->linelen + 1)) == NULL)
            return NULL;
+       state->growbuf = p;
        state->growbufsiz = state->linelen;
      }
      return state->growbuf;
***************
*** 696,701 ****
--- 699,706 ----
  
        for (;;)
        {
+           char_u      *p;
+ 
            if (fgets((char *)state->growbuf + growbuflen,
                        state->growbufsiz - growbuflen, state->fd) == NULL)
                break;
***************
*** 711,719 ****
  
            state->growbufsiz = 2 * state->growbufsiz < LINE_MAXLEN
                ? 2 * state->growbufsiz : LINE_MAXLEN;
!           state->growbuf = vim_realloc(state->growbuf, state->growbufsiz);
!           if (state->growbuf == NULL)
                return QF_NOMEM;
        }
  
        while (discard)
--- 716,724 ----
  
            state->growbufsiz = 2 * state->growbufsiz < LINE_MAXLEN
                ? 2 * state->growbufsiz : LINE_MAXLEN;
!           if ((p = vim_realloc(state->growbuf, state->growbufsiz)) == NULL)
                return QF_NOMEM;
+           state->growbuf = p;
        }
  
        while (discard)
***************
*** 825,830 ****
--- 830,1181 ----
  } 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(
+       char_u          *linebuf,
+       int             linelen,
+       efm_T           *fmt_ptr,
+       regmatch_T      *regmatch,
+       qffields_T      *fields,
+       int             qf_multiline,
+       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;
+     if (vim_strchr((char_u *)"EWI", idx) != NULL)
+       fields->type = idx;
+     else
+       fields->type = 0;
+     /*
+      * Extract error message data from matched line.
+      * 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;
+ }
+ 
+ /*
+  * Parse an error line in 'linebuf' using a single error format string in
+  * 'fmt_ptr->prog' and return the matching values in 'fields'.
+  * Returns QF_OK if the efm format matches completely and the fields are
+  * successfully copied. Otherwise returns QF_FAIL or QF_NOMEM.
+  */
+     static int
+ qf_parse_get_fields(
+       char_u          *linebuf,
+       int             linelen,
+       efm_T           *fmt_ptr,
+       qffields_T      *fields,
+       int             qf_multiline,
+       int             qf_multiscan,
+       char_u          **tail)
+ {
+     regmatch_T        regmatch;
+     int               status = QF_FAIL;
+     int               r;
+ 
+     if (qf_multiscan &&
+               vim_strchr((char_u *)"OPQ", fmt_ptr->prefix) == NULL)
+       return QF_FAIL;
+ 
+     fields->namebuf[0] = NUL;
+     fields->module[0] = NUL;
+     fields->pattern[0] = NUL;
+     if (!qf_multiscan)
+       fields->errmsg[0] = NUL;
+     fields->lnum = 0;
+     fields->col = 0;
+     fields->use_viscol = FALSE;
+     fields->enr = -1;
+     fields->type = 0;
+     *tail = NULL;
+ 
+     regmatch.regprog = fmt_ptr->prog;
+     r = vim_regexec(&regmatch, linebuf, (colnr_T)0);
+     fmt_ptr->prog = regmatch.regprog;
+     if (r)
+       status = qf_parse_match(linebuf, linelen, fmt_ptr, &regmatch,
+               fields, qf_multiline, qf_multiscan, tail);
+ 
+     return status;
+ }
+ 
+ /*
+  * Parse directory error format prefixes (%D and %X).
+  * Push and pop directories from the directory stack when scanning directory
+  * names.
+  */
+     static int
+ qf_parse_dir_pfx(int idx, qffields_T *fields, qf_list_T *qfl)
+ {
+     if (idx == 'D')                           /* enter directory */
+     {
+       if (*fields->namebuf == NUL)
+       {
+           EMSG(_("E379: Missing or empty directory name"));
+           return QF_FAIL;
+       }
+       qfl->qf_directory =
+           qf_push_dir(fields->namebuf, &qfl->qf_dir_stack, FALSE);
+       if (qfl->qf_directory == NULL)
+           return QF_FAIL;
+     }
+     else if (idx == 'X')                      /* leave directory */
+       qfl->qf_directory = qf_pop_dir(&qfl->qf_dir_stack);
+ 
+     return QF_OK;
+ }
+ 
+ /*
+  * Parse global file name error format prefixes (%O, %P and %Q).
+  */
+     static int
+ qf_parse_file_pfx(
+       int idx,
+       qffields_T *fields,
+       qf_list_T *qfl,
+       char_u *tail)
+ {
+     fields->valid = FALSE;
+     if (*fields->namebuf == NUL || mch_getperm(fields->namebuf) >= 0)
+     {
+       if (*fields->namebuf && idx == 'P')
+           qfl->qf_currfile =
+               qf_push_dir(fields->namebuf, &qfl->qf_file_stack, TRUE);
+       else if (idx == 'Q')
+           qfl->qf_currfile = qf_pop_dir(&qfl->qf_file_stack);
+       *fields->namebuf = NUL;
+       if (tail && *tail)
+       {
+           STRMOVE(IObuff, skipwhite(tail));
+           qfl->qf_multiscan = TRUE;
+           return QF_MULTISCAN;
+       }
+     }
+ 
+     return QF_OK;
+ }
+ 
+ /*
+  * Parse a non-error line (a line which doesn't match any of the error
+  * format in 'efm').
+  */
+     static int
+ qf_parse_line_nomatch(char_u *linebuf, int linelen, qffields_T *fields)
+ {
+     char_u    *p;
+ 
+     fields->namebuf[0] = NUL; /* no match found, remove file name */
+     fields->lnum = 0;                 /* don't jump to this line */
+     fields->valid = FALSE;
+     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;
+     }
+     /* copy whole line to error message */
+     vim_strncpy(fields->errmsg, linebuf, linelen);
+ 
+     return QF_OK;
+ }
+ 
+ /*
+  * Parse multi-line error format prefixes (%C and %Z)
+  */
+     static int
+ qf_parse_multiline_pfx(
+       qf_info_T *qi,
+       int qf_idx,
+       int idx,
+       qf_list_T *qfl,
+       qffields_T *fields)
+ {
+     char_u            *ptr;
+     int                       len;
+ 
+     if (!qfl->qf_multiignore)
+     {
+       qfline_T *qfprev = qfl->qf_last;
+ 
+       if (qfprev == NULL)
+           return QF_FAIL;
+       if (*fields->errmsg && !qfl->qf_multiignore)
+       {
+           len = (int)STRLEN(qfprev->qf_text);
+           if ((ptr = alloc((unsigned)(len + STRLEN(fields->errmsg) + 2)))
+                   == NULL)
+               return QF_FAIL;
+           STRCPY(ptr, qfprev->qf_text);
+           vim_free(qfprev->qf_text);
+           qfprev->qf_text = ptr;
+           *(ptr += len) = '\n';
+           STRCPY(++ptr, fields->errmsg);
+       }
+       if (qfprev->qf_nr == -1)
+           qfprev->qf_nr = fields->enr;
+       if (vim_isprintc(fields->type) && !qfprev->qf_type)
+           /* only printable chars allowed */
+           qfprev->qf_type = fields->type;
+ 
+       if (!qfprev->qf_lnum)
+           qfprev->qf_lnum = fields->lnum;
+       if (!qfprev->qf_col)
+           qfprev->qf_col = fields->col;
+       qfprev->qf_viscol = fields->use_viscol;
+       if (!qfprev->qf_fnum)
+           qfprev->qf_fnum = qf_get_fnum(qi, qf_idx,
+                   qfl->qf_directory,
+                   *fields->namebuf || qfl->qf_directory != NULL
+                   ? fields->namebuf
+                   : qfl->qf_currfile != NULL && fields->valid
+                   ? qfl->qf_currfile : 0);
+     }
+     if (idx == 'Z')
+       qfl->qf_multiline = qfl->qf_multiignore = FALSE;
+     line_breakcheck();
+ 
+     return QF_IGNORE_LINE;
+ }
+ 
+ /*
   * Parse a line and get the quickfix fields.
   * Return the QF_ status.
   */
***************
*** 838,853 ****
        qffields_T      *fields)
  {
      efm_T             *fmt_ptr;
-     char_u            *ptr;
-     int                       len;
-     int                       i;
      int                       idx = 0;
      char_u            *tail = NULL;
-     regmatch_T                regmatch;
      qf_list_T         *qfl = &qi->qf_lists[qf_idx];
! 
!     /* Always ignore case when looking for a matching error. */
!     regmatch.rm_ic = TRUE;
  
  restofline:
      /* If there was no %> item start at the first pattern */
--- 1189,1198 ----
        qffields_T      *fields)
  {
      efm_T             *fmt_ptr;
      int                       idx = 0;
      char_u            *tail = NULL;
      qf_list_T         *qfl = &qi->qf_lists[qf_idx];
!     int                       status;
  
  restofline:
      /* If there was no %> item start at the first pattern */
***************
*** 855,860 ****
--- 1200,1206 ----
        fmt_ptr = fmt_first;
      else
      {
+       /* Otherwise start from the last used pattern */
        fmt_ptr = fmt_start;
        fmt_start = NULL;
      }
***************
*** 866,1029 ****
      fields->valid = TRUE;
      for ( ; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next)
      {
-       int r;
- 
        idx = fmt_ptr->prefix;
!       if (qfl->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL)
!           continue;
!       fields->namebuf[0] = NUL;
!       fields->module[0] = NUL;
!       fields->pattern[0] = NUL;
!       if (!qfl->qf_multiscan)
!           fields->errmsg[0] = NUL;
!       fields->lnum = 0;
!       fields->col = 0;
!       fields->use_viscol = FALSE;
!       fields->enr = -1;
!       fields->type = 0;
!       tail = NULL;
! 
!       regmatch.regprog = fmt_ptr->prog;
!       r = vim_regexec(&regmatch, linebuf, (colnr_T)0);
!       fmt_ptr->prog = regmatch.regprog;
!       if (r)
!       {
!           if ((idx == 'C' || idx == 'Z') && !qfl->qf_multiline)
!               continue;
!           if (vim_strchr((char_u *)"EWI", idx) != NULL)
!               fields->type = idx;
!           else
!               fields->type = 0;
!           /*
!            * Extract error message data from matched line.
!            * 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)
!                   continue;
! 
!               /* 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)
!                   continue;
!           }
!           if ((i = (int)fmt_ptr->addr[1]) > 0)                /* %n */
!           {
!               if (regmatch.startp[i] == NULL)
!                   continue;
!               fields->enr = (int)atol((char *)regmatch.startp[i]);
!           }
!           if ((i = (int)fmt_ptr->addr[2]) > 0)                /* %l */
!           {
!               if (regmatch.startp[i] == NULL)
!                   continue;
!               fields->lnum = atol((char *)regmatch.startp[i]);
!           }
!           if ((i = (int)fmt_ptr->addr[3]) > 0)                /* %c */
!           {
!               if (regmatch.startp[i] == NULL)
!                   continue;
!               fields->col = (int)atol((char *)regmatch.startp[i]);
!           }
!           if ((i = (int)fmt_ptr->addr[4]) > 0)                /* %t */
!           {
!               if (regmatch.startp[i] == NULL)
!                   continue;
!               fields->type = *regmatch.startp[i];
!           }
!           if (fmt_ptr->flags == '+' && !qfl->qf_multiscan)    /* %+ */
!           {
!               if (linelen >= fields->errmsglen)
!               {
!                   /* linelen + null terminator */
!                   if ((fields->errmsg = vim_realloc(fields->errmsg,
!                                   linelen + 1)) == NULL)
!                       return QF_NOMEM;
!                   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)
!                   continue;
!               len = (int)(regmatch.endp[i] - regmatch.startp[i]);
!               if (len >= fields->errmsglen)
!               {
!                   /* len + null terminator */
!                   if ((fields->errmsg = vim_realloc(fields->errmsg, len + 1))
!                           == NULL)
!                       return QF_NOMEM;
!                   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)
!                   continue;
!               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)
!                   continue;
!               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)
!                   continue;
!               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)
!                   continue;
!               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)
!                   continue;
!               len = (int)(regmatch.endp[i] - regmatch.startp[i]);
!               if (len > CMDBUFFSIZE)
!                   len = CMDBUFFSIZE;
!               STRNCAT(fields->module, regmatch.startp[i], len);
!           }
            break;
-       }
      }
      qfl->qf_multiscan = FALSE;
  
--- 1212,1224 ----
      fields->valid = TRUE;
      for ( ; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next)
      {
        idx = fmt_ptr->prefix;
!       status = qf_parse_get_fields(linebuf, linelen, fmt_ptr, fields,
!                               qfl->qf_multiline, qfl->qf_multiscan, &tail);
!       if (status == QF_NOMEM)
!           return status;
!       if (status == QF_OK)
            break;
      }
      qfl->qf_multiscan = FALSE;
  
***************
*** 1031,1064 ****
      {
        if (fmt_ptr != NULL)
        {
!           if (idx == 'D')                             /* enter directory */
!           {
!               if (*fields->namebuf == NUL)
!               {
!                   EMSG(_("E379: Missing or empty directory name"));
!                   return QF_FAIL;
!               }
!               qfl->qf_directory =
!                   qf_push_dir(fields->namebuf, &qfl->qf_dir_stack, FALSE);
!               if (qfl->qf_directory == NULL)
!                   return QF_FAIL;
!           }
!           else if (idx == 'X')                        /* leave directory */
!               qfl->qf_directory = qf_pop_dir(&qfl->qf_dir_stack);
        }
!       fields->namebuf[0] = NUL;       /* no match found, remove file name */
!       fields->lnum = 0;                       /* don't jump to this line */
!       fields->valid = FALSE;
!       if (linelen >= fields->errmsglen)
!       {
!           /* linelen + null terminator */
!           if ((fields->errmsg = vim_realloc(fields->errmsg,
!                           linelen + 1)) == NULL)
!               return QF_NOMEM;
!           fields->errmsglen = linelen + 1;
!       }
!       /* copy whole line to error message */
!       vim_strncpy(fields->errmsg, linebuf, linelen);
        if (fmt_ptr == NULL)
            qfl->qf_multiline = qfl->qf_multiignore = FALSE;
      }
--- 1226,1241 ----
      {
        if (fmt_ptr != NULL)
        {
!           /* 'D' and 'X' directory specifiers */
!           status = qf_parse_dir_pfx(idx, fields, qfl);
!           if (status != QF_OK)
!               return status;
        }
! 
!       status = qf_parse_line_nomatch(linebuf, linelen, fields);
!       if (status != QF_OK)
!           return status;
! 
        if (fmt_ptr == NULL)
            qfl->qf_multiline = qfl->qf_multiignore = FALSE;
      }
***************
*** 1075,1141 ****
        }
        else if (vim_strchr((char_u *)"CZ", idx) != NULL)
        {                               /* continuation of multi-line msg */
!           if (!qfl->qf_multiignore)
!           {
!               qfline_T *qfprev = qfl->qf_last;
! 
!               if (qfprev == NULL)
!                   return QF_FAIL;
!               if (*fields->errmsg && !qfl->qf_multiignore)
!               {
!                   len = (int)STRLEN(qfprev->qf_text);
!                   if ((ptr = alloc((unsigned)(len + STRLEN(fields->errmsg) + 
2)))
!                           == NULL)
!                       return QF_FAIL;
!                   STRCPY(ptr, qfprev->qf_text);
!                   vim_free(qfprev->qf_text);
!                   qfprev->qf_text = ptr;
!                   *(ptr += len) = '\n';
!                   STRCPY(++ptr, fields->errmsg);
!               }
!               if (qfprev->qf_nr == -1)
!                   qfprev->qf_nr = fields->enr;
!               if (vim_isprintc(fields->type) && !qfprev->qf_type)
!                   /* only printable chars allowed */
!                   qfprev->qf_type = fields->type;
! 
!               if (!qfprev->qf_lnum)
!                   qfprev->qf_lnum = fields->lnum;
!               if (!qfprev->qf_col)
!                   qfprev->qf_col = fields->col;
!               qfprev->qf_viscol = fields->use_viscol;
!               if (!qfprev->qf_fnum)
!                   qfprev->qf_fnum = qf_get_fnum(qi, qf_idx,
!                           qfl->qf_directory,
!                           *fields->namebuf || qfl->qf_directory != NULL
!                           ? fields->namebuf
!                           : qfl->qf_currfile != NULL && fields->valid
!                           ? qfl->qf_currfile : 0);
!           }
!           if (idx == 'Z')
!               qfl->qf_multiline = qfl->qf_multiignore = FALSE;
!           line_breakcheck();
!           return QF_IGNORE_LINE;
        }
        else if (vim_strchr((char_u *)"OPQ", idx) != NULL)
!       {
!           /* global file names */
!           fields->valid = FALSE;
!           if (*fields->namebuf == NUL || mch_getperm(fields->namebuf) >= 0)
!           {
!               if (*fields->namebuf && idx == 'P')
!                   qfl->qf_currfile =
!                       qf_push_dir(fields->namebuf, &qfl->qf_file_stack, TRUE);
!               else if (idx == 'Q')
!                   qfl->qf_currfile = qf_pop_dir(&qfl->qf_file_stack);
!               *fields->namebuf = NUL;
!               if (tail && *tail)
!               {
!                   STRMOVE(IObuff, skipwhite(tail));
!                   qfl->qf_multiscan = TRUE;
!                   goto restofline;
!               }
!           }
        }
        if (fmt_ptr->flags == '-')      /* generally exclude this line */
        {
--- 1252,1266 ----
        }
        else if (vim_strchr((char_u *)"CZ", idx) != NULL)
        {                               /* continuation of multi-line msg */
!           status = qf_parse_multiline_pfx(qi, qf_idx, idx, qfl, fields);
!           if (status != QF_OK)
!               return status;
        }
        else if (vim_strchr((char_u *)"OPQ", idx) != NULL)
!       {                               /* global file names */
!           status = qf_parse_file_pfx(idx, fields, qfl, tail);
!           if (status == QF_MULTISCAN)
!               goto restofline;
        }
        if (fmt_ptr->flags == '-')      /* generally exclude this line */
        {
***************
*** 1358,1363 ****
--- 1483,1492 ----
      return retval;
  }
  
+ /*
+  * Set the title of the specified quickfix list. Frees the previous title.
+  * Prepends ':' to the title.
+  */
      static void
  qf_store_title(qf_info_T *qi, int qf_idx, char_u *title)
  {
***************
*** 1433,1438 ****
--- 1562,1570 ----
      }
  }
  
+ /*
+  * Free all the quickfix/location lists in the stack.
+  */
      void
  qf_free_all(win_T *wp)
  {
***************
*** 2876,2881 ****
--- 3008,3017 ----
      buf[i] = NUL;
  }
  
+ /*
+  * Display information (list number, list size and the title) about a
+  * quickfix/location list.
+  */
      static void
  qf_msg(qf_info_T *qi, int which, char *lead)
  {
***************
*** 2955,2960 ****
--- 3091,3099 ----
      qf_update_buffer(qi, NULL);
  }
  
+ /*
+  * Display the information about all the quickfix/location lists in the stack
+  */
      void
  qf_history(exarg_T *eap)
  {
***************
*** 3695,3700 ****
--- 3834,3842 ----
      KeyTyped = old_KeyTyped;
  }
  
+ /*
+  * For every change made to the quickfix list, update the changed tick.
+  */
      static void
  qf_list_changed(qf_info_T *qi, int qf_idx)
  {
***************
*** 5004,5010 ****
      QF_GETLIST_IDX    = 0x40,
      QF_GETLIST_SIZE   = 0x80,
      QF_GETLIST_TICK   = 0x100,
!     QF_GETLIST_ALL    = 0x1FF
  };
  
  /*
--- 5146,5152 ----
      QF_GETLIST_IDX    = 0x40,
      QF_GETLIST_SIZE   = 0x80,
      QF_GETLIST_TICK   = 0x100,
!     QF_GETLIST_ALL    = 0x1FF,
  };
  
  /*
***************
*** 5785,5790 ****
--- 5927,5935 ----
      return retval;
  }
  
+ /*
+  * Mark the context as in use for all the lists in a quickfix stack.
+  */
      static int
  mark_quickfix_ctx(qf_info_T *qi, int copyID)
  {
***************
*** 6167,6173 ****
  }
  
  /*
!  * Search for a pattern in all the help files in the 'runtimepath'.
   */
      static void
  hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *arg)
--- 6312,6321 ----
  }
  
  /*
!  * Search for a pattern in all the help files in the 'runtimepath'
!  * and add the matches to a quickfix list.
!  * 'arg' is the language specifier.  If supplied, then only matches in the
!  * specified language are found.
   */
      static void
  hgr_search_in_rtp(qf_info_T *qi, regmatch_T *p_regmatch, char_u *arg)
***************
*** 6192,6198 ****
      lang = check_help_lang(arg);
  #endif
  
!     /* Go through all directories in 'runtimepath' */
      p = p_rtp;
      while (*p != NUL && !got_int)
      {
--- 6340,6346 ----
      lang = check_help_lang(arg);
  #endif
  
!     /* Go through all the directories in 'runtimepath' */
      p = p_rtp;
      while (*p != NUL && !got_int)
      {
*** ../vim-8.0.1804/src/version.c       2018-05-08 22:01:02.197553218 +0200
--- src/version.c       2018-05-08 22:31:21.877471729 +0200
***************
*** 763,764 ****
--- 763,766 ----
  {   /* Add new patch number below this line */
+ /**/
+     1805,
  /**/

-- 
Advice to worms:  Sleep late.

 /// 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