# HG changeset patch # User Christian Brabandt # Date 1525812306 -7200 # Node ID 1282a54c1f5a7e846ed53646dd62bd91ddddb948 # Parent 4e1289c328a1a2b8adcc7f0739b9bb5524dcf553 patch 8.0.1805: qf_parse_line() is too long commit https://github.com/vim/vim/commit/18cebf44177542e6658251bacf6152aa9009ca58 Author: Bram Moolenaar Date: Tue May 8 22:31:37 2018 +0200 patch 8.0.1805: qf_parse_line() is too long Problem: qf_parse_line() is too long. Solution: Split it in parts. Properly handle vim_realloc() failing. (Yegappan Lakshmanan, closes #2881) diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -213,19 +213,19 @@ static struct fmtpattern 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', ".\\+"} - }; + { + {'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,7 +504,8 @@ enum { QF_OK = 1, QF_END_OF_INPUT = 2, QF_NOMEM = 3, - QF_IGNORE_LINE = 4 + QF_IGNORE_LINE = 4, + QF_MULTISCAN = 5, }; typedef struct { @@ -525,6 +526,8 @@ typedef struct { 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,9 +542,9 @@ qf_grow_linebuf(qfstate_T *state, int ne } else if (state->linelen > state->growbufsiz) { - state->growbuf = vim_realloc(state->growbuf, state->linelen + 1); - if (state->growbuf == NULL) + if ((p = vim_realloc(state->growbuf, state->linelen + 1)) == NULL) return NULL; + state->growbuf = p; state->growbufsiz = state->linelen; } return state->growbuf; @@ -696,6 +699,8 @@ qf_get_next_file_line(qfstate_T *state) for (;;) { + char_u *p; + if (fgets((char *)state->growbuf + growbuflen, state->growbufsiz - growbuflen, state->fd) == NULL) break; @@ -711,9 +716,9 @@ qf_get_next_file_line(qfstate_T *state) state->growbufsiz = 2 * state->growbufsiz < LINE_MAXLEN ? 2 * state->growbufsiz : LINE_MAXLEN; - state->growbuf = vim_realloc(state->growbuf, state->growbufsiz); - if (state->growbuf == NULL) + if ((p = vim_realloc(state->growbuf, state->growbufsiz)) == NULL) return QF_NOMEM; + state->growbuf = p; } while (discard) @@ -825,6 +830,352 @@ typedef struct { } 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,16 +1189,10 @@ qf_parse_line( 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; + int status; restofline: /* If there was no %> item start at the first pattern */ @@ -855,6 +1200,7 @@ restofline: fmt_ptr = fmt_first; else { + /* Otherwise start from the last used pattern */ fmt_ptr = fmt_start; fmt_start = NULL; } @@ -866,164 +1212,13 @@ restofline: 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); - } + 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,34 +1226,16 @@ restofline: { 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); + /* 'D' and 'X' directory specifiers */ + status = qf_parse_dir_pfx(idx, fields, qfl); + if (status != QF_OK) + return status; } - 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); + + 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,67 +1252,15 @@ restofline: } 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; + 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 */ - 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; - } - } + { /* 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,6 +1483,10 @@ qf_init_end: 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,6 +1562,9 @@ ll_free_all(qf_info_T **pqi) } } +/* + * Free all the quickfix/location lists in the stack. + */ void qf_free_all(win_T *wp) { @@ -2876,6 +3008,10 @@ qf_fmt_text(char_u *text, char_u *buf, i 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,6 +3091,9 @@ qf_age(exarg_T *eap) qf_update_buffer(qi, NULL); } +/* + * Display the information about all the quickfix/location lists in the stack + */ void qf_history(exarg_T *eap) { @@ -3695,6 +3834,9 @@ qf_fill_buffer(qf_info_T *qi, buf_T *buf 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,7 +5146,7 @@ enum { QF_GETLIST_IDX = 0x40, QF_GETLIST_SIZE = 0x80, QF_GETLIST_TICK = 0x100, - QF_GETLIST_ALL = 0x1FF + QF_GETLIST_ALL = 0x1FF, }; /* @@ -5785,6 +5927,9 @@ set_errorlist( 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,7 +6312,10 @@ hgr_search_files_in_dir( } /* - * Search for a pattern in all the help files in the 'runtimepath'. + * 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,7 +6340,7 @@ hgr_search_in_rtp(qf_info_T *qi, regmatc lang = check_help_lang(arg); #endif - /* Go through all directories in 'runtimepath' */ + /* Go through all the directories in 'runtimepath' */ p = p_rtp; while (*p != NUL && !got_int) { diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1805, +/**/ 1804, /**/ 1803,