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(®match, linebuf, (colnr_T)0);
+ fmt_ptr->prog = regmatch.regprog;
+ if (r)
+ status = qf_parse_match(linebuf, linelen, fmt_ptr, ®match,
+ 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(®match, 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.