diff options
author | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2019-09-24 04:22:54 -0400 |
---|---|---|
committer | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2019-10-01 22:27:42 -0400 |
commit | 0253f0cd929a59e1516359eab9ae84ce39643a7b (patch) | |
tree | 7ae45d01fc579e8ed2b2e5f02970b01429e5e13d /src | |
parent | 30ae60e7cac7e77005aa429bc13f8ffa3ce64eb1 (diff) | |
download | rneovim-0253f0cd929a59e1516359eab9ae84ce39643a7b.tar.gz rneovim-0253f0cd929a59e1516359eab9ae84ce39643a7b.tar.bz2 rneovim-0253f0cd929a59e1516359eab9ae84ce39643a7b.zip |
vim-patch:8.1.0010: efm_to_regpat() is too long
Problem: efm_to_regpat() is too long.
Solution: Split off three functions. (Yegappan Lakshmanan, closes vim/vim#2924)
https://github.com/vim/vim/commit/6bff719f7e472e918c60aa336de03e799b806c4f
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/quickfix.c | 239 |
1 files changed, 147 insertions, 92 deletions
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 528829e63d..5083e573d3 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -264,15 +264,152 @@ static struct fmtpattern { 'o', ".\\+" } }; +// 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( + const char_u *efmp, + efm_T *fmt_ptr, + int idx, + int round, + char_u *ptr, + char_u *errmsg, + size_t errmsglen) + FUNC_ATTR_NONNULL_ALL +{ + if (fmt_ptr->addr[idx]) { + // Each errorformat pattern can occur only once + snprintf((char *)errmsg, errmsglen, + _("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)) { + snprintf((char *)errmsg, errmsglen, + _("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 { + char_u *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( + const char_u *efm, + int len, + const char_u **pefmp, + char_u *ptr, + char_u *errmsg, + size_t errmsglen) + FUNC_ATTR_NONNULL_ALL +{ + const 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) != ']') { + } + if (efmp == efm + len) { + EMSG(_("E374: Missing ] in format string")); + return NULL; + } + } + } else if (efmp < efm + len) { // %*\D, %*\s etc. + *ptr++ = *++efmp; + } + *ptr++ = '\\'; + *ptr++ = '+'; + } else { + // TODO(vim): scanf()-like: %*ud, %*3c, %*f, ... ? + snprintf((char *)errmsg, errmsglen, + _("E375: Unsupported %%%c in format string"), *efmp); + EMSG(errmsg); + return NULL; + } + + *pefmp = efmp; + + return ptr; +} + +// Analyze/parse an errorformat prefix. +static int efm_analyze_prefix(const char_u **pefmp, efm_T *fmt_ptr, + char_u *errmsg, size_t errmsglen) + FUNC_ATTR_NONNULL_ALL +{ + const 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 { + snprintf((char *)errmsg, errmsglen, + _("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(char_u *efm, int len, efm_T *fmt_ptr, - char_u *regpat, char_u *errmsg) +static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr, + char_u *regpat, char_u *errmsg, size_t errmsglen) + FUNC_ATTR_NONNULL_ALL { // Build regexp pattern from current 'errorformat' option char_u *ptr = regpat; *ptr++ = '^'; int round = 0; - for (char_u *efmp = efm; efmp < efm + len; efmp++) { + for (const char_u *efmp = efm; efmp < efm + len; efmp++) { if (*efmp == '%') { efmp++; int idx; @@ -282,89 +419,15 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, } } if (idx < FMT_PATTERNS) { - if (fmt_ptr->addr[idx]) { - snprintf((char *)errmsg, CMDBUFFSIZE + 1, - _("E372: Too many %%%c in format string"), *efmp); - EMSG(errmsg); - return -1; - } - if ((idx - && idx < 6 - && vim_strchr((char_u *)"DXOPQ", fmt_ptr->prefix) != NULL) - || (idx == 6 - && vim_strchr((char_u *)"OPQ", fmt_ptr->prefix) == NULL)) { - snprintf((char *)errmsg, CMDBUFFSIZE + 1, - _("E373: Unexpected %%%c in format string"), *efmp); - EMSG(errmsg); + ptr = fmtpat_to_regpat(efmp, fmt_ptr, idx, round, ptr, + errmsg, errmsglen); + if (ptr == NULL) { return -1; } round++; - 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 { - char_u *srcptr = (char_u *)fmt_pat[idx].pattern; - while ((*ptr = *srcptr++) != NUL) { - ptr++; - } - } - *ptr++ = '\\'; - *ptr++ = ')'; } else if (*efmp == '*') { - if (*++efmp == '[' || *efmp == '\\') { - if ((*ptr++ = *efmp) == '[') { // %*[^a-z0-9] etc. - if (efmp[1] == '^') { - *ptr++ = *++efmp; - } - if (efmp < efm + len) { - efmp++; - *ptr++ = *efmp; // could be ']' - while (efmp < efm + len) { - efmp++; - if ((*ptr++ = *efmp) == ']') { - break; - } - } - if (efmp == efm + len) { - EMSG(_("E374: Missing ] in format string")); - return -1; - } - } - } else if (efmp < efm + len) { // %*\D, %*\s etc. - efmp++; - *ptr++ = *efmp; - } - *ptr++ = '\\'; - *ptr++ = '+'; - } else { - // TODO(vim): scanf()-like: %*ud, %*3c, %*f, ... ? - snprintf((char *)errmsg, CMDBUFFSIZE + 1, - _("E375: Unsupported %%%c in format string"), *efmp); - EMSG(errmsg); + ptr = scanf_fmt_to_regpat(efm, len, &efmp, ptr, errmsg, errmsglen); + if (ptr == NULL) { return -1; } } else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL) { @@ -374,15 +437,7 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, } else if (*efmp == '>') { fmt_ptr->conthere = true; } else if (efmp == efm + 1) { // analyse prefix - if (vim_strchr((char_u *)"+-", *efmp) != NULL) { - fmt_ptr->flags = *efmp++; - } - if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) { - fmt_ptr->prefix = *efmp; - } else { - snprintf((char *)errmsg, CMDBUFFSIZE + 1, - _("E376: Invalid %%%c in format string prefix"), *efmp); - EMSG(errmsg); + if (efm_analyze_prefix(&efmp, fmt_ptr, errmsg, errmsglen) == FAIL) { return -1; } } else { @@ -461,7 +516,7 @@ static efm_T * parse_efm_option(char_u *efm) } } - if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg) == -1) { + if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg, errmsglen) == -1) { goto parse_efm_error; } if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) { |