# HG changeset patch # User Christian Brabandt # Date 1526823904 -7200 # Node ID 9b1dc5c2f460b4ab65224541cfd35b88152358d8 # Parent edbc72b9de832c53fdba3bd6e8776cea2f7ad029 patch 8.1.0010: efm_to_regpat() is too long commit https://github.com/vim/vim/commit/6bff719f7e472e918c60aa336de03e799b806c4f Author: Bram Moolenaar Date: Sun May 20 15:41:17 2018 +0200 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 https://github.com/vim/vim/issues/2924) diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -228,19 +228,172 @@ static struct fmtpattern }; /* + * 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) + { + EMSG(_("E374: Missing ] in format string")); + return NULL; + } + } + } + else if (efmp < efm + len) /* %*\D, %*\s etc. */ + *ptr++ = *++efmp; + *ptr++ = '\\'; + *ptr++ = '+'; + } + else + { + /* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */ + sprintf((char *)errmsg, + _("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(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( char_u *efm, - int len, + int len, efm_T *fmt_ptr, char_u *regpat, char_u *errmsg) { char_u *ptr; char_u *efmp; - char_u *srcptr; int round; int idx = 0; @@ -260,102 +413,17 @@ efm_to_regpat( break; if (idx < FMT_PATTERNS) { - if (fmt_ptr->addr[idx]) - { - sprintf((char *)errmsg, - _("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)) - { - sprintf((char *)errmsg, - _("E373: Unexpected %%%c in format string"), *efmp); - EMSG(errmsg); + ptr = fmtpat_to_regpat(efmp, fmt_ptr, idx, round, ptr, + errmsg); + if (ptr == NULL) return -1; - } - 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++ = ')'; + round++; } else if (*efmp == '*') { - 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) - { - EMSG(_("E374: Missing ] in format string")); - return -1; - } - } - } - else if (efmp < efm + len) /* %*\D, %*\s etc. */ - *ptr++ = *++efmp; - *ptr++ = '\\'; - *ptr++ = '+'; - } - else - { - /* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */ - sprintf((char *)errmsg, - _("E375: Unsupported %%%c in format string"), *efmp); - EMSG(errmsg); + 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 */ @@ -365,17 +433,8 @@ efm_to_regpat( 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 - { - sprintf((char *)errmsg, - _("E376: Invalid %%%c in format string prefix"), *efmp); - EMSG(errmsg); + if (efm_analyze_prefix(&efmp, fmt_ptr, errmsg) == FAIL) return -1; - } } else { 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 */ /**/ + 10, +/**/ 9, /**/ 8,