To: vim_dev@googlegroups.com Subject: Patch 8.1.0010 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0010 Problem: efm_to_regpat() is too long. Solution: Split off three functions. (Yegappan Lakshmanan, closes #2924) Files: src/quickfix.c *** ../vim-8.1.0009/src/quickfix.c 2018-05-15 21:53:11.000000000 +0200 --- src/quickfix.c 2018-05-20 15:40:22.857179812 +0200 *************** *** 228,246 **** }; /* * 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) { char_u *ptr; char_u *efmp; - char_u *srcptr; int round; int idx = 0; --- 228,399 ---- }; /* + * 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, efm_T *fmt_ptr, char_u *regpat, char_u *errmsg) { char_u *ptr; char_u *efmp; int round; int idx = 0; *************** *** 260,361 **** 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); 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++ = ')'; } 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); return -1; - } } else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL) *ptr++ = *efmp; /* regexp magic characters */ --- 413,429 ---- break; if (idx < FMT_PATTERNS) { ! ptr = fmtpat_to_regpat(efmp, fmt_ptr, idx, round, ptr, ! errmsg); ! if (ptr == NULL) return -1; ! round++; } else if (*efmp == '*') { ! 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,381 **** 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); return -1; - } } else { --- 433,440 ---- fmt_ptr->conthere = TRUE; else if (efmp == efm + 1) /* analyse prefix */ { ! if (efm_analyze_prefix(&efmp, fmt_ptr, errmsg) == FAIL) return -1; } else { *** ../vim-8.1.0009/src/version.c 2018-05-20 14:57:19.121429579 +0200 --- src/version.c 2018-05-20 15:37:57.138956740 +0200 *************** *** 763,764 **** --- 763,766 ---- { /* Add new patch number below this line */ + /**/ + 10, /**/ -- SECOND SOLDIER: It could be carried by an African swallow! FIRST SOLDIER: Oh yes! An African swallow maybe ... but not a European swallow. that's my point. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 ///